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