001package org.cpsolver.studentsct.weights; 002 003import java.text.DecimalFormat; 004import java.util.ArrayList; 005import java.util.BitSet; 006import java.util.HashSet; 007import java.util.Set; 008 009import org.cpsolver.coursett.model.Placement; 010import org.cpsolver.coursett.model.RoomLocation; 011import org.cpsolver.coursett.model.TimeLocation; 012import org.cpsolver.ifs.assignment.Assignment; 013import org.cpsolver.ifs.assignment.DefaultSingleAssignment; 014import org.cpsolver.ifs.solution.Solution; 015import org.cpsolver.ifs.util.DataProperties; 016import org.cpsolver.ifs.util.ToolBox; 017import org.cpsolver.studentsct.extension.DistanceConflict; 018import org.cpsolver.studentsct.extension.TimeOverlapsCounter; 019import org.cpsolver.studentsct.model.Choice; 020import org.cpsolver.studentsct.model.Config; 021import org.cpsolver.studentsct.model.Course; 022import org.cpsolver.studentsct.model.CourseRequest; 023import org.cpsolver.studentsct.model.Enrollment; 024import org.cpsolver.studentsct.model.Instructor; 025import org.cpsolver.studentsct.model.Offering; 026import org.cpsolver.studentsct.model.Request; 027import org.cpsolver.studentsct.model.RequestGroup; 028import org.cpsolver.studentsct.model.SctAssignment; 029import org.cpsolver.studentsct.model.Section; 030import org.cpsolver.studentsct.model.Student; 031import org.cpsolver.studentsct.model.Subpart; 032 033 034/** 035 * New weighting model. It tries to obey the following principles: 036 * <ul> 037 * <li> Total student weight is between zero and one (one means student got the best schedule) 038 * <li> Weight of the given priority course is higher than sum of the remaining weights the student can get 039 * <li> First alternative is better than the following course 040 * <li> Second alternative is better than the second following course 041 * <li> Distance conflicts are considered secondary (priorities should be maximized first) 042 * <li> If alternative sections are otherwise equal, use the better balanced one 043 * </ul> 044 * 045 * @version StudentSct 1.3 (Student Sectioning)<br> 046 * Copyright (C) 2007 - 2014 Tomas Muller<br> 047 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 048 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 049 * <br> 050 * This library is free software; you can redistribute it and/or modify 051 * it under the terms of the GNU Lesser General Public License as 052 * published by the Free Software Foundation; either version 3 of the 053 * License, or (at your option) any later version. <br> 054 * <br> 055 * This library is distributed in the hope that it will be useful, but 056 * WITHOUT ANY WARRANTY; without even the implied warranty of 057 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 058 * Lesser General Public License for more details. <br> 059 * <br> 060 * You should have received a copy of the GNU Lesser General Public 061 * License along with this library; if not see 062 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 063 */ 064 065public class PriorityStudentWeights implements StudentWeights { 066 protected double iPriorityFactor = 0.5010; 067 protected double iFirstAlternativeFactor = 0.5010; 068 protected double iSecondAlternativeFactor = 0.2510; 069 protected double iDistanceConflict = 0.0100; 070 protected double iTimeOverlapFactor = 0.5000; 071 protected double iTimeOverlapMaxLimit = 0.5000; 072 protected boolean iLeftoverSpread = false; 073 protected double iBalancingFactor = 0.0050; 074 protected double iAlternativeRequestFactor = 0.1260; 075 protected double iProjectedStudentWeight = 0.0100; 076 protected boolean iMPP = false; 077 protected double iPerturbationFactor = 0.100; 078 protected double iSelectionFactor = 0.100; 079 protected double iSameChoiceWeight = 0.900; 080 protected double iSameTimeWeight = 0.700; 081 protected double iSameConfigWeight = 0.500; 082 protected double iGroupFactor = 0.100; 083 protected double iGroupBestRatio = 0.95; 084 protected double iGroupFillRatio = 0.05; 085 086 public PriorityStudentWeights(DataProperties config) { 087 iPriorityFactor = config.getPropertyDouble("StudentWeights.Priority", iPriorityFactor); 088 iFirstAlternativeFactor = config.getPropertyDouble("StudentWeights.FirstAlternative", iFirstAlternativeFactor); 089 iSecondAlternativeFactor = config.getPropertyDouble("StudentWeights.SecondAlternative", iSecondAlternativeFactor); 090 iDistanceConflict = config.getPropertyDouble("StudentWeights.DistanceConflict", iDistanceConflict); 091 iTimeOverlapFactor = config.getPropertyDouble("StudentWeights.TimeOverlapFactor", iTimeOverlapFactor); 092 iTimeOverlapMaxLimit = config.getPropertyDouble("StudentWeights.TimeOverlapMaxLimit", iTimeOverlapMaxLimit); 093 iLeftoverSpread = config.getPropertyBoolean("StudentWeights.LeftoverSpread", iLeftoverSpread); 094 iBalancingFactor = config.getPropertyDouble("StudentWeights.BalancingFactor", iBalancingFactor); 095 iAlternativeRequestFactor = config.getPropertyDouble("StudentWeights.AlternativeRequestFactor", iAlternativeRequestFactor); 096 iProjectedStudentWeight = config.getPropertyDouble("StudentWeights.ProjectedStudentWeight", iProjectedStudentWeight); 097 iMPP = config.getPropertyBoolean("General.MPP", false); 098 iPerturbationFactor = config.getPropertyDouble("StudentWeights.Perturbation", iPerturbationFactor); 099 iSelectionFactor = config.getPropertyDouble("StudentWeights.Selection", iSelectionFactor); 100 iSameChoiceWeight = config.getPropertyDouble("StudentWeights.SameChoice", iSameChoiceWeight); 101 iSameTimeWeight = config.getPropertyDouble("StudentWeights.SameTime", iSameTimeWeight); 102 iSameConfigWeight = config.getPropertyDouble("StudentWeights.SameConfig", iSameConfigWeight); 103 iGroupFactor = config.getPropertyDouble("StudentWeights.SameGroup", iGroupFactor); 104 iGroupBestRatio = config.getPropertyDouble("StudentWeights.GroupBestRatio", iGroupBestRatio); 105 iGroupFillRatio = config.getPropertyDouble("StudentWeights.GroupFillRatio", iGroupFillRatio); 106 } 107 108 public double getWeight(Request request) { 109 if (request.getStudent().isDummy() && iProjectedStudentWeight >= 0.0) { 110 double weight = iProjectedStudentWeight; 111 if (request.isAlternative()) 112 weight *= iAlternativeRequestFactor; 113 return weight; 114 } 115 double total = 10000.0; 116 int nrReq = request.getStudent().nrRequests(); 117 double remain = (iLeftoverSpread ? Math.floor(10000.0 * Math.pow(iPriorityFactor, nrReq) / nrReq) : 0.0); 118 for (int idx = 0; idx < request.getStudent().getRequests().size(); idx++) { 119 Request r = request.getStudent().getRequests().get(idx); 120 boolean last = (idx + 1 == request.getStudent().getRequests().size()); 121 boolean lastNotAlt = !r.isAlternative() && (last || request.getStudent().getRequests().get(1 + idx).isAlternative()); 122 double w = Math.ceil(iPriorityFactor * total) + remain; 123 if (lastNotAlt || last) { 124 w = total; 125 } else { 126 total -= w; 127 } 128 if (r.equals(request)) { 129 return w / 10000.0; 130 } 131 } 132 return 0.0; 133 } 134 135 public double getCachedWeight(Request request) { 136 Double w = (Double)request.getExtra(); 137 if (w == null) { 138 w = getWeight(request); 139 request.setExtra(w); 140 } 141 return w; 142 } 143 144 /** 145 * Return how much the given enrollment is different from the initial enrollment 146 * @param enrollment given enrollment 147 * @return 0.0 when all the sections are the same, 1.0 when all the section are different (including different times) 148 */ 149 protected double getDifference(Enrollment enrollment) { 150 if (enrollment.getStudent().isDummy()) return 1.0; 151 Enrollment other = enrollment.getRequest().getInitialAssignment(); 152 if (other != null) { 153 double similarSections = 0.0; 154 if (enrollment.getConfig().equals(other.getConfig())) { 155 // same configurations -- compare sections of matching subpart 156 for (Section section: enrollment.getSections()) { 157 for (Section initial: other.getSections()) { 158 if (section.getSubpart().equals(initial.getSubpart())) { 159 if (section.equals(initial)) { 160 similarSections += 1.0; 161 } else if (section.sameChoice(initial)) { 162 similarSections += iSameChoiceWeight; 163 } else if (section.sameTime(initial)) { 164 similarSections += iSameTimeWeight; 165 } 166 break; 167 } 168 } 169 } 170 } else { 171 // different configurations -- compare sections of matching itype 172 for (Section section: enrollment.getSections()) { 173 for (Section initial: other.getSections()) { 174 if (section.sameChoice(initial)) { 175 similarSections += iSameChoiceWeight; 176 break; 177 } else if (section.sameInstructionalType(initial) && section.sameTime(initial)) { 178 similarSections += iSameTimeWeight; 179 break; 180 } 181 } 182 } 183 } 184 return 1.0 - similarSections / enrollment.getAssignments().size(); 185 } 186 return 1.0; 187 } 188 189 /** 190 * Return how much the given enrollment is different from the selection (if any) 191 * @param enrollment given enrollment 192 * @return 0.0 when all the sections are the same, 1.0 when all the section are different (including different times) 193 */ 194 public double getSelection(Enrollment enrollment) { 195 if (enrollment.getStudent().isDummy()) return 1.0; 196 if (enrollment.isCourseRequest()) { 197 CourseRequest cr = (CourseRequest)enrollment.getRequest(); 198 if (!cr.getSelectedChoices().isEmpty()) { 199 double similarSections = 0.0; 200 for (Section section: enrollment.getSections()) { 201 double bestChoice = 0.0; 202 for (Choice ch: cr.getSelectedChoices()) { 203 if (bestChoice < 1.0 && ch.sameSection(section)) { 204 bestChoice = 1.0; 205 } else if (bestChoice < iSameChoiceWeight && ch.sameChoice(section)) { 206 bestChoice = iSameChoiceWeight; 207 } else if (bestChoice < iSameTimeWeight && ch.sameInstructionalType(section) && ch.sameTime(section)) { 208 bestChoice = iSameTimeWeight; 209 } else if (bestChoice < iSameConfigWeight && ch.sameConfiguration(section)) { 210 bestChoice = iSameConfigWeight; 211 } 212 } 213 similarSections += bestChoice; 214 } 215 return 1.0 - similarSections / enrollment.getAssignments().size(); 216 } else { 217 return 1.0; 218 } 219 } else { 220 return 1.0; 221 } 222 } 223 224 225 @Override 226 public double getBound(Request request) { 227 return getCachedWeight(request); 228 } 229 230 protected double round(double value) { 231 return Math.ceil(10000.0 * value) / 10000.0; 232 } 233 234 @Override 235 public double getWeight(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 236 double weight = getCachedWeight(enrollment.getRequest()); 237 switch (enrollment.getPriority()) { 238 case 1: weight *= iFirstAlternativeFactor; break; 239 case 2: weight *= iSecondAlternativeFactor; break; 240 } 241 if (enrollment.isCourseRequest() && iBalancingFactor != 0.0) { 242 double configUsed = enrollment.getConfig().getEnrollmentWeight(assignment, enrollment.getRequest()) + enrollment.getRequest().getWeight(); 243 double disbalanced = 0; 244 double total = 0; 245 for (Section section: enrollment.getSections()) { 246 Subpart subpart = section.getSubpart(); 247 if (subpart.getSections().size() <= 1) continue; 248 double used = section.getEnrollmentWeight(assignment, enrollment.getRequest()) + enrollment.getRequest().getWeight(); 249 // sections have limits -> desired size is section limit x (total enrollment / total limit) 250 // unlimited sections -> desired size is total enrollment / number of sections 251 double desired = (subpart.getLimit() > 0 252 ? section.getLimit() * (configUsed / subpart.getLimit()) 253 : configUsed / subpart.getSections().size()); 254 if (used > desired) 255 disbalanced += Math.min(enrollment.getRequest().getWeight(), used - desired) / enrollment.getRequest().getWeight(); 256 else 257 disbalanced -= Math.min(enrollment.getRequest().getWeight(), desired - used) / enrollment.getRequest().getWeight(); 258 total ++; 259 } 260 if (disbalanced > 0) 261 weight *= (1.0 - disbalanced / total * iBalancingFactor); 262 } 263 if (iMPP) { 264 double difference = getDifference(enrollment); 265 if (difference > 0.0) 266 weight *= (1.0 - difference * iPerturbationFactor); 267 } 268 if (iSelectionFactor != 0.0) { 269 double selection = getSelection(enrollment); 270 if (selection > 0.0) 271 weight *= (1.0 - selection * iSelectionFactor); 272 } 273 if (enrollment.isCourseRequest() && iGroupFactor != 0.0) { 274 double sameGroup = 0.0; int groupCount = 0; 275 for (RequestGroup g: ((CourseRequest)enrollment.getRequest()).getRequestGroups()) { 276 if (g.getCourse().equals(enrollment.getCourse())) { 277 sameGroup += g.getEnrollmentSpread(assignment, enrollment, iGroupBestRatio, iGroupFillRatio); 278 groupCount ++; 279 } 280 } 281 if (groupCount > 0) { 282 double difference = 1.0 - sameGroup / groupCount; 283 weight *= (1.0 - difference * iGroupFactor); 284 } 285 } 286 return round(weight); 287 } 288 289 @Override 290 public double getDistanceConflictWeight(Assignment<Request, Enrollment> assignment, DistanceConflict.Conflict c) { 291 if (c.getR1().getPriority() < c.getR2().getPriority()) { 292 return round(getWeight(assignment, c.getE2()) * iDistanceConflict); 293 } else { 294 return round(getWeight(assignment, c.getE1()) * iDistanceConflict); 295 } 296 } 297 298 @Override 299 public double getTimeOverlapConflictWeight(Assignment<Request, Enrollment> assignment, Enrollment e, TimeOverlapsCounter.Conflict c) { 300 double toc = Math.min(iTimeOverlapMaxLimit * c.getShare() / e.getNrSlots(), iTimeOverlapMaxLimit); 301 return round(getWeight(assignment, e) * toc); 302 } 303 304 @Override 305 public double getWeight(Assignment<Request, Enrollment> assignment, Enrollment enrollment, Set<DistanceConflict.Conflict> distanceConflicts, Set<TimeOverlapsCounter.Conflict> timeOverlappingConflicts) { 306 double base = getWeight(assignment, enrollment); 307 double dc = 0.0; 308 if (distanceConflicts != null) { 309 for (DistanceConflict.Conflict c: distanceConflicts) { 310 Enrollment other = (c.getE1().equals(enrollment) ? c.getE2() : c.getE1()); 311 if (other.getRequest().getPriority() <= enrollment.getRequest().getPriority()) 312 dc += base * iDistanceConflict; 313 else 314 dc += getWeight(assignment, other) * iDistanceConflict; 315 } 316 } 317 double toc = 0.0; 318 if (timeOverlappingConflicts != null) { 319 for (TimeOverlapsCounter.Conflict c: timeOverlappingConflicts) { 320 toc += base * Math.min(iTimeOverlapFactor * c.getShare() / enrollment.getNrSlots(), iTimeOverlapMaxLimit); 321 Enrollment other = (c.getE1().equals(enrollment) ? c.getE2() : c.getE1()); 322 toc += getWeight(assignment, other) * Math.min(iTimeOverlapFactor * c.getShare() / other.getNrSlots(), iTimeOverlapMaxLimit); 323 } 324 } 325 return round(base - dc - toc); 326 } 327 328 329 @Override 330 public boolean isBetterThanBestSolution(Solution<Request, Enrollment> currentSolution) { 331 return currentSolution.getBestInfo() == null || currentSolution.getModel().getTotalValue(currentSolution.getAssignment()) < currentSolution.getBestValue(); 332 } 333 334 @Override 335 public boolean isFreeTimeAllowOverlaps() { 336 return false; 337 } 338 339 /** 340 * Test case -- run to see the weights for a few courses 341 * @param args program arguments 342 */ 343 public static void main(String[] args) { 344 PriorityStudentWeights pw = new PriorityStudentWeights(new DataProperties()); 345 DecimalFormat df = new DecimalFormat("0.0000"); 346 Student s = new Student(0l); 347 new CourseRequest(1l, 0, false, s, ToolBox.toList( 348 new Course(1, "A", "1", new Offering(0, "A")), 349 new Course(1, "A", "2", new Offering(0, "A")), 350 new Course(1, "A", "3", new Offering(0, "A"))), false, null); 351 new CourseRequest(2l, 1, false, s, ToolBox.toList( 352 new Course(1, "B", "1", new Offering(0, "B")), 353 new Course(1, "B", "2", new Offering(0, "B")), 354 new Course(1, "B", "3", new Offering(0, "B"))), false, null); 355 new CourseRequest(3l, 2, false, s, ToolBox.toList( 356 new Course(1, "C", "1", new Offering(0, "C")), 357 new Course(1, "C", "2", new Offering(0, "C")), 358 new Course(1, "C", "3", new Offering(0, "C"))), false, null); 359 new CourseRequest(4l, 3, false, s, ToolBox.toList( 360 new Course(1, "D", "1", new Offering(0, "D")), 361 new Course(1, "D", "2", new Offering(0, "D")), 362 new Course(1, "D", "3", new Offering(0, "D"))), false, null); 363 new CourseRequest(5l, 4, false, s, ToolBox.toList( 364 new Course(1, "E", "1", new Offering(0, "E")), 365 new Course(1, "E", "2", new Offering(0, "E")), 366 new Course(1, "E", "3", new Offering(0, "E"))), false, null); 367 new CourseRequest(6l, 5, true, s, ToolBox.toList( 368 new Course(1, "F", "1", new Offering(0, "F")), 369 new Course(1, "F", "2", new Offering(0, "F")), 370 new Course(1, "F", "3", new Offering(0, "F"))), false, null); 371 new CourseRequest(7l, 6, true, s, ToolBox.toList( 372 new Course(1, "G", "1", new Offering(0, "G")), 373 new Course(1, "G", "2", new Offering(0, "G")), 374 new Course(1, "G", "3", new Offering(0, "G"))), false, null); 375 376 Assignment<Request, Enrollment> assignment = new DefaultSingleAssignment<Request, Enrollment>(); 377 Placement p = new Placement(null, new TimeLocation(1, 90, 12, 0, 0, null, null, new BitSet(), 10), new ArrayList<RoomLocation>()); 378 for (Request r: s.getRequests()) { 379 CourseRequest cr = (CourseRequest)r; 380 double[] w = new double[] {0.0, 0.0, 0.0}; 381 for (int i = 0; i < cr.getCourses().size(); i++) { 382 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 383 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 384 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 385 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 386 w[i] = pw.getWeight(assignment, e, null, null); 387 } 388 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 389 } 390 391 System.out.println("With one distance conflict:"); 392 for (Request r: s.getRequests()) { 393 CourseRequest cr = (CourseRequest)r; 394 double[] w = new double[] {0.0, 0.0, 0.0}; 395 for (int i = 0; i < cr.getCourses().size(); i++) { 396 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 397 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 398 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 399 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 400 Set<DistanceConflict.Conflict> dc = new HashSet<DistanceConflict.Conflict>(); 401 dc.add(new DistanceConflict.Conflict(s, e, (Section)sections.iterator().next(), e, (Section)sections.iterator().next())); 402 w[i] = pw.getWeight(assignment, e, dc, null); 403 } 404 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 405 } 406 407 System.out.println("With two distance conflicts:"); 408 for (Request r: s.getRequests()) { 409 CourseRequest cr = (CourseRequest)r; 410 double[] w = new double[] {0.0, 0.0, 0.0}; 411 for (int i = 0; i < cr.getCourses().size(); i++) { 412 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 413 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 414 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 415 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 416 Set<DistanceConflict.Conflict> dc = new HashSet<DistanceConflict.Conflict>(); 417 dc.add(new DistanceConflict.Conflict(s, e, (Section)sections.iterator().next(), e, (Section)sections.iterator().next())); 418 dc.add(new DistanceConflict.Conflict(s, e, (Section)sections.iterator().next(), e, 419 new Section(1, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null))); 420 w[i] = pw.getWeight(assignment, e, dc, null); 421 } 422 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 423 } 424 425 System.out.println("With 25% time overlapping conflict:"); 426 for (Request r: s.getRequests()) { 427 CourseRequest cr = (CourseRequest)r; 428 double[] w = new double[] {0.0, 0.0, 0.0}; 429 for (int i = 0; i < cr.getCourses().size(); i++) { 430 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 431 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 432 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 433 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 434 Set<TimeOverlapsCounter.Conflict> toc = new HashSet<TimeOverlapsCounter.Conflict>(); 435 toc.add(new TimeOverlapsCounter.Conflict(s, 3, e, sections.iterator().next(), e, sections.iterator().next())); 436 w[i] = pw.getWeight(assignment, e, null, toc); 437 } 438 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 439 } 440 441 System.out.println("Disbalanced sections (by 2 / 10 students):"); 442 for (Request r: s.getRequests()) { 443 CourseRequest cr = (CourseRequest)r; 444 double[] w = new double[] {0.0, 0.0, 0.0}; 445 for (int i = 0; i < cr.getCourses().size(); i++) { 446 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 447 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 448 Subpart x = new Subpart(0, "Lec", "Lec", cfg, null); 449 Section a = new Section(0, 10, "x", x, p, null); 450 new Section(1, 10, "y", x, p, null); 451 sections.add(a); 452 a.assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 453 a.assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 454 cfg.getContext(assignment).assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 455 cfg.getContext(assignment).assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 456 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 457 w[i] = pw.getWeight(assignment, e, null, null); 458 } 459 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 460 } 461 462 System.out.println("Same choice sections:"); 463 pw.iMPP = true; 464 for (Request r: s.getRequests()) { 465 CourseRequest cr = (CourseRequest)r; 466 double[] w = new double[] {0.0, 0.0, 0.0}; 467 for (int i = 0; i < cr.getCourses().size(); i++) { 468 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 469 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 470 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 471 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 472 Set<SctAssignment> other = new HashSet<SctAssignment>(); 473 other.add(new Section(1, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 474 cr.setInitialAssignment(new Enrollment(cr, i, cfg, other, assignment)); 475 w[i] = pw.getWeight(assignment, e, null, null); 476 } 477 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 478 } 479 480 System.out.println("Same time sections:"); 481 for (Request r: s.getRequests()) { 482 CourseRequest cr = (CourseRequest)r; 483 double[] w = new double[] {0.0, 0.0, 0.0}; 484 for (int i = 0; i < cr.getCourses().size(); i++) { 485 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 486 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 487 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 488 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 489 Set<SctAssignment> other = new HashSet<SctAssignment>(); 490 other.add(new Section(1, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null, new Instructor(1l, null, "Josef Novak", null))); 491 cr.setInitialAssignment(new Enrollment(cr, i, cfg, other, assignment)); 492 w[i] = pw.getWeight(assignment, e, null, null); 493 } 494 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 495 } 496 497 System.out.println("Different time sections:"); 498 Placement q = new Placement(null, new TimeLocation(1, 102, 12, 0, 0, null, null, new BitSet(), 10), new ArrayList<RoomLocation>()); 499 for (Request r: s.getRequests()) { 500 CourseRequest cr = (CourseRequest)r; 501 double[] w = new double[] {0.0, 0.0, 0.0}; 502 for (int i = 0; i < cr.getCourses().size(); i++) { 503 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 504 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 505 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 506 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 507 Set<SctAssignment> other = new HashSet<SctAssignment>(); 508 other.add(new Section(1, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), q, null)); 509 cr.setInitialAssignment(new Enrollment(cr, i, cfg, other, assignment)); 510 w[i] = pw.getWeight(assignment, e, null, null); 511 } 512 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 513 } 514 515 System.out.println("Two sections, one same choice, one same time:"); 516 for (Request r: s.getRequests()) { 517 CourseRequest cr = (CourseRequest)r; 518 double[] w = new double[] {0.0, 0.0, 0.0}; 519 for (int i = 0; i < cr.getCourses().size(); i++) { 520 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 521 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 522 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 523 sections.add(new Section(1, 1, "y", new Subpart(1, "Rec", "Rec", cfg, null), p, null)); 524 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 525 Set<SctAssignment> other = new HashSet<SctAssignment>(); 526 other.add(new Section(2, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 527 other.add(new Section(3, 1, "y", new Subpart(1, "Rec", "Rec", cfg, null), p, null, new Instructor(1l, null, "Josef Novak", null))); 528 cr.setInitialAssignment(new Enrollment(cr, i, cfg, other, assignment)); 529 w[i] = pw.getWeight(assignment, e, null, null); 530 } 531 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 532 } 533 534 } 535}