Passed
Push — master ( 1f3b93...63f895 )
by Alessandro
09:41
created

isPseudoControllable()   A

Complexity

Conditions 4

Size

Total Lines 34
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 14
dl 0
loc 34
rs 9.7
c 0
b 0
f 0
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
	 * @param type
340
	 * @return
341
	 */
342
	public synchronized <T extends TemporalQuery> T createTemporalQuery(TemporalQueryType type) {
343
		// query instance
344
		T query = this.qf.create(type);
345
		// get created instance
346
		return query;
347
	}
348
	
349
	/**
350
	 * 
351
	 * @param type
352
	 * @return
353
	 */
354
	public synchronized <T extends TemporalConstraint> T createTemporalConstraint(TemporalConstraintType type) {
355
		// create constraint
356
		T cons = this.cf.create(type);
357
		// get created constraint
358
		return cons;
359
	}
360
	
361
	/**
362
	 * 
363
	 */
364
	@Override
365
	public synchronized void process(TemporalQuery query) 
366
	{
367
		// check query type
368
		switch (query.getType()) 
369
		{
370
			// check distance between intervals
371
			case INTERVAL_DISTANCE : 
372
			{
373
				// get query
374
				IntervalDistanceQuery dQuery = (IntervalDistanceQuery) query;
375
				// get intervals
376
				TemporalInterval a = dQuery.getSource();
377
				TemporalInterval b = dQuery.getTarget();
378
				// create time point query
379
				TimePointDistanceQuery tpQuery = this.qf.create(TemporalQueryType.TP_DISTANCE);
380
				// set source and target
381
				tpQuery.setSource(a.getEndTime());
382
				tpQuery.setTarget(b.getStartTime());
383
				// process query
384
				this.solver.process(tpQuery);
385
				// set bounds
386
				dQuery.setDistanceLowerBound(tpQuery.getDistanceLowerBound());
387
				dQuery.setDistanceUpperBOund(tpQuery.getDistanceUpperBound());
388
			}
389
			break;
390
			
391
			// check overlapping intervals
392
			case INTERVAL_OVERLAP :
393
			{
394
				// get query
395
				IntervalOverlapQuery overlap = (IntervalOverlapQuery) query;
396
				// get intervals
397
				TemporalInterval a = overlap.getReference();
398
				TemporalInterval b = overlap.getTarget();
399
				
400
				// check the distance between the time point of A and the start time point of B
401
				TimePointDistanceQuery eAsB = this.qf.create(TemporalQueryType.TP_DISTANCE);
402
				eAsB.setSource(a.getEndTime());
403
				eAsB.setTarget(b.getStartTime());
404
				// process query
405
				this.process(eAsB);
406
				// check computed bounds
407
				long dmin = eAsB.getDistanceLowerBound();
408
				long dmax = eAsB.getDistanceUpperBound();
409
				// check if can overlap
410
				boolean o1 = !((dmin <= 0 && dmax <= 0) || (dmin >= 0 && dmax >= 0));
411
				
412
				
413
				// get intervals
414
				a = overlap.getTarget();
415
				b = overlap.getReference();
416
				
417
				// check the distance between the time point of A and the start time point of B
418
				TimePointDistanceQuery eBsA = this.qf.create(TemporalQueryType.TP_DISTANCE);
419
				eBsA.setSource(a.getEndTime());
420
				eBsA.setTarget(b.getStartTime());
421
				// process query
422
				this.process(eBsA);
423
				// check computed bounds
424
				dmin = eBsA.getDistanceLowerBound();
425
				dmax = eBsA.getDistanceUpperBound();
426
				// check if can overlap
427
				boolean o2 = !((dmin <= 0 && dmax <= 0) || (dmin >= 0 && dmax >= 0));
428
				
429
		
430
				// set result
431
				overlap.setCanOverlap(o1 || o2);
432
				// print logging message
433
				debug("[" + this.getClass().getName() + "] Processing query INTERVAL_OVERLAP:\n"
434
						+ "- Temporal Interval (A): " + a + "\n"
435
						+ "- Temporal Interval (B): " + b + "\n"
436
						+ "- Computed (flexible) distance: [dmin= " + dmin + ", dmax= " + dmax +"]\n"
437
						+ "- Answer to query: " + overlap.canOverlap());
438
			}
439
			break;
440
			
441
			// check interval schedule 
442
			case INTERVAL_SCHEDULE : 
443
			{
444
				// get query
445
				IntervalScheduleQuery scheduleQuery = (IntervalScheduleQuery) query;
446
				// get interval
447
				TemporalInterval i = scheduleQuery.getInterval();
448
				
449
				// create time point bound query
450
				TimePointScheduleQuery sQuery = this.qf.create(TemporalQueryType.TP_SCHEDULE);
451
				// set point 
452
				sQuery.setTimePoint(i.getStartTime());
453
				// check start schedule
454
				this.solver.process(sQuery);
455
				
456
				// process end time
457
				TimePointScheduleQuery eQuery = this.qf.create(TemporalQueryType.TP_SCHEDULE);
458
				// set point
459
				eQuery.setTimePoint(i.getEndTime());
460
				// check end schedule
461
				this.solver.process(eQuery);
462
				
463
				// check time point distance
464
				TimePointDistanceQuery dQuery= this.qf.create(TemporalQueryType.TP_DISTANCE);
465
				// set points
466
				dQuery.setSource(i.getStartTime());
467
				dQuery.setTarget(i.getEndTime());
468
				// process query
469
				this.solver.process(dQuery);
470
				
471
				// set interval duration
472
				i.setDurationLowerBound(dQuery.getDistanceLowerBound());
473
				i.setDurationUpperBound(dQuery.getDistanceUpperBound());
474
			}
475
			break;
476
			
477
			// check if squeezed interval
478
			case INTERVAL_PSEUDO_CONTROLLABILITY : 
479
			{
480
				// get query
481
				IntervalPseudoControllabilityQuery pseudoQuery = (IntervalPseudoControllabilityQuery) query;
482
				// get temporal interval
483
				TemporalInterval i = pseudoQuery.getInterval();
484
				// check the schedule
485
				IntervalScheduleQuery squery = this.qf.create(TemporalQueryType.INTERVAL_SCHEDULE);
486
				squery.setInterval(i);
487
				this.process(squery);
488
				// check if pseudo-controllability condition
489
				pseudoQuery.setPseudoControllable(i.getDurationLowerBound() == i.getNominalDurationLowerBound() && 
490
						i.getDurationUpperBound() == i.getNominalDurationUpperBound());
491
			}
492
			break;
493
			
494
			// time point queries
495
			case TP_SCHEDULE :
496
			case TP_DISTANCE : 
497
			case TP_DISTANCE_TO_HORIZON : {
498
				
499
				// propagate time point query to the reasoner
500
				this.solver.process((TimePointQuery) query);
501
			}
502
			break;
503
		}
504
	}
