it.cnr.istc.pst.platinum.ai.framework.time.TemporalFacade   F
last analyzed

Complexity

Total Complexity 68

Size/Duplication

Total Lines 1029
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 453
dl 0
loc 1029
rs 2.96
c 0
b 0
f 0
wmc 68

33 Methods

Rating   Name   Duplication   Size   Complexity  
A TemporalFacade() 0 10 1
A createTimePoint(long) 0 12 2
A createTimePoint() 0 13 2
A createTimePoint(long[]) 0 12 2
A createTemporalInterval(long[],boolean) 0 8 1
A createTemporalInterval(long[],long[],boolean) 0 8 1
A createTemporalInterval(boolean) 0 7 1
A getOrigin() 0 2 1
A getHorizon() 0 2 1
A createTemporalInterval(long[],long[],long[],boolean) 0 58 4
A deleteTemporalInterval(TemporalInterval) 0 11 1
A doPropagateContainsConstraint(ContainsIntervalConstraint) 0 25 1
A doPropagateFixIntervalDurationConstraint(FixIntervalDurationConstraint) 0 15 1
A doPropagateMeetsConstraint(MeetsIntervalConstraint) 0 15 1
A doPropagateBeforeConstraint(BeforeIntervalConstraint) 0 15 1
A verify() 0 11 3
A doPropagateDuringConstraint(DuringIntervalConstraint) 0 23 1
A doPropagateAfterConstraint(AfterIntervalConstraint) 0 15 1
A createTemporalConstraint(TemporalConstraintType) 0 5 1
F propagate(TemporalConstraint) 0 165 15
A verifyTemporalConsistency() 0 6 2
A doPropagateEndsDuringConstraint(EndsDuringIntervalConstraint) 0 23 1
A doPropagateMetByConstraint(MetByIntervalConstraint) 0 15 1
A retract(TemporalConstraint) 0 9 2
A isPseudoControllable() 0 34 4
A verifyPseudocontrollability() 0 6 2
C process(TemporalQuery) 0 139 8
A createTemporalQuery(TemporalQueryType) 0 5 1
A printDiagnosticData() 0 3 1
A doPropagateEqualsConstraint(EqualsIntervalConstraint) 0 25 1
A doPropagateStartsDuringConstraint(StartsDuringIntervalConstraint) 0 23 1
A toString() 0 7 1
A doPropagateFixTimePointConstraint(FixTimePointConstraint) 0 15 1

How to fix   Complexity   

Complexity

Complex classes like it.cnr.istc.pst.platinum.ai.framework.time.TemporalFacade often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package it.cnr.istc.pst.platinum.ai.framework.time;
2
3
import java.util.ArrayList;
4
import java.util.Arrays;
5
import java.util.HashSet;
6
import java.util.List;
7
import java.util.Set;
8
import java.util.concurrent.atomic.AtomicInteger;
9
10
import it.cnr.istc.pst.platinum.ai.framework.microkernel.FrameworkObject;
11
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.cfg.framework.TemporalFacadeConfiguration;
12
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.framework.TemporalNetworkPlaceholder;
13
import it.cnr.istc.pst.platinum.ai.framework.microkernel.annotation.inject.framework.TemporalSolverPlaceholder;
14
import it.cnr.istc.pst.platinum.ai.framework.microkernel.lang.ex.ConsistencyCheckException;
15
import it.cnr.istc.pst.platinum.ai.framework.microkernel.query.QueryManager;
16
import it.cnr.istc.pst.platinum.ai.framework.microkernel.query.TemporalQuery;
17
import it.cnr.istc.pst.platinum.ai.framework.microkernel.query.TemporalQueryFactory;
18
import it.cnr.istc.pst.platinum.ai.framework.microkernel.query.TemporalQueryType;
19
import it.cnr.istc.pst.platinum.ai.framework.time.ex.InconsistentIntervaEndTimeException;
20
import it.cnr.istc.pst.platinum.ai.framework.time.ex.InconsistentIntervalDurationException;
21
import it.cnr.istc.pst.platinum.ai.framework.time.ex.InconsistentIntervalStartTimeException;
22
import it.cnr.istc.pst.platinum.ai.framework.time.ex.PseudoControllabilityException;
23
import it.cnr.istc.pst.platinum.ai.framework.time.ex.TemporalConsistencyException;
24
import it.cnr.istc.pst.platinum.ai.framework.time.ex.TemporalConstraintPropagationException;
25
import it.cnr.istc.pst.platinum.ai.framework.time.ex.TemporalIntervalCreationException;
26
import it.cnr.istc.pst.platinum.ai.framework.time.ex.TimePointCreationException;
27
import it.cnr.istc.pst.platinum.ai.framework.time.lang.FixIntervalDurationConstraint;
28
import it.cnr.istc.pst.platinum.ai.framework.time.lang.FixTimePointConstraint;
29
import it.cnr.istc.pst.platinum.ai.framework.time.lang.TemporalConstraint;
30
import it.cnr.istc.pst.platinum.ai.framework.time.lang.TemporalConstraintFactory;
31
import it.cnr.istc.pst.platinum.ai.framework.time.lang.TemporalConstraintType;
32
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.AfterIntervalConstraint;
33
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.BeforeIntervalConstraint;
34
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.ContainsIntervalConstraint;
35
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.DuringIntervalConstraint;
36
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.EndsDuringIntervalConstraint;
37
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.EqualsIntervalConstraint;
38
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.MeetsIntervalConstraint;
39
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.MetByIntervalConstraint;
40
import it.cnr.istc.pst.platinum.ai.framework.time.lang.allen.StartsDuringIntervalConstraint;
41
import it.cnr.istc.pst.platinum.ai.framework.time.lang.query.IntervalDistanceQuery;
42
import it.cnr.istc.pst.platinum.ai.framework.time.lang.query.IntervalOverlapQuery;
43
import it.cnr.istc.pst.platinum.ai.framework.time.lang.query.IntervalPseudoControllabilityQuery;
44
import it.cnr.istc.pst.platinum.ai.framework.time.lang.query.IntervalScheduleQuery;
45
import it.cnr.istc.pst.platinum.ai.framework.time.solver.TemporalSolver;
46
import it.cnr.istc.pst.platinum.ai.framework.time.solver.TemporalSolverType;
47
import it.cnr.istc.pst.platinum.ai.framework.time.tn.TemporalNetwork;
48
import it.cnr.istc.pst.platinum.ai.framework.time.tn.TemporalNetworkType;
49
import it.cnr.istc.pst.platinum.ai.framework.time.tn.TimePoint;
50
import it.cnr.istc.pst.platinum.ai.framework.time.tn.TimePointDistanceConstraint;
51
import it.cnr.istc.pst.platinum.ai.framework.time.tn.ex.InconsistentDistanceConstraintException;
52
import it.cnr.istc.pst.platinum.ai.framework.time.tn.ex.InconsistentTpValueException;
53
import it.cnr.istc.pst.platinum.ai.framework.time.tn.lang.query.TimePointDistanceQuery;
54
import it.cnr.istc.pst.platinum.ai.framework.time.tn.lang.query.TimePointQuery;
55
import it.cnr.istc.pst.platinum.ai.framework.time.tn.lang.query.TimePointScheduleQuery;
56
57
/**
58
 * 
59
 * @author alessandro
60
 *
61
 */
