001package net.sf.cpsolver.exam.neighbours; 002 003import java.util.Set; 004 005import net.sf.cpsolver.exam.model.Exam; 006import net.sf.cpsolver.exam.model.ExamModel; 007import net.sf.cpsolver.exam.model.ExamPeriodPlacement; 008import net.sf.cpsolver.exam.model.ExamPlacement; 009import net.sf.cpsolver.exam.model.ExamRoomPlacement; 010import net.sf.cpsolver.ifs.heuristics.NeighbourSelection; 011import net.sf.cpsolver.ifs.model.Neighbour; 012import net.sf.cpsolver.ifs.solution.Solution; 013import net.sf.cpsolver.ifs.solver.Solver; 014import net.sf.cpsolver.ifs.util.DataProperties; 015import net.sf.cpsolver.ifs.util.ToolBox; 016 017/** 018 * A period is selected randomly for a randomly selected exam. Rooms are 019 * computed using {@link Exam#findBestAvailableRooms(ExamPeriodPlacement)}. <br> 020 * <br> 021 * 022 * @version ExamTT 1.2 (Examination Timetabling)<br> 023 * Copyright (C) 2008 - 2010 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 ExamRandomMove implements NeighbourSelection<Exam, ExamPlacement> { 042 private boolean iCheckStudentConflicts = false; 043 private boolean iCheckDistributionConstraints = true; 044 045 /** 046 * Constructor 047 * 048 * @param properties 049 * problem properties 050 */ 051 public ExamRandomMove(DataProperties properties) { 052 iCheckStudentConflicts = properties.getPropertyBoolean("ExamRandomMove.CheckStudentConflicts", 053 iCheckStudentConflicts); 054 iCheckDistributionConstraints = properties.getPropertyBoolean("ExamRandomMove.CheckDistributionConstraints", 055 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(ExamPeriodPlacement)}. 069 */ 070 @Override 071 public Neighbour<Exam, ExamPlacement> selectNeighbour(Solution<Exam, ExamPlacement> solution) { 072 ExamModel model = (ExamModel) solution.getModel(); 073 Exam exam = ToolBox.random(model.variables()); 074 int px = ToolBox.random(exam.getPeriodPlacements().size()); 075 for (int p = 0; p < exam.getPeriodPlacements().size(); p++) { 076 ExamPeriodPlacement period = exam.getPeriodPlacements().get((p + px) % exam.getPeriodPlacements().size()); 077 if (iCheckStudentConflicts && exam.countStudentConflicts(period) > 0) 078 continue; 079 if (iCheckDistributionConstraints && !exam.checkDistributionConstraints(period)) 080 continue; 081 Set<ExamRoomPlacement> rooms = exam.findBestAvailableRooms(period); 082 if (rooms == null) 083 continue; 084 return new ExamSimpleNeighbour(new ExamPlacement(exam, period, rooms)); 085 } 086 return null; 087 } 088}