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