62
@TemporalFacadeConfiguration(
63
		// default network type 
64
		network = TemporalNetworkType.STNU,
65
		// default temporal reasoner
66
		solver = TemporalSolverType.APSP
67
)
68
public class TemporalFacade extends FrameworkObject implements QueryManager<TemporalQuery>
69
{
70
	@TemporalNetworkPlaceholder
71
	protected TemporalNetwork tn;										// temporal network
72
73
	@TemporalSolverPlaceholder
74
	protected TemporalSolver<TimePointQuery> solver;					// time point reasoner
75
	
76
	protected Set<TemporalInterval> intervals;							// set of created temporal intervals
77
	protected TemporalQueryFactory qf;									// temporal query factory
78
	protected TemporalConstraintFactory cf;	 							// temporal constraint factory
79
	
80
	// static information
81
	
82
	private static final AtomicInteger ID_COUNTER = new AtomicInteger(0);
83
	
84
	/**
85
	 * 
86
	 */
87
	protected TemporalFacade() {
88
		super();
89
		
90
		// get query factory instance
91
		this.qf = new TemporalQueryFactory();
92
		this.cf = new TemporalConstraintFactory();
93
		this.intervals = new HashSet<>();
94
		
95
		// reset atomic id counter if needed
96
		ID_COUNTER.set(0);
97
	}
98
	
99
	/**
100
	 * 
101
	 * @return
102
	 */
103
	public long getOrigin() {
104
		return this.tn.getOrigin();
105
	}
106
	
107
	/**
108
	 * 
109
	 * @return
110
	 */
111
	public long getHorizon() {
112
		return this.tn.getHorizon();
113
	}
114
	
115
	/**
116
	 * Create a flexible time point
117
	 * 
118
	 * @return
119
	 * @throws TimePointCreationException
120
	 */
121
	public synchronized TimePoint createTimePoint() 
122
			throws TimePointCreationException 
123
	{
124
		// time point to create
125
		TimePoint point = null;
126
		try {
127
			// create a time point
128
			point = this.tn.addTimePoint();
129
		} catch (InconsistentDistanceConstraintException ex) {
130
			throw new TimePointCreationException(ex.getMessage());
131
		}
132
		// get time point
133
		return point;
134
	}
135
	
136
	/**
137
	 * Create a scheduled time point
138
	 * 
139
	 * @param at
140
	 * @return
141
	 * @throws TimePointCreationException
142
	 */
143
	public synchronized TimePoint createTimePoint(long at) 
144
			throws TimePointCreationException {
145
		// time point to create
146
		TimePoint point = null;
147
		try {
148
			// create a fixed time point
149
			point = this.tn.addTimePoint(at);
150
		} catch (InconsistentTpValueException | InconsistentDistanceConstraintException  ex) {
151
			throw new TimePointCreationException(ex.getMessage());
152
		}
153
		// get time point
154
		return point;
155
	}
156
	
157
	/**
158
	 * Create a flexible time point within the specified bound
159
	 * 
160
	 * @param bounds
161
	 * @return
162
	 * @throws TimePointCreationException
163
	 */
164
	public synchronized TimePoint createTimePoint(long[] bounds) 
165
			throws TimePointCreationException {
166
		// time point to create
167
		TimePoint point = null;
168
		try {
169
			// create a time point within bound
170
			point = this.tn.addTimePoint(bounds[0], bounds[1]);
171
		} catch (InconsistentDistanceConstraintException | InconsistentTpValueException ex) {
172
			throw new TimePointCreationException(ex.getMessage());
173
		}
174
		// get created time point
175
		return point;
176
	}
177
178
	/**
179
	 * Create a controllable temporal interval
180
	 * 
181
	 * @return
182
	 * @throws TemporalIntervalCreationException
183
	 */
184
	public synchronized TemporalInterval createTemporalInterval(boolean controllable) 
185
			throws TemporalIntervalCreationException {
186
		// create temporal interval
187
		return this.createTemporalInterval(new long[] {this.getOrigin(), this.getHorizon()}, 
188
				new long[] {this.getOrigin(), this.getHorizon()}, 
189
				new long[] {1, this.getHorizon()}, 
190
				controllable);		
191
	}
192
	
193
	/**
194
	 * Create a flexible interval with duration within the specified bound
195
	 * 
196
	 * @param duration
197
	 * @return
198
	 * @throws TemporalIntervalCreationException
199
	 */
200
	public synchronized TemporalInterval createTemporalInterval(long[] duration, boolean controllable) 
201
			throws TemporalIntervalCreationException 
202
	{
203
		// create temporal interval
204
		return this.createTemporalInterval(new long[] {this.getOrigin(), this.getHorizon()}, 
205
				new long[] {this.getOrigin(), this.getHorizon()}, 
206
				duration, 
207
				controllable);
208
	}
209
	
210
	/**
211
	 * 
212
	 * @param end
213
	 * @param duration
214
	 * @param controllable
215
	 * @return
216
	 * @throws TemporalIntervalCreationException
217
	 */
218
	public synchronized TemporalInterval createTemporalInterval(long[] end, long[] duration, boolean controllable) 
219
			throws TemporalIntervalCreationException 
220
	{
221
		// create temporal interval
222
		return this.createTemporalInterval(new long[] {this.getOrigin(), this.getHorizon()}, 
223
				end, 
224
				duration, 
225
				controllable);
226
	}
227
	
228
	/**
229
	 * 
230
	 * @param end
231
	 * @param duration
232
	 * @param controllable
233
	 * @return
234
	 * @throws TemporalIntervalCreationException
235
	 */
236
	public synchronized TemporalInterval createTemporalInterval(long[] start, long[] end, long[] duration, boolean controllable) 
237
			throws TemporalIntervalCreationException {
238
		
239
		// interval's start time
240
		TimePoint s = null;
241
		try {
242
			
243
			// create flexible start time
244
			s = this.tn.addTimePoint(start[0], start[1]);
245
			
246
		} catch (InconsistentDistanceConstraintException | InconsistentTpValueException ex) {
247
			// throw exception
248
			throw new InconsistentIntervalStartTimeException(ex.getMessage());
249
		}
250
		
251
		// interval's end time
252
		TimePoint e = null;
253
		try {
254
			
255
			// create flexible end time
256
			e = this.tn.addTimePoint(end[0], end[1]);
257
			
258
		} catch (InconsistentDistanceConstraintException | InconsistentTpValueException ex) {
259
			// delete start time
260
			this.tn.removeTimePoint(s);
261
			throw new InconsistentIntervaEndTimeException(ex.getMessage());
262
		}
263
		
264
		// interval's duration
265
		TimePointDistanceConstraint d = null;
266
		try {
267
			
268
			// create distance constraint
269
			d = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
270
			d.setReference(s);
271
			d.setTarget(e);
272
			d.setDistanceLowerBound(Math.max(1, duration[0]));
273
			d.setDistanceUpperBound(Math.min(duration[1], this.getHorizon()));
274
			d.setControllable(controllable);
275
			
276
			// propagate distance constraint
277
			this.tn.addDistanceConstraint(d);
278
			
279
		} catch (InconsistentDistanceConstraintException ex) {
280
			
281
			// remove start and end time points
282
			this.tn.removeTimePoint(s);
283
			this.tn.removeTimePoint(e);
284
			// throw exception
285
			throw new InconsistentIntervalDurationException(ex.getMessage());
286
		}
287
		
288
		// create temporal interval 
289
		TemporalInterval interval = new TemporalInterval(ID_COUNTER.getAndIncrement(), d);
290
		// record interval
291
		this.intervals.add(interval);
292
		// get created interval
293
		return interval;
294
	}
295
	
296
	/**
297
	 * 
298
	 * Remove a temporal interval from the temporal data-based. 
299
	 * 
300
	 * The method removes the time points of the interval and all related time point distance constraints from the underlying temporal network
301
	 * 
302
	 * @param i
303
	 */
304
	public synchronized void deleteTemporalInterval(TemporalInterval i) {
305
		// list of time points to remove
306
		List<TimePoint> list = new ArrayList<>();
307
		// get start time
308
		list.add(i.getStartTime());
309
		// get end time
310
		list.add(i.getEndTime());
311
		// the network will automatically remove all constraints concerning the two time points
312
		this.tn.removeTimePoints(list);
313
		// remove interval 
314
		this.intervals.remove(i);
315
	}
316
	
317
	/**
318
	 * Check the temporal consistency of the temporal information as well as the 
319
	 * pseudo-controllability property of the STNU.
320
	 * 
321
	 * 
322
	 */
323
	public synchronized void verify() 
324
			throws ConsistencyCheckException {
325
		
326
		// check temporal network consistency
327
		if (!this.solver.isValid()) {
328
			throw new TemporalConsistencyException("The STNU is not valid!\nCheck propagated temporal constraints...\n");
329
		}
330
		
331
		// check also if the network is valid
332
		if (!this.isPseudoControllable()) {
333
			throw new PseudoControllabilityException("The STNU is not pseudo-controllable!\nCheck constraints on uncontrollable intervals...\n");
334
		}
335
	}
336
	
337
	/**
338
	 * 
339
	 * @throws TemporalConsistencyException
340
	 */
341
	public synchronized void verifyTemporalConsistency() 
342
			throws TemporalConsistencyException {
343
		
344
		// check temporal network consistency
345
		if (!this.solver.isValid()) {
346
			throw new TemporalConsistencyException("The STNU is not valid!\nCheck propagated temporal constraints...\n");
347
		}
348
	}
349
	
350
	/**
351
	 * 
352
	 * @throws PseudoControllabilityException
353
	 */
354
	public synchronized void verifyPseudocontrollability() 
355
			throws PseudoControllabilityException {
356
		
357
		// check also if the network is valid
358
		if (!this.isPseudoControllable()) {
359
			throw new PseudoControllabilityException("The STNU is not pseudo-controllable!\nCheck constraints on uncontrollable intervals...\n");
360
		}
361
	}
362
	
363
	/**
364
	 * 
365
	 * @param type
366
	 * @return
367
	 */
368
	public synchronized <T extends TemporalQuery> T createTemporalQuery(TemporalQueryType type) {
369
		// query instance
370
		T query = this.qf.create(type);
371
		// get created instance
372
		return query;
373
	}
374
	
375
	/**
376
	 * 
377
	 * @param type
378
	 * @return
379
	 */
380
	public synchronized <T extends TemporalConstraint> T createTemporalConstraint(TemporalConstraintType type) {
381
		// create constraint
382
		T cons = this.cf.create(type);
383
		// get created constraint
384
		return cons;
385
	}
386
	
387
	/**
388
	 * 
389
	 */
390
	@Override
391
	public synchronized void process(TemporalQuery query) 
392
	{
393
		// check query type
394
		switch (query.getType()) 
395
		{
396
			// check distance between intervals
397
			case INTERVAL_DISTANCE : 
398
			{
399
				// get query
400
				IntervalDistanceQuery dQuery = (IntervalDistanceQuery) query;
401
				// get intervals
402
				TemporalInterval a = dQuery.getSource();
403
				TemporalInterval b = dQuery.getTarget();
404
				// create time point query
405
				TimePointDistanceQuery tpQuery = this.qf.create(TemporalQueryType.TP_DISTANCE);
406
				// set source and target
407
				tpQuery.setSource(a.getEndTime());
408
				tpQuery.setTarget(b.getStartTime());
409
				// process query
410
				this.solver.process(tpQuery);
411
				// set bounds
412
				dQuery.setDistanceLowerBound(tpQuery.getDistanceLowerBound());
413
				dQuery.setDistanceUpperBOund(tpQuery.getDistanceUpperBound());
414
			}
415
			break;
416
			
417
			// check overlapping intervals
418
			case INTERVAL_OVERLAP :
419
			{
420
				// get query
421
				IntervalOverlapQuery overlap = (IntervalOverlapQuery) query;
422
				// get intervals
423
				TemporalInterval a = overlap.getReference();
424
				TemporalInterval b = overlap.getTarget();
425
				
426
				// check the distance between the time point of A and the start time point of B
427
				TimePointDistanceQuery eAsB = this.qf.create(TemporalQueryType.TP_DISTANCE);
428
				eAsB.setSource(a.getEndTime());
429
				eAsB.setTarget(b.getStartTime());
430
				// process query
431
				this.process(eAsB);
432
				// check computed bounds
433
				long dmin = eAsB.getDistanceLowerBound();
434
				long dmax = eAsB.getDistanceUpperBound();
435
				// check if can overlap
436
				boolean o1 = !((dmin <= 0 && dmax <= 0) || (dmin >= 0 && dmax >= 0));
437
				
438
				
439
				// get intervals
440
				a = overlap.getTarget();
441
				b = overlap.getReference();
442
				
443
				// check the distance between the time point of A and the start time point of B
444
				TimePointDistanceQuery eBsA = this.qf.create(TemporalQueryType.TP_DISTANCE);
445
				eBsA.setSource(a.getEndTime());
446
				eBsA.setTarget(b.getStartTime());
447
				// process query
448
				this.process(eBsA);
449
				// check computed bounds
450
				dmin = eBsA.getDistanceLowerBound();
451
				dmax = eBsA.getDistanceUpperBound();
452
				// check if can overlap
453
				boolean o2 = !((dmin <= 0 && dmax <= 0) || (dmin >= 0 && dmax >= 0));
454
				
455
		
456
				// set result
457
				overlap.setCanOverlap(o1 || o2);
458
				// print logging message
459
				debug("[" + this.getClass().getName() + "] Processing query INTERVAL_OVERLAP:\n"
460
						+ "- Temporal Interval (A): " + a + "\n"
461
						+ "- Temporal Interval (B): " + b + "\n"
462
						+ "- Computed (flexible) distance: [dmin= " + dmin + ", dmax= " + dmax +"]\n"
463
						+ "- Answer to query: " + overlap.canOverlap());
464
			}
465
			break;
466
			
467
			// check interval schedule 
468
			case INTERVAL_SCHEDULE : 
469
			{
470
				// get query
471
				IntervalScheduleQuery scheduleQuery = (IntervalScheduleQuery) query;
472
				// get interval
473
				TemporalInterval i = scheduleQuery.getInterval();
474
				
475
				// create time point bound query
476
				TimePointScheduleQuery sQuery = this.qf.create(TemporalQueryType.TP_SCHEDULE);
477
				// set point 
478
				sQuery.setTimePoint(i.getStartTime());
479
				// check start schedule
480
				this.solver.process(sQuery);
481
				
482
				// process end time
483
				TimePointScheduleQuery eQuery = this.qf.create(TemporalQueryType.TP_SCHEDULE);
484
				// set point
485
				eQuery.setTimePoint(i.getEndTime());
486
				// check end schedule
487
				this.solver.process(eQuery);
488
				
489
				// check time point distance
490
				TimePointDistanceQuery dQuery= this.qf.create(TemporalQueryType.TP_DISTANCE);
491
				// set points
492
				dQuery.setSource(i.getStartTime());
493
				dQuery.setTarget(i.getEndTime());
494
				// process query
495
				this.solver.process(dQuery);
496
				
497
				// set interval duration
498
				i.setDurationLowerBound(dQuery.getDistanceLowerBound());
499
				i.setDurationUpperBound(dQuery.getDistanceUpperBound());
500
			}
501
			break;
502
			
503
			// check if squeezed interval
504
			case INTERVAL_PSEUDO_CONTROLLABILITY : 
505
			{
506
				// get query
507
				IntervalPseudoControllabilityQuery pseudoQuery = (IntervalPseudoControllabilityQuery) query;
508
				// get temporal interval
509
				TemporalInterval i = pseudoQuery.getInterval();
510
				// check the schedule
511
				IntervalScheduleQuery squery = this.qf.create(TemporalQueryType.INTERVAL_SCHEDULE);
512
				squery.setInterval(i);
513
				this.process(squery);
514
				// check if pseudo-controllability condition
515
				pseudoQuery.setPseudoControllable(i.getDurationLowerBound() == i.getNominalDurationLowerBound() && 
516
						i.getDurationUpperBound() == i.getNominalDurationUpperBound());
517
			}
518
			break;
519
			
520
			// time point queries
521
			case TP_SCHEDULE :
522
			case TP_DISTANCE : 
523
			case TP_DISTANCE_TO_HORIZON : {
524
				
525
				// propagate time point query to the reasoner
526
				this.solver.process((TimePointQuery) query);
527
			}
528
			break;
529
		}
530
	}
531
	
532
	/**
533
	 * This method propagates an interval constraint to the underlying temporal network.
534
	 * 
535
	 * When propagating constraints no contingent link can be affected or overwritten. Thus,
536
	 * the method throws an exception if a contingent link is affected by the propagated 
537
	 * constraint.
538
	 * 
539
	 * @param constraint
540
	 * @throws Exception
541
	 */
542
	public synchronized void propagate(TemporalConstraint constraint) 
543
			throws TemporalConstraintPropagationException 
544
	{
545
		try 
546
		{
547
			// check temporal constraint type
548
			switch (constraint.getType()) 
549
			{
550
				// create BEFORE constraint into the temporal network
551
				case BEFORE : 
552
				{
553
					// get constraint
554
					BeforeIntervalConstraint before = (BeforeIntervalConstraint) constraint;
555
					// propagate constraint
556
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] { 
557
						this.doPropagateBeforeConstraint(before)
558
					};
559
					
560
					// set propagated constraint
561
					before.setPropagatedConstraints(c);
562
				}
563
				break;
564
				
565
				// create AFTER constraint into the temporal network
566
				case AFTER : 
567
				{
568
					AfterIntervalConstraint after = (AfterIntervalConstraint) constraint;
569
					// propagate constraint
570
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] {
571
						this.doPropagateAfterConstraint(after)
572
					};
573
					// set propagated constraint
574
					after.setPropagatedConstraints(c);
575
				}
576
				break;
577
				
578
				// create MEETS constraint into the temporal network
579
				case MEETS : 
580
				{
581
					// get constraint
582
					MeetsIntervalConstraint meets = (MeetsIntervalConstraint) constraint;
583
					// propagate constraint
584
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] { 
585
							this.doPropagateMeetsConstraint(meets)	
586
					};
587
					// set propagated constraints
588
					meets.setPropagatedConstraints(c);
589
				}
590
				break;
591
				
592
				// create MET-BY constraint into the temporal network
593
				case MET_BY : 
594
				{
595
					// get constraint
596
					MetByIntervalConstraint metby = (MetByIntervalConstraint) constraint;
597
					// propagate constraint
598
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] {
599
							this.doPropagateMetByConstraint(metby)
600
					};
601
					// set propagated constraints
602
					metby.setPropagatedConstraints(c);
603
				}