505
	
506
	/**
507
	 * This method propagates an interval constraint to the underlying temporal network.
508
	 * 
509
	 * When propagating constraints no contingent link can be affected or overwritten. Thus,
510
	 * the method throws an exception if a contingent link is affected by the propagated 
511
	 * constraint.
512
	 * 
513
	 * @param constraint
514
	 * @throws Exception
515
	 */
516
	public synchronized void propagate(TemporalConstraint constraint) 
517
			throws TemporalConstraintPropagationException 
518
	{
519
		try 
520
		{
521
			// check temporal constraint type
522
			switch (constraint.getType()) 
523
			{
524
				// create BEFORE constraint into the temporal network
525
				case BEFORE : 
526
				{
527
					// get constraint
528
					BeforeIntervalConstraint before = (BeforeIntervalConstraint) constraint;
529
					// propagate constraint
530
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] { 
531
						this.doPropagateBeforeConstraint(before)
532
					};
533
					
534
					// set propagated constraint
535
					before.setPropagatedConstraints(c);
536
				}
537
				break;
538
				
539
				// create AFTER constraint into the temporal network
540
				case AFTER : 
541
				{
542
					AfterIntervalConstraint after = (AfterIntervalConstraint) constraint;
543
					// propagate constraint
544
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] {
545
						this.doPropagateAfterConstraint(after)
546
					};
547
					// set propagated constraint
548
					after.setPropagatedConstraints(c);
549
				}
550
				break;
551
				
552
				// create MEETS constraint into the temporal network
553
				case MEETS : 
554
				{
555
					// get constraint
556
					MeetsIntervalConstraint meets = (MeetsIntervalConstraint) constraint;
557
					// propagate constraint
558
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] { 
559
							this.doPropagateMeetsConstraint(meets)	
560
					};
561
					// set propagated constraints
562
					meets.setPropagatedConstraints(c);
563
				}
