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