001 package ifs.example.rpp;
002
003 import ifs.model.*;
004 import ifs.util.*;
005 import java.util.*;
006
007 /**
008 * Resource constraint (rectangular area where the rectangles are to be placed). It prohibits overlapping of the placed rectangles.
009 *
010 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
011 * @version 1.0
012 */
013 public class ResourceConstraint extends Constraint {
014 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(ResourceConstraint.class);
015 private Variable[][] iResource;
016 private int iWidth, iHeight;
017
018 /**
019 * Constructor.
020 * @param width area width
021 * @param height area height
022 */
023 public ResourceConstraint(int width, int height) {
024 super();
025 iWidth = width;
026 iHeight = height;
027 iResource = new Variable[width][height];
028 for (int x = 0; x < width; x++)
029 for (int y = 0; y < height; y++)
030 iResource[x][y] = null;
031 }
032
033 /**
034 * Compute conflicts with the given placement of the rectangle.
035 * This means the rectangles which are already placed and which are overlapping with the given assignment.
036 */
037 public void computeConflicts(Value value, Set conflicts) {
038 Rectangle rectangle = (Rectangle)value.variable();
039 Location placement = (Location)value;
040 for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
041 for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++)
042 if (iResource[x][y] != null)
043 conflicts.add(iResource[x][y].getAssignment());
044 }
045
046 /**
047 * Returns true if there is a rectangle which overlaps with the given assignment.
048 */
049 public boolean inConflict(Value value) {
050 Rectangle rectangle = (Rectangle)value.variable();
051 Location placement = (Location)value;
052 for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
053 for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++)
054 if (iResource[x][y] != null)
055 return true;
056 return false;
057 }
058
059 /**
060 * Returns true if the given rectangles (assignments) do not overlap.
061 */
062 public boolean isConsistent(Value value1, Value value2) {
063 Rectangle r1 = (Rectangle)value1.variable();
064 Location p1 = (Location)value1;
065 Rectangle r2 = (Rectangle)value2.variable();
066 Location p2 = (Location)value2;
067 if (p2.getX() + r2.getWidth() <= p1.getX()) return true;
068 if (p2.getX() >= p1.getX() + r1.getWidth()) return true;
069 if (p2.getY() + r2.getHeight() <= p1.getY()) return true;
070 if (p2.getY() >= p1.getY() + r1.getHeight()) return true;
071 return false;
072 }
073
074 /**
075 * Notification, when a rectangle is placed.
076 * It memorizes the rectangle's new position in 2D ([0..width][0..height]) array.
077 * It is used for faster lookup when computing conflicts.
078 */
079 public void assigned(long iteration, Value value) {
080 super.assigned(iteration, value);
081 Rectangle rectangle = (Rectangle)value.variable();
082 Location placement = (Location)value;
083 for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
084 for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++) {
085 iResource[x][y] = value.variable();
086 }
087 }
088
089 /**
090 * Notification, when a rectangle is unplaced.
091 * It removes the rectangle from the 2D ([0..width][0..height]) array.
092 */
093 public void unassigned(long iteration, Value value) {
094 super.unassigned(iteration, value);
095 Rectangle rectangle = (Rectangle)value.variable();
096 Location placement = (Location)value;
097 for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
098 for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++) {
099 iResource[x][y] = null;
100 }
101 }
102
103 public void check() {
104 sLogger.debug("check");
105 for (Enumeration e=variables().elements();e.hasMoreElements();) {
106 Rectangle rectangle = (Rectangle)e.nextElement();
107 Location placement = (Location)rectangle.getAssignment();
108 if (placement==null) {
109 sLogger.warn("Rectangle "+rectangle.getName()+" is not assigned.");
110 continue;
111 }
112 sLogger.debug("Checking "+rectangle.getName()+" (assigned:"+placement.getName()+", prohibited:"+rectangle.isProhibited(placement.getX(),placement.getY())+", initial:"+rectangle.getInitialAssignment()+", prohibited:["+rectangle.getProhibitedX()+","+rectangle.getProhibitedY()+"])");
113 if (placement.getX()==rectangle.getProhibitedX() || placement.getY()==rectangle.getProhibitedY())
114 sLogger.error("Placement is prohibited.");
115 if (placement.getX()<rectangle.getMinX() || placement.getX()>rectangle.getMaxX() ||
116 placement.getY()<rectangle.getMinY() || placement.getY()>rectangle.getMaxY())
117 sLogger.error("Placement is outside bounds.");
118 for (int x = placement.getX(); x < Math.min(iWidth, placement.getX() + rectangle.getWidth()); x++)
119 for (int y = placement.getY(); y < Math.min(iHeight, placement.getY() + rectangle.getHeight()); y++) {
120 if (iResource[x][y]==null || !iResource[x][y].equals(rectangle))
121 sLogger.error("Problem at ["+x+","+y+"], "+iResource[x][y]+" is assigned there.");
122 }
123 }
124 sLogger.debug(toString());
125 }
126
127 /**
128 * String representation of the constraint (for debugging and printing purposes).
129 */
130 public String toString() {
131 StringBuffer sb = new StringBuffer("ResourceConstraint{\n ");
132 for (int y = 0; y < iHeight; y++) {
133 for (int x = 0; x < iWidth; x++) {
134 sb.append(ToolBox.trim( iResource[x][y] == null ? "" : ((Rectangle)iResource[x][y]).getName().substring(4), 4));
135 }
136 sb.append("\n ");
137 }
138 sb.append("\n }");
139 return sb.toString();
140 }
141 }