001package org.cpsolver.instructor.constraints; 002 003import java.util.ArrayList; 004import java.util.List; 005import java.util.Set; 006 007import org.cpsolver.ifs.assignment.Assignment; 008import org.cpsolver.ifs.model.GlobalConstraint; 009import org.cpsolver.ifs.util.ToolBox; 010import org.cpsolver.instructor.model.Instructor.Context; 011import org.cpsolver.instructor.model.TeachingAssignment; 012import org.cpsolver.instructor.model.TeachingRequest; 013 014/** 015 * Instructor Constraint. This is the main constraint of the problem, ensuring that an instructor gets a consistent list of 016 * assignments. It checks for instructor availability, maximal load, time conflicts, and whether the given assignments are of the same 017 * course (if desired). 018 * 019 * @version IFS 1.3 (Instructor Sectioning)<br> 020 * Copyright (C) 2016 Tomáš Müller<br> 021 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 022 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 023 * <br> 024 * This library is free software; you can redistribute it and/or modify 025 * it under the terms of the GNU Lesser General Public License as 026 * published by the Free Software Foundation; either version 3 of the 027 * License, or (at your option) any later version. <br> 028 * <br> 029 * This library is distributed in the hope that it will be useful, but 030 * WITHOUT ANY WARRANTY; without even the implied warranty of 031 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 032 * Lesser General Public License for more details. <br> 033 * <br> 034 * You should have received a copy of the GNU Lesser General Public 035 * License along with this library; if not see 036 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 037 */ 038public class InstructorConstraint extends GlobalConstraint<TeachingRequest.Variable, TeachingAssignment> { 039 040 /** 041 * Constructor 042 */ 043 public InstructorConstraint() {} 044 045 @Override 046 public void computeConflicts(Assignment<TeachingRequest.Variable, TeachingAssignment> assignment, TeachingAssignment value, Set<TeachingAssignment> conflicts) { 047 Context context = value.getInstructor().getContext(assignment); 048 049 // Check availability 050 if (context.getInstructor().getTimePreference(value.variable().getRequest()).isProhibited()) { 051 conflicts.add(value); 052 return; 053 } 054 055 // Check for overlaps 056 for (TeachingAssignment ta : context.getAssignments()) { 057 if (ta.variable().equals(value.variable()) || conflicts.contains(ta)) 058 continue; 059 060 if (ta.variable().getRequest().overlaps(value.variable().getRequest())) 061 conflicts.add(ta); 062 } 063 064 // Same course and/or common 065 for (TeachingAssignment ta : context.getAssignments()) { 066 if (ta.variable().equals(value.variable()) || conflicts.contains(ta)) 067 continue; 068 if (ta.variable().getRequest().isSameCourseViolated(value.variable().getRequest()) || ta.variable().getRequest().isSameCommonViolated(value.variable().getRequest())) 069 conflicts.add(ta); 070 } 071 072 // Check load 073 float load = value.variable().getRequest().getLoad(); 074 List<TeachingAssignment> adepts = new ArrayList<TeachingAssignment>(); 075 for (TeachingAssignment ta : context.getAssignments()) { 076 if (ta.variable().equals(value.variable()) || conflicts.contains(ta)) 077 continue; 078 079 adepts.add(ta); 080 load += ta.variable().getRequest().getLoad(); 081 } 082 while (load > context.getInstructor().getMaxLoad()) { 083 if (adepts.isEmpty()) { 084 conflicts.add(value); 085 break; 086 } 087 TeachingAssignment conflict = ToolBox.random(adepts); 088 load -= conflict.variable().getRequest().getLoad(); 089 adepts.remove(conflict); 090 conflicts.add(conflict); 091 } 092 } 093 094 @Override 095 public String getName() { 096 return "Instructor Constraint"; 097 } 098 099 @Override 100 public String toString() { 101 return getName(); 102 } 103}