001    package net.sf.cpsolver.studentsct.heuristics;
002    
003    import net.sf.cpsolver.ifs.heuristics.RouletteWheelSelection;
004    import net.sf.cpsolver.ifs.heuristics.VariableSelection;
005    import net.sf.cpsolver.ifs.solution.Solution;
006    import net.sf.cpsolver.ifs.solver.Solver;
007    import net.sf.cpsolver.ifs.util.DataProperties;
008    import net.sf.cpsolver.studentsct.StudentSectioningModel;
009    import net.sf.cpsolver.studentsct.model.Enrollment;
010    import net.sf.cpsolver.studentsct.model.Request;
011    
012    /**
013     * Variable ({@link Request}) selection using {@link RouletteWheelSelection}.
014     * Unassigned request has 10 points, an assigned request has 1 point for each
015     * section that exceeds its bound.
016     * 
017     * <br>
018     * <br>
019     * 
020     * @version StudentSct 1.2 (Student Sectioning)<br>
021     *          Copyright (C) 2007 - 2010 Tomas Muller<br>
022     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
023     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
024     * <br>
025     *          This library is free software; you can redistribute it and/or modify
026     *          it under the terms of the GNU Lesser General Public License as
027     *          published by the Free Software Foundation; either version 3 of the
028     *          License, or (at your option) any later version. <br>
029     * <br>
030     *          This library is distributed in the hope that it will be useful, but
031     *          WITHOUT ANY WARRANTY; without even the implied warranty of
032     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
033     *          Lesser General Public License for more details. <br>
034     * <br>
035     *          You should have received a copy of the GNU Lesser General Public
036     *          License along with this library; if not see
037     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
038     */
039    public class RouletteWheelRequestSelection implements VariableSelection<Request, Enrollment> {
040        RouletteWheelSelection<Request> iRoulette = null;
041    
042        /**
043         * Constructor
044         * 
045         * @param properties
046         *            configuration
047         */
048        public RouletteWheelRequestSelection(DataProperties properties) {
049            super();
050        }
051    
052        /** Initialization */
053        @Override
054        public void init(Solver<Request, Enrollment> solver) {
055    
056        }
057    
058        /** Populate roulette wheel selection, if null or empty. */
059        protected RouletteWheelSelection<Request> getRoulette(Solution<Request, Enrollment> solution) {
060            if (iRoulette != null && iRoulette.hasMoreElements()) {
061                if (iRoulette.getUsedPoints() < 0.1 * iRoulette.getTotalPoints())
062                    return iRoulette;
063            }
064            iRoulette = new RouletteWheelSelection<Request>();
065            for (Request request : ((StudentSectioningModel) solution.getModel()).variables()) {
066                double points = 0;
067                if (request.getAssignment() == null)
068                    points += 10;
069                else {
070                    Enrollment enrollment = request.getAssignment();
071                    if (enrollment.toDouble() > request.getBound())
072                        points += 1;
073                }
074                if (points > 0)
075                    iRoulette.add(request, points);
076            }
077            return iRoulette;
078        }
079    
080        /**
081         * Variable selection. {@link RouletteWheelSelection} is used. Unassigned
082         * request has 10 points, an assigned request has 1 point for each section
083         * that exceeds its bound.
084         */
085        @Override
086        public Request selectVariable(Solution<Request, Enrollment> solution) {
087            return getRoulette(solution).nextElement();
088        }
089    }