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