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 }