564
				break;
565
				
566
				// create MET-BY constraint into the temporal network
567
				case MET_BY : 
568
				{
569
					// get constraint
570
					MetByIntervalConstraint metby = (MetByIntervalConstraint) constraint;
571
					// propagate constraint
572
					TimePointDistanceConstraint[] c = new TimePointDistanceConstraint[] {
573
							this.doPropagateMetByConstraint(metby)
574
					};
575
					// set propagated constraints
576
					metby.setPropagatedConstraints(c);
577
				}
578
				break;
579
				
580
				// create CONTAINS constraint into the temporal network
581
				case CONTAINS : 
582
				{
583
					// get constraint
584
					ContainsIntervalConstraint contains = (ContainsIntervalConstraint) constraint;
585
					// propagate constraint
586
					TimePointDistanceConstraint[] c = this.doPropagateContainsConstraint(contains);
587
					// set propagated constraints
588
					contains.setPropagatedConstraints(c);
589
				}
590
				break;
591
				
592
				// create DURING constraint into the temporal network
593
				case DURING : 
594
				{
595
					// get constraint
596
					DuringIntervalConstraint during = (DuringIntervalConstraint) constraint;
597
					// propagate constraint
598
					TimePointDistanceConstraint[] c = this.doPropagateDuringConstraint(during);
599
					// set propagated constraints
600
					during.setPropagatedConstraints(c);
601
				}
602
				break;
603
				
604
				// create STARTS-DURING constraint into the network
605
				case STARTS_DURING : 
606
				{
607
					// get constraint
608
					StartsDuringIntervalConstraint sdc = (StartsDuringIntervalConstraint) constraint;
609
					// propagate constraint
610
					TimePointDistanceConstraint[] c = this.doPropagateStartsDuringConstraint(sdc);
611
					// set propagated constraints
612
					sdc.setPropagatedConstraints(c);
613
				}
614
				break;
615
				
616
				// create ENDS-DURING constraint into the network
617
				case ENDS_DURING : 
618
				{
619
					// get constraint
620
					EndsDuringIntervalConstraint edc = (EndsDuringIntervalConstraint) constraint;
621
					// propagate constraint
622
					TimePointDistanceConstraint[] c = this.doPropagateEndsDuringConstraint(edc);
623
					// set propagated constraints
624
					edc.setPropagatedConstraints(c);
625
				}
626
				break;
627
				
628
				// create EQUALS constraint into the temporal network
629
				case EQUALS : 
630
				{
631
					// get constraint
632
					EqualsIntervalConstraint equals = (EqualsIntervalConstraint) constraint;
633
					// propagate constraint
634
					TimePointDistanceConstraint[] c = this.doPropagateEqualsConstraint(equals);
635
					// set propagated constraint
636
					equals.setPropagatedConstraints(c);
637
				}
638
				break;
639
				
640
				// set the duration of a temporal interval
