001package org.cpsolver.studentsct.online; 002 003import java.util.Set; 004 005import org.apache.log4j.Logger; 006import org.cpsolver.ifs.assignment.Assignment; 007import org.cpsolver.ifs.model.Constraint; 008import org.cpsolver.ifs.model.Value; 009import org.cpsolver.ifs.util.DataProperties; 010import org.cpsolver.studentsct.StudentSectioningModel; 011import org.cpsolver.studentsct.model.Enrollment; 012import org.cpsolver.studentsct.model.Request; 013import org.cpsolver.studentsct.model.Section; 014import org.cpsolver.studentsct.online.expectations.AvoidUnbalancedWhenNoExpectations; 015import org.cpsolver.studentsct.online.expectations.OverExpectedCriterion; 016import org.cpsolver.studentsct.online.expectations.PercentageOverExpected; 017 018/** 019 * An online model. A simple extension of the {@link OnlineSectioningModel} class that allows to set the over-expected 020 * criterion (see {@link OverExpectedCriterion}). This class is particularly useful in passing the over-expected criterion to the 021 * online sectioning algorithms and heuristics.<br><br> 022 * The over-expected criterion can be passed as a constructor parameter, or given using the OverExpectedCriterion.Class parameter. 023 * It defaults to {@link AvoidUnbalancedWhenNoExpectations}. 024 * 025 * @version StudentSct 1.3 (Student Sectioning)<br> 026 * Copyright (C) 2014 Tomas Muller<br> 027 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 028 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 029 * <br> 030 * This library is free software; you can redistribute it and/or modify 031 * it under the terms of the GNU Lesser General Public License as 032 * published by the Free Software Foundation; either version 3 of the 033 * License, or (at your option) any later version. <br> 034 * <br> 035 * This library is distributed in the hope that it will be useful, but 036 * WITHOUT ANY WARRANTY; without even the implied warranty of 037 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 038 * Lesser General Public License for more details. <br> 039 * <br> 040 * You should have received a copy of the GNU Lesser General Public 041 * License along with this library; if not see <a href='http://www.gnu.org/licenses'>http://www.gnu.org/licenses</a>. 042 * 043 */ 044public class OnlineSectioningModel extends StudentSectioningModel { 045 private static Logger sLog = Logger.getLogger(OnlineSectioningModel.class); 046 private OverExpectedCriterion iOverExpectedCriterion; 047 048 public OnlineSectioningModel(DataProperties properties) { 049 super(properties); 050 try { 051 @SuppressWarnings("unchecked") 052 Class<OverExpectedCriterion> overExpectedCriterionClass = (Class<OverExpectedCriterion>) 053 Class.forName(properties.getProperty("OverExpectedCriterion.Class", AvoidUnbalancedWhenNoExpectations.class.getName())); 054 iOverExpectedCriterion = overExpectedCriterionClass.getConstructor(DataProperties.class).newInstance(properties); 055 } catch (Exception e) { 056 sLog.error("Unable to create custom over-expected criterion (" + e.getMessage() + "), using default.", e); 057 iOverExpectedCriterion = new PercentageOverExpected(properties); 058 } 059 } 060 061 public OnlineSectioningModel(DataProperties config, OverExpectedCriterion criterion) { 062 super(config); 063 iOverExpectedCriterion = criterion; 064 } 065 066 /** 067 * Get over-expected criterion 068 * @return over-expected criterion 069 */ 070 public OverExpectedCriterion getOverExpectedCriterion() { return iOverExpectedCriterion; } 071 072 /** 073 * Set over-expected criterion 074 * @param overExpectedCriterion over-expected criterion 075 */ 076 public void setOverExpectedCriterion(OverExpectedCriterion overExpectedCriterion) { iOverExpectedCriterion = overExpectedCriterion; } 077 078 /** 079 * Expectation penalty, to be minimized (computed using {@link OverExpectedCriterion#getOverExpected(Assignment, Section, Request)}) 080 * @param assignment current assignment 081 * @param section section in question 082 * @param request student course request 083 * @return expectation penalty (typically 1.0 / number of subparts when over-expected, 0.0 otherwise) 084 */ 085 public double getOverExpected(Assignment<Request, Enrollment> assignment, Section section, Request request) { 086 return getOverExpectedCriterion().getOverExpected(assignment, section, request); 087 } 088 089 /** 090 * Expectation penalty, to be minimized 091 * @param assignment current assignment 092 * @param enrollment current enrollment of the student 093 * @param index only use enrollments 0 .. index - 1 from the assignment array 094 * @param section section in question 095 * @param request student course request 096 * @return expectation penalty (typically 1.0 / number of subparts when over-expected, 0.0 otherwise) 097 */ 098 public double getOverExpected(Assignment<Request, Enrollment> assignment, Enrollment[] enrollment, int index, Section section, Request request) { 099 if (getOverExpectedCriterion() instanceof OverExpectedCriterion.HasContext) 100 return ((OverExpectedCriterion.HasContext)getOverExpectedCriterion()).getOverExpected(assignment, enrollment, index, section, request); 101 else 102 return getOverExpectedCriterion().getOverExpected(assignment, section, request); 103 } 104 105 /** 106 * Expectation penalty, to be minimized. 107 * A variant of the {@link OverExpectedCriterion#getOverExpected(Assignment, Section, Request)} method that can be called from {@link Constraint#computeConflicts(Assignment, Value, Set)}. 108 * @param assignment current assignment 109 * @param selection selected enrollment question 110 * @param value an enrollment to be assigned 111 * @param conflicts enrollments that have been already identified as conflicting 112 * @return expectation penalty (typically 1.0 / number of subparts when over-expected, 0.0 otherwise) 113 */ 114 public double getOverExpected(Assignment<Request, Enrollment> assignment, Enrollment selection, Enrollment value, Set<Enrollment> conflicts) { 115 if (getOverExpectedCriterion() instanceof OverExpectedCriterion.HasContext) 116 return ((OverExpectedCriterion.HasContext)getOverExpectedCriterion()).getOverExpected(assignment, selection, value, conflicts); 117 else { 118 if (selection == null || !selection.isCourseRequest()) return 0.0; 119 double penalty = 0.0; 120 for (Section section: selection.getSections()) 121 penalty += getOverExpectedCriterion().getOverExpected(assignment, section, selection.getRequest()); 122 return penalty; 123 } 124 } 125 126}