001 package net.sf.cpsolver.studentsct.heuristics;
002
003 import java.util.Enumeration;
004 import java.util.Vector;
005
006 import net.sf.cpsolver.ifs.heuristics.NeighbourSelection;
007 import net.sf.cpsolver.ifs.model.Neighbour;
008 import net.sf.cpsolver.ifs.solution.Solution;
009 import net.sf.cpsolver.ifs.solver.Solver;
010 import net.sf.cpsolver.ifs.util.DataProperties;
011 import net.sf.cpsolver.studentsct.StudentSectioningModel;
012 import net.sf.cpsolver.studentsct.model.Student;
013
014 /**
015 * Two-phase (Batch) student sectioning neighbour selection.
016 * It is based on {@link StudentSctNeighbourSelection}, however in the first round, only real students are sectioned.
017 * All dummy students are removed from the problem during initialization of this neighbour selection, they
018 * are returned into the problem after the first round of {@link StudentSctNeighbourSelection}.
019 *
020 * <br><br>
021 *
022 * @version
023 * StudentSct 1.1 (Student Sectioning)<br>
024 * Copyright (C) 2007 Tomáš Müller<br>
025 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
026 * Lazenska 391, 76314 Zlin, Czech Republic<br>
027 * <br>
028 * This library is free software; you can redistribute it and/or
029 * modify it under the terms of the GNU Lesser General Public
030 * License as published by the Free Software Foundation; either
031 * version 2.1 of the License, or (at your option) any later version.
032 * <br><br>
033 * This library is distributed in the hope that it will be useful,
034 * but WITHOUT ANY WARRANTY; without even the implied warranty of
035 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
036 * Lesser General Public License for more details.
037 * <br><br>
038 * You should have received a copy of the GNU Lesser General Public
039 * License along with this library; if not, write to the Free Software
040 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
041 */
042
043 public class TwoPhaseStudentSctNeighbourSelection extends StudentSctNeighbourSelection {
044 private int iNrRounds = 7;
045
046 public TwoPhaseStudentSctNeighbourSelection(DataProperties properties) throws Exception {
047 super(properties);
048 iNrRounds = properties.getPropertyInt("TwoPhaseSectioning.NrRoundsFirstPhase", iNrRounds);
049 }
050
051 /** Initialization -- also remove all the dummy students from the problem */
052 public void init(Solver solver) {
053 super.init(solver);
054 if (removeDummyStudents(solver.currentSolution()))
055 registerSelection(new RestoreDummyStudents());
056 }
057
058 Vector iDummyStudents = null;
059 private boolean removeDummyStudents(Solution solution) {
060 StudentSectioningModel model = (StudentSectioningModel)solution.getModel();
061 if (model.getNrLastLikeStudents(false)==0 || model.getNrRealStudents(false)==0) return false;
062 iDummyStudents = new Vector();
063 for (Enumeration e=new Vector(model.getStudents()).elements();e.hasMoreElements();) {
064 Student student = (Student)e.nextElement();
065 if (student.isDummy()) {
066 iDummyStudents.add(student);
067 model.removeStudent(student);
068 }
069 }
070 return true;
071 }
072
073 private boolean addDummyStudents(Solution solution) {
074 if (iDummyStudents==null || iDummyStudents.isEmpty()) return false;
075 iNrRounds--;
076 if (iNrRounds>0) return false;
077 solution.restoreBest();
078 StudentSectioningModel model = (StudentSectioningModel)solution.getModel();
079 for (Enumeration e=iDummyStudents.elements();e.hasMoreElements();) {
080 Student student = (Student)e.nextElement();
081 model.addStudent(student);
082 }
083 iDummyStudents = null;
084 solution.saveBest();
085 return true;
086 }
087
088 /** Return all dummy students into the problem, executed as the last phase of the first round */
089 protected class RestoreDummyStudents implements NeighbourSelection {
090 public RestoreDummyStudents() {}
091 public void init(Solver solver) {}
092 /** Return all (removed) dummy students into the problem */
093 public Neighbour selectNeighbour(Solution solution) {
094 addDummyStudents(solution);
095 return null;
096 }
097 }
098 }