604
				break;
605
				
606
				// create CONTAINS constraint into the temporal network
607
				case CONTAINS : 
608
				{
609
					// get constraint
610
					ContainsIntervalConstraint contains = (ContainsIntervalConstraint) constraint;
611
					// propagate constraint
612
					TimePointDistanceConstraint[] c = this.doPropagateContainsConstraint(contains);
613
					// set propagated constraints
614
					contains.setPropagatedConstraints(c);
615
				}
616
				break;
617
				
618
				// create DURING constraint into the temporal network
619
				case DURING : 
620
				{
621
					// get constraint
622
					DuringIntervalConstraint during = (DuringIntervalConstraint) constraint;
623
					// propagate constraint
624
					TimePointDistanceConstraint[] c = this.doPropagateDuringConstraint(during);
625
					// set propagated constraints
626
					during.setPropagatedConstraints(c);
627
				}
628
				break;
629
				
630
				// create STARTS-DURING constraint into the network
631
				case STARTS_DURING : 
632
				{
633
					// get constraint
634
					StartsDuringIntervalConstraint sdc = (StartsDuringIntervalConstraint) constraint;
635
					// propagate constraint
636
					TimePointDistanceConstraint[] c = this.doPropagateStartsDuringConstraint(sdc);
637
					// set propagated constraints
638
					sdc.setPropagatedConstraints(c);
639
				}
