1 /*
2  * Tableau.cpp
3  *
4  *  Created on: May 28, 2014
5  *      Author: nicola
6  */
7 
8 #include "Tableau.h"
9 
10 namespace ctl_sat {
11 
sign(Formula * f)12 int sign(Formula * f){
13 	if(f->getType()==NEGATION)
14 		return -1;
15 
16 	return 1;
17 }
18 
~Tableau()19 Tableau::~Tableau() {}
20 
Tableau(Formula * f)21 Tableau::Tableau(Formula * f){//builds the tableau for formula f
22 
23 	//firstly, positive closure set is computed. Here there are only positive formulas (i.e. not negations). formulas must be sorted and copies must be removed.
24 	positive_closure = f->positiveClosure();
25 
26 	//sort positive closure set
27 	std::sort (positive_closure->begin(), positive_closure->end(), formulaLessThan);
28 
29 	//remove duplicates and resize
30 	positive_closure->resize( std::distance(positive_closure->begin(),
31 			std::unique (positive_closure->begin(), positive_closure->end(), formulaEqual)) );
32 
33 	cout << "Positive closure set (only non-negated formulas in the closure set):\n";
34 
35 	for(uint i=0;i<positive_closure->size();i++)
36 		cout << (i+1) << ".  " << positive_closure->at(i)->toString()<<endl;
37 
38 	cout << "\nClosure set has size " << positive_closure->size()*2<< ". \n\nBuilding initial feasible states of the tableau ... "<< endl;
39 
40 	computeSubFormulas();
41 
42 	formula_index orig_position = indexOf(f);//position of the original formula f in positive form in the positive closure
43 
44 	if(f->getType()==NEGATION)
45 		initial_formula = indexToNegativeFormula(orig_position);
46 	else
47 		initial_formula = indexToPositiveFormula(orig_position);
48 
49 	states = vector<state>();
50 	buildFeasibleStates();
51 
52 	number_of_states = states.size();
53 
54 	//these vectors mark formulas that are globally valid in a state (i.e. they have been previously checked and we don't need to check them again)
55 	globally_satisfied_formulas_positive = vector<state>(number_of_states);
56 	globally_satisfied_formulas_negative = vector<state>(number_of_states);
57 
58 	//visited_during_mark_removal = vector<bool>(number_of_states,false);
59 
60 	for(uint i=0;i<number_of_states;++i){
61 
62 		globally_satisfied_formulas_positive[i] = newState();
63 		globally_satisfied_formulas_negative[i] = newState();
64 
65 	}
66 
67 
68 	cout << "done. Initial model has " << number_of_states << " states"<<endl<<endl;
69 
70 	isRemoved =  vector<bool>(states.size());//tracks removed states
71 
72 	for(ulint i=0;i<states.size();i++)
73 		isRemoved.at(i)=false;
74 
75 	status = new state_status[states.size()];
76 	mark_timestamps.assign(states.size(),0);
77 
78 	//now build edges
79 
80 	cout << "Building initial feasible edges of the tableau ... "<< endl;
81 
82 	edges = vector<set<uint> >(states.size());
83 	back_edges = vector<set<uint> >(states.size());
84 
85 	buildEdges();
86 	cout << "done. Initial model has " << number_of_edges << " edges"<<endl<<endl;
87 
88 	//count how many states have the original formula
89 
90 	number_of_states_with_original_formula=0;
91 	for(uint i=0;i<states.size();i++)//for all states
92 		if(belongsTo(states.at(i),initial_formula))//if the original formula is in the state
93 			number_of_states_with_original_formula++;
94 
95 	//Now apply repeated cull.
96 	//culls are divided in 3 categories: easy, medium, hard:
97 	//easy: EXT, EX, ENX
98 	//medium: EU, ENU
99 	//hard: AU, ANU
100 	//heuristic:
101 	//1) firstly, apply only easy culls until it is no more possible to apply them
102 	//2) then, apply medium culls together with easy culls until is no more possible to apply medium/easy culls
103 	//3) at this point, try with the hard culls. Once a hard cull has been executed, restart from 1)
104 	//repeat until no more culls are possible.
105 	//when a state is removed, its predecessors are checked (and so on, recursively)
106 
107 	cout << "Applying repeated cull ..."<< endl;
108 	timestamp=time(0);
109 	last_time_printed=(ulint)timestamp+1;
110 	cull();
111 	cout << "\ndone. Number of states left : " << number_of_states <<endl<<endl;
112 
113 	/*cout << endl;
114 	for(uint i=0;i<states.size();i++){
115 
116 		cout << "State nr " << i << "\nedges : ";
117 
118 		for(uint j=0;j<edges.at(i).size();j++)
119 			cout << j << " ";
120 
121 		cout << "\nREMOVED? " << isRemoved.at(i) << endl;
122 
123 		printState(states.at(i));
124 		cout << endl;
125 	}
126 	cout << endl;*/
127 
128 }
129 
clearMarked()130 void Tableau::clearMarked(){
131 
132 	current_timestamp=0;
133 
134 	for(ulint i=0;i<states.size();i++){
135 		status[i] = NOT_VISITED;
136 		mark_timestamps[i]=0;
137 	}
138 }
139 
computeSubFormulas()140 void Tableau::computeSubFormulas(){
141 
142 	leftSubformula = new vector<int>(positive_closure->size());
143 		rightSubformula = new vector<int>(positive_closure->size());
144 
145 		for(uint i=0;i<positive_closure->size();i++){
146 
147 			switch(positive_closure->at(i)->getType()){
148 
149 				case ATOMIC: /*no subformulas*/ break;
150 
151 				case NEGATION:
152 					leftSubformula->at(i) = sign(positive_closure->at(i)->getSubFormula())*(indexOf(positive_closure->at(i)->getSubFormula())+1); break;
153 
154 				case CONJUNCTION:
155 					leftSubformula->at(i) = sign(positive_closure->at(i)->getLeftSubFormula())*(indexOf(positive_closure->at(i)->getLeftSubFormula())+1);
156 					rightSubformula->at(i) = sign(positive_closure->at(i)->getRightSubFormula())*(indexOf(positive_closure->at(i)->getRightSubFormula())+1); break;
157 
158 				case ALL_TOMORROW:
159 					leftSubformula->at(i) = sign(positive_closure->at(i)->getSubFormula())*(indexOf(positive_closure->at(i)->getSubFormula())+1); break;
160 
161 				case EXISTS_TOMORROW:
162 					leftSubformula->at(i) = sign(positive_closure->at(i)->getSubFormula())*(indexOf(positive_closure->at(i)->getSubFormula())+1); break;
163 
164 				case ALL_UNTIL:
165 					leftSubformula->at(i) = sign(positive_closure->at(i)->getLeftSubFormula())*(indexOf(positive_closure->at(i)->getLeftSubFormula())+1);
166 					rightSubformula->at(i) = sign(positive_closure->at(i)->getRightSubFormula())*(indexOf(positive_closure->at(i)->getRightSubFormula())+1); break;
167 
168 				case EXISTS_UNTIL:
169 					leftSubformula->at(i) = sign(positive_closure->at(i)->getLeftSubFormula())*(indexOf(positive_closure->at(i)->getLeftSubFormula())+1);
170 					rightSubformula->at(i) = sign(positive_closure->at(i)->getRightSubFormula())*(indexOf(positive_closure->at(i)->getRightSubFormula())+1); break;
171 
172 			}
173 
174 		}
175 
176 }
177 
newState()178 state Tableau::newState(){
179 
180 	//each state is a vector of bools with one bit for every formula in positive_closure_set. if the bit is 1, the formula appears
181 	//in positive form; otherwise, it appears in negative form (negated)
182 
183 	state x = vector<bool>(positive_closure->size(),false);
184 
185 	return x;
186 
187 }
188 
indexOf(Formula * f)189 uint Tableau::indexOf(Formula * f){//returns index of the formula f in closure_set. Linear-time, but used only at the beginning while constructing closure set
190 
191 	//assumption: f in positive form is in positive_closure
192 
193 	Formula * f1 = f;
194 
195 	if(f->getType()==NEGATION)
196 		f1 = f->getSubFormula();
197 
198 	uint idx=0;
199 	while(idx < positive_closure->size() and *(positive_closure->at(idx))!=(*f1))
200 		idx++;
201 
202 	return idx;
203 
204 }
205 
printState(state B)206 void Tableau::printState(state B){
207 
208 	for(uint i=0;i<B.size();i++){
209 		cout << (B.at(i)==0?"NOT ":" ") << positive_closure->at(i)->toString() <<endl;
210 	}
211 
212 }
213 
buildFeasibleStates()214 void Tableau::buildFeasibleStates(){
215 
216 	state inserted = newState();//tracks if the formula number i has been inserted (1) or not (0)
217 	state polarity = newState();//tracks if the formula number i has been inserted in positive (1) or negative (0) form
218 
219 	buildFeasibleStatesRecursive(inserted,polarity,0);
220 
221 }
222 
handleConjunction(state inserted,state polarity,formula_index formula_nr)223 void Tableau::handleConjunction(state inserted, state polarity, formula_index formula_nr){
224 
225 	formula a = leftSubformula->at(formula_nr);
226 	formula b = rightSubformula->at(formula_nr);
227 
228 	if( not (
229 			belongsTo(inserted,polarity,indexToNegativeFormula(formula_nr)) or
230 			belongsTo(inserted,polarity,negateFormula(a)) or
231 			belongsTo(inserted,polarity,negateFormula(b)) or
232 			a == negateFormula(b) /*otherwise a and b cannot be both inserted*/
233 		)
234 	){
235 
236 		//insert {a^b,a,b} and call recursively
237 		state inserted2 = inserted;
238 		state polarity2 = polarity;
239 
240 		inserted2.at(formula_nr) = true;
241 		inserted2.at(formulaToIndex(a)) = true;
242 		inserted2.at(formulaToIndex(b)) = true;
243 
244 		polarity2 = insert(polarity2,indexToPositiveFormula(formula_nr));
245 		polarity2 = insert(polarity2,a);
246 		polarity2 = insert(polarity2,b);
247 
248 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
249 
250 	}
251 
252 	if( not (
253 			belongsTo(inserted,polarity,indexToPositiveFormula(formula_nr)) or
254 			belongsTo(inserted,polarity,a) or
255 			belongsTo(inserted,polarity,negateFormula(b)) or
256 			a == b
257 		)
258 	){
259 
260 		//insert {~(a^b),~a,b} and call recursively
261 		state inserted2 = inserted;
262 		state polarity2 = polarity;
263 
264 		inserted2.at(formula_nr) = true;
265 		inserted2.at(formulaToIndex(a)) = true;
266 		inserted2.at(formulaToIndex(b)) = true;
267 
268 		polarity2 = insert(polarity2,indexToNegativeFormula(formula_nr));
269 		polarity2 = insert(polarity2,negateFormula(a));
270 		polarity2 = insert(polarity2,b);
271 
272 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
273 
274 	}
275 
276 	if( not (
277 			belongsTo(inserted,polarity,indexToPositiveFormula(formula_nr)) or
278 			belongsTo(inserted,polarity,a) or
279 			belongsTo(inserted,polarity,b) or
280 			a == negateFormula(b)
281 		)
282 	){
283 
284 		//insert {~(a^b),~a,~b} and call recursively
285 		state inserted2 = inserted;
286 		state polarity2 = polarity;
287 
288 		inserted2.at(formula_nr) = true;
289 		inserted2.at(formulaToIndex(a)) = true;
290 		inserted2.at(formulaToIndex(b)) = true;
291 
292 		polarity2 = insert(polarity2,indexToNegativeFormula(formula_nr));
293 		polarity2 = insert(polarity2,negateFormula(a));
294 		polarity2 = insert(polarity2,negateFormula(b));
295 
296 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
297 
298 	}
299 
300 	if( not (
301 			belongsTo(inserted,polarity,indexToPositiveFormula(formula_nr)) or
302 			belongsTo(inserted,polarity,negateFormula(a)) or
303 			belongsTo(inserted,polarity,b) or
304 			a == b
305 		)
306 	){
307 
308 		//insert {~(a^b),a,~b} and call recursively
309 		state inserted2 = inserted;
310 		state polarity2 = polarity;
311 
312 		inserted2.at(formula_nr) = true;
313 		inserted2.at(formulaToIndex(a)) = true;
314 		inserted2.at(formulaToIndex(b)) = true;
315 
316 		polarity2 = insert(polarity2,indexToNegativeFormula(formula_nr));
317 		polarity2 = insert(polarity2,a);
318 		polarity2 = insert(polarity2,negateFormula(b));
319 
320 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
321 
322 	}
323 
324 }
325 
handleUntil(state inserted,state polarity,formula_index formula_nr)326 void Tableau::handleUntil(state inserted, state polarity, formula_index formula_nr){
327 
328 	formula a = leftSubformula->at(formula_nr);
329 	formula b = rightSubformula->at(formula_nr);
330 
331 	if( not (
332 			belongsTo(inserted,polarity,indexToNegativeFormula(formula_nr)) or
333 			belongsTo(inserted,polarity,negateFormula(a)) or
334 			belongsTo(inserted,polarity,negateFormula(b)) or
335 			a == negateFormula(b) /*otherwise a and b cannot be both inserted*/
336 		)
337 	){
338 
339 		//insert {Y(aUb),a,b} (Y = A or E) and call recursively
340 		state inserted2 = inserted;
341 		state polarity2 = polarity;
342 
343 		inserted2.at(formula_nr) = true;
344 		inserted2.at(formulaToIndex(a)) = true;
345 		inserted2.at(formulaToIndex(b)) = true;
346 
347 		polarity2 = insert(polarity2,indexToPositiveFormula(formula_nr));
348 		polarity2 = insert(polarity2,a);
349 		polarity2 = insert(polarity2,b);
350 
351 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
352 
353 	}
354 
355 	if( not (
356 			belongsTo(inserted,polarity,indexToNegativeFormula(formula_nr)) or
357 			belongsTo(inserted,polarity,a) or
358 			belongsTo(inserted,polarity,negateFormula(b)) or
359 			a == b /*otherwise ~a and b cannot be both inserted*/
360 		)
361 	){
362 
363 		//insert {Y(aUb),~a,b} (Y = A or E) and call recursively
364 		state inserted2 = inserted;
365 		state polarity2 = polarity;
366 
367 		inserted2.at(formula_nr) = true;
368 		inserted2.at(formulaToIndex(a)) = true;
369 		inserted2.at(formulaToIndex(b)) = true;
370 
371 		polarity2 = insert(polarity2,indexToPositiveFormula(formula_nr));
372 		polarity2 = insert(polarity2,negateFormula(a));
373 		polarity2 = insert(polarity2,b);
374 
375 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
376 
377 	}
378 
379 	if( not (
380 			belongsTo(inserted,polarity,indexToNegativeFormula(formula_nr)) or
381 			belongsTo(inserted,polarity,negateFormula(a)) or
382 			belongsTo(inserted,polarity,b) or
383 			a == b /*otherwise a and ~b cannot be both inserted*/
384 		)
385 	){
386 
387 		//insert {Y(aUb),a,~b} (Y = A or E) and call recursively
388 		state inserted2 = inserted;
389 		state polarity2 = polarity;
390 
391 		inserted2.at(formula_nr) = true;
392 		inserted2.at(formulaToIndex(a)) = true;
393 		inserted2.at(formulaToIndex(b)) = true;
394 
395 		polarity2 = insert(polarity2,indexToPositiveFormula(formula_nr));
396 		polarity2 = insert(polarity2,a);
397 		polarity2 = insert(polarity2,negateFormula(b));
398 
399 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
400 
401 	}
402 
403 	if( not (
404 			belongsTo(inserted,polarity,indexToPositiveFormula(formula_nr)) or
405 			belongsTo(inserted,polarity,a) or
406 			belongsTo(inserted,polarity,b) or
407 			a == negateFormula(b) /*otherwise ~a and ~b cannot be both inserted*/
408 		)
409 	){
410 
411 		//insert {~Y(aUb),~a,~b} (Y = A or E) and call recursively
412 		state inserted2 = inserted;
413 		state polarity2 = polarity;
414 
415 		inserted2.at(formula_nr) = true;
416 		inserted2.at(formulaToIndex(a)) = true;
417 		inserted2.at(formulaToIndex(b)) = true;
418 
419 		polarity2 = insert(polarity2,indexToNegativeFormula(formula_nr));
420 		polarity2 = insert(polarity2,negateFormula(a));
421 		polarity2 = insert(polarity2,negateFormula(b));
422 
423 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
424 
425 	}
426 
427 	if( not (
428 			belongsTo(inserted,polarity,indexToPositiveFormula(formula_nr)) or
429 			belongsTo(inserted,polarity,negateFormula(a)) or
430 			belongsTo(inserted,polarity,b) or
431 			a == b
432 		)
433 	){
434 
435 		//insert {~Y(aUb),a,~b} (Y = A or E) and call recursively
436 		state inserted2 = inserted;
437 		state polarity2 = polarity;
438 
439 		inserted2.at(formula_nr) = true;
440 		inserted2.at(formulaToIndex(a)) = true;
441 		inserted2.at(formulaToIndex(b)) = true;
442 
443 		polarity2 = insert(polarity2,indexToNegativeFormula(formula_nr));
444 		polarity2 = insert(polarity2,a);
445 		polarity2 = insert(polarity2,negateFormula(b));
446 
447 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
448 
449 	}
450 
451 }
452 
handleOtherCases(state inserted,state polarity,formula_index formula_nr)453 void Tableau::handleOtherCases(state inserted, state polarity, formula_index formula_nr){
454 
455 	if( not (
456 			belongsTo(inserted,polarity,indexToPositiveFormula(formula_nr))
457 		)
458 	){
459 
460 		//insert ~a and call recursively
461 		state inserted2 = inserted;
462 		state polarity2 = polarity;
463 
464 		inserted2.at(formula_nr) = true;
465 
466 		polarity2 = insert(polarity2,indexToNegativeFormula(formula_nr));
467 
468 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
469 
470 	}
471 
472 	if( not (
473 			belongsTo(inserted,polarity,indexToNegativeFormula(formula_nr))
474 		)
475 	){
476 
477 		//insert a and call recursively
478 		state inserted2 = inserted;
479 		state polarity2 = polarity;
480 
481 		inserted2.at(formula_nr) = true;
482 
483 		polarity2 = insert(polarity2,indexToPositiveFormula(formula_nr));
484 
485 		buildFeasibleStatesRecursive(inserted2, polarity2, formula_nr+1);
486 
487 	}
488 }
489 
buildFeasibleStatesRecursive(state inserted,state polarity,formula_index formula_nr)490 void Tableau::buildFeasibleStatesRecursive(state inserted, state polarity, formula_index formula_nr){
491 
492 	if(formula_nr>=positive_closure->size()){
493 		states.push_back(polarity);
494 
495 		if(states.size()%1000==0){
496 			cout << " " << states.size() << " feasible states created until now\n";
497 		}
498 
499 		return;
500 	}
501 
502 	switch(positive_closure->at(formula_nr)->getType()){
503 
504 		case CONJUNCTION: //a^b. create new states inserting the combinations: {a^b,a,b},{~(a^b),~a,b},{~(a^b),~a,~b},{~(a^b),a,~b}
505 			handleConjunction(inserted, polarity, formula_nr); break;
506 
507 		case ALL_UNTIL://A(aUb). create new states inserting the combinations: {A(aUb),a,b},{A(aUb),~a,b},{A(aUb),a,~b},{~A(aUb),~a,~b},{~A(aUb),a,~b}
508 			handleUntil(inserted, polarity, formula_nr); break;
509 
510 		case EXISTS_UNTIL://E(aUb). create new states inserting the combinations: {E(aUb),a,b},{E(aUb),~a,b},{E(aUb),a,~b},{~E(aUb),~a,~b},{~E(aUb),a,~b}
511 			handleUntil(inserted, polarity, formula_nr); break;
512 
513 		default://other cases: insert the combinations {a} and {~a}
514 			handleOtherCases(inserted, polarity, formula_nr); break;
515 
516 	}
517 
518 }
519 
checkEdgeConditionsType1(ulint i,ulint j,formula_index k)520 bool Tableau::checkEdgeConditionsType1(ulint i, ulint j, formula_index k){
521 
522 	//		1.1) i(k) = AXa -> a must be in j
523 	//		1.2) i(k) = A~Xa = ~EXa -> ~a must be in j
524 	//		1.3) i(k) = A(aUb) AND ~b in i -> A(aUb) must be in j
525 	//		1.4) i(k) = A~(aUb) = ~E(aUb) AND a in i -> A~(aUb) = ~E(aUb) must be in j
526 
527 	switch(positive_closure->at(k)->getType()){
528 
529 		case ALL_TOMORROW: /*case 1.1*/
530 
531 			if(states.at(i).at(k)){//AXa is present in positive form inside i
532 
533 				formula a = leftSubformula->at(k);//extract subformula a of AXa
534 
535 				if( not belongsTo(states.at(j),a) )//a must be in j
536 					return false;
537 
538 			}
539 
540 		break;
541 
542 		case EXISTS_TOMORROW: /*case 1.2*/
543 
544 			if(not states.at(i).at(k)){//~EXa is present inside i (at position k). i(k)=~EXa
545 
546 				formula a = leftSubformula->at(k);//extract subformula a of ~EXa
547 
548 				if( not belongsTo(states.at(j),negateFormula(a) ) )//~a must be in j
549 					return false;
550 
551 			}
552 
553 		break;
554 
555 		case ALL_UNTIL: /*case 1.3*/
556 
557 			if(states.at(i).at(k)){//A(aUb) is present in positive form inside i
558 
559 				formula b = rightSubformula->at(k);//extract subformula b of A(aUb)
560 
561 				if( belongsTo(states.at(i),negateFormula(b)) ){//~b is in i
562 
563 					if( not belongsTo(states.at(j),indexToPositiveFormula(k)) )//A(aUb) must be in j
564 						return false;
565 
566 				}
567 
568 			}
569 
570 		break;
571 
572 		case EXISTS_UNTIL: /*case 1.4*/
573 
574 			if(not states.at(i).at(k)){//~E(aUb) is present inside i (at position k). i(k)=~E(aUb)
575 
576 				formula a = leftSubformula->at(k);//extract left subformula a of ~E(aUb)
577 
578 				if( belongsTo(states.at(i),a) ){//a is inside i
579 
580 					if( not belongsTo(states.at(j),indexToNegativeFormula(k) ) )//~E(aUb) must be in j
581 						return false;
582 
583 				}
584 
585 			}
586 
587 		break;
588 
589 		default: return true; break;
590 
591 	}
592 
593 
594 	return true;
595 
596 }
597 
checkEdgeConditionsType2(ulint i,ulint j,formula_index k)598 bool Tableau::checkEdgeConditionsType2(ulint i, ulint j, formula_index k){
599 
600 	//2) formula present in j -> check i
601 	//		2.1) j(k) = E(aUb) AND a in i -> E(aUb) must be in i
602 	//		2.2) j(k) = E~(aUb) = ~A(aUb) AND ~b in i -> E~(aUb) = ~A(aUb) must be in i
603 
604 	switch(positive_closure->at(k)->getType()){
605 
606 		case EXISTS_UNTIL:/*case 2.1*/
607 
608 			if(states.at(j).at(k)){//E(aUb) is present in positive form inside j. j(k)=E(aUb)
609 
610 				formula a = leftSubformula->at(k);//extract left subformula a of E(aUb)
611 
612 				if( belongsTo(states.at(i),a) ){//a is in i
613 
614 					if(not belongsTo(states.at(i),indexToPositiveFormula(k)) )//E(aUb) must be in i
615 						return false;
616 
617 				}
618 
619 			}
620 
621 		break;
622 
623 		case ALL_UNTIL:/*case 2.2*/
624 
625 			if(not states.at(j).at(k)){//~A(aUb) is present inside j. j(k)=~A(aUb)
626 
627 				formula b = rightSubformula->at(k);//extract right subformula b of ~A(aUb)
628 
629 				if( belongsTo(states.at(i), negateFormula(b)) ){//~b is inside i
630 
631 					if( not belongsTo(states.at(i),indexToNegativeFormula(k) ) )//~A(aUb) must be in i
632 						return false;
633 
634 				}
635 
636 			}
637 
638 		break;
639 
640 		default: return true; break;
641 
642 	}
643 
644 	return true;
645 
646 }
647 
buildEdges()648 void Tableau::buildEdges(){
649 
650 	number_of_edges = 0;
651 
652 	for(ulint i=0;i<states.size();i++){
653 
654 		for(ulint j=0;j<states.size();j++){//for each pair (i,j) of states
655 
656 			//2 types of conditions:
657 			//1) formula present in i -> check j
658 			//		1.1) AXa in i -> a must be in j
659 			//		1.2) A~Xa = ~EXa in i -> ~a must be in j
660 			//		1.3) { A(aUb), ~b } in i -> A(aUb) must be in D
661 			//		1.4) { A~(aUb) = ~E(aUb), a } in i -> A~(aUb) = ~E(aUb) must be in D
662 			//2) formula present in j -> check i
663 			//		2.1) E(aUb) in j AND a in i -> E(aUb) must be in i
664 			//		2.2) E~(aUb) = ~A(aUb) in j AND ~b in i -> E~(aUb) = ~A(aUb) must be in i
665 
666 			bool conditions_passed=true;
667 
668 			//check conditions of type 1
669 			for(formula_index k=0;conditions_passed and k<positive_closure->size();k++)//for each formula in i
670 				conditions_passed &= checkEdgeConditionsType1(i,j,k);
671 
672 			//check conditions of type 2
673 			if(conditions_passed)
674 				for(formula_index k=0;conditions_passed and k<positive_closure->size();k++)//for each formula in j
675 					conditions_passed &= checkEdgeConditionsType2(i,j,k);
676 
677 			if(conditions_passed){//add edge i->j and back_edge j->i
678 
679 				edges.at(i).insert(j);
680 				back_edges.at(j).insert(i);
681 				number_of_edges++;
682 
683 				if(number_of_edges%50000==0)
684 					cout << " " << number_of_edges << " feasible edges created until now\n";
685 
686 			}
687 
688 		}
689 
690 	}
691 
692 }
693 
cull()694 void Tableau::cull(){
695 
696 	bool verbose = false;
697 	uint states_removed = 1;//to enter in the while loop
698 
699 	while(isSatisfiable() and states_removed>0){//repeat cull until there exists a state where the original formula is satisfiable
700 
701 		if(verbose) cout << " Checking EX, EXT, ENX conditions ... ";
702 		states_removed = cullEasy();
703 		if(verbose) cout << states_removed << " states removed.\n";
704 
705 		if(states_removed==0){
706 
707 			if(verbose) cout << " All states satisfy EX, EXT, ENX conditions. Checking EU and ENU conditions ... ";
708 			states_removed = cullMedium();
709 			if(verbose) cout << states_removed << " states removed.\n";
710 
711 			if(states_removed==0){
712 				if(verbose) cout << " All states satisfy EX, EXT, ENX, EU, and ENU conditions. Checking AU and ANU conditions ... ";
713 				states_removed = cullHard();
714 				if(verbose) cout << states_removed << " states removed.\n";
715 			}
716 		}
717 
718 
719 	}
720 
721 }
722 
cullEasy()723 uint Tableau::cullEasy(){
724 
725 	uint initial_nr_of_states = number_of_states;
726 
727 	//1) check iteratively easy conditions: EXT, EX, ENX
728 
729 	//search a state that falsifies at least one easy condition and cull it recursively backtracking its back edges
730 	for(uint i=0;i<states.size();i++)//for all states
731 		if(not isRemoved.at(i)){//if state is present in the model
732 
733 			if(not checkEasy(i))
734 				cullEasyRecursive(i);
735 
736 		}
737 
738 	return initial_nr_of_states-number_of_states;//return number of states removed
739 
740 }
741 
cullMedium()742 uint Tableau::cullMedium(){
743 
744 	uint initial_nr_of_states = number_of_states;
745 
746 	for(uint i=0; i<states.size();i++)//for all states
747 		if(not isRemoved.at(i)){//if state is present in the model
748 
749 			if(not checkMedium(i))
750 				cullEasyRecursive(i);
751 
752 		}
753 
754 	return initial_nr_of_states-number_of_states;//return number of states removed
755 
756 }
757 
cullHard()758 uint Tableau::cullHard(){
759 
760 	uint initial_nr_of_states = number_of_states;
761 
762 	for(uint i=0; i<states.size();i++)//for all states
763 		if(not isRemoved.at(i)){//if state is present in the model
764 
765 			if(not checkHard(i))
766 				cullEasyRecursive(i);
767 
768 		}
769 
770 	return initial_nr_of_states-number_of_states;//return number of states removed
771 
772 }
773 
cullEasyRecursive(uint i)774 void Tableau::cullEasyRecursive(uint i){
775 
776 	removeState(i);//remove state, all its forward edges (not back edges) and remove the state i from the adj lists of all its neighbors
777 
778 	for(std::set<uint>::iterator it = back_edges.at(i).begin(); it != back_edges.at(i).end();++it){//for each predecessor of i
779 
780 		if(not checkEasy(*it) and not isRemoved.at(*it))
781 			cullEasyRecursive(*it);
782 
783 	}
784 
785 }
786 
removeGlobalMarks(uint i)787 void Tableau::removeGlobalMarks(uint i){
788 
789 	for(uint j=0;j<visited_during_mark_removal.size();++j)
790 		visited_during_mark_removal[j]=false;
791 
792 	removeGlobalMarksRecursive(i);
793 
794 }
795 
removeGlobalMarksRecursive(uint i)796 void Tableau::removeGlobalMarksRecursive(uint i){
797 
798 	globally_satisfied_formulas_positive[i] = newState();
799 	globally_satisfied_formulas_negative[i] = newState();
800 
801 	visited_during_mark_removal[i] = true;
802 
803 	std::set<uint>::iterator it;
804 
805 	//loop through states that have an edge towards i and clear their global marks
806 	for(it = back_edges.at(i).begin(); it != back_edges.at(i).end();++it)
807 		if(not visited_during_mark_removal[*it])
808 			removeGlobalMarksRecursive(*it);
809 
810 }
811 
removeState(uint i)812 void Tableau::removeState(uint i){//removes state i and all entering and exiting edges
813 
814 	if(isRemoved.at(i)){//already removed
815 
816 		cout << "WARNING: removing state already removed ("<<i<<")\n";
817 		return;
818 
819 	}
820 
821 	//if initial formula is in this state, decrease counter of states having the original formula.
822 	if(belongsTo(states.at(i),initial_formula)){
823 
824 		if(number_of_states_with_original_formula==0)
825 			cout << "WARNING: trying to decrease counter with zero value (number of states with original formula). Debug needed!\n";
826 		else
827 			number_of_states_with_original_formula--;
828 
829 	}
830 
831 	number_of_states--;
832 
833 	if(number_of_states%100==0)
834 		cout << "  " << number_of_states << " states left\n";
835 
836 	/*if((ulint)difftime( time(0), timestamp)%5==0 and (ulint)difftime( time(0), timestamp) != last_time_printed){
837 		last_time_printed = (ulint)difftime( time(0), timestamp);
838 		cout << "  " << number_of_states << " states left\n";
839 	}*/
840 
841 
842 	isRemoved.at(i) = true;//mark as removed
843 
844 	//removeGlobalMarks(i);//backtrack on predecessors and erase their global marks
845 
846 	std::set<uint>::iterator it;
847 
848 	//loop through states that have an edge towards i and remove i from their adjacency list
849 	for(it = back_edges.at(i).begin(); it != back_edges.at(i).end();++it)
850 		edges.at(*it).erase(i);
851 
852 	//loop through states in the adj list of i and remove i from their back adj list
853 	for(it = edges.at(i).begin(); it != edges.at(i).end();++it)
854 		back_edges.at(*it).erase(i);
855 
856 	//free memory of state i
857 	edges.at(i).clear();
858 	//back_edges.at(i).clear();//back_edges are not removed because they have to be used to backtrack cull effects
859 
860 }
861 
checkEasy(ulint i)862 bool Tableau::checkEasy(ulint i){
863 
864 	return checkEXT(i) and checkEX(i) and checkENX(i);
865 
866 }
867 
checkMedium(ulint i)868 bool Tableau::checkMedium(ulint i){
869 
870 	return checkEU(i) and checkENU(i);
871 
872 }
873 
checkHard(ulint i)874 bool Tableau::checkHard(ulint i){
875 
876 	return checkAU(i) and checkANU(i);
877 
878 }
879 
checkEXT(ulint i)880 bool Tableau::checkEXT(ulint i){
881 
882 	//state i must have at least one successor
883 	return edges.at(i).size()>0;
884 
885 }
886 
checkEX(ulint i)887 bool Tableau::checkEX(ulint i){
888 
889 	//if EXa is in i, then at least one successor of i must have a
890 
891 	bool all_exists_have_successor=true;
892 
893 	for(formula_index k = 0; all_exists_have_successor and k<positive_closure->size();k++){//for each formula in i
894 
895 		//if k is inside i in positive form AND k is a EXa (i.e. for all EXa inside i)
896 		if( belongsTo(states.at(i),indexToPositiveFormula(k)) and positive_closure->at(k)->getType()==EXISTS_TOMORROW){
897 
898 			formula a = leftSubformula->at(k);//get subformula of EXa
899 
900 			std::set<uint>::iterator it;
901 			bool exists_successor=false;
902 
903 			//loop through states in the adj list of i.
904 			for(it = edges.at(i).begin(); (not exists_successor) and it != edges.at(i).end();++it)
905 				exists_successor |= belongsTo(states.at(*it),a);//a must be in at least one successor of i
906 
907 			all_exists_have_successor &= exists_successor;
908 
909 		}
910 
911 	}
912 
913 	return all_exists_have_successor;
914 
915 }
916 
checkENX(ulint i)917 bool Tableau::checkENX(ulint i){
918 
919 	//if EX~a = E~Xa = ~AXa is in i, then at least one successor of i must have ~a
920 
921 	bool all_neg_exists_have_successor=true;
922 
923 	for(formula_index k = 0; all_neg_exists_have_successor and k<positive_closure->size();k++){//for each formula in i
924 
925 		//if k is inside i in negative form AND k is a AXa (i.e. for all ~AXa inside i)
926 		if( belongsTo(states.at(i),indexToNegativeFormula(k)) and positive_closure->at(k)->getType()==ALL_TOMORROW){
927 
928 			formula not_a = negateFormula(leftSubformula->at(k));//get subformula a of AXa and negate it, obtaining ~a
929 
930 			bool exists_successor=false;
931 
932 			//loop through states in the adj list of i.
933 			for(std::set<uint>::iterator it = edges.at(i).begin(); (not exists_successor) and it != edges.at(i).end();++it)
934 				exists_successor |= belongsTo(states.at(*it),not_a);//~a must be in at least one successor of i
935 
936 			all_neg_exists_have_successor &= exists_successor;
937 
938 		}
939 
940 	}
941 
942 	return all_neg_exists_have_successor;
943 
944 }
945 
checkEU(ulint i)946 bool Tableau::checkEU(ulint i){
947 
948 	//for each E(aUb): find a path starting from i that has always a until finally b is found
949 	//no loops back: mark states
950 
951 	bool all_EU_satisfied = true;
952 
953 	for(formula_index k = 0; all_EU_satisfied and k<positive_closure->size();k++){//for each formula in i
954 
955 		//if k is inside i in positive form AND k is a E(aUb) (i.e. for all E(aUb) inside i)
956 		if( belongsTo(states.at(i),indexToPositiveFormula(k)) and positive_closure->at(k)->getType()==EXISTS_UNTIL){
957 
958 			formula a = leftSubformula->at(k);
959 			formula b = rightSubformula->at(k);
960 
961 			clearMarked();//unmark all states
962 			all_EU_satisfied &= checkEUrecursive(i,k,a,b);//start visit (DFS)
963 
964 		}
965 
966 	}
967 
968 	return all_EU_satisfied;
969 
970 }
971 
checkAU(ulint i)972 bool Tableau::checkAU(ulint i){
973 
974 	//for each A(aUb): find a tree substructure having always a and the leafs contain b and consistent with EX, E~X, EU, E~U
975 	//no loops back: mark states
976 
977 	bool all_AU_satisfied = true;
978 
979 	for(formula_index k = 0; all_AU_satisfied and k<positive_closure->size();k++){//for each formula in i
980 
981 		//if k is inside i in positive form AND k is a A(aUb) (i.e. for all A(aUb) inside i)
982 		if( belongsTo(states.at(i),indexToPositiveFormula(k)) and positive_closure->at(k)->getType()==ALL_UNTIL){
983 
984 			formula a = leftSubformula->at(k);
985 			formula b = rightSubformula->at(k);
986 
987 			clearMarked();//unmark all states
988 			all_AU_satisfied &= checkAUrecursive(i,a,b);//start visit (DFS)
989 
990 		}
991 
992 	}
993 
994 	return all_AU_satisfied;
995 
996 }
997 
checkAUrecursive(ulint i,formula a,formula b)998 bool Tableau::checkAUrecursive(ulint i,formula a, formula b){
999 
1000 	//b is in this state: return true
1001 	if(belongsTo(states.at(i),b)){
1002 		status[i] = SATISFIED;
1003 		return true;
1004 	}
1005 
1006 	//here we know that b is not in i
1007 
1008 	if(not belongsTo(states.at(i),a)){//a and b are not in i: return false
1009 		status[i] = NOT_SATISFIED;
1010 		return false;
1011 	}
1012 
1013 	status[i] = VISITED;//mark status as visited to prevent loops
1014 
1015 	//here we are sure that the state contains a AND does not contain b: check AU rule
1016 
1017 	//1) visit recursively successors and check the A(aUb) rule
1018 
1019 	uint sat_successors=0;//number of satisfied successors
1020 
1021 	for(std::set<uint>::iterator it = edges.at(i).begin(); it != edges.at(i).end();++it){//for all non-visited successors of i
1022 
1023 		if(status[*it]==NOT_VISITED)
1024 			checkAUrecursive(*it,a, b);
1025 
1026 		if(status[*it]==SATISFIED)
1027 			sat_successors++;
1028 
1029 	}
1030 
1031 	//now each successor is marked as SATISFIED (A(aUb) satisfied), NOT_SATISFIED (A(aUb) not satisfied) or
1032 	//VISITED (loop: A(aUb) not satisfied because there exists a loop where a is always valid, but b never)
1033 
1034 	//extract all EX, E~X, EU, E~U rules present in state i
1035 
1036 	vector<formula> existential_formulas;//existential formulas inside state i
1037 
1038 	for(formula_index k = 0; k<positive_closure->size();k++){//for each formula in i
1039 
1040 		if( belongsTo(states.at(i),indexToPositiveFormula(k)) and positive_closure->at(k)->getType()==EXISTS_TOMORROW)//EX
1041 			existential_formulas.push_back(indexToPositiveFormula(k));
1042 
1043 		if( belongsTo(states.at(i),indexToNegativeFormula(k)) and positive_closure->at(k)->getType()==ALL_TOMORROW)//~AX = E~X
1044 				existential_formulas.push_back(indexToNegativeFormula(k));
1045 
1046 		if( belongsTo(states.at(i),indexToPositiveFormula(k)) and positive_closure->at(k)->getType()==EXISTS_UNTIL)//EU
1047 			existential_formulas.push_back(indexToPositiveFormula(k));
1048 
1049 		if( belongsTo(states.at(i),indexToNegativeFormula(k)) and positive_closure->at(k)->getType()==ALL_UNTIL)//~AU = E~U
1050 			existential_formulas.push_back(indexToNegativeFormula(k));
1051 
1052 	}
1053 
1054 	//now, 2 cases:
1055 	//1) if existential_formulas not empty: for each E formula in existential_formulas, check that there exist a successor marked SATISFIED that satisfies the E formula
1056 	//1) if existential_formulas is empty: there must be at least one successor marked SATISFIED
1057 
1058 	bool E_satisfied = true;
1059 
1060 	for(uint k=0;E_satisfied and k<existential_formulas.size();k++){//for each E formula
1061 
1062 		bool exist_good_successor = false;//exists a successor marked SATISFIED that satisfies the E formula
1063 
1064 		for(std::set<uint>::iterator it = edges.at(i).begin(); (not exist_good_successor) and it != edges.at(i).end();++it){//for all successors of i
1065 
1066 			if(status[*it]==SATISFIED)//only for successors marked SATISFIED
1067 				exist_good_successor |= checkEformula(existential_formulas.at(k),i,*it);//check that the E formula is sat in i->*it
1068 
1069 		}
1070 
1071 		E_satisfied &= exist_good_successor;
1072 
1073 	}
1074 
1075 	if(E_satisfied and sat_successors>0)
1076 		status[i] = SATISFIED;
1077 	else
1078 		status[i] = NOT_SATISFIED;
1079 
1080 	return status[i] == SATISFIED;
1081 
1082 }
1083 
checkANU(ulint i)1084 bool Tableau::checkANU(ulint i){
1085 
1086 	bool all_ANU_satisfied = true;
1087 
1088 	for(formula_index k = 0; all_ANU_satisfied and k<positive_closure->size();k++){//for each formula in i
1089 
1090 		//if k is inside i in negative form AND k is a E(aUb) (i.e. for all A~(aUb) inside i)
1091 		if( belongsTo(states.at(i),indexToNegativeFormula(k)) and positive_closure->at(k)->getType()==EXISTS_UNTIL){
1092 
1093 			formula a = leftSubformula->at(k);
1094 			formula b = rightSubformula->at(k);
1095 
1096 			clearMarked();//unmark all states
1097 			all_ANU_satisfied &= checkANUrecursive(i,a,b);//start visit (DFS)
1098 
1099 		}
1100 
1101 	}
1102 
1103 	return all_ANU_satisfied;
1104 
1105 }
1106 
checkANUrecursive(ulint i,formula a,formula b)1107 bool Tableau::checkANUrecursive(ulint i,formula a, formula b){
1108 
1109 	current_timestamp++;
1110 	mark_timestamps[i] = current_timestamp;
1111 
1112 	//b is in this state: return false
1113 	if(belongsTo(states.at(i),b)){
1114 		status[i] = NOT_SATISFIED;
1115 		return false;
1116 	}
1117 
1118 	//here we know that b is not in i
1119 
1120 	if(not belongsTo(states.at(i),a)){//a and b are not in i: return true (A~(aUb) satisfied in this state)
1121 		status[i] = SATISFIED;
1122 		return true;
1123 	}
1124 
1125 	//here we know that b is NOT in i and a is in i
1126 
1127 	status[i] = VISITED;//mark status as visited
1128 
1129 	//1) visit recursively successors and check the A~(aUb) rule
1130 
1131 	for(std::set<uint>::iterator it = edges.at(i).begin(); it != edges.at(i).end();++it){//for all non-visited successors of i
1132 
1133 		if(status[*it]==NOT_VISITED)
1134 			checkANUrecursive(*it,a, b);
1135 
1136 	}
1137 
1138 	//now each successor is marked as SATISFIED (A~(aUb) satisfied), NOT_SATISFIED (A~(aUb) not satisfied) or
1139 	//VISITED (loop)
1140 
1141 	//extract all EX, E~X, EU, E~U rules present in state i: sub-structure must be consistent
1142 
1143 	vector<formula> existential_formulas;//existential formulas inside state i
1144 
1145 	for(formula_index k = 0; k<positive_closure->size();k++){//for each formula in i
1146 
1147 		if( belongsTo(states.at(i),indexToPositiveFormula(k)) and positive_closure->at(k)->getType()==EXISTS_TOMORROW)//EX
1148 			existential_formulas.push_back(indexToPositiveFormula(k));
1149 
1150 		if( belongsTo(states.at(i),indexToNegativeFormula(k)) and positive_closure->at(k)->getType()==ALL_TOMORROW)//~AX = E~X
1151 				existential_formulas.push_back(indexToNegativeFormula(k));
1152 
1153 		if( belongsTo(states.at(i),indexToPositiveFormula(k)) and positive_closure->at(k)->getType()==EXISTS_UNTIL)//EU
1154 			existential_formulas.push_back(indexToPositiveFormula(k));
1155 
1156 		if( belongsTo(states.at(i),indexToNegativeFormula(k)) and positive_closure->at(k)->getType()==ALL_UNTIL)//~AU = E~U
1157 			existential_formulas.push_back(indexToNegativeFormula(k));
1158 
1159 	}
1160 
1161 	bool E_satisfied = true;//all existential formulas satisfied
1162 
1163 	for(uint k=0;E_satisfied and k<existential_formulas.size();k++){//for each E formula
1164 
1165 		bool exist_good_successor = false;//exists a successor marked SATISFIED or VISITED (loop) that satisfies the E formula
1166 
1167 		for(std::set<uint>::iterator it = edges.at(i).begin(); (not exist_good_successor) and it != edges.at(i).end();++it){//for all successors of i
1168 
1169 			if(status[*it]==SATISFIED or status[*it]==VISITED)//only for successors marked SATISFIED or VISITED
1170 				exist_good_successor |= checkEformula(existential_formulas.at(k),i,*it);//check that the E formula is sat in i->*it
1171 
1172 		}
1173 
1174 		E_satisfied &= exist_good_successor;
1175 
1176 	}
1177 
1178 	if(E_satisfied)
1179 		status[i] = SATISFIED;
1180 	else{
1181 
1182 		status[i] = NOT_SATISFIED;
1183 
1184 		//in this case, erase all marks made after the timestamp of this state because some assumptions made while
1185 		//accepting loops may no more be valid (e.g. if a loop turned back to this state, now this state is not satisfied so the loop should not
1186 		//have been accepted)
1187 
1188 		for(ulint s=0;s<states.size();s++){
1189 
1190 			if(mark_timestamps[s]>mark_timestamps[i]){//this status has been computed after the current node: erase it
1191 				mark_timestamps[s]=0;
1192 				status[s] = NOT_VISITED;
1193 			}
1194 
1195 		}
1196 
1197 	}
1198 
1199 	return status[i] == SATISFIED;
1200 
1201 }
1202 
1203 
checkEformula(formula f,ulint s1,ulint s2)1204 bool Tableau::checkEformula(formula f, ulint s1, ulint s2){//check if existential formula f is valid in the states s1->s2
1205 
1206 	//assumption: f is either EX, ~AX, EU or ~AU
1207 
1208 	formula_index k = formulaToIndex(f);
1209 	formula a,b;
1210 
1211 	switch(positive_closure->at(k)->getType()){
1212 
1213 		case EXISTS_TOMORROW: /*f is EXa: s2 must contain a*/
1214 
1215 			a = leftSubformula->at(k);
1216 			return belongsTo(states.at(s2),a);
1217 
1218 		break;
1219 
1220 		case ALL_TOMORROW: /*f is E~Xa: s2 must contain ~a*/
1221 
1222 			a = leftSubformula->at(k);
1223 			return belongsTo(states.at(s2),negateFormula(a));
1224 
1225 		break;
1226 
1227 		case EXISTS_UNTIL: /*f is E(aUb): either b must be in s1 or E(aUb) must be in s2*/
1228 
1229 			b = rightSubformula->at(k);
1230 
1231 			if(belongsTo(states.at(s1),b))
1232 				return true;
1233 
1234 			//b is not in s1: check that E(aUb) is in s2
1235 
1236 			return belongsTo(states.at(s2),f);
1237 
1238 		break;
1239 
1240 		case ALL_UNTIL: /* f is E~(aUb): by construction, ~b is in s1. either ~a must be in s1 or E~(aUb) must be in s2*/
1241 
1242 			a = leftSubformula->at(k);
1243 
1244 			if(belongsTo(states.at(s1),negateFormula(a)))
1245 				return true;
1246 
1247 			//s1 contains a and ~b. E~(aUb) must be in s2
1248 
1249 			return belongsTo(states.at(s2),f);
1250 
1251 		break;
1252 
1253 		default: cout << "WARNING: unexpected formula in function checkEformula\n. Debug needed!\n"; return false; break;
1254 
1255 	}
1256 
1257 	return false;
1258 
1259 }
1260 
1261 //parameters: state, index of the EU formula, left and right subformulas
checkEUrecursive(ulint i,formula_index k,formula a,formula b)1262 bool Tableau::checkEUrecursive(ulint i,formula_index k, formula a, formula b){
1263 
1264 	//check if the state had already been checked in the past for this formula
1265 	//if(globally_satisfied_formulas_positive[i][k])
1266 	//	return true;
1267 
1268 	//find a path starting from i that has always a until finally b is found (DFS visit)
1269 	//no loops back: mark states
1270 
1271 	status[i] = VISITED;
1272 	//marked->at(i) = true;//mark this state
1273 
1274 	if(belongsTo(states.at(i),b)){//b is in this state: mark globally and return success
1275 		//globally_satisfied_formulas_positive[i][k] = true;
1276 		return true;
1277 	}
1278 
1279 	if(not belongsTo(states.at(i),a))//a is not in this state (and neither b): return false
1280 		return false;
1281 
1282 	//b is not in this state and a is in this state. return success iif at least one non-visited successor returns success
1283 
1284 	bool path_found = false;
1285 
1286 	//first of all, check if there are successors marked globally (avoid recursion if possible)
1287 
1288 	/*for(std::set<uint>::iterator it = edges.at(i).begin(); (not path_found) and it != edges.at(i).end();++it){//for all successors of i
1289 
1290 		if(status[*it] == NOT_VISITED){//if the successor is not marked
1291 
1292 			path_found |= globally_satisfied_formulas_positive[*it][k];
1293 
1294 		}
1295 
1296 	}*/
1297 
1298 	//then, recurse only if no successors were already marked globally
1299 
1300 	for(std::set<uint>::iterator it = edges.at(i).begin(); (not path_found) and it != edges.at(i).end();++it){//for all successors of i
1301 
1302 		if(status[*it] == NOT_VISITED){//if the successor is not marked
1303 
1304 			path_found |= checkEUrecursive(*it,k,a,b);
1305 
1306 		}
1307 
1308 	}
1309 
1310 	//if(path_found)
1311 		//globally_satisfied_formulas_positive[i][k] = true;
1312 
1313 	return path_found;
1314 
1315 }
1316 
checkENU(ulint i)1317 bool Tableau::checkENU(ulint i){
1318 
1319 	//for each E~(aUb) = ~A(aUb): find a path starting from i that has always ~b until finally ~b and ~a is found, OR
1320 	//the path has always ~b and at some point it loops
1321 
1322 	clearMarked();//unmark all states
1323 
1324 	bool all_ENU_satisfied = true;
1325 
1326 	for(formula_index k = 0; all_ENU_satisfied and k<positive_closure->size();k++){//for each formula in i
1327 
1328 		//if k is inside i in negative form AND k is a A(aUb) (i.e. for all E~(aUb) inside i)
1329 		if( belongsTo(states.at(i),indexToNegativeFormula(k)) and positive_closure->at(k)->getType()==ALL_UNTIL){
1330 
1331 			formula a = leftSubformula->at(k);
1332 			formula b = rightSubformula->at(k);
1333 
1334 			all_ENU_satisfied &= checkENUrecursive(i,a,b);//start visit (DFS). note that states are all unmarked after call is finished (no need to call clearMarked())
1335 
1336 		}
1337 
1338 	}
1339 
1340 	return all_ENU_satisfied;
1341 
1342 }
1343 
checkENUrecursive(ulint i,formula a,formula b)1344 bool Tableau::checkENUrecursive(ulint i,formula a, formula b){
1345 
1346 	if(belongsTo(states.at(i),b))//b is in this state: return false
1347 		return false;
1348 
1349 	//here we are sure that ~b is in this state
1350 
1351 	if(belongsTo(states.at(i),negateFormula(a)))//~a is in this state return true
1352 		return true;
1353 
1354 	status[i] = VISITED;
1355 	//marked->at(i) = true;//mark this state
1356 
1357 	//here we know that the state contains ~b and a
1358 
1359 	bool path_found = false;
1360 
1361 	for(std::set<uint>::iterator it = edges.at(i).begin(); (not path_found) and it != edges.at(i).end();++it){//for all successors of i
1362 
1363 		if(status[*it] == NOT_VISITED){//if the successor is not marked: call recursive DFS
1364 
1365 			path_found |= checkENUrecursive(*it,a,b);
1366 
1367 		}else{//the successor is marked: since we are unmarking states returning from recursion, this means that we found a loop
1368 
1369 			return true;
1370 
1371 		}
1372 
1373 	}
1374 
1375 	status[i] = NOT_VISITED;
1376 	//marked->at(i) = false;//unmark this state
1377 
1378 	return path_found;
1379 
1380 }
1381 
isSatisfiable()1382 bool Tableau::isSatisfiable(){//true iif f admits a model
1383 
1384 	return number_of_states_with_original_formula>0;
1385 
1386 }
1387 
1388 
1389 } /* namespace ctl_sat */
1390 
1391 
1392 
1393