641
				case FIX_INTERVAL_DURATION : 
642
				{
643
					// get constraint
644
					FixIntervalDurationConstraint fix = (FixIntervalDurationConstraint) constraint;
645
					// propagate constraint
646
					TimePointDistanceConstraint c = this.doPropagateFixIntervalDurationConstraint(fix);
647
					// set propagate constraints
648
					fix.setPropagatedConstraints(new TimePointDistanceConstraint[] {c});
649
				}
650
				break;
651
				
652
				// schedule a time point at a given time
653
				case FIX_TIME_POINT :
654
				{
655
					// get constraint
656
					FixTimePointConstraint fix = (FixTimePointConstraint) constraint;
657
					// propagate constraint
658
					TimePointDistanceConstraint c = this.doPropagateFixTimePointConstraint(fix);
659
					// set propagated constraint
660
					fix.setPropagatedConstraints(new TimePointDistanceConstraint[] {c});
661
				}
662
				break;
663
				
664
				// set a distance constraint between two time points
665
				case TIME_POINT_DISTANCE :
666
				{
667
					// get constraint
668
					TimePointDistanceConstraint cons = (TimePointDistanceConstraint) constraint;
669
					// directly propagate distance constraint to the temporal network
670
					this.tn.addDistanceConstraint(cons);
671
				}
672
				break;
673
				
674
				default : { 
675
					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...
676
				}
677
			}
678
		}
679
		catch (InconsistentDistanceConstraintException ex) {
680
			throw new TemporalConstraintPropagationException(ex.getMessage());
681
		}
682
	}
683
684
	/**
685
	 * 
686
	 * @param constraint
687
	 * @throws Exception
688
	 */
689
	public synchronized void retract(TemporalConstraint constraint) {
690
		// retract propagated constraints
691
		TimePointDistanceConstraint[] toRetract = constraint.getPropagatedConstraints();
692
		// verify whether some constraints have been propagated
693
		if (toRetract != null) {
694
			// remove propagated distance constraints
695
			this.tn.removeDistanceConstraint(Arrays.asList(toRetract));
696
			// clear data structure
697
			constraint.clear();
698
		}
699
	}
700
	
701
	/**
702
	 * 
703
	 */
704
	@Override
705
	public String toString() {
706
		return "\nTemporal Network:\n"
707
				+ "" + this.tn.toString() + "\n"
708
				+ "--------------\n"
709
				+ "Solver:\n"
710
				+ "" + this.solver.toString() + "\n\n";
711
	}
712
	
713
	/**
714
	 * 
715
	 * @param equals
716
	 * @return
717
	 * @throws InconsistentDistanceConstraintException
718
	 */
719
	protected TimePointDistanceConstraint[] doPropagateEqualsConstraint(EqualsIntervalConstraint equals) 
720
			throws InconsistentDistanceConstraintException {
721
		
722
		// create distance constraint 
723
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
724
		// set constraint data
725
		c1.setReference(equals.getReference().getStartTime());
726
		c1.setTarget(equals.getTarget().getStartTime());
727
		c1.setDistanceLowerBound(0);
728
		c1.setDistanceUpperBound(0);
729
		c1.setControllable(true);
730
		
731
		// create distance constraint
732
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
733
		// set constraint data
734
		c2.setReference(equals.getReference().getEndTime());
735
		c2.setTarget(equals.getTarget().getEndTime());
736
		c2.setDistanceLowerBound(0);
737
		c2.setDistanceUpperBound(0);
738
		c2.setControllable(true);
739
		
740
		// add constraints
741
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
742
		// get added distance constraints
743
		return new TimePointDistanceConstraint[] {c1, c2};
744
	}
745
746
	/**
747
	 * 
748
	 * @param contains
749
	 * @return
750
	 * @throws InconsistentDistanceConstraintException
751
	 */
752
	protected TimePointDistanceConstraint[] doPropagateContainsConstraint(ContainsIntervalConstraint contains) 