640
				break;
641
				
642
				// create ENDS-DURING constraint into the network
643
				case ENDS_DURING : 
644
				{
645
					// get constraint
646
					EndsDuringIntervalConstraint edc = (EndsDuringIntervalConstraint) constraint;
647
					// propagate constraint
648
					TimePointDistanceConstraint[] c = this.doPropagateEndsDuringConstraint(edc);
649
					// set propagated constraints
650
					edc.setPropagatedConstraints(c);
651
				}
652
				break;
653
				
654
				// create EQUALS constraint into the temporal network
655
				case EQUALS : 
656
				{
657
					// get constraint
658
					EqualsIntervalConstraint equals = (EqualsIntervalConstraint) constraint;
659
					// propagate constraint
660
					TimePointDistanceConstraint[] c = this.doPropagateEqualsConstraint(equals);
661
					// set propagated constraint
662
					equals.setPropagatedConstraints(c);
663
				}
664
				break;
665
				
666
				// set the duration of a temporal interval
667
				case FIX_INTERVAL_DURATION : 
668
				{
669
					// get constraint
670
					FixIntervalDurationConstraint fix = (FixIntervalDurationConstraint) constraint;
671
					// propagate constraint
672
					TimePointDistanceConstraint c = this.doPropagateFixIntervalDurationConstraint(fix);
673
					// set propagate constraints
674
					fix.setPropagatedConstraints(new TimePointDistanceConstraint[] {c});
675
				}
