001package org.cpsolver.exam.neighbours; 002 003import java.util.Set; 004 005import org.cpsolver.exam.model.Exam; 006import org.cpsolver.exam.model.ExamModel; 007import org.cpsolver.exam.model.ExamPeriodPlacement; 008import org.cpsolver.exam.model.ExamPlacement; 009import org.cpsolver.exam.model.ExamRoomPlacement; 010import org.cpsolver.ifs.assignment.Assignment; 011import org.cpsolver.ifs.heuristics.NeighbourSelection; 012import org.cpsolver.ifs.model.Neighbour; 013import org.cpsolver.ifs.solution.Solution; 014import org.cpsolver.ifs.solver.Solver; 015import org.cpsolver.ifs.util.DataProperties; 016import org.cpsolver.ifs.util.ToolBox; 017 018 019/** 020 * A period is selected randomly for a randomly selected exam. Rooms are 021 * computed using {@link Exam#findBestAvailableRooms(Assignment, ExamPeriodPlacement)}. <br> 022 * <br> 023 * 024 * @version ExamTT 1.3 (Examination Timetabling)<br> 025 * Copyright (C) 2008 - 2014 Tomáš Müller<br> 026 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 027 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 028 * <br> 029 * This library is free software; you can redistribute it and/or modify 030 * it under the terms of the GNU Lesser General Public License as 031 * published by the Free Software Foundation; either version 3 of the 032 * License, or (at your option) any later version. <br> 033 * <br> 034 * This library is distributed in the hope that it will be useful, but 035 * WITHOUT ANY WARRANTY; without even the implied warranty of 036 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 037 * Lesser General Public License for more details. <br> 038 * <br> 039 * You should have received a copy of the GNU Lesser General Public 040 * License along with this library; if not see 041 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 042 */ 043public class ExamRandomMove implements NeighbourSelection<Exam, ExamPlacement> { 044 private boolean iCheckStudentConflicts = false; 045 private boolean iCheckDistributionConstraints = true; 046 047 /** 048 * Constructor 049 * 050 * @param properties 051 * problem properties 052 */ 053 public ExamRandomMove(DataProperties properties) { 054 iCheckStudentConflicts = properties.getPropertyBoolean("ExamRandomMove.CheckStudentConflicts", iCheckStudentConflicts); 055 iCheckDistributionConstraints = properties.getPropertyBoolean("ExamRandomMove.CheckDistributionConstraints", iCheckDistributionConstraints); 056 } 057 058 /** 059 * Initialization 060 */ 061 @Override 062 public void init(Solver<Exam, ExamPlacement> solver) { 063 } 064 065 /** 066 * Select an exam randomly, select an available period randomly (from 067 * {@link Exam#getPeriodPlacements()}), select rooms using 068 * {@link Exam#findBestAvailableRooms(Assignment, ExamPeriodPlacement)}. 069 */ 070 @Override 071 public Neighbour<Exam, ExamPlacement> selectNeighbour(Solution<Exam, ExamPlacement> solution) { 072 ExamModel model = (ExamModel) solution.getModel(); 073 Assignment<Exam, ExamPlacement> assignment = solution.getAssignment(); 074 Exam exam = ToolBox.random(model.variables()); 075 int px = ToolBox.random(exam.getPeriodPlacements().size()); 076 for (int p = 0; p < exam.getPeriodPlacements().size(); p++) { 077 ExamPeriodPlacement period = exam.getPeriodPlacements().get((p + px) % exam.getPeriodPlacements().size()); 078 if (iCheckStudentConflicts && exam.countStudentConflicts(assignment, period) > 0) 079 continue; 080 if (iCheckDistributionConstraints && !exam.checkDistributionConstraints(assignment, period)) 081 continue; 082 Set<ExamRoomPlacement> rooms = exam.findBestAvailableRooms(assignment, period); 083 if (rooms == null) 084 continue; 085 return new ExamSimpleNeighbour(assignment, new ExamPlacement(exam, period, rooms)); 086 } 087 return null; 088 } 089}