753
			throws InconsistentDistanceConstraintException {
754
		
755
		// create distance constraint
756
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
757
		// set data
758
		c1.setReference(contains.getReference().getStartTime());
759
		c1.setTarget(contains.getTarget().getStartTime());
760
		c1.setDistanceLowerBound(contains.getFirstBound()[0]);
761
		c1.setDistanceUpperBound(contains.getFirstBound()[1]);
762
		c1.setControllable(true);
763
		
764
		// create distance constraint
765
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
766
		// set data
767
		c2.setReference(contains.getTarget().getEndTime());
768
		c2.setTarget(contains.getReference().getEndTime());
769
		c2.setDistanceLowerBound(contains.getSecondBound()[0]);
770
		c2.setDistanceUpperBound(contains.getSecondBound()[1]);
771
		c2.setControllable(true);
772
		
773
		// add constraints
774
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
775
		// get added constraints
776
		return new TimePointDistanceConstraint[] {c1, c2};
777
	}
778
779
	/**
780
	 * 
781
	 * @param during
782
	 * @return
783
	 * @throws InconsistentDistanceConstraintException
784
	 */
785
	protected TimePointDistanceConstraint[] doPropagateDuringConstraint(DuringIntervalConstraint during) 
786
			throws InconsistentDistanceConstraintException {
787
		
788
		// create constraint
789
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
790
		c1.setReference(during.getTarget().getStartTime());
791
		c1.setTarget(during.getReference().getStartTime());
792
		c1.setDistanceLowerBound(during.getFirstBound()[0]);
793
		c1.setDistanceUpperBound(during.getFirstBound()[1]);
794
		c1.setControllable(true);
795
		
796
		// create constraint
797
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
798
		c2.setReference(during.getReference().getEndTime());
799
		c2.setTarget(during.getTarget().getEndTime());
800
		c2.setDistanceLowerBound(during.getSecondBound()[0]);
801
		c2.setDistanceUpperBound(during.getSecondBound()[1]);
802
		c2.setControllable(true);
803
				
804
		// add constraint
805
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
806
		// get added constraints
807
		return new TimePointDistanceConstraint[] {c1, c2};
808
	}
809
	
810
	/**
811
	 * 
812
	 * @param edc
813
	 * @return
814
	 * @throws InconsistentDistanceConstraintException
815
	 */
816
	protected TimePointDistanceConstraint[] doPropagateEndsDuringConstraint(EndsDuringIntervalConstraint edc) 
817
			throws InconsistentDistanceConstraintException {
818
		
819
		// create constraint
820
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
821
		c1.setReference(edc.getTarget().getStartTime());
822
		c1.setTarget(edc.getReference().getEndTime());
823
		c1.setDistanceLowerBound(edc.getFirstTimeBound()[0]);
824
		c1.setDistanceUpperBound(edc.getFirstTimeBound()[1]);
825
		c1.setControllable(true);
826
		
827
		// create constraint
828
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
829
		c2.setReference(edc.getReference().getEndTime());
830
		c2.setTarget(edc.getTarget().getEndTime());
831
		c2.setDistanceLowerBound(edc.getSecondTimeBound()[0]);
832
		c2.setDistanceUpperBound(edc.getSecondTimeBound()[1]);
833
		c2.setControllable(true);
834
		
835
		// add constraint 
836
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
837
		// propagate constraints
838
		return new TimePointDistanceConstraint[] {c1, c2};
839
	}
840
841
	/**
842
	 * 
843
	 * @param sdc
844
	 * @return
845
	 * @throws InconsistentDistanceConstraintException
846
	 */
847
	protected TimePointDistanceConstraint[] doPropagateStartsDuringConstraint(StartsDuringIntervalConstraint sdc) 
848
			throws InconsistentDistanceConstraintException 