676
				break;
677
				
678
				// schedule a time point at a given time
679
				case FIX_TIME_POINT :
680
				{
681
					// get constraint
682
					FixTimePointConstraint fix = (FixTimePointConstraint) constraint;
683
					// propagate constraint
684
					TimePointDistanceConstraint c = this.doPropagateFixTimePointConstraint(fix);
685
					// set propagated constraint
686
					fix.setPropagatedConstraints(new TimePointDistanceConstraint[] {c});
687
				}
688
				break;
689
				
690
				// set a distance constraint between two time points
691
				case TIME_POINT_DISTANCE :
692
				{
693
					// get constraint
694
					TimePointDistanceConstraint cons = (TimePointDistanceConstraint) constraint;
695
					// directly propagate distance constraint to the temporal network
696
					this.tn.addDistanceConstraint(cons);
697
				}
698
				break;
699
				
700
				default : { 
701
					throw new RuntimeException("Unknown temporal constraint!");
0 ignored issues
show
Best Practice introduced by
Dedicated exceptions should be preferred over throwing the generic Exception.
Loading history...
702
				}
703
			}
704
		}
705
		catch (InconsistentDistanceConstraintException ex) {
706
			throw new TemporalConstraintPropagationException(ex.getMessage());
707
		}
708
	}
