001package org.cpsolver.coursett; 002 003import java.io.File; 004import java.text.SimpleDateFormat; 005import java.util.ArrayList; 006import java.util.BitSet; 007import java.util.Calendar; 008import java.util.Date; 009import java.util.HashSet; 010import java.util.HashMap; 011import java.util.Hashtable; 012import java.util.Iterator; 013import java.util.List; 014import java.util.Locale; 015import java.util.Map; 016import java.util.Set; 017 018 019import org.cpsolver.coursett.constraint.ClassLimitConstraint; 020import org.cpsolver.coursett.constraint.DepartmentSpreadConstraint; 021import org.cpsolver.coursett.constraint.DiscouragedRoomConstraint; 022import org.cpsolver.coursett.constraint.GroupConstraint; 023import org.cpsolver.coursett.constraint.IgnoreStudentConflictsConstraint; 024import org.cpsolver.coursett.constraint.InstructorConstraint; 025import org.cpsolver.coursett.constraint.JenrlConstraint; 026import org.cpsolver.coursett.constraint.MinimizeNumberOfUsedGroupsOfTime; 027import org.cpsolver.coursett.constraint.MinimizeNumberOfUsedRoomsConstraint; 028import org.cpsolver.coursett.constraint.RoomConstraint; 029import org.cpsolver.coursett.constraint.SpreadConstraint; 030import org.cpsolver.coursett.constraint.FlexibleConstraint.FlexibleConstraintType; 031import org.cpsolver.coursett.model.Configuration; 032import org.cpsolver.coursett.model.Lecture; 033import org.cpsolver.coursett.model.Placement; 034import org.cpsolver.coursett.model.RoomLocation; 035import org.cpsolver.coursett.model.RoomSharingModel; 036import org.cpsolver.coursett.model.Student; 037import org.cpsolver.coursett.model.StudentGroup; 038import org.cpsolver.coursett.model.TimeLocation; 039import org.cpsolver.coursett.model.TimetableModel; 040import org.cpsolver.ifs.assignment.Assignment; 041import org.cpsolver.ifs.model.Constraint; 042import org.cpsolver.ifs.solution.Solution; 043import org.cpsolver.ifs.solver.Solver; 044import org.cpsolver.ifs.util.Progress; 045import org.cpsolver.ifs.util.ToolBox; 046import org.dom4j.Document; 047import org.dom4j.Element; 048import org.dom4j.io.SAXReader; 049 050/** 051 * This class loads the input model from XML file. <br> 052 * <br> 053 * Parameters: 054 * <table border='1' summary='Related Solver Parameters'> 055 * <tr> 056 * <th>Parameter</th> 057 * <th>Type</th> 058 * <th>Comment</th> 059 * </tr> 060 * <tr> 061 * <td>General.Input</td> 062 * <td>{@link String}</td> 063 * <td>Input XML file</td> 064 * </tr> 065 * <tr> 066 * <td>General.DeptBalancing</td> 067 * <td>{@link Boolean}</td> 068 * <td>Use {@link DepartmentSpreadConstraint}</td> 069 * </tr> 070 * <tr> 071 * <td>General.InteractiveMode</td> 072 * <td>{@link Boolean}</td> 073 * <td>Interactive mode (see {@link Lecture#purgeInvalidValues(boolean)})</td> 074 * </tr> 075 * <tr> 076 * <td>General.ForcedPerturbances</td> 077 * <td>{@link Integer}</td> 078 * <td>For testing of MPP: number of input perturbations, i.e., classes with 079 * prohibited intial assignment</td> 080 * </tr> 081 * <tr> 082 * <td>General.UseDistanceConstraints</td> 083 * <td>{@link Boolean}</td> 084 * <td>Consider distances between buildings</td> 085 * </tr> 086 * </table> 087 * 088 * @version CourseTT 1.3 (University Course Timetabling)<br> 089 * Copyright (C) 2006 - 2014 Tomas Muller<br> 090 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 091 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 092 * <br> 093 * This library is free software; you can redistribute it and/or modify 094 * it under the terms of the GNU Lesser General Public License as 095 * published by the Free Software Foundation; either version 3 of the 096 * License, or (at your option) any later version. <br> 097 * <br> 098 * This library is distributed in the hope that it will be useful, but 099 * WITHOUT ANY WARRANTY; without even the implied warranty of 100 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 101 * Lesser General Public License for more details. <br> 102 * <br> 103 * You should have received a copy of the GNU Lesser General Public 104 * License along with this library; if not see 105 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 106 */ 107 108public class TimetableXMLLoader extends TimetableLoader { 109 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(TimetableXMLLoader.class); 110 private static SimpleDateFormat sDF = new SimpleDateFormat("MM/dd"); 111 112 private boolean iDeptBalancing = true; 113 private int iForcedPerturbances = 0; 114 115 private boolean iInteractiveMode = false; 116 private File iInputFile; 117 118 private Progress iProgress = null; 119 120 public TimetableXMLLoader(TimetableModel model, Assignment<Lecture, Placement> assignment) { 121 super(model, assignment); 122 iProgress = Progress.getInstance(getModel()); 123 iInputFile = new File(getModel().getProperties().getProperty("General.Input", 124 "." + File.separator + "solution.xml")); 125 iForcedPerturbances = getModel().getProperties().getPropertyInt("General.ForcedPerturbances", 0); 126 iDeptBalancing = getModel().getProperties().getPropertyBoolean("General.DeptBalancing", true); 127 iInteractiveMode = getModel().getProperties().getPropertyBoolean("General.InteractiveMode", iInteractiveMode); 128 } 129 130 private Solver<Lecture, Placement> iSolver = null; 131 132 public void setSolver(Solver<Lecture, Placement> solver) { 133 iSolver = solver; 134 } 135 136 public Solver<Lecture, Placement> getSolver() { 137 return iSolver; 138 } 139 140 public void setInputFile(File inputFile) { 141 iInputFile = inputFile; 142 } 143 144 @Override 145 public void load() throws Exception { 146 load(null); 147 } 148 149 public void load(Solution<Lecture, Placement> currentSolution) throws Exception { 150 sLogger.debug("Reading XML data from " + iInputFile); 151 iProgress.setPhase("Reading " + iInputFile.getName() + " ..."); 152 153 Document document = (new SAXReader()).read(iInputFile); 154 Element root = document.getRootElement(); 155 156 sLogger.debug("Root element: " + root.getName()); 157 if (!"llrt".equals(root.getName()) && !"timetable".equals(root.getName())) { 158 throw new IllegalArgumentException("Given XML file is not large lecture room timetabling problem."); 159 } 160 161 if (root.element("input") != null) 162 root = root.element("input"); 163 164 iProgress.load(root, true); 165 iProgress.message(Progress.MSGLEVEL_STAGE, "Restoring from backup ..."); 166 167 doLoad(currentSolution, root); 168 169 try { 170 getSolver().getClass().getMethod("load", new Class[] { Element.class }).invoke(getSolver(), new Object[] { root }); 171 } catch (Exception e) { 172 } 173 174 iProgress.setPhase("Done", 1); 175 iProgress.incProgress(); 176 177 sLogger.debug("Model successfully loaded."); 178 iProgress.info("Model successfully loaded."); 179 } 180 181 public void load(Solution<Lecture, Placement> currentSolution, Document document) { 182 iProgress.setPhase("Reading solution file ..."); 183 184 Element root = document.getRootElement(); 185 186 sLogger.debug("Root element: " + root.getName()); 187 if (!"llrt".equals(root.getName()) && !"timetable".equals(root.getName())) { 188 throw new IllegalArgumentException("Given XML file is not large lecture room timetabling problem."); 189 } 190 191 if (root.element("input") != null) 192 root = root.element("input"); 193 194 iProgress.load(root, true); 195 iProgress.message(Progress.MSGLEVEL_STAGE, "Restoring from backup ..."); 196 197 doLoad(currentSolution, root); 198 199 iProgress.setPhase("Done", 1); 200 iProgress.incProgress(); 201 202 iProgress.info("Model successfully loaded."); 203 } 204 205 protected void doLoad(Solution<Lecture, Placement> currentSolution, Element root) { 206 if (root.attributeValue("term") != null) 207 getModel().getProperties().setProperty("Data.Term", root.attributeValue("term")); 208 if (root.attributeValue("year") != null) 209 getModel().setYear(Integer.parseInt(root.attributeValue("year"))); 210 else if (root.attributeValue("term") != null) 211 getModel().setYear(Integer.parseInt(root.attributeValue("term").substring(0, 4))); 212 if (root.attributeValue("initiative") != null) 213 getModel().getProperties().setProperty("Data.Initiative", root.attributeValue("initiative")); 214 if (root.attributeValue("semester") != null && root.attributeValue("year") != null) 215 getModel().getProperties().setProperty("Data.Term", 216 root.attributeValue("semester") + root.attributeValue("year")); 217 if (root.attributeValue("session") != null) 218 getModel().getProperties().setProperty("General.SessionId", root.attributeValue("session")); 219 if (root.attributeValue("solverGroup") != null) 220 getModel().getProperties().setProperty("General.SolverGroupId", root.attributeValue("solverGroup")); 221 String version = root.attributeValue("version"); 222 223 // Student sectioning considers the whole course (including committed classes), since 2.5 224 boolean sectionWholeCourse = true; 225 226 if (version != null && version.indexOf('.') >= 0) { 227 int majorVersion = Integer.parseInt(version.substring(0, version.indexOf('.'))); 228 int minorVersion = Integer.parseInt(version.substring(1 + version.indexOf('.'))); 229 230 sectionWholeCourse = (majorVersion == 2 && minorVersion >= 5) || majorVersion > 2; 231 } 232 233 HashMap<Long, TimeLocation> perts = new HashMap<Long, TimeLocation>(); 234 if (getModel().getProperties().getPropertyInt("MPP.TimePert", 0) > 0) { 235 int nrChanges = getModel().getProperties().getPropertyInt("MPP.TimePert", 0); 236 int idx = 0; 237 for (Iterator<?> i = root.element("perturbations").elementIterator("class"); i.hasNext() && idx < nrChanges; idx++) { 238 Element pertEl = (Element) i.next(); 239 Long classId = Long.valueOf(pertEl.attributeValue("id")); 240 TimeLocation tl = new TimeLocation(Integer.parseInt(pertEl.attributeValue("days"), 2), Integer 241 .parseInt(pertEl.attributeValue("start")), Integer.parseInt(pertEl.attributeValue("length")), 242 0, 0.0, 0, null, null, null, 0); 243 perts.put(classId, tl); 244 } 245 } 246 247 iProgress.setPhase("Creating rooms ...", root.element("rooms").elements("room").size()); 248 HashMap<String, Element> roomElements = new HashMap<String, Element>(); 249 HashMap<String, RoomConstraint> roomConstraints = new HashMap<String, RoomConstraint>(); 250 HashMap<Long, List<Lecture>> sameLectures = new HashMap<Long, List<Lecture>>(); 251 for (Iterator<?> i = root.element("rooms").elementIterator("room"); i.hasNext();) { 252 Element roomEl = (Element) i.next(); 253 iProgress.incProgress(); 254 roomElements.put(roomEl.attributeValue("id"), roomEl); 255 if ("false".equals(roomEl.attributeValue("constraint"))) 256 continue; 257 RoomSharingModel sharingModel = null; 258 Element sharingEl = roomEl.element("sharing"); 259 if (sharingEl != null) { 260 Character freeForAllPrefChar = null; 261 Element freeForAllEl = sharingEl.element("freeForAll"); 262 if (freeForAllEl != null) 263 freeForAllPrefChar = freeForAllEl.attributeValue("value", "F").charAt(0); 264 Character notAvailablePrefChar = null; 265 Element notAvailableEl = sharingEl.element("notAvailable"); 266 if (notAvailableEl != null) 267 notAvailablePrefChar = notAvailableEl.attributeValue("value", "X").charAt(0); 268 String pattern = sharingEl.element("pattern").getText(); 269 int unit = Integer.parseInt(sharingEl.element("pattern").attributeValue("unit", "1")); 270 Map<Character, Long> departments = new HashMap<Character, Long>(); 271 for (Iterator<?> j = sharingEl.elementIterator("department"); j.hasNext(); ) { 272 Element deptEl = (Element)j.next(); 273 char value = deptEl.attributeValue("value", String.valueOf((char)('0' + departments.size()))).charAt(0); 274 Long id = Long.valueOf(deptEl.attributeValue("id")); 275 departments.put(value, id); 276 } 277 sharingModel = new RoomSharingModel(unit, departments, pattern, freeForAllPrefChar, notAvailablePrefChar); 278 } 279 boolean ignoreTooFar = false; 280 if ("true".equals(roomEl.attributeValue("ignoreTooFar"))) 281 ignoreTooFar = true; 282 boolean fake = false; 283 if ("true".equals(roomEl.attributeValue("fake"))) 284 fake = true; 285 Double posX = null, posY = null; 286 if (roomEl.attributeValue("location") != null) { 287 String loc = roomEl.attributeValue("location"); 288 posX = Double.valueOf(loc.substring(0, loc.indexOf(','))); 289 posY = Double.valueOf(loc.substring(loc.indexOf(',') + 1)); 290 } 291 boolean discouraged = "true".equals(roomEl.attributeValue("discouraged")); 292 RoomConstraint constraint = (discouraged ? new DiscouragedRoomConstraint( 293 getModel().getProperties(), 294 Long.valueOf(roomEl.attributeValue("id")), 295 (roomEl.attributeValue("name") != null ? roomEl.attributeValue("name") : "r" 296 + roomEl.attributeValue("id")), 297 (roomEl.attributeValue("building") == null ? null : Long.valueOf(roomEl.attributeValue("building"))), 298 Integer.parseInt(roomEl.attributeValue("capacity")), sharingModel, posX, posY, ignoreTooFar, !fake) 299 : new RoomConstraint(Long.valueOf(roomEl.attributeValue("id")), 300 (roomEl.attributeValue("name") != null ? roomEl.attributeValue("name") : "r" 301 + roomEl.attributeValue("id")), (roomEl.attributeValue("building") == null ? null 302 : Long.valueOf(roomEl.attributeValue("building"))), Integer.parseInt(roomEl 303 .attributeValue("capacity")), sharingModel, posX, posY, ignoreTooFar, !fake)); 304 if (roomEl.attributeValue("type") != null) 305 constraint.setType(Long.valueOf(roomEl.attributeValue("type"))); 306 getModel().addConstraint(constraint); 307 roomConstraints.put(roomEl.attributeValue("id"), constraint); 308 309 for (Iterator<?> j = roomEl.elementIterator("travel-time"); j.hasNext();) { 310 Element travelTimeEl = (Element)j.next(); 311 getModel().getDistanceMetric().addTravelTime(constraint.getResourceId(), 312 Long.valueOf(travelTimeEl.attributeValue("id")), 313 Integer.valueOf(travelTimeEl.attributeValue("minutes"))); 314 } 315 } 316 317 HashMap<String, InstructorConstraint> instructorConstraints = new HashMap<String, InstructorConstraint>(); 318 if (root.element("instructors") != null) { 319 for (Iterator<?> i = root.element("instructors").elementIterator("instructor"); i.hasNext();) { 320 Element instructorEl = (Element) i.next(); 321 InstructorConstraint instructorConstraint = new InstructorConstraint(Long.valueOf(instructorEl 322 .attributeValue("id")), instructorEl.attributeValue("puid"), (instructorEl 323 .attributeValue("name") != null ? instructorEl.attributeValue("name") : "i" 324 + instructorEl.attributeValue("id")), "true".equals(instructorEl.attributeValue("ignDist"))); 325 if (instructorEl.attributeValue("type") != null) 326 instructorConstraint.setType(Long.valueOf(instructorEl.attributeValue("type"))); 327 instructorConstraints.put(instructorEl.attributeValue("id"), instructorConstraint); 328 329 getModel().addConstraint(instructorConstraint); 330 } 331 } 332 HashMap<Long, String> depts = new HashMap<Long, String>(); 333 if (root.element("departments") != null) { 334 for (Iterator<?> i = root.element("departments").elementIterator("department"); i.hasNext();) { 335 Element deptEl = (Element) i.next(); 336 depts.put(Long.valueOf(deptEl.attributeValue("id")), (deptEl.attributeValue("name") != null ? deptEl 337 .attributeValue("name") : "d" + deptEl.attributeValue("id"))); 338 } 339 } 340 341 HashMap<Long, Configuration> configs = new HashMap<Long, Configuration>(); 342 HashMap<Long, List<Configuration>> alternativeConfigurations = new HashMap<Long, List<Configuration>>(); 343 if (root.element("configurations") != null) { 344 for (Iterator<?> i = root.element("configurations").elementIterator("config"); i.hasNext();) { 345 Element configEl = (Element) i.next(); 346 Long configId = Long.valueOf(configEl.attributeValue("id")); 347 int limit = Integer.parseInt(configEl.attributeValue("limit")); 348 Long offeringId = Long.valueOf(configEl.attributeValue("offering")); 349 Configuration config = new Configuration(offeringId, configId, limit); 350 configs.put(configId, config); 351 List<Configuration> altConfigs = alternativeConfigurations.get(offeringId); 352 if (altConfigs == null) { 353 altConfigs = new ArrayList<Configuration>(); 354 alternativeConfigurations.put(offeringId, altConfigs); 355 } 356 altConfigs.add(config); 357 config.setAltConfigurations(altConfigs); 358 } 359 } 360 361 iProgress.setPhase("Creating variables ...", root.element("classes").elements("class").size()); 362 363 HashMap<String, Element> classElements = new HashMap<String, Element>(); 364 HashMap<String, Lecture> lectures = new HashMap<String, Lecture>(); 365 HashMap<Lecture, Placement> assignedPlacements = new HashMap<Lecture, Placement>(); 366 HashMap<Lecture, String> parents = new HashMap<Lecture, String>(); 367 int ord = 0; 368 for (Iterator<?> i1 = root.element("classes").elementIterator("class"); i1.hasNext();) { 369 Element classEl = (Element) i1.next(); 370 371 Configuration config = null; 372 if (classEl.attributeValue("config") != null) { 373 config = configs.get(Long.valueOf(classEl.attributeValue("config"))); 374 } 375 if (config == null && classEl.attributeValue("offering") != null) { 376 Long offeringId = Long.valueOf(classEl.attributeValue("offering")); 377 Long configId = Long.valueOf(classEl.attributeValue("config")); 378 List<Configuration> altConfigs = alternativeConfigurations.get(offeringId); 379 if (altConfigs == null) { 380 altConfigs = new ArrayList<Configuration>(); 381 alternativeConfigurations.put(offeringId, altConfigs); 382 } 383 for (Configuration c : altConfigs) { 384 if (c.getConfigId().equals(configId)) { 385 config = c; 386 break; 387 } 388 } 389 if (config == null) { 390 config = new Configuration(offeringId, configId, -1); 391 altConfigs.add(config); 392 config.setAltConfigurations(altConfigs); 393 configs.put(config.getConfigId(), config); 394 } 395 } 396 397 DatePattern defaultDatePattern = new DatePattern(); 398 if (classEl.attributeValue("dates") == null) { 399 int startDay = Integer.parseInt(classEl.attributeValue("startDay", "0")); 400 int endDay = Integer.parseInt(classEl.attributeValue("endDay", "1")); 401 defaultDatePattern.setPattern(startDay, endDay); 402 defaultDatePattern.setName(sDF.format(getDate(getModel().getYear(), startDay)) + "-" + sDF.format(getDate(getModel().getYear(), endDay))); 403 } else { 404 defaultDatePattern.setId(classEl.attributeValue("datePattern") == null ? null : Long.valueOf(classEl.attributeValue("datePattern"))); 405 defaultDatePattern.setName(classEl.attributeValue("datePatternName")); 406 defaultDatePattern.setPattern(classEl.attributeValue("dates")); 407 } 408 Hashtable<Long, DatePattern> datePatterns = new Hashtable<Long, TimetableXMLLoader.DatePattern>(); 409 for (Iterator<?> i2 = classEl.elementIterator("date"); i2.hasNext();) { 410 Element dateEl = (Element) i2.next(); 411 Long id = Long.valueOf(dateEl.attributeValue("id")); 412 datePatterns.put(id, new DatePattern( 413 id, 414 dateEl.attributeValue("name"), 415 dateEl.attributeValue("pattern"))); 416 } 417 classElements.put(classEl.attributeValue("id"), classEl); 418 List<InstructorConstraint> ics = new ArrayList<InstructorConstraint>(); 419 for (Iterator<?> i2 = classEl.elementIterator("instructor"); i2.hasNext();) { 420 Element instructorEl = (Element) i2.next(); 421 InstructorConstraint instructorConstraint = instructorConstraints 422 .get(instructorEl.attributeValue("id")); 423 if (instructorConstraint == null) { 424 instructorConstraint = new InstructorConstraint(Long.valueOf(instructorEl.attributeValue("id")), 425 instructorEl.attributeValue("puid"), 426 (instructorEl.attributeValue("name") != null ? instructorEl.attributeValue("name") : "i" 427 + instructorEl.attributeValue("id")), "true".equals(instructorEl 428 .attributeValue("ignDist"))); 429 instructorConstraints.put(instructorEl.attributeValue("id"), instructorConstraint); 430 getModel().addConstraint(instructorConstraint); 431 } 432 ics.add(instructorConstraint); 433 } 434 List<RoomLocation> roomLocations = new ArrayList<RoomLocation>(); 435 List<RoomConstraint> roomConstraintsThisClass = new ArrayList<RoomConstraint>(); 436 List<RoomLocation> initialRoomLocations = new ArrayList<RoomLocation>(); 437 List<RoomLocation> assignedRoomLocations = new ArrayList<RoomLocation>(); 438 List<RoomLocation> bestRoomLocations = new ArrayList<RoomLocation>(); 439 for (Iterator<?> i2 = classEl.elementIterator("room"); i2.hasNext();) { 440 Element roomLocationEl = (Element) i2.next(); 441 Element roomEl = roomElements.get(roomLocationEl.attributeValue("id")); 442 RoomConstraint roomConstraint = roomConstraints.get(roomLocationEl.attributeValue("id")); 443 444 Long roomId = null; 445 String roomName = null; 446 Long bldgId = null; 447 448 if (roomConstraint != null) { 449 roomConstraintsThisClass.add(roomConstraint); 450 roomId = roomConstraint.getResourceId(); 451 roomName = roomConstraint.getRoomName(); 452 bldgId = roomConstraint.getBuildingId(); 453 } else { 454 roomId = Long.valueOf(roomEl.attributeValue("id")); 455 roomName = (roomEl.attributeValue("name") != null ? roomEl.attributeValue("name") : "r" 456 + roomEl.attributeValue("id")); 457 bldgId = (roomEl.attributeValue("building") == null ? null : Long.valueOf(roomEl 458 .attributeValue("building"))); 459 } 460 461 boolean ignoreTooFar = false; 462 if ("true".equals(roomEl.attributeValue("ignoreTooFar"))) 463 ignoreTooFar = true; 464 Double posX = null, posY = null; 465 if (roomEl.attributeValue("location") != null) { 466 String loc = roomEl.attributeValue("location"); 467 posX = Double.valueOf(loc.substring(0, loc.indexOf(','))); 468 posY = Double.valueOf(loc.substring(loc.indexOf(',') + 1)); 469 } 470 RoomLocation rl = new RoomLocation(roomId, roomName, bldgId, Integer.parseInt(roomLocationEl 471 .attributeValue("pref")), Integer.parseInt(roomEl.attributeValue("capacity")), posX, posY, 472 ignoreTooFar, roomConstraint); 473 if ("true".equals(roomLocationEl.attributeValue("initial"))) 474 initialRoomLocations.add(rl); 475 if ("true".equals(roomLocationEl.attributeValue("solution"))) 476 assignedRoomLocations.add(rl); 477 if ("true".equals(roomLocationEl.attributeValue("best"))) 478 bestRoomLocations.add(rl); 479 roomLocations.add(rl); 480 } 481 List<TimeLocation> timeLocations = new ArrayList<TimeLocation>(); 482 TimeLocation initialTimeLocation = null; 483 TimeLocation assignedTimeLocation = null; 484 TimeLocation bestTimeLocation = null; 485 TimeLocation prohibitedTime = perts.get(Long.valueOf(classEl.attributeValue("id"))); 486 487 for (Iterator<?> i2 = classEl.elementIterator("time"); i2.hasNext();) { 488 Element timeLocationEl = (Element) i2.next(); 489 DatePattern dp = defaultDatePattern; 490 if (timeLocationEl.attributeValue("date") != null) 491 dp = datePatterns.get(Long.valueOf(timeLocationEl.attributeValue("date"))); 492 TimeLocation tl = new TimeLocation( 493 Integer.parseInt(timeLocationEl.attributeValue("days"), 2), 494 Integer.parseInt(timeLocationEl.attributeValue("start")), 495 Integer.parseInt(timeLocationEl.attributeValue("length")), 496 (int) Double.parseDouble(timeLocationEl.attributeValue("pref")), 497 Double.parseDouble(timeLocationEl.attributeValue("npref", timeLocationEl.attributeValue("pref"))), 498 Integer.parseInt(timeLocationEl.attributeValue("datePref", "0")), 499 dp.getId(), dp.getName(), dp.getPattern(), 500 Integer.parseInt(timeLocationEl.attributeValue("breakTime") == null ? "-1" : timeLocationEl.attributeValue("breakTime"))); 501 if (tl.getBreakTime() < 0) tl.setBreakTime(tl.getLength() == 18 ? 15 : 10); 502 if (timeLocationEl.attributeValue("pattern") != null) 503 tl.setTimePatternId(Long.valueOf(timeLocationEl.attributeValue("pattern"))); 504 /* 505 * if (timePatternTransform) tl = 506 * transformTimePattern(Long.valueOf 507 * (classEl.attributeValue("id")),tl); 508 */ 509 if (prohibitedTime != null && prohibitedTime.getDayCode() == tl.getDayCode() 510 && prohibitedTime.getStartSlot() == tl.getStartSlot() 511 && prohibitedTime.getLength() == tl.getLength()) { 512 sLogger.info("Time " + tl.getLongName(true) + " is prohibited for class " + classEl.attributeValue("id")); 513 continue; 514 } 515 if ("true".equals(timeLocationEl.attributeValue("solution"))) 516 assignedTimeLocation = tl; 517 if ("true".equals(timeLocationEl.attributeValue("initial"))) 518 initialTimeLocation = tl; 519 if ("true".equals(timeLocationEl.attributeValue("best"))) 520 bestTimeLocation = tl; 521 timeLocations.add(tl); 522 } 523 if (timeLocations.isEmpty()) { 524 sLogger.error(" ERROR: No time."); 525 continue; 526 } 527 528 int minClassLimit = 0; 529 int maxClassLimit = 0; 530 float room2limitRatio = 1.0f; 531 if (!"true".equals(classEl.attributeValue("committed"))) { 532 if (classEl.attributeValue("expectedCapacity") != null) { 533 minClassLimit = maxClassLimit = Integer.parseInt(classEl.attributeValue("expectedCapacity")); 534 int roomCapacity = Integer.parseInt(classEl.attributeValue("roomCapacity", classEl 535 .attributeValue("expectedCapacity"))); 536 if (minClassLimit == 0) 537 minClassLimit = maxClassLimit = roomCapacity; 538 room2limitRatio = (minClassLimit == 0 ? 1.0f : ((float) roomCapacity) / minClassLimit); 539 } else { 540 if (classEl.attribute("classLimit") != null) { 541 minClassLimit = maxClassLimit = Integer.parseInt(classEl.attributeValue("classLimit")); 542 } else { 543 minClassLimit = Integer.parseInt(classEl.attributeValue("minClassLimit")); 544 maxClassLimit = Integer.parseInt(classEl.attributeValue("maxClassLimit")); 545 } 546 room2limitRatio = Float.parseFloat(classEl.attributeValue("roomToLimitRatio", "1.0")); 547 } 548 } 549 550 Lecture lecture = new Lecture(Long.valueOf(classEl.attributeValue("id")), 551 (classEl.attributeValue("solverGroup") != null ? Long 552 .valueOf(classEl.attributeValue("solverGroup")) : null), Long.valueOf(classEl 553 .attributeValue("subpart", classEl.attributeValue("course", "-1"))), (classEl 554 .attributeValue("name") != null ? classEl.attributeValue("name") : "c" 555 + classEl.attributeValue("id")), timeLocations, roomLocations, Integer.parseInt(classEl 556 .attributeValue("nrRooms", roomLocations.isEmpty() ? "0" : "1")), null, minClassLimit, maxClassLimit, room2limitRatio); 557 lecture.setNote(classEl.attributeValue("note")); 558 559 if ("true".equals(classEl.attributeValue("committed"))) 560 lecture.setCommitted(true); 561 562 if (!lecture.isCommitted() && classEl.attributeValue("ord") != null) 563 lecture.setOrd(Integer.parseInt(classEl.attributeValue("ord"))); 564 else 565 lecture.setOrd(ord++); 566 567 lecture.setWeight(Double.parseDouble(classEl.attributeValue("weight", "1.0"))); 568 569 if (lecture.getNrRooms() > 1) 570 lecture.setMaxRoomCombinations(Integer.parseInt(classEl.attributeValue("maxRoomCombinations", "-1"))); 571 572 if (config != null) 573 lecture.setConfiguration(config); 574 575 if (initialTimeLocation != null && initialRoomLocations.size() == lecture.getNrRooms()) { 576 lecture.setInitialAssignment(new Placement(lecture, initialTimeLocation, initialRoomLocations)); 577 } 578 if (assignedTimeLocation != null && assignedRoomLocations.size() == lecture.getNrRooms()) { 579 assignedPlacements.put(lecture, new Placement(lecture, assignedTimeLocation, assignedRoomLocations)); 580 } else if (lecture.getInitialAssignment() != null) { 581 // assignedPlacements.put(lecture, lecture.getInitialAssignment()); 582 } 583 if (bestTimeLocation != null && bestRoomLocations.size() == lecture.getNrRooms()) { 584 lecture.setBestAssignment(new Placement(lecture, bestTimeLocation, bestRoomLocations), 0); 585 } else if (assignedTimeLocation != null && assignedRoomLocations.size() == lecture.getNrRooms()) { 586 // lecture.setBestAssignment(assignedPlacements.get(lecture), 0); 587 } 588 589 lectures.put(classEl.attributeValue("id"), lecture); 590 if (classEl.attributeValue("department") != null) 591 lecture.setDepartment(Long.valueOf(classEl.attributeValue("department"))); 592 if (classEl.attribute("scheduler") != null) 593 lecture.setScheduler(Long.valueOf(classEl.attributeValue("scheduler"))); 594 if ((sectionWholeCourse || !lecture.isCommitted()) && classEl.attributeValue("subpart", classEl.attributeValue("course")) != null) { 595 Long subpartId = Long.valueOf(classEl.attributeValue("subpart", classEl.attributeValue("course"))); 596 List<Lecture> sames = sameLectures.get(subpartId); 597 if (sames == null) { 598 sames = new ArrayList<Lecture>(); 599 sameLectures.put(subpartId, sames); 600 } 601 sames.add(lecture); 602 } 603 String parent = classEl.attributeValue("parent"); 604 if (parent != null) 605 parents.put(lecture, parent); 606 607 getModel().addVariable(lecture); 608 609 if (lecture.isCommitted()) { 610 Placement placement = assignedPlacements.get(lecture); 611 if (classEl.attribute("assignment") != null) 612 placement.setAssignmentId(Long.valueOf(classEl.attributeValue("assignment"))); 613 for (InstructorConstraint ic : ics) 614 ic.setNotAvailable(placement); 615 for (RoomConstraint rc : roomConstraintsThisClass) 616 rc.setNotAvailable(placement); 617 } else { 618 for (InstructorConstraint ic : ics) 619 ic.addVariable(lecture); 620 for (RoomConstraint rc : roomConstraintsThisClass) 621 rc.addVariable(lecture); 622 } 623 624 iProgress.incProgress(); 625 } 626 627 for (Map.Entry<Lecture, String> entry : parents.entrySet()) { 628 Lecture lecture = entry.getKey(); 629 Lecture parent = lectures.get(entry.getValue()); 630 if (parent == null) { 631 iProgress.warn("Parent class " + entry.getValue() + " does not exists."); 632 } else { 633 lecture.setParent(parent); 634 } 635 } 636 637 iProgress.setPhase("Creating constraints ...", root.element("groupConstraints").elements("constraint").size()); 638 HashMap<String, Element> grConstraintElements = new HashMap<String, Element>(); 639 HashMap<String, Constraint<Lecture, Placement>> groupConstraints = new HashMap<String, Constraint<Lecture, Placement>>(); 640 for (Iterator<?> i1 = root.element("groupConstraints").elementIterator("constraint"); i1.hasNext();) { 641 Element grConstraintEl = (Element) i1.next(); 642 Constraint<Lecture, Placement> c = null; 643 if ("SPREAD".equals(grConstraintEl.attributeValue("type"))) { 644 c = new SpreadConstraint(getModel().getProperties(), grConstraintEl.attributeValue("name", "spread")); 645 } else if ("MIN_ROOM_USE".equals(grConstraintEl.attributeValue("type"))) { 646 c = new MinimizeNumberOfUsedRoomsConstraint(getModel().getProperties()); 647 } else if ("CLASS_LIMIT".equals(grConstraintEl.attributeValue("type"))) { 648 if (grConstraintEl.element("parentClass") == null) { 649 c = new ClassLimitConstraint(Integer.parseInt(grConstraintEl.attributeValue("courseLimit")), 650 grConstraintEl.attributeValue("name", "class-limit")); 651 } else { 652 String classId = grConstraintEl.element("parentClass").attributeValue("id"); 653 c = new ClassLimitConstraint(lectures.get(classId), grConstraintEl.attributeValue("name", 654 "class-limit")); 655 } 656 if (grConstraintEl.attributeValue("delta") != null) 657 ((ClassLimitConstraint) c).setClassLimitDelta(Integer.parseInt(grConstraintEl 658 .attributeValue("delta"))); 659 } else if ("MIN_GRUSE(10x1h)".equals(grConstraintEl.attributeValue("type"))) { 660 c = new MinimizeNumberOfUsedGroupsOfTime(getModel().getProperties(), "10x1h", 661 MinimizeNumberOfUsedGroupsOfTime.sGroups10of1h); 662 } else if ("MIN_GRUSE(5x2h)".equals(grConstraintEl.attributeValue("type"))) { 663 c = new MinimizeNumberOfUsedGroupsOfTime(getModel().getProperties(), "5x2h", 664 MinimizeNumberOfUsedGroupsOfTime.sGroups5of2h); 665 } else if ("MIN_GRUSE(3x3h)".equals(grConstraintEl.attributeValue("type"))) { 666 c = new MinimizeNumberOfUsedGroupsOfTime(getModel().getProperties(), "3x3h", 667 MinimizeNumberOfUsedGroupsOfTime.sGroups3of3h); 668 } else if ("MIN_GRUSE(2x5h)".equals(grConstraintEl.attributeValue("type"))) { 669 c = new MinimizeNumberOfUsedGroupsOfTime(getModel().getProperties(), "2x5h", 670 MinimizeNumberOfUsedGroupsOfTime.sGroups2of5h); 671 } else if (IgnoreStudentConflictsConstraint.REFERENCE.equals(grConstraintEl.attributeValue("type"))) { 672 c = new IgnoreStudentConflictsConstraint(); 673 } else { 674 try { 675 FlexibleConstraintType f = FlexibleConstraintType.valueOf(grConstraintEl.attributeValue("type")); 676 try { 677 c = f.create( 678 Long.valueOf(grConstraintEl.attributeValue("id")), 679 grConstraintEl.attributeValue("owner"), 680 grConstraintEl.attributeValue("pref"), 681 grConstraintEl.attributeValue("reference")); 682 } catch (IllegalArgumentException e) { 683 iProgress.warn("Failed to create flexible constraint " + grConstraintEl.attributeValue("type") + ": " + e.getMessage(), e); 684 continue; 685 } 686 } catch (IllegalArgumentException e) { 687 // type did not match, continue with group constraint types 688 c = new GroupConstraint( 689 Long.valueOf(grConstraintEl.attributeValue("id")), 690 GroupConstraint.getConstraintType(grConstraintEl.attributeValue("type")), 691 grConstraintEl.attributeValue("pref")); 692 } 693 } 694 getModel().addConstraint(c); 695 for (Iterator<?> i2 = grConstraintEl.elementIterator("class"); i2.hasNext();) { 696 String classId = ((Element) i2.next()).attributeValue("id"); 697 Lecture other = lectures.get(classId); 698 if (other != null) 699 c.addVariable(other); 700 else 701 iProgress.warn("Class " + classId + " does not exists, but it is referred from group constraint " + c.getId() + " (" + c.getName() + ")"); 702 } 703 grConstraintElements.put(grConstraintEl.attributeValue("id"), grConstraintEl); 704 groupConstraints.put(grConstraintEl.attributeValue("id"), c); 705 iProgress.incProgress(); 706 } 707 708 iProgress.setPhase("Loading students ...", root.element("students").elements("student").size()); 709 boolean initialSectioning = true; 710 HashMap<Long, Student> students = new HashMap<Long, Student>(); 711 HashMap<Long, Set<Student>> offering2students = new HashMap<Long, Set<Student>>(); 712 for (Iterator<?> i1 = root.element("students").elementIterator("student"); i1.hasNext();) { 713 Element studentEl = (Element) i1.next(); 714 List<Lecture> lecturesThisStudent = new ArrayList<Lecture>(); 715 Long studentId = Long.valueOf(studentEl.attributeValue("id")); 716 Student student = students.get(studentId); 717 if (student == null) { 718 student = new Student(studentId); 719 students.put(studentId, student); 720 getModel().addStudent(student); 721 } 722 student.setAcademicArea(studentEl.attributeValue("area")); 723 student.setAcademicClassification(studentEl.attributeValue("classification")); 724 student.setMajor(studentEl.attributeValue("major")); 725 student.setCurriculum(studentEl.attributeValue("curriculum")); 726 for (Iterator<?> i2 = studentEl.elementIterator("offering"); i2.hasNext();) { 727 Element ofEl = (Element) i2.next(); 728 Long offeringId = Long.valueOf(ofEl.attributeValue("id")); 729 String priority = ofEl.attributeValue("priority"); 730 student.addOffering(offeringId, Double.parseDouble(ofEl.attributeValue("weight", "1.0")), priority == null ? null : Double.valueOf(priority)); 731 Set<Student> studentsThisOffering = offering2students.get(offeringId); 732 if (studentsThisOffering == null) { 733 studentsThisOffering = new HashSet<Student>(); 734 offering2students.put(offeringId, studentsThisOffering); 735 } 736 studentsThisOffering.add(student); 737 String altId = ofEl.attributeValue("alternative"); 738 if (altId != null) 739 student.addAlternatives(Long.valueOf(altId), offeringId); 740 } 741 for (Iterator<?> i2 = studentEl.elementIterator("class"); i2.hasNext();) { 742 String classId = ((Element) i2.next()).attributeValue("id"); 743 Lecture lecture = lectures.get(classId); 744 if (lecture == null) { 745 iProgress.warn("Class " + classId + " does not exists, but it is referred from student " + student.getId()); 746 continue; 747 } 748 if (lecture.isCommitted()) { 749 if (sectionWholeCourse && (lecture.getParent() != null || lecture.getConfiguration() != null)) { 750 // committed, but with course structure -- sectioning can be used 751 student.addLecture(lecture); 752 student.addConfiguration(lecture.getConfiguration()); 753 lecture.addStudent(getAssignment(), student); 754 lecturesThisStudent.add(lecture); 755 initialSectioning = false; 756 } else { 757 Placement placement = assignedPlacements.get(lecture); 758 student.addCommitedPlacement(placement); 759 } 760 } else { 761 student.addLecture(lecture); 762 student.addConfiguration(lecture.getConfiguration()); 763 lecture.addStudent(getAssignment(), student); 764 lecturesThisStudent.add(lecture); 765 initialSectioning = false; 766 } 767 } 768 769 for (Iterator<?> i2 = studentEl.elementIterator("prohibited-class"); i2.hasNext();) { 770 String classId = ((Element) i2.next()).attributeValue("id"); 771 Lecture lecture = lectures.get(classId); 772 if (lecture != null) 773 student.addCanNotEnroll(lecture); 774 else 775 iProgress.warn("Class " + classId + " does not exists, but it is referred from student " + student.getId()); 776 } 777 778 if (studentEl.attributeValue("instructor") != null) 779 student.setInstructor(instructorConstraints.get(studentEl.attributeValue("instructor"))); 780 781 iProgress.incProgress(); 782 } 783 784 if (root.element("groups") != null) { 785 iProgress.setPhase("Loading student groups ...", root.element("groups").elements("group").size()); 786 for (Iterator<?> i1 = root.element("groups").elementIterator("group"); i1.hasNext();) { 787 Element groupEl = (Element)i1.next(); 788 long groupId = Long.parseLong(groupEl.attributeValue("id")); 789 StudentGroup group = new StudentGroup(groupId, Double.parseDouble(groupEl.attributeValue("weight", "1.0")), groupEl.attributeValue("name", "Group-" + groupId)); 790 getModel().addStudentGroup(group); 791 for (Iterator<?> i2 = groupEl.elementIterator("student"); i2.hasNext();) { 792 Element studentEl = (Element)i2.next(); 793 Student student = students.get(Long.valueOf(studentEl.attributeValue("id"))); 794 if (student != null) { 795 group.addStudent(student); student.addGroup(group); 796 } 797 } 798 } 799 } 800 801 for (List<Lecture> sames: sameLectures.values()) { 802 for (Lecture lect : sames) { 803 lect.setSameSubpartLectures(sames); 804 } 805 } 806 807 if (initialSectioning) { 808 iProgress.setPhase("Initial sectioning ...", offering2students.size()); 809 for (Map.Entry<Long, Set<Student>> entry : offering2students.entrySet()) { 810 Long offeringId = entry.getKey(); 811 Set<Student> studentsThisOffering = entry.getValue(); 812 List<Configuration> altConfigs = alternativeConfigurations.get(offeringId); 813 getModel().getStudentSectioning().initialSectioning(getAssignment(), offeringId, String.valueOf(offeringId), studentsThisOffering, altConfigs); 814 iProgress.incProgress(); 815 } 816 for (Student student: students.values()) { 817 student.clearDistanceCache(); 818 if (student.getInstructor() != null) 819 for (Lecture lecture: student.getInstructor().variables()) { 820 student.addLecture(lecture); 821 student.addConfiguration(lecture.getConfiguration()); 822 lecture.addStudent(getAssignment(), student); 823 } 824 } 825 } 826 827 iProgress.setPhase("Computing jenrl ...", students.size()); 828 HashMap<Lecture, HashMap<Lecture, JenrlConstraint>> jenrls = new HashMap<Lecture, HashMap<Lecture, JenrlConstraint>>(); 829 for (Iterator<Student> i1 = students.values().iterator(); i1.hasNext();) { 830 Student st = i1.next(); 831 for (Iterator<Lecture> i2 = st.getLectures().iterator(); i2.hasNext();) { 832 Lecture l1 = i2.next(); 833 for (Iterator<Lecture> i3 = st.getLectures().iterator(); i3.hasNext();) { 834 Lecture l2 = i3.next(); 835 if (l1.getId() >= l2.getId()) 836 continue; 837 HashMap<Lecture, JenrlConstraint> x = jenrls.get(l1); 838 if (x == null) { 839 x = new HashMap<Lecture, JenrlConstraint>(); 840 jenrls.put(l1, x); 841 } 842 JenrlConstraint jenrl = x.get(l2); 843 if (jenrl == null) { 844 jenrl = new JenrlConstraint(); 845 jenrl.addVariable(l1); 846 jenrl.addVariable(l2); 847 getModel().addConstraint(jenrl); 848 x.put(l2, jenrl); 849 } 850 jenrl.incJenrl(getAssignment(), st); 851 } 852 } 853 iProgress.incProgress(); 854 } 855 856 if (iDeptBalancing) { 857 iProgress.setPhase("Creating dept. spread constraints ...", getModel().variables().size()); 858 HashMap<Long, DepartmentSpreadConstraint> depSpreadConstraints = new HashMap<Long, DepartmentSpreadConstraint>(); 859 for (Lecture lecture : getModel().variables()) { 860 if (lecture.getDepartment() == null) 861 continue; 862 DepartmentSpreadConstraint deptConstr = depSpreadConstraints.get(lecture.getDepartment()); 863 if (deptConstr == null) { 864 String name = depts.get(lecture.getDepartment()); 865 deptConstr = new DepartmentSpreadConstraint(getModel().getProperties(), lecture.getDepartment(), 866 (name != null ? name : "d" + lecture.getDepartment())); 867 depSpreadConstraints.put(lecture.getDepartment(), deptConstr); 868 getModel().addConstraint(deptConstr); 869 } 870 deptConstr.addVariable(lecture); 871 iProgress.incProgress(); 872 } 873 } 874 875 if (getModel().getProperties().getPropertyBoolean("General.PurgeInvalidPlacements", true)) { 876 iProgress.setPhase("Purging invalid placements ...", getModel().variables().size()); 877 for (Lecture lecture : getModel().variables()) { 878 lecture.purgeInvalidValues(iInteractiveMode); 879 iProgress.incProgress(); 880 } 881 } 882 883 if (getModel().hasConstantVariables() && getModel().constantVariables().size() > 0) { 884 iProgress.setPhase("Assigning committed classes ...", assignedPlacements.size()); 885 for (Map.Entry<Lecture, Placement> entry : assignedPlacements.entrySet()) { 886 Lecture lecture = entry.getKey(); 887 Placement placement = entry.getValue(); 888 if (!lecture.isCommitted()) { iProgress.incProgress(); continue; } 889 lecture.setConstantValue(placement); 890 getModel().weaken(getAssignment(), placement); 891 Map<Constraint<Lecture, Placement>, Set<Placement>> conflictConstraints = getModel().conflictConstraints(getAssignment(), placement); 892 if (conflictConstraints.isEmpty()) { 893 getAssignment().assign(0, placement); 894 } else { 895 iProgress.warn("WARNING: Unable to assign " + lecture.getName() + " := " + placement.getName()); 896 iProgress.debug(" Reason:"); 897 for (Constraint<Lecture, Placement> c : conflictConstraints.keySet()) { 898 Set<Placement> vals = conflictConstraints.get(c); 899 for (Placement v : vals) { 900 iProgress.debug(" " + v.variable().getName() + " = " + v.getName()); 901 } 902 iProgress.debug(" in constraint " + c); 903 } 904 } 905 iProgress.incProgress(); 906 } 907 } 908 909 if (currentSolution != null) { 910 iProgress.setPhase("Creating best assignment ...", 2 * getModel().variables().size()); 911 for (Lecture lecture : getModel().variables()) { 912 iProgress.incProgress(); 913 Placement placement = lecture.getBestAssignment(); 914 if (placement == null) continue; 915 getModel().weaken(getAssignment(), placement); 916 getAssignment().assign(0, placement); 917 } 918 919 currentSolution.saveBest(); 920 for (Lecture lecture : getModel().variables()) { 921 iProgress.incProgress(); 922 getAssignment().unassign(0, lecture); 923 } 924 } 925 926 iProgress.setPhase("Creating initial assignment ...", assignedPlacements.size()); 927 for (Map.Entry<Lecture, Placement> entry : assignedPlacements.entrySet()) { 928 Lecture lecture = entry.getKey(); 929 Placement placement = entry.getValue(); 930 if (lecture.isCommitted()) { iProgress.incProgress(); continue; } 931 getModel().weaken(getAssignment(), placement); 932 Map<Constraint<Lecture, Placement>, Set<Placement>> conflictConstraints = getModel().conflictConstraints(getAssignment(), placement); 933 if (conflictConstraints.isEmpty()) { 934 if (!placement.isValid()) { 935 iProgress.warn("WARNING: Lecture " + lecture.getName() + " does not contain assignment " 936 + placement.getLongName(true) + " in its domain (" + placement.getNotValidReason(getAssignment(), true) + ")."); 937 } else 938 getAssignment().assign(0, placement); 939 } else { 940 iProgress.warn("WARNING: Unable to assign " + lecture.getName() + " := " + placement.getName()); 941 iProgress.debug(" Reason:"); 942 for (Constraint<Lecture, Placement> c : conflictConstraints.keySet()) { 943 Set<Placement> vals = conflictConstraints.get(c); 944 for (Placement v : vals) { 945 iProgress.debug(" " + v.variable().getName() + " = " + v.getName()); 946 } 947 iProgress.debug(" in constraint " + c); 948 } 949 } 950 iProgress.incProgress(); 951 } 952 953 if (initialSectioning && getAssignment().nrAssignedVariables() != 0 && !getModel().getProperties().getPropertyBoolean("Global.LoadStudentEnrlsFromSolution", false)) 954 getModel().switchStudents(getAssignment()); 955 956 if (iForcedPerturbances > 0) { 957 iProgress.setPhase("Forcing perturbances", iForcedPerturbances); 958 for (int i = 0; i < iForcedPerturbances; i++) { 959 iProgress.setProgress(i); 960 Lecture var = null; 961 do { 962 var = ToolBox.random(getModel().variables()); 963 } while (var.getInitialAssignment() == null || var.values(getAssignment()).size() <= 1); 964 var.removeInitialValue(); 965 } 966 } 967 968 /* 969 for (Constraint<Lecture, Placement> c : getModel().constraints()) { 970 if (c instanceof SpreadConstraint) 971 ((SpreadConstraint) c).init(); 972 if (c instanceof DiscouragedRoomConstraint) 973 ((DiscouragedRoomConstraint) c).setEnabled(true); 974 if (c instanceof MinimizeNumberOfUsedRoomsConstraint) 975 ((MinimizeNumberOfUsedRoomsConstraint) c).setEnabled(true); 976 if (c instanceof MinimizeNumberOfUsedGroupsOfTime) 977 ((MinimizeNumberOfUsedGroupsOfTime) c).setEnabled(true); 978 } 979 */ 980 } 981 982 public static Date getDate(int year, int dayOfYear) { 983 Calendar c = Calendar.getInstance(Locale.US); 984 c.set(year, 1, 1, 0, 0, 0); 985 c.set(Calendar.DAY_OF_YEAR, dayOfYear); 986 return c.getTime(); 987 } 988 989 public static class DatePattern { 990 Long iId; 991 String iName; 992 BitSet iPattern; 993 public DatePattern() {} 994 public DatePattern(Long id, String name, BitSet pattern) { 995 setId(id); setName(name); setPattern(pattern); 996 } 997 public DatePattern(Long id, String name, String pattern) { 998 setId(id); setName(name); setPattern(pattern); 999 } 1000 public Long getId() { return iId; } 1001 public void setId(Long id) { iId = id; } 1002 public String getName() { return iName; } 1003 public void setName(String name) { iName = name; } 1004 public BitSet getPattern() { return iPattern; } 1005 public void setPattern(BitSet pattern) { iPattern = pattern; } 1006 public void setPattern(String pattern) { 1007 iPattern = new BitSet(pattern.length()); 1008 for (int i = 0; i < pattern.length(); i++) 1009 if (pattern.charAt(i) == '1') 1010 iPattern.set(i); 1011 } 1012 public void setPattern(int startDay, int endDay) { 1013 iPattern = new BitSet(366); 1014 for (int d = startDay; d <= endDay; d++) 1015 iPattern.set(d); 1016 } 1017 } 1018}