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