709
710
	/**
711
	 * 
712
	 * @param constraint
713
	 * @throws Exception
714
	 */
715
	public synchronized void retract(TemporalConstraint constraint) {
716
		// retract propagated constraints
717
		TimePointDistanceConstraint[] toRetract = constraint.getPropagatedConstraints();
718
		// verify whether some constraints have been propagated
719
		if (toRetract != null) {
720
			// remove propagated distance constraints
721
			this.tn.removeDistanceConstraint(Arrays.asList(toRetract));
722
			// clear data structure
723
			constraint.clear();
724
		}
725
	}
726
	
727
	/**
728
	 * 
729
	 */
730
	@Override
731
	public String toString() {
732
		return "\nTemporal Network:\n"
733
				+ "" + this.tn.toString() + "\n"
734
				+ "--------------\n"
735
				+ "Solver:\n"
736
				+ "" + this.solver.toString() + "\n\n";
737
	}
738
	
739
	/**
740
	 * 
741
	 * @param equals
742
	 * @return
743
	 * @throws InconsistentDistanceConstraintException
744
	 */
745
	protected TimePointDistanceConstraint[] doPropagateEqualsConstraint(EqualsIntervalConstraint equals) 
746
			throws InconsistentDistanceConstraintException {
747
		
748
		// create distance constraint 
749
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
750
		// set constraint data
751
		c1.setReference(equals.getReference().getStartTime());
752
		c1.setTarget(equals.getTarget().getStartTime());
753
		c1.setDistanceLowerBound(0);
754
		c1.setDistanceUpperBound(0);
755
		c1.setControllable(true);
756
		
757
		// create distance constraint
758
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
759
		// set constraint data
760
		c2.setReference(equals.getReference().getEndTime());
761
		c2.setTarget(equals.getTarget().getEndTime());
762
		c2.setDistanceLowerBound(0);
763
		c2.setDistanceUpperBound(0);
764
		c2.setControllable(true);
765
		
766
		// add constraints
767
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
768
		// get added distance constraints
769
		return new TimePointDistanceConstraint[] {c1, c2};
770
	}
771
772
	/**
773
	 * 
774
	 * @param contains
775
	 * @return
776
	 * @throws InconsistentDistanceConstraintException
777
	 */
778
	protected TimePointDistanceConstraint[] doPropagateContainsConstraint(ContainsIntervalConstraint contains) 
