001package org.cpsolver.coursett.criteria.additional; 002 003import java.util.Collection; 004import java.util.Map; 005 006import org.cpsolver.coursett.constraint.JenrlConstraint; 007import org.cpsolver.coursett.criteria.StudentConflict; 008import org.cpsolver.coursett.model.Lecture; 009import org.cpsolver.coursett.model.Placement; 010import org.cpsolver.coursett.model.Student; 011import org.cpsolver.ifs.assignment.Assignment; 012import org.cpsolver.ifs.criteria.Criterion; 013import org.cpsolver.ifs.util.DataProperties; 014 015 016/** 017 * Instructor student conflicts. This criterion penalizes cases when an instructor (of a class) is attending some 018 * other class as a student and there is a conflict between the two classes. 019 * <br> 020 * To enable instructor student conflicts, set solver parameter Global.LoadStudentInstructorConflicts to true. Also 021 * student course requests should be used in this case (to be able to match an instructor external id to a student 022 * external id). 023 * <br> 024 * Instructor student conflicts are weighted by Comparator.InstructorStudentConflictWeight. 025 * 026 * <br> 027 * 028 * @author Tomáš Müller 029 * @version CourseTT 1.3 (University Course Timetabling)<br> 030 * Copyright (C) 2006 - 2014 Tomáš Müller<br> 031 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 032 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 033 * <br> 034 * This library is free software; you can redistribute it and/or modify 035 * it under the terms of the GNU Lesser General Public License as 036 * published by the Free Software Foundation; either version 3 of the 037 * License, or (at your option) any later version. <br> 038 * <br> 039 * This library is distributed in the hope that it will be useful, but 040 * WITHOUT ANY WARRANTY; without even the implied warranty of 041 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 042 * Lesser General Public License for more details. <br> 043 * <br> 044 * You should have received a copy of the GNU Lesser General Public 045 * License along with this library; if not see 046 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 047 */ 048public class InstructorStudentConflict extends StudentConflict { 049 050 /** 051 * Only count students that are instructors assigned to one of the two classes and enrolled in the other. 052 */ 053 @Override 054 protected double jointEnrollment(JenrlConstraint jenrl) { 055 double ret = 0.0; 056 for (Student student: jenrl.getInstructors()) 057 ret += student.getJenrlWeight(jenrl.first(), jenrl.second()); 058 return ret; 059 } 060 061 @Override 062 public boolean isApplicable(Lecture l1, Lecture l2) { 063 return l1 != null && l2 != null && !ignore(l1, l2) && applicable(l1, l2) && instructor(l1, l2); 064 } 065 066 /** 067 * True if there is at least one student teaching one of the two classes and enrolled in the other. 068 * @param l1 first lecture 069 * @param l2 second lecture 070 * @return true if there is at least one student of one class teaching the other class 071 */ 072 public boolean instructor(Lecture l1, Lecture l2) { 073 JenrlConstraint jenrl = (l1 == null || l2 == null ? null : l1.jenrlConstraint(l2)); 074 if (jenrl == null) return false; 075 return jenrl.getNrInstructors() > 0; 076 } 077 078 @Override 079 public void incJenrl(Assignment<Lecture, Placement> assignment, JenrlConstraint jenrl, double studentWeight, Double conflictPriority, Student student) { 080 if (isApplicable(jenrl.first(), jenrl.second()) && inConflict(assignment.getValue(jenrl.first()), assignment.getValue(jenrl.second())) && student.getInstructor() != null 081 && (student.getInstructor().variables().contains(jenrl.first()) || student.getInstructor().variables().contains(jenrl.second()))) 082 inc(assignment, studentWeight); 083 } 084 085 @Override 086 public double getWeightDefault(DataProperties config) { 087 return config.getPropertyDouble("Comparator.InstructorStudentConflictWeight", 10.0 * config.getPropertyDouble("Comparator.StudentConflictWeight", 1.0)); 088 } 089 090 @Override 091 public String getPlacementSelectionWeightName() { 092 return "Placement.NrInstructorStudConfsWeight"; 093 } 094 095 @Override 096 public void getInfo(Assignment<Lecture, Placement> assignment, Map<String, String> info) { 097 super.getInfo(assignment, info); 098 double conf = getValue(assignment); 099 if (conf > 0.0) { 100 Criterion<Lecture, Placement> c = getModel().getCriterion(InstructorStudentHardConflict.class); 101 double hard = (c == null ? 0.0 : c.getValue(assignment)); 102 info.put("Instructor student conflicts", sDoubleFormat.format(conf) + (hard > 0.0 ? " [hard: " + sDoubleFormat.format(hard) + "]" : "")); 103 } 104 } 105 106 @Override 107 public void getInfo(Assignment<Lecture, Placement> assignment, Map<String, String> info, Collection<Lecture> variables) { 108 super.getInfo(assignment, info, variables); 109 double conf = getValue(assignment, variables); 110 if (conf > 0.0) { 111 Criterion<Lecture, Placement> c = getModel().getCriterion(InstructorStudentHardConflict.class); 112 double hard = (c == null ? 0.0 : c.getValue(assignment, variables)); 113 info.put("Instructor student conflicts", sDoubleFormat.format(conf) + (hard > 0.0 ? " [hard: " + sDoubleFormat.format(hard) + "]" : "")); 114 } 115 } 116 117}