001    package net.sf.cpsolver.exam.neighbours;
002    
003    import java.util.Set;
004    
005    import net.sf.cpsolver.exam.model.Exam;
006    import net.sf.cpsolver.exam.model.ExamModel;
007    import net.sf.cpsolver.exam.model.ExamPeriodPlacement;
008    import net.sf.cpsolver.exam.model.ExamPlacement;
009    import net.sf.cpsolver.ifs.heuristics.NeighbourSelection;
010    import net.sf.cpsolver.ifs.model.Neighbour;
011    import net.sf.cpsolver.ifs.solution.Solution;
012    import net.sf.cpsolver.ifs.solver.Solver;
013    import net.sf.cpsolver.ifs.util.DataProperties;
014    import net.sf.cpsolver.ifs.util.ToolBox;
015    
016    /**
017     * A period is selected randomly for a randomly selected exam. Rooms 
018     * are computed using {@link Exam#findBestAvailableRooms(ExamPeriodPlacement)}. 
019     * <br><br>
020     * 
021     * @version
022     * ExamTT 1.1 (Examination Timetabling)<br>
023     * Copyright (C) 2008 Tomáš Müller<br>
024     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
025     * Lazenska 391, 76314 Zlin, Czech Republic<br>
026     * <br>
027     * This library is free software; you can redistribute it and/or
028     * modify it under the terms of the GNU Lesser General Public
029     * License as published by the Free Software Foundation; either
030     * version 2.1 of the License, or (at your option) any later version.
031     * <br><br>
032     * This library is distributed in the hope that it will be useful,
033     * but 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.
036     * <br><br>
037     * You should have received a copy of the GNU Lesser General Public
038     * License along with this library; if not, write to the Free Software
039     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
040     */
041    public class ExamRandomMove implements NeighbourSelection {
042        private boolean iCheckStudentConflicts = false;
043        private boolean iCheckDistributionConstraints = true;
044        
045        /**
046         * Constructor
047         * @param properties problem properties
048         */
049        public ExamRandomMove(DataProperties properties) {
050            iCheckStudentConflicts = properties.getPropertyBoolean("ExamRandomMove.CheckStudentConflicts", iCheckStudentConflicts);
051            iCheckDistributionConstraints = properties.getPropertyBoolean("ExamRandomMove.CheckDistributionConstraints", iCheckDistributionConstraints);
052        }
053        
054        /**
055         * Initialization
056         */
057        public void init(Solver solver) {}
058        
059        /**
060         * Select an exam randomly,
061         * select an available period randomly (from {@link Exam#getPeriodPlacements()}), 
062         * select rooms using {@link Exam#findBestAvailableRooms(ExamPeriodPlacement)}.
063         */
064        public Neighbour selectNeighbour(Solution solution) {
065            ExamModel model = (ExamModel)solution.getModel();
066            Exam exam = (Exam)ToolBox.random(model.variables());
067            int px = ToolBox.random(exam.getPeriodPlacements().size());
068            for (int p=0;p<exam.getPeriodPlacements().size();p++) {
069                ExamPeriodPlacement period = (ExamPeriodPlacement)exam.getPeriodPlacements().elementAt((p+px)%exam.getPeriodPlacements().size());
070                if (iCheckStudentConflicts && exam.countStudentConflicts(period)>0) continue;
071                if (iCheckDistributionConstraints && !exam.checkDistributionConstraints(period)) continue;
072                Set rooms = exam.findBestAvailableRooms(period);
073                if (rooms==null) continue;
074                return new ExamSimpleNeighbour(new ExamPlacement(exam, period, rooms));
075            }
076            return null;
077        }
078    }