779
			throws InconsistentDistanceConstraintException {
780
		
781
		// create distance constraint
782
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
783
		// set data
784
		c1.setReference(contains.getReference().getStartTime());
785
		c1.setTarget(contains.getTarget().getStartTime());
786
		c1.setDistanceLowerBound(contains.getFirstBound()[0]);
787
		c1.setDistanceUpperBound(contains.getFirstBound()[1]);
788
		c1.setControllable(true);
789
		
790
		// create distance constraint
791
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
792
		// set data
793
		c2.setReference(contains.getTarget().getEndTime());
794
		c2.setTarget(contains.getReference().getEndTime());
795
		c2.setDistanceLowerBound(contains.getSecondBound()[0]);
796
		c2.setDistanceUpperBound(contains.getSecondBound()[1]);
797
		c2.setControllable(true);
798
		
799
		// add constraints
800
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
801
		// get added constraints
802
		return new TimePointDistanceConstraint[] {c1, c2};
803
	}
804
805
	/**
806
	 * 
807
	 * @param during
808
	 * @return
809
	 * @throws InconsistentDistanceConstraintException
810
	 */
811
	protected TimePointDistanceConstraint[] doPropagateDuringConstraint(DuringIntervalConstraint during) 
812
			throws InconsistentDistanceConstraintException {
813
		
814
		// create constraint
815
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
816
		c1.setReference(during.getTarget().getStartTime());
817
		c1.setTarget(during.getReference().getStartTime());
818
		c1.setDistanceLowerBound(during.getFirstBound()[0]);
819
		c1.setDistanceUpperBound(during.getFirstBound()[1]);
820
		c1.setControllable(true);
821
		
822
		// create constraint
823
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
824
		c2.setReference(during.getReference().getEndTime());
825
		c2.setTarget(during.getTarget().getEndTime());
826
		c2.setDistanceLowerBound(during.getSecondBound()[0]);
827
		c2.setDistanceUpperBound(during.getSecondBound()[1]);
828
		c2.setControllable(true);
829
				
830
		// add constraint
831
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
832
		// get added constraints
833
		return new TimePointDistanceConstraint[] {c1, c2};
834
	}
835
	
836
	/**
837
	 * 
838
	 * @param edc
839
	 * @return
840
	 * @throws InconsistentDistanceConstraintException
841
	 */
842
	protected TimePointDistanceConstraint[] doPropagateEndsDuringConstraint(EndsDuringIntervalConstraint edc) 
843
			throws InconsistentDistanceConstraintException {
844
		
845
		// create constraint
846
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
847
		c1.setReference(edc.getTarget().getStartTime());
848
		c1.setTarget(edc.getReference().getEndTime());
849
		c1.setDistanceLowerBound(edc.getFirstTimeBound()[0]);
850
		c1.setDistanceUpperBound(edc.getFirstTimeBound()[1]);
851
		c1.setControllable(true);
852
		
853
		// create constraint
854
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
855
		c2.setReference(edc.getReference().getEndTime());
856
		c2.setTarget(edc.getTarget().getEndTime());
857
		c2.setDistanceLowerBound(edc.getSecondTimeBound()[0]);
858
		c2.setDistanceUpperBound(edc.getSecondTimeBound()[1]);
859
		c2.setControllable(true);
860
		
861
		// add constraint 
862
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
863
		// propagate constraints
864
		return new TimePointDistanceConstraint[] {c1, c2};
865
	}
866
867
	/**
868
	 * 
869
	 * @param sdc
870
	 * @return
871
	 * @throws InconsistentDistanceConstraintException
872
	 */
873
	protected TimePointDistanceConstraint[] doPropagateStartsDuringConstraint(StartsDuringIntervalConstraint sdc) 
874
			throws InconsistentDistanceConstraintException 
875
	{
876
		// create constraint
877
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
878
		c1.setReference(sdc.getTarget().getStartTime());
879
		c1.setTarget(sdc.getReference().getStartTime());
880
		c1.setDistanceLowerBound(sdc.getFirstTimeBound()[0]);
881
		c1.setDistanceUpperBound(sdc.getFirstTimeBound()[1]);
882
		c1.setControllable(true);
883
		
884
		// create constraint
885
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE); 
886
		c2.setReference(sdc.getReference().getStartTime());
887
		c2.setTarget(sdc.getTarget().getEndTime());
888
		c2.setDistanceLowerBound(sdc.getSecondTimeBound()[0]);
889
		c2.setDistanceUpperBound(sdc.getSecondTimeBound()[1]);
890
		c2.setControllable(true);
891
		
892
		// add constraint
893
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
894
		// propagate constraints
895
		return new TimePointDistanceConstraint[] {c1, c2};
896
	}
897
898
	/**
899
	 * 
900
	 * @param before
901
	 * @return
902
	 * @throws InconsistentDistanceConstraintException
903
	 */
904
	protected TimePointDistanceConstraint doPropagateBeforeConstraint(BeforeIntervalConstraint before)
905
			throws InconsistentDistanceConstraintException {
906
		
907
		// create constraint
908
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
909
		c.setReference(before.getReference().getEndTime());
910
		c.setTarget(before.getTarget().getStartTime());
911
		c.setDistanceLowerBound(before.getLowerBound());
912
		c.setDistanceUpperBound(before.getUpperBound());
913
		c.setControllable(true);
914
		
915
		// add constraint
916
		this.tn.addDistanceConstraint(c);
917
		// get propagated constraint
918
		return c;
919
	}
920
	
921
	/**
922
	 * 
923
	 * @param meets
924
	 * @return
925
	 * @throws InconsistentDistanceConstraintException
926
	 */
927
	protected TimePointDistanceConstraint doPropagateMeetsConstraint(MeetsIntervalConstraint meets) 
