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