001package org.cpsolver.ifs.example.tt;
002
003import java.util.Set;
004
005import org.cpsolver.ifs.assignment.Assignment;
006import org.cpsolver.ifs.model.BinaryConstraint;
007
008
009/**
010 * Binary dependence between two activities.
011 * 
012 * @author  Tomáš Müller
013 * @version IFS 1.3 (Iterative Forward Search)<br>
014 *          Copyright (C) 2006 - 2014 Tomáš Müller<br>
015 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
016 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
017 * <br>
018 *          This library is free software; you can redistribute it and/or modify
019 *          it under the terms of the GNU Lesser General Public License as
020 *          published by the Free Software Foundation; either version 3 of the
021 *          License, or (at your option) any later version. <br>
022 * <br>
023 *          This library is distributed in the hope that it will be useful, but
024 *          WITHOUT ANY WARRANTY; without even the implied warranty of
025 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
026 *          Lesser General Public License for more details. <br>
027 * <br>
028 *          You should have received a copy of the GNU Lesser General Public
029 *          License along with this library; if not see
030 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
031 */
032public class Dependence extends BinaryConstraint<Activity, Location> {
033    public static final int TYPE_NO_DEPENDENCE = 0;
034    public static final int TYPE_BEFORE = 1;
035    public static final int TYPE_CLOSELY_BEFORE = 2;
036    public static final int TYPE_AFTER = 3;
037    public static final int TYPE_CLOSELY_AFTER = 4;
038    public static final int TYPE_CONCURRENCY = 5;
039    private int iType = TYPE_NO_DEPENDENCE;
040    private String iResourceId = null;
041
042    public Dependence(String id, int type) {
043        super();
044        iType = type;
045        iResourceId = id;
046    }
047
048    public int getType() {
049        return iType;
050    }
051
052    public String getResourceId() {
053        return iResourceId;
054    }
055
056    @Override
057    public void computeConflicts(Assignment<Activity, Location> assignment, Location location, Set<Location> conflicts) {
058        Activity activity = location.variable();
059        Activity another = another(activity);
060        Location anotherLocation = assignment.getValue(another);
061        if (anotherLocation == null)
062            return;
063        if (isFirst(activity)) {
064            if (!isConsistent(location.getSlot(), activity.getLength(), anotherLocation.getSlot(), another.getLength()))
065                conflicts.add(anotherLocation);
066        } else {
067            if (!isConsistent(anotherLocation.getSlot(), another.getLength(), location.getSlot(), activity.getLength()))
068                conflicts.add(anotherLocation);
069        }
070    }
071
072    public boolean isConsistent(int s1, int l1, int s2, int l2) {
073        switch (iType) {
074            case TYPE_BEFORE:
075                return s1 + l1 <= s2;
076            case TYPE_CLOSELY_BEFORE:
077                return s1 + l1 == s2;
078            case TYPE_AFTER:
079                return s2 + l2 <= s1;
080            case TYPE_CLOSELY_AFTER:
081                return s2 + l2 == s1;
082            case TYPE_CONCURRENCY:
083                return (s1 <= s2 && s2 + l2 <= s1 + l1) || (s2 <= s1 && s1 + l1 <= s2 + l2);
084            default:
085                return true;
086        }
087    }
088
089    @Override
090    public boolean inConflict(Assignment<Activity, Location> assignment, Location location) {
091        Activity activity = location.variable();
092        Activity another = another(activity);
093        Location anotherLocation = assignment.getValue(another);
094        if (anotherLocation == null)
095            return false;
096        if (isFirst(activity)) {
097            return !isConsistent(location.getSlot(), activity.getLength(), anotherLocation.getSlot(), another
098                    .getLength());
099        } else {
100            return !isConsistent(anotherLocation.getSlot(), another.getLength(), location.getSlot(), activity
101                    .getLength());
102        }
103    }
104
105    @Override
106    public boolean isConsistent(Location l1, Location l2) {
107        Activity a1 = l1.variable();
108        Activity a2 = l2.variable();
109        if (isFirst(a1)) {
110            return !isConsistent(l1.getSlot(), a1.getLength(), l2.getSlot(), a2.getLength());
111        } else {
112            return !isConsistent(l2.getSlot(), a2.getLength(), l1.getSlot(), a1.getLength());
113        }
114    }
115
116    @Override
117    public String getName() {
118        switch (iType) {
119            case TYPE_BEFORE:
120                return first().getName() + "<" + second().getName();
121            case TYPE_CLOSELY_BEFORE:
122                return first().getName() + "<|" + second().getName();
123            case TYPE_AFTER:
124                return first().getName() + ">" + second().getName();
125            case TYPE_CLOSELY_AFTER:
126                return first().getName() + "|>" + second().getName();
127            case TYPE_CONCURRENCY:
128                return first().getName() + "||" + second().getName();
129            default:
130                return first().getName() + "?" + second().getName();
131        }
132    }
133
134}