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