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