    001package org.cpsolver.studentsct.filter;
    002
    003import java.util.HashSet;
    004
    005import org.cpsolver.ifs.util.ToolBox;
    006import org.cpsolver.studentsct.model.Student;
    007
    008
    009/**
    010 * This student filter accepts every student with the given probability. The
    011 * choice for each student is remembered, i.e., if the student is passed to the
    012 * filter multiple times the same answer is returned.
    013 *
    014 * @version StudentSct 1.3 (Student Sectioning)<br>
    015 *          Copyright (C) 2007 - 2014 Tomáš Müller<br>
    016 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
    017 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
    018 * <br>
    019 *          This library is free software; you can redistribute it and/or modify
    020 *          it under the terms of the GNU Lesser General Public License as
    021 *          published by the Free Software Foundation; either version 3 of the
    022 *          License, or (at your option) any later version. <br>
    023 * <br>
    024 *          This library is distributed in the hope that it will be useful, but
    025 *          WITHOUT ANY WARRANTY; without even the implied warranty of
    026 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    027 *          Lesser General Public License for more details. <br>
    028 * <br>
    029 *          You should have received a copy of the GNU Lesser General Public
    030 *          License along with this library; if not see
    031 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
    032 */
    033public class RandomStudentFilter implements StudentFilter {
    034    private double iProb = 1.0;
    035    private HashSet<Long> iAcceptedStudentIds = new HashSet<Long>();
    036    private HashSet<Long> iRejectedStudentIds = new HashSet<Long>();
    037
    038    /**
    039     * Constructor
    040     *
    041     * @param prob
    042     *            probability of acceptance of a student
    043     */
    044    public RandomStudentFilter(double prob) {
    045        iProb = prob;
    046    }
    047
    048    /**
    049     * A student is accepted with the given probability
    050     */
    051    @Override
    052    public boolean accept(Student student) {
    053        Long studentId = new Long(student.getId());
    054        if (iAcceptedStudentIds.contains(studentId))
    055            return true;
    056        if (iRejectedStudentIds.contains(studentId))
    057            return false;
    058        boolean accept = (Math.random() < iProb);
    059        if (accept)
    060            iAcceptedStudentIds.add(studentId);
    061        else
    062            iRejectedStudentIds.add(studentId);
    063        return accept;
    064    }
    065
    066    /**
    067     * Set acceptance probability. Update the sets of accepted and rejected
    068     * students accordingly.
    069     *
    070     * @param prob
    071     *            new acceptance probability
    072     */
    073    public void setProbability(double prob) {
    074        iProb = prob;
    075        int accept = (int) Math.round(prob * (iAcceptedStudentIds.size() + iRejectedStudentIds.size()));
    076        while (iAcceptedStudentIds.size() < accept && !iRejectedStudentIds.isEmpty()) {
    077            Long studentId = ToolBox.random(iRejectedStudentIds);
    078            iRejectedStudentIds.remove(studentId);
    079            iAcceptedStudentIds.add(studentId);
    080        }
    081        while (iAcceptedStudentIds.size() > accept && !iAcceptedStudentIds.isEmpty()) {
    082            Long studentId = ToolBox.random(iAcceptedStudentIds);
    083            iRejectedStudentIds.add(studentId);
    084            iAcceptedStudentIds.remove(studentId);
    085        }
    086    }
    087
    088    @Override
    089    public String getName() {
    090        return "Random";
    091    }
    092
    093}