001package net.sf.cpsolver.ifs.example.tt;
002
003import net.sf.cpsolver.ifs.model.Value;
004
005/**
006 * Location (value, i.e., a single placement of the activity). Location encodes
007 * a slot and a selection of resources.
008 * 
009 * @version IFS 1.2 (Iterative Forward Search)<br>
010 *          Copyright (C) 2006 - 2010 Tomáš Müller<br>
011 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
012 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
013 * <br>
014 *          This library is free software; you can redistribute it and/or modify
015 *          it under the terms of the GNU Lesser General Public License as
016 *          published by the Free Software Foundation; either version 3 of the
017 *          License, or (at your option) any later version. <br>
018 * <br>
019 *          This library is distributed in the hope that it will be useful, but
020 *          WITHOUT ANY WARRANTY; without even the implied warranty of
021 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
022 *          Lesser General Public License for more details. <br>
023 * <br>
024 *          You should have received a copy of the GNU Lesser General Public
025 *          License along with this library; if not see
026 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
027 */
028public class Location extends Value<Activity, Location> {
029    private int iSlot;
030    private Resource[] iResources;
031    private int iNrOfDiscouragedSlots = -1;
032
033    /**
034     * Constructor.
035     * 
036     * @param activity
037     *            parent activity
038     * @param slot
039     *            starting time
040     * @param resources
041     *            selection of resources
042     */
043    public Location(Activity activity, int slot, Resource[] resources) {
044        super(activity);
045        iSlot = slot;
046        iResources = resources;
047        iNrOfDiscouragedSlots = computeNrOfDiscouragedSlots();
048    }
049
050    /**
051     * Constructor. slot = nrHours * day + hour
052     * 
053     * @param activity
054     *            parent activity
055     * @param day
056     *            day
057     * @param hour
058     *            starting hour
059     * @param resources
060     *            required resources
061     */
062    public Location(Activity activity, int day, int hour, Resource[] resources) {
063        super(activity);
064        iSlot = ((TimetableModel) activity.getModel()).getNrHours() * day + hour;
065        iResources = resources;
066        iNrOfDiscouragedSlots = computeNrOfDiscouragedSlots();
067    }
068
069    /** Gets slot */
070    public int getSlot() {
071        return iSlot;
072    }
073
074    /** Gets selection of resources */
075    public Resource[] getResources() {
076        return iResources;
077    }
078
079    /** Gets given resource */
080    public Resource getResource(int idx) {
081        return iResources[idx];
082    }
083
084    /** Returns true if the given resource is used by this location */
085    public boolean containResource(Resource resource) {
086        for (int i = 0; i < iResources.length; i++)
087            if (iResources[i].equals(resource))
088                return true;
089        return false;
090    }
091
092    /** Number of slots (over all resources) which are discouraged */
093    public int getNrOfDiscouragedSlots() {
094        return iNrOfDiscouragedSlots;
095    }
096
097    /** Int value (for optimization) -- getNrOfDiscouragedSlots() is returned */
098    @Override
099    public double toDouble() {
100        return iNrOfDiscouragedSlots;
101    }
102
103    /**
104     * Computes number of discouraged slots (over all resources and the
105     * activity)
106     */
107    public int computeNrOfDiscouragedSlots() {
108        Activity a = variable();
109        int ret = 0;
110        for (int i = getSlot(); i < getSlot() + a.getLength(); i++) {
111            if (a.isDiscouragedSlot(i))
112                ret++;
113            for (int j = 0; j < getResources().length; j++)
114                if (getResource(j).isDiscouragedSlot(i))
115                    ret++;
116        }
117        return ret;
118    }
119
120    /**
121     * Returns true if the location intersects with another location. This means
122     * the same resource is used in the same time.
123     */
124    public boolean hasIntersection(Location location) {
125        int s1 = getSlot();
126        int l1 = variable().getLength();
127        int s2 = location.getSlot();
128        int l2 = location.variable().getLength();
129        return !(s1 + l1 <= s2 || s2 + l2 <= s1);
130    }
131
132    /**
133     * Returns true if the location is prohibited. This means that the activity
134     * or a required resource has a time slot which is used by this location
135     * prohibited.
136     */
137    public boolean isProhibited() {
138        Activity a = variable();
139        for (int i = getSlot(); i < getSlot() + a.getLength(); i++) {
140            if (a.isProhibitedSlot(i))
141                return true;
142            for (int j = 0; j < getResources().length; j++)
143                if (getResource(j).isProhibitedSlot(i))
144                    return true;
145        }
146        return false;
147    }
148
149    @Override
150    public String getName() {
151        StringBuffer sb = new StringBuffer(getSlot() + "/");
152        for (int i = 0; i < iResources.length; i++) {
153            if (i > 0)
154                sb.append(",");
155            sb.append(iResources[i].getName());
156        }
157        return sb.toString();
158    }
159}