View Javadoc

1   package cz.cuni.amis.utils.astar;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Comparator;
6   import java.util.HashMap;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Set;
10  
11  /**
12   * This is Heap used by AStar algorithm.
13   * 
14   * Note that we assume that inserted Object has correctly implemented hashCode()
15   * and equals() function!
16   * 
17   * <p><p>
18   * Use amis-path-finding library instead, see svn://artemis.ms.mff.cuni.cz/pogamut/trunk/project/Utils/AmisPathFinding
19   */
20  @Deprecated
21  public class AStarHeap<NODE> implements Collection<NODE> {
22  	
23  	private NODE[] nodes;
24  	private int count;
25  	private int items;
26  	private HashMap<NODE, Integer> references;
27  	private Comparator<NODE> cmp;
28  	
29  	private void grow(){
30  		NODE[] tempNodes = (NODE[]) new Object[count*2];
31  		for (int i = 0; i <= items; ++i){
32  			tempNodes[i] = nodes[i];
33  		}
34  		nodes = tempNodes;
35  		count = count * 2;
36  	}
37  	
38  	private int left(int reference){
39  		return 2*reference;
40  	}
41  	
42  	private int right(int reference){
43  		return 2*reference+1;
44  	}
45  	
46  	private int upRef(int reference){
47  		return reference / 2;
48  	}
49  	
50  	private NODE getNode(int reference){
51  		while (reference >= count) 
52  			grow();		
53  		return nodes[reference];
54  	}
55  	
56  	private int downNode(int reference){
57  		NODE currentNode = getNode(reference);
58  		if (currentNode == null) {
59  			return reference;
60  		}
61  		NODE leftNode = null;
62  		NODE rightNode = null;
63  		int way = 0;
64  	
65  		while (true){
66  			way = 0;
67  			leftNode = getNode(left(reference));
68  			rightNode = getNode(right(reference));
69  		
70  			if ((leftNode == null) && (rightNode == null)){
71  				references.put(currentNode, reference);
72  				return reference;
73  			}
74  			if (rightNode == null) way = -1;
75  			else
76  				if (leftNode  == null) way = 1;
77  			if (way == 0) way = cmp.compare(leftNode, rightNode);
78  			
79  			if (way < 0){
80  				// we've got to ascend to the left
81  				if (cmp.compare(currentNode, leftNode) > 0){
82  					nodes[reference] = leftNode;
83  					references.put(leftNode, new Integer(reference));
84  					reference = left(reference);
85  					nodes[reference] = currentNode;					
86  				} else {
87  					references.put(currentNode, reference);				
88  					return reference;
89  				}				 
90  			} else {
91  				// we've got to ascend to the right
92  				if (cmp.compare(currentNode, rightNode) > 0){
93  					nodes[reference] = rightNode;
94  					references.put(rightNode, new Integer(reference));
95  					reference = right(reference);
96  					nodes[reference] = currentNode;					
97  					
98  				} else {
99  					references.put(currentNode, reference);				
100 					return reference;
101 				}				 
102 			}			
103 		}		
104 	}
105 	
106 	private int upNode(int reference){
107 		if (reference == 1) 
108 			return reference;
109 		NODE currentNode = getNode(reference);
110 		if (currentNode == null) 
111 			return reference;
112 		NODE upNode = null;
113 		while (reference > 1){
114 			upNode = getNode(upRef(reference));
115 			if (cmp.compare(currentNode, upNode) < 0){
116 				nodes[reference] = upNode;
117 				references.put(upNode, reference);				
118 				reference = upRef(reference);
119 			} else {
120 				break;
121 			}
122 		}
123 		nodes[reference] = currentNode;
124 		references.put(currentNode, reference);
125 		return reference;
126 	}
127 	
128 	private void initHeap(int capacity){
129 		if (capacity < 2) capacity = 2;
130 		nodes = (NODE[]) new Object[capacity];
131 		count = capacity;
132 		items = 0;
133 		references = new HashMap(capacity);
134 	}
135 	
136 	public AStarHeap(Comparator<NODE> comp, int capacity){
137 		initHeap(capacity);	
138 		cmp = comp;
139 	}
140 	
141 	public AStarHeap(Comparator<NODE> comp){
142 		initHeap(20);
143 		cmp = comp;
144 	}
145 	
146 	public NODE getMin(){
147 		return nodes[1]; // capacity is always >= 1
148 	}
149 	
150 	public boolean deleteMin(){
151 		if (items == 0) 
152 			return false;
153 		return remove(nodes[1], 1);
154 	}
155 	
156 	public boolean decreaseKey(NODE arg0){
157 		Integer reference = (Integer)references.get(arg0);
158 		if (reference == null){
159 			return add(arg0);
160 		}
161 		upNode(reference.intValue());
162 		return true;
163 	}
164 
165 	public boolean add(NODE arg0) {
166 		Integer reference = (Integer)references.get(arg0);
167 		if (reference == null){
168 			getNode(items+1); // ensure that capacity is sufficient
169 			nodes[items+1] = arg0;
170 			upNode(items+1);
171 			items = items + 1;
172 			return true;
173 		} else {
174 			int tempRef = upNode(reference.intValue());
175 			if (tempRef == reference.intValue()) 
176 				downNode(reference.intValue());
177 			return true;
178 		}		
179 	}
180 
181 	@Override
182 	public boolean addAll(Collection arg0) {
183 		Iterator<NODE> iter = arg0.iterator();
184 		while (iter.hasNext())
185 			add(iter.next());		
186 		return true;
187 	}
188 	
189 	public boolean addAll(NODE[] arg0){
190 		boolean ok = true;
191 		for (int i = 0; i < arg0.length; ++i){
192 			ok = this.add(arg0[i]) && ok;
193 		}
194 		return ok;
195 	}
196 
197 	public void clear() {
198 		for (int i = 0; i < count; ++i){
199 			nodes[i] = null;
200 			references.clear();
201 		}
202 	}
203 
204 	public boolean contains(Object arg0) {
205 		return references.containsKey(arg0);		
206 	}
207 
208 	public boolean containsAll(Collection arg0) {
209 		return references.containsKey(arg0);
210 	}
211 	
212 	public boolean containsAll(Object[] arg0) {
213 		for (int i = 0; i < arg0.length; ++i){
214 			if (!this.contains(arg0[i])) {
215 				return false;
216 			}
217 		}
218 		return true;
219 	}
220 
221 	public boolean isEmpty() {
222 		return references.isEmpty();
223 	}
224 
225 	public Iterator<NODE> iterator() {
226 		return new AStarHeapIterator<NODE>(nodes, items, this);
227 	}
228 	
229 	private boolean remove(NODE arg0, int reference){
230 		references.remove(arg0);
231 		if (items == 1){
232 			nodes[1] = null;
233 			items = 0;
234 			return true;
235 		}
236 		nodes[reference] = nodes[items];
237 		nodes[items] = null;
238 		items = items - 1;
239 		downNode(reference);	
240 		return true;
241 	}
242 
243 	public boolean remove(Object arg0) {
244 		Integer reference = (Integer)references.get(arg0);
245 		if (reference == null) 
246 			return false;
247 		return remove(reference.intValue());		
248 	}
249 
250 	public boolean removeAll(Collection arg0) {
251 		Iterator iter = arg0.iterator();
252 		while (iter.hasNext())
253 			remove(iter.next());
254 		return true;
255 	}
256 
257 	public boolean retainAll(Collection arg0) {
258 		Iterator iter = references.keySet().iterator();
259 		Object item; Integer reference;
260 		while (iter.hasNext()){
261 			item = iter.next();
262 			reference = (Integer)references.get(item);
263 			if (!arg0.contains(item)) remove((NODE) item, reference.intValue());
264 		}
265 		return true;
266 	}
267 
268 	public int size() {
269 		return items;
270 	}
271 	
272 	public boolean empty() {
273 		return items == 0;
274 	}
275 
276 	public Object[] toArray() {
277 		return references.keySet().toArray();
278 	}
279 
280 	public Object[] toArray(Object[] arg0) {
281 		return references.keySet().toArray(arg0);
282 	}
283 	
284 	public Set toSet(){
285 		return references.keySet();
286 	}
287 
288 	
289 // =======================
290 // MAIN METHOD - TEST ONLY
291 // =======================
292 	
293 	public static String mainToStr(Integer[] nums){
294 		if (nums.length == 0) return "";
295 		String str = nums[0].toString();
296 		for (int i = 1; i < nums.length; ++i){
297 			str += ", " + nums[i].toString();
298 		}
299 		return str;
300 	}
301 	
302 	public static boolean mainCheck(AStarHeap heap, Integer[] nums){
303 		System.out.println("Removing and checking " + mainToStr(nums));
304 		List heapInts = new ArrayList();
305 		List desiredInts = new ArrayList();
306 		for (int i = 0; i < nums.length; ++i){
307 			desiredInts.add(nums[i]);
308 			heapInts.add(heap.getMin());
309 			heap.deleteMin();
310 		}
311 		if ( heapInts.containsAll(desiredInts) ){
312 			System.out.println("OK");
313 			return true;
314 		} else {
315 			System.out.println("KO!");
316 			System.exit(1);
317 		}
318 		return false;
319 	}
320 	
321 	public static void mainAdd(AStarHeap heap, Integer[] nums){
322 		System.out.println("Adding: " + mainToStr(nums));
323 		for (int i = 0; i < nums.length; ++i){
324 			heap.add(nums[i]);
325 		}
326 	}
327 	
328 	public static void main(String[] args){
329 		/*
330 		AStarHeap heap = new AStarHeap(new Comparator(){
331                                                             public int compare(Object arg0, Object arg1) {
332                                                                     return (Integer)arg0 - (Integer)arg1;
333                                                             }
334                                                        },
335                                                        20
336                                                       );
337 		
338 		mainAdd(  heap, new Integer[]{10, 100, 1, 50, 5});
339 		mainCheck(heap, new Integer[]{1,5});
340 		mainCheck(heap, new Integer[]{10,50});
341 		mainAdd(  heap, new Integer[]{80, 60, 70});
342 		mainCheck(heap, new Integer[]{60, 70, 80, 100});
343 		mainAdd(  heap, new Integer[]{5,8,3,7,4,1,9});
344 		mainCheck(heap, new Integer[]{5,8,3,7,4,1,9});
345 		mainAdd(  heap, new Integer[]{2,7,3,5,6,4,9,1});
346 		mainCheck(heap, new Integer[]{1,2,3,4});
347 		mainAdd(  heap, new Integer[]{20,70,30,50,60,2,3,1,4});
348 		mainCheck(heap, new Integer[]{20,70,30,50,60,2,3,1,4,5,6,7,9});
349 		*/
350 	}
351 	
352 }