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