    001    package ttsolver.constraint;
    002
    003    import ifs.model.*;
    004    import ifs.util.*;
    005    import java.util.*;
    006    import ttsolver.model.*;
    007
    008    /**
    009     * Join student enrollment constraint.
    010     * <br>
    011     * This constraint is placed between all pairs of classes where there is at least one student attending both classes.
    012     * It represents a number of student conflicts (number of joined enrollments), if the given two classes overlap in time.
    013     * <br>
    014     * Also, it dynamically maintains the counter of all student conflicts. It is a soft constraint.
    015     *
    016     *
    017     * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
    018     * @version 1.0
    019     */
    020
    021    public class JenrlConstraint extends BinaryConstraint {
    022        private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(JenrlConstraint.class);
    023        private Counter iGlobalViolations;
    024        private long iJenrl;
    025        private boolean iAdded = false;
    026
    027        /** Constructor
    028         * @param jenrl number of joined enrollments
    029         * @param globalViolations global counter of student conflicts
    030         */
    031        public JenrlConstraint(long jenrl, Counter globalViolations) {
    032            super();
    033            iJenrl = jenrl;
    034            iGlobalViolations = globalViolations;
    035        }
    036
    037        /** Set global counter of student conflicts */
    038        public void setViolatedCounter(Counter globalViolations) { iGlobalViolations = globalViolations; }
    039
    040        public void computeConflicts(Value value, Set conflicts) {
    041        }
    042
    043        public boolean inConflict(Value value) {
    044            return false;
    045        }
    046
    047        public boolean isConsistent(Value value1, Value value2) {
    048            return true;
    049        }
    050
    051        public void unassigned(long iteration, Value value) {
    052            super.unassigned(iteration, value);
    053            if (iAdded) {
    054                iGlobalViolations.dec(iJenrl);
    055                iAdded=false;
    056                ((Lecture)first()).removeActiveJenrl(this);
    057                ((Lecture)second()).removeActiveJenrl(this);
    058            }
    059        }
    060
    061        /** Returns true if the given placements are overlapping or they are back-to-back and too far for students.*/
    062       public static boolean isInConflict(Placement p1, Placement p2) {
    063           if (p1==null || p2==null) return false;
    064           TimeLocation t1=p1.getTimeLocation(), t2=p2.getTimeLocation();
    065           if (!t1.shareDays(t2)) return false;
    066           if (t1.shareHours(t2)) return true;
    067           //if (t1.hasIntersection(t2)) return true;
    068           //if (!Placement.shareDays(p1,p2)) return false;
    069           int s1 = t1.getStartSlot(), s2 = t2.getStartSlot();
    070           if (s1+t1.getNrHalfHoursPerMeeting()!=s2 &&
    071               s2+t2.getNrHalfHoursPerMeeting()!=s1) return false;
    072           double distance = Placement.getDistance(p1,p2);
    073           if (distance <= 67.0) return false;
    074           if (distance <= 100.0 && (
    075               (t1.getLength()==3 && s1+t1.getLength()==s2) ||
    076               (t2.getLength()==3 && s2+t2.getLength()==s1)))
    077               return false;
    078           return true;
    079       }
    080
    081       public void assigned(long iteration, Value value) {
    082           super.assigned(iteration, value);
    083           if (second()==null || first().getAssignment()==null || second().getAssignment()==null) return;
    084            //if (v1.getInitialAssignment()!=null && v2.getInitialAssignment()!=null && v1.getAssignment().equals(v1.getInitialAssignment()) && v2.getAssignment().equals(v2.getInitialAssignment())) return;
    085            if (isInConflict((Placement)first().getAssignment(),(Placement)second().getAssignment())) {
    086                iAdded=true;
    087                iGlobalViolations.inc(iJenrl);
    088                ((Lecture)first()).addActiveJenrl(this);
    089                ((Lecture)second()).addActiveJenrl(this);
    090            }
    091        }
    092
    093       /** Number of joined enrollments if the given value is assigned to the given variable */
    094        public long jenrl(Variable variable, Value value) {
    095            Lecture anotherLecture = (Lecture)(first().equals(variable)?second():first());
    096            if (anotherLecture.getAssignment()==null) return 0;
    097            Lecture lecture = (Lecture) variable;
    098            return (isInConflict((Placement)anotherLecture.getAssignment(),(Placement)value)?iJenrl:0);
    099        }
    100
    101        /** True if the given two lectures overlap in time */
    102        public boolean isInConflict() {
    103            return iAdded;
    104        }
    105
    106        /** True if the given two lectures overlap in time */
    107        public boolean isInConflictPrecise() {
    108            return isInConflict((Placement)first().getAssignment(),(Placement)second().getAssignment());
    109        }
    110
    111        /** Increment the number of joined enrollments (during student final sectioning) */
    112        public void incJenrl() {
    113            if (iJenrl==0) {
    114                ((Lecture)first()).addActiveJenrl(this);
    115                ((Lecture)second()).addActiveJenrl(this);
    116            }
    117            iJenrl++;
    118            if (iAdded) iGlobalViolations.inc(1);
    119        }
    120
    121        /** Decrement the number of joined enrollments (during student final sectioning) */
    122        public void decJenrl() {
    123            iJenrl--;
    124            if (iAdded) iGlobalViolations.dec(1);
    125            if (iJenrl==0) {
    126                ((Lecture)first()).removeActiveJenrl(this);
    127                ((Lecture)second()).removeActiveJenrl(this);
    128            }
    129        }
    130
    131        /** Number of joined enrollments (during student final sectioning) */
    132        public long getJenrl() { return iJenrl; }
    133        public boolean isHard() { return false; }
    134
    135        public String toString() {
    136            return "JENR{"+first().getName()+","+second().getName()+","+(iAdded?iJenrl:0)+"/"+iJenrl+"}";
    137        }
    138
    139    }