849
	{
850
		// create constraint
851
		TimePointDistanceConstraint c1 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
852
		c1.setReference(sdc.getTarget().getStartTime());
853
		c1.setTarget(sdc.getReference().getStartTime());
854
		c1.setDistanceLowerBound(sdc.getFirstTimeBound()[0]);
855
		c1.setDistanceUpperBound(sdc.getFirstTimeBound()[1]);
856
		c1.setControllable(true);
857
		
858
		// create constraint
859
		TimePointDistanceConstraint c2 = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE); 
860
		c2.setReference(sdc.getReference().getStartTime());
861
		c2.setTarget(sdc.getTarget().getEndTime());
862
		c2.setDistanceLowerBound(sdc.getSecondTimeBound()[0]);
863
		c2.setDistanceUpperBound(sdc.getSecondTimeBound()[1]);
864
		c2.setControllable(true);
865
		
866
		// add constraint
867
		this.tn.addDistanceConstraint(new TimePointDistanceConstraint[] {c1, c2});
868
		// propagate constraints
869
		return new TimePointDistanceConstraint[] {c1, c2};
870
	}
871
872
	/**
873
	 * 
874
	 * @param before
875
	 * @return
876
	 * @throws InconsistentDistanceConstraintException
877
	 */
878
	protected TimePointDistanceConstraint doPropagateBeforeConstraint(BeforeIntervalConstraint before)
879
			throws InconsistentDistanceConstraintException {
880
		
881
		// create constraint
882
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
883
		c.setReference(before.getReference().getEndTime());
884
		c.setTarget(before.getTarget().getStartTime());
885
		c.setDistanceLowerBound(before.getLowerBound());
886
		c.setDistanceUpperBound(before.getUpperBound());
887
		c.setControllable(true);
888
		
889
		// add constraint
890
		this.tn.addDistanceConstraint(c);
891
		// get propagated constraint
892
		return c;
893
	}
894
	
895
	/**
896
	 * 
897
	 * @param meets
898
	 * @return
899
	 * @throws InconsistentDistanceConstraintException
900
	 */
901
	protected TimePointDistanceConstraint doPropagateMeetsConstraint(MeetsIntervalConstraint meets) 
902
			throws InconsistentDistanceConstraintException {
903
		
904
		// create constraint
905
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
906
		c.setReference(meets.getReference().getEndTime());
907
		c.setTarget(meets.getTarget().getStartTime());
908
		c.setDistanceLowerBound(0);
909
		c.setDistanceUpperBound(0);
910
		c.setControllable(true);
911
		
912
		// add constraint
913
		this.tn.addDistanceConstraint(c);
914
		// get propagated constraint
915
		return c;
916
	}
917
	
918
	/**
919
	 * 
920
	 * @param after
921
	 * @return
922
	 * @throws InconsistentDistanceConstraintException
923
	 */
924
	protected TimePointDistanceConstraint doPropagateAfterConstraint(AfterIntervalConstraint after) 
925
			throws InconsistentDistanceConstraintException {
926
		
927
		// create constraint
928
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
929
		c.setReference(after.getTarget().getEndTime());
930
		c.setTarget(after.getReference().getStartTime());
931
		c.setDistanceLowerBound(after.getLowerBound());
932
		c.setDistanceUpperBound(after.getUpperBound());
933
		c.setControllable(true);
934
		
935
		// add constraint
936
		this.tn.addDistanceConstraint(c);
937
		// get propagated constraint
938
		return c;
939
	}
940
	
941
	/**
942
	 * 
943
	 * @param metby
944
	 * @return
945
	 * @throws InconsistentDistanceConstraintException
946
	 */
947
	protected TimePointDistanceConstraint doPropagateMetByConstraint(MetByIntervalConstraint metby) 
948
			throws InconsistentDistanceConstraintException {
949
		
950
		// create constraint
951
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
952
		c.setReference(metby.getTarget().getEndTime());
953
		c.setTarget(metby.getReference().getStartTime());
954
		c.setDistanceLowerBound(0);
955
		c.setDistanceUpperBound(0);
956
		c.setControllable(true);
957
		
958
		// add constraint
959
		this.tn.addDistanceConstraint(c);
960
		// get propagated constraint
961
		return c;
962
	}
