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 iShortDistanceConflict = 0.1000; 071 protected double iTimeOverlapFactor = 0.5000; 072 protected double iTimeOverlapMaxLimit = 0.5000; 073 protected boolean iLeftoverSpread = false; 074 protected double iBalancingFactor = 0.0050; 075 protected double iNoTimeFactor = 0.0100; 076 protected double iAlternativeRequestFactor = 0.1260; 077 protected double iProjectedStudentWeight = 0.0100; 078 protected boolean iMPP = false; 079 protected double iPerturbationFactor = 0.100; 080 protected double iSelectionFactor = 0.100; 081 protected double iSameChoiceWeight = 0.900; 082 protected double iSameTimeWeight = 0.700; 083 protected double iSameConfigWeight = 0.500; 084 protected double iGroupFactor = 0.100; 085 protected double iGroupBestRatio = 0.95; 086 protected double iGroupFillRatio = 0.05; 087 088 public PriorityStudentWeights(DataProperties config) { 089 iPriorityFactor = config.getPropertyDouble("StudentWeights.Priority", iPriorityFactor); 090 iFirstAlternativeFactor = config.getPropertyDouble("StudentWeights.FirstAlternative", iFirstAlternativeFactor); 091 iSecondAlternativeFactor = config.getPropertyDouble("StudentWeights.SecondAlternative", iSecondAlternativeFactor); 092 iDistanceConflict = config.getPropertyDouble("StudentWeights.DistanceConflict", iDistanceConflict); 093 iShortDistanceConflict = config.getPropertyDouble("StudentWeights.ShortDistanceConflict", iShortDistanceConflict); 094 iTimeOverlapFactor = config.getPropertyDouble("StudentWeights.TimeOverlapFactor", iTimeOverlapFactor); 095 iTimeOverlapMaxLimit = config.getPropertyDouble("StudentWeights.TimeOverlapMaxLimit", iTimeOverlapMaxLimit); 096 iLeftoverSpread = config.getPropertyBoolean("StudentWeights.LeftoverSpread", iLeftoverSpread); 097 iBalancingFactor = config.getPropertyDouble("StudentWeights.BalancingFactor", iBalancingFactor); 098 iAlternativeRequestFactor = config.getPropertyDouble("StudentWeights.AlternativeRequestFactor", iAlternativeRequestFactor); 099 iProjectedStudentWeight = config.getPropertyDouble("StudentWeights.ProjectedStudentWeight", iProjectedStudentWeight); 100 iMPP = config.getPropertyBoolean("General.MPP", false); 101 iPerturbationFactor = config.getPropertyDouble("StudentWeights.Perturbation", iPerturbationFactor); 102 iSelectionFactor = config.getPropertyDouble("StudentWeights.Selection", iSelectionFactor); 103 iSameChoiceWeight = config.getPropertyDouble("StudentWeights.SameChoice", iSameChoiceWeight); 104 iSameTimeWeight = config.getPropertyDouble("StudentWeights.SameTime", iSameTimeWeight); 105 iSameConfigWeight = config.getPropertyDouble("StudentWeights.SameConfig", iSameConfigWeight); 106 iGroupFactor = config.getPropertyDouble("StudentWeights.SameGroup", iGroupFactor); 107 iGroupBestRatio = config.getPropertyDouble("StudentWeights.GroupBestRatio", iGroupBestRatio); 108 iGroupFillRatio = config.getPropertyDouble("StudentWeights.GroupFillRatio", iGroupFillRatio); 109 iNoTimeFactor = config.getPropertyDouble("StudentWeights.NoTimeFactor", iNoTimeFactor); 110 } 111 112 public double getWeight(Request request) { 113 if (request.getStudent().isDummy() && iProjectedStudentWeight >= 0.0) { 114 double weight = iProjectedStudentWeight; 115 if (request.isAlternative()) 116 weight *= iAlternativeRequestFactor; 117 return weight; 118 } 119 double total = 10000.0; 120 int nrReq = request.getStudent().nrRequests(); 121 double remain = (iLeftoverSpread ? Math.floor(10000.0 * Math.pow(iPriorityFactor, nrReq) / nrReq) : 0.0); 122 for (int idx = 0; idx < request.getStudent().getRequests().size(); idx++) { 123 Request r = request.getStudent().getRequests().get(idx); 124 boolean last = (idx + 1 == request.getStudent().getRequests().size()); 125 boolean lastNotAlt = !r.isAlternative() && (last || request.getStudent().getRequests().get(1 + idx).isAlternative()); 126 double w = Math.ceil(iPriorityFactor * total) + remain; 127 if (lastNotAlt || last) { 128 w = total; 129 } else { 130 total -= w; 131 } 132 if (r.equals(request)) { 133 return w / 10000.0; 134 } 135 } 136 return 0.0; 137 } 138 139 public double getCachedWeight(Request request) { 140 Double w = (Double)request.getExtra(); 141 if (w == null) { 142 w = getWeight(request); 143 request.setExtra(w); 144 } 145 return w; 146 } 147 148 /** 149 * Return how much the given enrollment is different from the initial enrollment 150 * @param enrollment given enrollment 151 * @return 0.0 when all the sections are the same, 1.0 when all the section are different (including different times) 152 */ 153 protected double getDifference(Enrollment enrollment) { 154 if (enrollment.getStudent().isDummy()) return 1.0; 155 Enrollment other = enrollment.getRequest().getInitialAssignment(); 156 if (other != null) { 157 double similarSections = 0.0; 158 if (enrollment.getConfig().equals(other.getConfig())) { 159 // same configurations -- compare sections of matching subpart 160 for (Section section: enrollment.getSections()) { 161 for (Section initial: other.getSections()) { 162 if (section.getSubpart().equals(initial.getSubpart())) { 163 if (section.equals(initial)) { 164 similarSections += 1.0; 165 } else if (section.sameChoice(initial)) { 166 similarSections += iSameChoiceWeight; 167 } else if (section.sameTime(initial)) { 168 similarSections += iSameTimeWeight; 169 } 170 break; 171 } 172 } 173 } 174 } else { 175 // different configurations -- compare sections of matching itype 176 for (Section section: enrollment.getSections()) { 177 for (Section initial: other.getSections()) { 178 if (section.sameChoice(initial)) { 179 similarSections += iSameChoiceWeight; 180 break; 181 } else if (section.sameInstructionalType(initial) && section.sameTime(initial)) { 182 similarSections += iSameTimeWeight; 183 break; 184 } 185 } 186 } 187 } 188 return 1.0 - similarSections / enrollment.getAssignments().size(); 189 } 190 return 1.0; 191 } 192 193 /** 194 * Return how much the given enrollment is different from the selection (if any) 195 * @param enrollment given enrollment 196 * @return 0.0 when all the sections are the same, 1.0 when all the section are different (including different times) 197 */ 198 public double getSelection(Enrollment enrollment) { 199 if (enrollment.getStudent().isDummy()) return 1.0; 200 if (enrollment.isCourseRequest()) { 201 CourseRequest cr = (CourseRequest)enrollment.getRequest(); 202 if (!cr.getSelectedChoices().isEmpty()) { 203 double similarSections = 0.0; 204 for (Section section: enrollment.getSections()) { 205 double bestChoice = 0.0; 206 for (Choice ch: cr.getSelectedChoices()) { 207 if (bestChoice < 1.0 && ch.sameSection(section)) { 208 bestChoice = 1.0; 209 } else if (bestChoice < iSameChoiceWeight && ch.sameChoice(section)) { 210 bestChoice = iSameChoiceWeight; 211 } else if (bestChoice < iSameTimeWeight && ch.sameInstructionalType(section) && ch.sameTime(section)) { 212 bestChoice = iSameTimeWeight; 213 } else if (bestChoice < iSameConfigWeight && ch.sameConfiguration(section)) { 214 bestChoice = iSameConfigWeight; 215 } 216 } 217 similarSections += bestChoice; 218 } 219 return 1.0 - similarSections / enrollment.getAssignments().size(); 220 } else { 221 return 1.0; 222 } 223 } else { 224 return 1.0; 225 } 226 } 227 228 229 @Override 230 public double getBound(Request request) { 231 return getCachedWeight(request); 232 } 233 234 protected double round(double value) { 235 return Math.ceil(10000.0 * value) / 10000.0; 236 } 237 238 @Override 239 public double getWeight(Assignment<Request, Enrollment> assignment, Enrollment enrollment) { 240 double weight = getCachedWeight(enrollment.getRequest()); 241 switch (enrollment.getPriority()) { 242 case 0: break; 243 case 1: weight *= iFirstAlternativeFactor; break; 244 case 2: weight *= iSecondAlternativeFactor; break; 245 default: 246 weight *= Math.pow(iFirstAlternativeFactor, enrollment.getPriority()); 247 } 248 if (enrollment.isCourseRequest() && iNoTimeFactor != 0.0) { 249 int noTimeSections = 0, total = 0; 250 for (Section section: enrollment.getSections()) { 251 if (section.getTime() == null) noTimeSections ++; 252 total ++; 253 } 254 if (noTimeSections > 0) 255 weight *= (1.0 - iNoTimeFactor * noTimeSections / total); 256 } 257 if (enrollment.isCourseRequest() && iBalancingFactor != 0.0) { 258 double configUsed = enrollment.getConfig().getEnrollmentTotalWeight(assignment, enrollment.getRequest()) + enrollment.getRequest().getWeight(); 259 double disbalanced = 0; 260 double total = 0; 261 for (Section section: enrollment.getSections()) { 262 Subpart subpart = section.getSubpart(); 263 if (subpart.getSections().size() <= 1) continue; 264 double used = section.getEnrollmentTotalWeight(assignment, enrollment.getRequest()) + enrollment.getRequest().getWeight(); 265 // sections have limits -> desired size is section limit x (total enrollment / total limit) 266 // unlimited sections -> desired size is total enrollment / number of sections 267 double desired = (subpart.getLimit() > 0 268 ? section.getLimit() * (configUsed / subpart.getLimit()) 269 : configUsed / subpart.getSections().size()); 270 if (used > desired) 271 disbalanced += Math.min(enrollment.getRequest().getWeight(), used - desired) / enrollment.getRequest().getWeight(); 272 else 273 disbalanced -= Math.min(enrollment.getRequest().getWeight(), desired - used) / enrollment.getRequest().getWeight(); 274 total ++; 275 } 276 if (disbalanced > 0) 277 weight *= (1.0 - disbalanced / total * iBalancingFactor); 278 } 279 if (iMPP) { 280 double difference = getDifference(enrollment); 281 if (difference > 0.0) 282 weight *= (1.0 - difference * iPerturbationFactor); 283 } 284 if (iSelectionFactor != 0.0) { 285 double selection = getSelection(enrollment); 286 if (selection > 0.0) 287 weight *= (1.0 - selection * iSelectionFactor); 288 } 289 if (enrollment.isCourseRequest() && iGroupFactor != 0.0) { 290 double sameGroup = 0.0; int groupCount = 0; 291 for (RequestGroup g: ((CourseRequest)enrollment.getRequest()).getRequestGroups()) { 292 if (g.getCourse().equals(enrollment.getCourse())) { 293 sameGroup += g.getEnrollmentSpread(assignment, enrollment, iGroupBestRatio, iGroupFillRatio); 294 groupCount ++; 295 } 296 } 297 if (groupCount > 0) { 298 double difference = 1.0 - sameGroup / groupCount; 299 weight *= (1.0 - difference * iGroupFactor); 300 } 301 } 302 return round(weight); 303 } 304 305 @Override 306 public double getDistanceConflictWeight(Assignment<Request, Enrollment> assignment, DistanceConflict.Conflict c) { 307 if (c.getR1().getPriority() < c.getR2().getPriority()) { 308 return round(getWeight(assignment, c.getE2()) * (c.getStudent().isNeedShortDistances() ? iShortDistanceConflict : iDistanceConflict)); 309 } else { 310 return round(getWeight(assignment, c.getE1()) * (c.getStudent().isNeedShortDistances() ? iShortDistanceConflict : iDistanceConflict)); 311 } 312 } 313 314 @Override 315 public double getTimeOverlapConflictWeight(Assignment<Request, Enrollment> assignment, Enrollment e, TimeOverlapsCounter.Conflict c) { 316 if (e == null || e.getRequest() == null) return 0.0; 317 double toc = Math.min(iTimeOverlapMaxLimit * c.getShare() / e.getNrSlots(), iTimeOverlapMaxLimit); 318 return round(getWeight(assignment, e) * toc); 319 } 320 321 @Override 322 public double getWeight(Assignment<Request, Enrollment> assignment, Enrollment enrollment, Set<DistanceConflict.Conflict> distanceConflicts, Set<TimeOverlapsCounter.Conflict> timeOverlappingConflicts) { 323 double base = getWeight(assignment, enrollment); 324 double dc = 0.0; 325 if (distanceConflicts != null) { 326 for (DistanceConflict.Conflict c: distanceConflicts) { 327 Enrollment other = (c.getE1().equals(enrollment) ? c.getE2() : c.getE1()); 328 if (other.getRequest().getPriority() <= enrollment.getRequest().getPriority()) 329 dc += base * (c.getStudent().isNeedShortDistances() ? iShortDistanceConflict : iDistanceConflict); 330 else 331 dc += getWeight(assignment, other) * (c.getStudent().isNeedShortDistances() ? iShortDistanceConflict : iDistanceConflict); 332 } 333 } 334 double toc = 0.0; 335 if (timeOverlappingConflicts != null) { 336 for (TimeOverlapsCounter.Conflict c: timeOverlappingConflicts) { 337 toc += base * Math.min(iTimeOverlapFactor * c.getShare() / enrollment.getNrSlots(), iTimeOverlapMaxLimit); 338 Enrollment other = (c.getE1().equals(enrollment) ? c.getE2() : c.getE1()); 339 if (other.getRequest() != null) 340 toc += getWeight(assignment, other) * Math.min(iTimeOverlapFactor * c.getShare() / other.getNrSlots(), iTimeOverlapMaxLimit); 341 } 342 } 343 return round(base - dc - toc); 344 } 345 346 347 @Override 348 public boolean isBetterThanBestSolution(Solution<Request, Enrollment> currentSolution) { 349 return currentSolution.getBestInfo() == null || currentSolution.getModel().getTotalValue(currentSolution.getAssignment()) < currentSolution.getBestValue(); 350 } 351 352 @Override 353 public boolean isFreeTimeAllowOverlaps() { 354 return false; 355 } 356 357 /** 358 * Test case -- run to see the weights for a few courses 359 * @param args program arguments 360 */ 361 public static void main(String[] args) { 362 PriorityStudentWeights pw = new PriorityStudentWeights(new DataProperties()); 363 DecimalFormat df = new DecimalFormat("0.0000"); 364 Student s = new Student(0l); 365 new CourseRequest(1l, 0, false, s, ToolBox.toList( 366 new Course(1, "A", "1", new Offering(0, "A")), 367 new Course(1, "A", "2", new Offering(0, "A")), 368 new Course(1, "A", "3", new Offering(0, "A"))), false, null); 369 new CourseRequest(2l, 1, false, s, ToolBox.toList( 370 new Course(1, "B", "1", new Offering(0, "B")), 371 new Course(1, "B", "2", new Offering(0, "B")), 372 new Course(1, "B", "3", new Offering(0, "B"))), false, null); 373 new CourseRequest(3l, 2, false, s, ToolBox.toList( 374 new Course(1, "C", "1", new Offering(0, "C")), 375 new Course(1, "C", "2", new Offering(0, "C")), 376 new Course(1, "C", "3", new Offering(0, "C"))), false, null); 377 new CourseRequest(4l, 3, false, s, ToolBox.toList( 378 new Course(1, "D", "1", new Offering(0, "D")), 379 new Course(1, "D", "2", new Offering(0, "D")), 380 new Course(1, "D", "3", new Offering(0, "D"))), false, null); 381 new CourseRequest(5l, 4, false, s, ToolBox.toList( 382 new Course(1, "E", "1", new Offering(0, "E")), 383 new Course(1, "E", "2", new Offering(0, "E")), 384 new Course(1, "E", "3", new Offering(0, "E"))), false, null); 385 new CourseRequest(6l, 5, true, s, ToolBox.toList( 386 new Course(1, "F", "1", new Offering(0, "F")), 387 new Course(1, "F", "2", new Offering(0, "F")), 388 new Course(1, "F", "3", new Offering(0, "F"))), false, null); 389 new CourseRequest(7l, 6, true, s, ToolBox.toList( 390 new Course(1, "G", "1", new Offering(0, "G")), 391 new Course(1, "G", "2", new Offering(0, "G")), 392 new Course(1, "G", "3", new Offering(0, "G"))), false, null); 393 394 Assignment<Request, Enrollment> assignment = new DefaultSingleAssignment<Request, Enrollment>(); 395 Placement p = new Placement(null, new TimeLocation(1, 90, 12, 0, 0, null, null, new BitSet(), 10), new ArrayList<RoomLocation>()); 396 for (Request r: s.getRequests()) { 397 CourseRequest cr = (CourseRequest)r; 398 double[] w = new double[] {0.0, 0.0, 0.0}; 399 for (int i = 0; i < cr.getCourses().size(); i++) { 400 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 401 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 402 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 403 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 404 w[i] = pw.getWeight(assignment, e, null, null); 405 } 406 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 407 } 408 409 System.out.println("With one distance conflict:"); 410 for (Request r: s.getRequests()) { 411 CourseRequest cr = (CourseRequest)r; 412 double[] w = new double[] {0.0, 0.0, 0.0}; 413 for (int i = 0; i < cr.getCourses().size(); i++) { 414 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 415 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 416 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 417 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 418 Set<DistanceConflict.Conflict> dc = new HashSet<DistanceConflict.Conflict>(); 419 dc.add(new DistanceConflict.Conflict(s, e, (Section)sections.iterator().next(), e, (Section)sections.iterator().next())); 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 two distance conflicts:"); 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<DistanceConflict.Conflict> dc = new HashSet<DistanceConflict.Conflict>(); 435 dc.add(new DistanceConflict.Conflict(s, e, (Section)sections.iterator().next(), e, (Section)sections.iterator().next())); 436 dc.add(new DistanceConflict.Conflict(s, e, (Section)sections.iterator().next(), e, 437 new Section(1, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null))); 438 w[i] = pw.getWeight(assignment, e, dc, null); 439 } 440 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 441 } 442 443 System.out.println("With 25% time overlapping conflict:"); 444 for (Request r: s.getRequests()) { 445 CourseRequest cr = (CourseRequest)r; 446 double[] w = new double[] {0.0, 0.0, 0.0}; 447 for (int i = 0; i < cr.getCourses().size(); i++) { 448 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 449 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 450 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 451 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 452 Set<TimeOverlapsCounter.Conflict> toc = new HashSet<TimeOverlapsCounter.Conflict>(); 453 toc.add(new TimeOverlapsCounter.Conflict(s, 3, e, sections.iterator().next(), e, sections.iterator().next())); 454 w[i] = pw.getWeight(assignment, e, null, toc); 455 } 456 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 457 } 458 459 System.out.println("Disbalanced sections (by 2 / 10 students):"); 460 for (Request r: s.getRequests()) { 461 CourseRequest cr = (CourseRequest)r; 462 double[] w = new double[] {0.0, 0.0, 0.0}; 463 for (int i = 0; i < cr.getCourses().size(); i++) { 464 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 465 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 466 Subpart x = new Subpart(0, "Lec", "Lec", cfg, null); 467 Section a = new Section(0, 10, "x", x, p, null); 468 new Section(1, 10, "y", x, p, null); 469 sections.add(a); 470 a.assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 471 a.assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 472 cfg.getContext(assignment).assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 473 cfg.getContext(assignment).assigned(assignment, new Enrollment(s.getRequests().get(0), i, cfg, sections, assignment)); 474 Enrollment e = new Enrollment(cr, i, cfg, sections, 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 choice sections:"); 481 pw.iMPP = true; 482 for (Request r: s.getRequests()) { 483 CourseRequest cr = (CourseRequest)r; 484 double[] w = new double[] {0.0, 0.0, 0.0}; 485 for (int i = 0; i < cr.getCourses().size(); i++) { 486 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 487 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 488 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 489 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 490 Set<SctAssignment> other = new HashSet<SctAssignment>(); 491 other.add(new Section(1, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 492 cr.setInitialAssignment(new Enrollment(cr, i, cfg, other, assignment)); 493 w[i] = pw.getWeight(assignment, e, null, null); 494 } 495 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 496 } 497 498 System.out.println("Same time sections:"); 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), p, null, new Instructor(1l, null, "Josef Novak", 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("Different time sections:"); 516 Placement q = new Placement(null, new TimeLocation(1, 102, 12, 0, 0, null, null, new BitSet(), 10), new ArrayList<RoomLocation>()); 517 for (Request r: s.getRequests()) { 518 CourseRequest cr = (CourseRequest)r; 519 double[] w = new double[] {0.0, 0.0, 0.0}; 520 for (int i = 0; i < cr.getCourses().size(); i++) { 521 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 522 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 523 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", 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(1, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), q, null)); 527 cr.setInitialAssignment(new Enrollment(cr, i, cfg, other, assignment)); 528 w[i] = pw.getWeight(assignment, e, null, null); 529 } 530 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 531 } 532 533 System.out.println("Two sections, one same choice, one same time:"); 534 for (Request r: s.getRequests()) { 535 CourseRequest cr = (CourseRequest)r; 536 double[] w = new double[] {0.0, 0.0, 0.0}; 537 for (int i = 0; i < cr.getCourses().size(); i++) { 538 Config cfg = new Config(0l, -1, "", cr.getCourses().get(i).getOffering()); 539 Set<SctAssignment> sections = new HashSet<SctAssignment>(); 540 sections.add(new Section(0, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 541 sections.add(new Section(1, 1, "y", new Subpart(1, "Rec", "Rec", cfg, null), p, null)); 542 Enrollment e = new Enrollment(cr, i, cfg, sections, assignment); 543 Set<SctAssignment> other = new HashSet<SctAssignment>(); 544 other.add(new Section(2, 1, "x", new Subpart(0, "Lec", "Lec", cfg, null), p, null)); 545 other.add(new Section(3, 1, "y", new Subpart(1, "Rec", "Rec", cfg, null), p, null, new Instructor(1l, null, "Josef Novak", null))); 546 cr.setInitialAssignment(new Enrollment(cr, i, cfg, other, assignment)); 547 w[i] = pw.getWeight(assignment, e, null, null); 548 } 549 System.out.println(cr + ": " + df.format(w[0]) + " " + df.format(w[1]) + " " + df.format(w[2])); 550 } 551 552 } 553}