001package org.cpsolver.exam.criteria; 002 003import java.util.Map; 004import java.util.Set; 005 006import org.cpsolver.exam.model.Exam; 007import org.cpsolver.exam.model.ExamPlacement; 008import org.cpsolver.ifs.assignment.Assignment; 009import org.cpsolver.ifs.util.DataProperties; 010 011 012/** 013 * Cost for using more than one room (nrSplits^2). 014 * <br><br> 015 * A weight for room split penalty can be set by problem 016 * property Exams.RoomSplitWeight, or in the input xml file, property 017 * roomSplitWeight. 018 * 019 * <br> 020 * 021 * @version ExamTT 1.3 (Examination Timetabling)<br> 022 * Copyright (C) 2008 - 2014 Tomáš Müller<br> 023 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 024 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 025 * <br> 026 * This library is free software; you can redistribute it and/or modify 027 * it under the terms of the GNU Lesser General Public License as 028 * published by the Free Software Foundation; either version 3 of the 029 * License, or (at your option) any later version. <br> 030 * <br> 031 * This library is distributed in the hope that it will be useful, but 032 * WITHOUT ANY WARRANTY; without even the implied warranty of 033 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 034 * Lesser General Public License for more details. <br> 035 * <br> 036 * You should have received a copy of the GNU Lesser General Public 037 * License along with this library; if not see 038 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 039 */ 040public class RoomSplitPenalty extends ExamCriterion { 041 042 @Override 043 public ValueContext createAssignmentContext(Assignment<Exam, ExamPlacement> assignment) { 044 return new RoomSplitContext(assignment); 045 } 046 047 @Override 048 public String getWeightName() { 049 return "Exams.RoomSplitWeight"; 050 } 051 052 @Override 053 public String getXmlWeightName() { 054 return "roomSplitWeight"; 055 } 056 057 @Override 058 public double getWeightDefault(DataProperties config) { 059 return 10.0; 060 } 061 062 @Override 063 public double getValue(Assignment<Exam, ExamPlacement> assignment, ExamPlacement value, Set<ExamPlacement> conflicts) { 064 return (value.getRoomPlacements() == null || value.getRoomPlacements().size() <= 1 ? 0 : (value.getRoomPlacements().size() - 1) * (value.getRoomPlacements().size() - 1)); 065 } 066 067 @Override 068 public void getInfo(Assignment<Exam, ExamPlacement> assignment, Map<String, String> info) { 069 if (getValue(assignment) != 0.0) { 070 int[] roomSplits = ((RoomSplitContext)getContext(assignment)).getRoomSplits(); 071 String split = ""; 072 for (int i = 0; i < roomSplits.length; i++) { 073 if (roomSplits[i] > 0) { 074 if (split.length() > 0) 075 split += ", "; 076 split += roomSplits[i] + "×" + (i + 2); 077 } 078 } 079 info.put(getName(), sDoubleFormat.format(getValue(assignment)) + " (" + split + ")"); 080 } 081 } 082 083 @Override 084 public String toString(Assignment<Exam, ExamPlacement> assignment) { 085 return "RSp:" + sDoubleFormat.format(getValue(assignment)); 086 } 087 088 @Override 089 public boolean isPeriodCriterion() { return false; } 090 091 protected class RoomSplitContext extends ValueContext { 092 private int iRoomSplits[] = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 093 094 public RoomSplitContext(Assignment<Exam, ExamPlacement> assignment) { 095 super(assignment); 096 for (Exam exam: getModel().variables()) { 097 ExamPlacement placement = assignment.getValue(exam); 098 if (placement != null && placement.getRoomPlacements() != null && placement.getRoomPlacements().size() > 1) 099 iRoomSplits[placement.getRoomPlacements().size() - 2] ++; 100 } 101 } 102 103 @Override 104 public void assigned(Assignment<Exam, ExamPlacement> assignment, ExamPlacement value) { 105 super.assigned(assignment, value); 106 if (value.getRoomPlacements() != null && value.getRoomPlacements().size() > 1) 107 iRoomSplits[value.getRoomPlacements().size() - 2] ++; 108 } 109 110 @Override 111 public void unassigned(Assignment<Exam, ExamPlacement> assignment, ExamPlacement value) { 112 super.unassigned(assignment, value); 113 if (value.getRoomPlacements() != null && value.getRoomPlacements().size() > 1) 114 iRoomSplits[value.getRoomPlacements().size() - 2] --; 115 } 116 117 public int[] getRoomSplits() { 118 return iRoomSplits; 119 } 120 } 121}