Passed
Push — master ( c71db0...37262d )
by Alessandro
05:46 queued 14s
created

expand(SearchSpaceNode,Flaw)   A

Complexity

Conditions 4

Size

Total Lines 62
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 18
dl 0
loc 62
rs 9.5
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
package it.cnr.istc.pst.platinum.ai.deliberative.solver;
2
3
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.List;
6
7
import it.cnr.istc.pst.platinum.ai.deliberative.heuristic.FlawSelectionHeuristic;
8
import it.cnr.istc.pst.platinum.ai.deliberative.strategy.SearchStrategy;
9
import it.cnr.istc.pst.platinum.ai.framework.domain.component.PlanDataBase;
10
import it.cnr.istc.pst.platinum.ai.framework.microkernel.FrameworkObject;
11
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.deliberative.FlawSelectionHeuristicPlaceholder;
12
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.deliberative.SearchStrategyPlaceholder;
13
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.framework.PlanDataBasePlaceholder;
14
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.lifecycle.PostConstruct;
15
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.NoSolutionFoundException;
16
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.OperatorPropagationException;
17
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.PlanRefinementException;
18
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.flaw.Flaw;
19
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.flaw.FlawSolution;
20
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.plan.Plan;
21
import it.cnr.istc.pst.platinum.ai.framework.microkernel.resolver.ex.UnsolvableFlawException;
22
23
/**
24
 * 
25
 * @author anacleto
26
 *
27
 */