928
			throws InconsistentDistanceConstraintException {
929
		
930
		// create constraint
931
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
932
		c.setReference(meets.getReference().getEndTime());
933
		c.setTarget(meets.getTarget().getStartTime());
934
		c.setDistanceLowerBound(0);
935
		c.setDistanceUpperBound(0);
936
		c.setControllable(true);
937
		
938
		// add constraint
939
		this.tn.addDistanceConstraint(c);
940
		// get propagated constraint
941
		return c;
942
	}
943
	
944
	/**
945
	 * 
946
	 * @param after
947
	 * @return
948
	 * @throws InconsistentDistanceConstraintException
949
	 */
950
	protected TimePointDistanceConstraint doPropagateAfterConstraint(AfterIntervalConstraint after) 
951
			throws InconsistentDistanceConstraintException {
952
		
953
		// create constraint
954
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
955
		c.setReference(after.getTarget().getEndTime());
956
		c.setTarget(after.getReference().getStartTime());
957
		c.setDistanceLowerBound(after.getLowerBound());
958
		c.setDistanceUpperBound(after.getUpperBound());
959
		c.setControllable(true);
960
		
961
		// add constraint
962
		this.tn.addDistanceConstraint(c);
963
		// get propagated constraint
964
		return c;
965
	}
966
	
967
	/**
968
	 * 
969
	 * @param metby
970
	 * @return
971
	 * @throws InconsistentDistanceConstraintException
972
	 */
973
	protected TimePointDistanceConstraint doPropagateMetByConstraint(MetByIntervalConstraint metby) 
974
			throws InconsistentDistanceConstraintException {
975
		
976
		// create constraint
977
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
978
		c.setReference(metby.getTarget().getEndTime());
979
		c.setTarget(metby.getReference().getStartTime());
980
		c.setDistanceLowerBound(0);
981
		c.setDistanceUpperBound(0);
982
		c.setControllable(true);
983
		
984
		// add constraint
985
		this.tn.addDistanceConstraint(c);
986
		// get propagated constraint
987
		return c;
988
	}
989
	
990
	/**
991
	 * 
992
	 * @param fix
993
	 * @return
994
	 * @throws InconsistentDistanceConstraintException
995
	 */
996
	protected TimePointDistanceConstraint doPropagateFixTimePointConstraint(FixTimePointConstraint fix) 
997
			throws InconsistentDistanceConstraintException {
998
		
999
		// create constraint
1000
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
1001
		c.setReference(this.tn.getOriginTimePoint());
1002
		c.setTarget(fix.getReference());
1003
		c.setDistanceLowerBound(fix.getTime());
1004
		c.setDistanceUpperBound(fix.getTime());
1005
		c.setControllable(true);
1006
		
1007
		// add constraint
1008
		this.tn.addDistanceConstraint(c);
1009
		// get propagated constraint
1010
		return c;
1011
	}
1012
1013
	/**
1014
	 * 
1015
	 * @param reference
1016
	 * @param duration
1017
	 * @return
1018
	 * @throws InconsistentDistanceConstraintException
1019
	 */
1020
	protected TimePointDistanceConstraint doPropagateFixIntervalDurationConstraint(FixIntervalDurationConstraint fix) 
1021
			throws InconsistentDistanceConstraintException {
1022
		
1023
		// create constraint
1024
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
1025
		c.setReference(fix.getReference().getStartTime());
1026
		c.setTarget(fix.getReference().getEndTime());
1027
		c.setDistanceLowerBound(fix.getDuration());
1028
		c.setDistanceUpperBound(fix.getDuration());
1029
		c.setControllable(true);
1030
		
1031
		// add constraint
1032
		this.tn.addDistanceConstraint(c);
1033
		// get propagated constraint
1034
		return c;
1035
	}
1036
	
1037
	/**
1038
	 * This method checks if the STNU is pseudo-controllable. 
1039
	 * 
1040
	 *	This procedure checks if contingent links have been "squeezed"
1041
	 *	so, the STNU is pseudo-controllable if no assumption has been 
1042
	 *	made on the duration of uncontrollable constraints (i.e. contingent
1043
	 *	links).
1044
	 *
1045
	 * @return
1046
	 */
1047
	private boolean isPseudoControllable() {
1048
		
1049
		// hypothesis
1050
		boolean pseudoControllable = true;
1051
		
1052
		// get constraints
1053
		for (TimePointDistanceConstraint constraint : this.tn.getContingentConstraints()) {
1054
			
1055
			// check contingent constraints
1056
			if (!constraint.isControllable()) {
1057
				
1058
				// create query
1059
				TimePointDistanceQuery query = this.qf.create(TemporalQueryType.TP_DISTANCE);
1060
				query.setSource(constraint.getReference());
1061
				query.setTarget(constraint.getTarget());
1062
				// process query
1063
				this.solver.process(query);
1064
				
1065
				// get actual bounds
1066
				long dmin = query.getDistanceLowerBound();
1067
				long dmax = query.getDistanceUpperBound();
1068
				
1069
				// check duration
1070
				pseudoControllable = !(dmin > constraint.getDistanceLowerBound() || dmax < constraint.getDistanceUpperBound());
1071
			}
1072
			
1073
			// check if pseudo-controllable
1074
			if (!pseudoControllable) {
1075
				break;
1076
			}
1077
		}
1078
				
1079
		// get result
1080
		return pseudoControllable;
1081
	}
1082
1083
	/**
1084
	 * 
1085
	 * For debugging only
1086
	 * 
1087
	 */
1088
	public void printDiagnosticData() {
1089
		this.tn.printDiagnosticData();
1090
		this.solver.printDiagnosticData();
1091
	}
1092
}
1093