001 package net.sf.cpsolver.studentsct.heuristics;
002
003 import java.util.ArrayList;
004 import java.util.List;
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.Enrollment;
013 import net.sf.cpsolver.studentsct.model.Request;
014 import net.sf.cpsolver.studentsct.model.Student;
015
016 /**
017 * Two-phase (Batch) student sectioning neighbour selection. It is based on
018 * {@link StudentSctNeighbourSelection}, however in the first round, only real
019 * students are sectioned. All dummy students are removed from the problem
020 * during initialization of this neighbour selection, they are returned into the
021 * problem after the first round of {@link StudentSctNeighbourSelection}.
022 *
023 * <br>
024 * <br>
025 *
026 * @version StudentSct 1.2 (Student Sectioning)<br>
027 * Copyright (C) 2007 - 2010 Tomas Muller<br>
028 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
029 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
030 * <br>
031 * This library is free software; you can redistribute it and/or modify
032 * it under the terms of the GNU Lesser General Public License as
033 * published by the Free Software Foundation; either version 3 of the
034 * License, or (at your option) any later version. <br>
035 * <br>
036 * This library is distributed in the hope that it will be useful, but
037 * WITHOUT ANY WARRANTY; without even the implied warranty of
038 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
039 * Lesser General Public License for more details. <br>
040 * <br>
041 * You should have received a copy of the GNU Lesser General Public
042 * License along with this library; if not see
043 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
044 */
045
046 public class TwoPhaseStudentSctNeighbourSelection extends StudentSctNeighbourSelection {
047 private int iNrRounds = 7;
048
049 public TwoPhaseStudentSctNeighbourSelection(DataProperties properties) throws Exception {
050 super(properties);
051 iNrRounds = properties.getPropertyInt("TwoPhaseSectioning.NrRoundsFirstPhase", iNrRounds);
052 }
053
054 /** Initialization -- also remove all the dummy students from the problem */
055 @Override
056 public void init(Solver<Request, Enrollment> solver) {
057 super.init(solver);
058 if (removeDummyStudents(solver.currentSolution()))
059 registerSelection(new RestoreDummyStudents());
060 }
061
062 List<Student> iDummyStudents = null;
063
064 private boolean removeDummyStudents(Solution<Request, Enrollment> solution) {
065 StudentSectioningModel model = (StudentSectioningModel) solution.getModel();
066 if (model.getNrLastLikeStudents(false) == 0 || model.getNrRealStudents(false) == 0)
067 return false;
068 iDummyStudents = new ArrayList<Student>();
069 for (Student student : new ArrayList<Student>(model.getStudents())) {
070 if (student.isDummy()) {
071 iDummyStudents.add(student);
072 model.removeStudent(student);
073 }
074 }
075 return true;
076 }
077
078 private boolean addDummyStudents(Solution<Request, Enrollment> solution) {
079 if (iDummyStudents == null || iDummyStudents.isEmpty())
080 return false;
081 iNrRounds--;
082 if (iNrRounds > 0)
083 return false;
084 solution.restoreBest();
085 StudentSectioningModel model = (StudentSectioningModel) solution.getModel();
086 for (Student student : iDummyStudents) {
087 model.addStudent(student);
088 }
089 iDummyStudents = null;
090 solution.saveBest();
091 return true;
092 }
093
094 /**
095 * Return all dummy students into the problem, executed as the last phase of
096 * the first round
097 */
098 protected class RestoreDummyStudents implements NeighbourSelection<Request, Enrollment> {
099 public RestoreDummyStudents() {
100 }
101
102 @Override
103 public void init(Solver<Request, Enrollment> solver) {
104 }
105
106 /** Return all (removed) dummy students into the problem */
107 @Override
108 public Neighbour<Request, Enrollment> selectNeighbour(Solution<Request, Enrollment> solution) {
109 addDummyStudents(solution);
110 return null;
111 }
112 }
113 }