28
public abstract class Solver extends FrameworkObject 
29
{
30
	@PlanDataBasePlaceholder
31
	protected PlanDataBase pdb;
32
	
33
	@SearchStrategyPlaceholder
34
	protected SearchStrategy fringe;
35
	
36
	@FlawSelectionHeuristicPlaceholder
37
	protected FlawSelectionHeuristic heuristic;
38
	
39
	protected long timeout;
40
	protected long time;
41
	protected long stepCounter;
42
	protected String label;
43
	
44
	/**
45
	 * 
46
	 * @param label
47
	 * @param timeout
48
	 */
49
	protected Solver(String label, long timeout) {
50
		super();
51
		this.label = label;
52
		this.timeout = timeout;
53
	}
54
	
55
	/**
56
	 * 
57
	 */
58
	@PostConstruct
59
	protected void init() {
60
		// create the root node
61
		SearchSpaceNode root = new SearchSpaceNode();
62
		// set initial partial plan
63
		root.setPartialPlan(this.pdb.getPlan());
64
		// check flaws
65
		for (Flaw f : this.pdb.checkFlaws()) {
66
			root.addCheckedFlaw(f);
67
		}
68
		
69
		// enqueue the root node
70
		this.fringe.enqueue(root);
71
	}
72
	
73
	/**
74
	 * 
75
	 * @return
76
	 * @throws NoSolutionFoundException
77
	 */
78
	public abstract SearchSpaceNode solve() 
79
			throws NoSolutionFoundException;
80
81
	/**
82
	 * 
83
	 */
84
	public abstract void clear();
85
	
86
	/**
87
	 * 
88
	 * @return
89
	 */
90
	protected SearchSpaceNode createSearchSpaceNode() {
91
		return new SearchSpaceNode();
92
	}
93
	
94
	/**
95
	 * 
96
	 * @return
97
	 */
98
	public String getLabel() {
99
		return label;
100
	}
101
	
102
	/**
103
	 * 
104
	 * @param node
105
	 */
106
	protected void backtrack(SearchSpaceNode node) 
107
	{
108
		// list of operators that have been applied to generate the node
109
		List<Operator> operators = node.getOperators();
110
		// retract operators starting from the more recent ones
111
		Collections.reverse(operators);
112
		// retract all operators
113
		for (Operator operator : operators) {
114
			// retract operator
115
			this.pdb.retract(operator);
116
		}
117
	}
118
	
119
	/**
120
	 * 
121
	 * @param node
122
	 * @throws OperatorPropagationException
123
	 */
124
	protected void propagate(SearchSpaceNode node) 
125
			throws PlanRefinementException 
126
	{
127
		// get the list of applied operators
128
		List<Operator> operators = node.getOperators();
129
		// list of committed operators
130
		List<Operator> committed = new ArrayList<>();
131
		try 
132
		{
133
			// propagate operators in chronological order
134
			for (Operator operator : operators) {
135
				// propagate operator
136
				this.pdb.propagate(operator);
137
				// add committed operator
138
				committed.add(operator);
139
			}
140
		}
141
		catch (OperatorPropagationException ex) {
142
			// retract committed operators in reverse order
143
			Collections.reverse(committed);
144
			for (Operator operator : committed) {
145
				this.pdb.retract(operator);
146
			}
147
148
			// throw exception
149
			throw new PlanRefinementException("Error while propagating node:\n" + node + "\n- message: " + ex.getMessage() + "\n");
150
		}
151
	}
152
	
153
	/**
154
	 * 
155
	 * @param last
156
	 * @param extracted
157
	 * @throws PlanRefinementException
158
	 */
159
	protected void contextSwitch(SearchSpaceNode last, SearchSpaceNode extracted) 
160
			throws PlanRefinementException 
161
	{
162
		// compare the two nodes
163
		if (last != null) 
164
		{
165
			// prepare a list of operators to retract 
166
			List<Operator> toRetract = new ArrayList<>();
167
			// prepare a list of operators to propagate
168
			List<Operator> toPropagate = new ArrayList<>();
169
			
170
			// get the list of operators of the nodes
171
			List<Operator> lastNodeOperators = last.getOperators();
172
			List<Operator> extractedNodeOperators = extracted.getOperators();
173
			
174
			// check min length between the two lists
175
			int minLength = Math.min(lastNodeOperators.size(), extractedNodeOperators.size());
176
			// check potentially common operators
177
			boolean common = true;
178
			for (int i = 0; i < minLength; i++) {
179
				
180
				// check common flag
181
				if (common && !lastNodeOperators.get(i).equals(extractedNodeOperators.get(i))) {
182
					common = false;
183
				}
184
				
185
				// check if no common operators have been found
186
				if (!common) {
187
					// add operator to the different lists
188
					toRetract.add(lastNodeOperators.get(i));
189
					toPropagate.add(extractedNodeOperators.get(i));
190
				}
191
			}
192
			
193
			// check other operators to retract
194
			for (int i = minLength; i < lastNodeOperators.size(); i++) {
195
				toRetract.add(lastNodeOperators.get(i));
196
			}
197
			
198
			// check other operators to propagate
199
			for (int i = minLength; i < extractedNodeOperators.size(); i++) {
200
				toPropagate.add(extractedNodeOperators.get(i));
201
			}
202
			
203
			
204
			// retract operators in reverse order
205
			Collections.reverse(toRetract);
206
			// retract all operators
207
			for (Operator operator : toRetract) {
208
				// retract operator
209
				this.pdb.retract(operator);
210
			}
211
			
212
			// list of committed operators
213
			List<Operator> committed = new ArrayList<>();
214
			try 
215
			{
216
				// propagate operators in chronological order
217
				for (Operator operator : toPropagate) {
218
					// propagate operator
219
					this.pdb.propagate(operator);
220
					// add committed operator
221
					committed.add(operator);
222
				}
223
			}
224
			catch (OperatorPropagationException  ex) {
225
				
226
				// retract committed operators in reverse order
227
				Collections.reverse(committed);
228
				for (Operator operator : committed) {
229
					// retract operator
230
					this.pdb.retract(operator);
231
				}
232
				
233
				// also restore retracted operators
234
				Collections.reverse(toRetract);
235
				for (Operator operator : toRetract) {
236
					try {
237
						// restore operator
238
						this.pdb.propagate(operator);
239
					}
240
					catch (OperatorPropagationException exx) {
241
						warning("[ContextSwitch] Error while restoring operators after failure:\n"
242
								+ "- message: " + ex.getMessage() + "\n");
243
					}
244
				}
245
246
				// throw exception
247
				throw new PlanRefinementException("Error while propagating node:\n" + extracted + "\n- message: " + ex.getMessage() + "\n");
248
			}
249
		}
250
		else {
251
			// simply propagate extracted node
252
			this.propagate(extracted);
253
		}
254
	}
255
	
256
	/**
257
	 * 
258
	 * Expand the search space by adding a new node for each solution of the flaw selected for 
259
	 * plan refinement
260
	 * 
261
	 * @param current
262
	 * @param flaw
263
	 * @return
264
	 * @throws UnsolvableFlawException
265
	 */
266
	protected List<SearchSpaceNode> expand(SearchSpaceNode current, Flaw flaw) 
267
			throws UnsolvableFlawException
268
	{
269
		// list of child nodes
270
		List<SearchSpaceNode> list = new ArrayList<>();
271
		// check if no expansion has done
272
		if (flaw.getSolutions().isEmpty()) {
273
			// this is for debug mainly, as this condition should never occur. Computed flaw solutions should be valid 
274
			throw new UnsolvableFlawException("Search space expansion failure as no valid operator can be applied:\n"
275
					+ "- current node: " + current + "\n"
276
					+ "- flaw: " + flaw + "\n");
277
		}
278
				
279
		// check flaw solutions
280
		for (FlawSolution solution : flaw.getSolutions()) 
281
		{
282
			// create operator
283
			Operator op = new Operator(solution);
284
//			try
285
//			{
286
//				// try to propagate operator
287
//				this.pdb.propagate(op);
288
//				// check plan database feasibility
289
//				this.pdb.verify();
290
				
291
				// get plan with updated temporal bounds and variable binding
292
				Plan plan = this.pdb.getPlan();
293
				// create a child search space node
294
				SearchSpaceNode child = new SearchSpaceNode(current, op);
295
				// set partial plan
296
				child.setPartialPlan(plan);
297
				// look ahead of flaws representing the agenda of the node
298
				for (Flaw f : this.pdb.checkFlaws()) {
299
					// add checked flaw
300
					child.addCheckedFlaw(f);
301
				}
302
303
				// add child
304
				list.add(child);
305
//			}
306
//			catch (OperatorPropagationException | ConsistencyCheckException ex) {
307
//				warning("Invalid operator found during search expansion phase:\n"
308
//						+ "- current node: " + current + "\n"
309
//						+ "- flaw: " + flaw + "\n"
310
//						+ "- failed operator: " + op + "\n");
311
//				
312
//				// debug
313
//				System.err.println("Invalid operator found during search expansion phase:\n"
314
//						+ "- current node: " + current + "\n"
315
//						+ "- flaw: " + flaw + "\n"
316
//						+ "- failed operator: " + op + "\n");
317
//			}
318
//			finally {
319
//				// retract operator
320
//				this.pdb.retract(op);
321
//			}
322
		}
323
		
324
		
325
		
326
		// get children
327
		return list;
328
	}
329
}
330