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