963
	
964
	/**
965
	 * 
966
	 * @param fix
967
	 * @return
968
	 * @throws InconsistentDistanceConstraintException
969
	 */
970
	protected TimePointDistanceConstraint doPropagateFixTimePointConstraint(FixTimePointConstraint fix) 
971
			throws InconsistentDistanceConstraintException {
972
		
973
		// create constraint
974
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
975
		c.setReference(this.tn.getOriginTimePoint());
976
		c.setTarget(fix.getReference());
977
		c.setDistanceLowerBound(fix.getTime());
978
		c.setDistanceUpperBound(fix.getTime());
979
		c.setControllable(true);
980
		
981
		// add constraint
982
		this.tn.addDistanceConstraint(c);
983
		// get propagated constraint
984
		return c;
985
	}
986
987
	/**
988
	 * 
989
	 * @param reference
990
	 * @param duration
991
	 * @return
992
	 * @throws InconsistentDistanceConstraintException
993
	 */
994
	protected TimePointDistanceConstraint doPropagateFixIntervalDurationConstraint(FixIntervalDurationConstraint fix) 
995
			throws InconsistentDistanceConstraintException {
996
		
997
		// create constraint
998
		TimePointDistanceConstraint c = this.cf.create(TemporalConstraintType.TIME_POINT_DISTANCE);
999
		c.setReference(fix.getReference().getStartTime());
1000
		c.setTarget(fix.getReference().getEndTime());
1001
		c.setDistanceLowerBound(fix.getDuration());
1002
		c.setDistanceUpperBound(fix.getDuration());
1003
		c.setControllable(true);
1004
		
1005
		// add constraint
1006
		this.tn.addDistanceConstraint(c);
1007
		// get propagated constraint
1008
		return c;
1009
	}
1010
	
1011
	/**
1012
	 * This method checks if the STNU is pseudo-controllable. 
1013
	 * 
1014
	 *	This procedure checks if contingent links have been "squeezed"
1015
	 *	so, the STNU is pseudo-controllable if no assumption has been 
1016
	 *	made on the duration of uncontrollable constraints (i.e. contingent
1017
	 *	links).
1018
	 *
1019
	 * @return
1020
	 */
1021
	private boolean isPseudoControllable() {
1022
		
1023
		// hypothesis
1024
		boolean pseudoControllable = true;
1025
		
1026
		// get constraints
1027
		for (TimePointDistanceConstraint constraint : this.tn.getContingentConstraints()) {
1028
			
1029
			// check contingent constraints
1030
			if (!constraint.isControllable()) {
1031
				
1032
				// create query
1033
				TimePointDistanceQuery query = this.qf.create(TemporalQueryType.TP_DISTANCE);
1034
				query.setSource(constraint.getReference());
1035
				query.setTarget(constraint.getTarget());
1036
				// process query
1037
				this.solver.process(query);
1038
				
1039
				// get actual bounds
1040
				long dmin = query.getDistanceLowerBound();
1041
				long dmax = query.getDistanceUpperBound();
1042
				
1043
				// check duration
1044
				pseudoControllable = !(dmin > constraint.getDistanceLowerBound() || dmax < constraint.getDistanceUpperBound());
1045
			}
1046
			
1047
			// check if pseudo-controllable
1048
			if (!pseudoControllable) {
1049
				break;
1050
			}
1051
		}
1052
				
1053
		// get result
1054
		return pseudoControllable;
1055
	}
1056
1057
	/**
1058
	 * 
1059
	 * For debugging only
1060
	 * 
1061
	 */
1062
	public void printDiagnosticData() {
1063
		this.tn.printDiagnosticData();
1064
		this.solver.printDiagnosticData();
1065
	}
1066
}
1067