module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,EA,SO,W} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		sys {N,EA,SO,W} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextHead = SO;

guarantee
	spec_nextMoveMode = FWD;

assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));

guarantee  
	G (next(spec_nextMoveMode = TURN_RIGHT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(spec_nextMoveMode = TURN_LEFT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)  -> next(spec_specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine Heading
 */
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));

 

guarantee
	G ((((spec_nextHead = N & Heading = EA) | (spec_nextHead = EA & Heading = SO) | (spec_nextHead = SO & Heading = W) | (spec_nextHead = W & Heading = N)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_RIGHT);

guarantee
	G ((((spec_nextHead = EA & Heading = N) | (spec_nextHead = SO & Heading = EA) | (spec_nextHead = W & Heading = SO) | (spec_nextHead = N & Heading = W)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_LEFT);
 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G (((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT) & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)));

guarantee
	G ((spec_turnState = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT))  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3) -> next(spec_turnState = T0));
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_RIGHT) <-> (LeftMotor = CALIB_TURN_RIGHT & RightMotor = CALIB_TURN_RIGHT)); 

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_LEFT) <-> (LeftMotor = CALIB_TURN_LEFT & RightMotor = CALIB_TURN_LEFT)); 

guarantee
	G ((next(spec_turnState) = T2) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_turnState = T2) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_RIGHT))) <-> (LeftMotor = CALIB_FWD_RIGHT & RightMotor = CALIB_FWD_RIGHT));
		
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_LEFT))) <-> (LeftMotor = CALIB_FWD_LEFT & RightMotor = CALIB_FWD_LEFT));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));

assumption
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle) = CLEAR);

assumption
  respondsTo((spec_nextMoveMode=TURN_RIGHT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_RIGHT));
	
assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,EA,SO,W} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		sys {N,EA,SO,W} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextHead = SO;

guarantee
	spec_nextMoveMode = FWD;

assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));

guarantee  
	G (next(spec_nextMoveMode = TURN_RIGHT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(spec_nextMoveMode = TURN_LEFT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)  -> next(spec_specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine Heading
 */
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));

 

guarantee
	G ((((spec_nextHead = N & Heading = EA) | (spec_nextHead = EA & Heading = SO) | (spec_nextHead = SO & Heading = W) | (spec_nextHead = W & Heading = N)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_RIGHT);

guarantee
	G ((((spec_nextHead = EA & Heading = N) | (spec_nextHead = SO & Heading = EA) | (spec_nextHead = W & Heading = SO) | (spec_nextHead = N & Heading = W)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_LEFT);
 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G (((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT) & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)));

guarantee
	G ((spec_turnState = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT))  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3) -> next(spec_turnState = T0));
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_RIGHT) <-> (LeftMotor = CALIB_TURN_RIGHT & RightMotor = CALIB_TURN_RIGHT)); 

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_LEFT) <-> (LeftMotor = CALIB_TURN_LEFT & RightMotor = CALIB_TURN_LEFT)); 

guarantee
	G ((next(spec_turnState) = T2) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_turnState = T2) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_RIGHT))) <-> (LeftMotor = CALIB_FWD_RIGHT & RightMotor = CALIB_FWD_RIGHT));
		
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_LEFT))) <-> (LeftMotor = CALIB_FWD_LEFT & RightMotor = CALIB_FWD_LEFT));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));

assumption
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle) = CLEAR);

assumption
  respondsTo((spec_nextMoveMode=TURN_RIGHT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_RIGHT));
	
assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,EA,SO,W} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		sys {N,EA,SO,W} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextHead = SO;

guarantee
	spec_nextMoveMode = FWD;

assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));

guarantee  
	G (next(spec_nextMoveMode = TURN_RIGHT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(spec_nextMoveMode = TURN_LEFT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)  -> next(spec_specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine Heading
 */
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));

 

guarantee
	G ((((spec_nextHead = N & Heading = EA) | (spec_nextHead = EA & Heading = SO) | (spec_nextHead = SO & Heading = W) | (spec_nextHead = W & Heading = N)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_RIGHT);

guarantee
	G ((((spec_nextHead = EA & Heading = N) | (spec_nextHead = SO & Heading = EA) | (spec_nextHead = W & Heading = SO) | (spec_nextHead = N & Heading = W)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_LEFT);
 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G (((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT) & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)));

guarantee
	G ((spec_turnState = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT))  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3) -> next(spec_turnState = T0));
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_RIGHT) <-> (LeftMotor = CALIB_TURN_RIGHT & RightMotor = CALIB_TURN_RIGHT)); 

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_LEFT) <-> (LeftMotor = CALIB_TURN_LEFT & RightMotor = CALIB_TURN_LEFT)); 

guarantee
	G ((next(spec_turnState) = T2) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_turnState = T2) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_RIGHT))) <-> (LeftMotor = CALIB_FWD_RIGHT & RightMotor = CALIB_FWD_RIGHT));
		
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_LEFT))) <-> (LeftMotor = CALIB_FWD_LEFT & RightMotor = CALIB_FWD_LEFT));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));

assumption
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle) = CLEAR);

assumption
  respondsTo((spec_nextMoveMode=TURN_RIGHT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_RIGHT));
	
assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,EA,SO,W} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		sys {N,EA,SO,W} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextHead = SO;

guarantee
	spec_nextMoveMode = FWD;

assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));

guarantee  
	G (next(spec_nextMoveMode = TURN_RIGHT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(spec_nextMoveMode = TURN_LEFT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)  -> next(spec_specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine Heading
 */
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));

 

guarantee
	G ((((spec_nextHead = N & Heading = EA) | (spec_nextHead = EA & Heading = SO) | (spec_nextHead = SO & Heading = W) | (spec_nextHead = W & Heading = N)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_RIGHT);

guarantee
	G ((((spec_nextHead = EA & Heading = N) | (spec_nextHead = SO & Heading = EA) | (spec_nextHead = W & Heading = SO) | (spec_nextHead = N & Heading = W)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_LEFT);
 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G (((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT) & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)));

guarantee
	G ((spec_turnState = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT))  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3) -> next(spec_turnState = T0));
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_RIGHT) <-> (LeftMotor = CALIB_TURN_RIGHT & RightMotor = CALIB_TURN_RIGHT)); 

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_LEFT) <-> (LeftMotor = CALIB_TURN_LEFT & RightMotor = CALIB_TURN_LEFT)); 

guarantee
	G ((next(spec_turnState) = T2) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_turnState = T2) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_RIGHT))) <-> (LeftMotor = CALIB_FWD_RIGHT & RightMotor = CALIB_FWD_RIGHT));
		
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_LEFT))) <-> (LeftMotor = CALIB_FWD_LEFT & RightMotor = CALIB_FWD_LEFT));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));

assumption
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle) = CLEAR);

assumption
  respondsTo((spec_nextMoveMode=TURN_RIGHT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_RIGHT));
	
assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} color ;
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {YES, NO} starting_pos ;
		env {YES, NO} edge ;
		
		env {PRESS, RELEASE} speedButton;
		env {PRESS, RELEASE} haltButton;
		
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {RIGHT, LEFT} direction ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		sys boolean spec_pauseButtonValidPressed ;
		sys {PAUSE, GO} spec_pausing ;
		
	define
		allsleep := verMot = SLEEP & horMot = SLEEP & botMot = STOP;
	define
		nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
	define
		verhor_dontmove := ack_ver = SLEEP & ack_hor = SLEEP;
	define
		onlybotmoves := verhor_dontmove & ack_bot = MOVE;
	
guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);

 
guarantee 
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
guarantee
	G (verMot = MOVE -> color = next(spec_currentColor));
	
guarantee  
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & horMot = SLEEP);
	
 

guarantee  
	motSpeed = LEVEL1 & !spec_dropping;
	
guarantee
	!spec_dropping & motSpeed = LEVEL1 & spec_pausing = GO & direction = RIGHT;

guarantee  
	G (spec_pausing = GO & !spec_dropping & starting_pos = NO & verhor_dontmove <-> botMot = RETURN);
		
 
		
guarantee
	G (!spec_dropping & starting_pos = YES & color = BLACK -> allsleep);
	
guarantee
	G (color = BLACK | spec_dropping -> verMot = SLEEP);
	
guarantee
	G (spec_pausing = GO & !spec_dropping & starting_pos = YES & nonemove & color != BLACK <-> verMot = MOVE);
	
guarantee  
	G (edge = YES <-> direction != next(direction));	
	
guarantee  
	G (spec_pausing = GO & spec_dropping & detect != spec_currentColor & verhor_dontmove <-> botMot = SEEK);

guarantee  
	G (spec_pausing = GO & spec_dropping & detect = spec_currentColor & verhor_dontmove <-> horMot = MOVE);
	
 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL1 -> next(motSpeed = LEVEL2));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL2 -> next(motSpeed = LEVEL3));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL3 -> next(motSpeed = LEVEL1));
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed -> motSpeed = next(motSpeed));

 

guarantee
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_pauseButtonValidPressed);
	
 

guarantee
	G ((spec_pauseButtonValidPressed & spec_pausing = GO) | (!spec_pauseButtonValidPressed & spec_pausing = PAUSE)
		-> next(spec_pausing) = PAUSE);
	
guarantee
	G ((!spec_pauseButtonValidPressed & spec_pausing = GO) | (spec_pauseButtonValidPressed & spec_pausing = PAUSE)
		-> next(spec_pausing) = GO);

assumption  
  respondsTo(spec_pausing=PAUSE,(spec_pausing=GO));
	
guarantee  
	G (spec_pausing = PAUSE -> allsleep);
	
 
 
  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));

assumption  
  GF (color!=BLACK);
	
assumption
  GF (ack_hor=MOVE);
	
 

guarantee
  respondsTo(color!=BLACK,(horMot=MOVE&detect=spec_currentColor));
 
guarantee
  GF (horMot=MOVE);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {NOEDGE, EDGE} atEdge ;
		
		env {ZERO, NOTZERO} num_of_cubes;
		
		env {PRESS, RELEASE} haltButton;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {RIGHT, LEFT, STOP, INITPOS} botMot ;
		
		sys boolean spec_allsleep ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {REDUCE, NOTREDUCE} reduce_num_of_cubes;
		
		sys { S0, S1, S2} spec_state ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys {WAIT, KICK, TOANGLERIGHT, TOANGLELEFT, DROP, FROMANGLE} spec_stage ;
		sys boolean spec_finished_cycle;
		
		sys boolean spec_speedButtonValidPressed ;
		sys boolean spec_haltButtonValidPressed ;
		
		sys {pause, go} spec_pausing ;

guarantee  
  spec_state=S0;

guarantee  
  G ((spec_state=S0 & ((!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(detect = spec_currentColor)) | ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP)) | (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor)) | (!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor))) & next(spec_state=S0)) |
  (spec_state=S0 & ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = spec_currentColor)) & next(spec_state=S1)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor)) & next(spec_state=S0)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = spec_currentColor)) & next(spec_state=S1)) |
  (spec_state=S1 & ((ack_ver_hor = MOVE & spec_stage = DROP)) & next(spec_state=S2)) |
  (spec_state=S2 & next(spec_state=S2)));

guarantee  
  GF (spec_state=S0|spec_state=S1);

guarantee
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_haltButtonValidPressed = true);

guarantee
	G ((spec_haltButtonValidPressed = true & spec_pausing = go) | (spec_haltButtonValidPressed = false & spec_pausing = pause)
		-> next(spec_pausing) = pause);
	
guarantee
	G ((spec_haltButtonValidPressed = false & spec_pausing = go) | (spec_haltButtonValidPressed = true & spec_pausing = pause)
		-> next(spec_pausing) = go);

guarantee  
  respondsTo(spec_haltButtonValidPressed=true&spec_pausing=go,(spec_haltButtonValidPressed=true));
	
guarantee  
	G (spec_pausing = pause | ack_ver_hor = MOVE -> 
		spec_allsleep = true & next(spec_stage) = spec_stage);
	
guarantee  
	G (spec_stage != WAIT -> next(spec_currentColor) = spec_currentColor);

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (spec_allsleep = true <-> verMot = SLEEP  & horMot = SLEEP & botMot = STOP);
	
guarantee  
	motSpeed = LEVEL1 & spec_stage = WAIT & spec_pausing = go;
	
 

 

guarantee  
	G ((color = BLACK | num_of_cubes = ZERO) & spec_stage = WAIT -> 
		spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (color != BLACK & num_of_cubes != ZERO & spec_stage = WAIT  & spec_pausing = go  ->
		verMot = MOVE  & color = next(spec_currentColor) & next(spec_stage) = KICK);

guarantee  
	G (ack_ver_hor = SLEEP & spec_stage = KICK  & spec_pausing = go  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

 
 
guarantee  
	G (atEdge != EDGE & spec_stage = TOANGLERIGHT & detect != spec_currentColor & spec_pausing = go  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

guarantee  
	G (atEdge = EDGE & spec_stage = TOANGLERIGHT & spec_pausing = go  & detect != spec_currentColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);
 
guarantee  
	G (spec_stage = TOANGLELEFT & spec_pausing = go  & detect != spec_currentColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);

guarantee  
	G ((spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & spec_pausing = go & detect = spec_currentColor ->
		verMot = SLEEP & horMot = MOVE & botMot = STOP & next(spec_stage) = DROP );

 
	 
guarantee  
	G (((ack_ver_hor = SLEEP & spec_stage = DROP) | ((ack_bot = MOVE | (ack_bot = SLEEP & PREV(spec_pausing = pause))) & spec_stage = FROMANGLE)) & spec_pausing = go ->
		botMot = INITPOS & next(spec_stage) = FROMANGLE);

guarantee
	G (spec_finished_cycle <-> ack_bot = SLEEP & PREV(spec_pausing = go) & spec_stage = FROMANGLE & spec_pausing = go);

guarantee  
	G (spec_finished_cycle -> spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (spec_finished_cycle <-> reduce_num_of_cubes = REDUCE);

 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed = true);


guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);

 

assumption  
  respondsTo(ack_ver_hor=MOVE,(ack_ver_hor=SLEEP));
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption
	G (spec_stage != KICK & spec_stage != DROP -> ack_ver_hor = SLEEP);
	
assumption  
  respondsTo(num_of_cubes!=ZERO,(num_of_cubes=ZERO));

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {NOEDGE, EDGE} atEdge ;
		
		env {ZERO, NOTZERO} num_of_cubes;
		
		env {PRESS, RELEASE} haltButton;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {RIGHT, LEFT, STOP, INITPOS} botMot ;
		
		sys boolean spec_allsleep ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {REDUCE, NOTREDUCE} reduce_num_of_cubes;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys {WAIT, KICK, TOANGLERIGHT, TOANGLELEFT, DROP, FROMANGLE} spec_stage ;
		sys boolean spec_finished_cycle;
		
		sys boolean spec_speedButtonValidPressed ;
		sys boolean spec_haltButtonValidPressed ;
		
		sys {PAUSE, GO} spec_pausing ;

guarantee
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_haltButtonValidPressed = true);

guarantee
	G ((spec_haltButtonValidPressed = true & spec_pausing = GO) | (spec_haltButtonValidPressed = false & spec_pausing = PAUSE)
		-> next(spec_pausing) = PAUSE);
	
guarantee
	G ((spec_haltButtonValidPressed = false & spec_pausing = GO) | (spec_haltButtonValidPressed = true & spec_pausing = PAUSE)
		-> next(spec_pausing) = GO);

guarantee  
  respondsTo(spec_haltButtonValidPressed=true&spec_pausing=GO,(spec_haltButtonValidPressed=true));
	
guarantee  
	G (spec_pausing = PAUSE | ack_ver_hor = MOVE -> 
		spec_allsleep = true & next(spec_stage) = spec_stage);
	
guarantee  
	G (spec_stage != WAIT -> next(spec_currentColor) = spec_currentColor);

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (spec_allsleep = true <-> verMot = SLEEP  & horMot = SLEEP & botMot = STOP);
	
guarantee  
	motSpeed = LEVEL1 & spec_stage = WAIT & spec_pausing = GO;
	
 

 

guarantee  
	G ((color = BLACK | num_of_cubes = ZERO) & spec_stage = WAIT -> 
		spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (color != BLACK & num_of_cubes != ZERO & spec_stage = WAIT  & spec_pausing = GO  ->
		verMot = MOVE  & color = next(spec_currentColor) & next(spec_stage) = KICK);

guarantee  
	G (ack_ver_hor = SLEEP & spec_stage = KICK  & spec_pausing = GO  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

 
 
guarantee  
	G (atEdge != EDGE & (spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & detect != spec_currentColor & spec_pausing = GO  ->
		(spec_stage = TOANGLERIGHT -> botMot = RIGHT) & (spec_stage = TOANGLELEFT -> botMot = LEFT) & next(spec_stage) = spec_stage);

guarantee  
	G (atEdge = EDGE & (spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & spec_pausing = GO  & detect != spec_currentColor ->
		(spec_stage = TOANGLERIGHT -> botMot = LEFT & next(spec_stage) = TOANGLELEFT) & (spec_stage = TOANGLELEFT -> botMot = RIGHT & next(spec_stage) = TOANGLERIGHT));
 /* 
LTLSPEC  
	G (spec_stage = TOANGLELEFT & spec_pausing = GO  & detect != spec_currentColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);
*/
guarantee  
	G ((spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & spec_pausing = GO & detect = spec_currentColor ->
		verMot = SLEEP & horMot = MOVE & botMot = STOP & next(spec_stage) = DROP );

 
	 
guarantee  
	G (((ack_ver_hor = SLEEP & spec_stage = DROP) | ((ack_bot = MOVE | (ack_bot = SLEEP & PREV(spec_pausing = PAUSE))) & spec_stage = FROMANGLE)) & spec_pausing = GO ->
		botMot = INITPOS & next(spec_stage) = FROMANGLE);

guarantee
	G (spec_finished_cycle <-> ack_bot = SLEEP & PREV(spec_pausing = GO) & spec_stage = FROMANGLE & spec_pausing = GO);

guarantee  
	G (spec_finished_cycle -> spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (spec_finished_cycle <-> reduce_num_of_cubes = REDUCE);

 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed = true);


guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);

 

assumption  
  respondsTo(ack_ver_hor=MOVE,(ack_ver_hor=SLEEP));
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption
	G (spec_stage != KICK & spec_stage != DROP -> ack_ver_hor = SLEEP);
	
assumption  
  respondsTo(num_of_cubes!=ZERO,(num_of_cubes=ZERO));

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} color ;
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {YES, NO} starting_pos ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
	define
		allsleep := verMot = SLEEP & horMot = SLEEP & botMot = STOP;
	define
		nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
	define
		verhor_dontmove := ack_ver = SLEEP & ack_hor = SLEEP;
	define
		onlybotmoves := verhor_dontmove & ack_bot = MOVE;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);

 
guarantee 
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
guarantee
	G (verMot = MOVE -> color = next(spec_currentColor));
	
guarantee  
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & horMot = SLEEP);
	
 

guarantee  
	!spec_dropping & motSpeed = LEVEL1;

guarantee  
	G (!spec_dropping & starting_pos = NO & verhor_dontmove <-> botMot = RETURN);
		
 
		
guarantee
	G (!spec_dropping & starting_pos = YES & color = BLACK -> allsleep);
	
guarantee
	G (color = BLACK | spec_dropping -> verMot = SLEEP);
	
guarantee
	G (!spec_dropping & starting_pos = YES & nonemove & color != BLACK <-> verMot = MOVE);
	
guarantee  
	G (spec_dropping & detect != spec_currentColor & verhor_dontmove <-> botMot = SEEK);

guarantee  
	G (spec_dropping & detect = spec_currentColor & verhor_dontmove <-> horMot = MOVE);
	
 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL1 -> next(motSpeed = LEVEL2));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL2 -> next(motSpeed = LEVEL3));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL3 -> next(motSpeed = LEVEL1));
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed -> motSpeed = next(motSpeed));

	
 
 
  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));

assumption  
  GF (color!=BLACK);
	
assumption
  GF (ack_hor=MOVE);
	
 

guarantee
  respondsTo(color!=BLACK,(horMot=MOVE&detect=spec_currentColor));
 
guarantee
  GF (horMot=MOVE);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {NOEDGE, EDGE} atEdge ;
		env boolean color_seen ;
		
		
		env {PRESS, RELEASE} haltButton;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {PLACE, RIGHT, LEFT, STOP, INITPOS} botMot ;
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} botMotColor ;
		sys boolean store_place ;
		
		sys boolean spec_allsleep ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2} spec_state ;
		
		sys {WAIT, KICK, TOANGLEPLACE, TOANGLERIGHT, TOANGLELEFT, DROP, FROMANGLE} spec_stage ;
		
		sys boolean spec_speedButtonValidPressed ;
		sys boolean spec_haltButtonValidPressed ;
		
		sys {pause, go} spec_pausing ;

guarantee  
  spec_state=S0;

guarantee  
  G ((spec_state=S0 & ((!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(detect = botMotColor)) | ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP)) | (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = botMotColor)) | (!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP) & (detect = botMotColor))) & next(spec_state=S0)) |
  (spec_state=S0 & ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = botMotColor)) & next(spec_state=S1)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = botMotColor)) & next(spec_state=S0)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = botMotColor)) & next(spec_state=S1)) |
  (spec_state=S1 & ((ack_ver_hor = MOVE & spec_stage = DROP)) & next(spec_state=S2)) |
  (spec_state=S2 & next(spec_state=S2)));

guarantee  
  GF (spec_state=S0|spec_state=S1);

guarantee
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_haltButtonValidPressed = true);

guarantee
	G ((spec_haltButtonValidPressed = true & spec_pausing = go) | (spec_haltButtonValidPressed = false & spec_pausing = pause)
		-> next(spec_pausing) = pause);
	
guarantee
	G ((spec_haltButtonValidPressed = false & spec_pausing = go) | (spec_haltButtonValidPressed = true & spec_pausing = pause)
		-> next(spec_pausing) = go);

guarantee  
  respondsTo(spec_haltButtonValidPressed=true&spec_pausing=go,(spec_haltButtonValidPressed=true));
	
guarantee  
	G (spec_pausing = pause | ack_ver_hor = MOVE -> 
		spec_allsleep = true & next(spec_stage) = spec_stage);
	
guarantee  
	G (spec_stage != WAIT -> next(botMotColor) = botMotColor);

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (spec_allsleep = true <-> verMot = SLEEP  & horMot = SLEEP & botMot = STOP);
	
guarantee  
	store_place = false & motSpeed = LEVEL1 & spec_stage = WAIT & spec_pausing = go;
	
 

 

guarantee  
	G (color = BLACK & spec_stage = WAIT -> 
		spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (color != BLACK & spec_stage = WAIT  & spec_pausing = go  ->
		verMot = MOVE  & color = next(botMotColor) & next(spec_stage) = KICK);

guarantee  
	G (ack_ver_hor = SLEEP & spec_stage = KICK  & spec_pausing = go & color_seen = false  ->
		(color_seen = false -> botMot = RIGHT & next(spec_stage) = TOANGLERIGHT) & (color_seen = true -> botMot = PLACE & next(spec_stage) = TOANGLERIGHT));

 
		
guarantee
	G (ack_bot = MOVE & spec_stage = TOANGLEPLACE & spec_pausing = go ->
		botMot = PLACE & next(spec_stage) = TOANGLERIGHT);
		
guarantee
	G (ack_bot = SLEEP & spec_stage = TOANGLEPLACE & spec_pausing = go ->
		horMot = MOVE & next(spec_stage) = DROP);

 
 
guarantee  
	G (atEdge != EDGE & spec_stage = TOANGLERIGHT & detect != botMotColor & spec_pausing = go  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

guarantee  
	G (atEdge = EDGE & spec_stage = TOANGLERIGHT & spec_pausing = go  & detect != botMotColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);
 
guarantee  
	G (spec_stage = TOANGLELEFT & spec_pausing = go  & detect != botMotColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);

guarantee  
	G ((spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & spec_pausing = go & detect = botMotColor ->
		horMot = MOVE & next(spec_stage) = DROP);
		
guarantee
	G (store_place = true <-> (spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & spec_pausing = go & detect = botMotColor);

 
	 
guarantee  
	G (((ack_ver_hor = SLEEP & spec_stage = DROP) | ((ack_bot = MOVE | (ack_bot = SLEEP & PREV(spec_pausing = pause))) & spec_stage = FROMANGLE)) & spec_pausing = go ->
		botMot = INITPOS & next(spec_stage) = FROMANGLE);

guarantee  
	G (ack_bot = SLEEP & PREV(spec_pausing = go) & spec_stage = FROMANGLE & spec_pausing = go -> 
		spec_allsleep & next(spec_stage) = WAIT);

 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed = true);


guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);

 

assumption  
  respondsTo(ack_ver_hor=MOVE,(ack_ver_hor=SLEEP));
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption
	G (spec_stage != KICK & spec_stage != DROP -> ack_ver_hor = SLEEP);

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys { S0, S1, S2} spec_state_1 ;
		sys { S0, S1, S2} spec_state_2 ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	spec_allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	spec_nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee  
	motSpeed = LEVEL1;
	
 

guarantee
	G (color = BLACK & spec_nonemove & spec_allsleep -> spec_allsleep);
/*	
LTLSPEC
	G (color != BLACK & spec_nonemove & spec_allsleep -> verMot = MOVE & next(spec_currentColor) = color);
	 
LTLSPEC  
  spec_state_1=S0;

LTLSPEC  
  G ((spec_state_1=S0 & ((!(verMot = MOVE) & !(ack_ver = SLEEP -> botMot = SEEK)) | ((verMot = MOVE) & (detect = spec_currentColor)) | (!(detect = spec_currentColor) & (ack_ver = SLEEP -> botMot = SEEK)) | (!(verMot = MOVE) & (detect = spec_currentColor) & (ack_ver = SLEEP -> botMot = SEEK))) & next(spec_state_1=S0)) |
  (spec_state_1=S0 & ((verMot = MOVE) & !(detect = spec_currentColor) & !(ack_ver = SLEEP -> botMot = SEEK)) & next(spec_state_1=S2)) |
  (spec_state_1=S1 & TRUE & next(spec_state_1=S1)) |
  (spec_state_1=S2 & (!(detect = spec_currentColor) & (ack_ver = SLEEP -> botMot = SEEK)) & next(spec_state_1=S0)) |
  (spec_state_1=S2 & ((detect = spec_currentColor)) & next(spec_state_1=S1)) |
  (spec_state_1=S2 & (!(detect = spec_currentColor) & !(ack_ver = SLEEP -> botMot = SEEK)) & next(spec_state_1=S2)));

LTLSPECENV  
  (G F (spec_state_1=S0));
	
LTLSPEC
	G (detect = spec_currentColor & PREV(botMot) = SEEK -> horMot = MOVE);
	
LTLSPEC  
  spec_state_2=S0;

LTLSPEC  
  G ((spec_state_2=S0 & ((!(horMot = MOVE) & !(ack_hor = SLEEP -> botMot = RETURN)) | ((horMot = MOVE) & (ack_bot = SLEEP)) | (!(ack_bot = SLEEP) & (ack_hor = SLEEP -> botMot = RETURN)) | (!(horMot = MOVE) & (ack_bot = SLEEP) & (ack_hor = SLEEP -> botMot = RETURN))) & next(spec_state_2=S0)) |
  (spec_state_2=S0 & ((horMot = MOVE) & !(ack_bot = SLEEP) & !(ack_hor = SLEEP -> botMot = RETURN)) & next(spec_state_2=S2)) |
  (spec_state_2=S1 & TRUE & next(spec_state_2=S1)) |
  (spec_state_2=S2 & (!(ack_bot = SLEEP) & (ack_hor = SLEEP -> botMot = RETURN)) & next(spec_state_2=S0)) |
  (spec_state_2=S2 & ((ack_bot = SLEEP)) & next(spec_state_2=S1)) |
  (spec_state_2=S2 & (!(ack_bot = SLEEP) & !(ack_hor = SLEEP -> botMot = RETURN)) & next(spec_state_2=S2)));

LTLSPECENV  
  (G F (spec_state_2=S0));
  
 	
LTLSPEC
	G ((ack_hor = SLEEP & PREV(ack_hor) = MOVE) | (PREV(botMot) = RETURN & PREV(ack_bot) = MOVE) -> botMot = RETURN);

LTLSPEC
	G (PREV(botMot) = RETURN & PREV(ack_bot) = SLEEP -> spec_allsleep);
*/
 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

guarantee
  respondsTo(color!=BLACK,(detect=spec_currentColor&horMot=MOVE));

guarantee
  GF (horMot=MOVE);

 

assumption  
  respondsTo(ack_ver=MOVE,(ack_ver=SLEEP));
assumption  
  respondsTo(ack_hor=MOVE,(ack_hor=SLEEP));
assumption  
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		sys { S0, S1, S2} spec_state_1 ;
		sys { S0, S1, S2} spec_state_2 ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	spec_allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	spec_nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor) & spec_dropping = next(spec_dropping));
	
 

guarantee
	G (spec_dropping -> verMot = SLEEP);
	
guarantee
	G (horMot = MOVE <-> spec_dropping & detect = spec_currentColor);

guarantee
	G (color = BLACK & !spec_dropping -> spec_allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color & next(spec_dropping));
	 
guarantee  
  spec_state_1=S0;

guarantee  
  G ((spec_state_1=S0 & ((!(verMot = MOVE) & !(detect = spec_currentColor)) | ((detect = spec_currentColor))) & next(spec_state_1=S0)) |
  (spec_state_1=S0 & ((verMot = MOVE) & !(botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state_1=S1)) |
  (spec_state_1=S0 & ((verMot = MOVE) & (botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state_1=S2)) |
  (spec_state_1=S1 & next(spec_state_1=S1)) |
  (spec_state_1=S2 & ((detect = spec_currentColor)) & next(spec_state_1=S0)) |
  (spec_state_1=S2 & (!(botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state_1=S1)) |
  (spec_state_1=S2 & ((botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state_1=S2)));

assumption  
  GF (spec_state_1=S0|spec_state_1=S2);

 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

assumption  
  GF (color!=BLACK);
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2} spec_state__seek ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	spec_allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	spec_nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(PREV(botMot = RETURN) & ack_bot = SLEEP));
	
guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> spec_allsleep);
	
assumption
	G (!spec_dropping -> spec_nonemove);
	
assumption
	G (ack_hor = MOVE <-> detect = spec_currentColor & (PREV(horMot = MOVE) | PREV(ack_hor = MOVE)));
	
assumption
	G (horMot = MOVE -> PREV(ack_ver = SLEEP));
	
 

guarantee
	G (spec_dropping -> verMot = SLEEP);
	
guarantee
	G (!spec_dropping -> botMot = STOP & horMot = SLEEP);

guarantee
	G (color = BLACK & !spec_dropping -> spec_allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color & next(spec_dropping));
	 
guarantee
	G (ack_ver = SLEEP & PREV(ack_ver = MOVE) & spec_dropping -> botMot = SEEK);

guarantee  
  spec_state__seek=S0;

guarantee  
  G ((spec_state__seek=S0 & ((!(botMot = SEEK) & !(detect = spec_currentColor)) | ((detect = spec_currentColor))) & next(spec_state__seek=S0)) |
  (spec_state__seek=S0 & ((botMot = SEEK) & !(botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state__seek=S1)) |
  (spec_state__seek=S0 & ((botMot = SEEK) & (botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state__seek=S2)) |
  (spec_state__seek=S1 & next(spec_state__seek=S1)) |
  (spec_state__seek=S2 & ((detect = spec_currentColor)) & next(spec_state__seek=S0)) |
  (spec_state__seek=S2 & (!(botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state__seek=S1)) |
  (spec_state__seek=S2 & ((botMot = SEEK) & !(detect = spec_currentColor)) & next(spec_state__seek=S2)));

assumption  
  GF (spec_state__seek=S0|spec_state__seek=S2);

guarantee
	G (spec_dropping & detect = spec_currentColor & PREV(botMot != STOP) <-> horMot = MOVE);

 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

assumption  
  GF (color!=BLACK);
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2} spec_state__return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP );
/* 	*/
guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color & next(spec_dropping));
	 
guarantee
	G ((nonemove & spec_dropping) | (PREV(botMot = SEEK) & onlybotmoves & detect != spec_currentColor) -> botMot = SEEK);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) -> horMot = MOVE);
/* 	
LTLSPEC
	G (nonemove & PREV(ack_hor) = MOVE & spec_dropping -> botMot = RETURN);

LTLSPEC  
  spec_state__return=S0;

LTLSPEC  
  G ((spec_state__return=S0 & ((!(botMot = RETURN) & !(ack_bot = SLEEP)) | ((ack_bot = SLEEP))) & next(spec_state__return=S0)) |
  (spec_state__return=S0 & ((botMot = RETURN) & !(botMot = RETURN) & !(ack_bot = SLEEP)) & next(spec_state__return=S1)) |
  (spec_state__return=S0 & ((botMot = RETURN) & (botMot = RETURN) & !(ack_bot = SLEEP)) & next(spec_state__return=S2)) |
  (spec_state__return=S1 & TRUE & next(spec_state__return=S1)) |
  (spec_state__return=S2 & ((ack_bot = SLEEP)) & next(spec_state__return=S0)) |
  (spec_state__return=S2 & (!(botMot = RETURN) & !(ack_bot = SLEEP)) & next(spec_state__return=S1)) |
  (spec_state__return=S2 & ((botMot = RETURN) & !(ack_bot = SLEEP)) & next(spec_state__return=S2)));

LTLSPECENV  
  (G F (spec_state__return=S0 | spec_state__return=S2));

LTLSPEC
	G (PREV(botMot) = RETURN & ack_bot = SLEEP -> allsleep & next(spec_dropping) = FALSE);
*/
 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

assumption  
  GF (color!=BLACK);
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
  G(spec_prevBotMotReturn<->PREV(botMot = RETURN));
  
  sys boolean spec_prevBotMotReturn ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & nonemove));
/* 	*/
guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);
	 
guarantee
	G ((nonemove & spec_dropping & PREV(ack_hor != MOVE)) | (PREV(botMot = SEEK) & onlybotmoves & detect != spec_currentColor) -> botMot = SEEK);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE)) | ((spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_prevBotMotReturn & ack_bot = MOVE))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_dropping & onlybotmoves -> botMot = RETURN) & (spec_prevBotMotReturn & ack_bot = MOVE)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & (spec_prevBotMotReturn & ack_bot = MOVE)) & next(spec_state_return=S3)) |
  (spec_state_return=S1 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S1 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_dropping & onlybotmoves -> botMot = RETURN)) & next(spec_state_return=S1)) |
  (spec_state_return=S1 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & !(spec_dropping & onlybotmoves -> botMot = RETURN)) & next(spec_state_return=S3)) |
  (spec_state_return=S2 & next(spec_state_return=S2)) |
  (spec_state_return=S3 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S3 & (!(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S3)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S1|spec_state_return=S3);
/* 
LTLSPEC
	G (spec_dropping & PREV(botMot) = RETURN & nonemove -> allsleep);
*/
 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
  
  
assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_seek ;
		sys { S0, S1, S2, S3} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
	G (spec_prevBotMotReturn<->PREV(botMot = RETURN));
guarantee
	G (spec_prevBotMotSeek<->PREV(botMot = SEEK));
  
  sys boolean spec_prevBotMotReturn ;
  sys boolean spec_prevBotMotSeek ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & nonemove));
/* 	*/
guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);
	 
guarantee
	G ((nonemove & spec_dropping & PREV(ack_hor != MOVE)) -> botMot = SEEK);

 
 
guarantee  
  spec_state_seek=S0;

guarantee  
  G ((spec_state_seek=S0 & ((!(spec_prevBotMotSeek & ack_bot = MOVE)) | ((spec_prevBotMotSeek & detect = spec_currentColor) & (spec_prevBotMotSeek & ack_bot = MOVE))) & next(spec_state_seek=S0)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S1 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S0)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S2 & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & (!(spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S3)));

guarantee  
  GF (spec_state_seek=S0|spec_state_seek=S1|spec_state_seek=S3);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE)) | ((spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_prevBotMotReturn & ack_bot = MOVE))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_dropping & onlybotmoves -> botMot = RETURN) & (spec_prevBotMotReturn & ack_bot = MOVE)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & (spec_prevBotMotReturn & ack_bot = MOVE)) & next(spec_state_return=S3)) |
  (spec_state_return=S1 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S1 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_dropping & onlybotmoves -> botMot = RETURN)) & next(spec_state_return=S1)) |
  (spec_state_return=S1 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & !(spec_dropping & onlybotmoves -> botMot = RETURN)) & next(spec_state_return=S3)) |
  (spec_state_return=S2 & next(spec_state_return=S2)) |
  (spec_state_return=S3 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S3 & (!(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S3)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S1|spec_state_return=S3);
/* 
LTLSPEC
	G (spec_dropping & PREV(botMot) = RETURN & nonemove -> allsleep);
*/
 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;
   

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
   
   /* 
LTLSPEC  
  !spec_waiting_ack_bot_mot;  
  
LTLSPEC  
  G(!spec_waiting_ack_bot_mot & botMot=STOP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (!spec_waiting_ack_bot_mot & botMot!=STOP -> next(spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot=SLEEP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot!=SLEEP -> next(spec_waiting_ack_bot_mot));

LTLSPECENV  
  G(!spec_waiting_ack_bot_mot -> ack_bot=SLEEP);
LTLSPECENV  
  G(spec_waiting_ack_bot_mot -> F(ack_bot=SLEEP)); 
  */
assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_seek ;
		sys { S0, S1, S2, S3} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
	G (spec_prevBotMotReturn<->PREV(botMot = RETURN));
guarantee
	G (spec_prevBotMotSeek<->PREV(botMot = SEEK));
  
  sys boolean spec_prevBotMotReturn ;
  sys boolean spec_prevBotMotSeek ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & ack_bot = SLEEP));
/* 	*/
guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);
	 
guarantee
	G (nonemove & spec_dropping & PREV(ack_hor != MOVE)-> botMot = SEEK);

 
 
guarantee  
  spec_state_seek=S0;

guarantee  
  G ((spec_state_seek=S0 & ((!(spec_prevBotMotSeek & ack_bot = MOVE)) | ((spec_prevBotMotSeek & detect = spec_currentColor) & (spec_prevBotMotSeek & ack_bot = MOVE))) & next(spec_state_seek=S0)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S1 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S0)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & onlybotmoves & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S2 & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & (!(spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S3)));

guarantee  
  GF (spec_state_seek=S0|spec_state_seek=S1|spec_state_seek=S3);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE)) | ((spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_prevBotMotReturn & ack_bot = MOVE))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_dropping & onlybotmoves -> botMot = RETURN) & (spec_prevBotMotReturn & ack_bot = MOVE)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & (spec_prevBotMotReturn & ack_bot = MOVE)) & next(spec_state_return=S3)) |
  (spec_state_return=S1 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S1 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & (spec_dropping & onlybotmoves -> botMot = RETURN)) & next(spec_state_return=S1)) |
  (spec_state_return=S1 & (!(spec_prevBotMotReturn & ack_bot = SLEEP) & !(spec_dropping & onlybotmoves -> botMot = RETURN)) & next(spec_state_return=S3)) |
  (spec_state_return=S2 & next(spec_state_return=S2)) |
  (spec_state_return=S3 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S3 & (!(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S3)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S1|spec_state_return=S3);
/* 
LTLSPEC
	G (spec_dropping & PREV(botMot) = RETURN & nonemove -> allsleep);
*/
 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;
   

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
   
   /* 
LTLSPEC  
  !spec_waiting_ack_bot_mot;  
  
LTLSPEC  
  G(!spec_waiting_ack_bot_mot & botMot=STOP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (!spec_waiting_ack_bot_mot & botMot!=STOP -> next(spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot=SLEEP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot!=SLEEP -> next(spec_waiting_ack_bot_mot));

LTLSPECENV  
  G(!spec_waiting_ack_bot_mot -> ack_bot=SLEEP);
LTLSPECENV  
  G(spec_waiting_ack_bot_mot -> F(ack_bot=SLEEP)); 
  */
assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_seek ;
		sys { S0, S1, S2} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
	G (spec_prevBotMotReturn<->PREV(botMot = RETURN));
guarantee
	G (spec_prevBotMotSeek<->PREV(botMot = SEEK));
  
  sys boolean spec_prevBotMotReturn ;
  sys boolean spec_prevBotMotSeek ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & ack_bot = SLEEP));
/* 	*/
guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);
	 
guarantee
	G (nonemove & spec_dropping & PREV(ack_ver = MOVE)-> botMot = SEEK);

 
 
guarantee  
  spec_state_seek=S0;

guarantee  
  G ((spec_state_seek=S0 & ((!(spec_prevBotMotSeek & ack_bot = MOVE)) | ((spec_prevBotMotSeek & detect = spec_currentColor) & (spec_prevBotMotSeek & ack_bot = MOVE))) & next(spec_state_seek=S0)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S1 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S0)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S2 & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & (!(spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S3)));

guarantee  
  GF (spec_state_seek=S0|spec_state_seek=S1|spec_state_seek=S3);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) | ((spec_prevBotMotReturn & ack_bot = SLEEP))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & (spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S1 & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S2 & (!(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S2);
 
guarantee
	G (spec_prevBotMotReturn & ack_bot = SLEEP -> allsleep);
/**/
 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;
   

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
   
   /* 
LTLSPEC  
  !spec_waiting_ack_bot_mot;  
  
LTLSPEC  
  G(!spec_waiting_ack_bot_mot & botMot=STOP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (!spec_waiting_ack_bot_mot & botMot!=STOP -> next(spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot=SLEEP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot!=SLEEP -> next(spec_waiting_ack_bot_mot));

LTLSPECENV  
  G(!spec_waiting_ack_bot_mot -> ack_bot=SLEEP);
LTLSPECENV  
  G(spec_waiting_ack_bot_mot -> F(ack_bot=SLEEP)); 
  */
assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_seek ;
		sys { S0, S1, S2} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
	G (spec_prevBotMotReturn<->PREV(botMot = RETURN));
guarantee
	G (spec_prevBotMotSeek<->PREV(botMot = SEEK));
  
  sys boolean spec_prevBotMotReturn ;
  sys boolean spec_prevBotMotSeek ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & ack_bot = SLEEP));

guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
/*	 
LTLSPEC
  G (spec_prevBotMotSeek & ack_bot = MOVE -> F (spec_prevBotMotSeek & detect = spec_currentColor));

LTLSPEC
  G F (horMot = MOVE);
*/	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);
	 
guarantee
	G (nonemove & spec_dropping & PREV(ack_ver = MOVE)-> botMot = SEEK);

 
 
guarantee  
  spec_state_seek=S0;

guarantee  
  G ((spec_state_seek=S0 & ((!(spec_prevBotMotSeek & ack_bot = MOVE)) | ((spec_prevBotMotSeek & detect = spec_currentColor) & (spec_prevBotMotSeek & ack_bot = MOVE))) & next(spec_state_seek=S0)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S1 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S0)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S2 & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & (!(spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S3)));

guarantee  
  GF (spec_state_seek=S0|spec_state_seek=S1|spec_state_seek=S3);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) | ((spec_prevBotMotReturn & ack_bot = SLEEP))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & (spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S1 & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S2 & (!(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S2);
 
guarantee
	G (spec_prevBotMotReturn & ack_bot = SLEEP -> allsleep);

 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;
   

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
   
/*   
LTLSPEC  
  !spec_waiting_ack_bot_mot;  
  
LTLSPEC  
  G(!spec_waiting_ack_bot_mot & botMot=STOP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (!spec_waiting_ack_bot_mot & botMot!=STOP -> next(spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot=SLEEP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot!=SLEEP -> next(spec_waiting_ack_bot_mot));

LTLSPECENV  
  G(!spec_waiting_ack_bot_mot -> ack_bot=SLEEP);
LTLSPECENV  
  G(spec_waiting_ack_bot_mot -> F(ack_bot=SLEEP)); 
   */
  
assumption
  respondsTo(ack_ver=MOVE,(ack_ver=SLEEP));
assumption
  respondsTo(ack_hor=MOVE,(ack_hor=SLEEP));
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_seek ;
		sys { S0, S1, S2} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
	G (spec_prevBotMotReturn<->PREV(botMot = RETURN));
guarantee
	G (spec_prevBotMotSeek<->PREV(botMot = SEEK));
  
  sys boolean spec_prevBotMotReturn ;
  sys boolean spec_prevBotMotSeek ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & ack_bot = SLEEP));

guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
/*	*/ 
guarantee
  respondsTo(color!=BLACK,(horMot=MOVE&detect=spec_currentColor));

guarantee
  GF (horMot=MOVE);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);

guarantee
	G (nonemove & spec_dropping & PREV(ack_ver = MOVE)-> botMot = SEEK);
 
 
 
guarantee  
  spec_state_seek=S0;

guarantee  
  G ((spec_state_seek=S0 & ((!(spec_prevBotMotSeek & ack_bot = MOVE)) | ((spec_prevBotMotSeek & detect = spec_currentColor) & (spec_prevBotMotSeek & ack_bot = MOVE))) & next(spec_state_seek=S0)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S1 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S0)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S2 & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & (!(spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S3)));

guarantee  
  GF (spec_state_seek=S0|spec_state_seek=S1|spec_state_seek=S3);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) | ((spec_prevBotMotReturn & ack_bot = SLEEP))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & (spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S1 & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S2 & (!(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S2);
 
guarantee
	G (spec_prevBotMotReturn & ack_bot = SLEEP -> allsleep);

 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);


 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;
   

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
   
/*   
LTLSPEC  
  !spec_waiting_ack_bot_mot;  
  
LTLSPEC  
  G(!spec_waiting_ack_bot_mot & botMot=STOP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (!spec_waiting_ack_bot_mot & botMot!=STOP -> next(spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot=SLEEP -> next(!spec_waiting_ack_bot_mot));
LTLSPEC
  G (spec_waiting_ack_bot_mot & ack_bot!=SLEEP -> next(spec_waiting_ack_bot_mot));

LTLSPECENV  
  G(!spec_waiting_ack_bot_mot -> ack_bot=SLEEP);
LTLSPECENV  
  G(spec_waiting_ack_bot_mot -> F(ack_bot=SLEEP)); 
   */
  
assumption
  respondsTo(ack_ver=MOVE,(ack_ver=SLEEP));
assumption
  respondsTo(ack_hor=MOVE,(ack_hor=SLEEP));
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));
	
assumption
  GF (ack_hor=MOVE);

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		 
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_seek ;
		sys { S0, S1, S2} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		/*ext spec_haltButtonValidPressed : boolean;
		
		ext spec_pausing : {PAUSE, GO};*/
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
	G (spec_prevBotMotReturn<->PREV(botMot = RETURN));
guarantee
	G (spec_prevBotMotSeek<->PREV(botMot = SEEK));
  
  sys boolean spec_prevBotMotReturn ;
  sys boolean spec_prevBotMotSeek ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & ack_bot = SLEEP));

guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
/*	*/ 
guarantee
  respondsTo(color!=BLACK,(horMot=MOVE&detect=spec_currentColor));

guarantee
  GF (horMot=MOVE);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);

guarantee
	G (nonemove & spec_dropping & PREV(ack_ver = MOVE)-> botMot = SEEK);
 
 
 
guarantee  
  spec_state_seek=S0;

guarantee  
  G ((spec_state_seek=S0 & ((!(spec_prevBotMotSeek & ack_bot = MOVE)) | ((spec_prevBotMotSeek & detect = spec_currentColor) & (spec_prevBotMotSeek & ack_bot = MOVE))) & next(spec_state_seek=S0)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S1 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S0)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S2 & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & (!(spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S3)));

guarantee  
  GF (spec_state_seek=S0|spec_state_seek=S1|spec_state_seek=S3);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) | ((spec_prevBotMotReturn & ack_bot = SLEEP))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & (spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S1 & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S2 & (!(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S2);
 
guarantee
	G (spec_prevBotMotReturn & ack_bot = SLEEP -> allsleep);

 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);
/* 
 

LTLSPEC
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_haltButtonValidPressed);

LTLSPEC
	G ((spec_haltButtonValidPressed & spec_pausing = GO) | (!spec_haltButtonValidPressed & spec_pausing = PAUSE)
		-> next(spec_pausing) = PAUSE);
	
LTLSPEC
	G ((!spec_haltButtonValidPressed & spec_pausing = GO) | (spec_haltButtonValidPressed & spec_pausing = PAUSE)
		-> next(spec_pausing) = GO);

LTLSPECENV  
	G (spec_pausing = PAUSE -> F (spec_pausing = GO));
*/
 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  G(horMot=MOVE -> next(ack_hor=MOVE));
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
  
/*   
LTLSPECENV
	G (ack_ver = MOVE -> F (ack_ver = SLEEP));
LTLSPECENV
	G (ack_hor = MOVE -> F (ack_hor = SLEEP));*/
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption
  GF (ack_hor=MOVE);
	
assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		
		 
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys { S0, S1, S2, S3} spec_state_seek ;
		sys { S0, S1, S2} spec_state_return ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		/*ext spec_haltButtonValidPressed : boolean;
		
		ext spec_pausing : {PAUSE, GO};*/
		
		
define  
	allsleep := verMot = SLEEP  & horMot = SLEEP & botMot = STOP;
define  
	nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
define  
	onlybotmoves := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = MOVE;

guarantee
	G (spec_prevBotMotReturn<->PREV(botMot = RETURN));
guarantee
	G (spec_prevBotMotSeek<->PREV(botMot = SEEK));
  
  sys boolean spec_prevBotMotReturn ;
  sys boolean spec_prevBotMotSeek ;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));

guarantee
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
	
guarantee
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & !(spec_prevBotMotReturn & ack_bot = SLEEP));

guarantee
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);
	
assumption
	G (!spec_dropping -> nonemove);
/*	*/ 
guarantee
  respondsTo(color!=BLACK,(horMot=MOVE&detect=spec_currentColor));

guarantee
  GF (horMot=MOVE);
	
 

guarantee
	G (color = BLACK & !spec_dropping -> allsleep);
	
guarantee
	G (color != BLACK & !spec_dropping -> verMot = MOVE & next(spec_currentColor) = color);

guarantee
	G (nonemove & spec_dropping & PREV(ack_ver = MOVE)-> botMot = SEEK);
 
 
 
guarantee  
  spec_state_seek=S0;

guarantee  
  G ((spec_state_seek=S0 & ((!(spec_prevBotMotSeek & ack_bot = MOVE)) | ((spec_prevBotMotSeek & detect = spec_currentColor) & (spec_prevBotMotSeek & ack_bot = MOVE))) & next(spec_state_seek=S0)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S0 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK) & (spec_prevBotMotSeek & ack_bot = MOVE)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S1 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S0)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & (spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S1)) |
  (spec_state_seek=S1 & (!(spec_prevBotMotSeek & detect = spec_currentColor) & !(spec_dropping & detect != spec_currentColor -> botMot = SEEK)) & next(spec_state_seek=S3)) |
  (spec_state_seek=S2 & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & ((spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S2)) |
  (spec_state_seek=S3 & (!(spec_prevBotMotSeek & detect = spec_currentColor)) & next(spec_state_seek=S3)));

guarantee  
  GF (spec_state_seek=S0|spec_state_seek=S1|spec_state_seek=S3);

guarantee
	G (spec_dropping & onlybotmoves & detect = spec_currentColor & PREV(botMot = SEEK) <-> horMot = MOVE);
 	
guarantee
	G (nonemove & PREV(ack_hor = MOVE) & spec_dropping -> botMot = RETURN);
 
 
guarantee  
  spec_state_return=S0;

guarantee  
  G ((spec_state_return=S0 & ((!(spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) | ((spec_prevBotMotReturn & ack_bot = SLEEP))) & next(spec_state_return=S0)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & !(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S0 & ((spec_prevBotMotReturn & ack_bot = MOVE) & (spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)) |
  (spec_state_return=S1 & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S0)) |
  (spec_state_return=S2 & (!(spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S1)) |
  (spec_state_return=S2 & ((spec_dropping & onlybotmoves -> botMot = RETURN) & !(spec_prevBotMotReturn & ack_bot = SLEEP)) & next(spec_state_return=S2)));

guarantee  
  GF (spec_state_return=S0|spec_state_return=S2);
 
guarantee
	G (spec_prevBotMotReturn & ack_bot = SLEEP -> allsleep);

 

guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (!spec_speedButtonValidPressed & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);
/* 
 

LTLSPEC
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_haltButtonValidPressed);

LTLSPEC
	G ((spec_haltButtonValidPressed & spec_pausing = GO) | (!spec_haltButtonValidPressed & spec_pausing = PAUSE)
		-> next(spec_pausing) = PAUSE);
	
LTLSPEC
	G ((!spec_haltButtonValidPressed & spec_pausing = GO) | (spec_haltButtonValidPressed & spec_pausing = PAUSE)
		-> next(spec_pausing) = GO);

LTLSPECENV  
	G (spec_pausing = PAUSE -> F (spec_pausing = GO));
*/
 

  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  G(verMot=MOVE -> next(ack_ver=MOVE));
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  G(horMot=MOVE -> next(ack_hor=MOVE));
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));
  
/*   
LTLSPECENV
	G (ack_ver = MOVE -> F (ack_ver = SLEEP));
LTLSPECENV
	G (ack_hor = MOVE -> F (ack_hor = SLEEP));*/
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));
	/* 
LTLSPECENV
	G (botMot = MOVE & spec_)
*/
/* 
LTLSPECENV
	G F (ack_hor = MOVE);
*/	
assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} color ;
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {YES, NO} starting_pos ;
		
		env {ZERO, NOTZERO} num_of_cubes;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {REDUCE, NOTREDUCE} reduce_num_of_cubes;
		
		sys {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
	define
		allsleep := verMot = SLEEP & horMot = SLEEP & botMot = STOP;
	define
		nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
	define
		verhor_dontmove := ack_ver = SLEEP & ack_hor = SLEEP;
	define
		onlybotmoves := verhor_dontmove & ack_bot = MOVE;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);

 
guarantee 
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
guarantee
	G (verMot = MOVE -> color = next(spec_currentColor));
	
guarantee  
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & horMot = SLEEP);
	
 

guarantee  
	!spec_dropping & motSpeed = LEVEL1;
	
guarantee  
	G (num_of_cubes = ZERO -> allsleep);
	
guarantee  
	G (!spec_dropping & starting_pos = YES & PREV(botMot = RETURN) <-> reduce_num_of_cubes = REDUCE);

guarantee  
	G (num_of_cubes = NOTZERO & !spec_dropping & starting_pos = NO & verhor_dontmove <-> botMot = RETURN);
		
 
		
guarantee
	G (!spec_dropping & starting_pos = YES & color = BLACK -> allsleep);
	
guarantee
	G (color = BLACK | spec_dropping -> verMot = SLEEP);
	
guarantee
	G (num_of_cubes = NOTZERO & !spec_dropping & starting_pos = YES & nonemove & color != BLACK <-> verMot = MOVE);
	
guarantee  
	G (num_of_cubes = NOTZERO & spec_dropping & detect != spec_currentColor & verhor_dontmove <-> botMot = SEEK);

guarantee  
	G (num_of_cubes = NOTZERO & spec_dropping & detect = spec_currentColor & verhor_dontmove <-> horMot = MOVE);
	
 
	
guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL1 -> next(motSpeed = LEVEL2));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL2 -> next(motSpeed = LEVEL3));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL3 -> next(motSpeed = LEVEL1));
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed -> motSpeed = next(motSpeed));

	
 
 
  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));

assumption  
  GF (color!=BLACK);
	
assumption
  GF (ack_hor=MOVE);
	
 

guarantee
  respondsTo(color!=BLACK,(horMot=MOVE&detect=spec_currentColor));
 
guarantee
  GF (horMot=MOVE);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} color ;
		env {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver ;
		env {MOVE, SLEEP} ack_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {YES, NO} starting_pos ;
		
		env {ZERO, NOTZERO} num_of_cubes;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {SEEK, STOP, RETURN} botMot ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {REDUCE, NOTREDUCE} reduce_num_of_cubes;
		
		sys {GREEN, BLACK, RED, BLUE,  YELLOW , WHITE} spec_currentColor;
		sys boolean spec_dropping ;
		
		sys boolean spec_speedButtonValidPressed ;
		
		
	define
		allsleep := verMot = SLEEP & horMot = SLEEP & botMot = STOP;
	define
		nonemove := ack_ver = SLEEP & ack_hor = SLEEP & ack_bot = SLEEP;
	define
		verhor_dontmove := ack_ver = SLEEP & ack_hor = SLEEP;
	define
		onlybotmoves := verhor_dontmove & ack_bot = MOVE;

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (ack_ver = MOVE | ack_hor = MOVE -> allsleep);

 
guarantee 
	G (verMot = SLEEP -> spec_currentColor = next(spec_currentColor));
guarantee
	G (verMot = MOVE -> color = next(spec_currentColor));
	
guarantee  
	G (spec_dropping = next(spec_dropping) <-> verMot = SLEEP & horMot = SLEEP);
	
 

guarantee  
	!spec_dropping & motSpeed = LEVEL1;
	
guarantee  
	G (num_of_cubes = ZERO -> allsleep);
	
guarantee  
	G (!spec_dropping & starting_pos = YES & PREV(botMot = RETURN) <-> reduce_num_of_cubes = REDUCE);

guarantee  
	G (num_of_cubes = NOTZERO & !spec_dropping & starting_pos = NO & verhor_dontmove <-> botMot = RETURN);
		
 
		
guarantee
	G (!spec_dropping & starting_pos = YES & color = BLACK -> allsleep);
	
guarantee
	G (color = BLACK | spec_dropping -> verMot = SLEEP);
	
guarantee
	G (num_of_cubes = NOTZERO & !spec_dropping & starting_pos = YES & nonemove & color != BLACK <-> verMot = MOVE);
	
guarantee  
	G (num_of_cubes = NOTZERO & spec_dropping & detect != spec_currentColor & verhor_dontmove <-> botMot = SEEK);

guarantee  
	G (num_of_cubes = NOTZERO & spec_dropping & detect = spec_currentColor & verhor_dontmove <-> horMot = MOVE);
	
 
	
guarantee
	motSpeed = LEVEL1 & !spec_dropping;

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed);


guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL1 -> next(motSpeed = LEVEL2));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL2 -> next(motSpeed = LEVEL3));
	
guarantee  
	G (spec_speedButtonValidPressed & motSpeed = LEVEL3 -> next(motSpeed = LEVEL1));
	 
	 
guarantee  
	G (!spec_speedButtonValidPressed -> motSpeed = next(motSpeed));

	
 
 
  sys boolean spec_waiting_ack_ver_mot;
  sys boolean spec_waiting_ack_hor_mot;

guarantee  
  !spec_waiting_ack_ver_mot;  
  
guarantee  
  G(!spec_waiting_ack_ver_mot & verMot!=MOVE -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (!spec_waiting_ack_ver_mot & verMot=MOVE -> next(spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver=SLEEP -> next(!spec_waiting_ack_ver_mot));
guarantee
  G (spec_waiting_ack_ver_mot & ack_ver!=SLEEP -> next(spec_waiting_ack_ver_mot));

assumption  
  G(!spec_waiting_ack_ver_mot -> ack_ver=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_ver_mot,(ack_ver=SLEEP));
  
  
guarantee  
  !spec_waiting_ack_hor_mot;  
  
guarantee  
  G(!spec_waiting_ack_hor_mot & horMot!=MOVE -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (!spec_waiting_ack_hor_mot & horMot=MOVE -> next(spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor=SLEEP -> next(!spec_waiting_ack_hor_mot));
guarantee
  G (spec_waiting_ack_hor_mot & ack_hor!=SLEEP -> next(spec_waiting_ack_hor_mot));

assumption  
  G(!spec_waiting_ack_hor_mot -> ack_hor=SLEEP);
assumption  
  respondsTo(spec_waiting_ack_hor_mot,(ack_hor=SLEEP));

assumption  
  GF (color!=BLACK);
	
assumption
  GF (ack_hor=MOVE);
	
assumption  
  GF (num_of_cubes!=ZERO);
	
assumption  
  respondsTo(num_of_cubes!=ZERO,(num_of_cubes=ZERO));
	
 

guarantee
  respondsTo(color!=BLACK,(horMot=MOVE&detect=spec_currentColor));
 
guarantee
  GF (horMot=MOVE);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Elevator
		 
		env {LOWER,MIDDLE,UPPER,NONE} floor ;
 
		sys {FWD, BWD, STOP} elevMot ;

 
	 
	
guarantee  
	elevMot=STOP;
	
guarantee  
  GF (elevMot=FWD);

 
 

guarantee  
  GF (floor=LOWER->elevMot=FWD);
	
guarantee  
  GF (floor=UPPER->elevMot=BWD);
	

assumption
    G (elevMot=STOP -> floor!=NONE);

	
	
 
 
 
module GyroAspect
		env {CLEAR, BLOCKED} frontDistSense ;
		env {CLEAR, BLOCKED} backDistSense ;
		env boolean isReady ;
		env {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT, SWITCH_MODE, SPEED_DOWN, SPEED_UP, NOP } bluetoothCmd ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;
		sys { SLOW, REGULAR, FAST } balancerSpeed ;
		sys { AUTO, MANUAL } spec_mode ;
		sys { STP, FWD, BWD, TURN_LEFT, TURN_RIGHT } spec_manualCmd ;


 
guarantee
	balancer=STP;

 
guarantee
	G (!isReady -> balancer=STP);

 
guarantee 
	G ((balancer=FWD) -> (frontDistSense=CLEAR));

 
guarantee 
	G ((balancer=BWD) -> (backDistSense=CLEAR));

 
guarantee 
  GF (spec_mode=AUTO->balancer=FWD);

 
 
define 
  	turningOp := (balancer=TURN_RIGHT | balancer=TURN_LEFT); 
  	
  sys { S0, S1, S2} spec_blockedState ;

guarantee  
  spec_blockedState=S0;

guarantee  
  G ((spec_mode=AUTO & isReady) -> ((spec_blockedState=S0 & ((!(frontDistSense=BLOCKED) & !(frontDistSense=CLEAR)) | (frontDistSense=CLEAR)) & next(spec_blockedState=S0)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & !turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2)) |
  (spec_blockedState=S1 & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (frontDistSense=CLEAR) & next(spec_blockedState=S0)) |
  (spec_blockedState=S2 & (!turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2))));

guarantee  
  GF (spec_mode=AUTO->(spec_blockedState=S0|spec_blockedState=S2));
 

 
 

guarantee  
  spec_mode=AUTO;

guarantee  
  G ((spec_mode=AUTO & bluetoothCmd=SWITCH_MODE & next(spec_mode=MANUAL) & (spec_manualCmd=STP)) | 
  	(spec_mode=MANUAL & bluetoothCmd=SWITCH_MODE & next(spec_mode=AUTO)) | 
  	(bluetoothCmd!=SWITCH_MODE & next(spec_mode)=spec_mode)
  	);

 

 
 

guarantee  
  balancerSpeed=REGULAR;

guarantee  
  G ((balancerSpeed=SLOW & bluetoothCmd=SPEED_DOWN & next(balancerSpeed=SLOW)) | 
  	(balancerSpeed=SLOW & bluetoothCmd=SPEED_UP & next(balancerSpeed=REGULAR)) | 
  	(balancerSpeed=REGULAR & bluetoothCmd=SPEED_DOWN & next(balancerSpeed=SLOW)) | 
  	(balancerSpeed=REGULAR & bluetoothCmd=SPEED_UP & next(balancerSpeed=FAST)) | 
  	(balancerSpeed=FAST & bluetoothCmd=SPEED_DOWN & next(balancerSpeed=REGULAR)) | 
  	(balancerSpeed=FAST & bluetoothCmd=SPEED_UP & next(balancerSpeed=FAST)) | 
  	((bluetoothCmd!=SPEED_DOWN & bluetoothCmd!=SPEED_UP) & next(balancerSpeed)=balancerSpeed)
  	);

 


 
 

 
guarantee
	G ((spec_mode=MANUAL) -> 
		(((bluetoothCmd=STP) -> (spec_manualCmd=STP)) &
		((bluetoothCmd=FWD) -> (spec_manualCmd=FWD)) &
		((bluetoothCmd=BWD) -> (spec_manualCmd=BWD)) &
		((bluetoothCmd=TURN_LEFT) -> (spec_manualCmd=TURN_LEFT)) &
		((bluetoothCmd=TURN_RIGHT) -> (spec_manualCmd=TURN_RIGHT))
	));

 
define
	bluetoothDrivingCmd := ((bluetoothCmd=STP) | (bluetoothCmd=FWD) | (bluetoothCmd=BWD) | (bluetoothCmd=TURN_LEFT) | (bluetoothCmd=TURN_RIGHT));
	
guarantee
	G ((spec_mode=MANUAL) -> 
		((!bluetoothDrivingCmd) -> (
		(PREV(spec_manualCmd=STP) -> spec_manualCmd=STP) &
		(PREV(spec_manualCmd=FWD) -> spec_manualCmd=FWD) &
		(PREV(spec_manualCmd=BWD) -> spec_manualCmd=BWD) &
		(PREV(spec_manualCmd=TURN_LEFT) -> spec_manualCmd=TURN_LEFT) &
		(PREV(spec_manualCmd=TURN_RIGHT) -> spec_manualCmd=TURN_RIGHT)
	)));	
	
guarantee
	G ((spec_mode=MANUAL) -> 
		((spec_manualCmd=FWD) -> ((frontDistSense=CLEAR & isReady)-> balancer=FWD))
	);
	
guarantee
	G ((spec_mode=MANUAL) -> 
		((spec_manualCmd=BWD) -> ((backDistSense=CLEAR & isReady) -> balancer=BWD))
	);
	
guarantee
	G ((spec_mode=MANUAL) -> 
		((spec_manualCmd=TURN_RIGHT) -> (isReady -> balancer=TURN_RIGHT))
	);
	
guarantee
	G ((spec_mode=MANUAL) -> 
		((spec_manualCmd=TURN_LEFT) -> (isReady -> balancer=TURN_LEFT))
	);
	
guarantee
	G ((spec_mode=MANUAL) -> 
		((spec_manualCmd=STP | (spec_manualCmd=FWD & frontDistSense=BLOCKED) | (spec_manualCmd=BWD & backDistSense=BLOCKED)) -> (isReady -> balancer=STP))
	);
	
 

 
assumption
	!isReady;

assumption
	bluetoothCmd=NOP;
		
 
assumption
	frontDistSense=CLEAR & backDistSense=CLEAR;

 
assumption
  GF (isReady);

 
assumption
	G (isReady -> next(isReady));

define 
  	moveAwayFromFrontObstacle := !(balancer=FWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromFrontObstacle,(!moveAwayFromFrontObstacle|frontDistSense=CLEAR));

define 
  	moveAwayFromBackObstacle := !(balancer=BWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromBackObstacle,(!moveAwayFromBackObstacle|backDistSense=CLEAR));

 
assumption
  respondsTo(balancer=FWD,(!(balancer=FWD)|frontDistSense=BLOCKED));
	
 
assumption
  respondsTo(balancer=BWD,(!(balancer=BWD)|backDistSense=BLOCKED));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module GyroAspect
		env {CLEAR, BLOCKED} frontDistSense ;
		env {CLEAR, BLOCKED} backDistSense ;
		env boolean isReady ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;

 
guarantee
	balancer=STP;

 
guarantee
	G (!isReady -> balancer=STP);

 
guarantee 
	G ((balancer=FWD) -> (frontDistSense=CLEAR));

 
guarantee 
	G ((balancer=BWD) -> (backDistSense=CLEAR));

 
guarantee 
  GF (balancer=FWD);

guarantee
  GF (balancer=TURN_RIGHT|balancer=TURN_LEFT);

guarantee
	G ((isReady & frontDistSense=CLEAR) -> balancer=FWD);
	
 
assumption
	!isReady;

 
assumption
	frontDistSense=CLEAR & backDistSense=CLEAR;

 
assumption
  GF (isReady);

 
assumption
	G (isReady -> next(isReady));

define 
  	moveAwayFromFrontObstacle := !(balancer=FWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromFrontObstacle,(!moveAwayFromFrontObstacle|frontDistSense=CLEAR));

define 
  	moveAwayFromBackObstacle := !(balancer=BWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromBackObstacle,(!moveAwayFromBackObstacle|backDistSense=CLEAR));

 
assumption
  respondsTo(balancer=FWD,(!(balancer=FWD)|frontDistSense=BLOCKED));
	
 
assumption
  respondsTo(balancer=BWD,(!(balancer=BWD)|backDistSense=BLOCKED));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module GyroAspect
		env {CLEAR, BLOCKED} distSense ;
		env boolean isReady ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;
		
guarantee  
	balancer=STP;
	
guarantee
	G (!isReady -> balancer=STP);

guarantee  
	G ((distSense=BLOCKED & isReady) -> !(balancer=FWD));

guarantee  
  GF (balancer=FWD);

guarantee
	G ((distSense=CLEAR & isReady) -> (balancer=FWD));

guarantee
	G ((balancer=FWD) -> next(!(balancer=TURN_RIGHT | balancer=TURN_LEFT)));

guarantee
	G ((distSense=BLOCKED & balancer=STP & isReady) -> next(!(balancer=STP)));

assumption
  respondsTo(!(balancer=FWD|balancer=STP),(distSense=CLEAR));

assumption
  GF (isReady);
	
assumption
	G (isReady -> next(isReady));
	
assumption
	!isReady;
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module GyroAspect
		env {CLEAR, BLOCKED} distSense ;
		env boolean isReady ;
		env {AUTO, NOP, FWD, BWD, TURN_LEFT, TURN_RIGHT} bluetoothCmd ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;
		 
		 

 
 

guarantee  
	balancer=STP;
	
guarantee
	G (!isReady -> balancer=STP);

guarantee  
	G ((balancer=FWD) -> (distSense=CLEAR));

guarantee  
  GF (bluetoothCmd=AUTO->balancer=FWD);
	
guarantee
	G ((bluetoothCmd=AUTO) -> ((balancer=FWD) -> next((bluetoothCmd=AUTO) -> !(balancer=TURN_RIGHT | balancer=TURN_LEFT)))); 

guarantee
	G ((bluetoothCmd=AUTO) -> ((distSense=CLEAR & isReady) -> (balancer=FWD)));

guarantee
	G ((bluetoothCmd=AUTO) -> ((distSense=BLOCKED & balancer=STP & isReady) -> next(!(balancer=STP)))); 
	
guarantee
	G ((bluetoothCmd=FWD) -> ((distSense=CLEAR & isReady)-> balancer=FWD));
	
guarantee
	G ((bluetoothCmd=BWD) -> (isReady -> balancer=BWD));
	
guarantee
	G ((bluetoothCmd=TURN_RIGHT) -> (isReady -> balancer=TURN_RIGHT));
	
guarantee
	G ((bluetoothCmd=TURN_LEFT) -> (isReady -> balancer=TURN_LEFT));
	
guarantee
	G ((bluetoothCmd=NOP) -> (isReady -> balancer=STP));

assumption
  respondsTo(!(balancer=FWD|balancer=STP),(distSense=CLEAR));

assumption
  GF (isReady);
	
assumption
	G (isReady -> next(isReady));
	
assumption
	!isReady;
	
assumption
	bluetoothCmd=AUTO;
	
/* 
LTLSPECENV
	G ((distSense=CLEAR & balancer=STP) -> next(distSense=CLEAR));
	
LTLSPECENV
	G ((distSense=BLOCKED & balancer=STP) -> next(distSense=BLOCKED));
	*/
	
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module GyroAspect
		env {CLEAR, BLOCKED} distSense ;
		env boolean isReady ;
		env {AUTO, NOP, FWD, BWD, TURN_LEFT, TURN_RIGHT} bluetoothCmd ;
		env {OK, FELL} balancerStatus ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;
		sys {OK, FELL} bluetoothStatus ;
		 
		 

 
 

guarantee  
	balancer=STP;
	
guarantee
	G (!isReady -> balancer=STP);

guarantee  
	G ((balancer=FWD) -> (distSense=CLEAR));

guarantee  
  GF (bluetoothCmd=AUTO->balancer=FWD);
	
guarantee
	G ((bluetoothCmd=AUTO) -> ((balancer=FWD) -> next((bluetoothCmd=AUTO) -> !(balancer=TURN_RIGHT | balancer=TURN_LEFT)))); 

guarantee
	G ((bluetoothCmd=AUTO) -> ((distSense=CLEAR & isReady) -> (balancer=FWD)));

guarantee
	G ((bluetoothCmd=AUTO) -> ((distSense=BLOCKED & balancer=STP & isReady) -> next(!(balancer=STP)))); 
	
guarantee
	G ((bluetoothCmd=FWD) -> ((distSense=CLEAR & isReady)-> balancer=FWD));
	
guarantee
	G ((bluetoothCmd=BWD) -> (isReady -> balancer=BWD));
	
guarantee
	G ((bluetoothCmd=TURN_RIGHT) -> (isReady -> balancer=TURN_RIGHT));
	
guarantee
	G ((bluetoothCmd=TURN_LEFT) -> (isReady -> balancer=TURN_LEFT));
	
guarantee
	G ((bluetoothCmd=NOP) -> (isReady -> balancer=STP));

assumption
  respondsTo(!(balancer=FWD|balancer=STP),(distSense=CLEAR));

assumption
  GF (isReady);
	
assumption
	G (isReady -> next(isReady));
	
assumption
	!isReady;
	
assumption
	bluetoothCmd=AUTO;
	
/* 
LTLSPECENV
	G ((distSense=CLEAR & balancer=STP) -> next(distSense=CLEAR));
	
LTLSPECENV
	G ((distSense=BLOCKED & balancer=STP) -> next(distSense=BLOCKED));
	*/
	
	
assumption
	balancerStatus=OK;
	
guarantee
	G ((balancerStatus=OK) -> (bluetoothStatus=OK));

guarantee
	G ((balancerStatus=FELL) -> (bluetoothStatus=FELL));
	
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module GyroAspect
		env {CLEAR, BLOCKED} distSense ;
		env boolean isReady ;
		env {AUTO, NOP, FWD, BWD, TURN_LEFT, TURN_RIGHT} bluetoothCmd ;
		env {OK, FELL} balancerStatus ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;
		sys {OK, FELL} bluetoothStatus ;
		 
		 

 
 

guarantee  
	balancer=STP;
	
guarantee
	G (!isReady -> balancer=STP);

guarantee  
	G ((balancer=FWD) -> (distSense=CLEAR));

guarantee  
  GF (bluetoothCmd=AUTO->balancer=FWD);
	 

guarantee
  GF (bluetoothCmd=AUTO->(balancer=TURN_RIGHT|balancer=TURN_LEFT));
		
 
 

guarantee
	G ((bluetoothCmd=AUTO) -> ((distSense=CLEAR & isReady) -> (balancer=FWD)));

 
	 
	
/*LTLSPEC
	G ((bluetoothCmd=FWD) -> ((distSense=CLEAR & isReady)-> balancer=FWD));
	
LTLSPEC
	G ((bluetoothCmd=BWD) -> (isReady -> balancer=BWD));
	
LTLSPEC
	G ((bluetoothCmd=TURN_RIGHT) -> (isReady -> balancer=TURN_RIGHT));
	
LTLSPEC
	G ((bluetoothCmd=TURN_LEFT) -> (isReady -> balancer=TURN_LEFT));
	
LTLSPEC
	G ((bluetoothCmd=NOP) -> (isReady -> balancer=STP));
*/

define 
  	moveAwayFromObstacle := !(balancer=FWD | balancer=STP); 
  
assumption
  respondsTo(moveAwayFromObstacle,(!moveAwayFromObstacle|distSense=CLEAR));

assumption
  GF (isReady);
	
assumption
	G (isReady -> next(isReady));

assumption
	!isReady;
	
assumption
	bluetoothCmd=AUTO;
	
 
assumption
	G ((distSense=CLEAR & (balancer=STP | balancer=BWD)) -> next(distSense=CLEAR));

assumption
	G ((distSense=BLOCKED & (balancer=STP | balancer=FWD)) -> next(distSense=BLOCKED));
	
assumption
  respondsTo((balancer=FWD),(balancer!=FWD|distSense=BLOCKED));
	
/*
LTLSPECENV
	bluetoothStatus=OK & balancerStatus=OK;
 	
LTLSPEC
	G ((balancerStatus=OK) -> (bluetoothStatus=OK));

LTLSPEC
	G ((balancerStatus=FELL) -> (bluetoothStatus=FELL));
	*/
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module GyroAspect
		env {CLEAR, BLOCKED} frontDistSense ;
		env {CLEAR, BLOCKED} backDistSense ;
		env boolean isReady ;
		env {AUTO, STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} bluetoothCmd ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;

 
guarantee
	balancer=STP;

 
guarantee
	G (!isReady -> balancer=STP);

 
guarantee 
	G ((balancer=FWD) -> (frontDistSense=CLEAR));

 
guarantee 
	G ((balancer=BWD) -> (backDistSense=CLEAR));

 
guarantee 
  GF (bluetoothCmd=AUTO->balancer=FWD);

 
guarantee
	G ((bluetoothCmd=AUTO) -> ((frontDistSense=CLEAR & isReady) -> (balancer=FWD)));

 
 
define 
  	turningOp := (balancer=TURN_RIGHT | balancer=TURN_LEFT); 
  	
  sys { S0, S1, S2} spec_blockedState ;

guarantee  
  spec_blockedState=S0;

guarantee  
  G ((bluetoothCmd=AUTO & isReady) -> ((spec_blockedState=S0 & ((!(frontDistSense=BLOCKED) & !(frontDistSense=CLEAR)) | (frontDistSense=CLEAR)) & next(spec_blockedState=S0)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & !turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2)) |
  (spec_blockedState=S1 & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (frontDistSense=CLEAR) & next(spec_blockedState=S0)) |
  (spec_blockedState=S2 & (!turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2))));

guarantee  
  GF (bluetoothCmd=AUTO->(spec_blockedState=S0|spec_blockedState=S2));
 

 
 
guarantee
	G ((bluetoothCmd=FWD) -> ((frontDistSense=CLEAR & isReady)-> balancer=FWD));
	
guarantee
	G ((bluetoothCmd=BWD) -> ((backDistSense=CLEAR & isReady) -> balancer=BWD));
	
guarantee
	G ((bluetoothCmd=TURN_RIGHT) -> (isReady -> balancer=TURN_RIGHT));
	
guarantee
	G ((bluetoothCmd=TURN_LEFT) -> (isReady -> balancer=TURN_LEFT));
	
guarantee
	G ((bluetoothCmd=STP | (bluetoothCmd=FWD & frontDistSense=BLOCKED) | (bluetoothCmd=BWD & backDistSense=BLOCKED)) -> (isReady -> balancer=STP));
	
 

 
assumption
	!isReady;
	
 
assumption
	bluetoothCmd=AUTO;

 
assumption
	frontDistSense=CLEAR & backDistSense=CLEAR;

 
assumption
  GF (isReady);

 
assumption
	G (isReady -> next(isReady));

 
 
define 
  	moveAwayFromFrontObstacle := !(balancer=FWD | balancer=STP); 

  sys { S0, S1} spec_moveAwayFromFrontObstacleState ;

guarantee  
  spec_moveAwayFromFrontObstacleState=S0;

guarantee  
  G (((spec_moveAwayFromFrontObstacleState=S0 & ((!moveAwayFromFrontObstacle) | (moveAwayFromFrontObstacle & (!moveAwayFromFrontObstacle | frontDistSense = CLEAR))) & next(spec_moveAwayFromFrontObstacleState=S0)) |
  (spec_moveAwayFromFrontObstacleState=S0 & (moveAwayFromFrontObstacle & !(!moveAwayFromFrontObstacle | frontDistSense = CLEAR)) & next(spec_moveAwayFromFrontObstacleState=S1)) |
  (spec_moveAwayFromFrontObstacleState=S1 & ((!moveAwayFromFrontObstacle | frontDistSense = CLEAR)) & next(spec_moveAwayFromFrontObstacleState=S0)) |
  (spec_moveAwayFromFrontObstacleState=S1 & (!(!moveAwayFromFrontObstacle | frontDistSense = CLEAR)) & next(spec_moveAwayFromFrontObstacleState=S1))));

assumption  
  GF (spec_moveAwayFromFrontObstacleState=S0);
 

 
 
define 
  	moveAwayFromBackObstacle := !(balancer=BWD | balancer=STP); 

  sys { S0, S1} spec_moveAwayFromBackObstacleState ;

guarantee  
  spec_moveAwayFromBackObstacleState=S0;

guarantee  
  G (((spec_moveAwayFromBackObstacleState=S0 & ((!moveAwayFromBackObstacle) | (moveAwayFromBackObstacle & (!moveAwayFromBackObstacle | backDistSense = CLEAR))) & next(spec_moveAwayFromBackObstacleState=S0)) |
  (spec_moveAwayFromBackObstacleState=S0 & (moveAwayFromBackObstacle & !(!moveAwayFromBackObstacle | backDistSense = CLEAR)) & next(spec_moveAwayFromBackObstacleState=S1)) |
  (spec_moveAwayFromBackObstacleState=S1 & ((!moveAwayFromBackObstacle | backDistSense = CLEAR)) & next(spec_moveAwayFromBackObstacleState=S0)) |
  (spec_moveAwayFromBackObstacleState=S1 & (!(!moveAwayFromBackObstacle | backDistSense = CLEAR)) & next(spec_moveAwayFromBackObstacleState=S1))));

assumption  
  GF (spec_moveAwayFromBackObstacleState=S0);
 

 
 
  sys { S0, S1} spec_forwardingState ;

guarantee  
  spec_forwardingState=S0;

guarantee  
  G (((spec_forwardingState=S0 & ((!(balancer=FWD)) | ((balancer=FWD) & (balancer!=FWD | frontDistSense=BLOCKED))) & next(spec_forwardingState=S0)) |
  (spec_forwardingState=S0 & ((balancer=FWD) & !(balancer!=FWD | frontDistSense=BLOCKED)) & next(spec_forwardingState=S1)) |
  (spec_forwardingState=S1 & ((balancer!=FWD | frontDistSense=BLOCKED)) & next(spec_forwardingState=S0)) |
  (spec_forwardingState=S1 & (!(balancer!=FWD | frontDistSense=BLOCKED)) & next(spec_forwardingState=S1))));

assumption  
  GF (spec_forwardingState=S0);
 

 
 
  sys { S0, S1} spec_backwardingState ;

guarantee  
  spec_backwardingState=S0;

guarantee  
  G (((spec_backwardingState=S0 & ((!(balancer=BWD)) | ((balancer=BWD) & (balancer!=BWD | backDistSense=BLOCKED))) & next(spec_backwardingState=S0)) |
  (spec_backwardingState=S0 & ((balancer=BWD) & !(balancer!=BWD | backDistSense=BLOCKED)) & next(spec_backwardingState=S1)) |
  (spec_backwardingState=S1 & ((balancer!=BWD | backDistSense=BLOCKED)) & next(spec_backwardingState=S0)) |
  (spec_backwardingState=S1 & (!(balancer!=BWD | backDistSense=BLOCKED)) & next(spec_backwardingState=S1))));

assumption  
  GF (spec_backwardingState=S0);
 
 
module GyroAspect
		env {CLEAR, BLOCKED} frontDistSense ;
		env {CLEAR, BLOCKED} backDistSense ;
		env boolean isReady ;
		env {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT, AUTO} bluetoothCmd ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;

 
guarantee
	balancer=STP;

 
guarantee
	G (!isReady -> balancer=STP);

 
guarantee 
	G ((balancer=FWD) -> (frontDistSense=CLEAR));

 
guarantee 
	G ((balancer=BWD) -> (backDistSense=CLEAR));

 
guarantee 
  GF (bluetoothCmd=AUTO->balancer=FWD);

 
 
define 
  	turningOp := (balancer=TURN_RIGHT | balancer=TURN_LEFT); 
  	
  sys { S0, S1, S2} spec_blockedState ;

guarantee  
  spec_blockedState=S0;

guarantee  
  G ((bluetoothCmd=AUTO & isReady) -> ((spec_blockedState=S0 & ((!(frontDistSense=BLOCKED) & !(frontDistSense=CLEAR)) | (frontDistSense=CLEAR)) & next(spec_blockedState=S0)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & !turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2)) |
  (spec_blockedState=S1 & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (frontDistSense=CLEAR) & next(spec_blockedState=S0)) |
  (spec_blockedState=S2 & (!turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2))));

guarantee  
  GF (bluetoothCmd=AUTO->(spec_blockedState=S0|spec_blockedState=S2));
 

 
 
guarantee
	G ((bluetoothCmd=FWD) -> ((frontDistSense=CLEAR & isReady)-> balancer=FWD));
	
guarantee
	G ((bluetoothCmd=BWD) -> ((backDistSense=CLEAR & isReady) -> balancer=BWD));
	
guarantee
	G ((bluetoothCmd=TURN_RIGHT) -> (isReady -> balancer=TURN_RIGHT));
	
guarantee
	G ((bluetoothCmd=TURN_LEFT) -> (isReady -> balancer=TURN_LEFT));
	
guarantee
	G ((bluetoothCmd=STP | (bluetoothCmd=FWD & frontDistSense=BLOCKED) | (bluetoothCmd=BWD & backDistSense=BLOCKED)) -> (isReady -> balancer=STP));
	
 

 
assumption
	!isReady;
	
 
assumption
	bluetoothCmd=AUTO;

 
assumption
	frontDistSense=CLEAR & backDistSense=CLEAR;

 
assumption
  GF (isReady);

 
assumption
	G (isReady -> next(isReady));

define 
  	moveAwayFromFrontObstacle := !(balancer=FWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromFrontObstacle,(!moveAwayFromFrontObstacle|frontDistSense=CLEAR));

define 
  	moveAwayFromBackObstacle := !(balancer=BWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromBackObstacle,(!moveAwayFromBackObstacle|backDistSense=CLEAR));

 
assumption
  respondsTo(balancer=FWD,(!(balancer=FWD)|frontDistSense=BLOCKED));
	
 
assumption
  respondsTo(balancer=BWD,(!(balancer=BWD)|backDistSense=BLOCKED));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module GyroAspect
		env {CLEAR, BLOCKED} frontDistSense ;
		env {CLEAR, BLOCKED} backDistSense ;
		env boolean isReady ;
		env {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT, AUTO} bluetoothCmd ;
		sys {STP, FWD, BWD, TURN_LEFT, TURN_RIGHT} balancer ;

 
guarantee
	balancer=STP;

 
guarantee
	G (!isReady -> balancer=STP);

 
guarantee 
	G ((balancer=FWD) -> (frontDistSense=CLEAR));

 
guarantee 
	G ((balancer=BWD) -> (backDistSense=CLEAR));

 
guarantee 
  GF (bluetoothCmd=AUTO->balancer=FWD);



 
 
define 
  	turningOp := (balancer=TURN_RIGHT | balancer=TURN_LEFT); 
  	
  sys { S0, S1, S2} spec_blockedState ;

guarantee  
  spec_blockedState=S0;

guarantee  
  G ((bluetoothCmd=AUTO & isReady) -> ((spec_blockedState=S0 & ((!(frontDistSense=BLOCKED) & !(frontDistSense=CLEAR)) | (frontDistSense=CLEAR)) & next(spec_blockedState=S0)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & !turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S0 & (frontDistSense=BLOCKED & turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2)) |
  (spec_blockedState=S1 & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (frontDistSense=CLEAR) & next(spec_blockedState=S0)) |
  (spec_blockedState=S2 & (!turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S1)) |
  (spec_blockedState=S2 & (turningOp & !(frontDistSense=CLEAR)) & next(spec_blockedState=S2))));

guarantee  
  GF (bluetoothCmd=AUTO->(spec_blockedState=S0|spec_blockedState=S2));
 

 
 
guarantee
	G ((bluetoothCmd=FWD) -> ((frontDistSense=CLEAR & isReady)-> balancer=FWD));
	
guarantee
	G ((bluetoothCmd=BWD) -> ((backDistSense=CLEAR & isReady) -> balancer=BWD));
	
guarantee
	G ((bluetoothCmd=TURN_RIGHT) -> (isReady -> balancer=TURN_RIGHT));
	
guarantee
	G ((bluetoothCmd=TURN_LEFT) -> (isReady -> balancer=TURN_LEFT));
	
guarantee
	G ((bluetoothCmd=STP | (bluetoothCmd=FWD & frontDistSense=BLOCKED) | (bluetoothCmd=BWD & backDistSense=BLOCKED)) -> (isReady -> balancer=STP));
	
 

 
assumption
	!isReady;
	
 
assumption
	bluetoothCmd=AUTO;

 
assumption
	frontDistSense=CLEAR & backDistSense=CLEAR;

 
assumption
  GF (isReady);

 
assumption
	G (isReady -> next(isReady));

define 
  	moveAwayFromFrontObstacle := !(balancer=FWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromFrontObstacle,(!moveAwayFromFrontObstacle|frontDistSense=CLEAR));

define 
  	moveAwayFromBackObstacle := !(balancer=BWD | balancer=STP); 

 
assumption
  respondsTo(moveAwayFromBackObstacle,(!moveAwayFromBackObstacle|backDistSense=CLEAR));

 
assumption
  respondsTo(balancer=FWD,(!(balancer=FWD)|frontDistSense=BLOCKED));
	
 
assumption
  respondsTo(balancer=BWD,(!(balancer=BWD)|backDistSense=BLOCKED));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {FWD, BWD, TURN_LEFT, TURN_RIGHT, NOT_CON} BtInput ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextMoveMode = FWD;
	
assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 



 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));

guarantee  
	G (next(spec_nextMoveMode = TURN_RIGHT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(spec_nextMoveMode = TURN_LEFT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)  -> next(spec_specState = Q0));
 




  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G (((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT) & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)));

guarantee
	G ((spec_turnState = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT))  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3) -> next(spec_turnState = T0));	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_RIGHT) <-> (LeftMotor = CALIB_TURN_RIGHT & RightMotor = CALIB_TURN_RIGHT)); 

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_LEFT) <-> (LeftMotor = CALIB_TURN_LEFT & RightMotor = CALIB_TURN_LEFT)); 


guarantee
	G ((next(spec_turnState) = T2) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_turnState = T2) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_RIGHT))) <-> (LeftMotor = CALIB_FWD_RIGHT & RightMotor = CALIB_FWD_RIGHT));
		
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_LEFT))) <-> (LeftMotor = CALIB_FWD_LEFT & RightMotor = CALIB_FWD_LEFT));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));
	
assumption
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle) = CLEAR);
	

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {FWD, TURN, BWD} InputMoveMode ;
		sys {FWD, BWD, STOP} LeftMotor ;
		sys {FWD, BWD, STOP} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, TURN, BWD} OutputMoveMode ;

guarantee 
	G((InputMoveMode = FWD & Obstacle = BLOCKED) -> ((OutputMoveMode = BWD & LeftMotor = BWD & RightMotor = FWD)));

guarantee 
	G((InputMoveMode = BWD & Obstacle = CLEAR) -> ((OutputMoveMode = FWD & LeftMotor = FWD & RightMotor = BWD)));

guarantee
	G  ((InputMoveMode = FWD & Obstacle = CLEAR) -> (LeftMotor = FWD & RightMotor = FWD));

guarantee
	G ((Obstacle = BLOCKED) -> (OutputMoveMode = BWD));
 
	 
	
 
	 
	
 
	 

 
	 
		
 
	 
	
 
	  
	
assumption
  respondsTo((OutputMoveMode=BWD),(Obstacle=CLEAR));
	 
	 
	
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2} InputMoveMode ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2} OutputMoveMode ;

guarantee 
	G((InputMoveMode = FWD & Obstacle = BLOCKED) -> (OutputMoveMode = TURN_LEFT_1));

guarantee 
	G((InputMoveMode = BWD & Obstacle = CLEAR) -> ((OutputMoveMode = FWD & LeftMotor = FWD & RightMotor = BWD)));

guarantee
	G  ((InputMoveMode = FWD & Obstacle = CLEAR) -> (LeftMotor = FWD & RightMotor = FWD));

guarantee
	G ((Obstacle = BLOCKED) -> !(OutputMoveMode = FWD));
 

guarantee 
	G ((InputMoveMode = TURN_LEFT_1) <-> (OutputMoveMode = TURN_LEFT_2));

guarantee
	G ((InputMoveMode = TURN_LEFT_1) -> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((InputMoveMode = TURN_LEFT_2) -> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G (!(InputMoveMode = TURN_LEFT_1 | InputMoveMode = TURN_LEFT_2) -> !(LeftMotor = TURN_BWD | RightMotor = TURN_BWD |LeftMotor = TURN_FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((InputMoveMode = TURN_LEFT_1 | InputMoveMode = TURN_LEFT_2) -> (HeadMotor = STOP));
 
	 
	
 
	 
	
 
	 

 
	 
	
 
	 
	
 
	 
	
 
	 

	
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2} InputMoveMode ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2} OutputMoveMode ;

guarantee 
	G((InputMoveMode = FWD & Obstacle = BLOCKED) -> (OutputMoveMode = TURN_LEFT_1 & LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN));

guarantee 
	G((InputMoveMode = BWD & Obstacle = CLEAR) -> ((OutputMoveMode = FWD & LeftMotor = FWD & RightMotor = BWD)));

 
	 

guarantee
	G  ((InputMoveMode = FWD & Y (InputMoveMode = TURN_LEFT_2)) -> (LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));

guarantee
	G  ((InputMoveMode = FWD & Obstacle = CLEAR & Y (InputMoveMode != TURN_LEFT_2)) -> (LeftMotor = FWD & RightMotor = FWD));

guarantee
	G ((Obstacle = BLOCKED) -> !(OutputMoveMode = FWD));
 

guarantee 
	G ((InputMoveMode = TURN_LEFT_1) <-> (OutputMoveMode = TURN_LEFT_2));

guarantee
	G ((InputMoveMode = TURN_LEFT_1) -> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((InputMoveMode = TURN_LEFT_2) -> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G (!(InputMoveMode = TURN_LEFT_1 | InputMoveMode = TURN_LEFT_2) -> !(LeftMotor = TURN_BWD | RightMotor = TURN_BWD |LeftMotor = TURN_FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((InputMoveMode = TURN_LEFT_1 | InputMoveMode = TURN_LEFT_2) -> (HeadMotor = STOP));
	
 
	 

guarantee
	G  ((InputMoveMode = TURN_LEFT_2 & Obstacle = CLEAR) -> (OutputMoveMode = FWD));

 
	 
assumption
	G((InputMoveMode = FWD & Y (InputMoveMode = TURN_LEFT_2)) -> (Obstacle = CLEAR));
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2, DANCE} InputMoveMode ;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD, DANCE} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD, DANCE} RightMotor ;
		sys {FWD, BWD, STOP, DANCE} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2, DANCE} OutputMoveMode ;

guarantee 
	G((InputMoveMode = FWD & Obstacle = BLOCKED) -> (OutputMoveMode = TURN_LEFT_1 & LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN));

guarantee 
	G((InputMoveMode = BWD & Obstacle = CLEAR) -> ((OutputMoveMode = FWD & LeftMotor = FWD & RightMotor = BWD)));

 
	 

guarantee
	G  ((InputMoveMode = FWD & Button = FREE & Y (InputMoveMode = TURN_LEFT_2)) -> (LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));

guarantee
	G  ((InputMoveMode = FWD & Obstacle = CLEAR & Button = FREE & Y (InputMoveMode != TURN_LEFT_2)) -> (LeftMotor = FWD & RightMotor = FWD));

guarantee
	G ((Obstacle = BLOCKED) -> !(OutputMoveMode = FWD));
 

guarantee 
	G ((InputMoveMode = TURN_LEFT_1) <-> (OutputMoveMode = TURN_LEFT_2));

guarantee
	G ((InputMoveMode = TURN_LEFT_1) -> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((InputMoveMode = TURN_LEFT_2) -> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G (!(InputMoveMode = TURN_LEFT_1 | InputMoveMode = TURN_LEFT_2) -> !(LeftMotor = TURN_BWD | RightMotor = TURN_BWD |LeftMotor = TURN_FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((InputMoveMode = TURN_LEFT_1 | InputMoveMode = TURN_LEFT_2) -> (HeadMotor = STOP));
	
 
	 

guarantee
	G  ((InputMoveMode = TURN_LEFT_2 & Obstacle = CLEAR) -> (OutputMoveMode = FWD));

 
guarantee
	G ((InputMoveMode = DANCE & OutputMoveMode = DANCE) -> (RightMotor = STOP & LeftMotor = DANCE & HeadMotor = DANCE));

guarantee
	G ((Button = FREE) -> (OutputMoveMode = InputMoveMode | InputMoveMode != DANCE));	
	
guarantee
	G ((Button = PRESSED & InputMoveMode = FWD & Obstacle = CLEAR) -> (OutputMoveMode = DANCE  & LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN));

guarantee
	G ((Button = PRESSED & InputMoveMode = DANCE & Obstacle = CLEAR) -> OutputMoveMode = FWD  & LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD);

guarantee
	G (!(Button = PRESSED | InputMoveMode = DANCE) -> !(OutputMoveMode = DANCE));

 
	 
assumption
	G((InputMoveMode = FWD & Y (InputMoveMode = TURN_LEFT_2)) -> (Obstacle = CLEAR));
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		 
		 
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2} nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} state ;
		
 
 
 
	 
	
guarantee 
	G((state = Q0 & nextMoveMode = FWD & next(nextMoveMode = BWD)) -> next(state = Q1));

guarantee 
	G((state = Q1 & nextMoveMode = BWD & next(nextMoveMode = FWD)) -> next(state = Q2));
	
guarantee
	G((state = Q2 & nextMoveMode = FWD & next(nextMoveMode = BWD)) -> next(state = Q3));

guarantee 
	G((state = Q1 & next(nextMoveMode = BWD)) -> (next(state = Q1)));

guarantee 
	G((state = Q2 & next(nextMoveMode = FWD)) -> (next(state = Q2)));
	
guarantee
	G(( (nextMoveMode = TURN_LEFT_1) | (nextMoveMode = TURN_LEFT_1)) -> next(state = Q0));
guarantee
	G(!(state = Q3));
 
	
guarantee
	G((Obstacle = BLOCKED) -> !(nextMoveMode = FWD));
	
guarantee
	G((Y(nextMoveMode = BWD) & (nextMoveMode = FWD)) <-> (LeftMotor = FWD & RightMotor = BWD));

guarantee
	G((Y(nextMoveMode = FWD) & (nextMoveMode = BWD)) <-> (LeftMotor = BWD & RightMotor = FWD));
	
guarantee
  GF (nextMoveMode=FWD);
	
 
	 
 
guarantee
	G ((nextMoveMode = BWD) -> (Y(nextMoveMode = FWD) | Y(nextMoveMode = BWD)));

guarantee
	G (Y (nextMoveMode = TURN_LEFT_2) -> !(nextMoveMode = BWD));
	

guarantee
	G  ((Y(nextMoveMode = FWD) & nextMoveMode = TURN_LEFT_1) <-> (LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN));
	
guarantee
	G ( (Y(nextMoveMode = BWD)) -> (nextMoveMode != TURN_LEFT_1)) ;
 
guarantee
	G  ((Y(nextMoveMode = FWD) & Y(Y(nextMoveMode = TURN_LEFT_2))) <-> (LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));

guarantee
	G (Y(nextMoveMode = TURN_LEFT_1) <-> nextMoveMode = TURN_LEFT_2);

guarantee
	G (Y(nextMoveMode = TURN_LEFT_1) -> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G (Y(nextMoveMode = TURN_LEFT_2) -> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G (!(Y(nextMoveMode = TURN_LEFT_1) | Y(nextMoveMode = TURN_LEFT_2)) -> !(LeftMotor = TURN_BWD | RightMotor = TURN_BWD | LeftMotor = TURN_FWD | RightMotor = TURN_FWD));


assumption
  respondsTo((nextMoveMode!=FWD),(Obstacle=CLEAR));

assumption
	G((nextMoveMode = BWD & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  GF ((Y(nextMoveMode=TURN_LEFT_2)&Obstacle=CLEAR));

assumption
	G((Y(Y(nextMoveMode = TURN_LEFT_2)) & Y(nextMoveMode = FWD)) -> Obstacle = CLEAR);

 
	 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {ONTRACK,LOST} Heading;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_state ;
		sys {M0,M1,M2} spec_search ;
		
 
 
guarantee
	spec_search = M0;
	
guarantee 
	G((spec_state = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_state = Q1));

guarantee 
	G((spec_state = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_state = Q2));
	
guarantee
	G((spec_state = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_state = Q3));

guarantee 
	G((spec_state = Q1 & next(spec_nextMoveMode = BWD)) -> (next(spec_state = Q1)));

guarantee 
	G((spec_state = Q2 & next(spec_nextMoveMode = FWD)) -> (next(spec_state = Q2)));
	
guarantee
	G(( (spec_nextMoveMode = TURN_LEFT_1) | (spec_nextMoveMode = TURN_LEFT_1)) -> next(spec_state = Q0));
	
guarantee
	G(!(spec_state = Q3));
	
 
/*LTLSPEC
	G ((Noise = NOISE & Heading = LOST) -> next(spec_search = M1));
	
LTLSPEC
	G ((Heading = LOST & spec_search = M1) -> next(spec_search = M1));

LTLSPEC
	G ((Heading = ONTRACK | (Noise = QUIET & spec_search = M0)) -> next(spec_search = M0));


 
LTLSPEC
	G((spec_search = M1) -> ( spec_nextMoveMode = TURN_LEFT_1  | spec_nextMoveMode = TURN_LEFT_2));
*/

guarantee
	G(HeadMotor = STOP);
	
guarantee 
	G ((spec_search = M0 & spec_nextMoveMode = FWD & Noise = NOISE & Heading = LOST) ->
		(next(spec_search = M1) & next(spec_nextMoveMode = FWD)));

guarantee
	G((spec_search = M1) -> next(spec_search = M2) & next(spec_nextMoveMode = TURN_LEFT_1));
	
guarantee
	G((spec_search = M2 & Heading = LOST) -> 
		(next(spec_search = M2) & (spec_nextMoveMode = TURN_LEFT_1 | spec_nextMoveMode = TURN_LEFT_2)));

guarantee
	G((spec_search = M2 & Heading = ONTRACK) -> next(spec_search = M0));

	
guarantee
	G(((Obstacle = BLOCKED) & !(Y(Y(spec_nextMoveMode = TURN_LEFT_2)))) -> (!(spec_nextMoveMode = FWD)));
	
guarantee
	G((Y(spec_nextMoveMode = BWD) & (spec_nextMoveMode = FWD)) <-> (LeftMotor = FWD & RightMotor = BWD));

guarantee
	G((Y(spec_nextMoveMode = FWD) & (spec_nextMoveMode = BWD)) <-> (LeftMotor = BWD & RightMotor = FWD));
	
guarantee
  GF (spec_nextMoveMode=FWD);
	
 
	 
 
guarantee
	G ((spec_nextMoveMode = BWD) -> (Y(spec_nextMoveMode = FWD) | Y(spec_nextMoveMode = BWD)));

guarantee
	G (Y (spec_nextMoveMode = TURN_LEFT_2) -> !(spec_nextMoveMode = BWD));
	

guarantee
	G  ((Y(spec_nextMoveMode = FWD) & spec_nextMoveMode = TURN_LEFT_1) <-> (LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN));
	
guarantee
	G ( (Y(spec_nextMoveMode = BWD)) -> (spec_nextMoveMode != TURN_LEFT_1)) ;
 
guarantee
	G  ((Y(spec_nextMoveMode = FWD) & Y(Y(spec_nextMoveMode = TURN_LEFT_2))) <-> (LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));

guarantee
	G (Y(spec_nextMoveMode = TURN_LEFT_1) <-> spec_nextMoveMode = TURN_LEFT_2);

guarantee
	G (Y(spec_nextMoveMode = TURN_LEFT_1) -> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G (Y(spec_nextMoveMode = TURN_LEFT_2) -> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G (!(Y(spec_nextMoveMode = TURN_LEFT_1) | Y(spec_nextMoveMode = TURN_LEFT_2)) -> !(LeftMotor = TURN_BWD | RightMotor = TURN_BWD | LeftMotor = TURN_FWD | RightMotor = TURN_FWD));

assumption
  respondsTo((spec_search=M2),(Heading=ONTRACK));

/*LTLSPECENV
	G((spec_search = M1) -> (Y(spec_nextMoveMode != BWD) & Y(Y(spec_nextMoveMode != TURN_LEFT_2))));
*/
assumption
  respondsTo((spec_nextMoveMode!=FWD),(Obstacle=CLEAR));

assumption
	G((spec_nextMoveMode = BWD & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  GF ((Y(spec_nextMoveMode=TURN_LEFT_2)&Obstacle=CLEAR));

 
	 

 
	 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,NW,W,SW,SO,SE,EA,NE} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT_1, TURN_LEFT_2} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_state ;
		sys {M0,M1} search ;
		sys {N,NW,W,SW,SO,SE,EA,NE} next_head ;
		
 
/*
 * initial state
 */
  
guarantee
	search = M0 & spec_state = Q0;







 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
guarantee
  GF (search=M0);
 







 
/*
 * to prevant robot from going FWD< 
 */
  
guarantee 
	 
	G((spec_state = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_state = Q1));
	
guarantee 
	 
	G((spec_state = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_state = Q2));
	
guarantee
	 
	G(!(spec_state = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));
	 
/*LTLSPEC 
	G((Y(spec_state = Q1) & spec_nextMoveMode = BWD) -> (spec_state = Q1));
	
LTLSPEC 
	G((Y(spec_state = Q2) & spec_nextMoveMode = FWD) -> (spec_state = Q2));
	*/
guarantee
	G(((spec_nextMoveMode = TURN_LEFT_1) | (spec_nextMoveMode = TURN_LEFT_2)) -> next(spec_state = Q0));
 











 
/*
 * automaton for searching direction
 */
  
 guarantee 
	G ((Y(search = M0) & Noise = NOISE & Heading != next_head & Button != PRESSED) -> 
		(search = M1));

guarantee
	G((Y(search = M1) & Heading = next_head) -> search = M0);
 
 guarantee
 	G((Y(search = M1) & Heading != next_head) -> search = M1);
  
 	
 	
 	
 	





 
/*
 * determine heading
 */	
  
guarantee 
	G ((Button = PRESSED & Y(search = M0)) -> (next(next_head) =  Heading));

guarantee 
	G ((Button = FREE | Y(search = M1)) -> (next(next_head) = next_head));
 








 
/*
 * 
 */
  
guarantee
	G((next(Obstacle = BLOCKED) & !((Y(spec_nextMoveMode = TURN_LEFT_2)))) -> next(!(spec_nextMoveMode = FWD)));
	
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	






 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Turn movement is an atomic movement of 2 steps, turn_left_1 to turn_left_2, can't do 1 without doing 2 right after, and 2 can come only after 1
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  


guarantee
	G ((spec_nextMoveMode = TURN_LEFT_1) -> next(LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_nextMoveMode = TURN_LEFT_2) -> next(LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_nextMoveMode = TURN_LEFT_1) <-> next(spec_nextMoveMode = TURN_LEFT_2));
	
guarantee  
	G (!((spec_nextMoveMode = TURN_LEFT_1) | (spec_nextMoveMode = TURN_LEFT_2)) -> next(!(LeftMotor = TURN_BWD | RightMotor = TURN_BWD | LeftMotor = TURN_FWD | RightMotor = TURN_FWD)));	
	
guarantee  
	G  (((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = TURN_LEFT_1)) <-> next(LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN));
	
guarantee  
	G  (((spec_nextMoveMode = FWD) & (Y(spec_nextMoveMode = TURN_LEFT_2))) <-> next(LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));
	
guarantee  
	G ( ((spec_nextMoveMode = BWD)) -> next(spec_nextMoveMode != TURN_LEFT_1));


 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  

assumption
  respondsTo((search=M1),(Heading=next_head));

assumption
	G(((spec_nextMoveMode = FWD | spec_nextMoveMode = BWD) & Heading != next_head) -> next(Heading) != next_head);

assumption
  respondsTo((spec_nextMoveMode!=FWD),(Obstacle=CLEAR));

assumption
	G((spec_nextMoveMode = BWD & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  GF ((Y(spec_nextMoveMode=TURN_LEFT_2)&(Obstacle=CLEAR)));
 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,SO} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		 
		sys {N,SO} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;
	
 
 

guarantee
	spec_nextHead = SO;
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 
 
 







 
/*
 * to prevant robot from going FWD< 
 */
  
guarantee 
	 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	 
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));
	 
guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G(spec_nextMoveMode = TURN_LEFT -> next(spec_specState = Q0));
 











 
/*
 * automaton for searching direction
 */
  
 /*LTLSPEC 
	G ((search = M0 & Noise = NOISE & Heading != spec_nextHead & Button != PRESSED) -> 
		next(search = M1));
		
 LTLSPEC 
	G ((search = M0 & !(Noise = NOISE & Heading != spec_nextHead & Button != PRESSED)) -> 
		next(search = M0));

LTLSPEC
	G((search = M1 & Heading = spec_nextHead) -> next(search = M0));
 
 LTLSPEC
 	G((search = M1 & Heading != spec_nextHead) -> next(search = M1));*/
 
 guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));
  
 	
 	
 	
 	





 
/*
 * determine heading
 */	
  
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
 








 
/*
 * 
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
	
	 
	
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));







  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G ((spec_nextMoveMode = TURN_LEFT & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & spec_nextMoveMode = TURN_LEFT));

guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = TURN_LEFT)  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3 & spec_nextMoveMode = FWD) -> next(spec_turnState = T0));

guarantee
	G ((spec_turnState = T3 & spec_nextMoveMode != FWD) -> next(spec_turnState = T2));
	
 
	 
 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1) <-> (LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN)); 

guarantee
	G (next(spec_turnState) = T2 <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G (spec_turnState = T2 <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0)) <-> (LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));
	 

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));
	
assumption
	G(((spec_nextMoveMode = FWD | spec_nextMoveMode = BWD)) -> next(Heading) = Heading);

assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

 
 
/*LTLSPECENV
	G((search = M1) -> F(Heading = spec_nextHead));
 
	 
	 
	 
	 

/*

LTLSPECENV
	G (spec_turnState = T3 -> next(Obstacle = CLEAR));
	
LTLSPECENV
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle = CLEAR));*/

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,SO} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		sys {N,SO} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextHead = SO;

guarantee
	spec_nextMoveMode = FWD;
	
assumption	
	Heading = N;
	
assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G(spec_nextMoveMode = TURN_LEFT -> next(spec_specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine heading
 */
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));
 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G ((spec_nextMoveMode = TURN_LEFT & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & spec_nextMoveMode = TURN_LEFT));

guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = TURN_LEFT)  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3 & spec_nextMoveMode = FWD) -> next(spec_turnState = T0));

guarantee
	G ((spec_turnState = T3 & spec_nextMoveMode != FWD) -> next(spec_turnState = T2));
	
 
	 
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1) <-> (LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN)); 

guarantee
	G (next(spec_turnState) = T2 <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G (spec_turnState = T2 <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0)) <-> (LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));
	 

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));
	
assumption
	G(((spec_nextMoveMode = FWD | spec_nextMoveMode = BWD)) -> next(Heading) = Heading);

assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

 
 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,EA,SO,W} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN, CALIB_FWD} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} specState ;
		sys {T0,T1,T2,T3} turnState ;
		sys {N,EA,SO,W} nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	specState = Q0;
	
guarantee
	turnState = T0;

guarantee
	nextHead = SO;

guarantee
	nextMoveMode = FWD;
	
assumption	
	Heading = N;
	
assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((nextMoveMode = BWD) & next(nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((nextMoveMode = FWD) & next(nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(nextMoveMode = BWD) -> ((nextMoveMode = FWD) | (nextMoveMode = BWD)));
	
guarantee  
	G (nextMoveMode = BWD -> next((nextMoveMode = FWD) | (nextMoveMode = BWD)));

guarantee  
	G (next(nextMoveMode = TURN_RIGHT) -> (nextMoveMode = FWD) | (nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(nextMoveMode = TURN_LEFT) -> (nextMoveMode = FWD) | (nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((specState = Q0 & nextMoveMode = FWD & next(nextMoveMode = BWD)) -> next(specState = Q1));
	
guarantee 
	G((specState = Q1 & nextMoveMode = BWD & next(nextMoveMode = FWD)) -> next(specState = Q2));
	
guarantee
	G(!(specState = Q2 & nextMoveMode = FWD & next(nextMoveMode = BWD)));

guarantee 
	G((specState = Q1 & next(nextMoveMode = BWD)) -> next(specState = Q1));
	
guarantee 
	G((specState = Q2 & next(nextMoveMode = FWD)) -> next(specState) = Q2);
	
guarantee
	G((nextMoveMode = TURN_RIGHT | nextMoveMode = TURN_LEFT)  -> next(specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine Heading
 */
guarantee 
	G ((Button = PRESSED) -> next(nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(nextHead) = nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=nextHead));

 
/*LTLSPEC
 	G (((nextHead > Heading & (nextHead - Heading < 2)) | (nextHead < Heading & !(Heading - nextHead < 2)))  -> nextMoveMode != TURN_LEFT);

LTLSPEC
 	G (((nextHead < Heading & (Heading - nextHead < 2)) | (nextHead > Heading & !(nextHead - Heading < 2))) -> nextMoveMode != TURN_RIGHT);
* 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(turnState) = T0 -> (turnState = T0 | turnState = T3));
	
guarantee
	G ((turnState = T0 & !(nextMoveMode = TURN_RIGHT | nextMoveMode = TURN_LEFT)) -> next(turnState) = T0);
	
guarantee
	G (((nextMoveMode = TURN_RIGHT | nextMoveMode = TURN_LEFT) & Y(nextMoveMode = FWD) & turnState = T0) -> next(turnState) = T1);

guarantee
	G (turnState = T1  -> (next(turnState) = T2 & (nextMoveMode = TURN_RIGHT | nextMoveMode = TURN_LEFT)));

guarantee
	G ((turnState = T2 & (nextMoveMode = TURN_RIGHT | nextMoveMode = TURN_LEFT))  -> next(turnState) = T1);
	
guarantee
	G ((turnState = T2 & nextMoveMode = FWD) -> next(turnState) = T3);
	
guarantee
	G ((turnState = T3 & nextMoveMode = FWD) -> next(turnState = T0));

guarantee
	G ((turnState = T3 & nextMoveMode != FWD) -> next(turnState = T2));
	
 
	 
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((turnState = T0 & next(turnState) = T1) <-> (LeftMotor = CALIB_TURN & RightMotor = CALIB_TURN)); 

guarantee
	G ((next(turnState) = T2  & nextMoveMode = TURN_RIGHT) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((turnState = T2 &  Y(nextMoveMode = TURN_RIGHT)) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((next(turnState) = T2  & nextMoveMode = TURN_LEFT) <-> (LeftMotor = TURN_FWD & RightMotor = FWD));
	
guarantee
	G ((turnState = T2 &  Y(nextMoveMode = TURN_LEFT)) <-> (LeftMotor = TURN_BWD & RightMotor = BWD));
	
guarantee
	G ((turnState = T3 & next(turnState = T0)) <-> (LeftMotor = CALIB_FWD & RightMotor = CALIB_FWD));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  

assumption
	G ((Y(nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));
	 

assumption
	G((Y(nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));
	
 
 

assumption
  respondsTo((nextMoveMode=TURN_RIGHT),(Heading=nextHead|nextMoveMode!=TURN_RIGHT));
	
assumption
  respondsTo((nextMoveMode=TURN_LEFT),(Heading=nextHead|nextMoveMode!=TURN_LEFT));

 
 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,EA,SO,W} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		sys {N,EA,SO,W} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextHead = SO;

guarantee
	spec_nextMoveMode = FWD;

assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));

guarantee  
	G (next(spec_nextMoveMode = TURN_RIGHT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(spec_nextMoveMode = TURN_LEFT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)  -> next(spec_specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine Heading
 */
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));

 

guarantee
	G ((((spec_nextHead = N & Heading = EA) | (spec_nextHead = EA & Heading = SO) | (spec_nextHead = SO & Heading = W) | (spec_nextHead = W & Heading = N)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_RIGHT);

guarantee
	G ((((spec_nextHead = EA & Heading = N) | (spec_nextHead = SO & Heading = EA) | (spec_nextHead = W & Heading = SO) | (spec_nextHead = N & Heading = W)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_LEFT);
 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G (((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT) & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)));

guarantee
	G ((spec_turnState = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT))  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3) -> next(spec_turnState = T0));
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_RIGHT) <-> (LeftMotor = CALIB_TURN_RIGHT & RightMotor = CALIB_TURN_RIGHT)); 

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_LEFT) <-> (LeftMotor = CALIB_TURN_LEFT & RightMotor = CALIB_TURN_LEFT)); 

guarantee
	G ((next(spec_turnState) = T2) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_turnState = T2) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_RIGHT))) <-> (LeftMotor = CALIB_FWD_RIGHT & RightMotor = CALIB_FWD_RIGHT));
		
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_LEFT))) <-> (LeftMotor = CALIB_FWD_LEFT & RightMotor = CALIB_FWD_LEFT));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));

assumption  
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle) = CLEAR);

assumption
  respondsTo((spec_nextMoveMode=TURN_RIGHT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_RIGHT));
	
assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module Humanoid
		env {CLEAR, BLOCKED} Obstacle ;
		env {QUIET, NOISE} Noise ;
		env {N,EA,SO,W} Heading;
		env {FREE, PRESSED} Button ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} LeftMotor ;
		sys {FWD, BWD, STOP, TURN_FWD, TURN_BWD, CALIB_TURN_LEFT, CALIB_TURN_RIGHT, CALIB_FWD_LEFT, CALIB_FWD_RIGHT} RightMotor ;
		sys {FWD, BWD, STOP} HeadMotor ;
		sys {FWD, BWD, TURN_RIGHT, TURN_LEFT} spec_nextMoveMode ;
		sys {Q0,Q1,Q2,Q3} spec_specState ;
		sys {T0,T1,T2,T3} spec_turnState ;
		sys {N,EA,SO,W} spec_nextHead ;
		
 
/*
 * initial state
 */
  
guarantee
	spec_specState = Q0;
	
guarantee
	spec_turnState = T0;

guarantee
	spec_nextHead = SO;

guarantee
	spec_nextMoveMode = FWD;

assumption
	Obstacle = CLEAR;
	
	
	





 
/*
 * goals 
 */
  
guarantee
  GF (spec_nextMoveMode=FWD);
	
 



 
/*
 * Main Restriction - do not run into walls
 */
  
guarantee
	G((Obstacle = BLOCKED) -> (!(spec_nextMoveMode = FWD)));
 








 
/*
 * 						MOTORS - CONTROL
 */
  
guarantee
	G(((spec_nextMoveMode = BWD) & next(spec_nextMoveMode = FWD)) <-> next(LeftMotor = FWD & RightMotor = BWD));

guarantee
	G(((spec_nextMoveMode = FWD) & next(spec_nextMoveMode = BWD)) <-> next(LeftMotor = BWD & RightMotor = FWD));
	
guarantee  
	G (next(spec_nextMoveMode = BWD) -> ((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));
	
guarantee  
	G (spec_nextMoveMode = BWD -> next((spec_nextMoveMode = FWD) | (spec_nextMoveMode = BWD)));

guarantee  
	G (next(spec_nextMoveMode = TURN_RIGHT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_RIGHT));
	
guarantee  
	G (next(spec_nextMoveMode = TURN_LEFT) -> (spec_nextMoveMode = FWD) | (spec_nextMoveMode = TURN_LEFT));
  



 
/*
 * 							Q - AUTOMATON
 * to prevant robot from going FWD< 
 */
 
guarantee 
	G((spec_specState = Q0 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q1 & spec_nextMoveMode = BWD & next(spec_nextMoveMode = FWD)) -> next(spec_specState = Q2));
	
guarantee
	G(!(spec_specState = Q2 & spec_nextMoveMode = FWD & next(spec_nextMoveMode = BWD)));

guarantee 
	G((spec_specState = Q1 & next(spec_nextMoveMode = BWD)) -> next(spec_specState = Q1));
	
guarantee 
	G((spec_specState = Q2 & next(spec_nextMoveMode = FWD)) -> next(spec_specState) = Q2);
	
guarantee
	G((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)  -> next(spec_specState = Q0));
 







 
/*
 * 						COMPASS - HANDELING
 */	
  
 
/*
 * determine Heading
 */
guarantee 
	G ((Button = PRESSED) -> next(spec_nextHead =  Heading));

guarantee 
	G ((Button = FREE) -> (next(spec_nextHead) = spec_nextHead));
	

/*
 *  trigger to start looking for saved direction
 */
guarantee
  respondsTo((Noise=NOISE),(Heading=spec_nextHead));

 

guarantee
	G ((((spec_nextHead = N & Heading = EA) | (spec_nextHead = EA & Heading = SO) | (spec_nextHead = SO & Heading = W) | (spec_nextHead = W & Heading = N)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_RIGHT);

guarantee
	G ((((spec_nextHead = EA & Heading = N) | (spec_nextHead = SO & Heading = EA) | (spec_nextHead = W & Heading = SO) | (spec_nextHead = N & Heading = W)) & 
		(spec_turnState = T0)) -> spec_nextMoveMode != TURN_LEFT);
 


 	
 	
 	
 





  
/*
 * 					TURNNING - AUTOMATON
 */
  
guarantee
	G (next(spec_turnState) = T0 -> (spec_turnState = T0 | spec_turnState = T3));
	
guarantee
	G ((spec_turnState = T0 & !(spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)) -> next(spec_turnState) = T0);
	
guarantee
	G (((spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT) & Y(spec_nextMoveMode = FWD) & spec_turnState = T0) -> next(spec_turnState) = T1);

guarantee
	G (spec_turnState = T1  -> (next(spec_turnState) = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT)));

guarantee
	G ((spec_turnState = T2 & (spec_nextMoveMode = TURN_RIGHT | spec_nextMoveMode = TURN_LEFT))  -> next(spec_turnState) = T1);
	
guarantee
	G ((spec_turnState = T2 & spec_nextMoveMode = FWD) -> next(spec_turnState) = T3);
	
guarantee
	G ((spec_turnState = T3) -> next(spec_turnState = T0));
	
 

 
/*
 * 						MOVEMENT - TURNNING
 * 
 * 
 * Some technical limitations on the movement
 * Starting to turn and stoping needs a calibration from FWD movement
 */
  

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_RIGHT) <-> (LeftMotor = CALIB_TURN_RIGHT & RightMotor = CALIB_TURN_RIGHT)); 

guarantee
	G ((spec_turnState = T0 & next(spec_turnState) = T1 & spec_nextMoveMode = TURN_LEFT) <-> (LeftMotor = CALIB_TURN_LEFT & RightMotor = CALIB_TURN_LEFT)); 

guarantee
	G ((next(spec_turnState) = T2) <-> (LeftMotor = FWD & RightMotor = TURN_FWD));
	
guarantee
	G ((spec_turnState = T2) <-> (LeftMotor = BWD & RightMotor = TURN_BWD));
	
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_RIGHT))) <-> (LeftMotor = CALIB_FWD_RIGHT & RightMotor = CALIB_FWD_RIGHT));
		
guarantee
	G ((spec_turnState = T3 & next(spec_turnState = T0) & Y(Y(spec_nextMoveMode = TURN_LEFT))) <-> (LeftMotor = CALIB_FWD_LEFT & RightMotor = CALIB_FWD_LEFT));

 
/*
 * 						ENVIRONMENT - ASSUMPTIONS
 * 
 */
  
  

assumption
	G ((Y(spec_nextMoveMode = FWD) & Obstacle = BLOCKED) -> next(Obstacle = BLOCKED));

assumption
	G((Y(spec_nextMoveMode = BWD) & Obstacle = CLEAR) -> (next(Obstacle != BLOCKED)));
	
assumption
  respondsTo((spec_turnState=T1),(Obstacle=CLEAR&next(Obstacle)=CLEAR));

assumption
	G ((spec_turnState = T2 & Obstacle = CLEAR) -> next(Obstacle) = CLEAR);

assumption
  respondsTo((spec_nextMoveMode=TURN_RIGHT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_RIGHT));
	
assumption
  respondsTo((spec_nextMoveMode=TURN_LEFT),(Heading=spec_nextHead|spec_nextMoveMode!=TURN_LEFT));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLEAR, BLOCKED} sideSense;
 env {NA,PARALLEL} parkResult;
 
 
 sys {FWD, BWD, STOP} throttle ;
 sys {RIGHT,LEFT, CENTER} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED} spec_policy;



 
guarantee
( spec_policy=SEEKING );

 
guarantee
  GF (spec_policy=PARKED);
 
 
  
 
 guarantee
 G((spec_policy = SEEKING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G((spec_policy = MEASURING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G((spec_policy = PARKING_0)-> (next(spec_policy)=(PARKING_1)));
 guarantee
 G((spec_policy = PARKING_1)-> (next(spec_policy)=(PARKING_2)));
 guarantee
 G((spec_policy = PARKING_2)-> (next(spec_policy)=(PARKED)));


 
guarantee
 G ((obstacle = BLOCKED)->!(throttle = FWD));


 
guarantee
 G ((sideSense = BLOCKED) -> !((steer =RIGHT) &(throttle=FWD)));


 
guarantee
 G(((obstacle=BLOCKED) &(spec_policy=MEASURING |spec_policy=SEEKING))->(next(spec_policy) = SEEKING));
 
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((spec_policy = SEEKING & parkResult=NA) -> (throttle != STOP));



 
guarantee
G(((spec_policy = SEEKING) & (sideSense = BLOCKED) & parkResult=NA) ->  ((next(spec_policy) = spec_policy) & (parkCommand = STOP)));

 
guarantee
 G (((spec_policy = SEEKING) & sideSense=CLEAR & (obstacle = CLEAR) & parkResult = NA)
 -> (next(spec_policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((spec_policy = MEASURING) & (sideSense=BLOCKED) &(parkResult =NA))
 -> (next(spec_policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((spec_policy = MEASURING) & sideSense=CLEAR & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(spec_policy) = spec_policy)&throttle=FWD & parkCommand=CHECK & steer = CENTER);
 
  
guarantee
 G (((((spec_policy = MEASURING)|(spec_policy=SEEKING & PREV(spec_policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) & steer = RIGHT);
 
 
 
guarantee
 G ((spec_policy = PARKING_0)
 -> (next(spec_policy) = PARKING_1) & (throttle = BWD) & steer = RIGHT & (parkCommand = STOP));
 
 
 
  
guarantee
 G ((spec_policy = PARKING_1)
 -> (next(spec_policy) = PARKING_2) & (throttle = STOP) & steer = LEFT & (parkCommand = STOP));
 
 
  
guarantee
 G ((spec_policy = PARKING_2)
 -> (next(spec_policy) = PARKED) & (throttle = BWD) & steer = LEFT & (parkCommand = STOP));

 
 
guarantee
 G (((spec_policy = PARKED))
 -> (next(spec_policy) = spec_policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 


assumption
G ((spec_policy = SEEKING)->next(parkResult = NA));  


assumption
  GF ((parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
sideSense=BLOCKED & parkResult = NA;

 
assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

 
 
 
 
 
 
 
 
 
 
 
  
 
 

 
 
 
 
 
 
 
 
 
  
 

 
 
 
 

 
 
 

 
 

 
 
 
 
 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
  
 
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED} policy;



 
guarantee
( policy=SEEKING );

 
 
 
 
guarantee
  GF (policy=PARKED);
 
 
 
 guarantee
  
  
  
 G((policy = SEEKING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
 guarantee
 G ((policy = SEEKING) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 
 guarantee
 G((policy = MEASURING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
  guarantee
 G ((policy = MEASURING) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((policy = PARKING_0)-> (next(policy)=(PARKING_1)));
 guarantee
 G((policy = PARKING_1)-> (next(policy)=(PARKING_2)));
 guarantee
 G((policy = PARKING_2)-> (next(policy)=(PARKED)));
 guarantee
 G((policy = PARKED)-> (next(policy)=(PARKED)));
 
 
 
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (policy=SEEKING) & parkResult = NA)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (policy = SEEKING | policy = MEASURING)) ->(next(policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((policy = SEEKING & parkResult=NA) -> (throttle != STOP));

 
 
 
 
  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = FAR) -> (steer=EASY_RIGHT));

  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense != CLOSE) & PREV(sideSense != FAR))) -> (steer=CENTER));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED) ->
 (steer=EASY_LEFT & next(steer)=CENTER));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED) ->
 (steer=EASY_RIGHT & next(steer)=CENTER));

 
 
 
 

assumption
G (PREV(sideSense = FAR) & sideSense = CENTERED -> next(sideSense) = CENTERED); 
assumption
G (PREV(sideSense = CLOSE) & sideSense = CENTERED -> next(sideSense) = CENTERED); 


 
 
   
 guarantee
  
  
  
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR) -> (steer=EASY_RIGHT));

   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING) -> (steer=CENTER));
 
 
 
 
 
 
guarantee
G(((policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & parkResult=NA)
-> ((next(policy) = policy) & (parkCommand = STOP)));


 
guarantee
 G (((policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR))
 -> (next(policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(policy) = policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G (((((policy = MEASURING & sideSense = PARALLEL_PARKING)|(policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(policy) = PARKING_0) & (throttle = BLOCKING_FWD) & (parkCommand = STOP) );

 
guarantee
 G ((policy = PARKING_0)
 -> (next(policy) = PARKING_1) & (throttle = STOP) & steer = CENTER & (parkCommand = STOP));

 
 
 
 
 
  
guarantee
 G ((policy = PARKING_1)
 -> (next(policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((policy = PARKING_2)
 -> (next(policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
guarantee
 G (((policy = PARKED))
 -> (next(policy) = policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));

 
 
 
 
assumption
G ((policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
sideSense=CENTERED & parkResult = NA;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

 
 

 
 

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
 env {BLACK, GREEN, RED} colorSense;
 env {FREE, PRESSED} reset;
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD, EXIT_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED, EXIT_0,EXIT_1} policy;


 
guarantee
( policy=SEEKING);

 
 
 
 
guarantee
  GF (policy=PARKED&colorSense=GREEN);
 
 guarantee
  
  
  
 G((policy = SEEKING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
 guarantee
 G ((policy = SEEKING) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 guarantee
  G ((policy = SEEKING & obstacle = CLEAR) -> (!(steer = RIGHT | steer = LEFT )));

 
 guarantee
 G((policy = MEASURING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
  guarantee
 G ((policy = MEASURING) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((policy = PARKING_0)-> (next(policy)=(PARKING_1)));
 guarantee
 G((policy = PARKING_1)-> (next(policy)=(PARKING_2)));
 guarantee
 G((policy = PARKING_2)-> (next(policy)=(PARKED)));
 guarantee
 G((policy = PARKED)-> (next(policy)=(PARKED) | next(policy)=(EXIT_0)));
 guarantee
 G((policy = EXIT_0)-> (next(policy)=(EXIT_1)));
 guarantee
 G((policy = EXIT_1)-> (next(policy)=(SEEKING)));
 
 
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (policy=SEEKING) & parkResult = NA)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (policy = SEEKING | policy = MEASURING)) ->(next(policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((policy = SEEKING & parkResult=NA) -> (throttle != STOP));

 
 
 
 guarantee
 G((policy=SEEKING & obstacle = CLEAR & PREV(obstacle = BLOCKED)) -> (steer=CENTER));
 
  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE & PREV(obstacle = CLEAR)) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = FAR & PREV(obstacle = CLEAR)) -> (steer=EASY_RIGHT));
 
  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense = CENTERED)) & PREV(obstacle = CLEAR)) -> (steer=CENTER));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED & PREV(obstacle = CLEAR)) ->
 (steer=EASY_LEFT));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED & PREV(obstacle = CLEAR)) ->
 (steer=EASY_RIGHT));
 
 
   
 guarantee
  
  
  
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR) -> (steer=EASY_RIGHT));

   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PARALLEL_PARKING)) -> (steer=CENTER));
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = CLOSE_PARKING)) -> (steer=EASY_RIGHT));
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PERPENDICULAR)) -> (steer=EASY_LEFT));
 
 
 
 
 
 
guarantee
G(((policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR))
-> ((next(policy) = policy) & (parkCommand = STOP)));


 
guarantee
 G (((policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR))
 -> (next(policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(policy) = policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G (((((policy = MEASURING & sideSense = PARALLEL_PARKING)|(policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) );

 
guarantee
 G ((policy = PARKING_0)
 -> (next(policy) = PARKING_1) & (throttle = BLOCKING_FWD) & steer = CENTER & (parkCommand = STOP));
 
  
guarantee
 G ((policy = PARKING_1)
 -> (next(policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((policy = PARKING_2)
 -> (next(policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
guarantee
 G (((policy = PARKED) & colorSense = GREEN & reset = FREE)
 -> (next(policy) = policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 
 
guarantee
 G (((policy = PARKED) & (!(colorSense = GREEN) | reset = PRESSED ))
 -> (next(policy) = EXIT_0) & (throttle = EXIT_FWD) & (steer = LEFT) & (parkCommand = STOP));

 
guarantee
 G (((policy = EXIT_0))
 -> (next(policy) = EXIT_1) & (throttle = EXIT_FWD) & (steer = RIGHT) & (parkCommand = STOP));

 
guarantee
 G (((policy = EXIT_1))
 -> (next(policy) = SEEKING) & (steer = CENTER) & (throttle = STOP));
 
 
 
 
 
assumption
G ((policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
parkResult = NA & reset = FREE;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));
 
assumption
G ((policy != PARKED) -> next(colorSense = BLACK));

assumption
  GF ((policy=PARKED&colorSense=GREEN&reset=FREE));

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
		env {CLEAR, BLOCKED, OBJECT} obstacle ;
		env {CLEAR,P_O, BLOCKED} sideSense;

		sys {FWD, BWD, STOP} throttle ;
		sys {RIGHT,LEFT, CENTER} steer ;

guarantee
	G (obstacle=BLOCKED -> ( !(throttle = FWD) ));
 
 
 
 
 
 
guarantee
	G (((obstacle = CLEAR) & (sideSense = CLEAR)) ->  (steer = CENTER));
guarantee
  GF ((throttle=FWD)&(steer=CENTER));
assumption
	G ((throttle = BWD)  -> next(obstacle = CLEAR));
assumption
  respondsTo(((throttle=FWD)&(steer=CENTER)&(sideSense=BLOCKED)),(sideSense=CLEAR));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
		env {CLEAR, BLOCKED, OBJECT} obstacle ;
		env {CLEAR,P_O, BLOCKED} sideSense;

		sys {FWD, BWD, STOP} throttle ;
		sys {RIGHT,LEFT, CENTER} steer ;

guarantee
	G (obstacle=BLOCKED -> ( !(throttle = FWD) ));
 
 
 
 
 
 
guarantee
	G (((obstacle = CLEAR) & (sideSense = CLEAR)) ->  (steer = CENTER));
guarantee
  GF ((throttle=FWD)&(steer=CENTER));
assumption
	G ((throttle = BWD)  -> next(obstacle = CLEAR));
assumption
  respondsTo(((throttle=FWD)&(steer=CENTER)&(sideSense=BLOCKED)),(sideSense=CLEAR));

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
		env {CLEAR, BLOCKED} obstacle ;
		env {CLEAR,P_O, BLOCKED} sideSense;
 
 
 
		sys {FWD, BWD, STOP} throttle ;
		sys {RIGHT,LEFT, CENTER} steer ;
guarantee
	G (obstacle=BLOCKED -> ( !(throttle = FWD) ));
guarantee
	G (((obstacle = CLEAR) & (sideSense = CLEAR)) ->  (steer = CENTER));
guarantee
  GF ((throttle=FWD)&(steer=CENTER));
 
 
 
 
 
 
assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));
assumption
  respondsTo(((throttle=FWD)&(steer=CENTER)&(sideSense=BLOCKED)),(sideSense=CLEAR));

  sys { S0, S1, S2} spec_b2f ;

guarantee  
  spec_b2f=S0;

guarantee  
  G((spec_b2f=S0 & ((!(throttle = BWD) & !(throttle = STOP)) | 
  		(throttle = BWD & throttle = FWD) | 
  		(!(throttle = FWD) & throttle = STOP) | 
  		(!(throttle = BWD) & throttle = FWD & throttle = STOP)) & next(spec_b2f=S0)) |
  (spec_b2f=S0 & (throttle = BWD & !(throttle = FWD) & !(throttle = STOP)) & next(spec_b2f=S1)) |
  (spec_b2f=S1 & (!(throttle = FWD) & throttle = STOP) & next(spec_b2f=S0)) |
  (spec_b2f=S1 & (!(throttle = FWD) & !(throttle = STOP)) & next(spec_b2f=S1)) |
  (spec_b2f=S1 & (throttle = FWD) & next(spec_b2f=S2)) |
  (spec_b2f=S2 & next(spec_b2f=S2)));

assumption  
  GF (spec_b2f=S0|spec_b2f=S1);
  
  sys { S0, S1, S2} spec_f2b ;

guarantee  
  spec_f2b=S0;

guarantee  
  G((spec_f2b=S0 & ((!(throttle = FWD) & !(throttle = STOP)) | 
  		(throttle = FWD & throttle = BWD) | 
  		(!(throttle = BWD) & throttle = STOP) | 
  		(!(throttle = FWD) & throttle = BWD & throttle = STOP)) & next(spec_f2b=S0)) |
  (spec_f2b=S0 & (throttle = FWD & !(throttle = BWD) & !(throttle = STOP)) & next(spec_f2b=S1)) |
  (spec_f2b=S1 & (!(throttle = BWD) & throttle = STOP) & next(spec_f2b=S0)) |
  (spec_f2b=S1 & (!(throttle = BWD) & !(throttle = STOP)) & next(spec_f2b=S1)) |
  (spec_f2b=S1 & (throttle = BWD) & next(spec_f2b=S2)) |
  (spec_f2b=S2 & next(spec_f2b=S2)));

assumption  
  GF (spec_f2b=S0|spec_f2b=S1);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
		env {CLEAR, BLOCKED} obstacle ;
		env {CLEAR,P_O, BLOCKED} sideSense;
		env {NA,PARALLEL} parkResult;
 
		sys {FWD, BWD, STOP} throttle ;
		sys {RIGHT,LEFT, CENTER} steer ;
		sys {START,STOP,CHECK} parkCommand ;
		sys boolean spec_park;
		sys {SEEKING,MEASURING,PARKING,PARKED} spec_policy;

 
 

guarantee
	spec_policy=SEEKING & !spec_park;

guarantee 
  GF (spec_park);

guarantee
	G(!next(spec_park) -> !next(spec_policy = PARKED));
guarantee
	G(next(spec_park) -> next(spec_policy = PARKED));	
 
 
guarantee
  respondsTo(!(spec_policy=PARKED),!(throttle=STOP));
guarantee
	G (((spec_policy=SEEKING|spec_policy=MEASURING)& obstacle = BLOCKED)->(throttle = BWD));
guarantee
	G (((spec_policy=PARKING|spec_policy=PARKED)& obstacle = BLOCKED)->!(throttle = FWD));
guarantee
	G ((sideSense = BLOCKED) -> !(steer =RIGHT));
 
guarantee
	G (((spec_policy = SEEKING) & (sideSense=BLOCKED) & (obstacle=CLEAR))
		-> (next(spec_policy=SEEKING) & throttle=FWD & parkCommand=STOP &steer = CENTER) );
guarantee
	G (((spec_policy = SEEKING) & (sideSense=BLOCKED))
		-> (next(spec_policy=SEEKING) & parkCommand=STOP &steer = CENTER) );


guarantee
	G (((spec_policy = SEEKING) & (sideSense=CLEAR | sideSense = P_O) & (obstacle = CLEAR) &(parkResult =NA))
		-> (next(spec_policy = MEASURING)&throttle=FWD & parkCommand=START & steer = CENTER));
guarantee
	G (((spec_policy = MEASURING) & (sideSense=CLEAR | sideSense = P_O)& (obstacle = CLEAR) &(parkResult =NA))
		-> (next(spec_policy = MEASURING)&throttle=FWD & parkCommand=CHECK & steer = CENTER));
guarantee
	G (((spec_policy = MEASURING) & (sideSense=CLEAR | sideSense = P_O)& (obstacle = CLEAR) &(parkResult =PARALLEL))
		-> (next(spec_policy = PARKING) & (throttle = STOP) & (parkCommand = STOP) & steer = CENTER)
	);
guarantee
	G (((spec_policy = MEASURING) & (sideSense=BLOCKED) & (obstacle = CLEAR) & (parkResult =PARALLEL)) 
		-> (next(spec_policy = PARKING) & (throttle = STOP) & (parkCommand = STOP))
	);
guarantee
	G (((spec_policy = MEASURING) & (sideSense=BLOCKED)& (obstacle = CLEAR) &(parkResult =NA))
		-> (next(spec_policy = SEEKING) & (throttle = FWD) & (parkCommand = STOP))
	);
guarantee
	G ( (spec_policy = PARKING) -> (next(spec_policy = PARKED)));
guarantee
	G (((spec_policy = PARKED))
		-> (next(spec_policy = PARKED) & (throttle = STOP) & (steer = LEFT) & (parkCommand = STOP))
	);
guarantee
	G(((obstacle=BLOCKED) &!(spec_policy=PARKING | spec_policy = PARKED))->(next(spec_policy = SEEKING)));
	
guarantee
	G((obstacle=BLOCKED)->(parkCommand=STOP));


assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
	G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

assumption
  respondsTo((spec_policy=SEEKING),(spec_policy=PARKING));
assumption
	G ((spec_policy = SEEKING) -> (parkResult = NA));
assumption
	parkResult = NA ;



 
 

 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
		env {CLEAR, BLOCKED} obstacle ;
		env {CLEAR,P_O, BLOCKED} sideSense;
		env {NA,PARALLEL} parkResult;
 
		sys {FWD, BWD, STOP} throttle ;
		sys {RIGHT,LEFT, CENTER} steer ;
		sys {START,STOP,CHECK} parkCommand ;
		sys boolean spec_park;
		sys {SEEKING,MEASURING,PARKING,PARKED} spec_policy;

 
 

guarantee
	spec_policy=SEEKING & !spec_park;

guarantee 
  GF (spec_park);

guarantee
	G(!next(spec_park) -> !next(spec_policy = PARKED));
guarantee
	G(next(spec_park) -> next(spec_policy = PARKED));	
 
 
guarantee
  respondsTo(!(spec_policy=PARKED),!(throttle=STOP));
guarantee
	G (((spec_policy=SEEKING|spec_policy=MEASURING)& obstacle = BLOCKED)->(throttle = BWD));
guarantee
	G (((spec_policy=PARKING|spec_policy=PARKED)& obstacle = BLOCKED)->!(throttle = FWD));
guarantee
	G ((sideSense = BLOCKED) -> !(steer =RIGHT));

 
 
guarantee
	G (((spec_policy = SEEKING) & (sideSense=BLOCKED) & (obstacle=CLEAR))
		-> (next(spec_policy=SEEKING) & throttle=FWD & parkCommand=STOP &steer = CENTER) );
 
guarantee
	G (((spec_policy = SEEKING) & (sideSense=BLOCKED))
		-> (next(spec_policy=SEEKING) & parkCommand=STOP &steer = CENTER) );
 
guarantee
	G (((spec_policy = SEEKING) & (sideSense=CLEAR | sideSense = P_O) & (obstacle = CLEAR) &(parkResult =NA))
		-> (next(spec_policy = MEASURING)&throttle=FWD & parkCommand=START & steer = CENTER));
 
guarantee
	G (((spec_policy = MEASURING) & (sideSense=CLEAR | sideSense = P_O)& (obstacle = CLEAR) &(parkResult =NA))
		-> (next(spec_policy = MEASURING)&throttle=FWD & parkCommand=CHECK & steer = CENTER));
 
guarantee
	G (((spec_policy = MEASURING) & (sideSense=CLEAR | sideSense = P_O)& (obstacle = CLEAR) &(parkResult =PARALLEL))
		-> (next(spec_policy = PARKING) & (throttle = STOP) & (parkCommand = STOP) & steer = CENTER)
	);
 
guarantee
	G (((spec_policy = MEASURING) & (sideSense=BLOCKED) & (obstacle = CLEAR) & (parkResult =PARALLEL)) 
		-> (next(spec_policy = PARKING) & (throttle = STOP) & (parkCommand = STOP))
	);
 
guarantee
	G (((spec_policy = MEASURING) & (sideSense=BLOCKED)& (obstacle = CLEAR) &(parkResult =NA))
		-> (next(spec_policy = SEEKING) & (throttle = FWD) & (parkCommand = STOP))
	);
 
guarantee
	G ( (spec_policy = PARKING) -> (next(spec_policy = PARKED)));
 
guarantee
	G (((spec_policy = PARKED))
		-> (next(spec_policy = PARKED) & (throttle = STOP) & (steer = LEFT) & (parkCommand = STOP))
	);
 
guarantee
	G(((obstacle=BLOCKED) &!(spec_policy=PARKING | spec_policy = PARKED))->(next(spec_policy = SEEKING)));
	
 
guarantee
	G((obstacle=BLOCKED)->(parkCommand=STOP));



 

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
	G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

assumption
  respondsTo((spec_policy=SEEKING),(spec_policy=PARKING));
assumption
	G ((spec_policy = SEEKING) -> (parkResult = NA));
assumption
	parkResult = NA ;



 
 

 
 
 
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLEAR,P_O, BLOCKED} sideSense;
 env {NA,PARALLEL} parkResult;
 
 sys {FWD, BWD, STOP} throttle ;
 sys {RIGHT,LEFT, CENTER} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED} spec_policy;

 
 

 
guarantee
( spec_policy=SEEKING |( spec_policy=MEASURING & parkCommand = START));

 
guarantee
  GF (spec_policy=PARKED);

 
 
 
 


guarantee
 G (((spec_policy=SEEKING|spec_policy=MEASURING)& obstacle = BLOCKED)->(throttle = BWD)); 
 
 
guarantee
 G ((obstacle = BLOCKED)->!(throttle = FWD));

 
guarantee
 G ((sideSense = BLOCKED) -> !((steer =RIGHT) &(throttle=FWD)));
 
 
 
 
 
 
 
 

guarantee
G(((spec_policy = SEEKING) & (sideSense = BLOCKED)) ->  ((next(spec_policy) = spec_policy)));


guarantee
 G (((spec_policy = SEEKING) & (sideSense=CLEAR | sideSense = P_O) & (obstacle = CLEAR))
 -> (next(spec_policy) = MEASURING)&throttle=FWD & parkCommand=START & steer = CENTER);
 
guarantee
 G (((spec_policy = MEASURING) & (sideSense=CLEAR | sideSense = P_O)& (obstacle = CLEAR) &(parkResult =NA))
 -> (next(spec_policy) = spec_policy)&throttle=FWD & parkCommand=CHECK & steer = CENTER);
guarantee
 G (((spec_policy = MEASURING) & (sideSense=CLEAR | sideSense = P_O)& (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) & steer = RIGHT);
 
guarantee
 G (((spec_policy = MEASURING) & (sideSense=BLOCKED) & (obstacle = CLEAR) & (parkResult =PARALLEL)) 
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) & steer = RIGHT);
 
guarantee
 G (((spec_policy = MEASURING) & (sideSense=BLOCKED)& (obstacle = CLEAR) &(parkResult =NA))
 -> (next(spec_policy) = SEEKING) & (throttle = FWD) & (parkCommand = STOP));
 
guarantee
 G ((spec_policy = PARKING_0)
 -> (next(spec_policy) = PARKING_1) & (throttle = BWD) & steer = RIGHT & (parkCommand = STOP));
 
guarantee
 G ((spec_policy = PARKING_1)
 -> (next(spec_policy) = PARKING_2) & (throttle = STOP) & steer = LEFT & (parkCommand = STOP));
 
guarantee
 G ((spec_policy = PARKING_2)
 -> (next(spec_policy) = PARKED) & (throttle = BWD) & steer = LEFT & (parkCommand = STOP));
 
guarantee
 G (((spec_policy = PARKED))
 -> (next(spec_policy) = spec_policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 
guarantee
 G(((obstacle=BLOCKED) &!(spec_policy=PARKING_0 |spec_policy=PARKING_1 |spec_policy=PARKING_2| spec_policy=PARKED))->(next(spec_policy) = SEEKING));
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G (spec_policy = SEEKING -> (throttle != STOP));

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

assumption
  respondsTo((spec_policy=SEEKING)&(throttle=FWD),(spec_policy=PARKING_0));
 
 
assumption
 parkResult = NA ;



 
 

 
 
 
 
 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLEAR, BLOCKED} sideSense;
 env {NA,PARALLEL} parkResult;
 
 
 sys {FWD, BWD, STOP} throttle ;
 sys {RIGHT,LEFT, CENTER} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED} spec_policy;



 
guarantee
( spec_policy=SEEKING );

 
guarantee
  GF (spec_policy=PARKED);
 
 
  
 
 guarantee
 G((spec_policy = SEEKING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G((spec_policy = MEASURING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G((spec_policy = PARKING_0)-> (next(spec_policy)=(PARKING_1)));
 guarantee
 G((spec_policy = PARKING_1)-> (next(spec_policy)=(PARKING_2)));
 guarantee
 G((spec_policy = PARKING_2)-> (next(spec_policy)=(PARKED)));


 
guarantee
 G ((obstacle = BLOCKED)->!(throttle = FWD));


 
guarantee
 G ((sideSense = BLOCKED) -> !((steer =RIGHT) &(throttle=FWD)));


 
guarantee
 G(((obstacle=BLOCKED) &(spec_policy=MEASURING |spec_policy=SEEKING))->(next(spec_policy) = SEEKING));
 
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((spec_policy = SEEKING & parkResult=NA) -> (throttle != STOP));



 
guarantee
G(((spec_policy = SEEKING) & (sideSense = BLOCKED) & parkResult=NA) ->  ((next(spec_policy) = spec_policy) & (parkCommand = STOP)));

 
guarantee
 G (((spec_policy = SEEKING) & sideSense=CLEAR & (obstacle = CLEAR) & parkResult = NA)
 -> (next(spec_policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((spec_policy = MEASURING) & (sideSense=BLOCKED) &(parkResult =NA))
 -> (next(spec_policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((spec_policy = MEASURING) & sideSense=CLEAR & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(spec_policy) = spec_policy)&throttle=FWD & parkCommand=CHECK & steer = CENTER);
 
  
guarantee
 G (((((spec_policy = MEASURING)|(spec_policy=SEEKING & PREV(spec_policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) & steer = RIGHT);
 
 
 
guarantee
 G ((spec_policy = PARKING_0)
 -> (next(spec_policy) = PARKING_1) & (throttle = BWD) & steer = RIGHT & (parkCommand = STOP));
 
 
 
  
guarantee
 G ((spec_policy = PARKING_1)
 -> (next(spec_policy) = PARKING_2) & (throttle = STOP) & steer = LEFT & (parkCommand = STOP));
 
 
  
guarantee
 G ((spec_policy = PARKING_2)
 -> (next(spec_policy) = PARKED) & (throttle = BWD) & steer = LEFT & (parkCommand = STOP));

 
 
guarantee
 G (((spec_policy = PARKED))
 -> (next(spec_policy) = spec_policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 


assumption
G ((spec_policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
sideSense=BLOCKED & parkResult = NA;

 
assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

 
 
 
 
 
 
 
 
 
 
 
  
 
 

 
 
 
 
 
 
 
 
 
  
 

 
 
 
 

 
 
 

 
 

 
 
 
 
 
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
  
 
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED} policy;



 
guarantee
( policy=SEEKING );

 
 
 
 
guarantee
  GF (policy=PARKED);
 
 
 
 guarantee
  
  
  
 G((policy = SEEKING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
 guarantee
 G ((policy = SEEKING) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 
 guarantee
 G((policy = MEASURING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
  guarantee
 G ((policy = MEASURING) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((policy = PARKING_0)-> (next(policy)=(PARKING_1)));
 guarantee
 G((policy = PARKING_1)-> (next(policy)=(PARKING_2)));
 guarantee
 G((policy = PARKING_2)-> (next(policy)=(PARKED)));
 guarantee
 G((policy = PARKED)-> (next(policy)=(PARKED)));
 
 
 
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (policy=SEEKING) & parkResult = NA)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (policy = SEEKING | policy = MEASURING)) ->(next(policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((policy = SEEKING & parkResult=NA) -> (throttle != STOP));

 
 
 
 
  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = FAR) -> (steer=EASY_RIGHT));

  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense != CLOSE) & PREV(sideSense != FAR))) -> (steer=CENTER));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED) ->
 (steer=EASY_LEFT & next(steer)=CENTER));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED) ->
 (steer=EASY_RIGHT & next(steer)=CENTER));

 
 
 
 

assumption
G (PREV(sideSense = FAR) & sideSense = CENTERED -> next(sideSense) = CENTERED); 
assumption
G (PREV(sideSense = CLOSE) & sideSense = CENTERED -> next(sideSense) = CENTERED); 


 
 
   
 guarantee
  
  
  
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR) -> (steer=EASY_RIGHT));

   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING) -> (steer=CENTER));
 
 
 
 
 
 
guarantee
G(((policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & parkResult=NA)
-> ((next(policy) = policy) & (parkCommand = STOP)));


 
guarantee
 G (((policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR))
 -> (next(policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(policy) = policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G (((((policy = MEASURING & sideSense = PARALLEL_PARKING)|(policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(policy) = PARKING_0) & (throttle = BLOCKING_FWD) & (parkCommand = STOP) );

 
guarantee
 G ((policy = PARKING_0)
 -> (next(policy) = PARKING_1) & (throttle = STOP) & steer = CENTER & (parkCommand = STOP));

 
 
 
 
 
  
guarantee
 G ((policy = PARKING_1)
 -> (next(policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((policy = PARKING_2)
 -> (next(policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
guarantee
 G (((policy = PARKED))
 -> (next(policy) = policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));

 
 
 
 
assumption
G ((policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
sideSense=CENTERED & parkResult = NA;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

 
 

 
 

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
  
 
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD, EXIT_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED, EXIT_0,EXIT_1, EXIT_2} spec_policy;


 
guarantee
( spec_policy=SEEKING );

 
 
 
 
guarantee
  GF (spec_policy=PARKED);
 
 
 
 guarantee
  
  
  
 G((spec_policy = SEEKING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G ((spec_policy = SEEKING) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 
 guarantee
 G((spec_policy = MEASURING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
  guarantee
 G ((spec_policy = MEASURING) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((spec_policy = PARKING_0)-> (next(spec_policy)=(PARKING_1)));
 guarantee
 G((spec_policy = PARKING_1)-> (next(spec_policy)=(PARKING_2)));
 guarantee
 G((spec_policy = PARKING_2)-> (next(spec_policy)=(PARKED)));
 guarantee
 G((spec_policy = PARKED)-> (next(spec_policy)=(PARKED) | next(spec_policy)=(EXIT_0)));
 guarantee
 G((spec_policy = EXIT_0)-> (next(spec_policy)=(EXIT_1)));
 guarantee
 G((spec_policy = EXIT_1)-> (next(spec_policy)=(EXIT_2)));
 guarantee
 G((spec_policy = EXIT_2)-> (next(spec_policy)=(SEEKING)));
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (spec_policy=SEEKING) & parkResult = NA)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (spec_policy = SEEKING | spec_policy = MEASURING)) ->(next(spec_policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((spec_policy = SEEKING & parkResult=NA) -> (throttle != STOP));

 
 
 
 
  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = FAR) -> (steer=EASY_RIGHT));

  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense = CENTERED))) -> (steer=CENTER));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED) ->
 (steer=EASY_LEFT));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED) ->
 (steer=EASY_RIGHT));

 
 
 
 

 
 
 
 


 
 
   
 guarantee
  
  
  
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR) -> (steer=EASY_RIGHT));

   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PARALLEL_PARKING)) -> (steer=CENTER));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = CLOSE_PARKING)) -> (steer=EASY_RIGHT));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PERPENDICULAR)) -> (steer=EASY_LEFT));
 
 
 
 
 
 
guarantee
G(((spec_policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & parkResult=NA)
-> ((next(spec_policy) = spec_policy) & (parkCommand = STOP)));


 
guarantee
 G (((spec_policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR))
 -> (next(spec_policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((spec_policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(spec_policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((spec_policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(spec_policy) = spec_policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G (((((spec_policy = MEASURING & sideSense = PARALLEL_PARKING)|(spec_policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(spec_policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) );

 
guarantee
 G ((spec_policy = PARKING_0)
 -> (next(spec_policy) = PARKING_1) & (throttle = BLOCKING_FWD) & steer = CENTER & (parkCommand = STOP));

 
 
 
 
 
  
guarantee
 G ((spec_policy = PARKING_1)
 -> (next(spec_policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((spec_policy = PARKING_2)
 -> (next(spec_policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
 
 
 
 
 
guarantee
 G (((spec_policy = PARKED))
 -> (next(spec_policy) = EXIT_0) & (throttle = EXIT_FWD) & (steer = LEFT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_0))
 -> (next(spec_policy) = EXIT_1) & (throttle = EXIT_FWD) & (steer = RIGHT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_1))
 -> (next(spec_policy) = EXIT_2) & (steer = CENTER) & (throttle = STOP));
 
 
guarantee
 G (((spec_policy = EXIT_2))
 -> (next(spec_policy) = SEEKING));

 
 
 
 
assumption
G ((spec_policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((spec_policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
sideSense=CENTERED & parkResult = NA;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));

 
 

 
 

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
 env {BLACK, GREEN, RED} colorSense;
 
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD, EXIT_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED, EXIT_0,EXIT_1, EXIT_2} spec_policy;


 
guarantee
( spec_policy=SEEKING );

 
 
 
 
guarantee
  GF (spec_policy=PARKED);
 
 
 
 guarantee
  
  
  
 G((spec_policy = SEEKING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G ((spec_policy = SEEKING) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 guarantee
  G ((spec_policy = SEEKING & obstacle = CLEAR) -> (!(steer = RIGHT | steer = LEFT )));

 
 guarantee
 G((spec_policy = MEASURING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
  guarantee
 G ((spec_policy = MEASURING) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((spec_policy = PARKING_0)-> (next(spec_policy)=(PARKING_1)));
 guarantee
 G((spec_policy = PARKING_1)-> (next(spec_policy)=(PARKING_2)));
 guarantee
 G((spec_policy = PARKING_2)-> (next(spec_policy)=(PARKED)));
 guarantee
 G((spec_policy = PARKED)-> (next(spec_policy)=(PARKED) | next(spec_policy)=(EXIT_0)));
 guarantee
 G((spec_policy = EXIT_0)-> (next(spec_policy)=(EXIT_1)));
 guarantee
 G((spec_policy = EXIT_1)-> (next(spec_policy)=(SEEKING)));
 
 
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (spec_policy=SEEKING) & parkResult = NA)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (spec_policy = SEEKING | spec_policy = MEASURING)) ->(next(spec_policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((spec_policy = SEEKING & parkResult=NA) -> (throttle != STOP));

 
 
 
 
  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = FAR) -> (steer=EASY_RIGHT));

  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense = CENTERED))) -> (steer=CENTER));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED) ->
 (steer=EASY_LEFT));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED) ->
 (steer=EASY_RIGHT));
 
 
   
 guarantee
  
  
  
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR) -> (steer=EASY_RIGHT));

   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PARALLEL_PARKING)) -> (steer=CENTER));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = CLOSE_PARKING)) -> (steer=EASY_RIGHT));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PERPENDICULAR)) -> (steer=EASY_LEFT));
 
 
 
 
 
 
guarantee
G(((spec_policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR))
-> ((next(spec_policy) = spec_policy) & (parkCommand = STOP)));


 
guarantee
 G (((spec_policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR))
 -> (next(spec_policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((spec_policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(spec_policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((spec_policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(spec_policy) = spec_policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G ((((spec_policy = MEASURING & sideSense = PARALLEL_PARKING)|(spec_policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(spec_policy=MEASURING))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) );

 
guarantee
 G ((spec_policy = PARKING_0)
 -> (next(spec_policy) = PARKING_1) & (throttle = BLOCKING_FWD) & steer = CENTER & (parkCommand = STOP));

 
 
 
 
 
  
guarantee
 G ((spec_policy = PARKING_1)
 -> (next(spec_policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((spec_policy = PARKING_2)
 -> (next(spec_policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
guarantee
 G (((spec_policy = PARKED) & colorSense = RED)
 -> (next(spec_policy) = spec_policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 
 
guarantee
 G (((spec_policy = PARKED) & colorSense != RED)
 -> (next(spec_policy) = EXIT_0) & (throttle = EXIT_FWD) & (steer = LEFT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_0))
 -> (next(spec_policy) = EXIT_1) & (throttle = EXIT_FWD) & (steer = RIGHT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_1))
 -> (next(spec_policy) = SEEKING) & (steer = CENTER) & (throttle = STOP));
 
 
 
 
 

 
 
 
 
assumption
G ((spec_policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((spec_policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
sideSense=CENTERED & parkResult = NA;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));
 
assumption
G ((spec_policy != PARKED) -> next(colorSense = BLACK)); 

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
 env {BLACK, GREEN, RED} colorSense;
 env {FREE, PRESSED} reset;
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD, EXIT_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED, EXIT_0,EXIT_1} policy;


 
guarantee
( policy=SEEKING);

 
 
 
 
guarantee
  GF (policy=PARKED&colorSense=GREEN);
 
 guarantee
  
  
  
 G((policy = SEEKING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
 guarantee
 G ((policy = SEEKING) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 guarantee
  G ((policy = SEEKING & obstacle = CLEAR) -> (!(steer = RIGHT | steer = LEFT )));

 
 guarantee
 G((policy = MEASURING)-> (next(policy)=SEEKING| next(policy) = MEASURING| next(policy) = PARKING_0));
  guarantee
 G ((policy = MEASURING) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((policy = PARKING_0)-> (next(policy)=(PARKING_1)));
 guarantee
 G((policy = PARKING_1)-> (next(policy)=(PARKING_2)));
 guarantee
 G((policy = PARKING_2)-> (next(policy)=(PARKED)));
 guarantee
 G((policy = PARKED)-> (next(policy)=(PARKED) | next(policy)=(EXIT_0)));
 guarantee
 G((policy = EXIT_0)-> (next(policy)=(EXIT_1)));
 guarantee
 G((policy = EXIT_1)-> (next(policy)=(SEEKING)));
 
 
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (policy=SEEKING) & parkResult = NA)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (policy = SEEKING | policy = MEASURING)) ->(next(policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((policy = SEEKING & parkResult=NA) -> (throttle != STOP));

 
 
 
 guarantee
 G((policy=SEEKING & obstacle = CLEAR & PREV(obstacle = BLOCKED)) -> (steer=CENTER));
 
  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE & PREV(obstacle = CLEAR)) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = FAR & PREV(obstacle = CLEAR)) -> (steer=EASY_RIGHT));
 
  
 guarantee
 G((policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense = CENTERED)) & PREV(obstacle = CLEAR)) -> (steer=CENTER));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED & PREV(obstacle = CLEAR)) ->
 (steer=EASY_LEFT));
 
 guarantee
 G((policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED & PREV(obstacle = CLEAR)) ->
 (steer=EASY_RIGHT));
 
 
   
 guarantee
  
  
  
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR) -> (steer=EASY_RIGHT));

   
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PARALLEL_PARKING)) -> (steer=CENTER));
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = CLOSE_PARKING)) -> (steer=EASY_RIGHT));
 guarantee
 G((policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PERPENDICULAR)) -> (steer=EASY_LEFT));
 
 
 
 
 
 
guarantee
G(((policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR))
-> ((next(policy) = policy) & (parkCommand = STOP)));


 
guarantee
 G (((policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR))
 -> (next(policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(policy) = policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G (((((policy = MEASURING & sideSense = PARALLEL_PARKING)|(policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) );

 
guarantee
 G ((policy = PARKING_0)
 -> (next(policy) = PARKING_1) & (throttle = BLOCKING_FWD) & steer = CENTER & (parkCommand = STOP));
 
  
guarantee
 G ((policy = PARKING_1)
 -> (next(policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((policy = PARKING_2)
 -> (next(policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
guarantee
 G (((policy = PARKED) & colorSense = GREEN & reset = FREE)
 -> (next(policy) = policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 
 
guarantee
 G (((policy = PARKED) & (!(colorSense = GREEN) | reset = PRESSED ))
 -> (next(policy) = EXIT_0) & (throttle = EXIT_FWD) & (steer = LEFT) & (parkCommand = STOP));

 
guarantee
 G (((policy = EXIT_0))
 -> (next(policy) = EXIT_1) & (throttle = EXIT_FWD) & (steer = RIGHT) & (parkCommand = STOP));

 
guarantee
 G (((policy = EXIT_1))
 -> (next(policy) = SEEKING) & (steer = CENTER) & (throttle = STOP));
 
 
 
 
 
assumption
G ((policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
parkResult = NA & reset = FREE;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));
 
assumption
G ((policy != PARKED) -> next(colorSense = BLACK));

assumption
  GF ((policy=PARKED&colorSense=GREEN&reset=FREE));

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
 env {BLACK, GREEN, RED} colorSense;
 env {FREE, PRESSED} reset;
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD, EXIT_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED, EXIT_0,EXIT_1} spec_policy;


 
guarantee
( spec_policy=SEEKING);

 
 
 
 
guarantee
  GF (spec_policy=PARKED&colorSense=GREEN);
 
 guarantee
  
  
  
 G((spec_policy = SEEKING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G ((spec_policy = SEEKING) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 guarantee
  G ((spec_policy = SEEKING & obstacle = CLEAR) -> (!(steer = RIGHT | steer = LEFT )));

 
 guarantee
 G((spec_policy = MEASURING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
  guarantee
 G ((spec_policy = MEASURING) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((spec_policy = PARKING_0)-> (next(spec_policy)=(PARKING_1)));
 guarantee
 G((spec_policy = PARKING_1)-> (next(spec_policy)=(PARKING_2)));
 guarantee
 G((spec_policy = PARKING_2)-> (next(spec_policy)=(PARKED)));
 guarantee
 G((spec_policy = PARKED)-> (next(spec_policy)=(PARKED) | next(spec_policy)=(EXIT_0)));
 guarantee
 G((spec_policy = EXIT_0)-> (next(spec_policy)=(EXIT_1)));
 guarantee
 G((spec_policy = EXIT_1)-> (next(spec_policy)=(SEEKING)));
 
 
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (spec_policy=SEEKING) & parkResult = NA)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (spec_policy = SEEKING | spec_policy = MEASURING)) ->(next(spec_policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((spec_policy = SEEKING & parkResult=NA) -> (throttle != STOP));

 
 
 
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR & PREV(obstacle = BLOCKED)) -> (steer=CENTER));
 
  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE & PREV(obstacle = CLEAR)) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = FAR & PREV(obstacle = CLEAR)) -> (steer=EASY_RIGHT));
 
  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense = CENTERED)) & PREV(obstacle = CLEAR)) -> (steer=CENTER));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED & PREV(obstacle = CLEAR)) ->
 (steer=EASY_LEFT));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED & PREV(obstacle = CLEAR)) ->
 (steer=EASY_RIGHT));
 
 
   
 guarantee
  
  
  
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR) -> (steer=EASY_RIGHT));

   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PARALLEL_PARKING)) -> (steer=CENTER));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = CLOSE_PARKING)) -> (steer=EASY_RIGHT));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PERPENDICULAR)) -> (steer=EASY_LEFT));
 
 
 
 
 
 
guarantee
G(((spec_policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR))
-> ((next(spec_policy) = spec_policy) & (parkCommand = STOP)));


 
guarantee
 G (((spec_policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR))
 -> (next(spec_policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((spec_policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(spec_policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((spec_policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA))
 -> (next(spec_policy) = spec_policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G (((((spec_policy = MEASURING & sideSense = PARALLEL_PARKING)|(spec_policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(spec_policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL))
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) );

 
guarantee
 G ((spec_policy = PARKING_0)
 -> (next(spec_policy) = PARKING_1) & (throttle = BLOCKING_FWD) & steer = CENTER & (parkCommand = STOP));
 
  
guarantee
 G ((spec_policy = PARKING_1)
 -> (next(spec_policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((spec_policy = PARKING_2)
 -> (next(spec_policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
guarantee
 G (((spec_policy = PARKED) & colorSense = GREEN & reset = FREE)
 -> (next(spec_policy) = spec_policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 
 
guarantee
 G (((spec_policy = PARKED) & (!(colorSense = GREEN) | reset = PRESSED ))
 -> (next(spec_policy) = EXIT_0) & (throttle = EXIT_FWD) & (steer = LEFT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_0))
 -> (next(spec_policy) = EXIT_1) & (throttle = EXIT_FWD) & (steer = RIGHT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_1))
 -> (next(spec_policy) = SEEKING) & (steer = CENTER) & (throttle = STOP));
 
 
 
 
 
assumption
G ((spec_policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((spec_policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
parkResult = NA & reset = FREE;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));
 
assumption
G ((spec_policy != PARKED) -> next(colorSense = BLACK));

assumption
  GF ((spec_policy=PARKED&colorSense=GREEN&reset=FREE));

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module PCar
 env {CLEAR, BLOCKED} obstacle ;
 env {CLOSE, CENTERED, FAR, CLOSE_PARKING, PARALLEL_PARKING ,PERPENDICULAR} sideSense;
 env {NA,PARALLEL} parkResult;
 env {BLACK, GREEN, RED} colorSense;
 env {AUTO,MANUAL,FWD,BWD,FWD_RIGHT,FWD_LEFT,BWD_LEFT,BWD_RIGHT,RIGHT,LEFT,CENTER} command;
 env {FREE, PRESSED} reset;
 
 sys {FWD, BWD, STOP,BLOCKING_BWD, BLOCKING_FWD, EXIT_FWD} throttle ;
 sys {RIGHT,LEFT, CENTER, EASY_RIGHT, EASY_LEFT} steer ;
 sys {START,STOP,CHECK} parkCommand ;
 sys {SEEKING,MEASURING,PARKING_0,PARKING_1,PARKING_2,PARKED, EXIT_0,EXIT_1} spec_policy;


 
guarantee
( spec_policy=SEEKING );

 
 
 
 
guarantee
  GF ((spec_policy=PARKED&colorSense=GREEN)|command!=AUTO);
 
 
 
 
 
 
 
  guarantee
 G(command=MANUAL   -> throttle=STOP & steer=CENTER); 
 
 
 guarantee
 G(command=FWD  -> throttle=FWD & steer=CENTER);
 
  guarantee
   G((command=BWD)-> throttle=BWD & steer=CENTER); 
 
   guarantee
 G((command=RIGHT) ->( steer=RIGHT & throttle=STOP)); 
 
    guarantee
 G((command=LEFT)-> steer=LEFT  & throttle=STOP); 
 
     guarantee
 G((command=CENTER)-> steer=CENTER & throttle=STOP ); 
 
    guarantee
 G((command=FWD_LEFT)-> steer=LEFT & throttle=FWD );
 
    guarantee
 G((command=FWD_RIGHT)-> steer=RIGHT & throttle=FWD);  
 
     guarantee
 G((command=BWD_LEFT)-> steer=LEFT & throttle=BWD );
 
     guarantee
 G( command=BWD_RIGHT -> steer=RIGHT & throttle=BWD);
 
 
 
 

 guarantee
  
  
  
 G((spec_policy = SEEKING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
 guarantee
 G ((spec_policy = SEEKING & command=AUTO ) -> ((throttle = FWD | throttle = STOP | throttle = BWD)));
 guarantee
  G ((spec_policy = SEEKING & obstacle = CLEAR & command=AUTO ) -> (!(steer = RIGHT | steer = LEFT )));

 
 guarantee
 G((spec_policy = MEASURING)-> (next(spec_policy)=SEEKING| next(spec_policy) = MEASURING| next(spec_policy) = PARKING_0));
  guarantee
 G ((spec_policy = MEASURING & command=AUTO) -> (throttle != BLOCKING_BWD & parkCommand != START & (steer = CENTER | steer = EASY_LEFT | steer = EASY_RIGHT)));
 
 
 guarantee
 G((spec_policy = PARKING_0)-> (next(spec_policy)=(PARKING_1)));
 guarantee
 G((spec_policy = PARKING_1)-> (next(spec_policy)=(PARKING_2)));
 guarantee
 G((spec_policy = PARKING_2)-> (next(spec_policy)=(PARKED)));
 guarantee
 G((spec_policy = PARKED)-> (next(spec_policy)=(PARKED) | next(spec_policy)=(EXIT_0)));
 guarantee
 G((spec_policy = EXIT_0)-> (next(spec_policy)=(EXIT_1)));
 guarantee
 G((spec_policy = EXIT_1)-> (next(spec_policy)=(SEEKING)));
 
 
 

 
 
 

guarantee
 G (((obstacle = CLEAR) & (spec_policy=SEEKING) & parkResult = NA & command=AUTO)->(throttle = FWD));


 
guarantee
 G(((obstacle=BLOCKED) & (spec_policy = SEEKING | spec_policy = MEASURING) & command=AUTO) ->(next(spec_policy) = SEEKING) & !(throttle = FWD | throttle = BLOCKING_FWD | throttle = BLOCKING_BWD) & !(steer = EASY_RIGHT | steer = EASY_LEFT));
 
 
guarantee
 G((obstacle=BLOCKED)->(parkCommand=STOP));
 
guarantee
G ((spec_policy = SEEKING & parkResult=NA & command=AUTO) -> (throttle != STOP));

 
 
 
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR & PREV(obstacle = BLOCKED) & command=AUTO) -> (steer=CENTER));
 
  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CLOSE & command=AUTO  & PREV(obstacle = CLEAR))  -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = FAR & command=AUTO  & PREV(obstacle = CLEAR)) -> (steer=EASY_RIGHT));

  
 guarantee
 G((spec_policy=SEEKING & obstacle = CLEAR &  sideSense = CENTERED & (PREV(sideSense = CENTERED)) & command=AUTO & PREV(obstacle = CLEAR)) -> (steer=CENTER));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = FAR) & sideSense = CENTERED & command=AUTO & PREV(obstacle = CLEAR)) ->
 (steer=EASY_LEFT));
 
 guarantee
 G((spec_policy = SEEKING & obstacle = CLEAR & PREV(sideSense = CLOSE) & sideSense = CENTERED & command=AUTO & PREV(obstacle = CLEAR)) ->
 (steer=EASY_RIGHT));
 
 
   
 guarantee
  
  
  
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = CLOSE_PARKING & command=AUTO) -> (steer=EASY_LEFT));
 
   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PERPENDICULAR & command=AUTO) -> (steer=EASY_RIGHT));

   
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PARALLEL_PARKING) & command=AUTO) -> (steer=CENTER));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = CLOSE_PARKING) & command=AUTO) -> (steer=EASY_RIGHT));
 guarantee
 G((spec_policy=MEASURING & obstacle = CLEAR &  sideSense = PARALLEL_PARKING & PREV(sideSense = PERPENDICULAR) & command=AUTO) -> (steer=EASY_LEFT));
 
 
 
 
 
 
guarantee
G(((spec_policy = SEEKING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR))
-> ((next(spec_policy) = spec_policy) & (parkCommand = STOP)));


 
guarantee
 G (((spec_policy = SEEKING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR)& command=AUTO)
 -> (next(spec_policy) = MEASURING) & throttle=FWD & parkCommand=START & steer = CENTER);
 

 
guarantee
 G (((spec_policy = MEASURING) & (sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) &(parkResult =NA))
 -> (next(spec_policy) = SEEKING)  & (parkCommand = STOP));

 

guarantee
 G (((spec_policy = MEASURING) & !(sideSense = CLOSE | sideSense = CENTERED | sideSense = FAR) & (obstacle = CLEAR) &(parkResult =NA)& command=AUTO)
 -> (next(spec_policy) = spec_policy) & throttle=FWD & parkCommand=CHECK);
 
  
guarantee
 G (((((spec_policy = MEASURING & sideSense = PARALLEL_PARKING)|(spec_policy=SEEKING & PREV(sideSense = PARALLEL_PARKING) & PREV(spec_policy=MEASURING)))) & (obstacle = CLEAR) &(parkResult =PARALLEL) & command=AUTO)
 -> (next(spec_policy) = PARKING_0) & (throttle = STOP) & (parkCommand = STOP) );

 
guarantee
 G ((spec_policy = PARKING_0 & command=AUTO)
 -> (next(spec_policy) = PARKING_1) & (throttle = BLOCKING_FWD) & steer = CENTER & (parkCommand = STOP));
 
  
guarantee
 G ((spec_policy = PARKING_1 & command=AUTO)
 -> (next(spec_policy) = PARKING_2) & (throttle = BLOCKING_BWD) & steer = RIGHT & (parkCommand = STOP));

 
  
guarantee
 G ((spec_policy = PARKING_2 & command=AUTO)
 -> (next(spec_policy) = PARKED) & (throttle = BLOCKING_BWD) & steer = LEFT & (parkCommand = STOP));


 
guarantee
 G (((spec_policy = PARKED) & colorSense = GREEN & reset = FREE & command=AUTO)
 -> (next(spec_policy) = spec_policy) & (throttle = STOP) & (steer = CENTER) & (parkCommand = STOP));
 
 
guarantee
 G (((spec_policy = PARKED) & (!(colorSense = GREEN) | reset = PRESSED ) & command=AUTO)
 -> (next(spec_policy) = EXIT_0) & (throttle = EXIT_FWD) & (steer = LEFT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_0 ) & command=AUTO)
 -> (next(spec_policy) = EXIT_1) & (throttle = EXIT_FWD) & (steer = RIGHT) & (parkCommand = STOP));

 
guarantee
 G (((spec_policy = EXIT_1) & command=AUTO)
 -> (next(spec_policy) = SEEKING) & (steer = CENTER) & (throttle = STOP));
 
 
 
 
 
assumption
G ((spec_policy = SEEKING)->next(parkResult = NA));

assumption
  GF ((spec_policy=MEASURING)&(parkResult=PARALLEL)&(obstacle=CLEAR));

assumption
parkResult = NA & command=AUTO & reset = FREE;

assumption
  respondsTo((throttle=BWD),(obstacle=CLEAR));

assumption
 G ((throttle=STOP)->((obstacle=next(obstacle))&(sideSense=next(sideSense))));
 
assumption
G ((spec_policy != PARKED) -> next(colorSense = BLACK));

assumption
  GF ((spec_policy=PARKED&colorSense=GREEN&reset=FREE));

 

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module AspectLTLAspect
 
		env {CLEAR, BLOCKED} obstacle ;
		
		env {	TOO_CLOSE,
							TOO_FAR,
							CENTERED,
							PS_TOO_FAR,
							PS_TOO_CLOSE,
							PS_CENTERED
						 } sideSensor ;
						 
		env {	TOO_CLOSE,
								TOO_FAR,
								CENTERED,
								PS_TOO_FAR,
								PS_TOO_CLOSE,
								PS_CENTERED
							 } rearSideSensor ;
							
	
		sys {MAX_RIGHT, MAX_LEFT, CENTER, ALIGN_RIGHT, ALIGN_LEFT} steeringMot ;
		
		sys {FWD, BWD} sensorMot ;
							
		sys {FWD, BWD, STOP, PARKING_BWD, PARKING_FWD, PREPARE_PERPENDICULAR_BWD, PERPENDICULAR_BWD} engineMot ;
		
		sys {	SEEKING_FOR_PS, 
							MEASURE_PARKING,
							PREPARE_FOR_PARALLEL_PARKING,
							ALIGN_BEFORE_PARKING,
							PARALLEL,
							PERPENDICULAR,
							PARKED
						} carStatus ;
						
		sys Int(0..14) spec_counter ;
		
		sys {PARALLEL, PERPENDICULAR} spec_parkingType ;
			
	define
		counterLimit := 14;
		
	define 
		phaseNone := 0;
		
	define 
		firstPhase := 1;
		
	define 
		secondPhase := 2;
		
	define 
		thirdPhase := 3;
			
	define
		weGotSideSensorSeekingValues := (sideSensor = TOO_CLOSE | sideSensor = TOO_FAR | sideSensor = CENTERED);
		
	define
		weGotSideSensorMeasuringValues := (sideSensor = PS_TOO_CLOSE | sideSensor = PS_TOO_FAR | sideSensor = PS_CENTERED);	
	
	define
		Stop := (engineMot = STOP);

	define
		suitableParallelPS := 6;
		
	define
		suitablePerpendicularPS := 4;
		
	define
		preparingParallelSteps := 2;
	
	define
		capablePerpendicular := (spec_counter >= suitablePerpendicularPS);
	
	define
		keepCarStatus := (next(carStatus) = carStatus);
		
	define
		keepCounterValue := (next(spec_counter) = spec_counter);
		
	define
		keepParkingType := (next(spec_parkingType) = spec_parkingType);

	define
		movingFwd := (engineMot = FWD | engineMot = PARKING_FWD);
		
	define
		movingBwd := (engineMot = BWD | 
						engineMot = PARKING_BWD | 
						engineMot = PREPARE_PERPENDICULAR_BWD | 
						engineMot = PERPENDICULAR_BWD
		);
	
	define
		rearTooFar :=   (rearSideSensor = TOO_FAR | rearSideSensor = PS_TOO_FAR);
	
	define
		rearTooClose := (rearSideSensor = TOO_CLOSE | rearSideSensor = PS_TOO_CLOSE);
		
	define
		rearCentered := (rearSideSensor = CENTERED | rearSideSensor = PS_CENTERED);
		
	define
		frontCentered := (sideSensor = CENTERED | sideSensor = PS_CENTERED);
		
	define
		frontTooFar :=   (sideSensor = TOO_FAR | sideSensor = PS_TOO_FAR);
	
	define
		frontTooClose := (sideSensor = TOO_CLOSE | sideSensor = PS_TOO_CLOSE);
		

		
	/* Init state*/
	guarantee
		(carStatus = SEEKING_FOR_PS & sensorMot = FWD & spec_counter = 0);
		
	/* Do not run into obstacles*/
	guarantee
		G ((obstacle = BLOCKED) -> 
			(Stop)
		);
		
	/* In case of an obstacle, keep the car status and the counter value as they were
	 */
	guarantee
		G ((obstacle = BLOCKED
		) -> 
			(keepCarStatus & 
				keepCounterValue
			)
		);

	
	/* Look where you are driving */
	guarantee
		G(movingBwd -> sensorMot = BWD);
		
	guarantee
		G(movingFwd -> sensorMot = FWD);
		
	/* Final goal! */
	guarantee
  GF (carStatus=PARKED);
		
	/* Reached the final goal */
	guarantee
		G((carStatus = PARKED
		) ->
			((Stop) & (keepCarStatus) & steeringMot = CENTER )
		);
		
/**********************************************************************************/
/******************************** wall alignment **********************************/
/**********************************************************************************/
	
	/* set of options available while seeking for parking spot */
	guarantee
		G((carStatus = SEEKING_FOR_PS)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
				(engineMot = FWD | engineMot = STOP) & (spec_counter = 0)
			)
		);
	
	/* Wall alignment instructions */
	guarantee
		G((carStatus = SEEKING_FOR_PS | carStatus = PREPARE_FOR_PARALLEL_PARKING | carStatus = MEASURE_PARKING)-> 
			(
				((sideSensor = TOO_CLOSE	| sideSensor = PS_TOO_CLOSE) 	& steeringMot = ALIGN_LEFT)		| 
				((sideSensor = TOO_FAR		| sideSensor = PS_TOO_FAR)		& steeringMot = ALIGN_RIGHT)	| 
				((sideSensor = CENTERED		| sideSensor = PS_CENTERED) 	& steeringMot = CENTER)
			)
		);
	
	/* If we still didn't find potential parking spot, and there's no obstacle - keep seeking */
	guarantee
		G((carStatus = SEEKING_FOR_PS & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR
		) -> 
			(keepCarStatus)
		);
	
	/* A potential parking spot was found, and there's no obstacle - move to measuring mode */
	guarantee
		G((carStatus = SEEKING_FOR_PS & 
			(weGotSideSensorMeasuringValues) & 
			obstacle = CLEAR
		)
			 -> (
			 	(engineMot = STOP) &
			 	(next(carStatus = MEASURE_PARKING)) & 
			 	(next(spec_counter) = 1)
			)
		);
		
	
	/* V2 - We don't bypass obstacles */
	assumption
  respondsTo(obstacle=BLOCKED,(obstacle=CLEAR));

/**********************************************************************************/
/********************** measure parking spaces specs ******************************/
/**********************************************************************************/
	/* Set of options available while measuring for parking spot */
	guarantee
		G((carStatus = MEASURE_PARKING)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
			(engineMot = FWD | engineMot = STOP) & (spec_counter <= suitableParallelPS))
		);
	
	/* Don't stop if you're measuring parking spot, and there's no obstacle */
	guarantee
		G((carStatus = MEASURE_PARKING & obstacle = CLEAR & weGotSideSensorMeasuringValues)	->
			(engineMot != STOP)
		);	

	/* If we are measuring a parking spot and we didn't measure enough space, keep measuring */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorMeasuringValues) & 
			(spec_counter < suitableParallelPS) &
			obstacle = CLEAR
		) -> 
			(keepCarStatus)
		);
	
	/* Do not count over the limit */
	guarantee
		G((spec_counter <= counterLimit));
		
	/* If the parking spot ended and there is no sufficient space (not parallel and not perpendicular), 
	 * keep seeking for another parking spot
	 */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR & 
			spec_counter < suitableParallelPS & 
			!capablePerpendicular 
		) -> 
			(next(carStatus = SEEKING_FOR_PS)) 
		);
		
	/* If the parking spot ended and we can park perpendicular, move to park perpendicular */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR & 
			spec_counter < suitableParallelPS & 
			capablePerpendicular 
		) -> 
			(next(carStatus = ALIGN_BEFORE_PARKING) &
				(next(spec_parkingType) = PERPENDICULAR) &
				next(spec_counter = 0)
			) 
		);
	
	/* While measuring the parking spot, increase counter if needed */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorMeasuringValues) & 
			obstacle = CLEAR & 
			engineMot = FWD & 
			spec_counter < suitableParallelPS
		) ->
			(next(spec_counter) = (spec_counter + 1))
		);
	
	/* If the parking spot ended and we can park parallel, move to preparing to parllel */
	guarantee
		G ((carStatus = MEASURE_PARKING & 
			spec_counter = suitableParallelPS  & 
			obstacle = CLEAR 
		) -> 
			(
				(next(carStatus) = PREPARE_FOR_PARALLEL_PARKING) &
				(next(spec_counter) = 0)
				));
				
	/* Goal for this stage */		
	guarantee
  respondsTo(carStatus=MEASURE_PARKING,(carStatus=PREPARE_FOR_PARALLEL_PARKING|carStatus=ALIGN_BEFORE_PARKING));
		
	/* How to achieve the goal above */
	assumption 
  respondsTo(engineMot=FWD,(carStatus=PREPARE_FOR_PARALLEL_PARKING|carStatus=ALIGN_BEFORE_PARKING));

/**********************************************************************************/
/*************************** Preparing for parallel parking************************/
/**********************************************************************************/
		
	/* Set of options available while preparing for parking */
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
			(engineMot = FWD | engineMot = STOP))
		);
		
		
	/* Keep performing the needed steps forward in order to prepare for parallel parking */
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING & obstacle = CLEAR
			& spec_counter < preparingParallelSteps
		) ->
			((next(spec_counter) = (spec_counter + 1)) & engineMot = FWD)
		);
	
	/* Keep the car status while performing the preparing, even when you are blocked~ */	
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING & 
			(spec_counter < preparingParallelSteps)
		) -> 
			(keepCarStatus)
		);
	
	/* We completed the preparing steps, now move to actually park paralell */
	guarantee
		G ((carStatus = PREPARE_FOR_PARALLEL_PARKING & 
			spec_counter = preparingParallelSteps & 
			obstacle = CLEAR
		) -> 
			( 
				(Stop) &
				(next(carStatus) = ALIGN_BEFORE_PARKING) &
				(next(spec_parkingType) = PARALLEL) &
				(next(spec_counter) = 0)
				));

    /* Perform the necessary actions in order to reach the suitable number of steps before parking */
	guarantee
  respondsTo(carStatus=PREPARE_FOR_PARALLEL_PARKING,(spec_counter=preparingParallelSteps));
	
	/* How to achieve the goal above */
	assumption 
  respondsTo(((obstacle=CLEAR&carStatus=PREPARE_FOR_PARALLEL_PARKING)->(engineMot=FWD)),(carStatus=ALIGN_BEFORE_PARKING));
		
	
 
 
 

	/*corecting the angle to the left - those set of specs are dealing with the case where
	SPARC rear side sensor is too far from the wall/PS and the front side sensor is too close*/
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			obstacle = CLEAR &
			((rearTooFar & (frontCentered | frontTooClose)) | (rearCentered & frontTooClose)))-> 
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 1))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 1 & obstacle = CLEAR) -> 
			(engineMot = BWD & keepCarStatus & next(spec_counter = 2) & steeringMot = ALIGN_RIGHT)		
		);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 2 & obstacle = CLEAR ) -> 
			(sensorMot = FWD & Stop & keepCarStatus & next(spec_counter = 3))		
		);
		
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 3 & obstacle = CLEAR) -> 
			(engineMot = FWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)		
		);
	/*end of corecting the angle to the left */

	/*corecting the angle to the right - those set of specs are dealing with the case where
	SPARC front side sensor is too far from the wall/PS and the rear side sensor is too close*/
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & obstacle = CLEAR &
			((frontTooFar & (rearCentered | rearTooClose)) | (frontCentered & rearTooClose)))-> 
			(engineMot = FWD & keepCarStatus & next(spec_counter = 4) & (steeringMot = ALIGN_RIGHT))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 4 &
			obstacle = CLEAR)->
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 5))
		);
		
	guarantee
		G ((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 5 & obstacle = CLEAR)->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)
		);
	/*end of corecting the angle to the right */

	/*corecting the angle to the left2 - those set of specs are dealing with the case where
	SPARC rear side sensor is too far from the wall/PS and the front side sensor is also too far*/
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			obstacle = CLEAR &
			(rearTooFar & frontTooFar))-> 
			(engineMot = FWD & steeringMot = ALIGN_RIGHT & keepCarStatus & next(spec_counter = 6))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 6 &
			obstacle = CLEAR) ->
			(engineMot = FWD & steeringMot=ALIGN_LEFT & keepCarStatus & next(spec_counter = 7))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 7 &
			obstacle = CLEAR) ->
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 8))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 8 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 9) & steeringMot = CENTER)
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 9 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)
			);
	/*end of corecting the angle to the left2 */	

	/*corecting the angle to the right2 - those set of specs are dealing with the case where
	SPARC rear side sensor is too close from the wall/PS and the front side sensor is also too close*/
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 &
			obstacle = CLEAR &
			(rearTooClose & frontTooClose))-> 
			(engineMot = FWD & steeringMot = ALIGN_LEFT & keepCarStatus & next(spec_counter = 10))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 10 &
			obstacle = CLEAR) ->
			(engineMot = FWD & steeringMot=ALIGN_RIGHT & keepCarStatus & next(spec_counter = 11))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 11 &
			obstacle = CLEAR) ->
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 12))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 12 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 13) & steeringMot = CENTER)
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 13 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)
			);
	/*end of corecting the angle to the right2 */
		
		
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			spec_parkingType = PERPENDICULAR & 
			rearCentered & 
			frontCentered &
			obstacle = CLEAR
		) -> 
			((sensorMot = BWD) & Stop & next(spec_counter = firstPhase) & next(carStatus) = PERPENDICULAR)
		);
		
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			spec_parkingType = PARALLEL & 
			rearCentered & 
			frontCentered &
			obstacle = CLEAR
		) -> 
			((sensorMot = BWD) & Stop & next(spec_counter = firstPhase) & next(carStatus) = PARALLEL)
		);
		
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING) -> keepParkingType);
	
	guarantee
  respondsTo((carStatus=ALIGN_BEFORE_PARKING),(carStatus=PERPENDICULAR|carStatus=PARALLEL));
		
	assumption
  respondsTo((carStatus=ALIGN_BEFORE_PARKING&(spec_counter=0)),(carStatus=PERPENDICULAR|carStatus=PARALLEL));
		
/**********************************************************************************/
/******************************** parking parallel ********************************/
/**********************************************************************************/

	guarantee
		G((obstacle = BLOCKED & 
			carStatus = PARALLEL & 
			(PREV(sensorMot = BWD) & !movingFwd)
		) -> (sensorMot = BWD));
	/* Set of options available while parking parallel */
	
	guarantee
		G((carStatus = PARALLEL) ->
			((steeringMot = MAX_RIGHT | steeringMot = CENTER | steeringMot = MAX_LEFT) & 
			(engineMot = PARKING_BWD | engineMot = STOP))
		);
	
	/* Performing first step of the parallel parking */
	guarantee
		G((carStatus = PARALLEL & 
			spec_counter = firstPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_BWD  & (keepCarStatus) & steeringMot = MAX_RIGHT & next(spec_counter = secondPhase))
		);
	
	/* Performing second step of the parallel parking */
	guarantee
		G((carStatus = PARALLEL & 
			spec_counter = secondPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_BWD & (next(carStatus = PARKED)) & steeringMot = MAX_LEFT)
		);
	
/**********************************************************************************/
/****************************** parking perpendicular *****************************/
/**********************************************************************************/

	/* Set of options available while parking perpendicular */
	guarantee
		G((carStatus = PERPENDICULAR) ->
			((steeringMot = MAX_RIGHT | steeringMot = CENTER | steeringMot = MAX_LEFT) & 
			(engineMot = PARKING_FWD | engineMot = STOP | engineMot = PREPARE_PERPENDICULAR_BWD | engineMot = PERPENDICULAR_BWD))
		);
	
	/* Performing first step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = firstPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PREPARE_PERPENDICULAR_BWD  & (keepCarStatus) & steeringMot = CENTER & next(spec_counter = secondPhase))
		);	
	
	/* Performing second step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = secondPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_FWD  & (keepCarStatus) & steeringMot = MAX_LEFT & next(spec_counter = thirdPhase))
		);
	
	/* Performing third step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = thirdPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PERPENDICULAR_BWD & next(carStatus = PARKED) & steeringMot = MAX_RIGHT)
		);
		
		
	
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module AspectLTLAspect
 
		env {CLEAR, BLOCKED} obstacle ;
		
		env {	TOO_CLOSE,
							TOO_FAR,
							CENTERED,
							PS_TOO_FAR,
							PS_TOO_CLOSE,
							PS_CENTERED
						 } sideSensor ;
						 
		env {	TOO_CLOSE,
								TOO_FAR,
								CENTERED,
								PS_TOO_FAR,
								PS_TOO_CLOSE,
								PS_CENTERED
							 } rearSideSensor ;
							
	
		sys {MAX_RIGHT, MAX_LEFT, CENTER, ALIGN_RIGHT, ALIGN_LEFT} steeringMot ;
		
		sys {FWD, BWD} sensorMot ;
							
		sys {FWD, BWD, STOP, PARKING_BWD, PARKING_FWD, PREPARE_PERPENDICULAR_BWD, PERPENDICULAR_BWD} engineMot ;
		
		sys {	SEEKING_FOR_PS, 
							MEASURE_PARKING,
							PREPARE_FOR_PARALLEL_PARKING,
							ALIGN_BEFORE_PARKING,
							PARALLEL,
							PERPENDICULAR,
							PARKED
						} carStatus ;
						
		sys Int(0..14) spec_counter ;
		
		sys {PARALLEL, PERPENDICULAR} spec_parkingType ;
			
	define
		counterLimit := 14;
		
	define 
		phaseNone := 0;
		
	define 
		firstPhase := 1;
		
	define 
		secondPhase := 2;
		
	define 
		thirdPhase := 3;
			
	define
		weGotSideSensorSeekingValues := (sideSensor = TOO_CLOSE | sideSensor = TOO_FAR | sideSensor = CENTERED);
		
	define
		weGotSideSensorMeasuringValues := (sideSensor = PS_TOO_CLOSE | sideSensor = PS_TOO_FAR | sideSensor = PS_CENTERED);	
	
	define
		Stop := (engineMot = STOP);

	define
		suitableParallelPS := 6;
		
	define
		suitablePerpendicularPS := 4;
		
	define
		preparingParallelSteps := 2;
	
	define
		capablePerpendicular := (spec_counter >= suitablePerpendicularPS);
	
	define
		keepCarStatus := (next(carStatus) = carStatus);
		
	define
		keepCounterValue := (next(spec_counter) = spec_counter);
		
	define
		keepParkingType := (next(spec_parkingType) = spec_parkingType);

	define
		movingFwd := (engineMot = FWD | engineMot = PARKING_FWD);
		
	define
		movingBwd := (engineMot = BWD | 
						engineMot = PARKING_BWD | 
						engineMot = PREPARE_PERPENDICULAR_BWD | 
						engineMot = PERPENDICULAR_BWD
		);
	
	define
		rearTooFar :=   (rearSideSensor = TOO_FAR | rearSideSensor = PS_TOO_FAR);
	
	define
		rearTooClose := (rearSideSensor = TOO_CLOSE | rearSideSensor = PS_TOO_CLOSE);
		
	define
		rearCentered := (rearSideSensor = CENTERED | rearSideSensor = PS_CENTERED);
		
	define
		frontCentered := (sideSensor = CENTERED | sideSensor = PS_CENTERED);
		
	define
		frontTooFar :=   (sideSensor = TOO_FAR | sideSensor = PS_TOO_FAR);
	
	define
		frontTooClose := (sideSensor = TOO_CLOSE | sideSensor = PS_TOO_CLOSE);
		

		
	/* Init state*/
	guarantee
		(carStatus = SEEKING_FOR_PS & sensorMot = FWD & spec_counter = 0);
		
	/* Do not run into obstacles*/
	guarantee
		G ((obstacle = BLOCKED) -> 
			(Stop)
		);
		
	/* In case of an obstacle, keep the car status and the counter value as they were
	 */
	guarantee
		G ((obstacle = BLOCKED
		) -> 
			(keepCarStatus & 
				keepCounterValue
			)
		);

	
	/* Look where you are driving */
	guarantee
		G(movingBwd -> sensorMot = BWD);
		
	guarantee
		G(movingFwd -> sensorMot = FWD);
		
	/* Final goal! */
	guarantee
  GF (carStatus=PARKED);
		
	/* Reached the final goal */
	guarantee
		G((carStatus = PARKED
		) ->
			((Stop) & (keepCarStatus) & steeringMot = CENTER )
		);
		
/**********************************************************************************/
/******************************** wall alignment **********************************/
/**********************************************************************************/
	
	/* set of options available while seeking for parking spot */
	guarantee
		G((carStatus = SEEKING_FOR_PS)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
				(engineMot = FWD | engineMot = STOP) & (spec_counter = 0)
			)
		);
	
	/* Wall alignment instructions */
	guarantee
		G((carStatus = SEEKING_FOR_PS | carStatus = PREPARE_FOR_PARALLEL_PARKING | carStatus = MEASURE_PARKING)-> 
			(
				((sideSensor = TOO_CLOSE	| sideSensor = PS_TOO_CLOSE) 	& steeringMot = ALIGN_LEFT)		| 
				((sideSensor = TOO_FAR		| sideSensor = PS_TOO_FAR)		& steeringMot = ALIGN_RIGHT)	| 
				((sideSensor = CENTERED		| sideSensor = PS_CENTERED) 	& steeringMot = CENTER)
			)
		);
	
	/* If we still didn't find potential parking spot, and there's no obstacle - keep seeking */
	guarantee
		G((carStatus = SEEKING_FOR_PS & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR
		) -> 
			(keepCarStatus)
		);
	
	/* A potential parking spot was found, and there's no obstacle - move to measuring mode */
	guarantee
		G((carStatus = SEEKING_FOR_PS & 
			(weGotSideSensorMeasuringValues) & 
			obstacle = CLEAR
		)
			 -> (
			 	(engineMot = STOP) &
			 	(next(carStatus = MEASURE_PARKING)) & 
			 	(next(spec_counter) = 1)
			)
		);
		
	
	/* V2 - We don't bypass obstacles */
	assumption
  respondsTo(obstacle=BLOCKED,(obstacle=CLEAR));

/**********************************************************************************/
/********************** measure parking spaces specs ******************************/
/**********************************************************************************/
	/* Set of options available while measuring for parking spot */
	guarantee
		G((carStatus = MEASURE_PARKING)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
			(engineMot = FWD | engineMot = STOP) & (spec_counter <= suitableParallelPS))
		);
	
	/* Don't stop if you're measuring parking spot, and there's no obstacle */
	guarantee
		G((carStatus = MEASURE_PARKING & obstacle = CLEAR & weGotSideSensorMeasuringValues)	->
			(engineMot != STOP)
		);	

	/* If we are measuring a parking spot and we didn't measure enough space, keep measuring */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorMeasuringValues) & 
			(spec_counter < suitableParallelPS) &
			obstacle = CLEAR
		) -> 
			(keepCarStatus)
		);
	
	/* Do not count over the limit */
	guarantee
		G((spec_counter <= counterLimit));
		
	/* If the parking spot ended and there is no sufficient space (not parallel and not perpendicular), 
	 * keep seeking for another parking spot
	 */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR & 
			spec_counter < suitableParallelPS & 
			!capablePerpendicular 
		) -> 
			(next(carStatus = SEEKING_FOR_PS)) 
		);
		
	/* If the parking spot ended and we can park perpendicular, move to park perpendicular */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR & 
			spec_counter < suitableParallelPS & 
			capablePerpendicular 
		) -> 
			(next(carStatus = ALIGN_BEFORE_PARKING) &
				(next(spec_parkingType) = PERPENDICULAR) &
				next(spec_counter = 0)
			) 
		);
	
	/* While measuring the parking spot, increase counter if needed */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorMeasuringValues) & 
			obstacle = CLEAR & 
			engineMot = FWD & 
			spec_counter < suitableParallelPS
		) ->
			(next(spec_counter) = (spec_counter + 1))
		);
	
	/* If the parking spot ended and we can park parallel, move to preparing to parllel */
	guarantee
		G ((carStatus = MEASURE_PARKING & 
			spec_counter = suitableParallelPS  & 
			obstacle = CLEAR 
		) -> 
			(
				(next(carStatus) = PREPARE_FOR_PARALLEL_PARKING) &
				(next(spec_counter) = 0)
				));
				
	/* Goal for this stage */		
	guarantee
  respondsTo(carStatus=MEASURE_PARKING,(carStatus=PREPARE_FOR_PARALLEL_PARKING|carStatus=ALIGN_BEFORE_PARKING));
		
	/* How to achieve the goal above */
	assumption 
  respondsTo(engineMot=FWD,(carStatus=PREPARE_FOR_PARALLEL_PARKING|carStatus=ALIGN_BEFORE_PARKING));

/**********************************************************************************/
/*************************** Preparing for parallel parking************************/
/**********************************************************************************/
		
	/* Set of options available while preparing for parking */
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
			(engineMot = FWD | engineMot = STOP))
		);
		
		
	/* Keep performing the needed steps forward in order to prepare for parallel parking */
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING & obstacle = CLEAR
			& spec_counter < preparingParallelSteps
		) ->
			((next(spec_counter) = (spec_counter + 1)) & engineMot = FWD)
		);
	
	/* Keep the car status while performing the preparing, even when you are blocked~ */	
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING & 
			(spec_counter < preparingParallelSteps)
		) -> 
			(keepCarStatus)
		);
	
	/* We completed the preparing steps, now move to actually park paralell */
	guarantee
		G ((carStatus = PREPARE_FOR_PARALLEL_PARKING & 
			spec_counter = preparingParallelSteps & 
			obstacle = CLEAR
		) -> 
			( 
				(Stop) &
				(next(carStatus) = ALIGN_BEFORE_PARKING) &
				(next(spec_parkingType) = PARALLEL) &
				(next(spec_counter) = 0)
				));

    /* Perform the necessary actions in order to reach the suitable number of steps before parking */
	guarantee
  respondsTo(carStatus=PREPARE_FOR_PARALLEL_PARKING,(spec_counter=preparingParallelSteps));
	
	/* How to achieve the goal above */
	assumption 
  respondsTo(((obstacle=CLEAR&carStatus=PREPARE_FOR_PARALLEL_PARKING)->(engineMot=FWD)),(carStatus=ALIGN_BEFORE_PARKING));
		
	
 
 
 

	/* Correcting the angle to the left - these set of specs are dealing with the case where
	SPARC rear side sensor is too far from the wall/PS and the front side sensor is too close */
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			obstacle = CLEAR &
			((rearTooFar & (frontCentered | frontTooClose)) | (rearCentered & frontTooClose)))-> 
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 1))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 1 & obstacle = CLEAR) -> 
			(engineMot = BWD & keepCarStatus & next(spec_counter = 2) & steeringMot = ALIGN_RIGHT)		
		);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 2 & obstacle = CLEAR ) -> 
			(sensorMot = FWD & Stop & keepCarStatus & next(spec_counter = 3))		
		);
		
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 3 & obstacle = CLEAR) -> 
			(engineMot = FWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)		
		);
	/* End of correcting the angle to the left */

	/* Correcting the angle to the right - these set of specs are dealing with the case where
	SPARC front side sensor is too far from the wall/PS and the rear side sensor is too close */
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & obstacle = CLEAR &
			((frontTooFar & (rearCentered | rearTooClose)) | (frontCentered & rearTooClose)))-> 
			(engineMot = FWD & keepCarStatus & next(spec_counter = 4) & (steeringMot = ALIGN_RIGHT))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 4 &
			obstacle = CLEAR)->
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 5))
		);
		
	guarantee
		G ((carStatus = ALIGN_BEFORE_PARKING & spec_counter = 5 & obstacle = CLEAR)->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)
		);
	/* End of correcting the angle to the right */

	/* Correcting the angle to the left2 - these set of specs are dealing with the case where
	SPARC rear side sensor is too far from the wall/PS and the front side sensor is also too far */
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			obstacle = CLEAR &
			(rearTooFar & frontTooFar))-> 
			(engineMot = FWD & steeringMot = ALIGN_RIGHT & keepCarStatus & next(spec_counter = 6))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 6 &
			obstacle = CLEAR) ->
			(engineMot = FWD & steeringMot=ALIGN_LEFT & keepCarStatus & next(spec_counter = 7))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 7 &
			obstacle = CLEAR) ->
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 8))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 8 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 9) & steeringMot = CENTER)
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 9 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)
			);
	/* End of corecting the angle to the left2 */	

	/* Correcting the angle to the right2 - these set of specs are dealing with the case where
	SPARC rear side sensor is too close from the wall/PS and the front side sensor is also too close */
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 &
			obstacle = CLEAR &
			(rearTooClose & frontTooClose))-> 
			(engineMot = FWD & steeringMot = ALIGN_LEFT & keepCarStatus & next(spec_counter = 10))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 10 &
			obstacle = CLEAR) ->
			(engineMot = FWD & steeringMot=ALIGN_RIGHT & keepCarStatus & next(spec_counter = 11))
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 11 &
			obstacle = CLEAR) ->
			(sensorMot = BWD & Stop & keepCarStatus & next(spec_counter = 12))
			);
	
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 12 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 13) & steeringMot = CENTER)
			);
			
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 13 &
			obstacle = CLEAR) ->
			(engineMot = BWD & keepCarStatus & next(spec_counter = 0) & steeringMot = CENTER)
			);
	/* End of correcting the angle to the right2 */
		
	/* Moving to actully park (depending on the type), now that we are aligned */
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			spec_parkingType = PERPENDICULAR & 
			rearCentered & 
			frontCentered &
			obstacle = CLEAR
		) -> 
			((sensorMot = BWD) & Stop & next(spec_counter = firstPhase) & next(carStatus) = PERPENDICULAR)
		);
		
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING & 
			spec_counter = 0 & 
			spec_parkingType = PARALLEL & 
			rearCentered & 
			frontCentered &
			obstacle = CLEAR
		) -> 
			((sensorMot = BWD) & Stop & next(spec_counter = firstPhase) & next(carStatus) = PARALLEL)
		);
	
	/* As long as you're aligning, keep remembering the parking type */
	guarantee
		G((carStatus = ALIGN_BEFORE_PARKING) -> keepParkingType);
	
	/* Goal for this stage */
	guarantee
  respondsTo((carStatus=ALIGN_BEFORE_PARKING),(carStatus=PERPENDICULAR|carStatus=PARALLEL));
		
	assumption
  respondsTo((carStatus=ALIGN_BEFORE_PARKING&(spec_counter=0)),(carStatus=PERPENDICULAR|carStatus=PARALLEL));
		
/**********************************************************************************/
/******************************** parking parallel ********************************/
/**********************************************************************************/

	guarantee
		G((obstacle = BLOCKED & 
			(carStatus = PARALLEL | carStatus = ALIGN_BEFORE_PARKING) & 
			(PREV(sensorMot = BWD) & !movingFwd)
		) -> (sensorMot = BWD));
		
	/* Set of options available while parking parallel */
	guarantee
		G((carStatus = PARALLEL) ->
			((steeringMot = MAX_RIGHT | steeringMot = CENTER | steeringMot = MAX_LEFT) & 
			(engineMot = PARKING_BWD | engineMot = STOP))
		);
	
	/* Performing first step of the parallel parking */
	guarantee
		G((carStatus = PARALLEL & 
			spec_counter = firstPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_BWD  & (keepCarStatus) & steeringMot = MAX_RIGHT & next(spec_counter = secondPhase))
		);
	
	/* Performing second step of the parallel parking */
	guarantee
		G((carStatus = PARALLEL & 
			spec_counter = secondPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_BWD & (next(carStatus = PARKED)) & steeringMot = MAX_LEFT)
		);
	
/**********************************************************************************/
/****************************** parking perpendicular *****************************/
/**********************************************************************************/

	/* Set of options available while parking perpendicular */
	guarantee
		G((carStatus = PERPENDICULAR) ->
			((steeringMot = MAX_RIGHT | steeringMot = CENTER | steeringMot = MAX_LEFT) & 
			(engineMot = PARKING_FWD | engineMot = STOP | engineMot = PREPARE_PERPENDICULAR_BWD | engineMot = PERPENDICULAR_BWD))
		);
	
	/* Performing first step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = firstPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PREPARE_PERPENDICULAR_BWD  & (keepCarStatus) & steeringMot = CENTER & next(spec_counter = secondPhase))
		);	
	
	/* Performing second step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = secondPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_FWD  & (keepCarStatus) & steeringMot = MAX_LEFT & next(spec_counter = thirdPhase))
		);
	
	/* Performing third step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = thirdPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PERPENDICULAR_BWD & next(carStatus = PARKED) & steeringMot = MAX_RIGHT)
		);
		
		
	
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
 
module AspectLTLAspect
 
		env {CLEAR, BLOCKED} obstacle ;
		
		env {	TOO_CLOSE,
							TOO_FAR,
							CENTERED,
							PS_TOO_FAR,
							PS_TOO_CLOSE,
							PS_CENTERED
						 } sideSensor ;
						 
		env {	TOO_CLOSE,
								TOO_FAR,
								CENTERED,
								PS_TOO_FAR,
								PS_TOO_CLOSE,
								PS_CENTERED
							 } rearSideSensor ;
							
	
		sys {MAX_RIGHT, MAX_LEFT, CENTER, ALIGN_RIGHT, ALIGN_LEFT} steeringMot ;
		
		sys {FWD, BWD} sensorMot ;
							
		sys {FWD, BWD, STOP, PARKING_BWD, PARKING_FWD, PREPARE_PERPENDICULAR_BWD,PERPENDICULAR_BWD, BYPASS_FWD} engineMot ;
		
		sys {	SEEKING_FOR_PS,
							MEASURE_PARKING,
							BYPASSING,
							PREPARE_FOR_PARALLEL_PARKING,
							PARALLEL,
							PERPENDICULAR,
							PARKED
						} carStatus ;
		sys Int(0..14) spec_counter ;
		
		sys Int(0..6) spec_obstacleCounter ;

	define
		counterLimit := 14;
		
	define 
		phaseNone := 0;
		
	define 
		firstPhase := 1;
		
	define 
		secondPhase := 2;
		
	define 
		thirdPhase := 3;
			
	define
		weGotSideSensorSeekingValues := (sideSensor = TOO_CLOSE | sideSensor = TOO_FAR | sideSensor = CENTERED);
	
	define
		weGotRearSideSensorSeekingValues := (rearSideSensor = TOO_CLOSE | rearSideSensor = TOO_FAR | rearSideSensor = CENTERED);
		
	define
		weGotSideSensorMeasuringValues := (sideSensor = PS_TOO_CLOSE | sideSensor = PS_TOO_FAR | sideSensor = PS_CENTERED);	
	
	define
		weGotRearSideSensorMeasuringValues := (rearSideSensor = PS_TOO_CLOSE | rearSideSensor = PS_TOO_FAR | rearSideSensor = PS_CENTERED);	
		
	define
		Stop := (engineMot = STOP);

	define
		suitableParallelPS := 6;
		
	define
		suitablePerpendicularPS := 4;
		
	define
		preparingParallelSteps := 2;
	
	define
		capablePerpendicular := (spec_counter >= suitablePerpendicularPS);
	
	define
		keepCarStatus := (next(carStatus) = carStatus);
		
	define
		keepCounterValue := (next(spec_counter) = spec_counter);

	define
		movingFwd := (engineMot = FWD | engineMot = PARKING_FWD | engineMot = BYPASS_FWD);
		
	define
		movingBwd := (engineMot = BWD | 
						engineMot = PARKING_BWD | 
						engineMot = PREPARE_PERPENDICULAR_BWD | 
						engineMot = PERPENDICULAR_BWD
		);
	
	define
		rearTooFar :=   (rearSideSensor = TOO_FAR | rearSideSensor = PS_TOO_FAR);
	
	define
		rearTooClose := (rearSideSensor = TOO_CLOSE | rearSideSensor = PS_TOO_CLOSE);
		
	define
		rearCentered := (rearSideSensor = CENTERED | rearSideSensor = PS_CENTERED);
		
	define
		frontCentered := (sideSensor = CENTERED | sideSensor = PS_CENTERED);
		
	define
		frontTooFar :=   (sideSensor = TOO_FAR | sideSensor = PS_TOO_FAR);
	
	define
		frontTooClose := (sideSensor = TOO_CLOSE | sideSensor = PS_TOO_CLOSE);
		
	define
		movingNextToObstacle := (carStatus = BYPASSING & spec_counter = 7);
		
	/* Init state*/
	guarantee
		(carStatus = SEEKING_FOR_PS & sensorMot = FWD & spec_counter = 0);
		
	/* Do not run into obstacles*/
	guarantee
		G ((obstacle = BLOCKED) -> 
			(Stop)
		);
		
	/* In case of an obstacle, keep the car status and the counter value as they were
	 * (except for some cases, that we need to change the car status or the counter)
	 */
	guarantee
		G ((obstacle = BLOCKED & !(carStatus = SEEKING_FOR_PS | carStatus = MEASURE_PARKING | 
			(carStatus = BYPASSING & spec_counter = 10) | (carStatus=PERPENDICULAR & spec_counter = thirdPhase)
		)) 
			-> 	(keepCarStatus & keepCounterValue
			)
		);
	
	/* Initiating the obstacleCounter in the first time we are blocked */
	guarantee
		G((carStatus != BYPASSING & 
			PREV(obstacle = CLEAR) & 
			obstacle = BLOCKED
		) -> (spec_obstacleCounter = 0));
	
	/* Don't turn the direction of the sensor if you don't need to */
	guarantee
		G((obstacle = BLOCKED & 
			carStatus != BYPASSING & 
			(PREV(sensorMot = BWD) & !movingFwd)
		) -> (sensorMot = BWD));
	
	/* Look where you are driving */
	guarantee
		G(movingBwd -> sensorMot = BWD);

	guarantee
		G(movingFwd -> sensorMot = FWD);
		
	/* Final goal! */
	guarantee
  GF (carStatus=PARKED);
		
	/* Reached the final goal */
	guarantee
		G((carStatus = PARKED
		) ->
			((Stop) & (keepCarStatus) & steeringMot = CENTER )
		);
		
/**********************************************************************************/
/******************************** wall alignment **********************************/
/**********************************************************************************/
	
	/* set of options available while seeking for parking spot */
	guarantee
		G((carStatus = SEEKING_FOR_PS)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
				(engineMot = FWD | engineMot = STOP) & (spec_counter = 0)
			)
		);
	
	/* Wall alignment instructions */
	guarantee
		G((carStatus = SEEKING_FOR_PS | carStatus = PREPARE_FOR_PARALLEL_PARKING | carStatus = MEASURE_PARKING | movingNextToObstacle)-> 
			(
				((sideSensor = TOO_CLOSE	| sideSensor = PS_TOO_CLOSE) 	& steeringMot = ALIGN_LEFT)		| 
				((sideSensor = TOO_FAR		| sideSensor = PS_TOO_FAR)		& steeringMot = ALIGN_RIGHT)	| 
				((sideSensor = CENTERED		| sideSensor = PS_CENTERED) 	& steeringMot = CENTER)
			)
		);
	
	/* If we still didn't find potential parking spot, and there's no obstacle - keep seeking */
	guarantee
		G((carStatus = SEEKING_FOR_PS & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR
		) -> 
			(keepCarStatus)
		);
	
	/* A potential parking spot was found, and there's no obstacle - move to measuring mode */
	guarantee
		G((carStatus = SEEKING_FOR_PS & 
			(weGotSideSensorMeasuringValues) & 
			obstacle = CLEAR
		)
			 -> (
			 	(engineMot = STOP) &
			 	(next(carStatus = MEASURE_PARKING)) & 
			 	(next(spec_counter) = 1)
			)
		);
	
	/* We bypass obstacles only when we're seeking for parking spot or when measuring one. 
	 * In all other cases we assume the obstacle will go away (temporary obstacle)
	 */
	assumption
  respondsTo((obstacle=BLOCKED&(carStatus!=MEASURE_PARKING&carStatus!=SEEKING_FOR_PS)),(obstacle=CLEAR));

/**********************************************************************************/
/********************** measure parking spaces specs ******************************/
/**********************************************************************************/
	/* Set of options available while measuring for parking spot */
	guarantee
		G((carStatus = MEASURE_PARKING)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
			(engineMot = FWD | engineMot = STOP) & (spec_counter <= suitableParallelPS))
		);
	
	/* Don't stop if you're measuring parking spot, and there's no obstacle */
	guarantee
		G((carStatus = MEASURE_PARKING & obstacle = CLEAR & weGotSideSensorMeasuringValues)	->
			(engineMot != STOP)
		);	

	/* If we are measuring a parking spot and we didn't measure enough space, keep measuring */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorMeasuringValues) & 
			(spec_counter < suitableParallelPS) &
			obstacle = CLEAR
		) -> 
			(keepCarStatus)
		);
	
	/* Do not count over the limit */
	guarantee
		G((spec_counter <= counterLimit));
		
	/* If the parking spot ended and there is no sufficient space (not parallel and not perpendicular), 
	 * keep seeking for another parking spot
	 */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR & 
			spec_counter < suitableParallelPS & 
			!capablePerpendicular 
		) -> 
			(next(carStatus = SEEKING_FOR_PS)) 
		);
		
	/* If the parking spot ended and we can park perpendicular, move to park perpendicular */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorSeekingValues) & 
			obstacle = CLEAR & 
			spec_counter < suitableParallelPS & 
			capablePerpendicular 
		) -> 
				(next(carStatus = PERPENDICULAR) &
				next(spec_counter = firstPhase) &
				sensorMot = BWD & 
				Stop
			) 
		);
	
	/* While measuring the parking spot, increase counter if needed */
	guarantee
		G((carStatus = MEASURE_PARKING & 
			(weGotSideSensorMeasuringValues) & 
			obstacle = CLEAR & 
			engineMot = FWD & 
			spec_counter < suitableParallelPS
		) ->
			(next(spec_counter) = (spec_counter + 1))
		);
	
	/* If the parking spot ended and we can park parallel, move to preparing to parllel */
	guarantee
		G ((carStatus = MEASURE_PARKING & 
			spec_counter = suitableParallelPS  & 
			obstacle = CLEAR 
		) -> 
			(
				(next(carStatus) = PREPARE_FOR_PARALLEL_PARKING) &
				(next(spec_counter) = 0)
				));
				
	/* Goal for this stage */		
	guarantee
  respondsTo(carStatus=MEASURE_PARKING,(carStatus=PREPARE_FOR_PARALLEL_PARKING|carStatus=PERPENDICULAR));
		
	/* How to achieve the goal above */
	assumption 
  respondsTo((obstacle=CLEAR&engineMot=FWD),(carStatus=PREPARE_FOR_PARALLEL_PARKING|carStatus=PERPENDICULAR));

/**********************************************************************************/
/*************************** Preparing for parallel parking************************/
/**********************************************************************************/
		
	/* Set of options available while preparing for parking */
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING)-> 
			((steeringMot = ALIGN_RIGHT | steeringMot = CENTER | steeringMot = ALIGN_LEFT) & 
			(engineMot = FWD | engineMot = STOP))
		);
		
 
 
 
 
	
	/* Keep performing the needed steps forward in order to prepare for parallel parking */
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING & obstacle = CLEAR
			& spec_counter < preparingParallelSteps
		) ->
			((next(spec_counter) = (spec_counter + 1)) & engineMot = FWD)
		);
	
	/* Keep the car status while performing the preparing, even when you are blocked~ */	
	guarantee
		G((carStatus = PREPARE_FOR_PARALLEL_PARKING & 
			(spec_counter < preparingParallelSteps)
		) -> 
			(keepCarStatus)
		);
	
	/* We completed the preparing steps, now move to actually park paralell */
	guarantee
		G ((carStatus = PREPARE_FOR_PARALLEL_PARKING & 
			spec_counter = preparingParallelSteps & 
			obstacle = CLEAR
		) -> 
			( 
				(Stop) &
				(next(carStatus) = PARALLEL) &
				next(spec_counter = firstPhase) &
				(sensorMot = BWD)				
				));

    /* Perform the necessary actions in order to reach the suitable number of steps before parking */
	guarantee
  respondsTo(carStatus=PREPARE_FOR_PARALLEL_PARKING,(spec_counter=preparingParallelSteps));
	
	/* How to achieve the goal above */
	assumption 
  respondsTo(((obstacle=CLEAR&carStatus=PREPARE_FOR_PARALLEL_PARKING)->(engineMot=FWD)),(carStatus=PARALLEL));
		
/**********************************************************************************/
/******************************** parking parallel ********************************/
/**********************************************************************************/

	/* Set of options available while parking parallel */
	guarantee
		G((carStatus = PARALLEL) ->
			((steeringMot = MAX_RIGHT | steeringMot = CENTER | steeringMot = MAX_LEFT) & 
			(engineMot = PARKING_BWD | engineMot = STOP))
		);
	
	/* Performing first step of the parallel parking */
	guarantee
		G((carStatus = PARALLEL & 
			spec_counter = firstPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_BWD  & (keepCarStatus) & steeringMot = MAX_RIGHT & next(spec_counter = secondPhase))
		);
	
	/* Performing second step of the parallel parking */
	guarantee
		G((carStatus = PARALLEL & 
			spec_counter = secondPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_BWD & (next(carStatus = PARKED)) & steeringMot = MAX_LEFT)
		);
	
/**********************************************************************************/
/****************************** parking perpendicular *****************************/
/**********************************************************************************/

	/* Set of options available while parking perpendicular */
	guarantee
		G((carStatus = PERPENDICULAR) ->
			((steeringMot = MAX_RIGHT | steeringMot = CENTER | steeringMot = MAX_LEFT) & 
			(engineMot = PARKING_FWD | engineMot = STOP | engineMot = PREPARE_PERPENDICULAR_BWD | engineMot = PERPENDICULAR_BWD))
		);
	
	/* Performing first step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = firstPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PREPARE_PERPENDICULAR_BWD  & (keepCarStatus) & steeringMot = CENTER & next(spec_counter = secondPhase))
		);	
	
	/* Performing second step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = secondPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PARKING_FWD  & (keepCarStatus) & steeringMot = MAX_LEFT & next(spec_counter = thirdPhase))
		);
	
	/* Performing third step of the perpendicular parking */
	guarantee
		G((carStatus = PERPENDICULAR & 
			spec_counter = thirdPhase & 
			obstacle = CLEAR
		) ->
			(engineMot = PERPENDICULAR_BWD & next(carStatus = PARKED) & steeringMot = MAX_RIGHT)
		);

/**********************************************************************************/
/************************************ bypassing ***********************************/
/**********************************************************************************/

	/* Don't turn the direction of the sensor if you don't need to */
	guarantee
		G((obstacle = BLOCKED & 
			carStatus = BYPASSING & 
			(spec_counter = 1 | spec_counter = 2 | spec_counter = 11) &
			(PREV(sensorMot = BWD) & !movingFwd)
		) -> (sensorMot = BWD));

	/* In order to avoid false detection of obstacles, and to avoid bypassing temporary obstacles, 
	 * we will wait 3 cycles before we start to bypass */
	guarantee
		G(((carStatus = SEEKING_FOR_PS | carStatus = MEASURE_PARKING) & 
			spec_obstacleCounter < 2 & obstacle = BLOCKED
		) ->
			(Stop & (next(spec_obstacleCounter) = spec_obstacleCounter + 1) & keepCarStatus & keepCounterValue)
		);
		
	/* This is probably a real obstacle, need to bypass*/
	guarantee
		G(((carStatus = SEEKING_FOR_PS | carStatus = MEASURE_PARKING) & 
			spec_obstacleCounter = 2 & obstacle = BLOCKED & PREV(obstacle = BLOCKED)
		) ->
			(Stop & 
				next(carStatus = BYPASSING) & 
				next(spec_counter = 0)
			)
		);

	/* As long as we are in the bypassing process, keep the car status */				
	guarantee
	G((carStatus = BYPASSING & spec_counter < 10) -> (keepCarStatus));
	
	/* Preparing to bypass - two steps backwards */
	guarantee
		G((carStatus = BYPASSING & spec_counter = 0 )->
			(Stop & sensorMot = BWD)
		);
	
	guarantee
		G((carStatus = BYPASSING & spec_counter = 0 & obstacle = CLEAR )->
			(next(spec_counter = 1)  )
		);
		
	guarantee
		G((carStatus = BYPASSING & spec_counter = 1 & obstacle = CLEAR )->
			(engineMot = BWD & steeringMot = CENTER & next(spec_counter = 2) )
		);
		
	guarantee
		G((carStatus = BYPASSING & spec_counter = 2 & obstacle = CLEAR )->
			(engineMot = BWD & steeringMot = CENTER & next(spec_counter = 3) )
		);
		
	guarantee
		G((carStatus = BYPASSING & spec_counter = 3 )->
			(Stop & sensorMot = FWD )
		);
		
	/* Starting to bypass */
	guarantee
		G((carStatus = BYPASSING & spec_counter = 3 & obstacle = CLEAR )->
			(next(spec_counter = 4) )
		);
		
	guarantee
		G((carStatus = BYPASSING & spec_counter = 4 & obstacle = CLEAR )->
			(engineMot = BYPASS_FWD & steeringMot = MAX_LEFT & next(spec_counter = 5) )
		);
		
	/* Keep moving forward and center if we are too close */
	guarantee
		G((carStatus = BYPASSING & spec_counter = 5 & obstacle = CLEAR & sideSensor = TOO_CLOSE)->
			(engineMot = FWD & steeringMot = CENTER & next(spec_counter = 6))
		);
		
	guarantee
		G((carStatus = BYPASSING & spec_counter = 5 & obstacle = CLEAR & sideSensor != TOO_CLOSE)->
			(Stop & steeringMot = CENTER & next(spec_counter = 6))
		);
		
	/* Completing first phase of bypassing - moving right and forward */
	guarantee
		G((carStatus = BYPASSING & spec_counter = 6 & obstacle = CLEAR )->
			(engineMot = PARKING_FWD & 
				steeringMot = MAX_RIGHT & 
				next(spec_counter = 7) & 
				next(spec_obstacleCounter = 0 )
		));
		
	/* Passing next to the obstacle - performing wall alignment  */
	guarantee
		G((movingNextToObstacle & 
			(weGotSideSensorSeekingValues | weGotRearSideSensorSeekingValues) &
			obstacle = CLEAR & spec_obstacleCounter < 3
		)->
			(keepCounterValue & next(spec_obstacleCounter = 0 ))
		);
	
	/* We already passed the obstacle, need to return back */
	guarantee
		G((movingNextToObstacle & 
			weGotSideSensorMeasuringValues & 
			weGotRearSideSensorMeasuringValues & 
			obstacle = CLEAR & spec_obstacleCounter < 6
		)->
			(keepCounterValue & (next(spec_obstacleCounter) = 1 + spec_obstacleCounter))
		);
	
	guarantee
		G((movingNextToObstacle & obstacle = CLEAR & spec_obstacleCounter = 6)->
			(Stop & sensorMot = BWD & next(spec_counter = 8)));
			
	guarantee
		G((carStatus = BYPASSING & spec_counter = 8 & obstacle = CLEAR )->
			(engineMot = PARKING_BWD & steeringMot = MAX_RIGHT & next(spec_counter = 9) )
		);
	
	guarantee
		G((carStatus = BYPASSING & spec_counter = 9 & obstacle = CLEAR )->
			(engineMot = PARKING_BWD & steeringMot = MAX_LEFT & next(spec_counter = 10))
		);
		
	/* Compeleted the bypass - moving back to seeking mode */
	guarantee
		G((carStatus = BYPASSING & spec_counter = 10)->
			(sensorMot = FWD & Stop & next(carStatus = SEEKING_FOR_PS))
		);
	
	/* While bypassing, stay in this status or move to seeking after done */
	guarantee
		G((carStatus = BYPASSING) -> (next(carStatus = SEEKING_FOR_PS) | next(carStatus = BYPASSING)));
		
	/* Goal for this stage, complete the bypass */
	guarantee
  respondsTo((carStatus=BYPASSING),(carStatus=SEEKING_FOR_PS));
		
	/* How to achieve the goal above */
	assumption
  respondsTo(((carStatus=BYPASSING)&engineMot=FWD),(carStatus=SEEKING_FOR_PS));
	
pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
import "../patterns/DwyerPatterns.spectra"

module AirportShuttleWithTechnicalJob

 
env Int(0..3) station;
env boolean atStation;
env Button emgButton;
env boolean readyToEmgBeep;
env boolean pressedStationZero;
env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean longTimeWithoutReqs;
env boolean doorAck;
env boolean mPressedStationZero;
env boolean mPressedStationOne;
env boolean mPressedStationTwo;
env boolean mPressedStationThree;
env boolean technicianAck; 

 
sys MotorCmd motors;
sys boolean emgBeepProcessReq;
sys boolean countTimeSinceReqs;
sys boolean doorReq;
sys boolean startTechnicalJob;

 
type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};

 
predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

 
define 
  
   
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
   
  atBaseStation := atGivenStation(0);
  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  willEnterStation := !atStation & next(atStation);
  
   
  noPressedStations := !pressedStationZero & !pressedStationOne & !pressedStationTwo & !pressedStationThree;
  noMpressedStations := !mPressedStationZero & !mPressedStationOne & !mPressedStationTwo & !mPressedStationThree;
  
   
  noTasks := !taskAtStationZero & !taskAtStationOne & !taskAtStationTwo & !taskAtStationThree;
  atStationWithTask := atStation & ((station = 0 & taskAtStationZero) |
                                    (station = 1 & taskAtStationOne) |
                                    (station = 2 & taskAtStationTwo) |
                                    (station = 3 & taskAtStationThree));                    
  noTasksForward := ((atGivenStation(0) & (!taskAtStationOne & !taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(1) &  (!taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(2) &  (!taskAtStationThree)));
  noTasksBackward := ((atGivenStation(3) & (!taskAtStationTwo & !taskAtStationOne & !taskAtStationZero)) | 
                     (atGivenStation(2) &  (!taskAtStationOne & !taskAtStationZero)) |
                     (atGivenStation(1) &  (!taskAtStationZero)));


 
 
 

/**
 * monitor taskAtStationZero is true when there is a task at station zero
 */
monitor boolean taskAtStationZero {
   
  !taskAtStationZero;
   
  G (pressedStationZero & !next(atEmgState) & !next(maintenanceAtStationZero)) -> (next(taskAtStationZero) = true);
   
  G (atGivenStation(0) & taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G ((!pressedStationZero | next(maintenanceAtStationZero)) &
    (!atGivenStation(0) | !taskAtStationZero | pressedStationZero) &
    (next(!atEmgState))) -> (next(taskAtStationZero) = taskAtStationZero); 
}

/**
 * monitor taskAtStationOne is true when there is a task at station one
 */
monitor boolean taskAtStationOne {
   
  !taskAtStationOne;
   
  G (pressedStationOne & next(!atEmgState) & next(!maintenanceAtStationOne)) -> (next(taskAtStationOne) = true);
   
  G (atGivenStation(1) & taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = false);
    
  G (next(atEmgState)) -> (next(taskAtStationOne) = false);
   
  G ((!pressedStationOne | next(maintenanceAtStationOne)) &
    (!atGivenStation(1) | !taskAtStationOne | pressedStationOne) &
    (next(!atEmgState))) -> (next(taskAtStationOne) = taskAtStationOne); 
} 

/**
 * monitor taskAtStationTwo is true when there is a task at station two
 */
monitor boolean taskAtStationTwo {
   
  !taskAtStationTwo;
   
  G (pressedStationTwo & !next(atEmgState) & !next(maintenanceAtStationTwo)) -> (next(taskAtStationTwo) = true);
   
  G (atGivenStation(2) & taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G ((!pressedStationTwo | next(maintenanceAtStationTwo)) &
    (!atGivenStation(2) | !taskAtStationTwo | pressedStationTwo) &
    (next(!atEmgState))) -> (next(taskAtStationTwo) = taskAtStationTwo); 
}

/**
 * monitor taskAtStationThree is true when there is a task at station three
 */
monitor boolean taskAtStationThree {
   
  !taskAtStationThree;
   
  G (pressedStationThree & !next(atEmgState) & !next(maintenanceAtStationThree)) -> (next(taskAtStationThree) = true);
   
  G (atGivenStation(3) & taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G ((!pressedStationThree | next(maintenanceAtStationThree)) &
    (!atGivenStation(3) | !taskAtStationThree | pressedStationThree) &
    (next(!atEmgState))) -> (next(taskAtStationThree) = taskAtStationThree); 
}  

/**
 * monitor goToBaseStation is true when there is a need to go to the base station
 */
monitor boolean goToBaseStation {
   
  !goToBaseStation;
   
  G (noTasks & longTimeWithoutReqs & !atEmgState & !atBaseStation) -> next(goToBaseStation);
   
  G atBaseStation -> next(!goToBaseStation);
  G (atStation & !noTasks) -> next(!goToBaseStation);
  G atEmgState -> next(!goToBaseStation);
   
  G (!atBaseStation & !atEmgState & (!atStation|noTasks) & (!longTimeWithoutReqs|!noTasks)) -> next(goToBaseStation) = goToBaseStation;
}

/**
 * monitor maintenanceAtStationZero becomes true when mPressedStationZero is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationZero{
   
  !maintenanceAtStationZero;
   
  G mPressedStationZero <-> next(maintenanceAtStationZero) = !maintenanceAtStationZero;
}

/**
 * monitor maintenanceAtStationOne becomes true when mPressedStationOne is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationOne{
   
  !maintenanceAtStationOne;
   
  G mPressedStationOne <-> next(maintenanceAtStationOne) = !maintenanceAtStationOne;
}

/**
 * monitor maintenanceAtStationTwo becomes true when mPressedStationTwo is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationTwo{
   
  !maintenanceAtStationTwo;
   
  G mPressedStationTwo<-> next(maintenanceAtStationTwo) = !maintenanceAtStationTwo;
}

/**
 * monitor maintenanceAtStationThree becomes true when mPressedStationThree is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationThree{
   
  !maintenanceAtStationThree;
   
  G mPressedStationThree <-> next(maintenanceAtStationThree) = !maintenanceAtStationThree;
}

/**
 * monitor atEmgState becomes true when emgButton is pressed
 * and stays true until atStation and emgButton is pressed again
 */
monitor boolean atEmgState {
   
  !atEmgState;
   
  G (!atStation & atEmgState) -> next(atEmgState);
   
  G (atStation | !atEmgState) -> (emgButton = PRESSED <-> (next(atEmgState)=!atEmgState));
} 

/**
 * monitor waitingForDoor becomes true when doorReq is true
 * and doorAck hasn't been received yet
 */
monitor boolean waitingForDoor{
   
  !waitingForDoor;
   
  G (doorReq & !doorAck) -> next(waitingForDoor);
   
  G doorAck-> next(!waitingForDoor);
   
  G (!doorReq & !doorAck) -> (next(waitingForDoor)= waitingForDoor);
}

/**
 * monitor openDoorAtEmgState becomes when entering emergency state
 * and it stays true until door request is sent
 */
monitor boolean openDoorAtEmgState {
   
  ! openDoorAtEmgState;
   
  G next(atEmgState) & !atEmgState -> next(openDoorAtEmgState);
   
  G atEmgState & doorReq -> next(!openDoorAtEmgState);
   
  G (!atEmgState | !doorReq) & (next(!atEmgState) | atEmgState)-> next(openDoorAtEmgState) = openDoorAtEmgState;
}

/**
 * monitor waitingForEmgBeeper is true when emgBeepProcessReq is true 
 * and readyToEmgBeep ack hasn't been received yet
 */
monitor boolean waitingForEmgBeeper {
   
  !waitingForEmgBeeper;
   
  G (emgBeepProcessReq -> next(waitingForEmgBeeper));
   
  G (readyToEmgBeep -> (next(!waitingForEmgBeeper) | emgBeepProcessReq));
   
  G (!emgBeepProcessReq & !readyToEmgBeep -> waitingForEmgBeeper = next(waitingForEmgBeeper));
} 


/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 5
 */ 
monitor Int(0..5) doorOperationsCounter {
  doorOperationsCounter = 0;
  G doorAck & (doorOperationsCounter != 5) -> (next(doorOperationsCounter) = (doorOperationsCounter + 1));  
  G doorOperationsCounter = 5 -> next(doorOperationsCounter) = 0;
  G (!doorAck & doorOperationsCounter != 5) -> (next(doorOperationsCounter) = doorOperationsCounter);
}

/**
 * monitor techGuyInAction becomes true when the door has been opened for 5 times, 
 * and technicianAck hasn't been received yet
 */
monitor boolean techGuyInAction {
  ! techGuyInAction;
  G ( (doorOperationsCounter = 5 & !technicianAck) -> next(techGuyInAction));
  G ( technicianAck -> next(!techGuyInAction));
  G ( (!technicianAck & doorOperationsCounter != 5) -> techGuyInAction = next(techGuyInAction));
}
                                        
 
 
 

 
assumption initialStateEnv:
  atGivenStation(0) 
      & noPressedStations 
      & emgButton = RELEASED 
      & !readyToEmgBeep 
      & !longTimeWithoutReqs 
      & !doorAck
      & noMpressedStations
      & !technicianAck;

 
assumption forwardingCauseStationToIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationToDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption stationChangesOnlyWhenEnteringStation:
  G !willEnterStation -> next(station) = station;

 
assumption stationIncreasesByForwardingAndEntringStation:
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption stationDecreasesByBackwardingAndEntringStation:
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption stationCanOnlyStayTheSameOrChangeByOne:
  G (next(station) = station) | (next(station) = station+1) | (next(station) = station-1); 

 
assumption stationCannotChangewhileStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationIsNotPressedWhileAtCurrentStation:
  G (next(atGivenStation(0)) -> next(!pressedStationZero)) &
    (next(atGivenStation(1)) -> next(!pressedStationOne)) &
    (next(atGivenStation(2)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(3)) -> next(!pressedStationThree));

 
assumption doorReturnsAnswerEventually:
pRespondsToS (waitingForDoor, doorAck);

 
assumption noStrangedoorAcks:
  G (next(doorAck) -> (waitingForDoor & !doorAck));

 
assumption beeperReturnsAnswerEventually:
pRespondsToS (waitingForEmgBeeper, readyToEmgBeep);

 
assumption noStrangeReadyToBeepAcks:
  G (next(readyToEmgBeep) -> (waitingForEmgBeeper & !readyToEmgBeep));

 
assumption notAlwaysAtEmgState:
  GF !atEmgState; 

 
assumption doneTechnicianActionEventually:
  pRespondsToS(techGuyInAction, technicianAck);
 
 
assumption noStrangeTechnicianAcks:
  G (next(technicianAck) -> (techGuyInAction & !technicianAck));


 
 
 
    
 
guarantee initialStateSys:
  stopping & !doorReq & !startTechnicalJob;

 
guarantee stopWhenPassingAstationThatWasCalled:
  G atStationWithTask -> stopping;

 
guarantee openDoorOnlyWhenNeeded:
G (!waitingForDoor & ((atStation & atEmgState & openDoorAtEmgState)| atStationWithTask)) <-> doorReq; 

 
guarantee stopWhileWaitingForDoor:
  G waitingForDoor -> stopping;

 
guarantee stopWhenAtEmgStateAndAtStation:
  G atStation & atEmgState -> stopping;

 
guarantee beepEmgIffEnteringStationOrReadyToEmgBeepAtStation:
G ((atEmgState & PREV(willEnterStation))|(atStation & readyToEmgBeep & atEmgState)) <-> emgBeepProcessReq;

 
guarantee stopWhenAtBaseStationAndNoTasks:
  G noTasks & atBaseStation -> stopping;
  
 
guarantee countTimeSinceReqsIffNoPressedStationsAndNotAtEmgState:
  G noPressedStations & !atEmgState <-> countTimeSinceReqs;

 
guarantee stopWhenTechGuyInAction:
G (techGuyInAction & atStation -> stopping);

 
guarantee
G !techGuyInAction & next(techGuyInAction) <-> next(startTechnicalJob);


 
 
 
  
 
guarantee dontGoBackwardWhenAtStationZero:
  G atGivenStation(0) -> !backwarding;

 
guarantee dontGoForwardWhenAtStationThree:
  G atGivenStation(3) -> !forwarding;

 
guarantee dontGoForwardWhenNoTasksForward:
  G noTasksForward -> !forwarding;  

 
guarantee dontGoBackwardWhenNoTasksBackward:
  G noTasksBackward & !goToBaseStation -> !backwarding; 

 
guarantee stopWhenAtStationAndNoTasksAndNotGoToBaseStation:
  G noTasks & atStation & !goToBaseStation -> stopping;

 
guarantee stopOnlyAtStation:
  G !atStation -> !stopping;

 
guarantee dontChangeDirectionWithoutStopping:
  G (!stopping -> (next(motors) = motors | next(stopping)));

 
guarantee preventUnnecessaryStops:
  G (!goToBaseStation & atStation & !atStationWithTask & !noTasks & !waitingForDoor & !techGuyInAction) -> !stopping; 

 
 
 
 

 
guarantee taskAtStationZeroIsSatisfiedEventually:
  GF !taskAtStationZero;

 
guarantee taskAtStationOneIsSatisfiedEventually:
  GF !taskAtStationOne;

 
guarantee taskAtStationTwoIsSatisfiedEventually:
  GF !taskAtStationTwo;

 
guarantee taskAtStationThreeIsSatisfiedEventually:
  GF !taskAtStationThree;

 
guarantee NotAlwaysGoToBaseStation: 
  GF !goToBaseStation;

  
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Station station;
env Button stopButton;
env DoorStatus doorStatus;
env boolean technicianAck;

sys MotorCmd mLeft;
sys MotorCmd mRight;
sys DoorOp doorReq;
sys boolean startTechnicalJob;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Station = {ONE, TWO, THREE, FOUR, NONE};
type DoorOp = {OPEN, CLOSE, NIL};
type DoorStatus = {OPENED, CLOSED, IN_PROCESS};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  atStation := station != NONE;
  enteringStation := (station != NONE) & (PREV (station = NONE));
  openDoorReq := doorReq = OPEN;
  closeDoorReq := doorReq = CLOSE;
  doorCounterIncreased := (PREV (next(doorOperationsCounter) - doorOperationsCounter = 1) & doorOperationsCounter=1) 
                           | (PREV (doorOperationsCounter=1) & doorOperationsCounter=2)
                           | (PREV (doorOperationsCounter=2) & doorOperationsCounter=3)
                           | (PREV (doorOperationsCounter=3) & doorOperationsCounter=4)
                           | (PREV (doorOperationsCounter=4) & doorOperationsCounter=5)
                           | (PREV (doorOperationsCounter=5) & doorOperationsCounter=6)
                           | (PREV (doorOperationsCounter=6) & doorOperationsCounter=7)
                           | (PREV (doorOperationsCounter=7) & doorOperationsCounter=8)
                           | (PREV (doorOperationsCounter=8) & doorOperationsCounter=9)
                           | (PREV (doorOperationsCounter=9) & doorOperationsCounter=10);

 
 
 
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding, !atStation | stopping);
  
 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> station = next(station));

 
assumption notAlwaysStopAtNearestStation:
  GF !stopAtNearestStation;

 
assumption initiallyDoorIsClosed:
  doorStatus=CLOSED;

 
assumption doneDoorProcessEventually:
  GF doorStatus!=IN_PROCESS;
    
 
assumption noStrangeDoorStatus1:
  G (next(doorStatus=OPENED) -> (doorStatus=IN_PROCESS));
  
 
assumption noStrangeDoorStatus2:
  G (next(doorStatus=CLOSED) -> (doorStatus!=OPENED));

 

 
assumption
  G (atStation -> stopButton=RELEASED);

 
assumption initiallyNoTechnicianAck:
  !technicianAck;
  
assumption doneTechnicianActionEventually:
  pRespondsToS(techGuyInAction, technicianAck);
 
 
assumption noStrangeTechnicianAcks:
  G (next(technicianAck) -> (techGuyInAction & !technicianAck));


 
 
 

 
guarantee initialState:
stopping & doorReq=NIL;

 
guarantee stopAtNearestStationWhenAsked:
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation becomes true when stopButton is pressed
 * TBD
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ( (stopButton = PRESSED & !doorCounterIncreased) -> next(stopAtNearestStation));
   
  G ( (doorCounterIncreased) -> next(!stopAtNearestStation));
   
  G ( ((stopButton = RELEASED) & !doorCounterIncreased) -> stopAtNearestStation = next(stopAtNearestStation));
} 


 
guarantee dontChangeDoorRequestWhenDoorIsInProcess:
  G (doorStatus=IN_PROCESS -> doorReq=NIL);


 
 
guarantee
G (atStation & stopAtNearestStation) & (doorStatus = CLOSED) & (!doorCounterIncreased) <-> openDoorReq;


 
guarantee closeDoorAfterOpen:
G ( (doorStatus = OPENED) <-> closeDoorReq);


/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 10
 */ 
monitor Int(0..10) doorOperationsCounter {
  doorOperationsCounter = 0;
  G ( (PREV (doorStatus = IN_PROCESS) & doorStatus=CLOSED & !(doorOperationsCounter = 10)) -> (next (doorOperationsCounter) = doorOperationsCounter + 1));
  G ( (doorOperationsCounter = 10) -> next (doorOperationsCounter) = 0);
  G ( ((doorStatus!=CLOSED) & (doorOperationsCounter != 10)) -> (next (doorOperationsCounter) = doorOperationsCounter));
}



monitor boolean techGuyInAction {
  ! techGuyInAction;
  G ( (doorOperationsCounter = 10 & !technicianAck) -> next(techGuyInAction));
  G ( technicianAck -> next(!techGuyInAction));
  G ( (!technicianAck & doorOperationsCounter != 10) -> techGuyInAction = next(techGuyInAction));
}


 
guarantee stopWhenTechGuyInAction:
G (techGuyInAction -> stopping);


 
guarantee
G (PREV(!techGuyInAction) & techGuyInAction <-> startTechnicalJob );



 
 
 



 
 
 

 
guarantee alwaysGoForward:
GF forwarding;

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Station station;
env Button stopButton;
env DoorStatus doorStatus;
env boolean technicianAck;

sys MotorCmd mLeft;
sys MotorCmd mRight;
sys DoorOp doorReq;
sys boolean startTechnicalJob;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Station = {ONE, TWO, THREE, FOUR, NONE};
type DoorOp = {OPEN, CLOSE, NIL};
type DoorStatus = {OPENED, CLOSED, IN_PROCESS};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  atStation := station != NONE;
  enteringStation := (station != NONE) & (PREV (station = NONE));
  openDoorReq := doorReq = OPEN;
  closeDoorReq := doorReq = CLOSE;
  doorCounterIncreased := (PREV (next(doorOperationsCounter) - doorOperationsCounter = 1) );

 
 
 
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding, !atStation | stopping);
  
 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> station = next(station));

 
assumption notAlwaysStopAtNearestStation:
  GF !stopAtNearestStation;

 
assumption initiallyDoorIsClosed:
  doorStatus=CLOSED;

 
assumption doneDoorProcessEventually:
  GF doorStatus!=IN_PROCESS;
    
 
assumption noStrangeDoorStatus1:
  G (next(doorStatus=OPENED) -> (doorStatus=IN_PROCESS));
  
 
assumption noStrangeDoorStatus2:
  G (next(doorStatus=CLOSED) -> (doorStatus!=OPENED));

 
assumption
  G (next(doorStatus = IN_PROCESS) -> (doorStatus = IN_PROCESS) | openDoorReq  | closeDoorReq);

 
assumption
  G (atStation -> stopButton=RELEASED);

 
assumption initiallyNoTechnicianAck:
  !technicianAck;
  
assumption doneTechnicianActionEventually:
  pRespondsToS(techGuyInAction, technicianAck);
 
 
assumption noStrangeTechnicianAcks:
  G (next(technicianAck) -> (techGuyInAction & !technicianAck));


 
 
 

 
guarantee initialState:
stopping & doorReq=NIL;

 
guarantee stopAtNearestStationWhenAsked:
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation becomes true when stopButton is pressed
 * TBD
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ( (stopButton = PRESSED & !doorCounterIncreased) -> next(stopAtNearestStation));
   
  G ( (doorCounterIncreased) -> next(!stopAtNearestStation));
   
  G ( ((stopButton = RELEASED) & !doorCounterIncreased) -> stopAtNearestStation = next(stopAtNearestStation));
} 


 
guarantee dontChangeDoorRequestWhenDoorIsInProcess:
  G (doorStatus=IN_PROCESS -> doorReq=NIL);


 
 
guarantee
G (atStation & stopAtNearestStation) & (doorStatus = CLOSED) & (!doorCounterIncreased) <-> openDoorReq;


 
guarantee closeDoorAfterOpen:
G ( (doorStatus = OPENED) <-> closeDoorReq);


/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 10
 */ 
monitor Int(0..10) doorOperationsCounter {
  doorOperationsCounter = 0;
  G (doorStatus != CLOSED) & (doorOperationsCounter != 10) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus = CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus != CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = (doorOperationsCounter + 1));
  G (doorOperationsCounter = 10) -> (next (doorOperationsCounter) = 0);
}



monitor boolean techGuyInAction {
  ! techGuyInAction;
  G ( (doorOperationsCounter = 10 & !technicianAck) -> next(techGuyInAction));
  G ( technicianAck -> next(!techGuyInAction));
  G ( (!technicianAck & doorOperationsCounter != 10) -> techGuyInAction = next(techGuyInAction));
}


 
guarantee stopWhenTechGuyInAction:
G (techGuyInAction -> stopping);


 
guarantee
G (PREV(!techGuyInAction) & techGuyInAction <-> startTechnicalJob );



 
 
 



 
 
 

 
guarantee alwaysGoForward:
GF forwarding;

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Station station;
env Button stopButton;
env DoorStatus doorStatus;
env boolean technicianAck;
env Station baseStation;
env Station pressedStation;
env boolean readyToBaseStation;

sys MotorCmd mLeft;
sys MotorCmd mRight;
sys DoorOp doorReq;
sys boolean startTechnicalJob;
sys boolean[2][4] shuttleTasks;
sys Station pickUpStation;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Station = {ONE, TWO, THREE, FOUR, NONE};
type DoorOp = {OPEN, CLOSE, NIL};
type DoorStatus = {OPENED, CLOSED, IN_PROCESS};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  backwarding := mLeft = BWD & mRight = BWD;
  atStation := station != NONE;
  enteringStation := (station != NONE) & (PREV (station = NONE));
  openDoorReq := doorReq = OPEN;
  closeDoorReq := doorReq = CLOSE;
  doorCounterIncreased := (PREV (next(doorOperationsCounter) - doorOperationsCounter = 1) );
  leftDirection := 0;
  rightDirection := 1;
  
 
 
 
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding, !atStation | stopping);
  
 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> station = next(station));

 
assumption notAlwaysStopAtNearestStation:
  GF !stopAtNearestStation;

assumption
  stopButton=RELEASED;

 
assumption initiallyDoorIsClosed:
  doorStatus=CLOSED;

 
assumption doneDoorProcessEventually:
  GF doorStatus!=IN_PROCESS;
    
 
assumption noStrangeDoorStatus1:
  G (next(doorStatus=OPENED) -> (doorStatus=IN_PROCESS));
  
 
assumption noStrangeDoorStatus2:
  G (next(doorStatus=CLOSED) -> (doorStatus!=OPENED));

 
assumption
  G (next(doorStatus = IN_PROCESS) -> (doorStatus = IN_PROCESS) | openDoorReq  | closeDoorReq);

 
assumption
  G (atStation -> stopButton=RELEASED);

 
assumption initiallyNoTechnicianAck:
  !technicianAck;
  
assumption doneTechnicianActionEventually:
  pRespondsToS(techGuyInAction, technicianAck);
 
 
assumption noStrangeTechnicianAcks:
  G (next(technicianAck) -> (techGuyInAction & !technicianAck));


 
 
 

 
guarantee initialState:
stopping & doorReq=NIL;

 
guarantee stopAtNearestStationWhenAsked:
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation becomes true when stopButton is pressed
 * TBD
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ( (stopButton = PRESSED & !doorCounterIncreased) -> next(stopAtNearestStation));
   
  G ( (doorCounterIncreased) -> next(!stopAtNearestStation));
   
  G ( ((stopButton = RELEASED) & !doorCounterIncreased) -> stopAtNearestStation = next(stopAtNearestStation));
} 


 
guarantee dontChangeDoorRequestWhenDoorIsInProcess:
  G (doorStatus=IN_PROCESS -> doorReq=NIL);


 
 
guarantee
G (atStation & stopAtNearestStation) & (doorStatus = CLOSED) & (!doorCounterIncreased) <-> openDoorReq;


 
guarantee closeDoorAfterOpen:
G ( (doorStatus = OPENED) <-> closeDoorReq);


/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 10
 */ 
monitor Int(0..10) doorOperationsCounter {
  doorOperationsCounter = 0;
  G (doorStatus != CLOSED) & (doorOperationsCounter != 10) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus = CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus != CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = (doorOperationsCounter + 1));
  G (doorOperationsCounter = 10) -> (next (doorOperationsCounter) = 0);
}



monitor boolean techGuyInAction {
  ! techGuyInAction;
  G ( (doorOperationsCounter = 10 & !technicianAck) -> next(techGuyInAction));
  G ( technicianAck -> next(!techGuyInAction));
  G ( (!technicianAck & doorOperationsCounter != 10) -> techGuyInAction = next(techGuyInAction));
}


 
guarantee stopWhenTechGuyInAction:
G (techGuyInAction -> stopping);


 
guarantee
G (PREV(!techGuyInAction) & techGuyInAction <-> startTechnicalJob );



 
 
 



 
 
 

 
guarantee alwaysGoForward:
GF forwarding;

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..4) station;
env Button stopButton;
env DoorStatus doorStatus;
env boolean technicianAck;
env Int(0..4) baseStation;  
env Int(0..4) pressedStation;
env boolean readyToBaseStation;  

sys MotorCmd mLeft;
sys MotorCmd mRight;
sys DoorOp doorReq;
sys boolean startTechnicalJob;
sys boolean[4] shuttleTasksFwd;
sys boolean[4] shuttleTasksBwd;

sys Int(0..4) pickUpStation;


type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Direction = {GOING_FWD, GOING_BWD, GOING_NONE};
type DoorOp = {OPEN, CLOSE, NIL};
type DoorStatus = {OPENED, CLOSED, IN_PROCESS};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  backwarding := mLeft = BWD & mRight = BWD;
  atStation := station != stationNone;
  atBaseStation := station = baseStation;
  enteringStation := (station != stationNone) & (PREV (station = stationNone));
  openDoorReq := doorReq = OPEN;
  closeDoorReq := doorReq = CLOSE;
  doorCounterIncreased := (PREV (next(doorOperationsCounter) - doorOperationsCounter = 1) );
  noRequestsFwd := (shuttleTasksFwd[0]=false & shuttleTasksFwd[1]=false & 
                     shuttleTasksFwd[2]=false & shuttleTasksFwd[3]=false);
  noRequestsBwd := (shuttleTasksBwd[0]=false & shuttleTasksBwd[1]=false & 
                     shuttleTasksBwd[2]=false & shuttleTasksBwd[3]=false);
  noRequests := noRequestsFwd & noRequestsBwd;
  stationOne := 0;
  stationTwo := 1;
  stationThree := 2;
  stationFour := 3;
  stationNone := 4;
  
  goingForward := shuttleDirection = GOING_FWD;
  goingBackward := shuttleDirection = GOING_BWD;
  goingNone := shuttleDirection = GOING_NONE;
  
 
predicate isBaseStationFwd(Direction d, Int(0..4) stationLast):
  isTaskDirectionFwdOrNoTask(d, stationLast, baseStation) | stationLast = 4;

predicate isBaseStationBwd(Direction d, Int(0..4) stationLast):
  isTaskDirectionBwdOrNoTask(d, stationLast, baseStation);

  
 
 
 

assumption initialStateEnv:
  stopButton=RELEASED & doorStatus=CLOSED & !atStation & noRequests;
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding | backwarding, !atStation | stopping);

 
assumption
  pRespondsToS(forwarding, noRequestsFwd);

 
assumption
  pRespondsToS(backwarding, noRequestsBwd);

 
assumption
  pRespondsToS(isBaseStationFwd(shuttleDirection, lastPassedStation) & forwarding, atBaseStation);

 
assumption
  pRespondsToS(isBaseStationBwd(shuttleDirection, lastPassedStation) & backwarding, atBaseStation);

 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> station = next(station));

 
assumption notAlwaysStopAtNearestStation:
  GF !stopAtNearestStation;

 
assumption doneDoorProcessEventually:
  GF doorStatus!=IN_PROCESS;
    
 
assumption noStrangeDoorStatus1:
  G (next(doorStatus=OPENED) -> (doorStatus=IN_PROCESS));
  
 
assumption noStrangeDoorStatus2:
  G (next(doorStatus=CLOSED) -> (doorStatus!=OPENED));

 
assumption
  G (next(doorStatus = IN_PROCESS) -> (doorStatus = IN_PROCESS) | openDoorReq  | closeDoorReq);

 
assumption
  G (atStation -> stopButton=RELEASED);

 
assumption initiallyNoTechnicianAck:
  !technicianAck;
  
assumption doneTechnicianActionEventually:
  pRespondsToS(techGuyInAction, technicianAck);
 
 
assumption noStrangeTechnicianAcks:
  G (next(technicianAck) -> (techGuyInAction & !technicianAck));


 
 
 

 
guarantee initialState:
stopping & doorReq=NIL;

 
guarantee stopAtNearestStationWhenAsked:
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation becomes true when stopButton is pressed
 * TBD
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ( (stopButton = PRESSED & !doorCounterIncreased) -> next(stopAtNearestStation));
   
  G ( (doorCounterIncreased) -> next(!stopAtNearestStation));
   
  G ( ((stopButton = RELEASED) & !doorCounterIncreased) -> stopAtNearestStation = next(stopAtNearestStation));
} 


 
guarantee dontChangeDoorRequestWhenDoorIsInProcess:
  G (doorStatus=IN_PROCESS -> doorReq=NIL);


 
 
guarantee
G (atStation & stopAtNearestStation) & (doorStatus = CLOSED) & (!doorCounterIncreased) <-> openDoorReq;


 
guarantee closeDoorAfterOpen:
G ( (doorStatus = OPENED) <-> closeDoorReq);


 
guarantee
G doorStatus = OPENED -> pickUpStation = station;

guarantee
G doorStatus != OPENED -> pickUpStation = stationNone;

/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 10
 */ 
monitor Int(0..10) doorOperationsCounter {
  doorOperationsCounter = 0;
  G (doorStatus != CLOSED) & (doorOperationsCounter != 10) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus = CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus != CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = (doorOperationsCounter + 1));
  G (doorOperationsCounter = 10) -> (next (doorOperationsCounter) = 0);
}



monitor boolean techGuyInAction {
  ! techGuyInAction;
  G ( (doorOperationsCounter = 10 & !technicianAck) -> next(techGuyInAction));
  G ( technicianAck -> next(!techGuyInAction));
  G ( (!technicianAck & doorOperationsCounter != 10) -> techGuyInAction = next(techGuyInAction));
}


 
guarantee stopWhenTechGuyInAction:
G (techGuyInAction -> stopping);


 
guarantee
G (PREV(!techGuyInAction) & techGuyInAction <-> startTechnicalJob );


monitor Int(0..4) lastPassedStation {
  lastPassedStation = stationNone;
  G (atStation -> next(lastPassedStation) = station);
  G (!atStation -> next(lastPassedStation) = lastPassedStation);
}


 

 
monitor Direction shuttleDirection{
  shuttleDirection = GOING_NONE;
  G atBaseStation & noRequests -> next(shuttleDirection) = GOING_NONE;
  G forwarding -> next(shuttleDirection) = GOING_FWD;
  G backwarding -> next(shuttleDirection) = GOING_BWD;
  G !forwarding & !backwarding & !(atBaseStation & noRequests) -> next(shuttleDirection) = shuttleDirection;
}

 
predicate updateTasks(boolean[4] tasks ,Int(0..4) indexPressed, Int(0..4) indexOpenedDoor):
  next(tasks[0]) = ((indexOpenedDoor != 0) & (tasks[0] | (indexPressed = 0))) &
  next(tasks[1]) = ((indexOpenedDoor != 1) & (tasks[1] | (indexPressed = 1))) &
  next(tasks[2]) = ((indexOpenedDoor != 2) & (tasks[2] | (indexPressed = 2))) &
  next(tasks[3]) = ((indexOpenedDoor != 3) & (tasks[3] | (indexPressed = 3)));

predicate isTaskDirectionFwdOrNoTask(Direction d, Int(0..4) stationLast, Int(0..4) s):
  ((d = GOING_FWD &  (stationLast - s < 0)) | 
  (d = GOING_BWD & (stationLast - s < 0)) );

predicate isTaskDirectionBwdOrNoTask(Direction d, Int(0..4) stationLast, Int(0..4) s):
  ((d = GOING_FWD &  (stationLast - s >= 0)) | 
  (d = GOING_BWD & (stationLast - s >= 0)) );


 
guarantee
  G isTaskDirectionFwdOrNoTask(shuttleDirection, lastPassedStation, pressedStation)  -> updateTasks(shuttleTasksFwd, pressedStation, pickUpStation) & updateTasks(shuttleTasksBwd, 4, 4);

 
guarantee
  G isTaskDirectionBwdOrNoTask(shuttleDirection, lastPassedStation, pressedStation) -> updateTasks(shuttleTasksBwd, pressedStation, pickUpStation) & updateTasks(shuttleTasksFwd, 4, 4);


 
guarantee
  pRespondsToS(noRequests & readyToBaseStation, atBaseStation);



 
 
 

 
guarantee 
G ( (noRequests & atBaseStation) -> stopping & updateTasks(shuttleTasksFwd, 4, 4) & updateTasks(shuttleTasksBwd, 4, 4));

guarantee onlyAllowedBwdFwdStop:
G (forwarding | backwarding | stopping);

 
 
 

guarantee allRequestsAreSatisfaidEventually:
  GF (noRequests);


 
 
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..4) station;
env Button stopButton;
env DoorStatus doorStatus;
env boolean technicianAck;
env Int(0..4) baseStation;  
env Int(0..4) pressedStation;
env boolean longTimeWithoutRequests;

sys MotorCmd mLeft;
sys MotorCmd mRight;
sys DoorOp doorReq;
sys boolean startTechnicalJob;
sys boolean[4] shuttleTasksFwd;
sys boolean[4] shuttleTasksBwd;

sys Int(0..4) pickUpStation;


type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Direction = {GOING_FWD, GOING_BWD, GOING_NONE};
type DoorOp = {OPEN, CLOSE, NIL};
type DoorStatus = {OPENED, CLOSED, IN_PROCESS};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  backwarding := mLeft = BWD & mRight = BWD;
  atStation := station != stationNone;
  atBaseStation := station = baseStation;
  enteringStation := (station != stationNone) & (PREV (station = stationNone));
  openDoorReq := doorReq = OPEN;
  closeDoorReq := doorReq = CLOSE;
  doorCounterIncreased := (PREV (next(doorOperationsCounter) - doorOperationsCounter = 1) );
  noRequestsFwd := (shuttleTasksFwd[0]=false & shuttleTasksFwd[1]=false & 
                     shuttleTasksFwd[2]=false & shuttleTasksFwd[3]=false);
  noRequestsBwd := (shuttleTasksBwd[0]=false & shuttleTasksBwd[1]=false & 
                     shuttleTasksBwd[2]=false & shuttleTasksBwd[3]=false);
  noRequests := noRequestsFwd & noRequestsBwd;
  stationOne := 0;
  stationTwo := 1;
  stationThree := 2;
  stationFour := 3;
  stationNone := 4;
  
 
predicate isBaseStationFwd(Direction d, Int(0..4) stationLast):
  isTaskDirectionFwdOrNoTask(d, stationLast, baseStation) | stationLast = 4;

predicate isBaseStationBwd(Direction d, Int(0..4) stationLast):
  isTaskDirectionBwdOrNoTask(d, stationLast, baseStation);

  
 
 
 


assumption initialStateEnv:
  stopButton=RELEASED & doorStatus=CLOSED & !atStation & noRequests;
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding | backwarding, !atStation | stopping);

 
assumption
  pRespondsToS(forwarding, noRequestsFwd);

 
assumption
  pRespondsToS(backwarding, noRequestsBwd);

 
assumption
  pRespondsToS(isBaseStationFwd(shuttleDirection, lastPassedStation) & forwarding, atBaseStation | backwarding | stopping);

 
assumption
  pRespondsToS(isBaseStationBwd(shuttleDirection, lastPassedStation) & backwarding, atBaseStation | forwarding | stopping);

 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> station = next(station));

 
assumption doneDoorProcessEventually:
  GF doorStatus!=IN_PROCESS;
    
 
assumption noStrangeDoorStatus1:
  G (next(doorStatus=OPENED) -> (doorStatus=IN_PROCESS));
  
 
assumption noStrangeDoorStatus2:
  G (next(doorStatus=CLOSED) -> (doorStatus!=OPENED));

 
assumption
  G (next(doorStatus = IN_PROCESS) -> (doorStatus = IN_PROCESS) | openDoorReq  | closeDoorReq);

 
assumption
  G (atStation -> stopButton=RELEASED);

 
assumption initiallyNoTechnicianAck:
  !technicianAck;
  
assumption doneTechnicianActionEventually:
  pRespondsToS(techGuyInAction, technicianAck);
 
 
assumption noStrangeTechnicianAcks:
  G (next(technicianAck) -> (techGuyInAction & !technicianAck));


 
 
 

 
guarantee initialState:
stopping & doorReq=NIL & !startTechnicalJob & noRequests;

 
guarantee stopAtNearestStationWhenAsked:
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation becomes true when stopButton is pressed
 * TBD: cancel monitor and use the regular mechanism
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ( (stopButton = PRESSED & !doorCounterIncreased) -> next(stopAtNearestStation));
   
  G ( (doorCounterIncreased) -> next(!stopAtNearestStation));
   
  G ( ((stopButton = RELEASED) & !doorCounterIncreased) -> stopAtNearestStation = next(stopAtNearestStation));
} 

 
guarantee dontChangeDoorRequestWhenDoorIsInProcess:
  G (doorStatus=IN_PROCESS -> doorReq=NIL);


predicate taskAtCurrentStation(Int(0..4) index):
((shuttleTasksFwd[0] | shuttleTasksBwd[0]) & index = 0) |
((shuttleTasksFwd[1] | shuttleTasksBwd[1]) & index = 1) |
((shuttleTasksFwd[2] | shuttleTasksBwd[2]) & index = 2) |
((shuttleTasksFwd[3] | shuttleTasksBwd[3]) & index = 3);

 
 
guarantee
G (atStation & (stopAtNearestStation| taskAtCurrentStation(station))) & (doorStatus = CLOSED) & (!doorCounterIncreased) <-> openDoorReq;


 
guarantee closeDoorAfterOpen:
G ( (doorStatus = OPENED) <-> closeDoorReq);


 
guarantee
G doorStatus = OPENED -> pickUpStation = station;

guarantee
G doorStatus != OPENED -> pickUpStation = stationNone;

/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 10
 */ 
monitor Int(0..10) doorOperationsCounter {
  doorOperationsCounter = 0;
  G (doorStatus != CLOSED) & (doorOperationsCounter != 10) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus = CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus != CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = (doorOperationsCounter + 1));
  G (doorOperationsCounter = 10) -> (next (doorOperationsCounter) = 0);
}



monitor boolean techGuyInAction {
  ! techGuyInAction;
  G ( (doorOperationsCounter = 10 & !technicianAck) -> next(techGuyInAction));
  G ( technicianAck -> next(!techGuyInAction));
  G ( (!technicianAck & doorOperationsCounter != 10) -> techGuyInAction = next(techGuyInAction));
}


 
guarantee stopWhenTechGuyInAction:
G (techGuyInAction -> stopping);


 
guarantee
G (PREV(!techGuyInAction) & techGuyInAction <-> startTechnicalJob );


monitor Int(0..4) lastPassedStation {
  lastPassedStation = stationNone;
  G (atStation -> next(lastPassedStation) = station);
  G (!atStation -> next(lastPassedStation) = lastPassedStation);
}


 

 
monitor Direction shuttleDirection{
  shuttleDirection = GOING_NONE;
  G atBaseStation & noRequests -> next(shuttleDirection) = GOING_NONE;
  G forwarding -> next(shuttleDirection) = GOING_FWD;
  G backwarding -> next(shuttleDirection) = GOING_BWD;
  G !forwarding & !backwarding & !(atBaseStation & noRequests) -> next(shuttleDirection) = shuttleDirection;
}

 
predicate updateTasks(boolean[4] tasks ,Int(0..4) indexPressed, Int(0..4) indexOpenedDoor):
  next(tasks[0]) = ((indexOpenedDoor != 0) & (tasks[0] | (indexPressed = 0))) &
  next(tasks[1]) = ((indexOpenedDoor != 1) & (tasks[1] | (indexPressed = 1))) &
  next(tasks[2]) = ((indexOpenedDoor != 2) & (tasks[2] | (indexPressed = 2))) &
  next(tasks[3]) = ((indexOpenedDoor != 3) & (tasks[3] | (indexPressed = 3)));

predicate isTaskDirectionFwdOrNoTask(Direction d, Int(0..4) stationLast, Int(0..4) s):
  ((d = GOING_FWD &  (stationLast - s < 0)) | 
  (d = GOING_BWD & (stationLast - s < 0)) );

predicate isTaskDirectionBwdOrNoTask(Direction d, Int(0..4) stationLast, Int(0..4) s):
  ((d = GOING_FWD &  (stationLast - s >= 0)) | 
  (d = GOING_BWD & (stationLast - s >= 0)) );


 
guarantee
  G isTaskDirectionFwdOrNoTask(shuttleDirection, lastPassedStation, pressedStation)  -> updateTasks(shuttleTasksFwd, pressedStation, pickUpStation) & updateTasks(shuttleTasksBwd, 4, 4);

 
guarantee
  G isTaskDirectionBwdOrNoTask(shuttleDirection, lastPassedStation, pressedStation) -> updateTasks(shuttleTasksBwd, pressedStation, pickUpStation) & updateTasks(shuttleTasksFwd, 4, 4);


 
guarantee
  pRespondsToS(noRequests & longTimeWithoutRequests, atBaseStation);



 
 
 

 
guarantee 
G ( (noRequests & atBaseStation) -> stopping & updateTasks(shuttleTasksFwd, 4, 4) & updateTasks(shuttleTasksBwd, 4, 4));

guarantee onlyAllowedBwdFwdStop:
G (forwarding | backwarding | stopping);


 
 
 

guarantee allRequestsAreSatisfaidEventually:
  GF (noRequests);

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..4) station;
env Button stopButton;
env DoorStatus doorStatus;
env boolean technicianAck;
env Int(0..4) baseStation;  
env Int(0..4) pressedStation;
env boolean longTimeWithoutRequests;

sys MotorCmd mLeft;
sys MotorCmd mRight;
sys DoorOp doorReq;
sys boolean startTechnicalJob;
sys boolean[4] shuttleTasksFwd;
sys boolean[4] shuttleTasksBwd;
sys Int(0..4) pickUpStation;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Direction = {GOING_FWD, GOING_BWD, GOING_NONE};
type DoorOp = {OPEN, CLOSE, NIL};
type DoorStatus = {OPENED, CLOSED, IN_PROCESS};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  backwarding := mLeft = BWD & mRight = BWD;
  atStation := station != stationNone;
  atBaseStation := station = baseStation;
  enteringStation := (station != stationNone) & (PREV (station = stationNone));
  openDoorReq := doorReq = OPEN;
  closeDoorReq := doorReq = CLOSE;
  doorCounterIncreased := (PREV (next(doorOperationsCounter) - doorOperationsCounter = 1) );
  noRequestsFwd := (shuttleTasksFwd[0]=false & shuttleTasksFwd[1]=false & 
                     shuttleTasksFwd[2]=false & shuttleTasksFwd[3]=false);
  noRequestsBwd := (shuttleTasksBwd[0]=false & shuttleTasksBwd[1]=false & 
                     shuttleTasksBwd[2]=false & shuttleTasksBwd[3]=false);
  noRequests := noRequestsFwd & noRequestsBwd;
  stationOne := 0;
  stationTwo := 1;
  stationThree := 2;
  stationFour := 3;
  stationNone := 4;
  

predicate isBaseStationFwd(Direction d, Int(0..4) stationLast):
  isTaskDirectionFwdOrNoTask(d, stationLast, baseStation) | stationLast = 4;

predicate isBaseStationBwd(Direction d, Int(0..4) stationLast):
  isTaskDirectionBwdOrNoTask(d, stationLast, baseStation);

 
 
 

assumption initialStateEnv:
  stopButton=RELEASED & doorStatus=CLOSED & !atStation & noRequests;
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding | backwarding, !atStation | stopping);

 
assumption
  pRespondsToS(forwarding, noRequestsFwd);

 
assumption
  pRespondsToS(backwarding, noRequestsBwd);

 
assumption
  pRespondsToS(isBaseStationFwd(shuttleDirection, lastPassedStation) & forwarding, atBaseStation | backwarding | stopping);

 
assumption
  pRespondsToS(isBaseStationBwd(shuttleDirection, lastPassedStation) & backwarding, atBaseStation | forwarding | stopping);

 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> station = next(station));

 
assumption doneDoorProcessEventually:
  GF doorStatus!=IN_PROCESS;
    
 
assumption noStrangeDoorStatus1:
  G (next(doorStatus=OPENED) -> (doorStatus=IN_PROCESS));
  
 
assumption noStrangeDoorStatus2:
  G (next(doorStatus=CLOSED) -> (doorStatus!=OPENED));

 
assumption
  G (next(doorStatus = IN_PROCESS) -> (doorStatus = IN_PROCESS) | openDoorReq  | closeDoorReq);

 
assumption
  G (atStation -> stopButton=RELEASED);

 
assumption initiallyNoTechnicianAck:
  !technicianAck;
  
assumption doneTechnicianActionEventually:
  pRespondsToS(techGuyInAction, technicianAck);
 
 
assumption noStrangeTechnicianAcks:
  G (next(technicianAck) -> (techGuyInAction & !technicianAck));

 
 
 

 
guarantee initialState:
stopping & doorReq=NIL & noRequests & !startTechnicalJob;

 
guarantee stopAtNearestStationWhenAsked:
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation becomes true when stopButton is pressed
 * TBD: cancel monitor and use the regular mechanism
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ( (stopButton = PRESSED & !doorCounterIncreased) -> next(stopAtNearestStation));
   
  G ( (doorCounterIncreased) -> next(!stopAtNearestStation));
   
  G ( ((stopButton = RELEASED) & !doorCounterIncreased) -> stopAtNearestStation = next(stopAtNearestStation));
} 

 
guarantee dontChangeDoorRequestWhenDoorIsInProcess:
  G (doorStatus=IN_PROCESS -> doorReq=NIL);

predicate taskAtCurrentStation(Int(0..4) index):
((shuttleTasksFwd[0] | shuttleTasksBwd[0]) & index = 0) |
((shuttleTasksFwd[1] | shuttleTasksBwd[1]) & index = 1) |
((shuttleTasksFwd[2] | shuttleTasksBwd[2]) & index = 2) |
((shuttleTasksFwd[3] | shuttleTasksBwd[3]) & index = 3);

 
 
guarantee
G (atStation & (stopAtNearestStation| taskAtCurrentStation(station))) & (doorStatus = CLOSED) & (!doorCounterIncreased) <-> openDoorReq;

 
guarantee closeDoorAfterOpen:
G ( (doorStatus = OPENED) <-> closeDoorReq);

 
guarantee
G doorStatus = OPENED -> pickUpStation = station;

guarantee
G doorStatus != OPENED -> pickUpStation = stationNone;

/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 10
 */ 
monitor Int(0..10) doorOperationsCounter {
  doorOperationsCounter = 0;
  G (doorStatus != CLOSED) & (doorOperationsCounter != 10) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus = CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus != CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = (doorOperationsCounter + 1));
  G (doorOperationsCounter = 10) -> (next (doorOperationsCounter) = 0);
}

monitor boolean techGuyInAction {
  ! techGuyInAction;
  G ( (doorOperationsCounter = 10 & !technicianAck) -> next(techGuyInAction));
  G ( technicianAck -> next(!techGuyInAction));
  G ( (!technicianAck & doorOperationsCounter != 10) -> techGuyInAction = next(techGuyInAction));
}

 
guarantee stopWhenTechGuyInAction:
G (techGuyInAction -> stopping);

 
guarantee
G (PREV(!techGuyInAction) & techGuyInAction <-> startTechnicalJob );

monitor Int(0..4) lastPassedStation {
  lastPassedStation = stationNone;
  G (atStation -> next(lastPassedStation) = station);
  G (!atStation -> next(lastPassedStation) = lastPassedStation);
}

 

 
monitor Direction shuttleDirection{
  shuttleDirection = GOING_NONE;
  G atBaseStation & noRequests & longTimeWithoutRequests & stopping -> next(shuttleDirection) = GOING_NONE;
  G forwarding -> next(shuttleDirection) = GOING_FWD;
  G backwarding -> next(shuttleDirection) = GOING_BWD;
  G !forwarding & !backwarding & !(atBaseStation & noRequests & longTimeWithoutRequests) -> next(shuttleDirection) = shuttleDirection;
}

 
predicate updateTasks(boolean[4] tasks ,Int(0..4) indexPressed, Int(0..4) indexOpenedDoor):
  next(tasks[0]) = ((indexOpenedDoor != 0) & (tasks[0] | (indexPressed = 0))) &
  next(tasks[1]) = ((indexOpenedDoor != 1) & (tasks[1] | (indexPressed = 1))) &
  next(tasks[2]) = ((indexOpenedDoor != 2) & (tasks[2] | (indexPressed = 2))) &
  next(tasks[3]) = ((indexOpenedDoor != 3) & (tasks[3] | (indexPressed = 3)));

predicate isTaskDirectionFwdOrNoTask(Direction d, Int(0..4) stationLast, Int(0..4) s):
  ((d = GOING_FWD &  (stationLast - s < 0)) | 
  (d = GOING_BWD & (stationLast - s < 0)) );

predicate isTaskDirectionBwdOrNoTask(Direction d, Int(0..4) stationLast, Int(0..4) s):
  ((d = GOING_FWD &  (stationLast - s >= 0)) | 
  (d = GOING_BWD & (stationLast - s >= 0)) );

 
guarantee
  G isTaskDirectionFwdOrNoTask(shuttleDirection, lastPassedStation, pressedStation)  -> updateTasks(shuttleTasksFwd, pressedStation, pickUpStation) & updateTasks(shuttleTasksBwd, 4, 4);

 
guarantee
  G isTaskDirectionBwdOrNoTask(shuttleDirection, lastPassedStation, pressedStation) -> updateTasks(shuttleTasksBwd, pressedStation, pickUpStation) & updateTasks(shuttleTasksFwd, 4, 4);

 
guarantee
  pRespondsToS(noRequests & longTimeWithoutRequests, atBaseStation);

 
 
 

 
guarantee 
G ( (noRequests & atBaseStation) -> stopping & updateTasks(shuttleTasksFwd, 4, 4) & updateTasks(shuttleTasksBwd, 4, 4));

guarantee onlyAllowedBwdFwdStop:
G (forwarding | backwarding | stopping);

 
 
 

guarantee allRequestsAreSatisfaidEventually:
  GF (noRequests);
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..4) station;
env Button stopButton;
env DoorStatus doorStatus;
 
 
env Int(0..4) pressedStation;  
 

sys MotorCmd mLeft;
sys MotorCmd mRight;
sys DoorOp doorReq;
 
sys boolean[4] shuttleTasksFwd;
sys boolean[4] shuttleTasksBwd;
sys Int(0..4) pickUpStation;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Direction = {GOING_FWD, GOING_BWD, GOING_NONE};
type DoorOp = {OPEN, CLOSE, NIL};
type DoorStatus = {OPENED, CLOSED, IN_PROCESS};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  backwarding := mLeft = BWD & mRight = BWD;
  atStation := station != stationNone;
   
  openDoorReq := doorReq = OPEN;
  closeDoorReq := doorReq = CLOSE;
  doorCounterIncreased := (PREV (next(doorOperationsCounter) - doorOperationsCounter = 1) );
  noRequestsFwd := (shuttleTasksFwd[0]=false & shuttleTasksFwd[1]=false & 
                     shuttleTasksFwd[2]=false & shuttleTasksFwd[3]=false);
  noRequestsBwd := (shuttleTasksBwd[0]=false & shuttleTasksBwd[1]=false & 
                     shuttleTasksBwd[2]=false & shuttleTasksBwd[3]=false);
  noRequests := noRequestsFwd & noRequestsBwd;
  stationOne := 0;
  stationTwo := 1;
  stationThree := 2;
  stationFour := 3;
  stationNone := 4;
  
 
 
 
 
 
 

 
 
 

assumption initialStateEnv:
  stopButton=RELEASED & doorStatus=CLOSED & !atStation & noRequests;
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding | backwarding, !atStation | stopping);

 
gar
  pRespondsToS(forwarding, noRequestsFwd);

 
gar
  pRespondsToS(backwarding, noRequestsBwd);

asm
G (forwarding -> (station != 4 -> (next(station) = 4 | next(station)=station)) & 
  (station = 4 -> (next(station) = lastPassedStation+1 | next(station) = station)));

asm
G (backwarding -> (station != 4 -> (next(station) = 4 | next(station)=station)) & 
  (station = 4 -> (next(station) = lastPassedStation-1 | next(station) = station)));

 
 
 
 
 
 
 

 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> station = next(station));

 
assumption doneDoorProcessEventually:
  GF doorStatus!=IN_PROCESS;

 
assumption
 doorStatus = OPENED -> next(doorStatus!=CLOSED);

 
assumption
 doorStatus = CLOSED -> next(doorStatus!=OPENED);
 
 
assumption
  G (openDoorReq | closeDoorReq) -> (next(doorStatus = IN_PROCESS));

 
assumption
  G (next(doorStatus = IN_PROCESS) -> (doorStatus = IN_PROCESS) | openDoorReq  | closeDoorReq);

 

  
 
 
 

 
 
 
 
 
 
 
 
 
 

 
 
 

 
guarantee initialState:
stopping & doorReq=NIL & noRequests ; 

 
guarantee stopAtNearestStationWhenAsked:
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation becomes true when stopButton is pressed
 * TBD: cancel monitor and use the regular mechanism
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ( (stopButton = PRESSED & !doorCounterIncreased) -> next(stopAtNearestStation));
   
  G ( (doorCounterIncreased) -> next(!stopAtNearestStation));
   
  G ( ((stopButton = RELEASED) & !doorCounterIncreased) -> stopAtNearestStation = next(stopAtNearestStation));
} 

 
guarantee dontChangeDoorRequestWhenDoorIsInProcess:
  G (doorStatus=IN_PROCESS -> doorReq=NIL);

 
 
 
 
 

predicate taskAtCurrentStation(Int(0..4) index):
  0=0;


 
 
guarantee
G (atStation & (stopAtNearestStation| taskAtCurrentStation(station))) & (doorStatus = CLOSED) & (!doorCounterIncreased) <-> openDoorReq;

 
guarantee closeDoorAfterOpen:
G ( (doorStatus = OPENED) <-> closeDoorReq);

 
guarantee
G doorStatus = OPENED -> pickUpStation = station;

guarantee
G doorStatus != OPENED -> pickUpStation = stationNone;

/**
 * monitor doorOperationsCounter is counting open-close operations
 * From 0 to 10
 */ 
monitor Int(0..10) doorOperationsCounter {
  doorOperationsCounter = 0;
  G (doorStatus != CLOSED) & (doorOperationsCounter != 10) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus = CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = doorOperationsCounter);
  G ((doorStatus = CLOSED) & PREV(doorStatus != CLOSED) & (doorOperationsCounter != 10)) -> (next(doorOperationsCounter) = (doorOperationsCounter + 1));
  G (doorOperationsCounter = 10) -> (next (doorOperationsCounter) = 0);
}

 
 
 
 
 
 

 
 
 
 
 
 
 

monitor Int(0..4) lastPassedStation {
  lastPassedStation = stationNone;
  G (atStation -> next(lastPassedStation) = station);
  G (!atStation -> next(lastPassedStation) = lastPassedStation);
}

 

 
 
 
 
 
 
 
 

 
monitor Direction shuttleDirection{
  shuttleDirection = GOING_NONE;
  
  G forwarding -> next(shuttleDirection) = GOING_FWD;
  G backwarding -> next(shuttleDirection) = GOING_BWD;
  G !forwarding & !backwarding -> next(shuttleDirection) = shuttleDirection;
}

 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 

 
 
 

 
 
 

 
 
 

guarantee onlyAllowedBwdFwdStop:
G (forwarding | backwarding | stopping);

 
 
 

guarantee allRequestsAreSatisfaidEventually:
  GF (noRequests);
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  enteringStation := atStation & (PREV (!atStation));
  
  noTasks := shuttleTasks[0]=false & 
             shuttleTasks[1]=false & 
             shuttleTasks[2]=false & 
             shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & 
                       !pressedStationTwo & 
                       !pressedStationThree & 
                       !pressedStationFour;
  
  taskAtCurrentStation := (shuttleTasks[0] & station = 0) | 
                          (shuttleTasks[1] & station = 1) |
                          (shuttleTasks[2] & station = 2) | 
                          (shuttleTasks[3] & station = 3);   
  
  satisfiesTask := (station = 0 -> next(shuttleTasks[0]=false)) &
                   (station = 1 -> next(shuttleTasks[1]=false)) &
                   (station = 2 -> next(shuttleTasks[2]=false)) &
                   (station = 3 -> next(shuttleTasks[3]=false));
  
  addTasks := (pressedStationOne -> next(shuttleTasks[0]=true)) &
              (pressedStationTwo -> next(shuttleTasks[1]=true)) &
              (pressedStationThree -> next(shuttleTasks[2]=true)) &
              (pressedStationFour -> next(shuttleTasks[3]=true));
  
  keepTasksStatus := (!pressedStationOne   & (!atGivenStation(0) | shuttleTasks[0] = false) -> next(shuttleTasks[0]) = shuttleTasks[0]) &
                     (!pressedStationTwo   & (!atGivenStation(1) | shuttleTasks[1] = false) -> next(shuttleTasks[1]) = shuttleTasks[1]) &
                     (!pressedStationThree & (!atGivenStation(2) | shuttleTasks[2] = false) -> next(shuttleTasks[2]) = shuttleTasks[2]) &
                     (!pressedStationFour  & (!atGivenStation(3) | shuttleTasks[3] = false) -> next(shuttleTasks[3]) = shuttleTasks[3]);
  
  stationIncreased := PREV (next(station) - station = 1);
  stationDecreased := PREV (station - next(station) = 1);
  
 
 
 

assumption initialStateEnv:
  station = 0 & atStation & noPressedStations;
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding | backwarding, !atStation | stopping);

assumption
  G !enteringStation <-> next(station) = station;

assumption
  G enteringStation & PREV(forwarding) <-> stationIncreased;
 
assumption
  G enteringStation & PREV(backwarding) <-> stationDecreased;  

assumption
  pHolds_afterQuntilR(forwarding, !atStation , stationIncreased & atStation);

assumption
  pHolds_afterQuntilR(backwarding, !atStation , stationDecreased & atStation);

 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> (atStation = next(atStation)) & (station = next(station)));

assumption curStationNotPressedWhileAtStation: 
  G (atGivenStation(0) -> !pressedStationOne) & (atGivenStation(1) -> !pressedStationTwo) &
    (atGivenStation(2) -> !pressedStationThree) & (atGivenStation(3) -> !pressedStationFour);

assumption
  GF noPressedStations;
  
 
 
 
    
 
guarantee initialState:
  stopping & noTasks;

 
guarantee
  G enteringStation & taskAtCurrentStation -> stopping & satisfiesTask ;

guarantee
  G addTasks; 
  
 
 
 

 
guarantee
  G keepTasksStatus;

 
guarantee
  
  G atStation & noTasks -> stopping;
  
  
 
 
 
   
 
 
 

guarantee allTasksAreSatisfaidEventually:
  GF (noTasks);
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  enteringStation := atStation & (PREV (!atStation));
  
  noTasks := shuttleTasks[0]=false & 
             shuttleTasks[1]=false & 
             shuttleTasks[2]=false & 
             shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & 
                       !pressedStationTwo & 
                       !pressedStationThree & 
                       !pressedStationFour;
  
  taskAtCurrentStation := (shuttleTasks[0] & station = 0) | 
                          (shuttleTasks[1] & station = 1) |
                          (shuttleTasks[2] & station = 2) | 
                          (shuttleTasks[3] & station = 3);   
  
  satisfiesTask := (station = 0 -> next(shuttleTasks[0]=false)) &
                   (station = 1 -> next(shuttleTasks[1]=false)) &
                   (station = 2 -> next(shuttleTasks[2]=false)) &
                   (station = 3 -> next(shuttleTasks[3]=false));
  
  addTasks := (pressedStationOne -> next(shuttleTasks[0]=true)) &
              (pressedStationTwo -> next(shuttleTasks[1]=true)) &
              (pressedStationThree -> next(shuttleTasks[2]=true)) &
              (pressedStationFour -> next(shuttleTasks[3]=true));
  
  keepTasksStatus := (!pressedStationOne   & (!atGivenStation(0) | shuttleTasks[0] = false) -> next(shuttleTasks[0]) = shuttleTasks[0]) &
                     (!pressedStationTwo   & (!atGivenStation(1) | shuttleTasks[1] = false) -> next(shuttleTasks[1]) = shuttleTasks[1]) &
                     (!pressedStationThree & (!atGivenStation(2) | shuttleTasks[2] = false) -> next(shuttleTasks[2]) = shuttleTasks[2]) &
                     (!pressedStationFour  & (!atGivenStation(3) | shuttleTasks[3] = false) -> next(shuttleTasks[3]) = shuttleTasks[3]);
  
  stationIncreased := PREV (next(station) - station = 1);
  stationDecreased := PREV (station - next(station) = 1);
  
 
 
 

assumption initialStateEnv:
  station = 0 & atStation & noPressedStations;
 
 
assumption leaveStationEventually:
  pRespondsToS (forwarding | backwarding, !atStation | stopping);

assumption
  G !enteringStation <-> PREV (next(station) = station);

assumption
  G enteringStation & PREV(forwarding) <-> stationIncreased;
 
assumption
  G enteringStation & PREV(backwarding) <-> stationDecreased;  

 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> (atStation = next(atStation)) & (station = next(station)));
  
assumption
  pHolds_afterQuntilR(forwarding, !atStation , stationIncreased);

assumption
  pHolds_afterQuntilR(backwarding, !atStation , stationDecreased);



assumption curStationNotPressedWhileAtStation: 
  G (atGivenStation(0) -> !pressedStationOne) & (atGivenStation(1) -> !pressedStationTwo) &
    (atGivenStation(2) -> !pressedStationThree) & (atGivenStation(3) -> !pressedStationFour);

assumption
  GF noPressedStations;
  
 
 
 
    
 
guarantee initialState:
  stopping & noTasks;

 
guarantee
  G enteringStation & taskAtCurrentStation -> stopping & satisfiesTask ;

guarantee
  G addTasks; 
  
 
 
 

 
guarantee
  G keepTasksStatus;

 
guarantee
 
  G atStation & noTasks -> stopping;
  
 
 
  
   
  
   
 
 
 

guarantee allTasksAreSatisfaidEventually:
  GF (noTasks);
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  enteringStation := atStation & (PREV (!atStation));
  
  noTasks := shuttleTasks[0]=false & 
             shuttleTasks[1]=false & 
             shuttleTasks[2]=false & 
             shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & 
                       !pressedStationTwo & 
                       !pressedStationThree & 
                       !pressedStationFour;
  
  taskAtCurrentStation := (shuttleTasks[0] & station = 0) | 
                          (shuttleTasks[1] & station = 1) |
                          (shuttleTasks[2] & station = 2) | 
                          (shuttleTasks[3] & station = 3);   
  
  satisfiesTask := (station = 0 -> next(shuttleTasks[0]=false)) &
                   (station = 1 -> next(shuttleTasks[1]=false)) &
                   (station = 2 -> next(shuttleTasks[2]=false)) &
                   (station = 3 -> next(shuttleTasks[3]=false));
  
  addTasks := (pressedStationOne -> next(shuttleTasks[0]=true)) &
              (pressedStationTwo -> next(shuttleTasks[1]=true)) &
              (pressedStationThree -> next(shuttleTasks[2]=true)) &
              (pressedStationFour -> next(shuttleTasks[3]=true));
  
  keepTasksStatus := (!pressedStationOne   & (!atGivenStation(0) | shuttleTasks[0] = false) -> next(shuttleTasks[0]) = shuttleTasks[0]) &
                     (!pressedStationTwo   & (!atGivenStation(1) | shuttleTasks[1] = false) -> next(shuttleTasks[1]) = shuttleTasks[1]) &
                     (!pressedStationThree & (!atGivenStation(2) | shuttleTasks[2] = false) -> next(shuttleTasks[2]) = shuttleTasks[2]) &
                     (!pressedStationFour  & (!atGivenStation(3) | shuttleTasks[3] = false) -> next(shuttleTasks[3]) = shuttleTasks[3]);
  
  stationIncreased := PREV (next(station) - station = 1);
  stationDecreased := PREV (station - next(station) = 1);
  
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

 
 
 

 
assumption leaveStationEventually:
  pRespondsToS (atStation & (forwarding | backwarding), !atStation | stopping);

 
assumption inStationEventually:
  pRespondsToS (!atStation & (forwarding | backwarding), atStation | stopping);

assumption
  G !enteringStation <-> PREV (next(station) = station);
  
assumption
  G enteringStation & PREV(forwarding) <-> stationIncreased;
 
assumption
  G enteringStation & PREV(backwarding) <-> stationDecreased;  

 
assumption stationDoesNotChangeWhenStopping:
  G (stopping -> (atStation = next(atStation)) & (station = next(station)));
  
assumption
  pHolds_afterQuntilR(forwarding, !atStation , stationIncreased);

assumption
  pHolds_afterQuntilR(backwarding, !atStation , stationDecreased);

assumption curStationNotPressedWhileAtStation: 
  G (atGivenStation(0) -> !pressedStationOne) & (atGivenStation(1) -> !pressedStationTwo) &
    (atGivenStation(2) -> !pressedStationThree) & (atGivenStation(3) -> !pressedStationFour);

assumption
  GF noPressedStations;
  
 
 
 
    
 
guarantee initialState:
  stopping & noTasks;

 
guarantee
  G enteringStation & taskAtCurrentStation -> stopping & satisfiesTask ;

guarantee
  G addTasks; 
  
 
 
 

 
guarantee
  G keepTasksStatus;

 
guarantee
  G atStation & noTasks -> stopping;
   
 
 
 

guarantee allTasksAreSatisfaidEventually:
  GF (noTasks);
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := shuttleTasks[0]=false & 
             shuttleTasks[1]=false & 
             shuttleTasks[2]=false & 
             shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & 
                       !pressedStationTwo & 
                       !pressedStationThree & 
                       !pressedStationFour;
  
 
 
 
 
 
 
 
 
 

  taskWillBeFalse := 
    ((next(shuttleTasks[0]) = false) <->
            ((shuttleTasks[0]=false & !pressedStationOne) | 
            (shuttleTasks[0]=true & atGivenStation(0) & stopping))) &
    ((next(shuttleTasks[1]) = false) <->
            ((shuttleTasks[1]=false & !pressedStationTwo) | 
            (shuttleTasks[1]=true & atGivenStation(1) & stopping))) &
    ((next(shuttleTasks[2]) = false) <->
            ((shuttleTasks[2]=false & !pressedStationThree) | 
            (shuttleTasks[2]=true & atGivenStation(2) & stopping))) &
    ((next(shuttleTasks[3]) = false) <->
            ((shuttleTasks[3]=false & !pressedStationFour) | 
            (shuttleTasks[3]=true & atGivenStation(3) & stopping)));

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

assumption farwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);
  
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
 
 
 
 
 
 


 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G stationWillIncrease -> forwarding;

 
assumption
  G stationWillDecrease -> backwarding; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
  
assumption currentStationNotPressedWhileAtStation:
  G ((atGivenStation(0)) -> !pressedStationOne) &
    ((atGivenStation(1)) -> !pressedStationTwo) &
    ((atGivenStation(2)) -> !pressedStationThree) &
    ((atGivenStation(3)) -> !pressedStationFour) ;

 
 
 
 
 
 
 
 
 
 
 

 
 
 
    
 
guarantee initialState:
  stopping & noTasks;
  
guarantee
  G taskWillBeFalse;

/* NOTE: taskWillBeFalse force guarantee that we must stop in order to satisfy Task! */

 
 
 
 
 

 
 
 
 
 

 
 
 
 
 
guarantee
  G noTasks -> stopping;
   
guarantee
  G atGivenStation(0) -> !backwarding;

guarantee
  G atGivenStation(3) -> !forwarding;
 
 
 

 
guarantee
  GF shuttleTasks[0]=false;
guarantee
  GF shuttleTasks[1]=false;
guarantee
  GF shuttleTasks[2]=false;
guarantee
  GF shuttleTasks[3]=false;
 
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := shuttleTasks[0]=false & 
             shuttleTasks[1]=false & 
             shuttleTasks[2]=false & 
             shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & 
                       !pressedStationTwo & 
                       !pressedStationThree & 
                       !pressedStationFour;
   
  taskWillBeFalse := 
    ((next(shuttleTasks[0]) = false) <->
            ((shuttleTasks[0]=false & !pressedStationOne) | 
            (shuttleTasks[0]=true & atGivenStation(0) & stopping))) &
    ((next(shuttleTasks[1]) = false) <->
            ((shuttleTasks[1]=false & !pressedStationTwo) | 
            (shuttleTasks[1]=true & atGivenStation(1) & stopping))) &
    ((next(shuttleTasks[2]) = false) <->
            ((shuttleTasks[2]=false & !pressedStationThree) | 
            (shuttleTasks[2]=true & atGivenStation(2) & stopping ))) &
    ((next(shuttleTasks[3]) = false) <->
            ((shuttleTasks[3]=false & !pressedStationFour) | 
            (shuttleTasks[3]=true & atGivenStation(3) & stopping )));

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

assumption farwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);
  
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G stationWillIncrease -> forwarding;

 
assumption
  G stationWillDecrease -> backwarding; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
  
 
 
 
 
 


 
 
 
    
 
guarantee initialState:
  stopping & noTasks;
  
guarantee
  G taskWillBeFalse;

/* NOTE: taskWillBeFalse force guarantee that we must stop in order to satisfy Task! */

 
 
 
 
 

 
 
 
 
 
guarantee
  G noTasks -> stopping;
   
guarantee
  G atGivenStation(0) -> !backwarding;

guarantee
  G atGivenStation(3) -> !forwarding;
 
 
 

 
guarantee
  GF shuttleTasks[0]=false;
guarantee
  GF shuttleTasks[1]=false;
guarantee
  GF shuttleTasks[2]=false;
guarantee
  GF shuttleTasks[3]=false;
  

 
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := shuttleTasks[0]=false & 
             shuttleTasks[1]=false & 
             shuttleTasks[2]=false & 
             shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & 
                       !pressedStationTwo & 
                       !pressedStationThree & 
                       !pressedStationFour;
   
  taskWillBeFalse := 
    ((next(shuttleTasks[0]) = false) <->
            ((shuttleTasks[0]=false & !pressedStationOne) | 
            (shuttleTasks[0]=true & atGivenStation(0) & stopping))) &
    ((next(shuttleTasks[1]) = false) <->
            ((shuttleTasks[1]=false & !pressedStationTwo) | 
            (shuttleTasks[1]=true & atGivenStation(1) & stopping))) &
    ((next(shuttleTasks[2]) = false) <->
            ((shuttleTasks[2]=false & !pressedStationThree) | 
            (shuttleTasks[2]=true & atGivenStation(2) & stopping ))) &
    ((next(shuttleTasks[3]) = false) <->
            ((shuttleTasks[3]=false & !pressedStationFour) | 
            (shuttleTasks[3]=true & atGivenStation(3) & stopping )));

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

assumption farwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);
  
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G stationWillIncrease -> forwarding;

 
assumption
  G stationWillDecrease -> backwarding; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
  
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationOne)) &
    (next(atGivenStation(1)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(2)) -> next(!pressedStationThree)) &
    (next(atGivenStation(3)) -> next(!pressedStationFour));



 
 
 
    
 
guarantee initialState:
  stopping & noTasks;
  
guarantee
  G taskWillBeFalse;

/* NOTE: taskWillBeFalse force guarantee that we must stop in order to satisfy Task! */


 
 
 
 
 
guarantee
  G noTasks -> stopping;
   
guarantee
  G atGivenStation(0) -> !backwarding;

guarantee
  G atGivenStation(3) -> !forwarding;
  
 
 
 
 
 
 
 
 
 
 
 
 
 
  
 
gar
G !atStation -> !stopping;

 
gar
  G (forwarding -> next (!backwarding)) & (backwarding -> next (!forwarding));
    
 
 
 

 
guarantee
  GF shuttleTasks[0]=false;
guarantee
  GF shuttleTasks[1]=false;
guarantee
  GF shuttleTasks[2]=false;
guarantee
  GF shuttleTasks[3]=false;
  
  
  
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;
  

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := shuttleTasks[0]=false & shuttleTasks[1]=false & 
             shuttleTasks[2]=false & shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & !pressedStationTwo & 
                       !pressedStationThree & !pressedStationFour;
  
 
 
 
 
  
  updateTasks := 
    ((next(shuttleTasks[0]) = false) <->
            ((shuttleTasks[0]=false & !pressedStationOne) | 
            (shuttleTasks[0]=true & atGivenStation(0) & stopping))) &
    ((next(shuttleTasks[1]) = false) <->
            ((shuttleTasks[1]=false & !pressedStationTwo) | 
            (shuttleTasks[1]=true & atGivenStation(1) & stopping))) &
    ((next(shuttleTasks[2]) = false) <->
            ((shuttleTasks[2]=false & !pressedStationThree) | 
            (shuttleTasks[2]=true & atGivenStation(2) & stopping ))) &
    ((next(shuttleTasks[3]) = false) <->
            ((shuttleTasks[3]=false & !pressedStationFour) | 
            (shuttleTasks[3]=true & atGivenStation(3) & stopping )));

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  
                                  
  noTasksForward := (atGivenStation(0) & (shuttleTasks[1] = false & shuttleTasks[2] = false & shuttleTasks[3] = false)) |
                    (atGivenStation(1) & (shuttleTasks[2] = false & shuttleTasks[3] = false)) |
                    (atGivenStation(2) & (shuttleTasks[3] = false));
  
  noTasksBackward := (atGivenStation(3) & (shuttleTasks[2] = false & shuttleTasks[1] = false & shuttleTasks[0] = false)) |
                     (atGivenStation(2) & (shuttleTasks[1] = false & shuttleTasks[0] = false)) |
                     (atGivenStation(1) & (shuttleTasks[0] = false));
  
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G stationWillIncrease -> forwarding;

 
assumption
  G stationWillDecrease -> backwarding; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationOne)) &
    (next(atGivenStation(1)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(2)) -> next(!pressedStationThree)) &
    (next(atGivenStation(3)) -> next(!pressedStationFour));

 
 
 
    
 
guarantee initialState:
  stopping & noTasks;
  
 
guarantee
  G updateTasks;

 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks -> stopping;

 
guarantee
  G noTasksForward -> next(!forwarding);  

 
guarantee
  G noTasksBackward -> next(!backwarding); 
 
 
 
 
 
 
 
 

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (forwarding -> next (!backwarding)) & (backwarding -> next (!forwarding));
 
    
 
 
 

 
guarantee
  GF shuttleTasks[0]=false;
guarantee
  GF shuttleTasks[1]=false;
guarantee
  GF shuttleTasks[2]=false;
guarantee
  GF shuttleTasks[3]=false;
  
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;
  

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := shuttleTasks[0]=false & shuttleTasks[1]=false & 
             shuttleTasks[2]=false & shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & !pressedStationTwo & 
                       !pressedStationThree & !pressedStationFour;
  
  atStationWithTask := atStation & ((station = 0 & shuttleTasks[0]=true) |
                                    (station = 1 & shuttleTasks[1]=true) |
                                    (station = 2 & shuttleTasks[2]=true) |
                                    (station = 3 & shuttleTasks[3]=true));  
  
  updateTasks := 
    ((next(shuttleTasks[0]) = false) <->
            ((shuttleTasks[0]=false & !pressedStationOne) | 
            (shuttleTasks[0]=true & atGivenStation(0) & stopping))) &
    ((next(shuttleTasks[1]) = false) <->
            ((shuttleTasks[1]=false & !pressedStationTwo) | 
            (shuttleTasks[1]=true & atGivenStation(1) & stopping))) &
    ((next(shuttleTasks[2]) = false) <->
            ((shuttleTasks[2]=false & !pressedStationThree) | 
            (shuttleTasks[2]=true & atGivenStation(2) & stopping ))) &
    ((next(shuttleTasks[3]) = false) <->
            ((shuttleTasks[3]=false & !pressedStationFour) | 
            (shuttleTasks[3]=true & atGivenStation(3) & stopping )));

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  
                                  
  noTasksForwardAndExistsTaskBackward := 
                    ((atGivenStation(1) & (shuttleTasks[1] = false & shuttleTasks[2] = false & shuttleTasks[3] = false) &  (shuttleTasks[0] = true)) |
                     (atGivenStation(2) & (shuttleTasks[2] = false & shuttleTasks[3] = false) & (shuttleTasks[1] = true | shuttleTasks[0] = true)));
  
  noTasksBackwardAndExistsTaskForward := 
                    ((atGivenStation(2) & (shuttleTasks[2] = false & shuttleTasks[1] = false & shuttleTasks[0] = false) & (shuttleTasks[3] = true)) |
                     (atGivenStation(1) & (shuttleTasks[1] = false & shuttleTasks[0] = false) & (shuttleTasks[2] = true| shuttleTasks[3] = true)));
   
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationOne)) &
    (next(atGivenStation(1)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(2)) -> next(!pressedStationThree)) &
    (next(atGivenStation(3)) -> next(!pressedStationFour));

 
 
 
    
 
guarantee initialState:
  stopping & noTasks;
  
 
guarantee
  G updateTasks;

 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks -> stopping;

 
guarantee
  G noTasksForwardAndExistsTaskBackward -> backwarding;  

 
guarantee
  G noTasksBackwardAndExistsTaskForward -> forwarding; 
  
guarantee
  G atStationWithTask -> stopping;

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (forwarding -> next (!backwarding)) & (backwarding -> next (!forwarding));
 
    
 
 
 

 
guarantee
  GF shuttleTasks[0]=false;
guarantee
  GF shuttleTasks[1]=false;
guarantee
  GF shuttleTasks[2]=false;
guarantee
  GF shuttleTasks[3]=false;
  
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;

env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean pressedStationFour;

sys MotorCmd motors;
sys boolean[4] shuttleTasks;

type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;
  

define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := shuttleTasks[0]=false & shuttleTasks[1]=false & 
             shuttleTasks[2]=false & shuttleTasks[3]=false;
  
  noPressedStations := !pressedStationOne & !pressedStationTwo & 
                       !pressedStationThree & !pressedStationFour;
  
  atStationWithTask := atStation & ((station = 0 & shuttleTasks[0]=true) |
                                    (station = 1 & shuttleTasks[1]=true) |
                                    (station = 2 & shuttleTasks[2]=true) |
                                    (station = 3 & shuttleTasks[3]=true));  
  
  updateTasks := 
    ((next(shuttleTasks[0]) = false) <->
            ((shuttleTasks[0]=false & !pressedStationOne) | 
            (shuttleTasks[0]=true & atGivenStation(0) & stopping))) &
    ((next(shuttleTasks[1]) = false) <->
            ((shuttleTasks[1]=false & !pressedStationTwo) | 
            (shuttleTasks[1]=true & atGivenStation(1) & stopping))) &
    ((next(shuttleTasks[2]) = false) <->
            ((shuttleTasks[2]=false & !pressedStationThree) | 
            (shuttleTasks[2]=true & atGivenStation(2) & stopping ))) &
    ((next(shuttleTasks[3]) = false) <->
            ((shuttleTasks[3]=false & !pressedStationFour) | 
            (shuttleTasks[3]=true & atGivenStation(3) & stopping )));

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  
                                  
  noTasksForward := ((atGivenStation(0) & (shuttleTasks[1] = false & shuttleTasks[2] = false & shuttleTasks[3] = false)) |
                    (atGivenStation(1) &  (shuttleTasks[2] = false & shuttleTasks[3] = false)) |
                    (atGivenStation(2) &  (shuttleTasks[3] = false)));
  
  noTasksBackward := ((atGivenStation(3) & (shuttleTasks[2] = false & shuttleTasks[1] = false & shuttleTasks[0] = false)) | 
                     (atGivenStation(2) &  (shuttleTasks[1] = false & shuttleTasks[0] = false)) |
                     (atGivenStation(1) &  (shuttleTasks[0] = false)));
                      
  noTaskAtCurrentStation := (atGivenStation(0) & shuttleTasks[0] = false) | 
                            (atGivenStation(1) & shuttleTasks[1] = false) |
                            (atGivenStation(2) & shuttleTasks[2] = false) | 
                            (atGivenStation(3) & shuttleTasks[3] = false);                       
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationOne)) &
    (next(atGivenStation(1)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(2)) -> next(!pressedStationThree)) &
    (next(atGivenStation(3)) -> next(!pressedStationFour));

 
 
 
    
 
guarantee initialState:
  stopping & noTasks;
  
 
guarantee
  G updateTasks;

 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks -> stopping;
  
 
guarantee
  G atStationWithTask -> stopping;

 
guarantee
  G noTasksForward -> (!forwarding);  

 
guarantee
  G noTasksBackward -> (!backwarding); 

 
guarantee
  G (noTaskAtCurrentStation & !noTasks) -> (!stopping);                              

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (!stopping -> (next(motors) = motors | next(stopping)));

 
 
 

 
guarantee
  GF shuttleTasks[0]=false;
guarantee
  GF shuttleTasks[1]=false;
guarantee
  GF shuttleTasks[2]=false;
guarantee
  GF shuttleTasks[3]=false;
  
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;
 
 

env boolean pressedStationZero;
env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;

sys MotorCmd motors;
 
 

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;


define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := !taskAtStationZero & !taskAtStationOne & !taskAtStationTwo & !taskAtStationThree;
  
  noPressedStations := !pressedStationZero & !pressedStationOne & !pressedStationTwo & !pressedStationThree;
  
  atStationWithTask := atStation & ((station = 0 & taskAtStationZero) |
                                    (station = 1 & taskAtStationOne) |
                                    (station = 2 & taskAtStationTwo) |
                                    (station = 3 & taskAtStationThree));  

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
                                  
  noTasksForward := ((atGivenStation(0) & (!taskAtStationOne & !taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(1) &  (!taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(2) &  (!taskAtStationThree)));
  
  noTasksBackward := ((atGivenStation(3) & (!taskAtStationTwo & !taskAtStationOne & !taskAtStationZero)) | 
                     (atGivenStation(2) &  (!taskAtStationOne & !taskAtStationZero)) |
                     (atGivenStation(1) &  (!taskAtStationZero)));
                                        
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations;

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationZero)) &
    (next(atGivenStation(1)) -> next(!pressedStationOne)) &
    (next(atGivenStation(2)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(3)) -> next(!pressedStationThree));

 
 
 

 
 
 
    
 
guarantee initialState:
  stopping;



 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks -> stopping;
  
 
guarantee
  G atStationWithTask -> stopping;

 
guarantee
  G noTasksForward -> (!forwarding);  

 
guarantee
  G noTasksBackward -> (!backwarding); 

 
guarantee
  G (!atStationWithTask & !noTasks) -> (!stopping);                              
 

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (!stopping -> (next(motors) = motors | next(stopping)));

 
 
 

 
guarantee
  GF !taskAtStationZero;

guarantee
  GF !taskAtStationOne;

guarantee
  GF !taskAtStationTwo;

guarantee
  GF !taskAtStationThree;

  
  
monitor boolean taskAtStationZero {
   
  !taskAtStationZero;
   
  G pressedStationZero -> next(taskAtStationZero) = true;
   
  G (atGivenStation(0) & taskAtStationZero & !pressedStationZero) -> next(taskAtStationZero) = false;
   
  G ((atGivenStation(0) & !taskAtStationZero & !pressedStationZero)) -> (next(taskAtStationZero) = taskAtStationZero);
  G (!atGivenStation(0) & !pressedStationZero) -> (next(taskAtStationZero) = taskAtStationZero); 
}
  
monitor boolean taskAtStationOne {
   
  !taskAtStationOne;
   
  G pressedStationOne -> next(taskAtStationOne) = true;
   
  G (atGivenStation(1) & taskAtStationOne & !pressedStationOne) -> next(taskAtStationOne) = false;
   
  G (atGivenStation(1) & !taskAtStationOne & !pressedStationOne) -> (next(taskAtStationOne) = taskAtStationOne); 
  G (!atGivenStation(1) & !pressedStationOne) -> (next(taskAtStationOne) = taskAtStationOne); 
} 

monitor boolean taskAtStationTwo {
   
  !taskAtStationTwo;
   
  G pressedStationTwo -> next(taskAtStationTwo) = true;
   
  G (atGivenStation(2) & taskAtStationTwo & !pressedStationTwo) -> next(taskAtStationTwo) = false;
   
  G (atGivenStation(2) & !taskAtStationTwo & !pressedStationTwo) -> (next(taskAtStationTwo) = taskAtStationTwo); 
  G (!atGivenStation(2) & !pressedStationTwo) -> (next(taskAtStationTwo) = taskAtStationTwo); 
}

monitor boolean taskAtStationThree {
   
  !taskAtStationThree;
   
  G pressedStationThree -> next(taskAtStationThree) = true;
   
  G (atGivenStation(3) & taskAtStationThree & !pressedStationThree) -> next(taskAtStationThree) = false;
   
  G (atGivenStation(3) & !taskAtStationThree & !pressedStationThree) -> (next(taskAtStationThree) = taskAtStationThree); 
  G (!atGivenStation(3) & !pressedStationThree) -> (next(taskAtStationThree) = taskAtStationThree); 
}

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;
env Button emgButton;
 

env boolean pressedStationZero;
env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;

sys MotorCmd motors;
 

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;


define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := !taskAtStationZero & !taskAtStationOne & !taskAtStationTwo & !taskAtStationThree;
  
  noPressedStations := !pressedStationZero & !pressedStationOne & !pressedStationTwo & !pressedStationThree;
  
  atStationWithTask := atStation & ((station = 0 & taskAtStationZero) |
                                    (station = 1 & taskAtStationOne) |
                                    (station = 2 & taskAtStationTwo) |
                                    (station = 3 & taskAtStationThree));  

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
                                  
  noTasksForward := ((atGivenStation(0) & (!taskAtStationOne & !taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(1) &  (!taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(2) &  (!taskAtStationThree)));
  
  noTasksBackward := ((atGivenStation(3) & (!taskAtStationTwo & !taskAtStationOne & !taskAtStationZero)) | 
                     (atGivenStation(2) &  (!taskAtStationOne & !taskAtStationZero)) |
                     (atGivenStation(1) &  (!taskAtStationZero)));
                                        
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations & emgButton = RELEASED;

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationZero)) &
    (next(atGivenStation(1)) -> next(!pressedStationOne)) &
    (next(atGivenStation(2)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(3)) -> next(!pressedStationThree));

 
assumption notAlwaysAtEmgState:
GF !atEmgState; 

 
 
 
    
 
guarantee initialState:
  stopping;

monitor boolean atEmgState {
   
  !atEmgState;
   
  G (!atStation & atEmgState) -> next(atEmgState);
   
  G (atStation | (!atStation & !atEmgState)) -> (emgButton = PRESSED <-> (next(atEmgState)=!atEmgState));
} 

guarantee
  G atStation & atEmgState -> stopping;

 
guarantee
  G atStationWithTask -> stopping;

 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks & atStation -> stopping;
  
 
guarantee
  G noTasksForward -> !forwarding;  

 
guarantee
  G noTasksBackward -> !backwarding; 

 
guarantee
  G (atStation & !atStationWithTask & !noTasks) -> !stopping; 

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (!stopping -> (next(motors) = motors | next(stopping)));

 
 
 

 
guarantee
  GF !taskAtStationZero;

guarantee
  GF !taskAtStationOne;

guarantee
  GF !taskAtStationTwo;

guarantee
  GF !taskAtStationThree;
  
  
monitor boolean taskAtStationZero {
   
  !taskAtStationZero;
   
  G (pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = true);
   
  G (atGivenStation(0) & taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (atGivenStation(0) & !taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero);
  G (!atGivenStation(0) & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero); 
}
  
monitor boolean taskAtStationOne {
   
  !taskAtStationOne;
   
  G (pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = true);
   
  G (atGivenStation(1) & taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = false);
    
  G (next(atEmgState)) -> (next(taskAtStationOne) = false);
   
  G (atGivenStation(1) & !taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
  G (!atGivenStation(1) & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
} 

monitor boolean taskAtStationTwo {
   
  !taskAtStationTwo;
   
  G (pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = true);
   
  G (atGivenStation(2) & taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (atGivenStation(2) & !taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
  G (!atGivenStation(2) & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
}

monitor boolean taskAtStationThree {
   
  !taskAtStationThree;
   
  G (pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = true);
   
  G (atGivenStation(3) & taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (atGivenStation(3) & !taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
  G (!atGivenStation(3) & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
}

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;
env Button emgButton;
env boolean readyToEmgBeep;

env boolean pressedStationZero;
env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;

sys MotorCmd motors;
sys boolean emgBeepProcessReq;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;


define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := !taskAtStationZero & !taskAtStationOne & !taskAtStationTwo & !taskAtStationThree;
  
  noPressedStations := !pressedStationZero & !pressedStationOne & !pressedStationTwo & !pressedStationThree;
  
  atStationWithTask := atStation & ((station = 0 & taskAtStationZero) |
                                    (station = 1 & taskAtStationOne) |
                                    (station = 2 & taskAtStationTwo) |
                                    (station = 3 & taskAtStationThree));  

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
                                  
  noTasksForward := ((atGivenStation(0) & (!taskAtStationOne & !taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(1) &  (!taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(2) &  (!taskAtStationThree)));
  
  noTasksBackward := ((atGivenStation(3) & (!taskAtStationTwo & !taskAtStationOne & !taskAtStationZero)) | 
                     (atGivenStation(2) &  (!taskAtStationOne & !taskAtStationZero)) |
                     (atGivenStation(1) &  (!taskAtStationZero)));
                                        
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations & emgButton = RELEASED & !readyToEmgBeep;

 
assumption beeperReturnsAnswerEventually:
pRespondsToS (waitingForEmgBeeper, readyToEmgBeep);

 
assumption
  G (next(readyToEmgBeep) -> (waitingForEmgBeeper & !readyToEmgBeep));

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationZero)) &
    (next(atGivenStation(1)) -> next(!pressedStationOne)) &
    (next(atGivenStation(2)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(3)) -> next(!pressedStationThree));

 
assumption notAlwaysAtEmgState:
GF !atEmgState; 

 
 
 
    
 
guarantee initialState:
  stopping;

monitor boolean atEmgState {
   
  !atEmgState;
   
  G (!atStation & atEmgState) -> next(atEmgState);
   
  G (atStation | (!atStation & !atEmgState)) -> (emgButton = PRESSED <-> (next(atEmgState)=!atEmgState));
} 

/**
 * monitor waitingForEmgBeeper is true when startBeepTimer is true 
 * and readyToBeep ack hasn't been received yet
 */
monitor boolean waitingForEmgBeeper {
   
  !waitingForEmgBeeper;
   
  G (emgBeepProcessReq -> next(waitingForEmgBeeper));
   
  G (readyToEmgBeep -> (next(!waitingForEmgBeeper) | emgBeepProcessReq));
   
  G (!emgBeepProcessReq & !readyToEmgBeep -> waitingForEmgBeeper = next(waitingForEmgBeeper));
} 

 
guarantee beepIffEnteringStationOrReadyToBeepAtStation:
G ((atEmgState & PREV(willEnterStation))|(atStation & readyToEmgBeep & atEmgState)) <-> emgBeepProcessReq;

guarantee
  G atStation & atEmgState -> stopping;

 
guarantee
  G atStationWithTask -> stopping;

 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks & atStation -> stopping;
  
 
guarantee
  G noTasksForward -> !forwarding;  

 
guarantee
  G noTasksBackward -> !backwarding; 

 
guarantee
  G (atStation & !atStationWithTask & !noTasks) -> !stopping; 

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (!stopping -> (next(motors) = motors | next(stopping)));

 
 
 

 
guarantee
  GF !taskAtStationZero;

guarantee
  GF !taskAtStationOne;

guarantee
  GF !taskAtStationTwo;

guarantee
  GF !taskAtStationThree;
  
  
monitor boolean taskAtStationZero {
   
  !taskAtStationZero;
   
  G (pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = true);
   
  G (atGivenStation(0) & taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (atGivenStation(0) & !taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero);
  G (!atGivenStation(0) & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero); 
}
  
monitor boolean taskAtStationOne {
   
  !taskAtStationOne;
   
  G (pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = true);
   
  G (atGivenStation(1) & taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = false);
    
  G (next(atEmgState)) -> (next(taskAtStationOne) = false);
   
  G (atGivenStation(1) & !taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
  G (!atGivenStation(1) & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
} 

monitor boolean taskAtStationTwo {
   
  !taskAtStationTwo;
   
  G (pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = true);
   
  G (atGivenStation(2) & taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (atGivenStation(2) & !taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
  G (!atGivenStation(2) & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
}

monitor boolean taskAtStationThree {
   
  !taskAtStationThree;
   
  G (pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = true);
   
  G (atGivenStation(3) & taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (atGivenStation(3) & !taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
  G (!atGivenStation(3) & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
}

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;
env Button emgButton;
env boolean readyToEmgBeep;

env boolean pressedStationZero;
env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean longTimeWithoutReqs;

sys MotorCmd motors;
sys boolean emgBeepProcessReq;
sys boolean countTimeSinceReqs;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;


define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  atBaseStation := atGivenStation(0);
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := !taskAtStationZero & !taskAtStationOne & !taskAtStationTwo & !taskAtStationThree;
  
  noPressedStations := !pressedStationZero & !pressedStationOne & !pressedStationTwo & !pressedStationThree;
  
  atStationWithTask := atStation & ((station = 0 & taskAtStationZero) |
                                    (station = 1 & taskAtStationOne) |
                                    (station = 2 & taskAtStationTwo) |
                                    (station = 3 & taskAtStationThree));  

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
                                  
  noTasksForward := ((atGivenStation(0) & (!taskAtStationOne & !taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(1) &  (!taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(2) &  (!taskAtStationThree)));
  
  noTasksBackward := ((atGivenStation(3) & (!taskAtStationTwo & !taskAtStationOne & !taskAtStationZero)) | 
                     (atGivenStation(2) &  (!taskAtStationOne & !taskAtStationZero)) |
                     (atGivenStation(1) &  (!taskAtStationZero)));
                                        
 
 
 

assumption initialStateEnv:
 station = 0 & atStation & noPressedStations & emgButton = RELEASED & !readyToEmgBeep & !longTimeWithoutReqs;

 
assumption beeperReturnsAnswerEventually:
pRespondsToS (waitingForEmgBeeper, readyToEmgBeep);

 
assumption
  G (next(readyToEmgBeep) -> (waitingForEmgBeeper & !readyToEmgBeep));

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationZero)) &
    (next(atGivenStation(1)) -> next(!pressedStationOne)) &
    (next(atGivenStation(2)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(3)) -> next(!pressedStationThree));

 
assumption notAlwaysAtEmgState:
GF !atEmgState; 

 
 
 
    
 
guarantee initialState:
  stopping & countTimeSinceReqs;

monitor boolean atEmgState {
   
  !atEmgState;
   
  G (!atStation & atEmgState) -> next(atEmgState);
   
  G (atStation | (!atStation & !atEmgState)) -> (emgButton = PRESSED <-> (next(atEmgState)=!atEmgState));
} 

/**
 * monitor waitingForEmgBeeper is true when startBeepTimer is true 
 * and readyToBeep ack hasn't been received yet
 */
monitor boolean waitingForEmgBeeper {
   
  !waitingForEmgBeeper;
   
  G (emgBeepProcessReq -> next(waitingForEmgBeeper));
   
  G (readyToEmgBeep -> (next(!waitingForEmgBeeper) | emgBeepProcessReq));
   
  G (!emgBeepProcessReq & !readyToEmgBeep -> waitingForEmgBeeper = next(waitingForEmgBeeper));
} 

 
guarantee beepIffEnteringStationOrReadyToBeepAtStation:
G ((atEmgState & PREV(willEnterStation))|(atStation & readyToEmgBeep & atEmgState)) <-> emgBeepProcessReq;

guarantee
  G atStation & atEmgState -> stopping;

 
guarantee
  G atStationWithTask -> stopping;

guarantee
  G noPressedStations & !atEmgState <-> countTimeSinceReqs;

 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks & atStation & !goToBaseStation -> stopping;
  
  
guarantee
  G noTasks & atBaseStation -> stopping;
  
 
guarantee
  G noTasksForward -> !forwarding;  

 
guarantee
  G noTasksBackward & !goToBaseStation -> !backwarding; 

 
guarantee
  G (!goToBaseStation & atStation & !atStationWithTask & !noTasks) -> !stopping; 

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (!stopping -> (next(motors) = motors | next(stopping)));

 
 
 

 
guarantee
  GF !taskAtStationZero;

guarantee
  GF !taskAtStationOne;

guarantee
  GF !taskAtStationTwo;

guarantee
  GF !taskAtStationThree;

guarantee  
  GF !goToBaseStation;


monitor boolean goToBaseStation {
  !goToBaseStation;
  G (noTasks & longTimeWithoutReqs & !atEmgState & !atBaseStation) -> next(goToBaseStation);
  G atBaseStation -> next(!goToBaseStation);
  G (atStation & !noTasks) -> next(!goToBaseStation);
  G atEmgState -> next(!goToBaseStation);
  G (!atBaseStation & !atEmgState & (!atStation|noTasks) & (!longTimeWithoutReqs|!noTasks)) -> next(goToBaseStation) = goToBaseStation;
}

monitor boolean taskAtStationZero {
   
  !taskAtStationZero;
   
  G (pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = true);
   
  G (atGivenStation(0) & taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (atGivenStation(0) & !taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero);
  G (!atGivenStation(0) & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero); 
}
  
monitor boolean taskAtStationOne {
   
  !taskAtStationOne;
   
  G (pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = true);
   
  G (atGivenStation(1) & taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = false);
    
  G (next(atEmgState)) -> (next(taskAtStationOne) = false);
   
  G (atGivenStation(1) & !taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
  G (!atGivenStation(1) & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
} 

monitor boolean taskAtStationTwo {
   
  !taskAtStationTwo;
   
  G (pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = true);
   
  G (atGivenStation(2) & taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (atGivenStation(2) & !taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
  G (!atGivenStation(2) & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
}

monitor boolean taskAtStationThree {
   
  !taskAtStationThree;
   
  G (pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = true);
   
  G (atGivenStation(3) & taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (atGivenStation(3) & !taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
  G (!atGivenStation(3) & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
}

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Int(0..3) station;
env boolean atStation;
env Button emgButton;
env boolean readyToEmgBeep;
env boolean pressedStationZero;
env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean longTimeWithoutReqs;
env boolean doorAck;

sys MotorCmd motors;
sys boolean emgBeepProcessReq;
sys boolean countTimeSinceReqs;
sys boolean doorReq;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type DoorOp = {OPEN_OP, CLOSE_OP, NIL};
type DoorStatus = {OPEN, CLOSE, IN_PROCESS};

predicate atGivenStation(Int(0..3) index):
  atStation & station=index;


define 
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  atBaseStation := atGivenStation(0);
  
  willEnterStation := !atStation & next(atStation);
  
  noTasks := !taskAtStationZero & !taskAtStationOne & !taskAtStationTwo & !taskAtStationThree;
  
  noPressedStations := !pressedStationZero & !pressedStationOne & !pressedStationTwo & !pressedStationThree;
  
  atStationWithTask := atStation & ((station = 0 & taskAtStationZero) |
                                    (station = 1 & taskAtStationOne) |
                                    (station = 2 & taskAtStationTwo) |
                                    (station = 3 & taskAtStationThree));  

  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
                                  
  noTasksForward := ((atGivenStation(0) & (!taskAtStationOne & !taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(1) &  (!taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(2) &  (!taskAtStationThree)));
  
  noTasksBackward := ((atGivenStation(3) & (!taskAtStationTwo & !taskAtStationOne & !taskAtStationZero)) | 
                     (atGivenStation(2) &  (!taskAtStationOne & !taskAtStationZero)) |
                     (atGivenStation(1) &  (!taskAtStationZero)));
                                        
 
 
 

assumption initialStateEnv:
 atGivenStation(0) & noPressedStations & emgButton = RELEASED 
            & !readyToEmgBeep & !longTimeWithoutReqs & !doorAck;

 
assumption beeperReturnsAnswerEventually:
pRespondsToS (waitingForEmgBeeper, readyToEmgBeep);

 
assumption
  G (next(readyToEmgBeep) -> (waitingForEmgBeeper & !readyToEmgBeep));

 
assumption forwardingCauseStationIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption 
  G !willEnterStation -> next(station) = station;

 
assumption
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption
  G (next(station)= station) | (next(station)= station +1) | (next(station)= station-1); 

 
assumption stationDoesNotChangeWhenStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationNotPressedWhileAtStation:
  G (next(atGivenStation(0)) -> next(!pressedStationZero)) &
    (next(atGivenStation(1)) -> next(!pressedStationOne)) &
    (next(atGivenStation(2)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(3)) -> next(!pressedStationThree));

 
assumption notAlwaysAtEmgState:
GF !atEmgState; 

 
 
 
    
 
guarantee initialState:
  stopping & countTimeSinceReqs & !doorReq;

monitor boolean atEmgState {
   
  !atEmgState;
   
  G (!atStation & atEmgState) -> next(atEmgState);
   
  G (atStation | (!atStation & !atEmgState)) -> (emgButton = PRESSED <-> (next(atEmgState)=!atEmgState));
} 

/**
 * monitor waitingForEmgBeeper is true when startBeepTimer is true 
 * and readyToBeep ack hasn't been received yet
 */
monitor boolean waitingForEmgBeeper {
   
  !waitingForEmgBeeper;
   
  G (emgBeepProcessReq -> next(waitingForEmgBeeper));
   
  G (readyToEmgBeep -> (next(!waitingForEmgBeeper) | emgBeepProcessReq));
   
  G (!emgBeepProcessReq & !readyToEmgBeep -> waitingForEmgBeeper = next(waitingForEmgBeeper));
} 

 
guarantee beepIffEnteringStationOrReadyToBeepAtStation:
G ((atEmgState & PREV(willEnterStation))|(atStation & readyToEmgBeep & atEmgState)) <-> emgBeepProcessReq;

guarantee
  G atStation & atEmgState -> stopping;

 
guarantee
  G atStationWithTask -> stopping;

guarantee
  G noPressedStations & !atEmgState <-> countTimeSinceReqs;


 
 
 
  
 
guarantee
  G atGivenStation(0) -> !backwarding;

 
guarantee
  G atGivenStation(3) -> !forwarding;

 
guarantee
  G noTasks & atStation & !goToBaseStation -> stopping;
  
  
guarantee
  G noTasks & atBaseStation -> stopping;
  
 
guarantee
  G noTasksForward -> !forwarding;  

 
guarantee
  G noTasksBackward & !goToBaseStation -> !backwarding; 

 
guarantee
  G (!goToBaseStation & atStation & !atStationWithTask & !noTasks & !waitingForDoor) -> !stopping; 

 
guarantee
G !atStation -> !stopping;

 
guarantee
  G (!stopping -> (next(motors) = motors | next(stopping)));


 
 
 
 

 
guarantee
  GF !taskAtStationZero;

guarantee
  GF !taskAtStationOne;

guarantee
  GF !taskAtStationTwo;

guarantee
  GF !taskAtStationThree;

guarantee  
  GF !goToBaseStation;


monitor boolean goToBaseStation {
   
  !goToBaseStation;
   
  G (noTasks & longTimeWithoutReqs & !atEmgState & !atBaseStation) -> next(goToBaseStation);
   
  G atBaseStation -> next(!goToBaseStation);
  G (atStation & !noTasks) -> next(!goToBaseStation);
  G atEmgState -> next(!goToBaseStation);
   
  G (!atBaseStation & !atEmgState & (!atStation|noTasks) & (!longTimeWithoutReqs|!noTasks)) -> next(goToBaseStation) = goToBaseStation;
}

monitor boolean taskAtStationZero {
   
  !taskAtStationZero;
   
  G (pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = true);
   
  G (atGivenStation(0) & taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (atGivenStation(0) & !taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero);
  G (!atGivenStation(0) & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = taskAtStationZero); 
}
  
monitor boolean taskAtStationOne {
   
  !taskAtStationOne;
   
  G (pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = true);
   
  G (atGivenStation(1) & taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = false);
    
  G (next(atEmgState)) -> (next(taskAtStationOne) = false);
   
  G (atGivenStation(1) & !taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
  G (!atGivenStation(1) & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = taskAtStationOne); 
} 

monitor boolean taskAtStationTwo {
   
  !taskAtStationTwo;
   
  G (pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = true);
   
  G (atGivenStation(2) & taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (atGivenStation(2) & !taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
  G (!atGivenStation(2) & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = taskAtStationTwo); 
}

monitor boolean taskAtStationThree {
   
  !taskAtStationThree;
   
  G (pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = true);
   
  G (atGivenStation(3) & taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (atGivenStation(3) & !taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
  G (!atGivenStation(3) & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = taskAtStationThree); 
}





monitor boolean waitingForDoor{
  !waitingForDoor;
  G doorReq -> next(waitingForDoor);
  G doorAck -> next(!waitingForDoor);
  G !doorReq & !doorAck -> (next(waitingForDoor)= waitingForDoor);
}

assumption 
pRespondsToS (waitingForDoor, doorAck);

 
assumption
  G (next(doorAck) -> (waitingForDoor & !doorAck));

 
guarantee
G (!waitingForDoor & ((atStation & atEmgState & openDoorAtEmgState)| atStationWithTask)) <-> doorReq; 

gar
G waitingForDoor -> stopping;


monitor boolean openDoorAtEmgState {
  ! openDoorAtEmgState;
  G next(atEmgState) & !atEmgState -> next(openDoorAtEmgState);
  G atEmgState & doorReq -> next(!openDoorAtEmgState);
  G (!atEmgState | !doorReq) & (next(!atEmgState) | atEmgState)-> next(openDoorAtEmgState) = openDoorAtEmgState;
}
  
import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

 
env Int(0..3) station;
env boolean atStation;
env Button emgButton;
env boolean readyToEmgBeep;
env boolean pressedStationZero;
env boolean pressedStationOne;
env boolean pressedStationTwo;
env boolean pressedStationThree;
env boolean longTimeWithoutReqs;
env boolean doorAck;
env boolean mPressedStationZero;
env boolean mPressedStationOne;
env boolean mPressedStationTwo;
env boolean mPressedStationThree;

 
sys MotorCmd motors;
sys boolean emgBeepProcessReq;
sys boolean countTimeSinceReqs;
sys boolean doorReq;

 
type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};

 
predicate atGivenStation(Int(0..3) index):
  atStation & station=index;

 
define 
  
   
  stopping := motors = STOP;
  forwarding := motors = FWD;
  backwarding := motors = BWD;
  
   
  atBaseStation := atGivenStation(0);
  stationWillIncrease := next(station) = station+1;
  stationWillDecrease := next(station) = station-1;
  willEnterStation := !atStation & next(atStation);
  
   
  noPressedStations := !pressedStationZero & !pressedStationOne & !pressedStationTwo & !pressedStationThree;
  noMpressedStations := !mPressedStationZero & !mPressedStationOne & !mPressedStationTwo & !mPressedStationThree;
  
   
  noTasks := !taskAtStationZero & !taskAtStationOne & !taskAtStationTwo & !taskAtStationThree;
  atStationWithTask := atStation & ((station = 0 & taskAtStationZero) |
                                    (station = 1 & taskAtStationOne) |
                                    (station = 2 & taskAtStationTwo) |
                                    (station = 3 & taskAtStationThree));                    
  noTasksForward := ((atGivenStation(0) & (!taskAtStationOne & !taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(1) &  (!taskAtStationTwo & !taskAtStationThree)) |
                    (atGivenStation(2) &  (!taskAtStationThree)));
  noTasksBackward := ((atGivenStation(3) & (!taskAtStationTwo & !taskAtStationOne & !taskAtStationZero)) | 
                     (atGivenStation(2) &  (!taskAtStationOne & !taskAtStationZero)) |
                     (atGivenStation(1) &  (!taskAtStationZero)));


 
 
 

/**
 * monitor taskAtStationZero is true when there is a task at station zero
 */
monitor boolean taskAtStationZero {
   
  !taskAtStationZero;
   
  G (pressedStationZero & !next(atEmgState) & !next(maintenanceAtStationZero)) -> (next(taskAtStationZero) = true);
   
  G (atGivenStation(0) & taskAtStationZero & !pressedStationZero & !next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationZero) = false);
   
  G ((!pressedStationZero | next(maintenanceAtStationZero)) &
    (!atGivenStation(0) | !taskAtStationZero | pressedStationZero) &
    (next(!atEmgState))) -> (next(taskAtStationZero) = taskAtStationZero); 
}

/**
 * monitor taskAtStationOne is true when there is a task at station one
 */
monitor boolean taskAtStationOne {
   
  !taskAtStationOne;
   
  G (pressedStationOne & next(!atEmgState) & next(!maintenanceAtStationOne)) -> (next(taskAtStationOne) = true);
   
  G (atGivenStation(1) & taskAtStationOne & !pressedStationOne & !next(atEmgState)) -> (next(taskAtStationOne) = false);
    
  G (next(atEmgState)) -> (next(taskAtStationOne) = false);
   
  G ((!pressedStationOne | next(maintenanceAtStationOne)) &
    (!atGivenStation(1) | !taskAtStationOne | pressedStationOne) &
    (next(!atEmgState))) -> (next(taskAtStationOne) = taskAtStationOne); 
} 

/**
 * monitor taskAtStationTwo is true when there is a task at station two
 */
monitor boolean taskAtStationTwo {
   
  !taskAtStationTwo;
   
  G (pressedStationTwo & !next(atEmgState) & !next(maintenanceAtStationTwo)) -> (next(taskAtStationTwo) = true);
   
  G (atGivenStation(2) & taskAtStationTwo & !pressedStationTwo & !next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationTwo) = false);
   
  G ((!pressedStationTwo | next(maintenanceAtStationTwo)) &
    (!atGivenStation(2) | !taskAtStationTwo | pressedStationTwo) &
    (next(!atEmgState))) -> (next(taskAtStationTwo) = taskAtStationTwo); 
}

/**
 * monitor taskAtStationThree is true when there is a task at station three
 */
monitor boolean taskAtStationThree {
   
  !taskAtStationThree;
   
  G (pressedStationThree & !next(atEmgState) & !next(maintenanceAtStationThree)) -> (next(taskAtStationThree) = true);
   
  G (atGivenStation(3) & taskAtStationThree & !pressedStationThree & !next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G (next(atEmgState)) -> (next(taskAtStationThree) = false);
   
  G ((!pressedStationThree | next(maintenanceAtStationThree)) &
    (!atGivenStation(3) | !taskAtStationThree | pressedStationThree) &
    (next(!atEmgState))) -> (next(taskAtStationThree) = taskAtStationThree); 
}  

/**
 * monitor goToBaseStation is true when there is a need to go to the base station
 */
monitor boolean goToBaseStation {
   
  !goToBaseStation;
   
  G (noTasks & longTimeWithoutReqs & !atEmgState & !atBaseStation) -> next(goToBaseStation);
   
  G atBaseStation -> next(!goToBaseStation);
  G (atStation & !noTasks) -> next(!goToBaseStation);
  G atEmgState -> next(!goToBaseStation);
   
  G (!atBaseStation & !atEmgState & (!atStation|noTasks) & (!longTimeWithoutReqs|!noTasks)) -> next(goToBaseStation) = goToBaseStation;
}

/**
 * monitor maintenanceAtStationZero becomes true when mPressedStationZero is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationZero{
   
  !maintenanceAtStationZero;
   
  G mPressedStationZero <-> next(maintenanceAtStationZero) = !maintenanceAtStationZero;
}

/**
 * monitor maintenanceAtStationOne becomes true when mPressedStationOne is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationOne{
   
  !maintenanceAtStationOne;
   
  G mPressedStationOne <-> next(maintenanceAtStationOne) = !maintenanceAtStationOne;
}

/**
 * monitor maintenanceAtStationTwo becomes true when mPressedStationTwo is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationTwo{
   
  !maintenanceAtStationTwo;
   
  G mPressedStationTwo<-> next(maintenanceAtStationTwo) = !maintenanceAtStationTwo;
}

/**
 * monitor maintenanceAtStationThree becomes true when mPressedStationThree is pressed
 * until it is pressed again
 */
monitor boolean maintenanceAtStationThree{
   
  !maintenanceAtStationThree;
   
  G mPressedStationThree <-> next(maintenanceAtStationThree) = !maintenanceAtStationThree;
}

/**
 * monitor atEmgState becomes true when emgButton is pressed
 * and stays true until atStation and emgButton is pressed again
 */
monitor boolean atEmgState {
   
  !atEmgState;
   
  G (!atStation & atEmgState) -> next(atEmgState);
   
  G (atStation | !atEmgState) -> (emgButton = PRESSED <-> (next(atEmgState)=!atEmgState));
} 

/**
 * monitor waitingForDoor becomes true when doorReq is true
 * and doorAck hasn't been received yet
 */
monitor boolean waitingForDoor{
   
  !waitingForDoor;
   
  G (doorReq & !doorAck) -> next(waitingForDoor);
   
  G doorAck-> next(!waitingForDoor);
   
  G (!doorReq & !doorAck) -> (next(waitingForDoor)= waitingForDoor);
}

/**
 * monitor openDoorAtEmgState becomes when entering emergency state
 * and it stays true until door request is sent
 */
monitor boolean openDoorAtEmgState {
   
  ! openDoorAtEmgState;
   
  G next(atEmgState) & !atEmgState -> next(openDoorAtEmgState);
   
  G atEmgState & doorReq -> next(!openDoorAtEmgState);
   
  G (!atEmgState | !doorReq) & (next(!atEmgState) | atEmgState)-> next(openDoorAtEmgState) = openDoorAtEmgState;
}

/**
 * monitor waitingForEmgBeeper is true when emgBeepProcessReq is true 
 * and readyToEmgBeep ack hasn't been received yet
 */
monitor boolean waitingForEmgBeeper {
   
  !waitingForEmgBeeper;
   
  G (emgBeepProcessReq -> next(waitingForEmgBeeper));
   
  G (readyToEmgBeep -> (next(!waitingForEmgBeeper) | emgBeepProcessReq));
   
  G (!emgBeepProcessReq & !readyToEmgBeep -> waitingForEmgBeeper = next(waitingForEmgBeeper));
} 

                                        
 
 
 

 
assumption initialStateEnv:
  atGivenStation(0) 
      & noPressedStations 
      & emgButton = RELEASED 
      & !readyToEmgBeep 
      & !longTimeWithoutReqs 
      & !doorAck
      & noMpressedStations;

 
assumption forwardingCauseStationToIncrease:
  pRespondsToS(forwarding &  !atGivenStation(3), stationWillIncrease | !forwarding);

 
assumption backwardingCauseStationToDecrease:
  pRespondsToS(backwarding & !atGivenStation(0), stationWillDecrease | !backwarding);

 
assumption stationChangesOnlyWhenEnteringStation:
  G !willEnterStation -> next(station) = station;

 
assumption stationIncreasesByForwardingAndEntringStation:
  G willEnterStation & forwarding -> stationWillIncrease;

 
assumption stationDecreasesByBackwardingAndEntringStation:
  G willEnterStation & backwarding -> stationWillDecrease; 

 
assumption stationCanOnlyStayTheSameOrChangeByOne:
  G (next(station) = station) | (next(station) = station+1) | (next(station) = station-1); 

 
assumption stationCannotChangewhileStopping:
  G  (stopping -> ((atStation = next(atStation)) & (station = next(station))));
 
 
assumption currentStationIsNotPressedWhileAtCurrentStation:
  G (next(atGivenStation(0)) -> next(!pressedStationZero)) &
    (next(atGivenStation(1)) -> next(!pressedStationOne)) &
    (next(atGivenStation(2)) -> next(!pressedStationTwo)) &
    (next(atGivenStation(3)) -> next(!pressedStationThree));

 
assumption doorReturnsAnswerEventually:
pRespondsToS (waitingForDoor, doorAck);

 
assumption noStrangedoorAcks:
  G (next(doorAck) -> (waitingForDoor & !doorAck));

 
assumption beeperReturnsAnswerEventually:
pRespondsToS (waitingForEmgBeeper, readyToEmgBeep);

 
assumption noStrangeReadyToBeepAcks:
  G (next(readyToEmgBeep) -> (waitingForEmgBeeper & !readyToEmgBeep));

 
assumption notAlwaysAtEmgState:
  GF !atEmgState; 


 
 
 
    
 
guarantee initialStateSys:
  stopping & !doorReq;

 
guarantee stopWhenPassingAstationThatWasCalled:
  G atStationWithTask -> stopping;

 
guarantee openDoorOnlyWhenNeeded:
G (!waitingForDoor & ((atStation & atEmgState & openDoorAtEmgState)| atStationWithTask)) <-> doorReq; 

 
guarantee stopWhileWaitingForDoor:
  G waitingForDoor -> stopping;

 
guarantee stopWhenAtEmgStateAndAtStation:
  G atStation & atEmgState -> stopping;

 
guarantee beepEmgIffEnteringStationOrReadyToEmgBeepAtStation:
G ((atEmgState & PREV(willEnterStation))|(atStation & readyToEmgBeep & atEmgState)) <-> emgBeepProcessReq;

 
guarantee stopWhenAtBaseStationAndNoTasks:
  G noTasks & atBaseStation -> stopping;
  
 
guarantee countTimeSinceReqsIffNoPressedStationsAndNotAtEmgState:
  G noPressedStations & !atEmgState <-> countTimeSinceReqs;


 
 
 
  
 
guarantee dontGoBackwardWhenAtStationZero:
  G atGivenStation(0) -> !backwarding;

 
guarantee dontGoForwardWhenAtStationThree:
  G atGivenStation(3) -> !forwarding;

 
guarantee dontGoForwardWhenNoTasksForward:
  G noTasksForward -> !forwarding;  

 
guarantee dontGoBackwardWhenNoTasksBackward:
  G noTasksBackward & !goToBaseStation -> !backwarding; 

 
guarantee stopWhenAtStationAndNoTasksAndNotGoToBaseStation:
  G noTasks & atStation & !goToBaseStation -> stopping;

 
guarantee stopOnlyAtStation:
  G !atStation -> !stopping;

 
guarantee dontChangeDirectionWithoutStopping:
  G (!stopping -> (next(motors) = motors | next(stopping)));

 
guarantee preventUnnecessaryStops:
  G (!goToBaseStation & atStation & !atStationWithTask & !noTasks & !waitingForDoor) -> !stopping; 

 
 
 
 

 
guarantee taskAtStationZeroIsSatisfiedEventually:
  GF !taskAtStationZero;

 
guarantee taskAtStationOneIsSatisfiedEventually:
  GF !taskAtStationOne;

 
guarantee taskAtStationTwoIsSatisfiedEventually:
  GF !taskAtStationTwo;

 
guarantee taskAtStationThreeIsSatisfiedEventually:
  GF !taskAtStationThree;

 
guarantee NotAlwaysGoToBaseStation: 
  GF !goToBaseStation;

import "../patterns/DwyerPatterns.spectra"

module AirportShuttle

env Station station;
env Button stopButton;

sys MotorCmd mLeft;
sys MotorCmd mRight;

type Button = {PRESSED, RELEASED};
type MotorCmd = {FWD, STOP, BWD};
type Station = {ONE, TWO, THREE, FOUR, NONE};

define 
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  turning := mLeft != mRight;
  atStation := station != NONE;
 

 
 
 
 
 
assumption leaveStationEventually:
pRespondsToS (forwarding, !atStation);
  
 
assumption stationDoesNotChangeWhenStopping:
G (stopping -> station = next (station) );

 
assumption notAlwaysStopAtNearestStation:
GF !stopAtNearestStation;


 
 
 

 
guarantee initialStop:
stopping;

 
guarantee
G (atStation & stopAtNearestStation -> stopping);

/**
 * monitor stopAtNearestStation is true when XXX
 */
monitor boolean stopAtNearestStation {
   
  !stopAtNearestStation;
   
  G ((stopButton = PRESSED) <-> next(stopAtNearestStation)=!stopAtNearestStation);
} 


 
 
 


 
 
 

 
guarantee alwaysGoForward:
GF forwarding;

/*
 * Auto-generated Spectra file
 */
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..255) sense;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 20;
  maxDist := 30;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
guarantee notTurning:
  G !turning;

guarantee beeping:
  G (!stopping <-> beep = 1);

guarantee initialization:
  stopping;  
  
guarantee accel:
  G (accelerating -> (next(mLeft) - mLeft = 1 | (mLeft = 4 & next(mLeft)=4) ));
  
guarantee slowDwn:
  G (slowingDown -> ((mLeft = 0 & next(mLeft)=0) | mLeft - next(mLeft) = 1 ));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..255) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G farFromNextCar -> (accelerating);

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> (accelerating));

guarantee
  G ((inRange & (lastDist = sense)) -> (mLeft = next(mLeft)));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> (slowingDown));
  
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);
 
 
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..13) color;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;
aux boolean trnLft;
aux boolean trnRt;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  inLane := rightColor = black & leftColor = white;
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
   
  white := 1;
  black := 0;
  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  accelLeft := (next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee
  G ((trnLft <-> turningLeft) & (trnRt <-> turningRight));

guarantee beeping:
  G (!stopping <-> beep = 1);
guarantee initialization:
  stopping;  
 
guarantee
  G (!inLane -> (next(turning) | next(stopping)));
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G ((farFromNextCar & inLane) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense) & inLane) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense) & inLane) -> (accelerating));

guarantee
  G ((inRange & (lastDist = sense) & inLane) -> (mLeft = next(mLeft)));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> (slowingDown));
  
guarantee stayInLane:
  GF (inLane);
  
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption
  G (pRespondsToS(turningRight SINCE (rightColor = white), next(inLane)));
assumption
  pRespondsToS(turningLeft SINCE (leftColor = black), next(inLane));


 
 
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;

  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
   
  white := 1;
  black := 0;
  inLane := (rightColor = black) & (leftColor = white);

  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;


  accelLeft := (next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee beeping:
  G (!stopping <-> beep = 1);
guarantee initialization:
  stopping;  
  
guarantee accel:
  G (accelerating <-> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G ((farFromNextCar & inLane) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense) & inLane) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense) & inLane) -> (accelerating));

guarantee
  G (tooClose -> (slowingDown));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));

guarantee fixLaneRight:
  G (pHolds_afterQuntilR(next(turningRight | tooClose), (rightColor = white), inLane));

guarantee fixLaneLeft:
  G (pHolds_afterQuntilR(next(turningLeft | tooClose), (leftColor = black), inLane));

guarantee
  G (inLane -> !next(turning));
  
assumption laneNotReversed:
  G !((rightColor = white) & (leftColor = black));
  
assumption inLaneBetweenLeftDevAndRightDev:
  G (pBecomesTrue_betweenQandR(inLane, rightColor = white, leftColor = black));

assumption inLaneBetweenRightDevAndLeftDev:
  G (pBecomesTrue_betweenQandR(inLane, leftColor = black, rightColor = white));
    
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption laneClearEventually:
  pRespondsToS(stopping, farFromNextCar);

assumption initiallyInLane:
  inLane;
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;

  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));
  devLeft := ((leftColor = white & rightColor = white));
  devRight := ((rightColor = black & leftColor = black));

  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;

  accelLeft := ((next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4));
  accelRight := ((next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4)); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee initiallyStopping:
  stopping;

guarantee beeping:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
G ((farFromNextCar) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> accelerating);

guarantee
  G (tooClose -> (slowingDown));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));

guarantee stayInLane:
 GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
assumption caFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));
  
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  



assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption laneClearEventually:
  G (pRespondsToS(stopping, farFromNextCar));

assumption initiallyInLane:
  inLane;
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;

  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));
  devLeft := ((leftColor = white & rightColor = white));
  devRight := ((rightColor = black & leftColor = black));

  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;

  accelLeft := ((next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4));
  accelRight := ((next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4)); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee initiallyStopping:
  stopping;

guarantee beeping:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
G ((farFromNextCar) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> accelerating);

guarantee
  G (tooClose -> (slowingDown));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));

guarantee stayInLane:
 GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
assumption caFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));
  
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  



assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption laneClearEventually:
  G (pRespondsToS(stopping, farFromNextCar));

/*
 * Auto-generated Spectra file
 */
import "../patterns/DwyerPatterns.spectra"
 
module ConvoyCarSpec     
     
env Int(0..255) sense;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 20;
  maxDist := 30;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
guarantee notTurning:
  G !turning;

guarantee initialization:
  stopping & !accelerating & !slowingDown;
  
guarantee accel:
  G (accelerating -> (next(mLeft) - mLeft = 1 | (mLeft = 4 & next(mLeft)=4) ));
  
guarantee slowDwn:
  G (slowingDown -> ((mLeft = 0 & next(mLeft)=0) | mLeft - next(mLeft) = 1 ));

monitor Int(0..255) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G farFromNextCar -> next(accelerating);

guarantee
  G ((inRange & (lastDist > sense)) -> next(slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> next(accelerating));

guarantee
  G ((inRange & (lastDist = sense)) -> (!next(accelerating) & !next(slowingDown) ));
  
guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> next(slowingDown));
assumption initDist:
  sense >= minDist;
/*
 * Auto-generated Spectra file
 */
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..255) sense;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 20;
  maxDist := 30;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
guarantee notTurning:
  G !turning;

guarantee beeping:
  G (!stopping <-> beep = 1);

guarantee initialization:
  stopping;  
  
guarantee accel:
  G (accelerating -> (next(mLeft) - mLeft = 1 | (mLeft = 4 & next(mLeft)=4) ));
  
guarantee slowDwn:
  G (slowingDown -> ((mLeft = 0 & next(mLeft)=0) | mLeft - next(mLeft) = 1 ));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..255) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G farFromNextCar -> (accelerating);

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> (accelerating));

guarantee
  G ((inRange & (lastDist = sense)) -> (mLeft = next(mLeft)));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> (slowingDown));
  
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);
assumption initDist:
  sense >= minDist;
/*
 * Auto-generated Spectra file
 */
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..255) sense;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 20;
  maxDist := 30;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
guarantee notTurning:
  G !turning;

guarantee beeping:
  G (!stopping <-> beep = 1);

guarantee initialization:
  stopping;  
  
guarantee accel:
  G (accelerating -> (next(mLeft) - mLeft = 1 | (mLeft = 4 & next(mLeft)=4) ));
  
guarantee slowDwn:
  G (slowingDown -> ((mLeft = 0 & next(mLeft)=0) | mLeft - next(mLeft) = 1 ));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..255) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G farFromNextCar -> (accelerating);

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> (accelerating));

guarantee
  G ((inRange & (lastDist = sense)) -> (mLeft = next(mLeft)));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> (slowingDown));
  
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);
 
 
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..13) color;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;
aux boolean trnLft;
aux boolean trnRt;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  inLane := rightColor = black & leftColor = white;
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
   
  white := 1;
  black := 0;
  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  accelLeft := (next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee
  G ((trnLft <-> turningLeft) & (trnRt <-> turningRight));

guarantee beeping:
  G (!stopping <-> beep = 1);
guarantee initialization:
  stopping;  
 
guarantee
  G (!inLane -> (next(turning) | next(stopping)));
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G ((farFromNextCar & inLane) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense) & inLane) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense) & inLane) -> (accelerating));

guarantee
  G ((inRange & (lastDist = sense) & inLane) -> (mLeft = next(mLeft)));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> (slowingDown));
  
guarantee stayInLane:
  GF (inLane);
  
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption
  G (pRespondsToS(turningRight SINCE (rightColor = white), next(inLane)));
assumption
  pRespondsToS(turningLeft SINCE (leftColor = black), next(inLane));


 
 
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;

  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
   
  white := 1;
  black := 0;
  inLane := (rightColor = black) & (leftColor = white);

  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;


  accelLeft := (next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee beeping:
  G (!stopping <-> beep = 1);
guarantee initialization:
  stopping;  
  
guarantee accel:
  G (accelerating <-> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G ((farFromNextCar & inLane) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense) & inLane) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense) & inLane) -> (accelerating));

guarantee
  G (tooClose -> (slowingDown));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));

guarantee fixLaneRight:
  G (pHolds_afterQuntilR(next(turningRight | tooClose), (rightColor = white), inLane));

guarantee fixLaneLeft:
  G (pHolds_afterQuntilR(next(turningLeft | tooClose), (leftColor = black), inLane));

guarantee
  G (inLane -> !next(turning));
  
assumption laneNotReversed:
  G !((rightColor = white) & (leftColor = black));
  
assumption inLaneBetweenLeftDevAndRightDev:
  G (pBecomesTrue_betweenQandR(inLane, rightColor = white, leftColor = black));

assumption inLaneBetweenRightDevAndLeftDev:
  G (pBecomesTrue_betweenQandR(inLane, leftColor = black, rightColor = white));
    
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption laneClearEventually:
  pRespondsToS(stopping, farFromNextCar);

assumption initiallyInLane:
  inLane;
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;

  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));
  devLeft := ((leftColor = white & rightColor = white));
  devRight := ((rightColor = black & leftColor = black));

  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;

  accelLeft := ((next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4));
  accelRight := ((next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4)); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee initiallyStopping:
  stopping;

guarantee beeping:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
G ((farFromNextCar) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> accelerating);

guarantee
  G (tooClose -> (slowingDown));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));

guarantee stayInLane:
 GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
assumption caFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));
  
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  



assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption laneClearEventually:
  G (pRespondsToS(stopping, farFromNextCar));

assumption initiallyInLane:
  inLane;
/*
 * Auto-generated Spectra file
 */
  
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;

  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));
  devLeft := ((leftColor = white & rightColor = white));
  devRight := ((rightColor = black & leftColor = black));

  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;

  accelLeft := ((next(mLeft) - mLeft = 1) | (mLeft = 4 & next(mLeft)=4));
  accelRight := ((next(mRight) - mRight = 1) | (mRight = 4 & next(mRight)=4)); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft - next(mLeft) = 1);
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight - next(mRight) = 1);

guarantee initiallyStopping:
  stopping;

guarantee beeping:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
G ((farFromNextCar) -> (accelerating));

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> accelerating);

guarantee
  G (tooClose -> (slowingDown));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));

guarantee stayInLane:
 GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
assumption caFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));
  
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  



assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);

assumption laneClearEventually:
  G (pRespondsToS(stopping, farFromNextCar));


  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define

   
  stopping := mLeft = 0 & mRight = 0;
  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  accelLeft := (next(mLeft) > mLeft) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) > mRight) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft > next(mLeft));
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight > next(mRight));
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));
  devLeft := ((leftColor = white & rightColor = white));
  devRight := ((rightColor = black & leftColor = black));

   
  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  laneClear := sense >= maxDist;
  nextCarCloser := inRange & (lastDist > sense);
  nextCarFarther := inRange & (lastDist < sense);

monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee initiallyStopping:
  stopping;

guarantee beepWhenMoving:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
guarantee accelerateIfClear:
  G (laneClear -> accelerating);

guarantee slowDownInRange:
  G (nextCarCloser -> slowingDown);

guarantee accelInRange:
  G (nextCarFarther -> accelerating);

guarantee slowDownIfTooClose:
  G (tooClose -> slowingDown);

guarantee convoy:
  GF (inRange | laneClear | (tooClose & stopping));  

guarantee stayInLane:
  GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
assumption caFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));
  
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  

assumption laneClearEventually:
  G (pRespondsToS(stopping, laneClear));

/*
 * - removed some redundant assumptions
 * - named all guarantees/assumptions, and made some cosmetic changes
 *    (to make the spec more readable)
 * 
 */
 
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define

   
  stopping := mLeft = 0 & mRight = 0;
  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  accelLeft := (next(mLeft) > mLeft) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) > mRight) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft > next(mLeft));
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight > next(mRight));
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));
  devLeft := ((leftColor = white & rightColor = white));
  devRight := ((rightColor = black & leftColor = black));

   
  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  laneClear := sense >= maxDist;
  nextCarCloser := inRange & (lastDist > sense);
  nextCarFarther := inRange & (lastDist < sense);

monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee initiallyStopping:
  stopping;

guarantee beepWhenMoving:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
guarantee accelerateIfClear:
  G (laneClear -> accelerating);

guarantee slowDownInRange:
  G (nextCarCloser -> slowingDown);

guarantee accelInRange:
  G (nextCarFarther -> accelerating);

guarantee slowDownIfTooClose:
  G (tooClose -> slowingDown);

guarantee convoy:
  GF (inRange | laneClear | (tooClose & stopping));  

guarantee stayInLane:
  GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
assumption caFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));
  
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  

assumption laneClearEventually:
  G (pRespondsToS(stopping, laneClear));

/*
 * - removed some redundant assumptions
 * - named all guarantees/assumptions, and made some cosmetic changes
 *    (to make the spec more readable)
 * 
 */
 
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;
env Int(0..1) rightColor;
env Int(0..1) leftColor;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define

   
  stopping := mLeft = 0 & mRight = 0;
  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  accelLeft := (next(mLeft) > mLeft) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) > mRight) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft > next(mLeft));
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight > next(mRight));
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));
  devLeft := ((leftColor = white & rightColor = white));
  devRight := ((rightColor = black & leftColor = black));

   
  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  laneClear := sense >= maxDist;
  nextCarCloser := inRange & (lastDist > sense);
  nextCarFarther := inRange & (lastDist < sense);

monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee initiallyStopping:
  stopping;

guarantee beepWhenMoving:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
guarantee accelerateIfClear:
  G (laneClear -> accelerating);

guarantee slowDownInRange:
  G (nextCarCloser -> slowingDown);

guarantee accelInRange:
  G (nextCarFarther -> accelerating);

guarantee slowDownIfTooClose:
  G (tooClose -> slowingDown);

guarantee convoy:
  GF (inRange | laneClear);

guarantee stayInLane:
  GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
assumption caFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));
  
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  

assumption laneClearEventually:
  G (pRespondsToS(stopping, laneClear));

/*
 * - removed some redundant assumptions
 * - named all guarantees/assumptions, and made some cosmetic changes
 *    (to make the spec more readable)
 * 
 */
 
  
  
  
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..10) sense;      
env Int(0..1) rightColor;  
env Int(0..1) leftColor;   
sys Int(0..4) mLeft;       
sys Int(0..4) mRight;      
sys Int(0..1) beep;        

aux boolean accelerating;
aux boolean slowingDown;

define

   
  stopping := mLeft = 0 & mRight = 0;
  turningLeft := mLeft < mRight;
  turningRight := mLeft > mRight;
  turning := turningLeft | turningRight;
  accelLeft := (next(mLeft) > mLeft) | (mLeft = 4 & next(mLeft)=4);
  accelRight := (next(mRight) > mRight) | (mRight = 4 & next(mRight)=4); 
  slowDownLeft := (mLeft = 0 & next(mLeft)=0) | (mLeft > next(mLeft));
  slowDownRight := (mRight = 0 & next(mRight)=0) | (mRight > next(mRight));
  
   
  white := 1;
  black := 0;
  inLane := ((rightColor = black) & (leftColor = white));
  reversedLane := ((rightColor = white) & (leftColor = black));  
  devLeft := ((leftColor = white & rightColor = white));   
  devRight := ((rightColor = black & leftColor = black));  

   
  minDist := 0;
  maxDist := 10;
  inRange := (minDist < sense) & (sense < maxDist);  
  tooClose := sense <= minDist;    
  laneClear := sense >= maxDist;   
  nextCarCloser := inRange & (lastDist > sense);   
  nextCarFarther := inRange & (lastDist < sense);  

monitor Int(0..10) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee initiallyStopping:
  stopping;

guarantee beepWhenMoving:
  G (!stopping <-> beep = 1);
  
guarantee accel:
  G (accelerating -> (accelLeft | accelRight));
  
guarantee slowDown:
  G (slowingDown -> (slowDownLeft | slowDownRight));

 
guarantee smoothnessLeft: 
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
guarantee accelerateIfClear:
  G (laneClear -> accelerating);

guarantee slowDownInRange:  
  G (nextCarCloser -> slowingDown);

guarantee accelInRange:  
  G (nextCarFarther -> accelerating);

guarantee slowDownIfTooClose:
  G (tooClose -> slowingDown);

guarantee convoy:
  GF (inRange | laneClear);

guarantee stayInLane:
  GF (inLane);
 
guarantee advance:
  GF (!stopping);

guarantee
  G (inLane -> !next(turning));
  
 
assumption canFixRightDeviation:
  G (pRespondsToS((devRight & turningLeft), (inLane | !turningLeft)));

 
assumption canFixLeftDeviation:
  G (pRespondsToS((devLeft & turningRight), (inLane | !turningRight)));

 
assumption canFixReversedLane:
  G (pRespondsToS((reversedLane & turningRight), (inLane | !turningRight)));  
 
assumption laneClearEventually:
  G (pRespondsToS(stopping, (laneClear | !stopping)));

/*
 * Auto-generated Spectra file
 */
import "../patterns/DwyerPatterns.spectra"
 
module ConvoyCarSpec     
     
env Int(0..255) sense;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 20;
  maxDist := 30;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
guarantee notTurning:
  G !turning;

guarantee initialization:
  stopping & !accelerating & !slowingDown;
  
guarantee accel:
  G (accelerating -> (next(mLeft) - mLeft = 1 | (mLeft = 4 & next(mLeft)=4) ));
  
guarantee slowDwn:
  G (slowingDown -> ((mLeft = 0 & next(mLeft)=0) | mLeft - next(mLeft) = 1 ));

monitor Int(0..255) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G farFromNextCar -> next(accelerating);

guarantee
  G ((inRange & (lastDist > sense)) -> next(slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> next(accelerating));

guarantee
  G ((inRange & (lastDist = sense)) -> (!next(accelerating) & !next(slowingDown) ));
  
guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> next(slowingDown));
assumption initDist:
  sense >= minDist;
/*
 * Auto-generated Spectra file
 */
import "../patterns/DwyerPatterns.spectra"
  
module ConvoyCarSpec     
     
env Int(0..255) sense;
sys Int(0..4) mLeft;
sys Int(0..4) mRight;
sys Int(0..1) beep;

aux boolean accelerating;
aux boolean slowingDown;

define
  stopping := mLeft = 0 & mRight = 0;
  turning := mLeft != mRight;
  minDist := 20;
  maxDist := 30;
  inRange := (minDist < sense) & (sense < maxDist);
  tooClose := sense <= minDist;
  farFromNextCar := sense >= maxDist;
guarantee notTurning:
  G !turning;

guarantee beeping:
  G (!stopping <-> beep = 1);

guarantee initialization:
  stopping;  
  
guarantee accel:
  G (accelerating -> (next(mLeft) - mLeft = 1 | (mLeft = 4 & next(mLeft)=4) ));
  
guarantee slowDwn:
  G (slowingDown -> ((mLeft = 0 & next(mLeft)=0) | mLeft - next(mLeft) = 1 ));

guarantee smoothnessLeft:
  G ((-1 <= next(mLeft) - mLeft) & (next(mLeft) - mLeft <= 1));
guarantee smoothnessRight:
  G ((-1 <= next(mRight) - mRight) & (next(mRight) - mRight <= 1));
  
monitor Int(0..255) lastDist{
  lastDist = sense;
  G next(lastDist) = sense;
}

guarantee accelerateIfClear:
  G farFromNextCar -> (accelerating);

guarantee
  G ((inRange & (lastDist > sense)) -> (slowingDown));

guarantee
  G ((inRange & (lastDist < sense)) -> (accelerating));

guarantee
  G ((inRange & (lastDist = sense)) -> (mLeft = next(mLeft)));

guarantee convoy:
  GF (inRange | farFromNextCar | (tooClose & stopping));
  
guarantee
  G (tooClose -> (slowingDown));
  
assumption
  G (inRange -> (!farFromNextCar & !tooClose));
assumption
  G (tooClose -> !farFromNextCar & !inRange);
assumption
  G (farFromNextCar -> !inRange & !tooClose);
assumption initDist:
  sense >= minDist;
import "../patterns/DwyerPatterns.spectra"

module Elevator


type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};
type LampCmd= {ON, OFF};
type FloorState={FLOOR0,FLOOR1,FLOOR2,FLOOR3,NONE};
type DoorsState={Closed,Opened,FullyOpened};
 



 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;

 
 
env boolean seconds3;
env boolean seconds5;
env boolean seconds20;
 
 
 
env FloorState floor_c;
env DoorsState doors_c;

 


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys LampCmd lamp_c;
sys boolean countTime_c;


 

define 
  goingUp                      :=   (liftM_c = UP);
  goingDown                    :=   (liftM_c = DOWN);
  moving                       :=   (liftM_c = UP | liftM_c = DOWN);
  openningDoors                :=   (doorsM_c = OPEN);
  closingDoors                 :=   (doorsM_c = CLOSE);
  keepDoorsState               :=   (doorsM_c = STOP);
  lightIsOn                    :=   (lamp_c = ON);
  doorsAreClosed               :=   (doors_c = Closed);
  doorsAreFullyOpened          :=   (doors_c = FullyOpened);  
  floor0                       :=   (floor_c=FLOOR0);
  floor1                       :=   (floor_c=FLOOR1);
  floor2                       :=   (floor_c=FLOOR2);
  floor3                       :=   (floor_c=FLOOR3);
  atEdgedFloor                 :=   (floor0 | floor3);
  atFloor                      :=   floor0|floor1|floor2|floor3; 
  anyCalls                     :=   (memCall0 | memCall1 | memCall2 | memCall3); 
  atDesignatedFloor            :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor  :=   atDesignatedFloor&doorsAreClosed;
  openStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  

   

monitor boolean returnTo0
{  !returnTo0;
   G (!floor0 & ((!anyCalls&seconds20) | returnTo0))<->next (returnTo0) ; 
}


monitor boolean memCall0
{
  !memCall0;
  G (calls0_c & !memCall0) -> next (memCall0);
  G (floor0 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall0);
  G (!(calls0_c & !memCall0) & !(floor0 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall0) = memCall0);
}

monitor boolean memCall1
{
  !memCall1;
  G (calls1_c & !memCall1) -> next (memCall1);
  G (floor1 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall1);
  G (!(calls1_c & !memCall1) & !(floor1 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (calls2_c & !memCall2) -> next (memCall2);
  G (floor2 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall2);
  G (!(calls2_c & !memCall2) & !(floor2 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (calls3_c & !memCall3) -> next (memCall3);
  G (floor3 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall3);
  G (!(calls3_c & !memCall3) & !(floor3 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall3) = memCall3);
}


/* 
gar
  pHolds_afterQuntilR(openningDoors,doorsAreClosed,doorsAreFullyOpened);
  
gar
  pHolds_afterQuntilR(closingDoors,doorsAreFullyOpened,doorsAreClosed);

gar
  G (!moving);
*/

/*
gar
  pHolds_afterQuntilR(goingUp,floor0,floor1);
  
gar
  pHolds_afterQuntilR(goingDown,floor1,floor0);

gar
  G (keepDoorsState);

*/

 
gar init_motors:
(!moving) & (keepDoorsState) & (!lightIsOn) ;


 
asm startFromFloor0:
  floor0;
  
asm startFromClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  !(seconds3|seconds5|seconds20);



gar
  G !lightIsOn;
/* 
gar lightBlinksWhileMoving:
G moving -> (next (lightIsOn) = !lightIsOn);

gar lightIsOffWhileNotMoving:
G (!moving) -> (next(!lightIsOn) );
*/


 
gar ifFloor0DontGoDown:
G floor0 -> !(goingDown) ;

gar ifFloor3DontGoUp:
G floor3 -> !(goingUp) ;

gar ifDoorsAreClosedDontClose:
G doorsAreClosed -> (!closingDoors) ;

gar ifDoorsAreFullyOpenedDontOpen:
G doorsAreFullyOpened->(!openningDoors);


gar dontMoveWithoutAReason:
  G (((!anyCalls) & (!returnTo0))| (returnTo0 & floor0)) -> !moving;


gar dontOpenDoorsWithoutAReason:
  G (!atDesignatedFloor)->(!openningDoors);
  
  
 
  
 
gar doorsAreClosedWhileMoving:
  G ((!doorsAreClosed)->(!moving)) & (moving->keepDoorsState);

gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  

gar dontStopWithoutAReason:
  G moving->(next(!moving->(atDesignatedFloor|atEdgedFloor)));
  
  
  
 
asm floorChangeCannotHappenWithoutMoving: 
  G (!moving)->(next(floor_c)=floor_c);
  
  
asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);
  
  
asm movingDoorsCauseChangeInDoorsState:
  G (openningDoors->next(!doorsAreClosed))&(closingDoors->next(!doorsAreFullyOpened));  


asm goingUpFromFloor0CauseVisitingFloor1:
  pRespondsToS(floor0&goingUp,floor1);
  
asm goingUpFromFloor1CauseVisitingFloor2:
  pRespondsToS(floor1&goingUp,floor2);

asm goingUpFromFloor2CauseVisitingFloor3:
  pRespondsToS(floor2&goingUp,floor3); 
  
asm goingDownFromFloor1CauseVisitingFloor0:
  pRespondsToS(floor1&goingDown,floor0);
  
asm goingDownFromFloor2CauseVisitingFloor1:
  pRespondsToS(floor2&goingDown,floor1);

asm goingDownFromFloor3CauseVisitingFloor2:
  pRespondsToS(floor3&goingDown,floor2);




 
gar ifAtDesignatedFloorDontMove:
    G atDesignatedFloor->(!moving);
    
gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    pHolds_afterQuntilR(!openningDoors,firstStateAtDesignatedFloor,seconds3);

gar AtDesignatedFloorOpenDoorsWithin3Seconds:
    pHolds_afterQuntilR(openningDoors,firstStateAtDesignatedFloor&seconds3,doorsAreFullyOpened);
    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    pHolds_afterQuntilR(keepDoorsState,doorsAreFullyOpened,seconds5);

 


 

gar startCountingTime:
  G (!(moving|anyCalls |floor0|returnTo0) | firstStateAtDesignatedFloor | openStateAtDesignatedFloor)->countTime_c;
 

asm envDoesntCountTimeWhenNotRequired:
  G (!countTime_c) -> next (!seconds3&!seconds5&!seconds20) ;

asm not20SecondsAnd5SecondsBefore3Seconds:
  G (!seconds3) -> !(seconds20|seconds5) ;

asm not20SecondsBefore5Seconds:
  G (!seconds5)->(!seconds20);

asm ifCount3SecAndStillCountThenNext3Sec:
  G (seconds3&countTime_c)->next(seconds3);  

asm ifCount5SecAndStillCountThenNext5Sec:
  G (seconds5&countTime_c)->next(seconds5);  

asm ifCount20SecAndStillCountThenNext20Sec:
  G (seconds20&countTime_c)->next(seconds20);



 
  


  


 


 
 
   
import "../patterns/DwyerPatterns.spectra"

module Elevator


type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};
type LampCmd= {ON, OFF};
 



 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;

env boolean emergency_c;


 
 
 
env Int(0..3) secondsState_c; 
 
 
 
env Int(0..6) floor_c;
 
env Int(0..2) doors_c;

 


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys LampCmd lamp_c;
sys boolean countTime_c;


 

define 
  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  lightIsOn                           :=   (lamp_c = ON);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atEdgedFloor                        :=   (floor0 | floor3);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  betweenFloors01                     :=   (floor_c=1);
  betweenFloors12                     :=   (floor_c=3);
  betweenFloors23                     :=   (floor_c=5);
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  
  
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds20                           :=   secondsState_c=3;
  
  onlyDownCalls                       :=   (floor1&(memCall0)&!(memCall1|memCall2|memCall3))|
                                           (floor2&(memCall0|memCall1)&!(memCall2|memCall3));
                                           
  onlyUpCalls                         :=   (floor1&(memCall2|memCall3)&!(memCall0|memCall1))|
                                           (floor2&(memCall3)&!(memCall0|memCall1|memCall2));
  
  atEmergencyFloor                    :=   (atFloor&(memEmergency|(emergency_c&doorsAreClosed)));
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  secondHalfOfEmregencyFloor          :=   (atFloor&!atDesignatedFloor&doorsWereFullyOpened);   
  lastStateAtEmergencyFloor           :=   (secondHalfOfEmregencyFloor&doorsAreClosed);                                 

   


monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed) | returnTo0))<->next (returnTo0); 
}


monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G (doorsAreClosed->next(!doorsWereFullyOpened));
  G (doorsAreOpened->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}

monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency & doorsAreClosed/* */) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency & doorsAreClosed/* */) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}

monitor boolean memCall0
{
  !memCall0;
  G (calls0_c & !memCall0 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor0)) -> next (memCall0);
  G (memCall0 & ((floor0 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor))) -> next(!memCall0);
  G (!(calls0_c & !memCall0 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor0)) & !(memCall0 & ((floor0 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor)))) -> (next(memCall0) = memCall0);
}

monitor boolean memCall1
{
  !memCall1;
  G (calls1_c & !memCall1 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor1)) -> next (memCall1);
  G (memCall1 & ((floor1 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor))) -> next(!memCall1);
  G (!(calls1_c & !memCall1 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor1)) & !(memCall1 & ((floor1 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor)))) -> (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (calls2_c & !memCall2 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor2)) -> next (memCall2);
  G (memCall2 & ((floor2 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor))) -> next(!memCall2);
  G (!(calls2_c & !memCall2 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor2)) & !(memCall2 & ((floor2 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor)))) -> (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (calls3_c & !memCall3 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor3)) -> next (memCall3);
  G (memCall3 & ((floor3 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor))) -> next(!memCall3);
  G (!(calls3_c & !memCall3 & !emergency_c & (!memEmergency|doorsWereFullyOpened&!floor3)) & !(memCall3 & ((floor3 & doorsWereFullyOpened & doorsAreClosed)|(fullyOpenedStateAtEmergencyFloor)))) -> (next(memCall3) = memCall3);
}



/*
pattern takeCareOfFloor(call,floor,doorsAreClosed)
{
  var boolean memCalltemp;
  
  !memCalltemp;
  
  G (call & !memCalltemp) -> next (memCalltemp);
  G (floor & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCalltemp);
  G (!(call & !memCalltemp) & !(floor & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCalltemp) = memCalltemp);
  
  GF (!memCalltemp);
  
}
*/



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
 
 

 
 

 
 
  
 
 
  
 
 

gar
  G !lightIsOn;


 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
  
 
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G ((!doorsAreClosed)/*|(doorsWereFullyOpened)*/)->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->closingDoors);
  
  
  


  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!((emergency_c&doorsAreClosed)|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G (((emergency_c&doorsAreClosed)|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|(!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds)/*&(seconds3)*/)->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

 
 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor)/*&!returnTo0*/)->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)/*&(floor_c=next(floor_c))*/->next(!stayInPlace|atEmergencyFloor);

gar dontGoUpWhenOnlyCallsFromDown:
  G (onlyDownCalls&PREV(stayInPlace))->(goingDown|atEmergencyFloor);

gar dontGoDownWhenOnlyCallsFromUp:
  G (onlyUpCalls&PREV(stayInPlace))->(goingUp|atEmergencyFloor);


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
     
    G(firstStateAtDesignatedFloor&(noSeconds)/*&!emergency*/&!atEmergencyFloor)->keepDoorsState;

    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
     
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)/*&!emergency*/&!memEmergency)->keepDoorsState;




 

gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);




 

gar returnTo0WhenRequired:
   
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInThebeginning:
  !emergency_c;
  
 
 


 
 

 
 

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
   
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
  
 
import "../patterns/DwyerPatterns.spectra"

module Elevator


type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;

env boolean emergency_c;
env boolean sabbath_c;


 
 
 
env Int(0..4) secondsState_c; 
 
 
 
env Int(0..6) floor_c;
 
env Int(0..2) doors_c;

 


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 

define 
  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
   
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
   
   
   
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  
  
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds10                           :=   secondsState_c=3;
  seconds20                           :=   secondsState_c=4;
  
  onlyDownCalls                       :=   (floor1&(memCall0)&!(memCall1|memCall2|memCall3))|
                                           (floor2&(memCall0|memCall1)&!(memCall2|memCall3));
                                           
  onlyUpCalls                         :=   (floor1&(memCall2|memCall3)&!(memCall0|memCall1))|
                                           (floor2&(memCall3)&!(memCall0|memCall1|memCall2));
  
  
  atEmergencyFloor                    :=   (atFloor&(memEmergency|emergency_c));
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);

  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)/*|(floor2&!memCall3)*/));
                                         
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  
  
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));
                                           
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  
  
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));
                                           
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  
  
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));
                                             
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  

  activateSabbathMode                 :=   (!sabbathMode & sabbath_c & !emergency_c & !memEmergency /*& doorsAreClosed*/);
  deActivateSabbathMode               :=   (sabbathMode  & (sabbath_c|emergency_c|memEmergency));
  


monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}


monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}


monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
  
  
}


monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened,boolean doorsAreClosed):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
  
 
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G ((!doorsAreClosed))->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor/*&!atSabbathFloor&(!doorsAreClosed)*/)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(/*sabbath_c|*/emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G (/*sabbath_c|*/(emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds)/*&(seconds3)*/)->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

gar dontGoUpWhenOnlyCallsFromDown:
  G (onlyDownCalls&PREV(stayInPlace))->(goingDown|atEmergencyFloor);

gar dontGoDownWhenOnlyCallsFromUp:
  G (onlyUpCalls&PREV(stayInPlace))->(goingUp|atEmergencyFloor);


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    
 
 


gar AtDesignatedFloorInSabbathModeHoldTheDoorsFullyOpenedFor10Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3|seconds5)&!memEmergency&sabbathMode&PREV(keepDoorsState))->(keepDoorsState);


 

gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);




 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
   
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   
  
/*
weight pnaltyFloor0: -1
  memCall0&next(memCall0);

weight pnaltyFloor1: -1
  memCall1&next(memCall1);

weight pnaltyFloor2: -1
  memCall2&next(memCall2);

weight pnaltyFloor3: -1
  memCall3&next(memCall3);

   

weight rewardFloor0: 1
  memCall0&next(!memCall0);

weight rewardFloor1: 2
  memCall1&next(!memCall1);

weight rewardFloor2: 3
  memCall2&next(!memCall2);

weight rewardFloor3: 4
  memCall3&next(!memCall3);
  
*/

 
import "../patterns/DwyerPatterns.spectra"

module Elevator

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 
  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds10                           :=   secondsState_c=3;
  seconds20                           :=   secondsState_c=4;
  onlyDownCalls                       :=   (floor1&(memCall0)&!(memCall1|memCall2|memCall3))|
                                           (floor2&(memCall0|memCall1)&!(memCall2|memCall3));                                        
  onlyUpCalls                         :=   (floor1&(memCall2|memCall3)&!(memCall0|memCall1))|
                                           (floor2&(memCall3)&!(memCall0|memCall1|memCall2)); 
  atEmergencyFloor                    :=   (atFloor&(memEmergency|emergency_c));
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,floor0,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,floor1,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,floor2,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,floor3,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateSabbathMode                 :=   (!sabbathMode & sabbath_c & !emergency_c & !memEmergency);
  deActivateSabbathMode               :=   (sabbathMode  & (sabbath_c|emergency_c|memEmergency));
  


monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}


monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}


monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}


monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean floor,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G ((!doorsAreClosed))->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor/*&!atSabbathFloor&(!doorsAreClosed)*/)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

gar dontGoUpWhenOnlyCallsFromDown:
  G (onlyDownCalls&PREV(stayInPlace))->(goingDown|atEmergencyFloor);

gar dontGoDownWhenOnlyCallsFromUp:
  G (onlyUpCalls&PREV(stayInPlace))->(goingUp|atEmergencyFloor);


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    
 
 


gar AtDesignatedFloorInSabbathModeHoldTheDoorsFullyOpenedFor10Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3|seconds5)&!memEmergency&sabbathMode&PREV(keepDoorsState))->(keepDoorsState);


 

gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);




 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
   
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   
  
/*
weight pnaltyFloor0: -1
  memCall0&next(memCall0);

weight pnaltyFloor1: -1
  memCall1&next(memCall1);

weight pnaltyFloor2: -1
  memCall2&next(memCall2);

weight pnaltyFloor3: -1
  memCall3&next(memCall3);

   

weight rewardFloor0: 1
  memCall0&next(!memCall0);

weight rewardFloor1: 2
  memCall1&next(!memCall1);

weight rewardFloor2: 3
  memCall2&next(!memCall2);

weight rewardFloor3: 4
  memCall3&next(!memCall3);
  
*/

 
import "../patterns/DwyerPatterns.spectra"

module Elevator

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 

  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds20                           :=   secondsState_c=4;
  onlyDownCalls                       :=   (floor1&(memCall0)&!(memCall1|memCall2|memCall3))|
                                           (floor2&(memCall0|memCall1)&!(memCall2|memCall3));                                        
  onlyUpCalls                         :=   (floor1&(memCall2|memCall3)&!(memCall0|memCall1))|
                                           (floor2&(memCall3)&!(memCall0|memCall1|memCall2)); 
  emergency_state                     :=   (emergency_c|memEmergency);
  atEmergencyFloor                    :=   (atFloor&emergency_state);
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,floor0,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,floor1,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,floor2,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,floor3,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateSabbathMode                 :=   (!sabbathMode & sabbath_c & !emergency_c & !memEmergency);
  deActivateSabbathMode               :=   (sabbathMode  & (sabbath_c|emergency_c|memEmergency));
   
   
   
  

monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}




monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}


monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}




monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean floor,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G (!doorsAreClosed)->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

gar dontGoUpWhenOnlyCallsFromDown:
  G (onlyDownCalls&PREV(stayInPlace))->(!goingUp); 

gar dontGoDownWhenOnlyCallsFromUp:
  G (onlyUpCalls&PREV(stayInPlace))->(!goingDown); 


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

gar AtDesignatedFloorOpenDoorsAfer3Seconds:
    G(firstStateAtDesignatedFloor&(seconds3)&!atEmergencyFloor)->openingDoors;
    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    

gar AtDesignatedFloorInSabbathModeHoldTheDoorsFullyOpenedFor10Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3|seconds5)&!memEmergency&sabbathMode&PREV(keepDoorsState))->(keepDoorsState);


 

/*
gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);
*/



 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   


 

weight notServing: -20
  true&next(anyMemCalls&!atDesignatedFloor&stayInPlace&!(returnTo0&floor0)&!atEmergencyFloor);   
                                                                                         
weight gettingFarFromFloor0: -1
  stayInPlace&next(memCall0&!floor0&goingUp&!emergency_state);

weight gettingFarFromFloor1UP: -1
  stayInPlace&next(memCall1&(floor_c>2)&goingUp&!emergency_state);

/*
weight gettingFarFromFloor1DOWN: -1
  stayInPlace&next(memCall1&(floor_c<2)&goingDown&!returnTo0&!emergency_state);
*/

/*
weight gettingFarFromFloor2UP: -1
  stayInPlace&next(memCall2&(floor_c>4)&goingUp&!emergency_state);
*/  

weight gettingFarFromFloor2DOWN: -1
  stayInPlace&next(memCall2&(floor_c<4)&goingDown&!returnTo0&!emergency_state);

  
weight gettingFarFromFloor3: -3 
  stayInPlace&next(memCall3&!floor3&goingDown&!returnTo0&!emergency_state);
  


 

weight gettingCloseToFloor0: 1
  stayInPlace&next(memCall0&!floor0&goingDown&!returnTo0&!emergency_state);

/*  
weight gettingCloseToFloor1UP: 1
  stayInPlace&next(memCall1&(floor_c<2)&goingUp&!emergency_state);
*/
  
weight gettingCloseToFloor1DOWN: 1
  stayInPlace&next(memCall1&(floor_c>2)&goingDown&!returnTo0&!emergency_state);
  
weight gettingCloseToFloor2UP: 1
  stayInPlace&next(memCall2&(floor_c<4)&goingUp&!emergency_state);
  
/*
weight gettingCloseToFloor2DOWN: 1
  stayInPlace&next(memCall2&(floor_c>4)&goingDown&!emergency_state);
*/

weight gettingCloseToFloor3: 2
  stayInPlace&next(memCall3&!floor3&goingUp&!emergency_state);




 
 
 
import "../patterns/DwyerPatterns.spectra"

module Elevator


type TouchSensorCont={ON,OFF};
type DoorMotorCont={CLOSE,STOP,OPEN};
type LiftMotorCont={UP,STOP,DOWN};
type LampCont={ON,OFF};
type Velocity={ZERO,SLOW,FAST};

 
 
env Int(0..21) current_time_c;  


env boolean[4] calls_c;  


sys LiftMotorCont liftM_c;
sys DoorMotorCont doorM_c;
sys LampCont lamp_c;

 
 

 
aux boolean[4] memCalls;
aux Int(0..3) currentFloor;

define
  goingUp             := (liftM_c=UP);
  goingDown           := (liftM_c=DOWN);
  moving              := (goingUp|goingDown);
  stayingSameHeigt    := !moving;   
                                    
  openningDoors       := (doorM_c=OPEN);
  closingDoors        := (doorM_c=CLOSE);
  keepDoorsState      := (doorM_c=STOP);
  lightIsOn           := (lamp_c=ON);
  floor0              := (aboveTheGround=0);
  floor1              := (aboveTheGround=5);
  floor2              := (aboveTheGround=10); 
  floor3              := (aboveTheGround=15);
  atFloor             := (floor0|floor1|floor2|floor3); 
  atFloorThatCalled   := (floor0&memCalls[0])|(floor1&memCalls[1])|(floor2&memCalls[2])|(floor3&memCalls[3]);
  doorsAreFullyOpened := (distanceBetweenDoors=15);
  doorsAreClosed      := (distanceBetweenDoors=0); 
  anyCalls            := (memCalls[0]|memCalls[1]|memCalls[2]|memCalls[3]);


predicate changeMonitorByOperation(boolean cond,Int(0..15) m,Int(0..2) d):
  cond<->(next(m)=m+(d-1));

 
    

predicate xImpNextY(boolean cond1,boolean cond2):
  cond1->next(cond2);

 
   

monitor Int(0..15) aboveTheGround
{
  (aboveTheGround=0);
  G changeMonitorByOperation(goingUp,aboveTheGround,2);
  G changeMonitorByOperation(goingDown,aboveTheGround,0);
  G changeMonitorByOperation(stayingSameHeigt,aboveTheGround,1);
}

monitor Int(0..15) distanceBetweenDoors
{
  (distanceBetweenDoors=0);
  G changeMonitorByOperation(openningDoors,distanceBetweenDoors,2);
  G changeMonitorByOperation(closingDoors,distanceBetweenDoors,0);
  G changeMonitorByOperation(keepDoorsState,distanceBetweenDoors,1);
}

monitor Int(0..21) sampledTime
{
  (sampledTime=0);
  G ((!anyCalls) & PREV(anyCalls))->(next(sampledTime)=current_time_c);
   
  
}


gar init_motors:
  (stayingSameHeigt)&(keepDoorsState)&(!lightIsOn)&(!anyCalls);
    

gar setCurrentFloorVar:
  G((floor0->(currentFloor=0))&
    (floor1->(currentFloor=1))&
    (floor2->(currentFloor=2))&
    (floor3->(currentFloor=3)));  
     
     
  
  
gar doorsAreClosedWhileMoving:
  G(moving -> (doorsAreClosed&keepDoorsState));


gar ifFloor0DontGoDown:
  G(floor0->!(goingDown));
  
gar ifFloor3DontGoUp:
  G(floor3->!(goingUp));
  
gar lightBlinksWhileMoving:
  G(moving->(next(lightIsOn)!=lightIsOn));

gar lightIsOffWhileNotMoving:
  G((!moving)->(!next(lightIsOn)));  
   

gar ifCallsFromFloor0GoTo0:
  pRespondsToS(calls_c[0],floor0);  
   
   
   
   
   
   

 
  
  
 
   
  
 
   

gar dontChangeDirectionWithoutStopping:
   
  G((goingUp->next(!goingDown))&(goingDown->next(!goingUp)));


gar rememberCalls:
  G(xImpNextY(calls_c[0],memCalls[0])&
    xImpNextY(calls_c[1],memCalls[1])&
    xImpNextY(calls_c[2],memCalls[2])&
    xImpNextY(calls_c[3],memCalls[3]));
    /*G((calls_c[0]->next(memCalls[0]))&
      (calls_c[1]->next(memCalls[1]))&
      (calls_c[2]->next(memCalls[2]))&
      (calls_c[3]->next(memCalls[3])));*/
    
 


gar ifMovingDontStopTillDesignatedFloorHasBeenVisited:
  G(moving->next((stayingSameHeigt)<->(atFloorThatCalled|floor3|floor0)));
 
  
  
 
   
  
  
gar ifArriveToDesignatedFloorRemoveCall:
    G(((floor0&!calls_c[0])->next(!memCalls[0]))&
      ((floor1&!calls_c[1])->next(!memCalls[1]))&
      ((floor2&!calls_c[2])->next(!memCalls[2]))&
      ((floor3&!calls_c[3])->next(!memCalls[3])));
      
 
     
    
 
   
  
  
 
  
    
import "../patterns/DwyerPatterns.spectra"

module Elevator


type TouchSensorC={ON,OFF};
type DoorMotorC={CLOSE,STOP,OPEN};
type LiftMotorC={UP,STOP,DOWN};
type LampC={ON,OFF};
type VelocityC={ZERO,SLOW,FAST};



env boolean[4] calls_c;
env boolean seconds3;
 
env boolean seconds20;
 



sys LiftMotorC liftM_c;
sys DoorMotorC doorM_c;
sys LampC lamp_c;
sys boolean countTime_c;


aux boolean[4] memCalls;

define
  goingUp             := (liftM_c=UP);
  goingDown           := (liftM_c=DOWN);
  moving              := (goingUp|goingDown);
  stayingSameHeigt    := !moving;  
  openningDoors       := (doorM_c=OPEN);
  closingDoors        := (doorM_c=CLOSE);
  keepDoorsState      := (doorM_c=STOP);
  lightIsOn           := (lamp_c=ON);
  floor0              := (aboveTheGround=0);
  floor1              := (aboveTheGround=5);
  floor2              := (aboveTheGround=10); 
  floor3              := (aboveTheGround=15);
   
  atFloorThatCalled   := (floor0&memCalls[0])|(floor1&memCalls[1])|(floor2&memCalls[2])|(floor3&memCalls[3]);
   
  doorsAreClosed      := (distanceBetweenDoors=0); 
  anyCalls            := (memCalls[0]|memCalls[1]|memCalls[2]|memCalls[3]);
  edged_floor         := (aboveTheGround=0|aboveTheGround=15);

predicate changeMonitorByOperation(boolean cond,Int(0..15) m,Int(0..2) d):
  cond<->(next(m)=(m+d-1));


 
 

 
monitor Int(0..15) aboveTheGround
{
  (aboveTheGround=0);
  G changeMonitorByOperation(goingUp,aboveTheGround,2);
  G changeMonitorByOperation(goingDown,aboveTheGround,0);
  G changeMonitorByOperation(stayingSameHeigt,aboveTheGround,1);
}


monitor Int(0..15) distanceBetweenDoors
{
  (distanceBetweenDoors=0);
  G changeMonitorByOperation(openningDoors,distanceBetweenDoors,2);
  G changeMonitorByOperation(closingDoors,distanceBetweenDoors,0);
  G changeMonitorByOperation(keepDoorsState,distanceBetweenDoors,1);
}


monitor Int(0..3) currentFloor
{
  (currentFloor=0);
  G floor0<->(currentFloor=0);
  G floor1<->(currentFloor=1);
  G floor2<->(currentFloor=2);
  G floor3<->(currentFloor=3);
}


monitor boolean returnTo0
{
   (!returnTo0);
   G (!floor0) & (((!anyCalls)&(seconds20))|returnTo0)<->next(returnTo0); 
}


gar init_motors:
  (stayingSameHeigt)&(keepDoorsState)&(!lightIsOn);
  
gar setZeroCalls:
  (!memCalls[0])&(!memCalls[1])&(!memCalls[2])&(!memCalls[3]);
  
asm
  !seconds20;
  
  
gar doorsAreClosedWhileMoving:
  G(moving -> (doorsAreClosed&keepDoorsState));

gar ifFloor0DontGoDown:
  G(floor0->!(goingDown));
  
gar ifFloor3DontGoUp:
  G(floor3->!(goingUp));
  
gar lightBlinksWhileMoving:
  G(moving->(next(lightIsOn)!=lightIsOn));

gar lightIsOffWhileNotMoving:
  G((!moving)->(!next(lightIsOn)));

gar ifCallsFromFloor0GoTo0:
  pRespondsToS(calls_c[0],floor0);

gar ifCallsFromFloor1GoTo1:
  pRespondsToS(calls_c[1],floor1);
  
 
   
  
 
   

gar dontChangeDirectionWithoutStopping:
  G((goingUp->next(!goingDown))&(goingDown->next(!goingUp)));
 
gar rememberCalls:
  G   (calls_c[0]->next(memCalls[0]))&
      (calls_c[1]->next(memCalls[1]))&
      (calls_c[2]->next(memCalls[2]))&
      (calls_c[3]->next(memCalls[3]));
    


gar ifMovingDontStopTillFloorThatCalled:
  G moving->next((stayingSameHeigt)<->(atFloorThatCalled|edged_floor));
    
 
gar ifAtFloorThatCalledRemoveCall:
    G ((floor0&!calls_c[0])->next(!memCalls[0]))&
      ((floor1&!calls_c[1])->next(!memCalls[1]))&
      ((floor2&!calls_c[2])->next(!memCalls[2]))&
      ((floor3&!calls_c[3])->next(!memCalls[3]));
/* 
asm whenCalledAndAtTheRightFloor:
  pBecomesTrue_betweenQandR(seconds3,atFloorThatCalled&(!moving),moving);
  
 
gar dontMoveWithoutReason:
  G ((!anyCalls)&(!returnTo0))->!moving; 

gar startCountingTime:
  G ((!(anyCalls|floor0))|(atFloorThatCalled&(!moving)))<->countTime_c;

gar returnTo1WhenNeeds:
  G (returnTo0&(!floor0))->goingDown;
  
asm
  G (!countTime_c)->(!(seconds20)|(seconds3));
  
*/
 
   
import "../patterns/DwyerPatterns.spectra"

module Elevator


type TouchSensorC={ON,OFF};
type DoorMotorC={CLOSE,STOP,OPEN};
type LiftMotorC={UP,STOP,DOWN};
type LampC={ON,OFF};
type VelocityC={ZERO,SLOW,FAST};



env boolean[4] calls_c;
env boolean seconds3;
 
env boolean seconds20;
 



sys LiftMotorC liftM_c;
sys DoorMotorC doorM_c;
sys LampC lamp_c;
sys boolean countTime_c;


aux boolean[4] memCalls;

define
  goingUp             := (liftM_c=UP);
  goingDown           := (liftM_c=DOWN);
  moving              := (goingUp|goingDown);
  openningDoors       := (doorM_c=OPEN);
  closingDoors        := (doorM_c=CLOSE);
  keepDoorsState      := (doorM_c=STOP);
  lightIsOn           := (lamp_c=ON);
  floor0              := (aboveTheGround=0);
  floor1              := (aboveTheGround=3);
  floor2              := (aboveTheGround=6); 
  floor3              := (aboveTheGround=9);
   
  atFloorThatCalled   := (floor0&memCalls[0])|(floor1&memCalls[1])|(floor2&memCalls[2])|(floor3&memCalls[3]);
  doorsAreFullyOpened := (distanceBetweenDoors=9);
  doorsAreClosed      := (distanceBetweenDoors=0); 
  anyCalls            := (memCalls[0]|memCalls[1]|memCalls[2]|memCalls[3]);
  edged_floor         := (aboveTheGround=0|aboveTheGround=9);

predicate changeMonitorByOperation(boolean cond,Int(0..9) m,Int(0..2) d):
  cond<->(next(m)=(m+d-1));

 
monitor Int(0..9) aboveTheGround
{
  (aboveTheGround=0);
  G changeMonitorByOperation(goingUp,aboveTheGround,2);
  G changeMonitorByOperation(goingDown,aboveTheGround,0);
  G changeMonitorByOperation(!moving,aboveTheGround,1);
  
}


monitor Int(0..9) distanceBetweenDoors
{
  (distanceBetweenDoors=0);
  G changeMonitorByOperation(openningDoors,distanceBetweenDoors,2);
  G changeMonitorByOperation(closingDoors,distanceBetweenDoors,0);
  G changeMonitorByOperation(keepDoorsState,distanceBetweenDoors,1);
}


monitor boolean returnTo0
{
   (!returnTo0);
   G (!floor0) & (((!anyCalls)&(seconds20))|returnTo0)<->next(returnTo0); 
}

monitor boolean takeCareOfFloor
{
   
  G (atFloorThatCalled&(!moving))->takeCareOfFloor;
   
  G (takeCareOfFloor&(distanceBetweenDoors=1)&closingDoors)<->(next(takeCareOfFloor)!=takeCareOfFloor);
}

gar init_motors:
  (!moving)&(keepDoorsState)&(!lightIsOn);
  
gar setZeroCalls:
  (!memCalls[0])&(!memCalls[1])&(!memCalls[2])&(!memCalls[3]);


gar doorsAreClosedWhileMoving:
  G(moving -> (doorsAreClosed&keepDoorsState));

gar ifFloor0DontGoDown:
  G(floor0->!(goingDown));
  
gar ifFloor3DontGoUp:
  G(floor3->!(goingUp));
  
gar lightBlinksWhileMoving:
  G(moving->(next(lightIsOn)!=lightIsOn));

gar lightIsOffWhileNotMoving:
  G((!moving)->(!next(lightIsOn)));

gar ifCallsFromFloor0GoTo0:
  pRespondsToS(calls_c[0],floor0);

gar ifCallsFromFloor1GoTo1:
  pRespondsToS(calls_c[1],floor1);
  
gar ifCallsFromFloor2GoTo2:
  pRespondsToS(calls_c[2],floor2);
  
gar ifCallsFromFloor3GoTo3:
  pRespondsToS(calls_c[3],floor3);

gar dontChangeDirectionWithoutStopping:
  G((goingUp->next(!goingDown))&(goingDown->next(!goingUp)));
 
gar rememberCalls:
  G   (calls_c[0]->next(memCalls[0]))&
      (calls_c[1]->next(memCalls[1]))&
      (calls_c[2]->next(memCalls[2]))&
      (calls_c[3]->next(memCalls[3]));
    


gar ifMovingDontStopTillFloorThatCalled:
  G moving->next((!moving)<->(atFloorThatCalled|edged_floor));
    
 
gar ifAtFloorThatCalledRemoveCall:
    G ((floor0&!calls_c[0])->next(!memCalls[0]))&
      ((floor1&!calls_c[1])->next(!memCalls[1]))&
      ((floor2&!calls_c[2])->next(!memCalls[2]))&
      ((floor3&!calls_c[3])->next(!memCalls[3]));
 
 
gar dontMoveWithoutReason:
  G ((!anyCalls)&(!returnTo0))->!moving; 

gar startCountingTime:
  G ((!(anyCalls|floor0))|(takeCareOfFloor&(!moving)))<->countTime_c;

gar returnTo0WhenNeeds:
   
  pBecomesTrue_betweenQandR(floor0,returnTo0,goingUp|!moving);
  
asm envDontCountTimeWhenDoesntNeed:
  G (!countTime_c)->(!next(seconds20|seconds3));

asm not20SecondsBefore3Seconds:
  G (!seconds3)->(!seconds20);
  
gar openDoorsAtFloorThatCalledBeforeMoving:
  pBecomesTrue_betweenQandR(doorsAreFullyOpened,atFloorThatCalled&(!moving),moving|keepDoorsState|closingDoors);

asm openDoorsAtFloorThatCalledIn3Seconds:
  pBecomesTrue_betweenQandR(seconds3,atFloorThatCalled&(!moving),!doorsAreClosed);

  
import "../patterns/DwyerPatterns.spectra"

module Elevator

type TouchSensorC= {ON, OFF};
type DoorMotorC= {CLOSE, STOP,OPEN};
type LiftMotorC= {UP, STOP,DOWN};
type LampC= {ON, OFF};
 



env boolean[4] calls_c;
env boolean seconds3;
env boolean seconds5;
env boolean seconds20;
 



sys LiftMotorC liftM_c;
sys DoorMotorC doorM_c;
sys LampC lamp_c;
sys boolean countTime_c;

aux boolean[4] memCalls;

define goingUp := (liftM_c = UP);
  goingDown := (liftM_c = DOWN);
  moving := (goingUp | goingDown);
  openningDoors := (doorM_c = OPEN);
  closingDoors := (doorM_c = CLOSE);
  keepDoorsState := (doorM_c = STOP);
  lightIsOn := (lamp_c = ON);
  floor0 := (aboveTheGround = 0);
  floor1 := (aboveTheGround = 3);
  floor2 := (aboveTheGround = 6); 
  floor3 := (aboveTheGround = 9);
  
  atDesignatedFloor := (floor0 & memCalls[0]) | (floor1 & memCalls[1]) | (floor2 & memCalls[2]) | (floor3 & memCalls[3]);
  doorsAreFullyOpened := (distanceBetweenDoors = 9);
  doorsAreClosed := (distanceBetweenDoors = 0); 
  anyCalls := (memCalls[0] | memCalls[1] | memCalls[2] | memCalls[3]);
  edged_floor := (floor0 | floor3);
  
   


   
  justStoppedAtDesignatedFloor   := (!handleFloor) & atDesignatedFloor & (!moving) ;
  notFinishedWithDesignatedFloor := handleFloor&!doorsAreClosed;
 
monitor Int(0..9) aboveTheGround
{
  (aboveTheGround = 0);
  G goingUp->(next (aboveTheGround) = (aboveTheGround+1)); 
  G goingDown->(next (aboveTheGround) = (aboveTheGround-1));
  G !moving->(next (aboveTheGround) = aboveTheGround);
  
}


monitor Int(0..9) distanceBetweenDoors
{
  (distanceBetweenDoors = 0);
  G openningDoors<->(next (distanceBetweenDoors) = distanceBetweenDoors+1);
  G closingDoors<->(next (distanceBetweenDoors) = distanceBetweenDoors-1);
  G keepDoorsState<->(next (distanceBetweenDoors) = distanceBetweenDoors);
}



monitor boolean returnTo0
{ (!returnTo0) ;
   G (!floor0) & (( (!anyCalls) & (seconds20) ) | returnTo0)<->next (returnTo0) ; 
}

monitor boolean handleFloor
{ (!handleFloor) ;
  G justStoppedAtDesignatedFloor -> next (handleFloor) ;
  G (notFinishedWithDesignatedFloor & next (doorsAreClosed) ) -> next (!handleFloor) ;
  G (!justStoppedAtDesignatedFloor&!(notFinishedWithDesignatedFloor&next(doorsAreClosed))) -> (next (handleFloor) = handleFloor);
}

/* 
monitor Int(0..3) currentFloor
{
  (currentFloor = 0);
  G ((floor0 -> (currentFloor = 0)) & (floor1 -> (currentFloor = 1)) & (floor2 -> (currentFloor = 2)) & (floor3 -> (currentFloor = 3)));
}

monitor Int(0..3) currentCall
{
  (currentCall = 0);
  G ((calls_c[0] -> (currentCall = 0)) &
  *  (calls_c[1] -> (currentCall = 1)) &
  *  (calls_c[2] -> (currentCall = 2)) &
  *  (calls_c[3] -> (currentCall = 3)));
     
     
     
     
}

monitor boolean dontGoUp  
{
  (dontGoUp = false);
  G (currentFloor > currentCall & !dontGoDown) -> dontGoUp;
}

monitor boolean dontGoDown  
{
  (dontGoDown = false);
  G (currentFloor < currentCall & !dontGoUp) -> dontGoDown;
}

monitor Int(0..3) lockingFloor  
                                
                                
                                
{
  (lockingFloor = 3);
  G ((dontGoUp & PREV (!dontGoUp) ) | (dontGoDown & PREV (!dontGoDown) )) -> (lockingFloor = currentFloor);
}

*/

gar init_motors:
(!moving) & (keepDoorsState) & (!lightIsOn) ;

gar setZeroCalls:
(!memCalls[0]) & (!memCalls[1]) & (!memCalls[2]) & (!memCalls[3]) ;
  
gar doorsAreClosedWhileMoving:
G (moving -> (doorsAreClosed & keepDoorsState));

gar ifFloor0DontGoDown:
G floor0 -> ! (goingDown) ;

gar ifFloor3DontGoUp:
G floor3 -> ! (goingUp) ;

gar ifClosedDoorsDontClose:
G doorsAreClosed -> (!closingDoors) ;

gar lightBlinksWhileMoving:
 
G moving -> (next (lightIsOn) != lightIsOn);

gar lightIsOffWhileNotMoving:
G (!moving) -> (next(!lightIsOn) );

gar ifCallsFromFloor0GoTo0:
pRespondsToS (calls_c[0], floor0) ;

gar ifCallsFromFloor1GoTo1:
pRespondsToS (calls_c[1], floor1) ;

gar ifCallsFromFloor2GoTo2:
pRespondsToS (calls_c[2], floor2) ;

gar ifCallsFromFloor3GoTo3:
pRespondsToS (calls_c[3], floor3) ;


gar dontChangeDirectionWithoutStopping:
G ((goingUp -> next (!goingDown) ) & (goingDown -> next (!goingUp) ));

gar ifMovingDontStopTillDesignatedFloor:
G moving -> next ((!moving)<->(atDesignatedFloor|edged_floor)) ;

gar rememberCalls:
G (calls_c[0] & (!memCalls[0]) -> next (memCalls[0]) ) &
  (calls_c[1] & (!memCalls[1]) -> next (memCalls[1]) ) &
  (calls_c[2] & (!memCalls[2]) -> next (memCalls[2]) ) &
  (calls_c[3] & (!memCalls[3]) -> next (memCalls[3]) );

gar ifFinishedWithDesignatedFloorRemoveCall:
G ((floor0 & handleFloor & next (!handleFloor)) -> next (!memCalls[0]) ) &
  ((floor1 & handleFloor & next (!handleFloor)) -> next (!memCalls[1]) ) &
  ((floor2 & handleFloor & next (!handleFloor)) -> next (!memCalls[2]) ) &
  ((floor3 & handleFloor & next (!handleFloor)) -> next (!memCalls[3]) );

gar keepRememberedCalls:
G  ((!(calls_c[0] & !memCalls[0])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[0]) = memCalls[0]) &
   ((!(calls_c[1] & !memCalls[1])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[1]) = memCalls[1]) &
   ((!(calls_c[2] & !memCalls[2])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[2]) = memCalls[2]) &
   ((!(calls_c[3] & !memCalls[3])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[3]) = memCalls[3]);

gar dontMoveWithoutReason:
G ( ((!anyCalls) & (!returnTo0))  | handleFloor) -> !moving;  

gar startCountingTime:
G ( (!(anyCalls | floor0 | moving)) | (handleFloor & (!moving) ))<->countTime_c;

gar returnTo0WhenRequired:
pBecomesTrue_betweenQandR (floor0&doorsAreClosed, returnTo0,goingUp|!moving|openningDoors|keepDoorsState) ;


asm envDoesntCountTimeWhenNotRequired:
G (!countTime_c) -> next (!seconds20&!seconds3); 


asm not20SecondsBefore3Seconds:
G (!seconds3) -> (!seconds20) ;

 
 

 
 

asm ifCount3SecAndStillCountThenNext3Sec:
G (seconds3&countTime_c)->next(seconds3);  


asm ifCount20SecAndStillCountThenNext20Sec:
G (seconds20&countTime_c)->next(seconds20);  


gar openDoorsAtDesignatedFloorBeforeMoving:
   
  pBecomesTrue_betweenQandR(doorsAreFullyOpened, justStoppedAtDesignatedFloor,moving|closingDoors|(keepDoorsState&seconds3)) ;

asm openDoorsAtFloorThatCalledIn3Seconds:
 
  pBecomesTrue_betweenQandR (seconds3,justStoppedAtDesignatedFloor,openningDoors);


 
 



 
 
 
 
 
 
import "../patterns/DwyerPatterns.spectra"

module Elevator

type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};
type LampCmd= {ON, OFF};
type FloorState={FLOOR0,FLOOR1,FLOOR2,FLOOR3,NONE};
type DoorsState={Closed,Opened,FullyOpened};
 



 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;

 
env boolean seconds3;
env boolean seconds5;
env boolean seconds20;

 
env FloorState floor_c;
env DoorsState doors_c;

 


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys LampCmd lamp_c;
sys boolean countTime_c;

 
aux boolean[4] memCalls;


 

define 
  goingUp := (liftM_c = UP);
  goingDown := (liftM_c = DOWN);
  moving := (goingUp | goingDown);
  openningDoors := (doorsM_c = OPEN);
  closingDoors := (doorsM_c = CLOSE);
  keepDoorsState := (doorsM_c = STOP);
  lightIsOn := (lamp_c = ON);
  doorsAreClosed  :=  (doors_c=Closed);
  doorsAreFullyOpened :=  (doors_c=FullyOpened);
  
  floor0  :=  (floor_c=FLOOR0);
  floor1  :=  (floor_c=FLOOR1);
  floor2  :=  (floor_c=FLOOR2);
  floor3  :=  (floor_c=FLOOR3);

  atDesignatedFloor := (floor0 & memCalls[0]) | (floor1 & memCalls[1]) | (floor2 & memCalls[2]) | (floor3 & memCalls[3]);
  anyCalls := (memCalls[0] | memCalls[1] | memCalls[2] | memCalls[3]);
  edged_floor := (floor0 | floor3);
  

   
  justArrivedToDesignatedFloor   := (!handleFloor) & atDesignatedFloor;
  justStoppedAtDesignatedFloor   := justArrivedToDesignatedFloor & (!moving)&!(returnTo0);
  notFinishedWithDesignatedFloor := handleFloor&!doorsAreClosed;
  

monitor boolean returnTo0
{  (!returnTo0) ;
   G (!floor0 & ((!anyCalls&seconds20) | returnTo0))<->next (returnTo0) ; 
}

monitor boolean handleFloor
{ (!handleFloor) ;
  G justStoppedAtDesignatedFloor -> next (handleFloor) ;
  G (notFinishedWithDesignatedFloor & next (doorsAreClosed) ) -> next (!handleFloor) ;
  G (!(justStoppedAtDesignatedFloor)&!(notFinishedWithDesignatedFloor&next(doorsAreClosed))) -> (next (handleFloor) = handleFloor);
}



gar init_motors:
(!moving) & (keepDoorsState) & (!lightIsOn) ;

asm startFromFloor0:
  floor0;
  
asm startFromClosedDoors:
  doorsAreClosed;

gar setZeroCalls:
(!memCalls[0]) & (!memCalls[1]) & (!memCalls[2]) & (!memCalls[3]) ;
  
gar doorsAreClosedWhileMoving:
G (!doorsAreClosed)->(!moving);


gar ifFloor0DontGoDown:
G floor0 -> ! (goingDown) ;

gar ifFloor3DontGoUp:
G floor3 -> ! (goingUp) ;

gar ifDoorsAreClosedDontClose:
G doorsAreClosed -> (!closingDoors) ;

gar ifDoorsAreOpenedDontOpen:
G doorsAreFullyOpened->(!openningDoors);

gar lightBlinksWhileMoving:
G moving -> (next (lightIsOn) != lightIsOn);

gar lightIsOffWhileNotMoving:
G (!moving) -> (next(!lightIsOn) );

asm ifCallsFromFloor0GoTo0:
pRespondsToS (memCalls[0], floor0) ;

asm ifCallsFromFloor1GoTo1:
pRespondsToS (memCalls[1], floor1) ;

asm ifCallsFromFloor2GoTo2:
pRespondsToS (memCalls[2], floor2) ;

asm ifCallsFromFloor3GoTo3:
pRespondsToS (memCalls[3], floor3) ;


gar dontChangeDirectionWithoutStopping:
G ((goingUp -> next (!goingDown) ) & (goingDown -> next (!goingUp) ));

gar ifMovingDontStopTillDesignatedFloorOrEdgedFloor:
G (moving&!returnTo0) -> next ((!moving)<->(atDesignatedFloor|edged_floor)) ;


gar ifAtDesignatedFloorDontMove:
  G (atDesignatedFloor&!returnTo0)->(!moving);


gar rememberCalls:
G (calls0_c & (!memCalls[0]) -> next (memCalls[0]) ) &
  (calls1_c & (!memCalls[1]) -> next (memCalls[1]) ) &
  (calls2_c & (!memCalls[2]) -> next (memCalls[2]) ) &
  (calls3_c & (!memCalls[3]) -> next (memCalls[3]) );

gar ifFinishedWithDesignatedFloorRemoveCall:
G ((floor0 & handleFloor & next (!handleFloor)) -> next (!memCalls[0]) ) &
  ((floor1 & handleFloor & next (!handleFloor)) -> next (!memCalls[1]) ) &
  ((floor2 & handleFloor & next (!handleFloor)) -> next (!memCalls[2]) ) &
  ((floor3 & handleFloor & next (!handleFloor)) -> next (!memCalls[3]) );

gar keepRememberedCalls:
G  ((!(calls0_c & !memCalls[0])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[0]) = memCalls[0]) &
   ((!(calls1_c & !memCalls[1])) & !(floor1 & handleFloor & next (!handleFloor))) -> (next (memCalls[1]) = memCalls[1]) &
   ((!(calls2_c & !memCalls[2])) & !(floor2 & handleFloor & next (!handleFloor))) -> (next (memCalls[2]) = memCalls[2]) &
   ((!(calls3_c & !memCalls[3])) & !(floor3 & handleFloor & next (!handleFloor))) -> (next (memCalls[3]) = memCalls[3]);


gar dontMoveWithoutReason:
  G ( ((!anyCalls) & (!returnTo0))  | handleFloor) -> !moving;  

gar dontOpenDoorsWithNoReason:
  G (!handleFloor)->(!openningDoors);


gar startCountingTime:
G (!(moving|anyCalls |floor0|returnTo0) | (handleFloor & (doorsAreClosed | doorsAreFullyOpened)))<->countTime_c;

/*
asm returnTo0WhenRequired:
  pBecomesTrue_betweenQandR (floor0&doorsAreClosed, returnTo0, goingUp|!moving|openningDoors|(keepDoorsState&!moving)) ;
*/

gar whenNeedToReturnTo0CloseDoors:
  G (returnTo0&(!doorsAreClosed))->closingDoors;

gar whenNeedToReturnTo0GoDown:
  G (returnTo0&!floor0&doorsAreClosed)->goingDown;


asm envDoesntCountTimeWhenNotRequired:
G (!countTime_c) -> next (!seconds20&!seconds3&!seconds5) ;


asm not20SecondsBefore3Seconds:
  G (!seconds3) -> !(seconds20|seconds5) ;

asm not20SecondsBefore5Seconds:
  G (!seconds5)->(!seconds20);


asm ifCount3SecAndStillCountThenNext3Sec:
G (seconds3&countTime_c)->next(seconds3);  

asm ifCount5SecAndStillCountThenNext5Sec:
G (seconds5&countTime_c)->next(seconds5);  

asm ifCount20SecAndStillCountThenNext20Sec:
G (seconds20&countTime_c)->next(seconds20);  


asm canCount3SecWhileHandleFloor:
  pRespondsToS (countTime_c&handleFloor, seconds3) ;

asm canCount5SecWhileDoorsAreOpened:
  pRespondsToS (countTime_c&handleFloor&doorsAreFullyOpened, seconds5) ;

asm canCount20SecWhileTheresNoCallOrThereWillBeCall:
  pRespondsToS (countTime_c&!anyCalls, seconds20|anyCalls) ;


asm ifArrivedDesignatedFloorThanDoorsWillBeFullyOpened:
  pRespondsToS(justStoppedAtDesignatedFloor, doorsAreFullyOpened);
  

asm openDoorsAtFloorThatCalledIn3Seconds:
  pBecomesTrue_betweenQandR (seconds3,justArrivedToDesignatedFloor&next(handleFloor)/*&!openningDoors*/,openningDoors);

gar doorsStayOpenedInDesignatedFloorFor5Sec:
  G (handleFloor&doorsAreFullyOpened&(!seconds5))->(!closingDoors);
import "../patterns/DwyerPatterns.spectra"

module Elevator


type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};
type LampCmd= {ON, OFF};
type FloorState={FLOOR0,FLOOR1,FLOOR2,FLOOR3,NONE};
type DoorsState={Closed,Opened,FullyOpened};
 



 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;

 
 
env boolean seconds3;
env boolean seconds5;
env boolean seconds20;
 
 
 
env FloorState floor_c;
env DoorsState doors_c;

 


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys LampCmd lamp_c;
sys boolean countTime_c;
 
 


 

define 
  goingUp := (liftM_c = UP);
  goingDown := (liftM_c = DOWN);
  moving := (liftM_c = UP | liftM_c = DOWN);
  openningDoors := (doorsM_c = OPEN);
  closingDoors := (doorsM_c = CLOSE);
  keepDoorsState := (doorsM_c = STOP);
  lightIsOn := (lamp_c = ON);
  doorsAreClosed  :=  (doors_c = Closed);
  doorsAreFullyOpened :=  (doors_c = FullyOpened);  
  floor0  :=  (floor_c=FLOOR0);
  floor1  :=  (floor_c=FLOOR1);
  floor2  :=  (floor_c=FLOOR2);
  floor3  :=  (floor_c=FLOOR3);
  edged_floor := (floor0 | floor3);
  atFloor     := floor0|floor1|floor2|floor3;  
  atDesignatedFloor := (floor0 & memCall0) | (floor1 & memCall1) | (floor2 & memCall2) | (floor3 & memCall3);
  firstMomentAtDesignatedFloor  :=  atDesignatedFloor&doorsAreClosed;
  openMomentAtDesignatedFloor   :=  atDesignatedFloor&doorsAreFullyOpened;
  
  anyCalls := (memCall0 | memCall1 | memCall2 | memCall3);
  

   
   
   
   
  returnTo0 := false;

 
 
 
 


monitor boolean memCall0
{
  !memCall0;
  G (calls0_c & !memCall0) -> next (memCall0);
  G (floor0 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall0);
  G (!(calls0_c & !memCall0) & !(floor0 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall0) = memCall0);
}

monitor boolean memCall1
{
  !memCall1;
  G (calls1_c & !memCall1) -> next (memCall1);
  G (floor1 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall1);
  G (!(calls1_c & !memCall1) & !(floor1 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (calls2_c & !memCall2) -> next (memCall2);
  G (floor2 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall2);
  G (!(calls2_c & !memCall2) & !(floor2 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (calls3_c & !memCall3) -> next (memCall3);
  G (floor3 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall3);
  G (!(calls3_c & !memCall3) & !(floor3 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall3) = memCall3);
}

/*
monitor boolean handleFloor
{ 
  (!handleFloor);
  G justStoppedAtDesignatedFloor -> next (handleFloor) ;
  G (notFinishedWithDesignatedFloor & next (doorsAreClosed) ) -> next (!handleFloor) ;
  G (!(justStoppedAtDesignatedFloor)&!(notFinishedWithDesignatedFloor&next(doorsAreClosed))) -> (next (handleFloor) = handleFloor);
}
*/
/*
gar
  pHolds_afterQuntilR(goingUp,floor0,floor3);
  
gar
  pHolds_afterQuntilR(goingDown,floor3,floor0);

gar
  G (keepDoorsState);
*/



 
gar init_motors:
(!moving) & (keepDoorsState) & (!lightIsOn) ;


 
asm startFromFloor0:
  floor0;
  
asm startFromClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart:  
  !(seconds3|seconds5|seconds20);


 
 

 
   
  
 
   
  
 
 


gar
  G !lightIsOn;
/* 
gar lightBlinksWhileMoving:
G moving -> (next (lightIsOn) = !lightIsOn);

gar lightIsOffWhileNotMoving:
G (!moving) -> (next(!lightIsOn) );
*/

gar doorsAreClosedWhileMoving:
G ((!doorsAreClosed)->(!moving)) & (moving->keepDoorsState);


 
gar ifFloor0DontGoDown:
G floor0 -> !(goingDown) ;

gar ifFloor3DontGoUp:
G floor3 -> !(goingUp) ;

gar ifDoorsAreClosedDontClose:
G doorsAreClosed -> (!closingDoors) ;

gar ifDoorsAreFullyOpenedDontOpen:
G doorsAreFullyOpened->(!openningDoors);



 
 
 




gar dontMoveWithoutAReason:
  G (((!anyCalls) & (!returnTo0)) | (returnTo0 & floor0)) -> !moving;


gar dontOpenDoorsWithoutAReason:
  G (!atDesignatedFloor)->(!openningDoors);
  
  
  
  
 
asm floorChangeCannotHappenWithoutMoving: 
  G (!moving)->(next(floor_c)=floor_c);
  
asm keepingTheStateOfTheDoors:  
  G (keepDoorsState)->(next(doors_c)=doors_c);
 
 
 
  
asm movingDoorsCauseCangeInDoorsState:
  G (openningDoors->next(!doorsAreClosed))&(closingDoors->next(!doorsAreFullyOpened));  


 
gar ifAtDesignatedFloorDontMove:
    pHolds_afterQuntilR(!moving,atDesignatedFloor,!atDesignatedFloor);
  
gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    pHolds_afterQuntilR(!openningDoors,firstMomentAtDesignatedFloor,seconds3);

 
 
 
 
gar AtDesignatedFloorOpenDoorsWithin3Seconds:
    pHolds_afterQuntilR(openningDoors,firstMomentAtDesignatedFloor&seconds3,doorsAreFullyOpened);
    
 
 
    
    
 
 


 
 






 

gar startCountingTime:
  G (/*!(moving|anyCalls |floor0|returnTo0) |*/ firstMomentAtDesignatedFloor | openMomentAtDesignatedFloor)->countTime_c;
  
asm countingTimeFirstMomentAtDesignatedFloorCount3Seconds:  
  pRespondsToS(firstMomentAtDesignatedFloor&countTime_c,seconds3);
 
 
 
  
  
/* 
asm envDoesntCountTimeWhenNotRequired:
  G (!countTime_c) -> next (!seconds3&!seconds5&!seconds20) ;

asm not20SecondsAnd5SecondsBefore3Seconds:
  G (!seconds3) -> !(seconds20|seconds5) ;

asm not20SecondsBefore5Seconds:
  G (!seconds5)->(!seconds20);

asm ifCount3SecAndStillCountThenNext3Sec:
G (seconds3&countTime_c)->next(seconds3);  

asm ifCount5SecAndStillCountThenNext5Sec:
G (seconds5&countTime_c)->next(seconds5);  

asm ifCount20SecAndStillCountThenNext20Sec:
G (seconds20&countTime_c)->next(seconds20);

*/



 


 
 


 
 

/* 
gar whenNeedToReturnTo0GoDown:
  G (returnTo0&!floor0&doorsAreClosed)->goingDown;





/*
asm canCount3SecWhileHandleFloor:
  pRespondsToS (countTime_c&handleFloor, seconds3) ;

asm canCount5SecWhileDoorsAreOpened:
  pRespondsToS (countTime_c&handleFloor&doorsAreFullyOpened, seconds5) ;

asm canCount20SecWhileTheresNoCallOrThereWillBeCall:
  pRespondsToS (countTime_c&!anyCalls, seconds20|anyCalls) ;


gar doorsStayOpenedInDesignatedFloorFor5Sec:
  G (handleFloor&doorsAreFullyOpened&(!seconds5))->(!closingDoors);

 
   
*/






import "../patterns/DwyerPatterns.spectra"

module EqualFloorsNoGF

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 

  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds20                           :=   secondsState_c=4;
   
   
   
   
  emergency_state                     :=   (emergency_c|memEmergency);
  atEmergencyFloor                    :=   (atFloor&emergency_state);
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,floor0,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,floor1,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,floor2,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,floor3,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateSabbathMode                 :=   (!sabbathMode & sabbath_c & !emergency_c & !memEmergency);
  deActivateSabbathMode               :=   (sabbathMode  & (sabbath_c|emergency_c|memEmergency));
   
   
   
  

monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}




monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}


monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}




monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean floor,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G (!doorsAreClosed)->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

 
 

 
 


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

gar AtDesignatedFloorOpenDoorsAfer3Seconds:
    G(firstStateAtDesignatedFloor&(seconds3)&!atEmergencyFloor)->openingDoors;
    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    

gar AtDesignatedFloorInSabbathModeHoldTheDoorsFullyOpenedFor10Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3|seconds5)&!memEmergency&sabbathMode&PREV(keepDoorsState))->(keepDoorsState);



 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   


 

weight notServing: -20
  true&next(anyMemCalls&!atDesignatedFloor&stayInPlace&!(returnTo0&floor0)&!atEmergencyFloor);   
                                                                                         

weight gettingFarFromFloor0: -1
  memCall0&!floor0&next(goingUp&!emergency_state);

weight gettingFarFromFloor1UP: -1
  memCall1&(floor_c>2)&next(goingUp&!emergency_state);


weight gettingFarFromFloor1DOWN: -1
  memCall1&(floor_c<2)&next(goingDown&!returnTo0&!emergency_state);

weight gettingFarFromFloor2UP: -1
  memCall2&(floor_c>4)&next(goingUp&!emergency_state);
 
weight gettingFarFromFloor2DOWN: -1
  memCall2&(floor_c<4)&next(goingDown&!returnTo0&!emergency_state);

  
weight gettingFarFromFloor3: -1
  memCall3&!floor3&next(goingDown&!returnTo0&!emergency_state);
  

 

weight gettingCloseToFloor0: 3
  memCall0&!floor0&next(goingDown&!returnTo0&!emergency_state);

  
weight gettingCloseToFloor1UP: 1
  memCall1&(floor_c<2)&next(goingUp&!emergency_state);

  
weight gettingCloseToFloor1DOWN: 2
  memCall1&(floor_c>2)&next(goingDown&!returnTo0&!emergency_state);
  
weight gettingCloseToFloor2UP: 2
  memCall2&(floor_c<4)&next(goingUp&!emergency_state);
  

weight gettingCloseToFloor2DOWN: 1
  memCall2&(floor_c>4)&next(goingDown&!emergency_state);


weight gettingCloseToFloor3: 3
  memCall3&!floor3&next(goingUp&!emergency_state);




 
import "../patterns/DwyerPatterns.spectra"

module EqualFloorsWithGF

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 

  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds20                           :=   secondsState_c=4;
   
   
   
   
  emergency_state                     :=   (emergency_c|memEmergency);
  atEmergencyFloor                    :=   (atFloor&emergency_state);
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,floor0,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,floor1,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,floor2,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,floor3,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateSabbathMode                 :=   (!sabbathMode & sabbath_c & !emergency_c & !memEmergency);
  deActivateSabbathMode               :=   (sabbathMode  & (sabbath_c|emergency_c|memEmergency));
   
   
   
  

monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}




monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}


monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}




monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean floor,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G (!doorsAreClosed)->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

 
 

 
 


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

gar AtDesignatedFloorOpenDoorsAfer3Seconds:
    G(firstStateAtDesignatedFloor&(seconds3)&!atEmergencyFloor)->openingDoors;
    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    

gar AtDesignatedFloorInSabbathModeHoldTheDoorsFullyOpenedFor10Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3|seconds5)&!memEmergency&sabbathMode&PREV(keepDoorsState))->(keepDoorsState);


 


gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);




 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   


 

weight notServing: -20
  true&next(anyMemCalls&!atDesignatedFloor&stayInPlace&!(returnTo0&floor0)&!atEmergencyFloor);   
                                                                                         

weight gettingFarFromFloor0: -1
  memCall0&!floor0&next(goingUp&!emergency_state);

weight gettingFarFromFloor1UP: -1
  memCall1&(floor_c>2)&next(goingUp&!emergency_state);


weight gettingFarFromFloor1DOWN: -1
  memCall1&(floor_c<2)&next(goingDown&!returnTo0&!emergency_state);

weight gettingFarFromFloor2UP: -1
  memCall2&(floor_c>4)&next(goingUp&!emergency_state);
 
weight gettingFarFromFloor2DOWN: -1
  memCall2&(floor_c<4)&next(goingDown&!returnTo0&!emergency_state);

  
weight gettingFarFromFloor3: -1
  memCall3&!floor3&next(goingDown&!returnTo0&!emergency_state);
  

 

weight gettingCloseToFloor0: 3
  memCall0&!floor0&next(goingDown&!returnTo0&!emergency_state);

  
weight gettingCloseToFloor1UP: 1
  memCall1&(floor_c<2)&next(goingUp&!emergency_state);

  
weight gettingCloseToFloor1DOWN: 2
  memCall1&(floor_c>2)&next(goingDown&!returnTo0&!emergency_state);
  
weight gettingCloseToFloor2UP: 2
  memCall2&(floor_c<4)&next(goingUp&!emergency_state);
  

weight gettingCloseToFloor2DOWN: 1
  memCall2&(floor_c>4)&next(goingDown&!emergency_state);


weight gettingCloseToFloor3: 3
  memCall3&!floor3&next(goingUp&!emergency_state);




 
import "../patterns/DwyerPatterns.spectra"

module FavoriteFloor3NoGF

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 

  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds20                           :=   secondsState_c=4;
   
   
   
   
  emergency_state                     :=   (emergency_c|memEmergency);
  atEmergencyFloor                    :=   (atFloor&emergency_state);
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,floor0,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,floor1,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,floor2,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,floor3,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
   
   
   
   
   
  sabbathMode                         := false;

monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}




monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}

/*
monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}
*/



monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean floor,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G (!doorsAreClosed)->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

 
 

 
 


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

gar AtDesignatedFloorOpenDoorsAfer3Seconds:
    G(firstStateAtDesignatedFloor&(seconds3)&!atEmergencyFloor)->openingDoors;
    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    

 
 


 

/*
gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);
*/



 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   


 

weight notServing: -20
  true&next(anyMemCalls&!atDesignatedFloor&stayInPlace&!(returnTo0&floor0)&!atEmergencyFloor);   
                                                                                         
weight gettingFarFromFloor0: -1
  stayInPlace&next(memCall0&!floor0&goingUp&!emergency_state);

weight gettingFarFromFloor1UP: -1
  stayInPlace&next(memCall1&(floor_c>2)&goingUp&!emergency_state);

/*
weight gettingFarFromFloor1DOWN: -1
  stayInPlace&next(memCall1&(floor_c<2)&goingDown&!returnTo0&!emergency_state);
*/

/*
weight gettingFarFromFloor2UP: -1
  stayInPlace&next(memCall2&(floor_c>4)&goingUp&!emergency_state);
*/  

weight gettingFarFromFloor2DOWN: -1
  stayInPlace&next(memCall2&(floor_c<4)&goingDown&!returnTo0&!emergency_state);

  
weight gettingFarFromFloor3h: -3
  stayInPlace&next(memCall3&!floor3&goingDown&!returnTo0&!emergency_state);

 

weight gettingCloseToFloor0: 1
  stayInPlace&next(memCall0&!floor0&goingDown&!returnTo0&!emergency_state);

/*  
weight gettingCloseToFloor1UP: 1
  stayInPlace&next(memCall1&(floor_c<2)&goingUp&!emergency_state);
*/
  
weight gettingCloseToFloor1DOWN: 1
  stayInPlace&next(memCall1&(floor_c>2)&goingDown&!returnTo0&!emergency_state);
  
weight gettingCloseToFloor2UP: 1
  stayInPlace&next(memCall2&(floor_c<4)&goingUp&!emergency_state);
  
/*
weight gettingCloseToFloor2DOWN: 1
  stayInPlace&next(memCall2&(floor_c>4)&goingDown&!emergency_state);
*/

weight gettingCloseToFloor3: 2
  stayInPlace&next(memCall3&!floor3&goingUp&!emergency_state);




 
import "../patterns/DwyerPatterns.spectra"

module FavoriteFloor3NoGF

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 

  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds20                           :=   secondsState_c=4;
   
   
   
   
  emergency_state                     :=   (emergency_c|memEmergency);
  atEmergencyFloor                    :=   (atFloor&emergency_state);
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,floor0,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,floor1,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,floor2,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode /*& !sabbath_c*/ & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,floor3,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
   
   
   
   
   
  sabbathMode                         := false;

monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}




monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}

/*
monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}
*/



monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean floor,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G (!doorsAreClosed)->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

 
 

 
 


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

gar AtDesignatedFloorOpenDoorsAfer3Seconds:
    G(firstStateAtDesignatedFloor&(seconds3)&!atEmergencyFloor)->openingDoors;
    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    

 
 


 


gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);




 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   


 

weight notServing: -20
  true&next(anyMemCalls&!atDesignatedFloor&stayInPlace&!(returnTo0&floor0)&!atEmergencyFloor);   
                                                                                         
weight gettingFarFromFloor0: -1
  stayInPlace&atFloor&next(memCall0&!floor0&goingUp&!emergency_state);

weight gettingFarFromFloor1UP: -1
  stayInPlace&atFloor&next(memCall1&(floor_c>2)&goingUp&!emergency_state);

/*
weight gettingFarFromFloor1DOWN: -1
  stayInPlace&next(memCall1&(floor_c<2)&goingDown&!returnTo0&!emergency_state);
*/

/*
weight gettingFarFromFloor2UP: -1
  stayInPlace&next(memCall2&(floor_c>4)&goingUp&!emergency_state);
*/  

weight gettingFarFromFloor2DOWN: -1
  stayInPlace&atFloor&next(memCall2&(floor_c<4)&goingDown&!returnTo0&!emergency_state);

  
weight gettingFarFromFloor3: -10
  stayInPlace&atFloor&next(memCall3&!floor3&goingDown&!returnTo0&!emergency_state);

 

weight gettingCloseToFloor0: 1
  stayInPlace&atFloor&next(memCall0&!floor0&goingDown&!returnTo0&!emergency_state);

/*  
weight gettingCloseToFloor1UP: 1
  stayInPlace&next(memCall1&(floor_c<2)&goingUp&!emergency_state);
*/
  
weight gettingCloseToFloor1DOWN: 1
  stayInPlace&atFloor&next(memCall1&(floor_c>2)&goingDown&!returnTo0&!emergency_state);
  
weight gettingCloseToFloor2UP: 1
  stayInPlace&atFloor&next(memCall2&(floor_c<4)&goingUp&!emergency_state);
  
/*
weight gettingCloseToFloor2DOWN: 1
  stayInPlace&next(memCall2&(floor_c>4)&goingDown&!emergency_state);
*/

weight gettingCloseToFloor3: 2
  stayInPlace&atFloor&next(memCall3&!floor3&goingUp&!emergency_state);




 
import "../patterns/DwyerPatterns.spectra"

module Elevator


type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};
type LampCmd= {ON, OFF};
type FloorState={FLOOR0,FLOOR1,FLOOR2,FLOOR3,NONE};
type DoorsState={Closed,Opened,FullyOpened};
 



 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;

 
 
env boolean seconds3;
env boolean seconds5;
env boolean seconds20;
 
 
 
env FloorState floor_c;
env DoorsState doors_c;

 


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys LampCmd lamp_c;
sys boolean countTime_c;


 

define 
  goingUp                      :=   (liftM_c = UP);
  goingDown                    :=   (liftM_c = DOWN);
  moving                       :=   (liftM_c = UP | liftM_c = DOWN);
  openningDoors                :=   (doorsM_c = OPEN);
  closingDoors                 :=   (doorsM_c = CLOSE);
  keepDoorsState               :=   (doorsM_c = STOP);
  lightIsOn                    :=   (lamp_c = ON);
  doorsAreClosed               :=   (doors_c = Closed);
  doorsAreFullyOpened          :=   (doors_c = FullyOpened);  
  floor0                       :=   (floor_c=FLOOR0);
  floor1                       :=   (floor_c=FLOOR1);
  floor2                       :=   (floor_c=FLOOR2);
  floor3                       :=   (floor_c=FLOOR3);
  atEdgedFloor                 :=   (floor0 | floor3);
  atFloor                      :=   floor0|floor1|floor2|floor3; 
  anyCalls                     :=   (memCall0 | memCall1 | memCall2 | memCall3); 
  atDesignatedFloor            :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor  :=   atDesignatedFloor&doorsAreClosed;
  openStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  

  returnTo0 := false;
/*
monitor boolean returnTo0
{  !returnTo0;
   G (!floor0 & ((!anyCalls&seconds20) | returnTo0))<->next (returnTo0) ; 
}
*/

monitor boolean memCall0
{
  !memCall0;
  G (calls0_c & !memCall0) -> next (memCall0);
  G (floor0 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall0);
  G (!(calls0_c & !memCall0) & !(floor0 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall0) = memCall0);
}

monitor boolean memCall1
{
  !memCall1;
  G (calls1_c & !memCall1) -> next (memCall1);
  G (floor1 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall1);
  G (!(calls1_c & !memCall1) & !(floor1 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (calls2_c & !memCall2) -> next (memCall2);
  G (floor2 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall2);
  G (!(calls2_c & !memCall2) & !(floor2 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (calls3_c & !memCall3) -> next (memCall3);
  G (floor3 & !doorsAreClosed & next (doorsAreClosed)) -> next (!memCall3);
  G (!(calls3_c & !memCall3) & !(floor3 & !doorsAreClosed & next (doorsAreClosed))) -> (next (memCall3) = memCall3);
}


/* 
gar
  pHolds_afterQuntilR(openningDoors,doorsAreClosed,doorsAreFullyOpened);
  
gar
  pHolds_afterQuntilR(closingDoors,doorsAreFullyOpened,doorsAreClosed);

gar
  G (!moving);
*/

/*
gar
  pHolds_afterQuntilR(goingUp,floor0,floor1);
  
gar
  pHolds_afterQuntilR(goingDown,floor1,floor0);

gar
  G (keepDoorsState);

*/


 
gar init_motors:
(!moving) & (keepDoorsState) & (!lightIsOn) ;


 
asm startFromFloor0:
  floor0;
  
asm startFromClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart:  
  !(seconds3|seconds5|seconds20);



gar
  G !lightIsOn;
/* 
gar lightBlinksWhileMoving:
G moving -> (next (lightIsOn) = !lightIsOn);

gar lightIsOffWhileNotMoving:
G (!moving) -> (next(!lightIsOn) );
*/

gar doorsAreClosedWhileMoving:
G ((!doorsAreClosed)->(!moving)) & (moving->keepDoorsState);


 
gar ifFloor0DontGoDown:
G floor0 -> !(goingDown) ;

gar ifFloor3DontGoUp:
G floor3 -> !(goingUp) ;

gar ifDoorsAreClosedDontClose:
G doorsAreClosed -> (!closingDoors) ;

gar ifDoorsAreFullyOpenedDontOpen:
G doorsAreFullyOpened->(!openningDoors);


gar dontMoveWithoutAReason:
  G (((!anyCalls) & (!returnTo0))| (returnTo0 & floor0)) -> !moving;


gar dontOpenDoorsWithoutAReason:
  G (!atDesignatedFloor)->(!openningDoors);
  
gar dontStopWithoutAReason:
  G moving->(next(!moving)->(atDesignatedFloor|atEdgedFloor));
  
  
  
 
asm floorChangeCannotHappenWithoutMoving: 
  G (!moving)->(next(floor_c)=floor_c);
  
  
asm keepingTheStateOfTheDoors:  
  G (keepDoorsState)->(next(doors_c)=doors_c);
 
 
 
  
  
asm movingDoorsCauseChangeInDoorsState:
  G (openningDoors->next(!doorsAreClosed))&(closingDoors->next(!doorsAreFullyOpened));  


asm goingUpFromFloor0CauseBehingAtFloor1:
  pRespondsToS(floor0&goingUp,floor1);
  
asm goingUpFromFloor1CauseBehingAtFloor2:
  pRespondsToS(floor1&goingUp,floor2);

asm goingUpFromFloor2CauseBehingAtFloor3:
  pRespondsToS(floor2&goingUp,floor3); 
  
asm goingDownFromFloor1CauseBehingAtFloor0:
  pRespondsToS(floor1&goingDown,floor0);
  
asm goingDownFromFloor2CauseBehingAtFloor1:
  pRespondsToS(floor2&goingDown,floor1);

asm goingDownFromFloor3CauseBehingAtFloor2:
  pRespondsToS(floor3&goingDown,floor2);






 
gar ifAtDesignatedFloorDontMove:
     
    G atDesignatedFloor->(!moving);
    
gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    pHolds_afterQuntilR(!openningDoors,firstStateAtDesignatedFloor,seconds3);

 
 
 
 
gar AtDesignatedFloorOpenDoorsWithin3Seconds:
    pHolds_afterQuntilR(openningDoors,firstStateAtDesignatedFloor&seconds3,doorsAreFullyOpened);
    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    pHolds_afterQuntilR(keepDoorsState,doorsAreFullyOpened,seconds5);

        


 

gar startCountingTime:
  G (/*!(moving|anyCalls |floor0|returnTo0) |*/ firstStateAtDesignatedFloor | openStateAtDesignatedFloor)<->countTime_c;
 
   
 
 
 
 
 
  
asm envDoesntCountTimeWhenNotRequired:
  G (!countTime_c) -> next (!seconds3&!seconds5&!seconds20) ;

asm not20SecondsAnd5SecondsBefore3Seconds:
  G (!seconds3) -> !(seconds20|seconds5) ;

asm not20SecondsBefore5Seconds:
  G (!seconds5)->(!seconds20);

asm ifCount3SecAndStillCountThenNext3Sec:
G (seconds3&countTime_c)->next(seconds3);  

asm ifCount5SecAndStillCountThenNext5Sec:
G (seconds5&countTime_c)->next(seconds5);  

asm ifCount20SecAndStillCountThenNext20Sec:
G (seconds20&countTime_c)->next(seconds20);



 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  



  


 


 
   


import "../patterns/DwyerPatterns.spectra"

module Elevator

type TouchSensorC= {ON, OFF};
type DoorMotorC= {CLOSE, STOP,OPEN};
type LiftMotorC= {UP, STOP,DOWN};
type LampC= {ON, OFF};
 



env boolean[4] calls_c;
env boolean seconds3;
env boolean seconds5;
env boolean seconds20;
 



sys LiftMotorC liftM_c;
sys DoorMotorC doorM_c;
sys LampC lamp_c;
sys boolean countTime_c;

aux boolean[4] memCalls;

define goingUp := (liftM_c = UP);
  goingDown := (liftM_c = DOWN);
  moving := (goingUp | goingDown);
  openningDoors := (doorM_c = OPEN);
  closingDoors := (doorM_c = CLOSE);
  keepDoorsState := (doorM_c = STOP);
  lightIsOn := (lamp_c = ON);
  floor0 := (aboveTheGround = 0);
  floor1 := (aboveTheGround = 3);
  floor2 := (aboveTheGround = 6); 
  floor3 := (aboveTheGround = 9);
  
  atDesignatedFloor := (floor0 & memCalls[0]) | (floor1 & memCalls[1]) | (floor2 & memCalls[2]) | (floor3 & memCalls[3]);
  doorsAreFullyOpened := (distanceBetweenDoors = 9);
  doorsAreClosed := (distanceBetweenDoors = 0); 
  anyCalls := (memCalls[0] | memCalls[1] | memCalls[2] | memCalls[3]);
  edged_floor := (floor0 | floor3);
  
   


   
  justStoppedAtDesignatedFloor   := (!handleFloor) & atDesignatedFloor & (!moving) ;
  notFinishedWithDesignatedFloor := handleFloor&!doorsAreClosed;
 
monitor Int(0..9) aboveTheGround
{
  (aboveTheGround = 0);
  G goingUp->(next (aboveTheGround) = (aboveTheGround+1)); 
  G goingDown->(next (aboveTheGround) = (aboveTheGround-1));
  G !moving->(next (aboveTheGround) = aboveTheGround);
  
}


monitor Int(0..9) distanceBetweenDoors
{
  (distanceBetweenDoors = 0);
  G openningDoors<->(next (distanceBetweenDoors) = distanceBetweenDoors+1);
  G closingDoors<->(next (distanceBetweenDoors) = distanceBetweenDoors-1);
  G keepDoorsState<->(next (distanceBetweenDoors) = distanceBetweenDoors);
}



monitor boolean returnTo0
{ (!returnTo0) ;
   G (!floor0) & (( (!anyCalls) & (seconds20) ) | returnTo0)<->next (returnTo0) ; 
}

monitor boolean handleFloor
{ (!handleFloor) ;
  G justStoppedAtDesignatedFloor -> next (handleFloor) ;
  G (notFinishedWithDesignatedFloor & next (doorsAreClosed) ) -> next (!handleFloor) ;
  G (!justStoppedAtDesignatedFloor&!(notFinishedWithDesignatedFloor&next(doorsAreClosed))) -> (next (handleFloor) = handleFloor);
}

/* 
monitor Int(0..3) currentFloor
{
  (currentFloor = 0);
  G ((floor0 -> (currentFloor = 0)) & (floor1 -> (currentFloor = 1)) & (floor2 -> (currentFloor = 2)) & (floor3 -> (currentFloor = 3)));
}

monitor Int(0..3) currentCall
{
  (currentCall = 0);
  G ((calls_c[0] -> (currentCall = 0)) &
  *  (calls_c[1] -> (currentCall = 1)) &
  *  (calls_c[2] -> (currentCall = 2)) &
  *  (calls_c[3] -> (currentCall = 3)));
     
     
     
     
}

monitor boolean dontGoUp  
{
  (dontGoUp = false);
  G (currentFloor > currentCall & !dontGoDown) -> dontGoUp;
}

monitor boolean dontGoDown  
{
  (dontGoDown = false);
  G (currentFloor < currentCall & !dontGoUp) -> dontGoDown;
}

monitor Int(0..3) lockingFloor  
                                
                                
                                
{
  (lockingFloor = 3);
  G ((dontGoUp & PREV (!dontGoUp) ) | (dontGoDown & PREV (!dontGoDown) )) -> (lockingFloor = currentFloor);
}

*/

gar init_motors:
(!moving) & (keepDoorsState) & (!lightIsOn) ;

gar setZeroCalls:
(!memCalls[0]) & (!memCalls[1]) & (!memCalls[2]) & (!memCalls[3]) ;
  
gar doorsAreClosedWhileMoving:
G (moving -> (doorsAreClosed & keepDoorsState));

gar ifFloor0DontGoDown:
G floor0 -> ! (goingDown) ;

gar ifFloor3DontGoUp:
G floor3 -> ! (goingUp) ;

gar ifClosedDoorsDontClose:
G doorsAreClosed -> (!closingDoors) ;

gar lightBlinksWhileMoving:
 
G moving -> (next (lightIsOn) != lightIsOn);

gar lightIsOffWhileNotMoving:
G (!moving) -> (next(!lightIsOn) );

gar ifCallsFromFloor0GoTo0:
pRespondsToS (calls_c[0], floor0) ;

gar ifCallsFromFloor1GoTo1:
pRespondsToS (calls_c[1], floor1) ;

gar ifCallsFromFloor2GoTo2:
pRespondsToS (calls_c[2], floor2) ;

gar ifCallsFromFloor3GoTo3:
pRespondsToS (calls_c[3], floor3) ;


gar dontChangeDirectionWithoutStopping:
G ((goingUp -> next (!goingDown) ) & (goingDown -> next (!goingUp) ));

gar ifMovingDontStopTillDesignatedFloor:
G moving -> next ((!moving)<->(atDesignatedFloor|edged_floor)) ;

gar rememberCalls:
G (calls_c[0] & (!memCalls[0]) -> next (memCalls[0]) ) &
  (calls_c[1] & (!memCalls[1]) -> next (memCalls[1]) ) &
  (calls_c[2] & (!memCalls[2]) -> next (memCalls[2]) ) &
  (calls_c[3] & (!memCalls[3]) -> next (memCalls[3]) );

gar ifFinishedWithDesignatedFloorRemoveCall:
G ((floor0 & handleFloor & next (!handleFloor)) -> next (!memCalls[0]) ) &
  ((floor1 & handleFloor & next (!handleFloor)) -> next (!memCalls[1]) ) &
  ((floor2 & handleFloor & next (!handleFloor)) -> next (!memCalls[2]) ) &
  ((floor3 & handleFloor & next (!handleFloor)) -> next (!memCalls[3]) );

gar keepRememberedCalls:
G  ((!(calls_c[0] & !memCalls[0])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[0]) = memCalls[0]) &
   ((!(calls_c[1] & !memCalls[1])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[1]) = memCalls[1]) &
   ((!(calls_c[2] & !memCalls[2])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[2]) = memCalls[2]) &
   ((!(calls_c[3] & !memCalls[3])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[3]) = memCalls[3]);

gar dontMoveWithoutReason:
G ( ((!anyCalls) & (!returnTo0))  | handleFloor) -> !moving;  

gar startCountingTime:
G ( (!(anyCalls | floor0 | moving)) | (handleFloor & (!moving) ))<->countTime_c;

gar returnTo0WhenRequired:
pBecomesTrue_betweenQandR (floor0&doorsAreClosed, returnTo0,goingUp|!moving|openningDoors|keepDoorsState) ;


asm envDoesntCountTimeWhenNotRequired:
G (!countTime_c) -> next (!seconds20&!seconds3); 


asm not20SecondsBefore3Seconds:
G (!seconds3) -> (!seconds20) ;

 
 

 
 

asm ifCount3SecAndStillCountThenNext3Sec:
G (seconds3&countTime_c)->next(seconds3);  


asm ifCount20SecAndStillCountThenNext20Sec:
G (seconds20&countTime_c)->next(seconds20);  


gar openDoorsAtDesignatedFloorBeforeMoving:
   
  pBecomesTrue_betweenQandR(doorsAreFullyOpened, justStoppedAtDesignatedFloor,moving|closingDoors|(keepDoorsState&seconds3)) ;

asm openDoorsAtFloorThatCalledIn3Seconds:
 
  pBecomesTrue_betweenQandR (seconds3,justStoppedAtDesignatedFloor,openningDoors);


 
 



 
 
 
 
 
 
import "../patterns/DwyerPatterns.spectra"

module Elevator

type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};
type LampCmd= {ON, OFF};
type FloorState={FLOOR0,FLOOR1,FLOOR2,FLOOR3,NONE};
type DoorsState={Closed,Opened,FullyOpened};
 



 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;

 
env boolean seconds3;
env boolean seconds5;
env boolean seconds20;

 
env FloorState floor_c;
env DoorsState doors_c;

 


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys LampCmd lamp_c;
sys boolean countTime_c;

 
aux boolean[4] memCalls;


 

define 
  goingUp := (liftM_c = UP);
  goingDown := (liftM_c = DOWN);
  moving := (goingUp | goingDown);
  openningDoors := (doorsM_c = OPEN);
  closingDoors := (doorsM_c = CLOSE);
  keepDoorsState := (doorsM_c = STOP);
  lightIsOn := (lamp_c = ON);
  doorsAreClosed  :=  (doors_c=Closed);
  doorsAreFullyOpened :=  (doors_c=FullyOpened);
  
  floor0  :=  (floor_c=FLOOR0);
  floor1  :=  (floor_c=FLOOR1);
  floor2  :=  (floor_c=FLOOR2);
  floor3  :=  (floor_c=FLOOR3);

  atDesignatedFloor := (floor0 & memCalls[0]) | (floor1 & memCalls[1]) | (floor2 & memCalls[2]) | (floor3 & memCalls[3]);
  anyCalls := (memCalls[0] | memCalls[1] | memCalls[2] | memCalls[3]);
  edged_floor := (floor0 | floor3);
  

   
  justArrivedToDesignatedFloor   := (!handleFloor) & atDesignatedFloor;
  justStoppedAtDesignatedFloor   := justArrivedToDesignatedFloor & (!moving)&!(returnTo0);
  notFinishedWithDesignatedFloor := handleFloor&!doorsAreClosed;
  

monitor boolean returnTo0
{  (!returnTo0) ;
   G (!floor0 & ((!anyCalls&seconds20) | returnTo0))<->next (returnTo0) ; 
}

monitor boolean handleFloor
{ (!handleFloor) ;
  G justStoppedAtDesignatedFloor -> next (handleFloor) ;
  G (notFinishedWithDesignatedFloor & next (doorsAreClosed) ) -> next (!handleFloor) ;
  G (!(justStoppedAtDesignatedFloor)&!(notFinishedWithDesignatedFloor&next(doorsAreClosed))) -> (next (handleFloor) = handleFloor);
}



gar init_motors:
(!moving) & (keepDoorsState) & (!lightIsOn) ;

asm startFromFloor0:
  floor0;
  
asm startFromClosedDoors:
  doorsAreClosed;


asm atTheStartNoSecondsCounted:
  !(seconds3|seconds5|seconds20);



gar setZeroCalls:
(!memCalls[0]) & (!memCalls[1]) & (!memCalls[2]) & (!memCalls[3]) ;
  
gar doorsAreClosedWhileMoving:
G (!doorsAreClosed)->(!moving);


gar ifFloor0DontGoDown:
G floor0 -> ! (goingDown) ;

gar ifFloor3DontGoUp:
G floor3 -> ! (goingUp) ;

gar ifDoorsAreClosedDontClose:
G doorsAreClosed -> (!closingDoors) ;

gar ifDoorsAreFullyOpenedDontOpen:
G doorsAreFullyOpened->(!openningDoors);

gar lightBlinksWhileMoving:
G moving -> (next (lightIsOn) != lightIsOn);

gar lightIsOffWhileNotMoving:
G (!moving) -> (next(!lightIsOn) );

asm ifCallsFromFloor0GoTo0:
pRespondsToS (memCalls[0], floor0) ;

asm ifCallsFromFloor1GoTo1:
pRespondsToS (memCalls[1], floor1) ;

asm ifCallsFromFloor2GoTo2:
pRespondsToS (memCalls[2], floor2) ;

asm ifCallsFromFloor3GoTo3:
pRespondsToS (memCalls[3], floor3) ;


gar dontChangeDirectionWithoutStopping:
G ((goingUp -> next (!goingDown) ) & (goingDown -> next (!goingUp) ));

gar ifMovingDontStopTillDesignatedFloorOrEdgedFloor:
G (moving&!returnTo0) -> next ((!moving)<->(atDesignatedFloor|edged_floor)) ;


gar ifAtDesignatedFloorDontMove:
  G (atDesignatedFloor&!returnTo0)->(!moving);


gar rememberCalls:
G (calls0_c & (!memCalls[0]) -> next (memCalls[0]) ) &
  (calls1_c & (!memCalls[1]) -> next (memCalls[1]) ) &
  (calls2_c & (!memCalls[2]) -> next (memCalls[2]) ) &
  (calls3_c & (!memCalls[3]) -> next (memCalls[3]) );

gar ifFinishedWithDesignatedFloorRemoveCall:
G ((floor0 & handleFloor & next (!handleFloor)) -> next (!memCalls[0]) ) &
  ((floor1 & handleFloor & next (!handleFloor)) -> next (!memCalls[1]) ) &
  ((floor2 & handleFloor & next (!handleFloor)) -> next (!memCalls[2]) ) &
  ((floor3 & handleFloor & next (!handleFloor)) -> next (!memCalls[3]) );

gar keepRememberedCalls:
G  ((!(calls0_c & !memCalls[0])) & !(floor0 & handleFloor & next (!handleFloor))) -> (next (memCalls[0]) = memCalls[0]) &
   ((!(calls1_c & !memCalls[1])) & !(floor1 & handleFloor & next (!handleFloor))) -> (next (memCalls[1]) = memCalls[1]) &
   ((!(calls2_c & !memCalls[2])) & !(floor2 & handleFloor & next (!handleFloor))) -> (next (memCalls[2]) = memCalls[2]) &
   ((!(calls3_c & !memCalls[3])) & !(floor3 & handleFloor & next (!handleFloor))) -> (next (memCalls[3]) = memCalls[3]);


gar dontMoveWithoutReason:
  G ( ((!anyCalls) & (!returnTo0))  | handleFloor) -> !moving;  

gar dontOpenDoorsWithNoReason:
  G (!handleFloor)->(!openningDoors);


gar startCountingTime:
G (!(moving|anyCalls |floor0|returnTo0) | (handleFloor & (doorsAreClosed | doorsAreFullyOpened)))<->countTime_c;

/*
asm returnTo0WhenRequired:
  pBecomesTrue_betweenQandR (floor0&doorsAreClosed, returnTo0, goingUp|!moving|openningDoors|(keepDoorsState&!moving)) ;
*/

gar whenNeedToReturnTo0CloseDoors:
  G (returnTo0&(!doorsAreClosed))->closingDoors;

gar whenNeedToReturnTo0GoDown:
  G (returnTo0&!floor0&doorsAreClosed)->goingDown;


asm envDoesntCountTimeWhenNotRequired:
G (!countTime_c) -> next (!seconds20&!seconds3&!seconds5) ;


asm not20SecondsBefore3Seconds:
  G (!seconds3) -> !(seconds20|seconds5) ;

asm not20SecondsBefore5Seconds:
  G (!seconds5)->(!seconds20);


asm ifCount3SecAndStillCountThenNext3Sec:
G (seconds3&countTime_c)->next(seconds3);  

asm ifCount5SecAndStillCountThenNext5Sec:
G (seconds5&countTime_c)->next(seconds5);  

asm ifCount20SecAndStillCountThenNext20Sec:
G (seconds20&countTime_c)->next(seconds20);  


asm canCount3SecWhileHandleFloor:
  pRespondsToS (countTime_c&handleFloor, seconds3) ;

asm canCount5SecWhileDoorsAreOpened:
  pRespondsToS (countTime_c&handleFloor&doorsAreFullyOpened, seconds5) ;

asm canCount20SecWhileTheresNoCallOrThereWillBeCall:
  pRespondsToS (countTime_c&!anyCalls, seconds20|anyCalls) ;


asm ifArrivedDesignatedFloorThanDoorsWillBeFullyOpened:
  pRespondsToS(justStoppedAtDesignatedFloor, doorsAreFullyOpened);
  

asm openDoorsAtFloorThatCalledIn3Seconds:
  pBecomesTrue_betweenQandR (seconds3,justArrivedToDesignatedFloor&next(handleFloor)/*&!openningDoors*/,openningDoors);

gar doorsStayOpenedInDesignatedFloorFor5Sec:
  G (handleFloor&doorsAreFullyOpened&(!seconds5))->(!closingDoors);
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 
 
gar 
mode = PARKING & driveMotor = STOP & steeringMotor = STRAIGHT & velocity=0;

gar
G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar
G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

gar
G mode = PARKING -> velocity <= 1;


 
gar
G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = PARKING );  

gar
G (align = false) -> (next(mode) = PARKING );


 
gar 
G(mode = PARKING & status = REVERSE & align = false & done = false & next(frontSense >0)) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar
G(mode = PARKING & status = REVERSE & align = true & done = false & next(frontSense >0)) -> (next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = PARKING ) ;

 
gar
G(mode = PARKING & status = PARALLEL & align = false & done = false & next(frontSense >0)) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar
G(mode = PARKING & status = PARALLEL & align = true & done = false & next(frontSense >0)) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = PARKING ) ;
 
 
 


 
gar 
GF (mode = PARKED);

 
gar
pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar
pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);

gar
G forwarding -> frontSense > 0;


 
 
 
 
gar
G(valid_parking_spot) -> (next(mode) = PARKED);

 
gar
G(mode = PARKED -> stopping);

 
gar
G driveMotor = STOP -> next(velocity) <= velocity;

 
 
 
 
 
 

 
 

 
 
 
 

 

 
asm 
(status = PARALLEL)  & (color =BLACK) & (sideSense >0 | frontSense>0) & (align = false) & (done = false);

 
asm
pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm
pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 

 
asm 
GF valid_parking_spot | stopping;

 
 

 
asm
GF sideSense > 0 | stopping;

asm
GF frontSense > 0 | stopping;

 
asm
G (status = PARALLEL) -> (next(status) = PARALLEL);

asm
G (status = REVERSE) -> (next(status) = REVERSE);

 
 

asm
G forwarding & mode !=PARKING -> next(frontSense) <= frontSense;  

 
 

 
 

 
 

 
 

asm
pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm
pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) | frontSense = 0);

asm
pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm
pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm
pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm
pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm
G stopping -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color & next(align) = align & next(done) = done);

asm
G steeringMotor = STRAIGHT & (mode != PARKING) -> next(sideSense) = sideSense;  
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type SenseMotorCmd = {SIDE, BACK};
type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color = GREEN);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 
 
gar 
mode = PARKING & driveMotor = STOP & steeringMotor = STRAIGHT;

 
gar 
GF (mode = PARKED);  

 
gar
G (mode = PARKED) <-> (valid_parking_spot = true);

guarantee dontCrashSide:
G (PREV(sideSense <= 1)) -> (!right);

 
 
 
 

 

 
asm 
(status = PARALLEL) &(sideStatus = NONE) & (color !=GREEN);

 
asm
pRespondsToS((reversing) & (right), (color != BLACK));  
 

 
asm 
GF valid_parking_spot;

 
asm
G (status = PARALLEL) -> (next(status) = PARALLEL);

asm
G (status = REVERSE) -> (next(status) = REVERSE);

 
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type SenseMotorCmd = {SIDE, BACK};
type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color = GREEN);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 
 
gar 
mode = PARKING & driveMotor = STOP & steeringMotor = STRAIGHT;

gar
G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar
G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

gar
G (mode = PARKING) <-> (velocity = 1);

gar
G mode = PARKING -> next(mode = PARKING | mode = PARKED);

 
gar 
GF (mode = PARKED);

 
 
 
gar
G(valid_parking_spot <-> next(mode = PARKED));

gar
G(mode = PARKED -> stopping);

guarantee dontCrashSide:
G (PREV(sideSense <= 1)) -> (!right);

 
 
 
 

 

 
asm 
(status = PARALLEL)  & (color !=GREEN);

 
asm
pRespondsToS((reversing) & (right), (color != BLACK) | !((reversing) & (right)));  
 

 
asm 
GF valid_parking_spot;

 
asm
G (status = PARALLEL) -> (next(status) = PARALLEL);

asm
G (status = REVERSE) -> (next(status) = REVERSE);

 
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color = GREEN) & (done = true);
  stopping := velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 
 
gar 
mode = PARKING & driveMotor = STOP & steeringMotor = STRAIGHT & velocity=0;

gar
G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar
G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

gar
G mode = PARKING -> velocity <= 1;


 
gar
G (mode = PARKING & done = false) -> next(mode = PARKING | mode = PARKED);


 
gar 
GF (mode = PARKED);

 
gar
pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar
pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);

gar
G forwarding -> frontSense > 0;


 
 
 
 
gar
G(valid_parking_spot <-> mode = PARKED);

 
gar
G(mode = PARKED -> stopping);

 
gar
G driveMotor = STOP -> next(velocity) <= velocity;

 
 
 
 
 
 

 
 

 
 
 
 

 

 
asm 
(status = PARALLEL)  & (color !=GREEN) & (sideSense >0 | frontSense>0) & (align = false) & (done = false);

 
asm
pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm
pRespondsToS((reversing) & (left) & (align = true), (color = GREEN) | !((reversing) & (left)));  
 

 
asm 
GF valid_parking_spot | stopping;

 
asm
GF sideSense > 0 | stopping;

asm
GF frontSense > 0 | stopping;

 
asm
G (status = PARALLEL) -> (next(status) = PARALLEL);

asm
G (status = REVERSE) -> (next(status) = REVERSE);

asm
G reversing -> next(frontSense) >= frontSense;

asm
G forwarding -> next(frontSense) <= frontSense;

asm
G (left & reversing) -> (next(sideSense) >= sideSense);

asm
G (right & reversing) -> (next(sideSense) <= sideSense);

asm
G (left & forwarding) -> (next(sideSense) >= sideSense);

asm
G (right & forwarding) -> (next(sideSense) <= sideSense);

asm
pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm
pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) | frontSense = 0);

asm
pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm
pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm
pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm
pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm
G stopping -> (next(sideSense) = sideSense & next(frontSense) = frontSense) & next(color)=color;

asm
G steeringMotor = STRAIGHT -> next(sideSense) = sideSense;
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 
 
gar 
mode = PARKING & driveMotor = STOP & steeringMotor = STRAIGHT & velocity=0;

gar
G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar
G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

gar
G mode = PARKING -> velocity <= 1;


 
gar
G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = PARKING );  

gar
G (align = false) -> (next(mode) = PARKING);

 
gar
G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar
G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar
G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;
 
 
 


 
gar 
GF (mode = PARKED);

 
gar
pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar
pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);

gar
G forwarding -> frontSense > 0;


 
 
 
 
gar
G(valid_parking_spot) -> (next(mode) = PARKED);

 
gar
G(mode = PARKED -> stopping);

 
gar
G driveMotor = STOP -> next(velocity) <= velocity;

 
 
 
 
 
 

 
 

 
 
 
 

 

 
asm 
(status = REVERSE)  & (color =BLACK) & (sideSense >0 | frontSense>0) & (align = false) & (done = false);

 
asm
pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm
pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 

 
asm 
GF valid_parking_spot | stopping;

 
 

 
asm
GF sideSense > 0 | stopping;

asm
GF frontSense > 0 | stopping;

 
asm
G (status = PARALLEL) -> (next(status) = PARALLEL);

asm
G (status = REVERSE) -> (next(status) = REVERSE);

 
 

asm
G forwarding -> next(frontSense) <= frontSense;

 
 

 
 

asm
G (left & forwarding) -> (next(sideSense) >= sideSense);

asm
G (right & forwarding) -> (next(sideSense) <= sideSense);

asm
pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm
pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) | frontSense = 0);

asm
pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm
pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm
pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm
pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm
G stopping -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color & next(align) = align & next(done) = done);

asm
G steeringMotor = STRAIGHT -> next(sideSense) = sideSense;

import "../patterns/DwyerPatterns.spectra"
module VehicleSpec      

env Int(0..5) frontSense;
env Int(0..5) backSense;
env Int(0..5) sideSense;
env ParkingSpotStatus status; 
env ParkingType parkingTypeFound; 


sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(1..5) velocity;
 

type SenseMotorCmd = {SCANNING, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE, PARKED};
type ParkingType = {PARALLEL, REVERSED, NONE};
type AngleCmd = {HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;
  parked := status = PARKED & steeringMotor = STRAIGHT & driveMotor = STOP;
monitor boolean scanning
{
  !scanning;
  G (senseMotor = SCANNING) -> (scanning = true);
  G (senseMotor = REVERSE) -> (scanning = false);
}
    
guarantee initialStop:
  stopping & senseMotor = REVERSE;

 
 


guarantee scannOften:
  GF scanning;
 
 
 

 
guarantee keepScanning:
  G scanning -> forwarding & steeringMotor = STRAIGHT ;

 
 
 
 
 

 
 
 



guarantee lookBack:
  G (driveMotor = BWD) -> PREV(senseMotor = REVERSE);  

 
guarantee dontCrashFront:
  G frontSense = 0 -> driveMotor != FWD;
  
 
 

 
guarantee dontCrashBack:  
  G  backSense = 0 & PREV(senseMotor = REVERSE) -> driveMotor != BWD;

 
 
 

 
guarantee speedWhileInReverse:
  G reversing -> PREV(senseMotor = REVERSE) &  velocity = 1;

 
guarantee speedWhileClear:
  G frontSense = 5 & senseMotor != REVERSE  -> velocity = 5;
guarantee speedWhileVeryFar:
  G frontSense = 4 & senseMotor != REVERSE -> velocity = 4;
guarantee speedWhileFar:
  G frontSense = 3 & senseMotor != REVERSE -> velocity = 3;
guarantee speedWhileMedium:
  G frontSense = 2 & senseMotor != REVERSE-> velocity = 2;
guarantee speedWhileClose:
  G frontSense = 1 -> velocity = 1;
  
 
assumption 
  pRespondsToS((forwarding | fwd_turning), backSense > 0);

 
assumption
  pRespondsToS((reversing | bwd_turning), frontSense > 0);

 
assumption notInACage:
  GF frontSense != 0 | backSense !=0;

guarantee dontCrashSide:
  G senseMotor != REVERSE & sideSense =0 -> !sideways;
 
 
 
  
 

 
assumption aParkingSpotExists:
  GF (parkingTypeFound = REVERSED | parkingTypeFound = PARALLEL) ;
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 
env boolean button;
 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar
  GF (mode = PARKED);

 
 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | steeringMotor = HARD_LEFT & next(mode = SEARCHING)));

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar 
  G (mode = PARKED & !button) -> (next(mode) = PARKED); 

gar
  G (mode = PARKED & button) -> (next(mode) = EXIT);

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);

 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = EXIT ) & next(stopping);

 
gar G (mode = EXIT & done = true & align = true ) -> (next(mode) = SEARCHING ) & next(stopping);

 
 

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> (next(mode) = EXIT)  & next(stopping);


gar 
G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar
G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> (next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;

 
gar
G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar
G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;


gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);


 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) & (button = false) ;

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED));

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);

import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED);

 
 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | steeringMotor = HARD_LEFT & next(mode = SEARCHING)));

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) <-> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar G(mode = PARKED) -> (next(mode) = EXIT);

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);

 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = EXIT ) & next(stopping);

 
gar G (mode = EXIT & done = true & align = true ) -> (next(mode) = SEARCHING ) & next(stopping);

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> (next(mode) = EXIT)  & next(stopping);


gar 
G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar
G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> (next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;

 
gar
G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar
G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;


gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);


 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) ;

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED));

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);


import "../patterns/DwyerPatterns.spectra"
module VehicleSpec      

env Int(0..5) frontSense;
env Int(0..5) backSense;
env Int(0..5) sideSense;
env ParkingSpotStatus status; 
env ParkingType parkingTypeFound; 


sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(1..5) velocity;
 

type SenseMotorCmd = {SCANNING, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE, PARKED};
type ParkingType = {PARALLEL, REVERSED, NONE};
type AngleCmd = {HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;
  parked := status = PARKED & steeringMotor = STRAIGHT & driveMotor = STOP;
monitor boolean scanning
{
  !scanning;
  G (senseMotor = SCANNING) -> (scanning = true);
  G (senseMotor = REVERSE) -> (scanning = false);
}
    
guarantee initialStop:
  stopping & senseMotor = REVERSE;

 
 


guarantee scannOften:
  GF scanning;
 
 
 

 
guarantee keepScanning:
  G scanning -> forwarding & steeringMotor = STRAIGHT ;

 
 
 
 
 

 
 
 



guarantee lookBack:
  G (driveMotor = BWD) -> PREV(senseMotor = REVERSE);  

 
guarantee dontCrashFront:
  G frontSense = 0 -> driveMotor != FWD;
  
 
 

 
guarantee dontCrashBack:  
  G  backSense = 0 & PREV(senseMotor = REVERSE) -> driveMotor != BWD;

 
 
 

 
guarantee speedWhileInReverse:
  G reversing -> PREV(senseMotor = REVERSE) &  velocity = 1;

 
guarantee speedWhileClear:
  G frontSense = 5 & senseMotor != REVERSE  -> velocity = 5;
guarantee speedWhileVeryFar:
  G frontSense = 4 & senseMotor != REVERSE -> velocity = 4;
guarantee speedWhileFar:
  G frontSense = 3 & senseMotor != REVERSE -> velocity = 3;
guarantee speedWhileMedium:
  G frontSense = 2 & senseMotor != REVERSE-> velocity = 2;
guarantee speedWhileClose:
  G frontSense = 1 -> velocity = 1;
  
 
assumption 
  pRespondsToS((forwarding | fwd_turning), backSense > 0);

 
assumption
  pRespondsToS((reversing | bwd_turning), frontSense > 0);

 
assumption notInACage:
  GF frontSense != 0 | backSense !=0;

guarantee dontCrashSide:
  G senseMotor != REVERSE & sideSense =0 -> !sideways;
 
 
 
  
 

 
assumption aParkingSpotExists:
  GF (parkingTypeFound = REVERSED | parkingTypeFound = PARALLEL) ;

import "../patterns/DwyerPatterns.spectra"
module VehicleSpec      

env Int(0..5) frontSense;
env Int(0..5) backSense;
env Int(0..5) sideSense;
env Status status; 

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(1..5) velocity;
sys Mode mode;


type SenseMotorCmd = {SIDE, BACK};
type MotorCmd = {FWD, STOP, BWD};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, NONE};
type AngleCmd = {STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};


define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

    
guarantee initial:
mode = SEARCHING & senseMotor = SIDE & steeringMotor = STRAIGHT;
  
gar
G mode = SEARCHING | mode = SCANNING -> senseMotor = SIDE; 

 
 
 
 
 

 
gar keepScanning:
G mode = SCANNING & frontSense > 2 & sideSense > 2 -> senseMotor = SIDE & next(mode) = SCANNING & driveMotor = FWD & steeringMotor = STRAIGHT;  

 
guarantee parallelParkingPart1:
 G mode = PARKING & status = PARALLEL & backSense > 2 -> PREV(senseMotor = BACK) & driveMotor = BWD & next(mode) = PARKING & steeringMotor = HARD_RIGHT;
  
gar parallelParkingPart2:
G mode = PARKING & status = PARALLEL & backSense <= 2 & backSense > 1 -> PREV(senseMotor = BACK) & driveMotor = BWD & next(mode) = PARKING & steeringMotor = HARD_LEFT;

gar parallelParkingPart3:
G mode = PARKING & status = PARALLEL & backSense <= 1 -> PREV(senseMotor = BACK) & driveMotor = STOP & next(mode) = PARKED & steeringMotor = STRAIGHT;

gar stayAtParking:
G mode = PARKED -> next(mode) = PARKED & driveMotor = STOP & steeringMotor = STRAIGHT;
 
 
 
 
 
 

 
guarantee dontCrashBack:  
G  backSense = 0 & PREV(senseMotor = BACK) -> driveMotor = FWD;

 
guarantee speedWhileInReverse:
G reversing -> PREV(senseMotor = BACK) &  velocity = 1;

 
guarantee speedWhileClear:
  G frontSense = 5 & mode = SEARCHING -> velocity = 5;
guarantee speedWhileVeryFar:
  G frontSense = 4 & mode = SEARCHING -> velocity = 4;
guarantee speedWhileFar:
  G frontSense = 3 & mode = SEARCHING -> velocity = 3;
guarantee speedWhileMedium:
  G frontSense = 2 & mode = SEARCHING -> velocity = 2;
guarantee slowSpeed:
  G frontSense = 1  | mode = PARKING | mode = SCANNING -> velocity = 1;

  
 
assumption 
  pRespondsToS(forwarding, backSense > 0);

 
assumption
  pRespondsToS((hard_left_fwd), frontSense > 0);

 
assumption notInACage:
GF frontSense != 0 | backSense !=0;

 
assumption notParkedInitially:
status = NONE ;
  
 

 
assumption aParkingSpotExists:
  GF  status = PARALLEL;
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec      

env Int(0..5) frontSense;
env Int(0..5) backSense;
env Int(0..5) sideSense;
env Status status; 

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(1..5) velocity;
sys Mode mode;


type SenseMotorCmd = {SIDE, BACK};
type MotorCmd = {FWD, STOP, BWD};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, NONE};
type AngleCmd = {STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};


define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

   
 
 
 
 
  
guarantee initial:
  mode = SEARCHING & senseMotor = SIDE & steeringMotor = STRAIGHT;
  
gar
G (mode = SEARCHING | mode = SCANNING) & status = NONE -> senseMotor = SIDE; 

 
gar startScanning:
G (mode = SEARCHING & frontSense > 2 & sideSense > 2 & status = NONE) -> (senseMotor = SIDE & next(mode) = SCANNING & driveMotor = FWD & steeringMotor = STRAIGHT); 

 
gar keepScanning:
G (mode = SCANNING & frontSense > 2 & sideSense > 2 & status = NONE) -> (senseMotor = SIDE & next(mode) = SCANNING & driveMotor = FWD & steeringMotor = STRAIGHT);  

gar foundPlace:
G (PREV(mode = SCANNING) & status = PARALLEL) -> (mode = PARKING);

gar pGear:
G (status = PARALLEL & mode = PARKING & sideSense <= 1 & steeringMotor = STRAIGHT & driveMotor = STOP) <-> (next(mode) = PARKED);

gar alwaysParkTheCar:
GF mode = PARKED;

 
 
 
 
 
 
 
 
 

gar stayAtParking:
G (mode = PARKED) -> (driveMotor = STOP & steeringMotor = STRAIGHT);
 
guarantee dontCrashFront:
G (frontSense <= 2 & (mode = SCANNING | mode = SEARCHING) & status = NONE) -> (senseMotor = SIDE & next(mode) = SEARCHING & driveMotor = FWD & steeringMotor = HARD_LEFT);
 
 
 

 
guarantee dontCrashBack:  
G driveMotor = BWD -> backSense > 0 & PREV(senseMotor = BACK);

 
guarantee speedWhileInReverse:
G reversing -> PREV(senseMotor = BACK) &  velocity = 1;

 
guarantee speedWhileClear:
  G frontSense = 5 & mode = SEARCHING -> velocity = 5;
guarantee speedWhileVeryFar:
  G frontSense = 4 & mode = SEARCHING -> velocity = 4;
guarantee speedWhileFar:
  G frontSense = 3 & mode = SEARCHING -> velocity = 3;
guarantee speedWhileMedium:
  G frontSense = 2 & mode = SEARCHING -> velocity = 2;
guarantee slowSpeed:
  G frontSense = 1  | mode = PARKING | mode = SCANNING -> velocity = 1;

  
 
assumption 
  pRespondsToS(forwarding, backSense > 0);

 
assumption
  pRespondsToS((hard_left_fwd), frontSense > 0);

 
 

asm 
G (driveMotor = STOP & (frontSense != 0 | backSense !=0)) -> (sideSense = next(sideSense) & backSense = next(backSense) & frontSense = next(frontSense));

gar
G (mode = PARKING) -> (next(mode) = PARKING | next(mode) = PARKED);

gar 
G (driveMotor = BWD) -> (next(driveMotor) = BWD | next(sideSense) = sideSense - 1);

gar 
G (driveMotor = FWD) -> (next(driveMotor) = FWD | next(sideSense) = sideSense + 1);

gar
GF (mode = PARKING -> driveMotor != STOP);

 
assumption notInACage:
GF frontSense != 0 | backSense !=0;

 
assumption notParkedInitially:
status = NONE & sideSense = 0 & frontSense > 2;
  
 

 
assumption aParkingSpotExists:
  GF  status = PARALLEL;
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec      

env Int(0..5) frontSense;
env Int(0..5) backSense;
env Int(0..5) sideSense;
env Status status; 

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(0..5) velocity;
sys Mode mode;


type SenseMotorCmd = {SIDE, BACK};
type MotorCmd = {FWD, STOP, BWD};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, NONE};
type AngleCmd = {STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};


define
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

   
 
 
 
 
  

 
assumption notParkedInitially:
status = NONE & frontSense > 2 & sideSense > 2;

guarantee initial:
mode = SEARCHING & senseMotor = SIDE & steeringMotor = STRAIGHT & stopping;

 
 
 

 
gar
G ((mode = SCANNING) & status = NONE & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar
G ((mode = SEARCHING) & status = NONE & frontSense > 2 & next(frontSense)>2 ) -> (steeringMotor = STRAIGHT & next(driveMotor) = FWD);
 
 
 
 

 


 
 

 
gar
G (mode = SCANNING & sideSense <= 2 & status = NONE) -> (next(mode) = SEARCHING);

 
gar
G (mode = SCANNING  & status = NONE & sideSense >2 ) -> (next(mode) = SCANNING);

 
gar
G (mode = SEARCHING & sideSense <= 2) -> (next(mode) = SEARCHING);

 
gar startScanning:
G ((mode = SEARCHING) & frontSense > 2 & sideSense > 2) -> (next(mode) = SCANNING); 



asm
G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm
G (mode = PARKING | mode = PARKED) -> (next(status = PARALLEL));

 
asm
pRespondsToS(mode = SCANNING, status = PARALLEL);

 
gar foundPlace:
G  (status = PARALLEL & mode = SCANNING) -> (next(mode) = PARKING);

 

 
gar pGear:
G (mode = PARKING & stopping) <-> (next(mode) = PARKED);

 
gar alwaysParkTheCar:
GF mode = PARKED;

 
 
 
 

 
gar
G (mode = PARKING) -> (next(mode) != SEARCHING & next(mode) != SCANNING);

 
asm
pRespondsToS(driveMotor = BWD, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm
pRespondsToS(driveMotor = FWD, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm
pRespondsToS((driveMotor = BWD & steeringMotor = STRAIGHT & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense -1 | next(backSense) = backSense)
);

 
asm
pRespondsToS((driveMotor = BWD & steeringMotor = STRAIGHT & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense | next(sideSense) = sideSense)
);

 
asm
pRespondsToS((driveMotor = FWD & steeringMotor = STRAIGHT & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense | next(sideSense) = sideSense)
);

 
asm
pRespondsToS((driveMotor = FWD & steeringMotor = STRAIGHT & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense+1 | next(backSense) = backSense)
);


asm
pRespondsToS((driveMotor = BWD & left & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense + 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = BWD & left & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense - 1 | next(backSense) = backSense)
);

 
asm
pRespondsToS((driveMotor = BWD & right & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense - 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = BWD & right & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense - 1 | next(backSense) = backSense)
);

 
asm
pRespondsToS((driveMotor = FWD & left & senseMotor = SIDE),
  (senseMotor = BACK | next(sideSense) = sideSense + 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = FWD & left & senseMotor = BACK),
  (senseMotor = SIDE | next(backSense) = backSense + 1 | next(backSense) = backSense)
);

asm
pRespondsToS((driveMotor = FWD & right & senseMotor = SIDE),
  (senseMotor = BACK | next(sideSense) = sideSense + 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = FWD & right & senseMotor = BACK),
  (senseMotor = SIDE | next(backSense) = backSense + 1 | next(backSense) = backSense)
);

 
 
 

 
guarantee dontCrashFront:
G (frontSense <= 2) -> (driveMotor != FWD);

 
 
 

guarantee dontCrashBack:
G (PREV(senseMotor = BACK) & backSense <= 1) -> (driveMotor != BWD);

guarantee dontCrashSide:
G (PREV(senseMotor = SIDE) & sideSense <= 1) -> (steeringMotor = STRAIGHT);



guarantee lookToTheSideBeforeForward:  
G (driveMotor = FWD) -> (PREV(senseMotor = SIDE));

guarantee lookBeforeGoingBackwards: 
G(driveMotor = BWD) -> ((PREV(senseMotor = SIDE)) & 
  (PREV(backSense > 0 & stopping) & PREV(PREV(senseMotor = BACK))));


 
guarantee speedWhileInReverse:
G reversing -> velocity = 1;

 
guarantee speedWhileInStopping:
G driveMotor = STOP <-> velocity = 0;

 
guarantee speedWhileClear:
  G (frontSense = 5 & mode = SEARCHING & !stopping) -> (velocity = 5);
guarantee speedWhileVeryFar:
  G (frontSense = 4 & mode = SEARCHING & !stopping ) -> (velocity = 4);
guarantee speedWhileFar:
  G (frontSense = 3 & mode = SEARCHING & !stopping) -> (velocity = 3);
guarantee slowSpeed:
  G (frontSense = 3 & (mode = PARKING | mode = SCANNING) & !stopping) -> (velocity = 1);
  
 
 
 

 
 
 

 
 

 
 
 

 
 


 
 

 
 
 

 
 
 

assumption moveAfterStopping:
pRespondsToS(stopping , frontSense > 2 & sideSense > 2);


assumption ableToScan:
GF ((frontSense > 2 & sideSense > 2));

assumption notInACage:
GF (frontSense > 2 | backSense > 2 | sideSense > 2);


 
asm parkingSpotsDontDisappear:
G (status = PARALLEL) -> (next(status) = PARALLEL);

 
assumption aParkingSpotExists:
  GF (status = PARALLEL | stopping);
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec      

env Int(0..5) frontSense;
env Int(0..5) backSense;
env Int(0..5) sideSense;
env Status status; 

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(0..5) velocity;
sys Mode mode;


type SenseMotorCmd = {SIDE, BACK};
type MotorCmd = {FWD, STOP, BWD};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, NONE};
type AngleCmd = {STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};


define
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

   
 
 
 
 
  

 
assumption notParkedInitially:
status = NONE & frontSense > 2 & sideSense > 2;

guarantee initial:
mode = SEARCHING & senseMotor = SIDE & steeringMotor = STRAIGHT & stopping;

 
 
 

 
gar
G ((mode = SCANNING) & status = NONE & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar
G ((mode = SEARCHING) & status = NONE & frontSense > 2 & next(frontSense)>2 ) -> (steeringMotor = STRAIGHT & next(driveMotor) = FWD);
 
 
 
 

 


 
 

 
gar
G (mode = SCANNING & sideSense <= 2 & status = NONE) -> (next(mode) = SEARCHING);

 
gar
G (mode = SCANNING  & status = NONE & sideSense >2 ) -> (next(mode) = SCANNING);

 
gar
G (mode = SEARCHING & sideSense <= 2) -> (next(mode) = SEARCHING);

 
gar startScanning:
G ((mode = SEARCHING) & frontSense > 2 & sideSense > 2) -> (next(mode) = SCANNING); 



asm
G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm
G (mode = PARKING | mode = PARKED) -> (next(status = PARALLEL));

 
asm
pRespondsToS(mode = SCANNING, status = PARALLEL);

 
gar foundPlace:
G  (status = PARALLEL & mode = SCANNING) -> (next(mode) = PARKING);

 

 
gar pGear:
G (mode = PARKING & stopping) <-> (next(mode) = PARKED);

 
gar alwaysParkTheCar:
GF mode = PARKED;

 
 
 
 

 
gar
G (mode = PARKING) -> (next(mode) != SEARCHING & next(mode) != SCANNING);

 
asm
pRespondsToS(driveMotor = BWD, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm
pRespondsToS(driveMotor = FWD, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm
pRespondsToS((driveMotor = BWD & steeringMotor = STRAIGHT & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense -1 | next(backSense) = backSense)
);

 
asm
pRespondsToS((driveMotor = BWD & steeringMotor = STRAIGHT & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense | next(sideSense) = sideSense)
);

 
asm
pRespondsToS((driveMotor = FWD & steeringMotor = STRAIGHT & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense | next(sideSense) = sideSense)
);

 
asm
pRespondsToS((driveMotor = FWD & steeringMotor = STRAIGHT & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense+1 | next(backSense) = backSense)
);


asm
pRespondsToS((driveMotor = BWD & left & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense + 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = BWD & left & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense - 1 | next(backSense) = backSense)
);

 
asm
pRespondsToS((driveMotor = BWD & right & senseMotor = SIDE), 
  (senseMotor = BACK | next(sideSense) = sideSense - 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = BWD & right & senseMotor = BACK), 
  (senseMotor = SIDE | next(backSense) = backSense - 1 | next(backSense) = backSense)
);

 
asm
pRespondsToS((driveMotor = FWD & left & senseMotor = SIDE),
  (senseMotor = BACK | next(sideSense) = sideSense + 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = FWD & left & senseMotor = BACK),
  (senseMotor = SIDE | next(backSense) = backSense + 1 | next(backSense) = backSense)
);

asm
pRespondsToS((driveMotor = FWD & right & senseMotor = SIDE),
  (senseMotor = BACK | next(sideSense) = sideSense + 1 | next(sideSense) = sideSense)
);

asm
pRespondsToS((driveMotor = FWD & right & senseMotor = BACK),
  (senseMotor = SIDE | next(backSense) = backSense + 1 | next(backSense) = backSense)
);

 
 
 

 
guarantee dontCrashFront:
G (frontSense <= 2) -> (driveMotor != FWD);

 
 
 

guarantee dontCrashBack:
G (PREV(senseMotor = BACK) & backSense <= 1) -> (driveMotor != BWD);

guarantee dontCrashSide:
G (PREV(senseMotor = SIDE) & sideSense <= 1) -> (steeringMotor = STRAIGHT);



guarantee lookToTheSideBeforeForward:  
G (driveMotor = FWD) -> (PREV(senseMotor = SIDE));

guarantee lookBeforeGoingBackwards: 
G(driveMotor = BWD) -> ((PREV(senseMotor = SIDE)) & 
  (PREV(backSense > 0 & stopping) & PREV(PREV(senseMotor = BACK))));


 
guarantee speedWhileInReverse:
G reversing -> velocity = 1;

 
guarantee speedWhileInStopping:
G driveMotor = STOP <-> velocity = 0;

 
guarantee speedWhileClear:
  G (frontSense = 5 & mode = SEARCHING & !stopping) -> (velocity = 5);
guarantee speedWhileVeryFar:
  G (frontSense = 4 & mode = SEARCHING & !stopping ) -> (velocity = 4);
guarantee speedWhileFar:
  G (frontSense = 3 & mode = SEARCHING & !stopping) -> (velocity = 3);
guarantee slowSpeed:
  G (frontSense = 3 & (mode = PARKING | mode = SCANNING) & !stopping) -> (velocity = 1);
  
 
 
 

 
 
 

 
 

 
asm 
G (stopping & (frontSense > 2 & sideSense >2)) -> (sideSense = next(sideSense) & backSense = next(backSense) & frontSense = next(frontSense));

 
 


 
 

 
 
 

 
 
 

assumption moveAfterStopping:
pRespondsToS(stopping , frontSense > 2 & sideSense > 2);


assumption ableToScan:
GF ((frontSense > 2 & sideSense > 2));

assumption notInACage:
GF (frontSense > 2 | backSense > 2 | sideSense > 2);


 
asm parkingSpotsDontDisappear:
G (status = PARALLEL) -> (next(status) = PARALLEL);

 
assumption aParkingSpotExists:
  GF (status = PARALLEL | stopping);
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED);

 
 
gar dontCrashFront: G ((frontSense <= 2)) -> ((driveMotor != FWD) | steeringMotor = HARD_LEFT);

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);





 
 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = PARKING );  

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);


 





 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) ;

asm G forwarding -> next(frontSense) <= frontSense;

asm G reversing -> next(frontSense) >= frontSense;

asm G (left & !stopping) -> (next(sideSense) >= sideSense);

asm G (right & !stopping) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G stopping -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color & next(align) = align & next(done) = done);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;





 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = SCANNING | mode = PARKING)) -> (next(status) = REVERSE | next(status) = PARALLEL);





 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF valid_parking_spot | stopping;

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 





 
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED);

 
 
gar dontCrashFront: G ((frontSense <= 2)) -> (((driveMotor != FWD) | steeringMotor = HARD_LEFT & next(mode = SEARCHING)));

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = PARKING );  

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

 





 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) ;

asm G (forwarding & (mode !=PARKING) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING| mode != PARKED)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color & next(align) = align & next(done) = done);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & mode = PARKING) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED) | stopping);

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 





 
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED | mode = EXIT);

 
 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | steeringMotor = HARD_LEFT & next(mode = SEARCHING)));

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar G(mode = PARKED) -> (next(mode) = EXIT);

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);

 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = EXIT ) & next(stopping);

 
gar G (mode = EXIT & done = true & align = true ) -> (next(mode) = SEARCHING ) & next(stopping);

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> (next(mode) = EXIT)  & next(stopping);


gar 
G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar
G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> (next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;

 
gar
G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar
G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;


gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);


 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) ;

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED) | stopping);

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);


import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env FrontDistance sense;
env SideDistance parking; 
env boolean color;
env boolean emgOff;

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys Int(0..90) steeringMotor; 

type SenseMotorCmd = {DRIVE, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type FrontDistance = {CLEAR, FAR, MEDIUM, CLOSE ,BLOCKED};
type SideDistance = {CLOSE, MEDIUM, FAR};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD & steeringMotor = 45 & senseMotor = DRIVE;
  leftTurning := steeringMotor < 45  & driveMotor != STOP;
  rightTurning := steeringMotor > 45  & driveMotor != STOP;  
  reversing := senseMotor = REVERSE & driveMotor = BWD;
  parked := parking = CLOSE & driveMotor = STOP & steeringMotor = 45;
    
      
guarantee initialStop:
  stopping;

guarantee dontCrashFront:
  G (((sense = BLOCKED) & (senseMotor =DRIVE))  -> ! forwarding);
  
guarantee dontCrashBack:  
  G (((sense = BLOCKED) & (senseMotor = REVERSE))  -> ! reversing);
  

guarantee 
  GF forwarding;


assumption canGetClear:
  pRespondsToS(leftTurning | rightTurning, sense = CLEAR);


import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 
env boolean manual;

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED);

 
 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | steeringMotor = HARD_LEFT & next(mode = SEARCHING)));

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar G(mode = PARKED) -> (next(mode) = PARKED);  

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);

 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = EXIT ) & next(stopping);

 
gar G (mode = EXIT & done = true & align = true ) -> (next(mode) = SEARCHING ) & next(stopping);

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> (next(mode) = EXIT)  & next(stopping);


gar 
G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar
G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> (next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;

 
gar
G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar
G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;


gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);


 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) ;

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED));

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);

import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 
 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED);

 
 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | steeringMotor = HARD_LEFT & next(mode = SEARCHING)));

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar G(mode = PARKED) -> (next(mode) = PARKED);  

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);

 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = EXIT ) & next(stopping);

 
gar G (mode = EXIT & done = true & align = true ) -> (next(mode) = SEARCHING ) & next(stopping);

 
 

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> (next(mode) = EXIT)  & next(stopping);


gar 
G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar
G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> (next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;

 
gar
G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar
G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;


gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);


 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) ;

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED));

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);

import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 
env boolean button;
 

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED);

 
 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | steeringMotor = HARD_LEFT & next(mode = SEARCHING)));

 

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT) /*| mode = EXIT*/ & driveMotor != STOP | reversing) -> (velocity = 1);

 
 
gar two: pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

 
gar one: pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);





 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor) = FWD);

gar  
G (mode = SCANNING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar G (mode = SCANNING  & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning: G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING); 

 
gar noMatch: G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING);

 
gar G (frontSense = 5 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & mode = SEARCHING & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 

gar G (mode = PARKING & align = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> (next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> (next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar G(mode = PARKED & !button) -> (next(mode) = PARKED);  

gar G(mode = PARKED & button) -> (next(mode) = EXIT);

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);

 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE ) -> (next(mode) = EXIT ) & next(stopping);

 
gar G (mode = EXIT & done = true & align = true ) -> (next(mode) = SEARCHING ) & next(stopping);

 
 

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> (next(mode) = EXIT)  & next(stopping);


gar 
G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar
G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> (next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;

 
gar
G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar
G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;


gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);


 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) & (button = false) ;

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED));

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);


import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env Distance sense;
env Distance parking; 
env boolean color;
env boolean emgOff;

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys Int(0..10) steeringMotor; 
sys Int(1..5) velocity;

type SenseMotorCmd = {DRIVE, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};


define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD & steeringMotor = 5  & senseMotor = DRIVE;
  leftTurning := steeringMotor < 5  & driveMotor != STOP;
  rightTurning := steeringMotor > 5  & driveMotor != STOP;  
  reversing := senseMotor = REVERSE & driveMotor = BWD;
  parked := parking = BLOCKED -> (driveMotor = STOP & steeringMotor = 5);
  
      
guarantee initialStop:
  stopping;

guarantee dontCrashFront:
  G (((sense = BLOCKED) & (senseMotor = DRIVE))  -> ! forwarding);
  
guarantee dontCrashBack:  
  G (((sense = BLOCKED) & (senseMotor = REVERSE))  -> ! reversing);
  

guarantee keepMovingForward:
  GF forwarding;

 
guarantee eyesOnTheRoad:
  G forwarding -> senseMotor = DRIVE;

 
guarantee useYourRearviewMirror: 
  G reversing -> senseMotor = REVERSE;  
  


guarantee finishedParking:
  GF parked;  
  
guarantee speedWhileClear:
  G sense = CLEAR -> velocity = 5;

guarantee speedWhileVeryFar:
  G sense = VERY_FAR -> velocity = 4;

guarantee speedWhileFar:
  G sense = FAR -> velocity = 3;

guarantee speedWhileMedium:
  G sense = MEDIUM -> velocity = 2;

guarantee speedWhileClose:
  G sense = CLOSE -> velocity = 1;


assumption canGetClear:
  pRespondsToS(leftTurning | rightTurning | reversing, sense = CLEAR);



import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env Distance sense;
env Distance parking;
env boolean wideEnoughtToPark;
env boolean deepEnoughtToPark; 
env boolean color;
env boolean emgOff;

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys Int(0..10) steeringMotor; 
sys Int(1..5) velocity;

type SenseMotorCmd = {DRIVE, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};


define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD & steeringMotor = 5  & senseMotor = DRIVE;
  leftTurning := steeringMotor < 5  & driveMotor != STOP;
  rightTurning := steeringMotor > 5  & driveMotor != STOP;  
  reversing := senseMotor = REVERSE & driveMotor = BWD;
  reverseParking := (senseMotor = REVERSE & sense = BLOCKED & parking = BLOCKED) -> (driveMotor = STOP & steeringMotor = 5);
  parallelParking := parking = BLOCKED -> (driveMotor = STOP & steeringMotor = 5);
  
guarantee initialStop:
  stopping;

guarantee dontCrashFront:
  G (((sense = BLOCKED) & (senseMotor = DRIVE))  -> ! forwarding);
  
guarantee dontCrashBack:  
  G (((sense = BLOCKED) & (senseMotor = REVERSE))  -> ! reversing);
  

guarantee keepMovingForward:
  GF forwarding;

 
guarantee eyesOnTheRoad:
  G forwarding -> senseMotor = DRIVE;

 
guarantee useYourRearviewMirror: 
  G reversing -> senseMotor = REVERSE;    

guarantee finishedParking:
  GF reverseParking | parallelParking;  

guarantee beginParkingInReverse:
    pRespondsToS(deepEnoughtToPark, reverseParking);
    
guarantee beginParallelParking:
  pRespondsToS(wideEnoughtToPark, parallelParking);    
  
guarantee speedWhileClear:
  G sense = CLEAR -> velocity = 5;

guarantee speedWhileVeryFar:
  G sense = VERY_FAR -> velocity = 4;

guarantee speedWhileFar:
  G sense = FAR -> velocity = 3;

guarantee speedWhileMedium:
  G sense = MEDIUM -> velocity = 2;

guarantee speedWhileClose:
  G sense = CLOSE -> velocity = 1;

assumption canGetClear:
  pRespondsToS(leftTurning | rightTurning | reversing, sense = CLEAR);

assumption aParkingSpotExists:
  GF wideEnoughtToPark | deepEnoughtToPark;
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 
 
env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 
env boolean button;
env boolean manual;
env MotorCmd driveCmd;
env MotorCmd steeringCmd;

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT, MANUAL};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED | manual = true | button = true);

 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | (steeringMotor = HARD_LEFT & next(mode = SEARCHING)) | next(mode = MANUAL)));

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT)  & driveMotor != STOP | reversing) -> (velocity = 1);

 
gar pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

gar pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);

 




 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor = FWD) | !manual);

 
gar G (mode = SCANNING & sideStatus = NONE ) -> (next(mode = SEARCHING)| !manual);

 
gar G (mode = SCANNING & status = NONE  & sideStatus != NONE & frontSense >2 ) -> (next(mode) = SCANNING);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode = SEARCHING) | !manual);

 
gar G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING | !manual); 

 
gar G (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING | !manual);

 
gar G (frontSense = 5 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & manual = false & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> 
(next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT);




 
 

gar G (mode = PARKING & align = false & manual = false) -> (next(mode) = PARKING);

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> (next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> ((next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | !manual);

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> ((next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | !manual) ;

gar G(mode = PARKING & valid_parking_spot) -> (next(mode) = PARKED);
 
gar G(mode = PARKED -> stopping);

gar G(mode = PARKED & !button) -> (next(mode = PARKED) | !manual);  

gar G(mode = PARKED & button) -> (next(mode = EXIT) | !manual);

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);






 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE) -> (next(mode = EXIT & stopping) | !manual);

 
gar G (mode = EXIT & done = true & align = true) -> (next(mode = SEARCHING & stopping) | !manual);

 
 

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> (next(mode) = EXIT)  & next(stopping);

gar G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> (next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD);

gar G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> ((next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT) | !manual) ;

 
gar G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> (next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD);

gar G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> (next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT ) ;

gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);



 
 
gar G (mode = MANUAL & frontSense > 2 -> (driveMotor = driveCmd & steeringMotor = steeringCmd));

 
gar G (manual = true <-> mode = MANUAL); 



 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) & (button = false) & (manual = false) ;

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED));

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);


 
 
asm G steeringCmd != FWD & steeringCmd != BWD & steeringCmd != STOP;

asm G driveCmd != HARD_LEFT & driveCmd != LIGHT_LEFT & driveCmd != STRAIGHT & driveCmd != LIGHT_RIGHT & driveCmd != HARD_RIGHT;
import "../patterns/DwyerPatterns.spectra"
module ParkingSpec      

 
 
env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align;  
env boolean done; 
env boolean button;
env boolean manual;
env MotorCmd driveCmd;
env MotorCmd steeringCmd;

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT, MANUAL};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 

 
 
gar mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar GF (mode = PARKED | manual = true);

 
gar dontCrashFront: G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | (steeringMotor = HARD_LEFT & next(mode = SEARCHING)) | next(mode = MANUAL)));

 
gar G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: G ((mode = SCANNING | mode = PARKING | mode = EXIT)  & driveMotor != STOP | reversing) -> (velocity = 1);

 
gar pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

gar pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);

 




 

gar G (mode = SCANNING) -> PREV(mode != PARKED);

gar G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor = FWD) | next(mode)= MANUAL);

 
gar G (mode = SCANNING & sideStatus = NONE ) -> (next(mode = SEARCHING)| next(mode)= MANUAL);

 
gar G (mode = SCANNING & status = NONE  & sideStatus != NONE & frontSense >2) -> ((next(mode) = SCANNING) | next(mode)= MANUAL);

 
gar G (mode = SEARCHING & sideStatus = NONE) -> (next(mode = SEARCHING) | next(mode)= MANUAL);

 
gar G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING |next(mode)= MANUAL); 

 
gar G (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING | next(mode)= MANUAL);

 
gar G (frontSense = 5 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 5);
gar G (frontSense = 4 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 4);
gar G (frontSense = 3 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 3);
gar G (frontSense = 2 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 2);
gar G (frontSense = 1 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace: G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> 
((next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT) | (next(mode) = MANUAL));




 
 

gar G (mode = PARKING & align = false & manual = false) -> (next(mode) = PARKING | (next(mode) = MANUAL));

gar G (mode = PARKING) -> PREV(mode != SEARCHING);

gar G (mode = PARKING) -> PREV(mode != PARKED);

gar G (mode = PARKING) -> PREV(mode != EXIT);

 
gar G(mode = PARKING & align = false & done = false) -> ((next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD) | next(mode)= MANUAL);

 
gar G(mode = PARKING & status = PARALLEL & align = true & done = false) -> ((next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | next(mode)= MANUAL);

 
gar G(mode = PARKING & status = REVERSE & align = true & done = false) -> ((next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | next(mode)= MANUAL) ;

gar G(mode = PARKING & valid_parking_spot) -> ((next(mode) = PARKED) | next(mode)= MANUAL);
 
gar G(mode = PARKED -> stopping);

gar G(mode = PARKED & !button) -> (next(mode = PARKED) | next(mode)= MANUAL);  

gar G(mode = PARKED & button) -> (next(mode = EXIT) | next(mode)= MANUAL);

gar G (mode = PARKED) -> PREV(mode != SEARCHING);

gar G (mode = PARKED) -> PREV(mode != SCANNING);

gar G (mode = PARKED) -> PREV(mode != EXIT);






 

 
gar G (mode = PARKING & done = true & align = true & color = BLUE) -> (next(mode = EXIT & stopping) | next(mode)= MANUAL);

 
gar G (mode = EXIT & done = true & align = true) -> (next(mode = SEARCHING & stopping) | next(mode)= MANUAL);

 
 

 
gar G (mode = EXIT & align = false) -> (next(mode) = EXIT | next(mode)= MANUAL);

 
gar G (mode = EXIT & next(frontSense<=2) & done = false) -> ((next(mode) = EXIT  & next(stopping))) | next(mode)= MANUAL;

gar G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> ((next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD)| next(mode)= MANUAL);

gar G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> ((next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT) | next(mode)= MANUAL) ;

 
gar G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> ((next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD)| next(mode)= MANUAL);

gar G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> ((next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT )| next(mode)= MANUAL) ;

gar G (mode = EXIT) -> PREV(mode != SEARCHING);

gar G (mode = EXIT) -> PREV(mode != SCANNING);



 
 
gar G ((mode = MANUAL & frontSense > 2) -> (driveMotor = driveCmd & steeringMotor = steeringCmd));

 
gar G (manual = true) <-> (next(mode) = MANUAL); 



 
 
 
asm (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) & (button = false) & (manual = false) & (steeringCmd = STRAIGHT) & (driveCmd= STOP);

asm G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT) & (mode != MANUAL)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);

 
asm GF sideSense > 0 | stopping;
asm GF frontSense > 0 | stopping;



 
asm G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsScanningMode: G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear: G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 
 
asm aParkingSpotExists: GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
 
asm GF ((valid_parking_spot & mode = PARKED) | manual = true);

 
asm pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right)));  

asm pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left)));  
 


asm pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true)));  

asm G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);

asm G (align = false) -> (next(done) = false);


 
 
asm G (manual = true) ->((next(steeringCmd) != FWD) & (next(steeringCmd) != BWD) & (next(steeringCmd) != STOP));

asm G (manual = false) ->((next(steeringCmd) = steeringCmd) );

asm G (manual = true) -> ((next(driveCmd) != HARD_LEFT) & (next(driveCmd) != LIGHT_LEFT) & (next(driveCmd) != STRAIGHT) & (next(driveCmd) != LIGHT_RIGHT) & (next(driveCmd) != HARD_RIGHT));

asm G (manual = false) ->((next(driveCmd) = driveCmd) );
import "../patterns/DwyerPatterns.spectra"

module ParkingSpec      

 
env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align; 
env boolean done; 
env boolean button;
env boolean manual;
env MotorCmd driveCmd;
env MotorCmd steeringCmd;

 
sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT, MANUAL};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

 
define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 


 


 
gar initialState:
  mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar achieveTheGoalEventually:
  GF (mode = PARKED | manual = true);

 
gar dontCrashFront: 
  G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | (steeringMotor = HARD_LEFT & next(mode = SEARCHING)) | next(mode = MANUAL)));

 
gar steeringOptions:
  G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar driveMotorOptions:
  G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: 
  G ((mode = SCANNING | mode = PARKING | mode = EXIT)  & driveMotor != STOP | reversing) -> (velocity = 1);

 
gar
  pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

gar 
  pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);




 



gar scanningAndParkedOrder:
  G (mode = SCANNING) -> PREV(mode != PARKED);

gar scanningAndParkingOrder:
  G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar forwardWhileScanning:
  G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar forwardWhileSearching:
  G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor = FWD) | next(mode)= MANUAL);

 
gar scanningFailed:
  G (mode = SCANNING & sideStatus = NONE ) -> (next(mode = SEARCHING)| next(mode)= MANUAL);

 
gar continueScanning:
  G (mode = SCANNING & status = NONE  & sideStatus != NONE & frontSense >2) -> ((next(mode) = SCANNING) | next(mode)= MANUAL);

 
gar searchingAgain:
  G (mode = SEARCHING & sideStatus = NONE) -> (next(mode = SEARCHING) | next(mode)= MANUAL);

 
gar switchToScanning:
  G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING |next(mode)= MANUAL); 

 
gar lookForParallelParking: 
  G (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING | next(mode)= MANUAL);

 
gar Clear:
  G (frontSense = 5 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 5);
gar veryFar:
  G (frontSense = 4 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 4);
gar far:
  G (frontSense = 3 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 3);
gar close:
  G (frontSense = 2 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 2);
gar veryClose:
  G (frontSense = 1 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace:
  G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> 
     ((next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT) | (next(mode) = MANUAL));




 

 
gar keepParking:
  G (mode = PARKING & align = false & manual = false) -> (next(mode) = PARKING | (next(mode) = MANUAL));

gar parkingAndSearchingOrder:
  G (mode = PARKING) -> PREV(mode != SEARCHING);

gar parkingAndParkedOrder:
  G (mode = PARKING) -> PREV(mode != PARKED);

gar parkingAndExitOrder:
  G (mode = PARKING) -> PREV(mode != EXIT);

 
gar firstStepParking:
  G(mode = PARKING & align = false & done = false) -> ((next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD) | next(mode)= MANUAL);

 
gar secondStepParallelParking:
  G(mode = PARKING & status = PARALLEL & align = true & done = false) -> ((next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | next(mode)= MANUAL);

 
gar secondStepReverseParking:
  G(mode = PARKING & status = REVERSE & align = true & done = false) -> ((next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | next(mode)= MANUAL) ;

 
gar switchToParkedMode:
  G(mode = PARKING & valid_parking_spot) -> ((next(mode) = PARKED) | next(mode)= MANUAL);
  
 
gar stopIfParked:
  G(mode = PARKED -> stopping);

 
gar stayParked:
  G(mode = PARKED & !button) -> (next(mode = PARKED) | next(mode)= MANUAL); 

 
gar switchToExitMode:
  G(mode = PARKED & button) -> (next(mode = EXIT) | next(mode)= MANUAL);

 
gar parkedAndSearchingOrder:
  G (mode = PARKED) -> PREV(mode != SEARCHING);

gar parkedAndScanningOrder:
  G (mode = PARKED) -> PREV(mode != SCANNING);

gar parkedAndExitOrder:
  G (mode = PARKED) -> PREV(mode != EXIT);





 


 
gar disabledParking:
  G (mode = PARKING & done = true & align = true & color = BLUE) -> (next(mode = EXIT & stopping) | next(mode)= MANUAL);

 
gar searchAgainAfterExit:
  G (mode = EXIT & done = true & align = true) -> (next(mode = SEARCHING & stopping) | next(mode)= MANUAL);


gar keepExit:
  G (mode = EXIT & align = false) -> (next(mode) = EXIT | next(mode)= MANUAL);

 
gar ifBlockedWhileExit:
  G (mode = EXIT & next(frontSense<=2) & done = false) -> ((next(mode) = EXIT  & next(stopping))) | next(mode)= MANUAL;

 
gar FirstStepReverseExit:
  G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> ((next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD)| next(mode)= MANUAL);

 
gar SecndStepReverseExit:
  G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> ((next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT) | next(mode)= MANUAL) ;

 
gar FirstStepParallelExit:
  G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> ((next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD)| next(mode)= MANUAL);

 
gar SecndStepParallelExit:
  G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> ((next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT )| next(mode)= MANUAL) ;

gar exitAndSearchingOrder:
  G (mode = EXIT) -> PREV(mode != SEARCHING);

gar exitAndScanningOrder:
  G (mode = EXIT) -> PREV(mode != SCANNING);



 

 
gar manualCommands:
  G ((mode = MANUAL & frontSense > 2) -> (driveMotor = driveCmd & steeringMotor = steeringCmd));

 
gar switchtoManual:
  G (manual = true) <-> (next(mode) = MANUAL); 



 
 

 
asm initialAssumptions:
  (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) & (button = false) & (manual = false) & (steeringCmd = STRAIGHT) & (driveCmd= STOP);

asm frontSenseAndForwarding:
  G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm frontSenseAndReversing:
  G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm sideSenseAndLedtReversing:
  G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm sideSenseAndRightReversing:
  G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm reversingAssm:
  pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm forwardingAssm:
  pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm leftReversingAssm:
  pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm rightReversingAssm:
  pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm leftForwardingAssm:
  pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm rightForwardingAssm:
  pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm stopAssm:
  G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT) & (mode != MANUAL)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);


asm sideBlock:
  GF sideSense > 0 | stopping;
asm frontBlock:
  GF frontSense > 0 | stopping;



 
asm statusSearchingAssm:
  G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm findPlaceWhileScanning:
  pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm continueBackwardsAssm:
  pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm continueforwardAssm:
  pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: 
  G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

 
asm ReverseparkingSpotsScanningMode: 
  G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

 
asm ReverseparkingSpotsDontDisappear: 
  G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 

 
asm aParkingSpotExists: 
  GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
asm goalASssm:
  GF ((valid_parking_spot & mode = PARKED) | manual = true);

asm firstStepFinishEventually:
  pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right))); 

asm validParkingAssm:
  pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left))); 

 
asm finishParking:
  pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true))); 

 
asm alignFinishFirst:
  G (align = false) -> (next(done) = false);

asm parkStatus:
  G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);



 


 
asm steeringCmdOptions:
  G (manual = true) ->((next(steeringCmd) != FWD) & (next(steeringCmd) != BWD) & (next(steeringCmd) != STOP));

asm driveMotoeCmdOptions:
  G (manual = true) -> ((next(driveCmd) != HARD_LEFT) & (next(driveCmd) != LIGHT_LEFT) & (next(driveCmd) != STRAIGHT) & (next(driveCmd) != LIGHT_RIGHT) & (next(driveCmd) != HARD_RIGHT));

 
asm steeringCmdAssm:
  G (manual = false) ->((next(steeringCmd) = steeringCmd) );
  
asm driveCmdAssm:
  G (manual = false) ->((next(driveCmd) = driveCmd) );
import "../patterns/DwyerPatterns.spectra"

module ParkingSpec      

 
env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
env boolean align; 
env boolean done; 
env boolean button;
env boolean manual;
env MotorCmd driveCmd;
env MotorCmd steeringCmd;

 
sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;

 
type MotorCmd = {FWD, STOP, BWD, STRAIGHT, HARD_LEFT, LIGHT_LEFT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED, EXIT, MANUAL};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};

 
define
  valid_parking_spot := (status != NONE) & (color != BLUE) &(align = true)& (done = true);
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD & velocity > 0;
  reversing := driveMotor = BWD & velocity > 0;
  
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

 


 


 
gar initialState:
  mode = SEARCHING  & stopping & steeringMotor = STRAIGHT; 

 
gar achieveTheGoalEventually:
  GF (mode = PARKED | manual = true);

 
gar dontCrashFront: 
  G ((frontSense <= 2) & (mode !=EXIT)) -> (((driveMotor != FWD) | (steeringMotor = HARD_LEFT & next(mode = SEARCHING)) | next(mode = MANUAL)));

 
gar steeringOptions:
  G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

gar driveMotorOptions:
  G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;

 
gar slowSpeed: 
  G ((mode = SCANNING | mode = PARKING | mode = EXIT)  & driveMotor != STOP | reversing) -> (velocity = 1);

 
gar
  pRespondsToS(driveMotor = STOP, driveMotor != STOP | next(velocity) < velocity | velocity=0);

gar 
  pRespondsToS(driveMotor != STOP, driveMotor = STOP | next(velocity) > velocity | velocity=5);




 



gar scanningAndParkedOrder:
  G (mode = SCANNING) -> PREV(mode != PARKED);

gar scanningAndParkingOrder:
  G (mode = SCANNING) -> PREV(mode != PARKING);

 
gar forwardWhileScanning:
  G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);

 
gar forwardWhileSearching:
  G ((mode = SEARCHING) & status = NONE) -> (next(driveMotor = FWD) | next(mode)= MANUAL);

 
gar scanningFailed:
  G (mode = SCANNING & sideStatus = NONE ) -> (next(mode = SEARCHING)| next(mode)= MANUAL);

 
gar continueScanning:
  G (mode = SCANNING & status = NONE  & sideStatus != NONE & frontSense >2) -> ((next(mode) = SCANNING) | next(mode)= MANUAL);

 
gar searchingAgain:
  G (mode = SEARCHING & sideStatus = NONE) -> (next(mode = SEARCHING) | next(mode)= MANUAL);

 
gar switchToScanning:
  G (mode = SEARCHING & sideStatus != NONE & frontSense >2) -> (next(mode) = SCANNING |next(mode)= MANUAL); 

 
gar lookForParallelParking: 
  G (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL & frontSense >2) -> (next(mode) = SCANNING | next(mode)= MANUAL);

 
gar Clear:
  G (frontSense = 5 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 5);
gar veryFar:
  G (frontSense = 4 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 4);
gar far:
  G (frontSense = 3 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 3);
gar close:
  G (frontSense = 2 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 2);
gar veryClose:
  G (frontSense = 1 & (mode = SEARCHING | mode = MANUAL) & driveMotor = FWD) -> (velocity = 1);
  
  
  
  
  
 
 
gar parkinglPlace:
  G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> 
     ((next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT) | (next(mode) = MANUAL));




 

 
gar keepParking:
  G (mode = PARKING & align = false & manual = false) -> (next(mode) = PARKING | (next(mode) = MANUAL));

gar parkingAndSearchingOrder:
  G (mode = PARKING) -> PREV(mode != SEARCHING);

gar parkingAndParkedOrder:
  G (mode = PARKING) -> PREV(mode != PARKED);

gar parkingAndExitOrder:
  G (mode = PARKING) -> PREV(mode != EXIT);

 
gar firstStepParking:
  G(mode = PARKING & align = false & done = false) -> ((next(steeringMotor)= HARD_RIGHT & next(driveMotor) = BWD) | next(mode)= MANUAL);

 
gar secondStepParallelParking:
  G(mode = PARKING & status = PARALLEL & align = true & done = false) -> ((next(steeringMotor) = HARD_LEFT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | next(mode)= MANUAL);

 
gar secondStepReverseParking:
  G(mode = PARKING & status = REVERSE & align = true & done = false) -> ((next(steeringMotor) = STRAIGHT & next(driveMotor) = BWD & next(velocity) =1 & next(mode) = PARKING) | next(mode)= MANUAL) ;

 
gar switchToParkedMode:
  G(mode = PARKING & valid_parking_spot) -> ((next(mode) = PARKED) | next(mode)= MANUAL);
  
 
gar stopIfParked:
  G(mode = PARKED -> stopping);

 
gar stayParked:
  G(mode = PARKED & !button) -> (next(mode = PARKED) | next(mode)= MANUAL); 

 
gar switchToExitMode:
  G(mode = PARKED & button) -> (next(mode = EXIT) | next(mode)= MANUAL);

 
gar parkedAndSearchingOrder:
  G (mode = PARKED) -> PREV(mode != SEARCHING);

gar parkedAndScanningOrder:
  G (mode = PARKED) -> PREV(mode != SCANNING);

gar parkedAndExitOrder:
  G (mode = PARKED) -> PREV(mode != EXIT);





 


 
gar disabledParking:
  G (mode = PARKING & done = true & align = true & color = BLUE) -> (next(mode = EXIT & stopping) | next(mode)= MANUAL);

 
gar searchAgainAfterExit:
  G (mode = EXIT & done = true & align = true) -> (next(mode = SEARCHING & stopping) | next(mode)= MANUAL);


gar keepExit:
  G (mode = EXIT & align = false) -> (next(mode) = EXIT | next(mode)= MANUAL);

 
gar ifBlockedWhileExit:
  G (mode = EXIT & next(frontSense<=2) & done = false) -> ((next(mode) = EXIT  & next(stopping))) | next(mode)= MANUAL;

 
gar FirstStepReverseExit:
  G(mode = EXIT & status = REVERSE & align = false & done = false & next(frontSense) >2 ) -> ((next(steeringMotor)= STRAIGHT & next(driveMotor) = FWD)| next(mode)= MANUAL);

 
gar SecndStepReverseExit:
  G(mode = EXIT & status = REVERSE & align = true & done = false & next(frontSense) >2 ) -> ((next(steeringMotor) = HARD_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT) | next(mode)= MANUAL) ;

 
gar FirstStepParallelExit:
  G(mode = EXIT & status = PARALLEL & align = false & done = false & next(frontSense) >2) -> ((next(steeringMotor)= LIGHT_LEFT& next(driveMotor) = FWD)| next(mode)= MANUAL);

 
gar SecndStepParallelExit:
  G(mode = EXIT & status = PARALLEL & align = true & done = false & next(frontSense) >2) -> ((next(steeringMotor) = LIGHT_RIGHT & next(driveMotor) = FWD & next(velocity) =1 & next(mode) = EXIT )| next(mode)= MANUAL) ;

gar exitAndSearchingOrder:
  G (mode = EXIT) -> PREV(mode != SEARCHING);

gar exitAndScanningOrder:
  G (mode = EXIT) -> PREV(mode != SCANNING);



 

 
gar manualCommands:
  G ((mode = MANUAL & frontSense > 2) -> (driveMotor = driveCmd & steeringMotor = steeringCmd));
  
gar manualCommandsDontCrash:
  G ((mode = MANUAL & frontSense <= 2) -> (driveMotor = STOP & steeringMotor = steeringCmd));  

 
gar switchtoManual:
  G (manual = true) <-> (next(mode) = MANUAL); 


 
 
 

 
asm initialAssumptions:
  (status = NONE) & (color = BLACK) & (sideSense > 0 | frontSense>0) & (align = false) & (done = false) & (button = false) & (manual = false) & (steeringCmd = STRAIGHT) & (driveCmd= STOP);

asm frontSenseAndForwarding:
  G (forwarding & (mode !=PARKING) & (mode !=EXIT) & (steeringMotor) = STRAIGHT) -> (next(frontSense) <= frontSense);

asm frontSenseAndReversing:
  G (reversing  & (mode !=PARKING ))-> (next(frontSense) >= frontSense);

asm sideSenseAndLedtReversing:
  G (left & reversing  & (mode !=PARKING) ) -> (next(sideSense) >= sideSense);

asm sideSenseAndRightReversing:
  G (right & reversing  & (mode !=PARKING)) -> (next(sideSense) <= sideSense);

asm reversingAssm:
  pRespondsToS(reversing, !reversing | (next(frontSense) = frontSense+1) | frontSense = 5);

asm forwardingAssm:
  pRespondsToS(forwarding, !forwarding | (next(frontSense) = frontSense-1) |frontSense = 0);

asm leftReversingAssm:
  pRespondsToS(left & reversing, !left | !reversing | (next(sideSense) = sideSense+1) | sideSense = 5);

asm rightReversingAssm:
  pRespondsToS(right & reversing, !right | !reversing | (next(sideSense) = sideSense-1) | sideSense = 0);

asm leftForwardingAssm:
  pRespondsToS(left & forwarding, !left | !forwarding | (next(sideSense) = sideSense+1) | sideSense = 5);

asm rightForwardingAssm:
  pRespondsToS(right & forwarding, !right | !forwarding | (next(sideSense) = sideSense-1) | sideSense = 0);

asm stopAssm:
  G (stopping & (mode!=PARKING) & (mode != PARKED) & (mode!=EXIT) & (mode != MANUAL)) -> (next(sideSense) = sideSense & next(frontSense) = frontSense & next(color)=color);


asm sideBlock:
  GF sideSense > 0 | stopping;
asm frontBlock:
  GF frontSense > 0 | stopping;



 
asm statusSearchingAssm:
  G (mode = SEARCHING & status = NONE) -> (next(status = NONE));

 
asm findPlaceWhileScanning:
  pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm continueBackwardsAssm:
  pRespondsToS(driveMotor = BWD & mode != PARKING, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm continueforwardAssm:
  pRespondsToS(driveMotor = FWD & mode != PARKING, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
asm ParallelparkingSpotsDontDisappear: 
  G (status = PARALLEL & (mode = SCANNING | mode = PARKING | mode = EXIT)) -> (next(status) = PARALLEL);

 
asm ReverseparkingSpotsScanningMode: 
  G (status = REVERSE & (mode = SCANNING)) -> (next(status) = REVERSE | next(status) = PARALLEL);

 
asm ReverseparkingSpotsDontDisappear: 
  G (status = REVERSE & (mode = PARKING | mode = EXIT)) -> (next(status) = REVERSE);




 

 
asm aParkingSpotExists: 
  GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));

 
asm goalASssm:
  GF ((valid_parking_spot & mode = PARKED) | manual = true);

asm firstStepFinishEventually:
  pRespondsToS((reversing) & (right) & (align = false), (align = true) | !((reversing) & (right))); 

asm validParkingAssm:
  pRespondsToS((reversing) & (left) & (align = true), (color != BLUE) | !((reversing) & (left))); 

 
asm finishParking:
  pRespondsToS((mode = PARKING & align =false & done = false), ((align = true) & (done = true))); 

 
asm alignFinishFirst:
  G (align = false) -> (next(done) = false);

asm parkStatus:
  G (mode = EXIT | mode = PARKING | mode = PARKED)  -> (next(status != NONE) & next(sideStatus)!= NONE);



 


 
asm steeringCmdOptions:
  G (manual = true) ->((next(steeringCmd) != FWD) & (next(steeringCmd) != BWD) & (next(steeringCmd) != STOP));

asm driveMotoeCmdOptions:
  G (manual = true) -> ((next(driveCmd) != HARD_LEFT) & (next(driveCmd) != LIGHT_LEFT) & (next(driveCmd) != STRAIGHT) & (next(driveCmd) != LIGHT_RIGHT) & (next(driveCmd) != HARD_RIGHT));

 
asm steeringCmdAssm:
  G (manual = false) ->((next(steeringCmd) = steeringCmd) );
  
asm driveCmdAssm:
  G (manual = false) ->((next(driveCmd) = driveCmd) );
 
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env Distance sense;
env Distance parking;
env ParkingSpotStatus status; 
env ParkingType parkingTypeFound; 
env boolean color;
env boolean emgOff;

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys Int(0..90) steeringMotor; 
sys Int(1..5) velocity;
sys ParkingType parkingMode;

type SenseMotorCmd = {DRIVE, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE};
type ParkingType = {PARALLEL, REVERSED, NONE};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD & steeringMotor = 50;
  leftTurning := steeringMotor < 45& driveMotor != STOP;
  rightTurning := steeringMotor > 45  & driveMotor != STOP;  
  reversing := driveMotor = BWD;
  reverseParking := (senseMotor = REVERSE & sense = CLOSE & parking = BLOCKED) -> (driveMotor = STOP & steeringMotor = 45);
  parallelParking := parking = BLOCKED -> (driveMotor = STOP & steeringMotor = 45);
  foundAParallelSpot := (parkingTypeFound = PARALLEL & status = FINISHED_SCANNING);
  foundAReverseSpot := (parkingTypeFound = REVERSED & status = FINISHED_SCANNING);
  scanning := status = STARTED_SCANNING & sense != BLOCKED;
    
guarantee initialStop:
  stopping;

 
guarantee initalNotParking:
  parkingMode = NONE;

 
guarantee keepScanning:
  G scanning -> forwarding;  

 
guarantee startParkingInParallel:
  pRespondsToS(foundAParallelSpot, parallelParking);

 
guarantee startParkingInReverse:
  pRespondsToS(foundAReverseSpot, reverseParking);

 
guarantee dontCrashFront:
  G (((sense = BLOCKED) & (senseMotor = DRIVE))  -> ! forwarding);
  
 
guarantee dontCrashBack:  
  G (((sense = BLOCKED) & (senseMotor = REVERSE))  -> ! reversing);

 
guarantee keepMovingForward:
  GF forwarding;

 
guarantee eyesOnTheRoad:
  G forwarding -> senseMotor = DRIVE;

 
guarantee useYourRearviewMirror: 
  G reversing -> senseMotor = REVERSE;    

 
guarantee finishedParking:
  GF reverseParking | parallelParking;  

 
guarantee speedWhileInReverse:
  G senseMotor = REVERSE -> velocity = 1;
  
 
guarantee speedWhileClear:
  G sense = CLEAR -> velocity = 5;
guarantee speedWhileVeryFar:
  G sense = VERY_FAR -> velocity = 4;
guarantee speedWhileFar:
  G sense = FAR -> velocity = 3;
guarantee speedWhileMedium:
  G sense = MEDIUM -> velocity = 2;
guarantee speedWhileClose:
  G sense = CLOSE -> velocity = 1;

 
assumption canGetClear:
  pRespondsToS(leftTurning | rightTurning | reversing, sense = CLEAR);

 
assumption aParkingSpotExists:
  GF parkingTypeFound = REVERSED | parkingTypeFound = PARALLEL;

 
assumption notParkedInitially:
  parkingTypeFound = NONE & status = NONE;
  
 
assumption eventuallyGetOutOfParking:
  GF status = NONE;
 
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env Distance sense;
env Distance parking;
env ParkingSpotStatus status; 
env ParkingType parkingTypeFound; 
env boolean color;
env boolean emgOff;

sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys Int(0..90) steeringMotor; 
sys Int(1..5) velocity;
sys ParkingType parkingMode;

type SenseMotorCmd = {DRIVE, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE};
type ParkingType = {PARALLEL, REVERSED, NONE};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD & steeringMotor = 50;
  leftTurning := steeringMotor < 45& driveMotor != STOP;
  rightTurning := steeringMotor > 45  & driveMotor != STOP;  
  reversing := driveMotor = BWD;
  reverseParking := (senseMotor = REVERSE & sense = CLOSE & parking = BLOCKED) -> (driveMotor = STOP & steeringMotor = 45);
  parallelParking := parking = BLOCKED -> (driveMotor = STOP & steeringMotor = 45);
  foundAParallelSpot := (parkingTypeFound = PARALLEL & status = FINISHED_SCANNING);
  foundAReverseSpot := (parkingTypeFound = REVERSED & status = FINISHED_SCANNING);
  scanning := status = STARTED_SCANNING & sense != BLOCKED;
    
guarantee initialStop:
  stopping;

guarantee initialDirection:
  senseMotor = DRIVE;

 
guarantee initalNotParking:
  parkingMode = NONE;

 
guarantee keepScanning:
  G scanning -> forwarding;  

 
guarantee startParkingInParallel:
  pRespondsToS(foundAParallelSpot, parallelParking);

 
guarantee startParkingInReverse:
  pRespondsToS(foundAReverseSpot, reverseParking);

 
guarantee dontCrashFront:
  G (((sense = BLOCKED) & (senseMotor = DRIVE))  -> ! forwarding);
  
 
guarantee dontCrashBack:  
  G (((sense = BLOCKED) & (senseMotor = REVERSE))  -> ! reversing);

 
guarantee keepMovingForward:
  GF forwarding;

 
guarantee eyesOnTheRoad:
  G forwarding -> senseMotor = DRIVE;

 
guarantee useYourRearviewMirror: 
  G reversing -> senseMotor = REVERSE;    

 
guarantee finishedParking:
  GF reverseParking | parallelParking;  

 
guarantee speedWhileInReverse:
  G senseMotor = REVERSE -> velocity = 1;
  
 
guarantee speedWhileClear:
  G sense = CLEAR -> velocity = 5;
guarantee speedWhileVeryFar:
  G sense = VERY_FAR -> velocity = 4;
guarantee speedWhileFar:
  G sense = FAR -> velocity = 3;
guarantee speedWhileMedium:
  G sense = MEDIUM -> velocity = 2;
guarantee speedWhileClose:
  G sense = CLOSE -> velocity = 1;

 
assumption canGetClear:
  pRespondsToS(leftTurning | rightTurning | reversing, sense = CLEAR);

 
assumption aParkingSpotExists:
  GF parkingTypeFound = REVERSED | parkingTypeFound = PARALLEL;

 
assumption notParkedInitially:
  parkingTypeFound = NONE & status = NONE;
  
 
assumption eventuallyGetOutOfParking:
  GF status = NONE;
 
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env Distance sense;
env Distance parking;
env ParkingSpotStatus status; 
env ParkingType parkingTypeFound; 
env boolean color;
env boolean emgOff;


sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys Int(0..90) steeringMotor; 
sys Int(1..5) velocity;
sys ParkingType parkingMode;

type SenseMotorCmd = {DRIVE, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE};
type ParkingType = {PARALLEL, REVERSED, NONE};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD & steeringMotor = 50;
  leftTurning := steeringMotor < 45& driveMotor != STOP;
  rightTurning := steeringMotor > 45  & driveMotor != STOP;  
  reversing := driveMotor = BWD;
  reverseParking := (senseMotor = REVERSE & sense = CLOSE & parking = BLOCKED) -> (driveMotor = STOP & steeringMotor = 45);
  parallelParking := parking = BLOCKED -> (driveMotor = STOP & steeringMotor = 45);
  foundAParallelSpot := (parkingTypeFound = PARALLEL & status = FINISHED_SCANNING);
  foundAReverseSpot := (parkingTypeFound = REVERSED & status = FINISHED_SCANNING);
  scanning := status = STARTED_SCANNING & sense != BLOCKED;
    
guarantee initialStop:
  stopping & senseMotor = DRIVE & parkingMode = NONE & steeringMotor = 45;

 
 
 
 
 
 
  


 
guarantee keepScanning:
  G scanning -> forwarding;  

 
guarantee startParkingInParallel:
  pRespondsToS(foundAParallelSpot, parallelParking);

 
guarantee startParkingInReverse:
  pRespondsToS(foundAReverseSpot, reverseParking);

 
guarantee dontCrashFront:
  G (((sense = BLOCKED) & (senseMotor = DRIVE))  -> ! forwarding);
  
 
guarantee dontCrashBack:  
  G (((sense = BLOCKED) & (senseMotor = REVERSE))  -> ! reversing);

 
guarantee keepMovingForward:
  GF forwarding;

 
guarantee eyesOnTheRoad:
  G forwarding -> senseMotor = DRIVE;

 
guarantee useYourRearviewMirror: 
  G reversing -> senseMotor = REVERSE;    

 
guarantee finishedParking:
  GF reverseParking | parallelParking;  

 
guarantee speedWhileInReverse:
  G senseMotor = REVERSE -> velocity = 1;
  
 
guarantee speedWhileClear:
  G sense = CLEAR -> velocity = 5;
guarantee speedWhileVeryFar:
  G sense = VERY_FAR -> velocity = 4;
guarantee speedWhileFar:
  G sense = FAR -> velocity = 3;
guarantee speedWhileMedium:
  G sense = MEDIUM -> velocity = 2;
guarantee speedWhileClose:
  G sense = CLOSE -> velocity = 1;

 
assumption canGetClear:
  pRespondsToS(leftTurning | rightTurning | reversing, sense = CLEAR);

 
assumption aParkingSpotExists:
  GF parkingTypeFound = REVERSED | parkingTypeFound = PARALLEL;

 
assumption notParkedInitially:
  parkingTypeFound = NONE & status = NONE;
  
 
assumption eventuallyGetOutOfParking:
  GF status = NONE;
 
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env Distance frontSense;
env Distance backSense;
 
 


sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(1..5) velocity;
 

type SenseMotorCmd = {SCANNING, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE};
type ParkingType = {PARALLEL, REVERSED, NONE};
type AngleCmd = {HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  
  
  
  
  
   
    
guarantee initialStop:
    stopping & senseMotor = SCANNING & steeringMotor = STRAIGHT;

 
 

 
 
 
 
 
 
 
 
  


 
 
 
 
 
 
 
 
 
 
 

gar
  G (driveMotor = BWD & backSense != BLOCKED) -> senseMotor = REVERSE;

 
guarantee dontCrashFront:
  G frontSense = BLOCKED -> driveMotor != FWD;
  
 
guarantee dontCrashBack:  
  G  (backSense = BLOCKED & steeringMotor = STRAIGHT & senseMotor = REVERSE) -> driveMotor != BWD;

 
guarantee keepMovingForward:
  GF forwarding & steeringMotor = STRAIGHT; 

 
 
 
 
 


 
 
 

 
guarantee speedWhileInReverse:
  G senseMotor = REVERSE & reversing -> velocity = 1;

 
 
  
 
guarantee speedWhileClear:
  G frontSense = CLEAR -> velocity = 5;
guarantee speedWhileVeryFar:
  G frontSense = VERY_FAR -> velocity = 4;
guarantee speedWhileFar:
  G frontSense = FAR -> velocity = 3;
guarantee speedWhileMedium:
  G frontSense = MEDIUM -> velocity = 2;
guarantee speedWhileClose:
  G frontSense = CLOSE -> velocity = 1;

 
assumption canGetClear:
  pRespondsToS(reversing | (next(steeringMotor) != steeringMotor & reversing), frontSense != BLOCKED);
assumption 
  pRespondsToS(sideways, frontSense != BLOCKED & backSense != BLOCKED);
 
 


 
 
 
 

 
 
 
 
 
 
 
  
 

 import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			


env Distance sense;
env boolean sound;

sys MotorCmd mLeft;
sys MotorCmd mRight;

monitor boolean clapped {
  !clapped;  
  G sound <-> next(clapped)=!clapped;  
}

type MotorCmd = { FWD, STOP, BWD };
type Distance = { CLEAR, BLOCKED };

define
  stopping := mLeft = STOP & mRight = STOP;
  forwarding := mLeft = FWD & mRight = FWD;
  turning := mLeft != mRight;
  




guarantee initialStop:
  stopping;

guarantee dontCrash:
  G ((sense = BLOCKED) -> ! forwarding);

guarantee 
  GF forwarding;

guarantee startTurningOnClap:
  G clapped -> turning; 
  

assumption canGetClear:
  pRespondsToS(turning, sense = CLEAR);

assumption canForwardInfinitelyOften:
  GF clapped != true & sense = CLEAR;
        
      

 
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec			

env Distance frontSense;
env Distance backSense;
 
 


sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(1..5) velocity;
 

type SenseMotorCmd = {SCANNING, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE};
type ParkingType = {PARALLEL, REVERSED, NONE};
type AngleCmd = {HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  
  
  
  
  
   
    
guarantee initialStop:
    stopping & senseMotor = SCANNING & steeringMotor = STRAIGHT;

 
 

 
 
 
 
 
 
 
 
  


 
 
 
 
 
 
 
 
 
 
 

 
gar
  G (driveMotor = BWD & backSense != BLOCKED) -> senseMotor = REVERSE;

 
guarantee dontCrashFront:
  G frontSense = BLOCKED -> driveMotor != FWD;
  
 
guarantee dontCrashBack:  
  G  (backSense = BLOCKED & senseMotor = REVERSE) -> driveMotor != BWD;

 
guarantee keepMovingForward:
  GF forwarding & steeringMotor = STRAIGHT;   


 
 
 
 
 


 
 
 

 
guarantee speedWhileInReverse:
  G (senseMotor = REVERSE & reversing) -> velocity = 1;

 
 
  
 
guarantee speedWhileClear:
  G (frontSense = CLEAR & !reversing) -> velocity = 5;
guarantee speedWhileVeryFar:
  G (frontSense = VERY_FAR & !reversing) -> velocity = 4;
guarantee speedWhileFar:
  G (frontSense = FAR & !reversing) -> velocity = 3;
guarantee speedWhileMedium:
  G (frontSense = MEDIUM & !reversing) -> velocity = 2;
guarantee speedWhileClose:
  G frontSense = CLOSE -> velocity = 1;


 
assumption canGetClear:
  pRespondsToS(reversing | (next(steeringMotor) != steeringMotor & reversing) , frontSense != BLOCKED);
  
 
   
  
assumption 
  pRespondsToS(hard_right_bwd | light_right_bwd | hard_left_bwd | light_left_bwd  , frontSense != BLOCKED);
assumption 
  pRespondsToS(hard_right_fwd | light_right_fwd | hard_left_fwd | light_left_fwd  , backSense != BLOCKED);

 
 




 
 
 
 

 
 
 
 
 
 
 
  
 
 
import "../patterns/DwyerPatterns.spectra"
module VehicleSpec      

env Int(0..5) frontSense;
env Int(0..5) backSense;
env Int(0..5) sideSense;
env ParkingSpotStatus status; 
env ParkingType parkingTypeFound; 


sys MotorCmd driveMotor;
sys SenseMotorCmd senseMotor; 
sys AngleCmd steeringMotor; 
sys Int(1..5) velocity;
sys ParkingType parkingMode;

type SenseMotorCmd = {SCANNING, REVERSE};
type MotorCmd = {FWD, STOP, BWD};
type Distance = {BLOCKED, CLOSE, MEDIUM, FAR, VERY_FAR, CLEAR};
type ParkingSpotStatus = {STARTED_SCANNING, FINISHED_SCANNING, NONE};
type ParkingType = {PARALLEL, REVERSED, NONE};
type AngleCmd = {HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};

define
  stopping := driveMotor = STOP ;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;
  
  
  
  
   
    
guarantee initialStop:
    stopping & steeringMotor = STRAIGHT & senseMotor = REVERSE;

 
 

 
 
 
 
 
 
 
 
  


 
 
 
 
 
 
 
 
 
 
 

gar lookBack:
  G (driveMotor = BWD) -> PREV(senseMotor = REVERSE);

asm
GF frontSense != 0 | backSense !=0;

 
guarantee dontCrashFront:
 G frontSense = 0 -> driveMotor != FWD;

 
guarantee dontCrashBack:  
  G  backSense = 0 & PREV(senseMotor = REVERSE) -> driveMotor != BWD;

 
guarantee keepMovingForward:
  GF forwarding & steeringMotor = STRAIGHT; 

 
 
 
 
 


 
 
 

 
guarantee speedWhileInReverse:
  G reversing -> PREV(senseMotor = REVERSE) &  velocity = 1;

 
 
  
 
guarantee speedWhileClear:
  G frontSense = 5 -> velocity = 5;
guarantee speedWhileVeryFar:
  G frontSense = 4 -> velocity = 4;
guarantee speedWhileFar:
  G frontSense = 3 -> velocity = 3;
guarantee speedWhileMedium:
  G frontSense = 2 -> velocity = 2;
guarantee speedWhileClose:
  G frontSense = 1 -> velocity = 1;

 
 
 
 

 
 
 
 
 
 

assumption 
  pRespondsToS(forwarding | fwd_turning, backSense > 0);

assumption
  pRespondsToS((reversing | bwd_turning), frontSense > 0);
  
 
 
 
 
 
 


 
 
 
 

 
 
 
 
 
 
 
  
 
import "../patterns/DwyerPatterns.spectra"
module moveAndScan    

env Int(0..5) frontSense;
 
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
 

sys MotorCmd driveMotor;
 
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;


 
type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};


define
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

   
 
 
 
 
  

 
assumption notParkedInitially:
status = NONE &   frontSense > 2 & sideSense !=0;

guarantee initial:
mode = SEARCHING  & steeringMotor = STRAIGHT & stopping;

 
gar
G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

 
gar
G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;


 
gar
G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);


 
gar
G ((mode = SEARCHING) & status = NONE & frontSense > 2 & next(frontSense)>2 ) -> (steeringMotor = STRAIGHT & next(driveMotor) = FWD);
 


 
gar
G (mode = SCANNING & sideStatus = NONE & status = NONE) -> (next(mode) = SEARCHING);

 
gar
G (mode = SCANNING  & status = NONE  & sideStatus != NONE ) -> (next(mode) = SCANNING);

 
gar
G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning:
G (mode = SEARCHING & sideStatus!= NONE) -> (next(mode) = SCANNING); 

 
 


asm
G (mode = SEARCHING & status = NONE) -> (next(status = NONE));


 
asm
pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
gar reverselPlace:
G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT & next(steeringMotor) = STRAIGHT);

 
 

 
gar noMatch:
G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL) -> (next(mode) = SCANNING);

 
gar alwaysParkTheCar:
GF (stopping & (status = PARALLEL | status = REVERSE) & mode = PARKING) ;

 
 



 
asm
pRespondsToS(driveMotor = BWD, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm
pRespondsToS(driveMotor = FWD, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));

 
 
 
 
 

 
 
 
 
 

 
 
 
 
 

 
 
 
 
 


 
 
 
 

 
 
 
 


 
 
 
 

 
 
 
 


 
 
 
 

 
 
 
 

 
 
  
 

 
 
 
 

 
 
 

 
guarantee dontCrashFront:
G (frontSense <= 2) -> (driveMotor != FWD);

 
 
 

 
 

guarantee dontCrashSide:
G ( sideSense <= 1) -> (steeringMotor = STRAIGHT);



 
 

 
 
 


 
guarantee speedWhileInReverse:
G reversing -> velocity = 1;

 
guarantee speedWhileInStopping:
G driveMotor = STOP <-> velocity = 0;

 
guarantee speedWhileClear:
  G (frontSense = 5 & mode = SEARCHING & !stopping) -> (velocity = 5);
guarantee speedWhileVeryFar:
  G (frontSense = 4 & mode = SEARCHING & !stopping ) -> (velocity = 4);
guarantee speedWhileFar:
  G (frontSense = 3 & mode = SEARCHING & !stopping) -> (velocity = 3);
guarantee slowSpeed:
  G (frontSense = 3 & (mode = SCANNING) & !stopping) -> (velocity = 1);
  
 
 
 

 
 
 

 
 

 
 
 


 
 

 
 


 
 

 
 
 

 
 
 

assumption moveAfterStopping:
pRespondsToS(stopping , frontSense > 2 & sideSense >= 2);


 
 

assumption notInACage:
GF (frontSense > 2  | sideSense >= 2);


 
asm ParallelparkingSpotsDontDisappear:
G (status = PARALLEL) -> (next(status) = PARALLEL);

asm ReverseparkingSpotsDontDisappear:
G (status = REVERSE) -> (next(status) = REVERSE | next(status) = PARALLEL);

 
assumption aParkingSpotExists:
  GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));
import "../patterns/DwyerPatterns.spectra"
module moveAndScan    

env Int(0..5) frontSense;
 
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;
 

sys MotorCmd driveMotor;
 
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;


 
type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};


define
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

   
 
 
 
 
  

 
assumption notParkedInitially:
status = NONE &   frontSense > 2 & sideSense !=0;

guarantee initial:
mode = SEARCHING  & steeringMotor = STRAIGHT & stopping;

 
gar
G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

 
gar
G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;


 
gar
G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);


 
gar
G ((mode = SEARCHING) & status = NONE & frontSense > 2 & next(frontSense)>2 ) -> (steeringMotor = STRAIGHT & next(driveMotor) = FWD);
 


 
gar
G (mode = SCANNING & sideStatus = NONE & status = NONE) -> (next(mode) = SEARCHING);

 
gar
G (mode = SCANNING  & status = NONE  & sideStatus != NONE ) -> (next(mode) = SCANNING);

 
gar
G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning:
G (mode = SEARCHING & sideStatus!= NONE) -> (next(mode) = SCANNING); 

 
 

 
asm
G (mode = SEARCHING & status = NONE) -> (next(status = NONE));


 
asm
pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
gar reverselPlace:
G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT & next(steeringMotor) = STRAIGHT);

 
 

 
gar noMatch:
G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL) -> (next(mode) = SCANNING);

 
gar alwaysParkTheCar:
GF (stopping & (status = PARALLEL | status = REVERSE) & mode = PARKING) ;

 
 



 
asm
pRespondsToS(driveMotor = BWD, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm
pRespondsToS(driveMotor = FWD, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));




 
 
 

 
guarantee dontCrashFront:
G (frontSense <= 2) -> ((driveMotor != FWD) | steeringMotor = HARD_LEFT);

 
guarantee dontCrashSide:
G ( sideSense <= 1) -> (steeringMotor = STRAIGHT);

 
guarantee speedWhileInStopping:
G driveMotor = STOP <-> velocity = 0;

 
guarantee speedWhileClear:
  G (frontSense = 5 & mode = SEARCHING & !stopping) -> (velocity = 5);
guarantee speedWhileVeryFar:
  G (frontSense = 4 & mode = SEARCHING & !stopping ) -> (velocity = 4);
guarantee speedWhileFar:
  G (frontSense = 3 & mode = SEARCHING & !stopping) -> (velocity = 3);
guarantee slowSpeed:
  G (frontSense = 3 & (mode = SCANNING) & !stopping) -> (velocity = 1);
  




 
 

 
 
 


 
 

 
 


 
 

 
 
 

 
 
 

 
assumption moveAfterStopping:
pRespondsToS(stopping , frontSense > 2 & sideSense >= 2);


 
 

 
assumption notInACage:
GF (frontSense > 2  | sideSense >= 2);


 
asm ParallelparkingSpotsDontDisappear:
G (status = PARALLEL) -> (next(status) = PARALLEL);

 
asm ReverseparkingSpotsDontDisappear:
G (status = REVERSE) -> (next(status) = REVERSE | next(status) = PARALLEL);

 
assumption aParkingSpotExists:
  GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));
import "../patterns/DwyerPatterns.spectra"
module moveAndScan    

env Int(0..5) frontSense;
env Int(0..5) sideSense;
env Status status; 
env SideStatus sideStatus;
env ColorCmd color;

sys MotorCmd driveMotor;
sys MotorCmd steeringMotor;
sys Int(0..5) velocity;
sys Mode mode;


type MotorCmd = {FWD, STOP, BWD, HARD_LEFT, LIGHT_LEFT, STRAIGHT, LIGHT_RIGHT, HARD_RIGHT};
type Mode = {SEARCHING, SCANNING, PARKING, PARKED};
type Status = {PARALLEL, REVERSE, NONE};
type SideStatus = {MIN_PARALLEL , MIN_REVERSE, NONE};
type ColorCmd = {BLACK , GREEN , BLUE};


define
  stopping := driveMotor = STOP & velocity = 0;
  forwarding := driveMotor = FWD; 
  reversing := driveMotor = BWD ;
  left := steeringMotor = LIGHT_LEFT | steeringMotor = HARD_LEFT;
  right := steeringMotor = LIGHT_RIGHT | steeringMotor = HARD_RIGHT;
  light_left_fwd := steeringMotor = LIGHT_LEFT & driveMotor = FWD;
  light_left_bwd := steeringMotor = LIGHT_LEFT & driveMotor = BWD;
  hard_left_fwd := steeringMotor = HARD_LEFT & driveMotor = FWD;
  hard_left_bwd := steeringMotor = HARD_LEFT & driveMotor = BWD;
  light_right_fwd := steeringMotor = LIGHT_RIGHT & driveMotor = FWD;
  light_right_bwd := steeringMotor = LIGHT_RIGHT & driveMotor = BWD;
  hard_right_fwd := steeringMotor = HARD_RIGHT & driveMotor = FWD;
  hard_right_bwd := steeringMotor = HARD_RIGHT & driveMotor = BWD;
  getCloser := (PREV(sideSense = 5) & (sideSense < 5)) | (PREV(sideSense = 4) & (sideSense < 4)) | (PREV(sideSense = 3) & (sideSense < 3)) | (PREV(sideSense = 2) & (sideSense < 2)) | (PREV(sideSense = 1) & (sideSense < 1));
  sideways := light_left_fwd | light_left_bwd | hard_left_fwd | hard_left_bwd | light_right_fwd | light_right_bwd | hard_right_fwd | hard_right_bwd;
  fwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & forwarding;
  bwd_turning := (steeringMotor = HARD_LEFT | steeringMotor = HARD_RIGHT | steeringMotor = LIGHT_LEFT | steeringMotor = LIGHT_RIGHT) & reversing;

   
 
 
 
 
  



guarantee initial:
mode = SEARCHING  & steeringMotor = STRAIGHT & stopping;

 
gar 
pRespondsToS( ((mode = SEARCHING | mode = SCANNING) & (sideSense > 1)),  mode != SEARCHING | mode != SCANNING | sideSense = 1);
 

 
gar
G steeringMotor != FWD & steeringMotor != BWD & steeringMotor != STOP;

 
gar
G driveMotor != HARD_LEFT & driveMotor != LIGHT_LEFT & driveMotor != STRAIGHT & driveMotor != LIGHT_RIGHT & driveMotor != HARD_RIGHT;


 
gar
G ((mode = SCANNING) & (status = NONE   | (status = REVERSE & sideStatus = MIN_PARALLEL)) & frontSense > 2) -> (steeringMotor = STRAIGHT & driveMotor = FWD);


 
gar
G ((mode = SEARCHING) & status = NONE & frontSense > 2 & next(frontSense)>2 ) -> (steeringMotor = STRAIGHT & next(driveMotor) = FWD);
 


 
gar
G (mode = SCANNING & sideStatus = NONE & status = NONE) -> (next(mode) = SEARCHING);

 
gar
G (mode = SCANNING  & status = NONE  & sideStatus != NONE ) -> (next(mode) = SCANNING);

 
gar
G (mode = SEARCHING & sideStatus = NONE) -> (next(mode) = SEARCHING);

 
gar startScanning:
G (mode = SEARCHING & sideStatus != NONE) -> (next(mode) = SCANNING); 

 
 

 
guarantee dontCrashFront:
G (frontSense <= 2) -> ((driveMotor != FWD) | steeringMotor = HARD_LEFT);

 
guarantee dontCrashSide:
G ( sideSense <= 1) -> (steeringMotor = STRAIGHT);

 
guarantee speedWhileInStopping:
G driveMotor = STOP <-> velocity = 0;

 
guarantee speedWhileClear:
G (frontSense = 5 & mode = SEARCHING & !stopping) -> (velocity = 5);
guarantee speedWhileVeryFar:
G (frontSense = 4 & mode = SEARCHING & !stopping ) -> (velocity = 4);
guarantee speedWhileFar:
G (frontSense = 3 & mode = SEARCHING & !stopping) -> (velocity = 3);
guarantee slowSpeed:
G (frontSense = 3 & (mode = SCANNING) & !stopping) -> (velocity = 1);
  


 
gar reverselPlace:
G  (mode = SCANNING & ((status = REVERSE & sideStatus = MIN_REVERSE) | (status = PARALLEL & sideStatus = MIN_PARALLEL)) ) -> (next(stopping) & (next(mode) = PARKING) & steeringMotor = STRAIGHT & next(steeringMotor) = STRAIGHT);

 
 

 
gar noMatch:
G  (mode = SCANNING & status = REVERSE & sideStatus = MIN_PARALLEL) -> (next(mode) = SCANNING);

 
gar alwaysParkTheCar:
GF (stopping & (status = PARALLEL | status = REVERSE) & mode = PARKING) ;

 
 

 
assumption notParkedInitially:
status = NONE & frontSense > 2 & sideSense !=0;

 
asm
G (mode = SEARCHING & status = NONE) -> (next(status = NONE));


 
asm
pRespondsToS(mode = SCANNING, ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE)));

 
asm
pRespondsToS(driveMotor = BWD, (next(frontSense) = frontSense +1 | next(frontSense) = frontSense));

 
asm
pRespondsToS(driveMotor = FWD, (next(frontSense) = frontSense -1 | next(frontSense) = frontSense));




 
 
 





 
 

 
 
 


 
 

 
 


 
 

 
 
 

 
 
 

 
assumption moveAfterStopping:
pRespondsToS(stopping , frontSense > 2 & sideSense >= 2);


 
 

 
assumption notInACage:
GF (frontSense > 2  | sideSense >= 2);


 
asm ParallelparkingSpotsDontDisappear:
G (status = PARALLEL) -> (next(status) = PARALLEL);

 
asm ReverseparkingSpotsDontDisappear:
G (status = REVERSE) -> (next(status) = REVERSE | next(status) = PARALLEL);

 
assumption aParkingSpotExists:
 GF ((status = PARALLEL & sideStatus = MIN_PARALLEL) | (status = REVERSE & sideStatus = MIN_REVERSE));
module Robot 


env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;


sys Mode mode;
sys Int(0..5) from;
sys Int(0..5) to;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 
type Mode = {MOVE, NOTHING, INIT};

/*
 * The task that should be done now.
 * SORT task sorts the stations using mode = MOVE, and then satisfies mode = NOTHING
 * EXCHANGE task exchanges two different colored balls using mode = MOVE
 *  
 */
type Task = {SORT, EXCHANGE};


gar mode = INIT;

aux boolean initDone;
gar !initDone;
gar G next(initDone) = (mode = INIT | initDone);

 
gar G initDone -> mode != INIT;




asm sortingAssumptions;

/*
 * The combination of the second two gars yields that the array is finally sorted,
 * and then it stays sorted as long as task = SORT
 */
gar
  GF (task = SORT) -> sorted;
  
gar
  G (task = SORT & sorted & mode != INIT) -> mode = NOTHING; 




gar
  G (task = EXCHANGE & initDone) -> (mode = MOVE & incrementFrom);

      
        
   

gar moveRequirements:
  G (mode = MOVE) -> (fromExists & toExists & toIsEmpty & from != to);

 
 
asm saveOnInit:
  G (mode = INIT) -> saveAll;

asm saveOnNothing:
  G (mode = NOTHING) -> saveAll;

asm saveOnMove:
  G (mode = MOVE) -> (onExchangeSave & swap);

  




/*
 * some defines
 * 
 */
 
 define
  
   
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;
  
 
 
predicate swapAux(Int(0..5) fromVal, Color fromColor):
  
  (((from = fromVal) & (to = 0)) -> (next(fromColor) = s0 & next(s0) = fromColor)) &
  (((from = fromVal) & (to = 1)) -> (next(fromColor) = s1 & next(s1) = fromColor)) &
  (((from = fromVal) & (to = 2)) -> (next(fromColor) = s2 & next(s2) = fromColor)) &
  (((from = fromVal) & (to = 3)) -> (next(fromColor) = s3 & next(s3) = fromColor)) &
  (((from = fromVal) & (to = 4)) -> (next(fromColor) = s4 & next(s4) = fromColor)) &
  (((from = fromVal) & (to = 5)) -> (next(fromColor) = s5 & next(s5) = fromColor)) ;

 
define
/*
 * Iterates over all the possible values of 'from', and performs swapAux
 * which, in turn, iterates over all possible values of 'to',
 * and performs swap if the correct pair of ('from', 'to') is found 
 * 
 */
  swap :=
    swapAux(0, s0) &
    swapAux(1, s1) &
    swapAux(2, s2) &
    swapAux(3, s3) &
    swapAux(4, s4) &
    swapAux(5, s5) ;

/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  toIsEmpty :=
    ((to = 0) -> (s0 = EMPTY)) &
    ((to = 1) -> (s1 = EMPTY)) &
    ((to = 2) -> (s2 = EMPTY)) &
    ((to = 3) -> (s3 = EMPTY)) &
    ((to = 4) -> (s4 = EMPTY)) &
    ((to = 5) -> (s5 = EMPTY)) ;
  
  
  
   sorted :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;
   

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;

define

   fromExists :=
      exists(from);
      
   toExists :=
      exists(to);
   
   somethingExists :=
      (s0 != NOT) |
      (s1 != NOT) |
      (s2 != NOT) |
      (s3 != NOT) |
      (s4 != NOT) |
      (s5 != NOT) ;
      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;
  
define
      
   equal :=
      allEqual(RED)   |
      allEqual(GREEN) |
      allEqual(BLUE)  ;
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
   
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);
 
   
   
  sortingAssumptions :=
    extraAssumptions & somethingEmpty & firstStationsExist & somethingExists & !equal;
 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 5) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 5) & exists(from+1)) -> next(from) = 0) ;

 
 
module b

env Color color0;
env Color color1;
env Color color2;

sys Int(0..2) a;
sys Int(0..2) b;

aux Color aColor;
aux Color bColor;

type Color = {RED, GREEN, BLUE, EMPTY, NOT};

 
predicate assign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = color0) &
  ((index = 1) -> colorIndex = color1) &
  ((index = 2) -> colorIndex = color2) ;

gar G assign(a, aColor);
gar G assign(b, bColor);



define
  swap :=
    (aColor = next(bColor)) &
    (bColor = next(aColor)) ;

asm G swap;
module c

env Color color0;
env Color color1;
env Color color2;

sys Int(0..2) a;
sys Int(0..2) b;

aux Color aColor;
aux Color bColor;

type Color = {RED, GREEN, BLUE, EMPTY, NOT};

 
predicate assign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = color0) &
  ((index = 1) -> colorIndex = color1) &
  ((index = 2) -> colorIndex = color2) ;

gar G assign(a, aColor) & assign(b, bColor);


 
predicate setColor(Int(0..2) index, Color color):
  ((index = 0) -> next(color0)=color) &
  ((index = 1) -> next(color1)=color) &
  ((index = 2) -> next(color2)=color) ;

 
 
 
asm G setColor(a, aColor) & setColor(b, bColor);
 
 
 
 

 
 
 
 


gar a!=b;
gar G next(a)!=next(b);
module Robot 


env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;


sys Mode mode;
sys Int(0..5) from;
sys Int(0..5) to;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 
type Mode = {MOVE, NOTHING, INIT};

/*
 * The task that should be done now.
 * SORT task sorts the stations using mode = MOVE, and then satisfies mode = NOTHING
 * EXCHANGE task exchanges two different colored balls using mode = MOVE
 *  
 */
type Task = {SORT, EXCHANGE};


gar mode = INIT;

aux boolean initDone;
gar !initDone;
gar G next(initDone) = (mode = INIT | initDone);

 
gar G initDone -> mode != INIT;




asm sortingAssumptions;

/*
 * The combination of the second two gars yields that the array is finally sorted,
 * and then it stays sorted as long as task = SORT
 */
gar
  GF (task = SORT) -> sorted;
  
gar
  G (task = SORT & sorted & mode != INIT) -> mode = NOTHING; 




gar
  G (task = EXCHANGE & initDone) -> (mode = MOVE & incrementFrom);

      
        
   

gar moveRequirements:
  G (mode = MOVE) -> (fromExists & toExists & toIsEmpty & from != to);

 
 
asm saveOnInit:
  G (mode = INIT) -> saveAll;

asm saveOnNothing:
  G (mode = NOTHING) -> saveAll;

asm saveOnMove:
  G (mode = MOVE) -> (onExchangeSave & swap);

  




/*
 * some defines
 * 
 */
 
 define
  
   
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;
  
 
 
predicate swapAux(Int(0..5) fromVal, Color fromColor):
  
  (((from = fromVal) & (to = 0)) -> (next(fromColor) = s0 & next(s0) = fromColor)) &
  (((from = fromVal) & (to = 1)) -> (next(fromColor) = s1 & next(s1) = fromColor)) &
  (((from = fromVal) & (to = 2)) -> (next(fromColor) = s2 & next(s2) = fromColor)) &
  (((from = fromVal) & (to = 3)) -> (next(fromColor) = s3 & next(s3) = fromColor)) &
  (((from = fromVal) & (to = 4)) -> (next(fromColor) = s4 & next(s4) = fromColor)) &
  (((from = fromVal) & (to = 5)) -> (next(fromColor) = s5 & next(s5) = fromColor)) ;

 
define
/*
 * Iterates over all the possible values of 'from', and performs swapAux
 * which, in turn, iterates over all possible values of 'to',
 * and performs swap if the correct pair of ('from', 'to') is found 
 * 
 */
  swap :=
    swapAux(0, s0) &
    swapAux(1, s1) &
    swapAux(2, s2) &
    swapAux(3, s3) &
    swapAux(4, s4) &
    swapAux(5, s5) ;

/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  toIsEmpty :=
    ((to = 0) -> (s0 = EMPTY)) &
    ((to = 1) -> (s1 = EMPTY)) &
    ((to = 2) -> (s2 = EMPTY)) &
    ((to = 3) -> (s3 = EMPTY)) &
    ((to = 4) -> (s4 = EMPTY)) &
    ((to = 5) -> (s5 = EMPTY)) ;
  
  
  
   sorted :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;
   

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;

define

   fromExists :=
      exists(from);
      
   toExists :=
      exists(to);
   
   somethingExists :=
      (s0 != NOT) |
      (s1 != NOT) |
      (s2 != NOT) |
      (s3 != NOT) |
      (s4 != NOT) |
      (s5 != NOT) ;
      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;
  
define
      
   equal :=
      allEqual(RED)   |
      allEqual(GREEN) |
      allEqual(BLUE)  ;
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
   
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);
 
   
   
  sortingAssumptions :=
    extraAssumptions & somethingEmpty & firstStationsExist & somethingExists & !equal;
 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 5) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 5) & exists(from+1)) -> next(from) = 0) ;

 
 
module x


env Color s0;
env Color s1;
env Color s2;

env Task task;


sys boolean isMoving;
sys Int(0..5) from;
sys Int(0..5) to;

 
aux Color fromColor;
aux Color toColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..5) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) ;

gar G assign(from, fromColor);
gar G assign(to, toColor);



 
predicate setColor(Int(0..5) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) ;
  
asm saveOnStaying:
  G !isMoving & task != SCAN -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) ;
  
  
  
  
   sortDone :=
    
      (s0 <= s1) &
      (s1 <= s2) ;
 
 
 
 


predicate isColor(Color color):
  color != EMPTY & color != NOT;
  
define
  strongAssumptions :=
    s0 = EMPTY &
    s1 = RED &
    s2 = NOT ;

asm G next(strongAssumptions);
 
asm G task = SCAN -> strongAssumptions;
module r



env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;


sys boolean isMoving;
sys Int(0..5) from;
sys Int(0..5) to;

 
aux Color fromColor;
aux Color toColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..5) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) &
  ((index = 4) -> colorIndex = s4) &
  ((index = 5) -> colorIndex = s5) ;

gar G assign(from, fromColor);
gar G assign(to, toColor);



 
predicate setColor(Int(0..5) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) &
  ((index = 4) -> next(s4)=color) &
  ((index = 5) -> next(s5)=color) ;
  
asm saveOnStaying:
  G !isMoving & task != SCAN -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
   
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */


 


define
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);



predicate isColor(Color color):
  color != EMPTY & color != NOT;
  
define
  strongAssumptions :=
    s0 = EMPTY &
    s1 = RED &
    s2 = NOT &
     
     
     
    s3 = NOT &
    s4 = NOT &
    s5 = NOT;


 
 
 
 
 
 
asm G next(strongAssumptions);
asm G task = SCAN -> strongAssumptions;
asm G task = SCAN -> next(strongAssumptions);
module z


env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;

sys boolean isMoving;
sys Mode mode;
sys Int(0..5) from;
sys Int(0..5) to;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 
type Mode = {MOVE, NOTHING};

/*
 * The task that should be done now.
 * SORT task sorts the stations using mode = MOVE, and then satisfies mode = NOTHING
 * EXCHANGE task exchanges two different colored balls using mode = MOVE
 *  
 */
type Task = {SORT, EXCHANGE, SCAN};





asm sortingAssumptions;

/*
 * The combination of the second two gars yields that the array is finally sorted,
 * and then it stays sorted as long as task = SORT
 */
gar
  GF (task = SORT) -> sorted;
  
gar
  G (task = SORT & sorted) -> mode = NOTHING; 




gar
  G (task = EXCHANGE) -> (mode = MOVE & incrementFrom);

      
        
   

gar moveRequirements:
  G (mode = MOVE) -> (fromExists & toExists & toIsEmpty & from != to);

 
 
 
 

asm saveOnNothing:
  G (mode = NOTHING) -> saveAll;

asm saveOnMove:
  G (mode = MOVE) -> (onExchangeSave & swap);

  




/*
 * some defines
 * 
 */
 
 define
  
   
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;
  
 
 
predicate swapAux(Int(0..5) fromVal, Color fromColor):
  
  (((from = fromVal) & (to = 0)) -> (next(fromColor) = s0 & next(s0) = fromColor)) &
  (((from = fromVal) & (to = 1)) -> (next(fromColor) = s1 & next(s1) = fromColor)) &
  (((from = fromVal) & (to = 2)) -> (next(fromColor) = s2 & next(s2) = fromColor)) &
  (((from = fromVal) & (to = 3)) -> (next(fromColor) = s3 & next(s3) = fromColor)) &
  (((from = fromVal) & (to = 4)) -> (next(fromColor) = s4 & next(s4) = fromColor)) &
  (((from = fromVal) & (to = 5)) -> (next(fromColor) = s5 & next(s5) = fromColor)) ;

 
define
/*
 * Iterates over all the possible values of 'from', and performs swapAux
 * which, in turn, iterates over all possible values of 'to',
 * and performs swap if the correct pair of ('from', 'to') is found 
 * 
 */
  swap :=
    swapAux(0, s0) &
    swapAux(1, s1) &
    swapAux(2, s2) &
    swapAux(3, s3) &
    swapAux(4, s4) &
    swapAux(5, s5) ;

/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  toIsEmpty :=
    ((to = 0) -> (s0 = EMPTY)) &
    ((to = 1) -> (s1 = EMPTY)) &
    ((to = 2) -> (s2 = EMPTY)) &
    ((to = 3) -> (s3 = EMPTY)) &
    ((to = 4) -> (s4 = EMPTY)) &
    ((to = 5) -> (s5 = EMPTY)) ;
  
  
  
   sorted :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;
   

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;

define

   fromExists :=
      exists(from);
      
   toExists :=
      exists(to);
   
   somethingExists :=
      (s0 != NOT) |
      (s1 != NOT) |
      (s2 != NOT) |
      (s3 != NOT) |
      (s4 != NOT) |
      (s5 != NOT) ;
      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;
  
define
      
   equal :=
      allEqual(RED)   |
      allEqual(GREEN) |
      allEqual(BLUE)  ;
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
   
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);
 
   
   
  sortingAssumptions :=
    extraAssumptions & somethingEmpty & firstStationsExist & somethingExists & !equal;
 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 5) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 5) & exists(from+1)) -> next(from) = 0) ;

 
 

define 
  strongAsm :=
    s0 = EMPTY &
    s1 = BLUE &
    s2 = GREEN &
    s3 = RED &
    s4 = NOT &
    s5 = NOT ;
    
 
 


asm G task = SCAN -> strongAsm;
asm G task = SCAN -> next(strongAsm);

asm G next(task) = SORT;
module v


asm G next(task) = SORT;

env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;


sys boolean isMoving;
sys Int(0..5) from;
sys Int(0..5) to;

 
aux Color fromColor;
aux Color toColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving & task != HANOI) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..5) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) &
  ((index = 4) -> colorIndex = s4) &
  ((index = 5) -> colorIndex = s5) ;

gar G assign(from, fromColor);
gar G assign(to, toColor);



 
predicate setColor(Int(0..5) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) &
  ((index = 4) -> next(s4)=color) &
  ((index = 5) -> next(s5)=color) ;
  
asm saveOnStaying:
  G !isMoving & task != SCAN -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN & task != HANOI) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;

/*
 * 
 * 
 * 
 *  
 * 
 * Recall that in Hanoi task moving from 'from' to 'to' gets another interpretation
 * 
 * 
 */
    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !isMoving;     


asm
  G isMoving & task = HANOI -> onExchangeSave;
  
gar
  G task = HANOI & isMoving -> hanoiLegalMove;
  
  
define


  hanoiAsms :=
    s0 != NOT &
    s1 != NOT &
    s2 != NOT ;
    
 
 
 
 
  
 
 
 
  
  hanoiDone :=  
    (s0 = EMPTY) &
    (s2 = EMPTY);
  
  hanoiLegalMove :=
    (from <= 2) &  
    (to   <= 2) &  
    toColor <= fromColor;
    

asm
  G (task = HANOI & isMoving & hanoiAsms & hanoiLegalMove) ->
      incrementColor(from);  
    
asm
  G (task = HANOI & isMoving & hanoiAsms & hanoiLegalMove) ->
      setColor(to, fromColor) ;
       

 
 
predicate incrementColor(Int (0..5) index):
  ((index = 0 & s0 != EMPTY) -> (next(s0) > s0) & (next(s0) != NOT)) &
  ((index = 1 & s1 != EMPTY) -> (next(s1) > s1) & (next(s1) != NOT)) &
  ((index = 2 & s2 != EMPTY) -> (next(s2) > s2) & (next(s2) != NOT)) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 5) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 5) & exists(from+1)) -> next(from) = 0) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s5 = RED) -> (s4 = RED)) &
    ((s4 = RED) -> (s3 = RED)) &
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) &
  ((index >= 5) -> (s4 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) &
      ((s4 = RED) -> prevBallsNotEmpty(4)) &
      ((s5 = RED) -> prevBallsNotEmpty(5)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color |
  s4 = color |
  s5 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */


 


define
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);



predicate isColor(Color color):
  color != EMPTY & color != NOT;
  
define
  strongAssumptions :=
    s0 = EMPTY &
    s1 = RED &
    s2 = BLUE &
     
     
     
    s3 = NOT &
    s4 = NOT &
    s5 = NOT;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
asm G next(task) = task | nextTask;


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);




define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE |
    s4 = RED | s4 = GREEN | s4 = BLUE |
    s5 = RED | s5 = GREEN | s5 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
asm G next(movingAsms);


 
 
 
 

 
module k


asm G next(task) = SORT;

env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;


sys boolean isMoving;
sys Int(0..5) from;
sys Int(0..5) to;

 
aux Color fromColor;
aux Color toColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT  
  
};



gar moveRequirements:
  G (isMoving ) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..5) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) &
  ((index = 4) -> colorIndex = s4) &
  ((index = 5) -> colorIndex = s5) ;

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));



 
predicate setColor(Int(0..5) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) &
  ((index = 4) -> next(s4)=color) &
  ((index = 5) -> next(s5)=color) ;
  
asm saveOnStaying:
  G !isMoving & task != SCAN -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);



asm saveOnMoving:
  G (isMoving & task != SCAN ) -> (onExchangeSave);

asm G (isMoving & task != SCAN ) -> (swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


 
 
 
 
 
 
 
 

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */


 


define
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);



predicate isColor(Color color):
  color != EMPTY & color != NOT;
  
define
  strongAssumptions :=
 
 
 

    s0 != EMPTY & s0 != NOT &
    s1 != EMPTY & s1 != NOT &
    s2 != EMPTY & s2 != NOT &
    
 
 
 
    s3 = NOT &
    s4 = NOT &
    s5 = NOT;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
 


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=true;




define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE |
    s4 = RED | s4 = GREEN | s4 = BLUE |
    s5 = RED | s5 = GREEN | s5 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

asm someColorExists;
asm G next(someColorExists);

asm colorExists(EMPTY);
asm G next(colorExists(EMPTY));


 
 


 
 
 
 

 


predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color |
  s4 = color |
  s5 = color ;
module t


asm G next(task) = SORT;

env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;



type Color = {RED, GREEN, BLUE, EMPTY, NOT};


type Task = {
  SCAN,
  SORT  
  
};





asm startWithScan:
  task = SCAN;




      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;

  
 
   
   
  
 
    
   
  
  
  
  
  
     




  
define
  strongAssumptions :=
 
 
 

    s0 != EMPTY & s0 != NOT &
    s1 != EMPTY & s1 != NOT &
    s2 != EMPTY & s2 != NOT &
    
 
 
 
    s3 = NOT &
    s4 = NOT &
    s5 = NOT;

  


 
asm G next(strongAssumptions);

  




define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE |
    s4 = RED | s4 = GREEN | s4 = BLUE |
    s5 = RED | s5 = GREEN | s5 = BLUE ;
    
    

asm G next(colorExists(EMPTY));



predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color |
  s4 = color |
  s5 = color ;
module e



env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;


sys boolean isMoving;
sys Int(0..5) from;
sys Int(0..5) to;

 
aux Color fromColor;
aux Color toColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving & task != HANOI) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..5) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) &
  ((index = 4) -> colorIndex = s4) &
  ((index = 5) -> colorIndex = s5) ;

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));



 
predicate setColor(Int(0..5) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) &
  ((index = 4) -> next(s4)=color) &
  ((index = 5) -> next(s5)=color) ;
  
asm saveOnStaying:
  G !isMoving & task != SCAN -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN & task != HANOI) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;

/*
 * 
 * 
 * 
 *  
 * 
 * Recall that in Hanoi task moving from 'from' to 'to' gets another interpretation
 * 
 * 
 */
    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !isMoving;     


asm
  G isMoving & task = HANOI -> onExchangeSave;
  
gar
  G task = HANOI & isMoving -> hanoiLegalMove;
  
  
define


  hanoiAsms :=
    s0 != NOT &
    s1 != NOT &
    s2 != NOT ;
    
 
 
 
 
  
 
 
 
  
  hanoiDone :=  
    (s0 = EMPTY) &
    (s2 = EMPTY);
  
  hanoiLegalMove :=
    (from <= 2) &  
    (to   <= 2) &  
    toColor <= fromColor;
    

asm
  G (task = HANOI & isMoving & hanoiAsms & hanoiLegalMove) ->
      incrementColor(from);  
    
asm
  G (task = HANOI & isMoving & hanoiAsms & hanoiLegalMove) ->
      setColor(to, fromColor) ;
       

 
 
predicate incrementColor(Int (0..5) index):
  ((index = 0 & s0 != EMPTY) -> (next(s0) > s0) & (next(s0) != NOT)) &
  ((index = 1 & s1 != EMPTY) -> (next(s1) > s1) & (next(s1) != NOT)) &
  ((index = 2 & s2 != EMPTY) -> (next(s2) > s2) & (next(s2) != NOT)) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 5) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 5) & exists(from+1)) -> next(from) = 0) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s5 = RED) -> (s4 = RED)) &
    ((s4 = RED) -> (s3 = RED)) &
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) &
  ((index >= 5) -> (s4 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) &
      ((s4 = RED) -> prevBallsNotEmpty(4)) &
      ((s5 = RED) -> prevBallsNotEmpty(5)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color |
  s4 = color |
  s5 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




define
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);



predicate isColor(Color color):
  color != EMPTY & color != NOT;
  
define
  strongAssumptions :=
 
 
 
    isColor(s0) &
    isColor(s1) &
    isColor(s2) &
    s3 = EMPTY &
    s4 = NOT &
    s5 = NOT;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
 


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    
 


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE |
    s4 = RED | s4 = GREEN | s4 = BLUE |
    s5 = RED | s5 = GREEN | s5 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
asm G next(movingAsms);

asm G next(task) = GATHER_REDS;

 
 
 
 

 
module z2


env Color t0;
env Color t1;
env Color t2;



env Task task;


sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;


aux Color hanoiFromColor;
aux Color hanoiToColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};





predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));



  





/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 * 
 * 
 *  
 * 
 * Recall that in Hanoi task moving from 'from' to 'to' gets another interpretation
 * 
 * 
 */
    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (((hanoiFrom != 0) & (hanoiTo!=0)) -> ((next(t0) = t0))) &
    (((hanoiFrom != 1) & (hanoiTo!=1)) -> ((next(t1) = t1))) &
    (((hanoiFrom != 2) & (hanoiTo!=2)) -> ((next(t2) = t2))) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
 
 
 
 
  
 
 
 
  
  hanoiDone :=  
    (t0 = EMPTY) &
    (t2 = EMPTY);
  
  hanoiLegalMove :=
 
 
    hanoiFromColor != EMPTY &
    hanoiToColor > hanoiFromColor;
    
 
 
 
 
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->      
 
      hanoiNextFrom;


predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
predicate hanoiIncrementColor(Int (0..2) index):
  ((index = 0 & t0 != EMPTY) -> (next(t0) > t0) & (next(t0) != NOT)) &
  ((index = 1 & t1 != EMPTY) -> (next(t1) > t1) & (next(t1) != NOT)) &
  ((index = 2 & t2 != EMPTY) -> (next(t2) > t2) & (next(t2) != NOT)) ;

define
  hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0)) &
    (hanoiFrom = 1 -> nextColor(t1)) &
    (hanoiFrom = 2 -> nextColor(t2)) ;
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */






predicate isColor(Color color):
  color != EMPTY & color != NOT;
 

  


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    
 




asm G next(task) = HANOI;

 
 
 
 

 

define
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;

asm hanoiStrongAsms;
asm G task = SCAN -> next(hanoiStrongAsms);

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G !hanoiIsMoving -> hanoiSaveAll;

predicate notEequal(Color a, Color b):
  next(a = b -> a = EMPTY);
define
  noRepeats :=
    notEequal(t0, t1) &
    notEequal(t0, t2) &
    notEequal(t1, t2) &
 
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t0) -> t0 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t1) -> t1 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t2) -> t2 =EMPTY) ;
    
asm G task = HANOI -> noRepeats;

   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
 

    
module z1


env Color t0;
env Color t1;
env Color t2;

env Color s0;
env Color s1;
env Color s2;
env Color s3;
env Color s4;
env Color s5;

env Task task;


sys boolean isMoving;
sys Int(0..5) from;
sys Int(0..5) to;

sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;

 
aux Color fromColor;
aux Color toColor;

aux Color hanoiFromColor;
aux Color hanoiToColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..5) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) &
  ((index = 4) -> colorIndex = s4) &
  ((index = 5) -> colorIndex = s5) ;

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));

predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));



 
predicate setColor(Int(0..5) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) &
  ((index = 4) -> next(s4)=color) &
  ((index = 5) -> next(s5)=color) ;
  
asm saveOnStaying:
  G !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) &
    (next(s4) = s4) &
    (next(s5) = s5) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) &
    (((from != 4) & (to!=4)) -> ((next(s4) = s4))) &
    (((from != 5) & (to!=5)) -> ((next(s5) = s5))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..5) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) &
  ((index = 4) -> (s4 != NOT)) &
  ((index = 5) -> (s5 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) &
  ((s4 = color) | (s4 = EMPTY) | (s4 = NOT)) &
  ((s5 = color) | (s5 = EMPTY) | (s5 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */
 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) &
    ((s3 = NOT) -> (s4 = NOT)) &
    ((s4 = NOT) -> (s5 = NOT)) ;
    
    
 
  somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) |
    (s4 = EMPTY) |
    (s5 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) &
      (s3 <= s4) &
      (s4 <= s5) ;

/*
 * 
 * 
 * 
 *  
 * 
 * Recall that in Hanoi task moving from 'from' to 'to' gets another interpretation
 * 
 * 
 */
    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  
gar
  G isMoving -> task != HANOI;

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (((hanoiFrom != 0) & (hanoiTo!=0)) -> ((next(t0) = t0))) &
    (((hanoiFrom != 1) & (hanoiTo!=1)) -> ((next(t1) = t1))) &
    (((hanoiFrom != 2) & (hanoiTo!=2)) -> ((next(t2) = t2))) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
 
 
 
 
  
 
 
 
  
  hanoiDone :=  
    (t0 = EMPTY) &
    (t2 = EMPTY);
  
  hanoiLegalMove :=
 
 
    hanoiFromColor != EMPTY &
    hanoiToColor > hanoiFromColor;
    
 
 
 
 
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->      
 
      hanoiNextFrom;


predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
predicate hanoiIncrementColor(Int (0..2) index):
  ((index = 0 & t0 != EMPTY) -> (next(t0) > t0) & (next(t0) != NOT)) &
  ((index = 1 & t1 != EMPTY) -> (next(t1) > t1) & (next(t1) != NOT)) &
  ((index = 2 & t2 != EMPTY) -> (next(t2) > t2) & (next(t2) != NOT)) ;
  define
    hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0)) &
    (hanoiFrom = 1 -> nextColor(t1)) &
    (hanoiFrom = 2 -> nextColor(t2)) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 5) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 5) & exists(from+1)) -> next(from) = 0) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s5 = RED) -> (s4 = RED)) &
    ((s4 = RED) -> (s3 = RED)) &
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) &
  ((index >= 5) -> (s4 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) &
      ((s4 = RED) -> prevBallsNotEmpty(4)) &
      ((s5 = RED) -> prevBallsNotEmpty(5)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color |
  s4 = color |
  s5 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




define
   extraAssumptions :=
 
 
 
 
      (s4  = NOT)   &
      (s5  = NOT);



predicate isColor(Color color):
  color != EMPTY & color != NOT;
  
define
  strongAssumptions :=
 
 
 
    isColor(s0) &
    isColor(s1) &
    isColor(s2) &
    s3 = EMPTY &
    s4 = NOT &
    s5 = NOT;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
 


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    
 


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE |
    s4 = RED | s4 = GREEN | s4 = BLUE |
    s5 = RED | s5 = GREEN | s5 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
asm G next(movingAsms);

asm G next(task) = HANOI;

 
 
 
 

 

define
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;

asm hanoiStrongAsms;
asm G task = SCAN -> next(hanoiStrongAsms);

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G !hanoiIsMoving -> hanoiSaveAll;

predicate notEequal(Color a, Color b):
  next(a = b -> a = EMPTY);
define
  noRepeats :=
    notEequal(t0, t1) &
    notEequal(t0, t2) &
    notEequal(t1, t2) &
 
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t0) -> t0 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t1) -> t1 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t2) -> t2 =EMPTY) ;
    
asm G task = HANOI -> noRepeats;

   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
 

    
module z3

env Color s0;
env Color s1;
env Color s2;
env Color s3;

env Task task;


sys boolean isMoving;
sys Int(0..3) from;
sys Int(0..3) to;


 
aux Color fromColor;
aux Color toColor;



/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..3) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) ;

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));




 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  
asm saveOnStaying:
  G task != SCAN & !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */

define 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) ;
    
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




define
   extraAssumptions :=true;
 
 
 
 
 
 



predicate isColor(Color color):
  color = RED | color = GREEN | color = BLUE;
 
  
define
  strongAssumptions :=
 
 
 
    s0 = EMPTY &
    isColor(s1) &
    isColor(s2) &
    isColor(s3) ;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
 


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    
 


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
 


asm G next(colorExists(EMPTY)) ; 
asm G next(someColorExists);


 
 
 
 

 





predicate notEequal(Color a, Color b):
  next(a = b -> a = EMPTY);


   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
 
 
 
 
 
 
 

asm G next(task) = GATHER_REDS;

 
module z4

env Color s0;
env Color s1;
env Color s2;
env Color s3;

env Task task;


sys boolean isMoving;
sys Int(0..3) from;
sys Int(0..3) to;


 
aux Color fromColor;
aux Color toColor;



/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..3) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) ;

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));




 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  
asm saveOnStaying:
  G task != SCAN & !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */

define 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) ;
    
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




define
   extraAssumptions :=true;
 
 
 
 
 
 



predicate isColor(Color color):
  color = RED | color = GREEN | color = BLUE;
 
  
define
  strongAssumptions :=
 
 
 
    s0 = EMPTY &
    isColor(s1) &
    isColor(s2) &
    isColor(s3) ;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
 


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    
 


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
asm G next(movingAsms);


 
 





 
 
 
 
 
 
 

asm G next(task) = HANOI;

 

























/*
 * 
 * 
 * 
 * HANOI TASK
 * 
 * 
 * 
 */




env Color t0;
env Color t1;
env Color t2;



sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;


aux Color hanoiFromColor;
aux Color hanoiToColor;






predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));





    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (((hanoiFrom != 0) & (hanoiTo!=0)) -> ((next(t0) = t0))) &
    (((hanoiFrom != 1) & (hanoiTo!=1)) -> ((next(t1) = t1))) &
    (((hanoiFrom != 2) & (hanoiTo!=2)) -> ((next(t2) = t2))) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
      
  hanoiDone :=  
    (t0 = EMPTY) &
    (t2 = EMPTY);
  
  hanoiLegalMove :=
 
 
    hanoiFromColor != EMPTY &
    hanoiToColor > hanoiFromColor;
    
 
 
 
 
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->      
 
      hanoiNextFrom;


predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
predicate hanoiIncrementColor(Int (0..2) index):
  ((index = 0 & t0 != EMPTY) -> (next(t0) > t0) & (next(t0) != NOT)) &
  ((index = 1 & t1 != EMPTY) -> (next(t1) > t1) & (next(t1) != NOT)) &
  ((index = 2 & t2 != EMPTY) -> (next(t2) > t2) & (next(t2) != NOT)) ;

define
  hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0)) &
    (hanoiFrom = 1 -> nextColor(t1)) &
    (hanoiFrom = 2 -> nextColor(t2)) ;
  
define
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;

asm hanoiStrongAsms;
asm G task = SCAN -> next(hanoiStrongAsms);

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G !hanoiIsMoving -> hanoiSaveAll;

predicate notEqual(Color a, Color b):
  next(a = b -> a = EMPTY);
define
  noRepeats :=
    notEqual(t0, t1) &
    notEqual(t0, t2) &
    notEqual(t1, t2) &
 
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t0) -> t0 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t1) -> t1 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t2) -> t2 =EMPTY) ;
    
asm G task = HANOI -> noRepeats;

   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
  
  
asm G next(hanoiAsms);
module Z5

env Color s0;
env Color s1;
env Color s2;
env Color s3;

env Task task;


sys boolean isMoving;
sys Int(0..3) from;
sys Int(0..3) to;


 
aux Color fromColor;
aux Color toColor;



/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..3) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) ;

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));




 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  
asm saveOnStaying:
  G task != SCAN & !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */

define 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) ;
    
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




define
   extraAssumptions :=true;
 
 
 
 
 
 



predicate isColor(Color color):
  color = RED | color = GREEN | color = BLUE;
 
  
define
  strongAssumptions :=
 
 
 
    s0 = EMPTY &
    isColor(s1) &
    isColor(s2) &
    isColor(s3) ;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
asm G next(task) = task | nextTask;


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
asm G next(movingAsms);




 
 
 
 
 
 
 

asm G next(task) = HANOI;

 







/*
 * 
 * 
 * 
 * HANOI TASK
 * 
 * 
 * 
 */




env Color t0;
env Color t1;
env Color t2;



sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;


aux Color hanoiFromColor;
aux Color hanoiToColor;






predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));





    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF task = HANOI -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (((hanoiFrom != 0) & (hanoiTo!=0)) -> ((next(t0) = t0))) &
    (((hanoiFrom != 1) & (hanoiTo!=1)) -> ((next(t1) = t1))) &
    (((hanoiFrom != 2) & (hanoiTo!=2)) -> ((next(t2) = t2))) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
      
  hanoiDone :=  
    (t0 = EMPTY) &
    (t2 = EMPTY);
  
  hanoiLegalMove :=
 
 
    hanoiFromColor != EMPTY &
    hanoiToColor > hanoiFromColor;
    
 
 
 
 
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) &
      hanoiNextFrom;



predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
predicate hanoiIncrementColor(Int (0..2) index):
  ((index = 0 & t0 != EMPTY) -> (next(t0) > t0) & (next(t0) != NOT)) &
  ((index = 1 & t1 != EMPTY) -> (next(t1) > t1) & (next(t1) != NOT)) &
  ((index = 2 & t2 != EMPTY) -> (next(t2) > t2) & (next(t2) != NOT)) ;

define
  hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0)) &
    (hanoiFrom = 1 -> nextColor(t1)) &
    (hanoiFrom = 2 -> nextColor(t2)) ;
  
 
 
 
 
 
 
 
 

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G !hanoiIsMoving -> hanoiSaveAll;

predicate notEqual(Color a, Color b):
  next(a = b -> a = EMPTY);
define
  noRepeats :=
    notEqual(t0, t1) &
    notEqual(t0, t2) &
    notEqual(t1, t2) &
 
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t0) -> t0 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t1) -> t1 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t2) -> t2 =EMPTY) ;
    
asm G task = HANOI -> noRepeats;

   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
  
asm hanoiAsms;  
asm G next(hanoiAsms);
module Robot

env Color s0;
env Color s1;
env Color s2;
env Color s3;

env Task task;


sys boolean isMoving;
sys Int(0..3) from;
sys Int(0..3) to;


 
aux Color fromColor;
aux Color toColor;


/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 

type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};


gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..3) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) ;

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));



 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  
asm saveOnStaying:
  G task != SCAN & !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */

define 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) ;
    
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
    ( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */



define
   extraAssumptions :=true;
 
 
 
 
 
 



predicate isColor(Color color):
  color = RED | color = GREEN | color = BLUE;
 
  
define
  strongAssumptions :=
 
 
 
    s0 = EMPTY &
    isColor(s1) &
    isColor(s2) &
    isColor(s3) ;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
 
asm G next(s0) != GREEN &
      next(s1) != GREEN &
      next(s2) != GREEN &
      next(s3) != GREEN ;


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);


    
 


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

asm movingAsms;
asm G next(movingAsms);


 
 

 
 
 
 
 
 
 

 

 

























/*
 * 
 * 
 * 
 * HANOI TASK
 * 
 * 
 * 
 */


env Color t0;
env Color t1;
env Color t2;



sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;


aux Color hanoiFromColor;
aux Color hanoiToColor;


predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));




asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (((hanoiFrom != 0) & (hanoiTo!=0)) -> ((next(t0) = t0))) &
    (((hanoiFrom != 1) & (hanoiTo!=1)) -> ((next(t1) = t1))) &
    (((hanoiFrom != 2) & (hanoiTo!=2)) -> ((next(t2) = t2))) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
      
  hanoiDone :=  
    (t0 = EMPTY) &
    (t2 = EMPTY);
  
  hanoiLegalMove :=
 
 
    hanoiFromColor != EMPTY &
    hanoiToColor > hanoiFromColor;
    
 
 
 
 
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->      
 
      hanoiNextFrom;


predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
predicate hanoiIncrementColor(Int (0..2) index):
  ((index = 0 & t0 != EMPTY) -> (next(t0) > t0) & (next(t0) != NOT)) &
  ((index = 1 & t1 != EMPTY) -> (next(t1) > t1) & (next(t1) != NOT)) &
  ((index = 2 & t2 != EMPTY) -> (next(t2) > t2) & (next(t2) != NOT)) ;

define
  hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0)) &
    (hanoiFrom = 1 -> nextColor(t1)) &
    (hanoiFrom = 2 -> nextColor(t2)) ;
  
define
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;

asm hanoiStrongAsms;
asm G task!=HANOI -> next(hanoiStrongAsms);

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G task = HANOI & !hanoiIsMoving -> hanoiSaveAll;

predicate notEqual(Color a, Color b):
  next(a = b -> a = EMPTY);
define
  noRepeats :=
    notEqual(t0, t1) &
    notEqual(t0, t2) &
    notEqual(t1, t2) &
 
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t0) -> t0 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t1) -> t1 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t2) -> t2 =EMPTY) ;
    
asm G task = HANOI -> noRepeats;

   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
  

asm hanoiAsms;
asm G next(hanoiAsms);
module z7

env Color s0;
env Color s1;
env Color s2;
env Color s3;

env Task task;


sys boolean isMoving;
sys Int(0..3) from;
sys Int(0..3) to;


 
aux Color fromColor;
aux Color toColor;



/*
 * EMPTY denotes an empty station
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..3) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) ;

gar assign(from, fromColor);
gar assign(to, toColor);

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));




 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  
asm saveOnStaying:
  G task != SCAN & !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */

define 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) ;
    
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
   
    (( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0)) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




define
   extraAssumptions :=true;
 
 
 
 
 
 



predicate isColor(Color color):
  color = RED | color = GREEN | color = BLUE;
 
  
define
  strongAssumptions :=
 
 
 
    s0 = EMPTY &
    isColor(s1) &
    isColor(s2) &
    isColor(s3) ;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN -> next(strongAssumptions);




 
 
asm G next(s0) != GREEN &
      next(s1) != GREEN &
      next(s2) != GREEN &
      next(s3) != GREEN ;


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    
 


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
asm G next(movingAsms);


 
 





 
 
 
 
 
 
 

 

 

























/*
 * 
 * 
 * 
 * HANOI TASK
 * 
 * 
 * 
 */




env Color t0;
env Color t1;
env Color t2;



sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;


aux Color hanoiFromColor;
aux Color hanoiToColor;






predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar hanoiAssign(hanoiFrom, hanoiFromColor);
gar hanoiAssign(hanoiTo, hanoiToColor);

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));





    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (((hanoiFrom != 0) & (hanoiTo!=0)) -> ((next(t0) = t0))) &
    (((hanoiFrom != 1) & (hanoiTo!=1)) -> ((next(t1) = t1))) &
    (((hanoiFrom != 2) & (hanoiTo!=2)) -> ((next(t2) = t2))) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
      
  hanoiDone :=  
    (t0 = EMPTY) &
    (t2 = EMPTY);
  
  hanoiLegalMove :=
 
 
    hanoiFromColor != EMPTY &
    hanoiToColor > hanoiFromColor;
    
 
 
 
 
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->      
 
      hanoiNextFrom;


predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
predicate hanoiIncrementColor(Int (0..2) index):
  ((index = 0 & t0 != EMPTY) -> (next(t0) > t0) & (next(t0) != NOT)) &
  ((index = 1 & t1 != EMPTY) -> (next(t1) > t1) & (next(t1) != NOT)) &
  ((index = 2 & t2 != EMPTY) -> (next(t2) > t2) & (next(t2) != NOT)) ;

define
  hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0)) &
    (hanoiFrom = 1 -> nextColor(t1)) &
    (hanoiFrom = 2 -> nextColor(t2)) ;
  
define
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;

asm hanoiStrongAsms;
asm G task!=HANOI -> next(hanoiStrongAsms);

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G task = HANOI & !hanoiIsMoving -> hanoiSaveAll;

predicate notEqual(Color a, Color b):
  next(a = b -> a = EMPTY);
define
  noRepeats :=
    notEqual(t0, t1) &
    notEqual(t0, t2) &
    notEqual(t1, t2) &
 
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t0) -> t0 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t1) -> t1 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t2) -> t2 =EMPTY) ;
    
asm G task = HANOI -> noRepeats;

   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
  

asm hanoiAsms;
asm G next(hanoiAsms);



 
 
 
 
 

gar
G !hanoiIsMoving -> hanoiFrom = 0 & hanoiTo = 1;

gar
G task = SORT & !sortDone -> isMoving;

gar
G task = HANOI -> !isMoving;

gar
G task = HANOI & !hanoiDone -> hanoiIsMoving;
module z8

 
 
env Color s0;
env Color s1;
env Color s2;
env Color s3;

 
env Task task;


 
sys boolean isMoving;
 
sys Int(0..3) from;
sys Int(0..3) to;


 
aux Color fromColor;
aux Color toColor;



/*
 * EMPTY denotes an empty station (that does not contain a ball)
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
   
   
   
  
   
   
   
   
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..3) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) ;

gar assign(from, fromColor);
gar assign(to, toColor);

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));




 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  
asm saveOnStaying:
  G task != SCAN & task != HANOI & !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN & task != HANOI) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF (task = SORT & sortAsms) -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;

  
define
   
   /*
    * These assumptions are needed as in the general case the generated automaton
    * requires more heap memory than the standard heap memory in Eclipse.
    * So, we need to focus on special cases.
    * 
    */
 
   
   
  sortAsms :=
    somethingEmpty & firstStationsExist;
     


/*
 * The stations are ordered such that the non-existing stations are to the end
 * 
 * This is needed as otherwise, sorting were not possible,
 * as sorting never moves non-existing stations, and in sorted array,
 * the non-existing ones should be to the end
 * 
 * This is implemented in the following way:
 * if something does not exist,
 * then its successor must also not exist,
 * and so does its successor, and so forth.
 *  
 */

define 
  firstStationsExist :=
    ((s0 = NOT) -> (s1 = NOT)) &
    ((s1 = NOT) -> (s2 = NOT)) &
    ((s2 = NOT) -> (s3 = NOT)) ;
    
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  
  
  
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
   
    (( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0)) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS & gatherRedsAsms) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

  gatherRedsAsms :=
    somethingEmpty & firstStationsExist;
    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




define
   extraAssumptions :=true;
 
 
 
 
 
 



predicate isColor(Color color):
  color = RED | color = GREEN | color = BLUE;
 
  
define
  strongAssumptions :=
 
 
 
    s0 = EMPTY &
    isColor(s1) &
    isColor(s2) &
    isColor(s3) ;

  
 
 
 
 
 


asm strongAssumptions;  
asm G task = SCAN | task = HANOI -> next(strongAssumptions);




 
 
asm G next(s0) != GREEN &
      next(s1) != GREEN &
      next(s2) != GREEN &
      next(s3) != GREEN ;


define

 
 
 

  
 
 
 
 
    
    
    
  nextTask :=
    (task = SCAN              -> next(task) = SORT) &
    (task = SORT              -> next(task) = EXCHANGE) &
    (task = EXCHANGE          -> next(task) = SWAP_RED_AND_BLUE) &
    (task = SWAP_RED_AND_BLUE -> next(task) = MOVE_RED_LEFT) &
    (task = MOVE_RED_LEFT     -> next(task) = GATHER_REDS) &
    (task = GATHER_REDS       -> next(task) = HANOI) &
    (task = HANOI             -> next(task) = SCAN);



    
 


define
  someColorExists :=
    s0 = RED | s0 = GREEN | s0 = BLUE |
    s1 = RED | s1 = GREEN | s1 = BLUE | 
    s2 = RED | s2 = GREEN | s2 = BLUE |
    s3 = RED | s3 = GREEN | s3 = BLUE ;
    
  movingAsms :=
    colorExists(EMPTY) & 
    someColorExists;
    

    
asm movingAsms;
asm G next(movingAsms);


 
 





 
 
 
 
 
 
 

 

 

























/*
 * 
 * 
 * 
 * HANOI TASK
 * 
 * 
 * 
 */




env Color t0;
env Color t1;
env Color t2;



sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;


aux Color hanoiFromColor;
aux Color hanoiToColor;






predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar hanoiAssign(hanoiFrom, hanoiFromColor);
gar hanoiAssign(hanoiTo, hanoiToColor);

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));





    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (((hanoiFrom != 0) & (hanoiTo!=0)) -> ((next(t0) = t0))) &
    (((hanoiFrom != 1) & (hanoiTo!=1)) -> ((next(t1) = t1))) &
    (((hanoiFrom != 2) & (hanoiTo!=2)) -> ((next(t2) = t2))) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
      
  hanoiDone :=  
    (t0 = EMPTY) &
    (t2 = EMPTY);
  
  hanoiLegalMove :=
 
 
    hanoiFromColor != EMPTY &
    hanoiToColor > hanoiFromColor;
    
 
 
 
 
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->      
 
      hanoiNextFrom;


predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
predicate hanoiIncrementColor(Int (0..2) index):
  ((index = 0 & t0 != EMPTY) -> (next(t0) > t0) & (next(t0) != NOT)) &
  ((index = 1 & t1 != EMPTY) -> (next(t1) > t1) & (next(t1) != NOT)) &
  ((index = 2 & t2 != EMPTY) -> (next(t2) > t2) & (next(t2) != NOT)) ;

define
  hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0)) &
    (hanoiFrom = 1 -> nextColor(t1)) &
    (hanoiFrom = 2 -> nextColor(t2)) ;
  
define
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;

asm hanoiStrongAsms;
asm G task!=HANOI -> next(hanoiStrongAsms);

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G task = HANOI & !hanoiIsMoving -> hanoiSaveAll;

predicate notEqual(Color a, Color b):
  next(a = b -> a = EMPTY);
define
  noRepeats :=
    notEqual(t0, t1) &
    notEqual(t0, t2) &
    notEqual(t1, t2) &
 
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t0) -> t0 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t1) -> t1 =EMPTY) &
    (hanoiIsMoving & hanoiSetColor(hanoiFrom, t2) -> t2 =EMPTY) ;
    
asm G task = HANOI -> noRepeats;

   
predicate nextColor(Color color):
  next(color) = EMPTY |
  (
  (color = RED   -> next(color) = GREEN) &
  (color = GREEN -> next(color) = BLUE) &
  (color = BLUE  -> next(color) = EMPTY) &
  (color = EMPTY -> next(color) = EMPTY) );
  

asm hanoiAsms;
asm G next(hanoiAsms);



gar
G !hanoiIsMoving -> hanoiFrom = 0 & hanoiTo = 1;

 
 

gar
G task = HANOI -> !isMoving;

 
 
module z14

 
 
env Color s0;
env Color s1;
env Color s2;
env Color s3;

 
env Task task;


 
sys boolean isMoving;
 
sys Int(0..3) from;
sys Int(0..3) to;


 
aux Color fromColor;
aux Color toColor;



/*
 * EMPTY denotes an empty station (that does not contain a ball)
 * NOT denotes a not exists station. For example, if there're only 4 stations, then the stations[4] = NOT, and stations[5] = NOT
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};

/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * NOTHING means that the robot stands and does not move, and just does nothing
 * 
 * Notice that MOVE essentially swaps between 'from' and 'to',
 * as after MOVE 'from' points to the empty place that previously was in the place 'to' points to,
 * and 'to' points to the ball that previously was in the place pointed to by 'from'
 */
 



type Task = {
  SCAN,
  SORT,  
  EXCHANGE,  
  
  SWAP_RED_AND_BLUE,
  MOVE_RED_LEFT,
  GATHER_REDS,
  
   
  HANOI
  
};



gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate assign(Int(0..3) index, Color colorIndex):
  ((index = 0) -> colorIndex = s0) &
  ((index = 1) -> colorIndex = s1) &
  ((index = 2) -> colorIndex = s2) &
  ((index = 3) -> colorIndex = s3) ;

gar assign(from, fromColor);
gar assign(to, toColor);

gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));




 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  
asm saveOnStaying:
  G task != SCAN & task != HANOI & !isMoving -> saveAll;

 
 


gar
  from != to;
gar
  G next(from) != next(to);


asm saveOnMoving:
  G (isMoving & task != SCAN & task != HANOI) -> (onExchangeSave & swap);
  

define
    
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

  
   
   
   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
    

 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;




/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 */

asm startWithScan:
  task = SCAN;

/*
 * 
 *  
 * 
 * 
 */


asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
gar
  GF task = SORT -> sortDone;

gar
  G task = SORT & sortDone -> !isMoving;

      
   
   
 
 
predicate allEqual(Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;

  


define 
     
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);

      
        
   
 

 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY, or from=to
   * 
   */
   
  
  incrementFrom :=
   
    (( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0)) ;



/*
 * 
 * 
 *  
 * 
 * 
 */


asm continueGatherUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;


gar
  GF (task = GATHER_REDS) -> gatherRedsDone;

gar
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  


define
   
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

    
/*
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 * 
 * 
 */
 

asm continueMoveRedUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;
   
gar
  GF (task = MOVE_RED_LEFT & moveRedLeftAsms) -> moveRedLeftDone;

gar
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     

predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  
  
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    moveRedLeftAsms :=
      true;
    
      
      

      
/*
 * 
 * 
 * 
 * 
 * 
 *  
 * 
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  
     
/*
 * 
 * 
 * 
 * EXTRA ASSUMPTIONS
 * 
 * 
 * 
 */




  




define
    
  movingAsms :=
    colorExists(EMPTY) & 
    !colorExists(NOT);
   
    
asm movingAsms;
asm G next(movingAsms);


 
 





 
 
 
 
 
 
 

 

 

























/*
 * 
 * 
 * 
 * HANOI TASK
 * 
 * 
 * 
 */




env Color t0;
env Color t1;
env Color t2;



sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;


aux Color hanoiFromColor;
aux Color hanoiToColor;






predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

gar hanoiAssign(hanoiFrom, hanoiFromColor);
gar hanoiAssign(hanoiTo, hanoiToColor);

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));





    


asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
gar
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

gar
  G task = HANOI & hanoiDone ->
  
 
 
 
  !hanoiIsMoving;     


asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
  
gar
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

gar
  G hanoiIsMoving -> task = HANOI;
  
  
define

  hanoiOnExchangeSave :=
   
    (hanoiFrom != 0 & hanoiTo!=0 -> next(t0) = t0) &
    (hanoiFrom != 1 & hanoiTo!=1 -> next(t1) = t1) &
    (hanoiFrom != 2 & hanoiTo!=2 -> next(t2) = t2) ;


  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
      
  hanoiDone :=  
    
 
 
 
        
    (t0 = EMPTY) &
    (t1 = EMPTY);
  
  hanoiLegalMove :=
    hanoiFromColor != EMPTY &
    hanoiToColor >= hanoiFromColor;
    
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) -> 
      hanoiNextFrom;


predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;

 
 
 
 
 
 

define
  hanoiNextFrom :=
    
 
 
 
  
    (hanoiFrom = 0 -> nextColor(t0, r0)) &
    (hanoiFrom = 1 -> nextColor(t1, r1)) &
    (hanoiFrom = 2 -> nextColor(t2, r2)) ;
  
define
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;


aux Int(0..3) r0;
aux Int(0..3) r1;
aux Int(0..3) r2;

define
  initRs:=
    r0 = 3 &
    r1 = 0 &
    r2 = 0 ;
  
gar G
  task = HANOI & hanoiIsMoving ->
  (
  (hanoiFrom = 0 -> next(r0) = r0 - 1) &
  (hanoiFrom = 1 -> next(r1) = r1 - 1) &
  (hanoiFrom = 2 -> next(r2) = r2 - 1)
  &
  (hanoiTo   = 0 -> next(r0) = r0 + 1) &
  (hanoiTo   = 1 -> next(r1) = r1 + 1) &
  (hanoiTo   = 2 -> next(r2) = r2 + 1)
   
  & 
  
  (hanoiFrom != 0 & hanoiTo != 0 -> next(r0) = r0) &
  (hanoiFrom != 1 & hanoiTo != 1 -> next(r1) = r1) &
  (hanoiFrom != 2 & hanoiTo != 2 -> next(r2) = r2) 
  );

gar G
  task = HANOI & !hanoiIsMoving ->
    next(r0) = r0 &
    next(r1) = r1 &
    next(r2) = r2 ;

asm G
task = HANOI & hanoiIsMoving ->
  (
  (r0 = 1 & hanoiFrom = 0 -> next(t0) = EMPTY) &
  (r1 = 1 & hanoiFrom = 1 -> next(t1) = EMPTY) &
  (r2 = 1 & hanoiFrom = 2 -> next(t2) = EMPTY) 
  );

 
 
 
 
 
 
 
 



   
asm hanoiStrongAsms;
 
asm G task != HANOI & next(task) = HANOI -> next(hanoiStrongAsms);

gar G task != HANOI -> next(initRs);

gar G next(hanoiFrom) != next(hanoiTo);

define
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

asm G task = HANOI & !hanoiIsMoving -> hanoiSaveAll;


   
   
  
  

predicate hanoiExists(Color color):
  t0 = color | 
  t1 = color |
  t2 = color;

predicate nextColor(Color color, Int(0..3) count):
 
  
  (count <= 1 -> next(color) = EMPTY) &
  
  (count > 1 ->
    (
      (!hanoiExists(RED)   & next(color) = RED  ) |
      (!hanoiExists(GREEN) & next(color) = GREEN) |
      (!hanoiExists(BLUE)  & next(color) = BLUE ) 
    )
  );


asm hanoiAsms;
asm G next(hanoiAsms);



gar
G !hanoiIsMoving -> hanoiFrom = 0 & hanoiTo = 1;

 
 

gar
G task = HANOI -> !isMoving;

 
 



 
 
 
 
 
module zz

/*
 * 
 * 
 *  
 * 
 * Here we have the basic declarations, definitions, assumptions, and guarantees that all tasks (but Hanoi task) rely on
 * 
 * 
 * 
 */


 
 
 
env Color s0;
env Color s1;
env Color s2;
env Color s3;

 
env Task task;


 
sys boolean isMoving;
 
sys Int(0..3) from;
sys Int(0..3) to;



/*
 * EMPTY denotes an empty station (that does not contain a ball)
 * 
 * NOT denotes a not exists station. For example, if there're only 3 stations, then the s3 = NOT.
 * For the sake of simplicity, there're assumptions in the code that the color NOT is never used.
 * So in order to use it, one needs to delete these assumptions first
 *
 *  
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};
 

 
type Task = {
  SCAN,  
  SORT,  
  EXCHANGE,  
  SWAP_RED_AND_BLUE,  
  MOVE_RED_LEFT,  
  GATHER_REDS, 
  HANOI  
};


 
aux Color fromColor;
aux Color toColor;


 
predicate assign(Int(0..3) index, Color color):
  ((index = 0) -> color = s0) &
  ((index = 1) -> color = s1) &
  ((index = 2) -> color = s2) &
  ((index = 3) -> color = s3) ;

 
gar assign(from, fromColor);
gar assign(to, toColor);

 
 
gar G next(assign(from, fromColor));
gar G next(assign(to, toColor));


 
gar
  from != to;
gar
  G next(from) != next(to);


 
gar moveRequirements:
  G (isMoving) -> (fromColor != NOT & toColor = EMPTY);


 
predicate setColor(Int(0..3) index, Color color):
  ((index = 0) -> next(s0)=color) &
  ((index = 1) -> next(s1)=color) &
  ((index = 2) -> next(s2)=color) &
  ((index = 3) -> next(s3)=color) ;
  

 
asm saveOnStaying:
  G task != SCAN & task != HANOI & !isMoving -> saveAll;

 
 
asm saveOnMoving:
  G (isMoving & task != SCAN & task != HANOI) -> (onExchangeSave & swap);
  

define
   
  saveAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
   
  onExchangeSave :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;

   
   
  swap :=
    setColor(from, toColor) & setColor(to, fromColor);
    
   
 
predicate colorExists(Color color):
  s0 = color |
  s1 = color |
  s2 = color |
  s3 = color ;

 
 
define  
  movingAsms :=
    colorExists(EMPTY) & 
    !colorExists(NOT);
   
    
asm movingAsms;
asm G next(movingAsms);

/*
 * 
 * 
 *  
 * 
 * Atomic action that is not defined in the Spectra, but in the Java, and can be used to
 * reassess colors in all stations 
 * 
 * 
 */

 
asm startWithScan:
  task = SCAN;

/*
 * 
 * 
 *  
 * 
 * Sorts all balls in all stations w.r.t the total ordering: RED < GREEN < BLUE < EMPTY < NOT
 * 
 * 
 */

 
asm continueSortUntilDone:
  G (task = SORT & !sortDone) -> next(task) = SORT; 
  
 
gar eventuallySortDone:
  GF task = SORT -> sortDone;

 
gar stopMovingOnceSortDone:
  G task = SORT & sortDone -> !isMoving;

  


define 
     
    
    
   sortDone :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;


/*
 * 
 * 
 *  
 * 
 * Unsorts the balls (in a clever way that avoids just moving one ball back and forth)
 *  
 * 
 * 
 */
 
 
 
 
gar
  G task = EXCHANGE -> (isMoving & incrementFrom);



 
predicate exists(Int(0..3) index):
  
  ((index = 0) -> (s0 != NOT)) &
  ((index = 1) -> (s1 != NOT)) &
  ((index = 2) -> (s2 != NOT)) &
  ((index = 3) -> (s3 != NOT)) ;
 
 define 
 
 /*
   * We iterate over all existing values of 'from' in a cyclic manner
   * 
   * Notice that when !exists(from+1), then also !exists(from+2), etc.,
   * so we we're in the last existing value
   * 
   * Notice also that we also may pass through from=EMPTY
   * 
   */
   
  incrementFrom :=
    (( ((from != 3) & exists(from+1)) -> next(from) = from+1) &
    (!((from != 3) & exists(from+1)) -> next(from) = 0)) ;



/*
 * 
 * 
 *  
 * 
 * Gathers all red balls in adjacent stations.
 * 
 * 
 */

 
asm continueGatherRedsUntilDone:
  G (task = GATHER_REDS & !gatherRedsDone) -> next(task) = GATHER_REDS;

 
gar eventuallyGatherRedsDone:
  GF (task = GATHER_REDS) -> gatherRedsDone;

 
gar stopMovingOnceGatherRedsDone:
  G (task = GATHER_REDS & gatherRedsDone) -> !isMoving;
  

 
define
  gatherRedsDone :=
    ((s3 = RED) -> (s2 = RED)) &
    ((s2 = RED) -> (s1 = RED)) &
    ((s1 = RED) -> (s0 = RED)) ;

    
/*
 * 
 *  
 *  
 * 
 * Moves as many red balls to their left as possible.
 * This task is done once every red ball has no empty place to its left.
 * Of course, if no red ball exists, the task considered (vacantly) completed, and the robot does not move 
 * 
 */
 
 
asm continueMoveRedLeftUntilDone:
  G (task = MOVE_RED_LEFT & !moveRedLeftDone) -> next(task) = MOVE_RED_LEFT;

 
gar eventuallyMoveRedLeftDone:
  GF (task = MOVE_RED_LEFT) -> moveRedLeftDone;

 
gar stopMovingOnceMoveRedLeftDone:
  G (task = MOVE_RED_LEFT & moveRedLeftDone) -> !isMoving;
     
 
gar moveLegality:
  G task = MOVE_RED_LEFT & isMoving -> fromColor = RED;


 
predicate prevBallsNotEmpty(Int(0..5) index):
  ((index >= 1) -> (s0 != EMPTY)) &
  ((index >= 2) -> (s1 != EMPTY)) &
  ((index >= 3) -> (s2 != EMPTY)) &
  ((index >= 4) -> (s3 != EMPTY)) ;
  

 
define
    moveRedLeftDone :=
      ((s0 = RED) -> prevBallsNotEmpty(0)) &
      ((s1 = RED) -> prevBallsNotEmpty(1)) &
      ((s2 = RED) -> prevBallsNotEmpty(2)) &
      ((s3 = RED) -> prevBallsNotEmpty(3)) ;
    
    
      
      

      
/*
 * 
 * 
 *  
 * 
 * Swapping 'fromColor' from red to blue and vice versa,
 * and thereby, swapping the red and the blue again and again.
 * 
 * 
 */
 
 
gar
  G (swapRedAndBlueAsms & task = SWAP_RED_AND_BLUE) ->
      isMoving &
      ((fromColor = RED -> next(fromColor) = BLUE) &
      (fromColor = BLUE -> next(fromColor) = RED));

  
  
define
  swapRedAndBlueAsms :=
    colorExists(BLUE) &
    colorExists(RED); 
  


/*
 * 
 * 
 *  
 * 
 * Solving the n=3 case (3 disks) of the famous Hanoi Tower riddle.
 * 
 * Looking at the figures in our PowerPoint representation is highly recommended to better
 * understand how do these towers look like in the reality. 
 * 
 * Notice that many variables, defines, asms, gars, etc. already appeared above
 * with minor differences: isMoving -> hanoiIsMoving, s -> t, from -> hanoiFrom, to -> hanoiTo, etc.
 * To emphasize it, we have the prefix 'hanoi' in their names (like 'hanoiFrom')
 * Shahar & Or told us to have these variables, defines, etc. duplicated rather than giving them different interpretation in Hanoi task  
 *    
 * 
 */



 
 
env Color t0;
env Color t1;
env Color t2;


 
 
sys boolean hanoiIsMoving;
sys Int(0..2) hanoiFrom;
sys Int(0..2) hanoiTo;

 
aux Color hanoiFromColor;
aux Color hanoiToColor;


 
predicate hanoiAssign(Int(0..2) index, Color colorIndex):
  ((index = 0) -> colorIndex = t0) &
  ((index = 1) -> colorIndex = t1) &
  ((index = 2) -> colorIndex = t2) ;

 
gar hanoiAssign(hanoiFrom, hanoiFromColor);
gar hanoiAssign(hanoiTo, hanoiToColor);

gar G next(hanoiAssign(hanoiFrom, hanoiFromColor));
gar G next(hanoiAssign(hanoiTo, hanoiToColor));


gar G next(hanoiFrom) != next(hanoiTo);






 
asm continueHanoiUntilDone:
  G (task = HANOI & !hanoiDone) -> next(task) = HANOI;
    
 
gar eventuallyHanoiDone:
  GF (task = HANOI & hanoiAsms) -> hanoiDone;

 
gar stopMovingOnceHanoiDone:
  G task = HANOI & hanoiDone -> !hanoiIsMoving;     


 
gar hanoiMoveLegality:
  G task = HANOI & hanoiIsMoving -> hanoiLegalMove;
  

 
gar hanoiIsMovingImpliesHanoi:
  G hanoiIsMoving -> task = HANOI;
  
  
define
   
  hanoiAsms :=
    t0 != NOT &
    t1 != NOT &
    t2 != NOT ;
    
   
  hanoiDone := 
    (t0 = EMPTY) &
    (t1 = EMPTY);
  
   
  hanoiLegalMove :=
    hanoiFromColor != EMPTY &
    hanoiToColor >= hanoiFromColor;
    
   
  hanoiOnExchangeSave :=
    (hanoiFrom != 0 & hanoiTo!=0 -> next(t0) = t0) &
    (hanoiFrom != 1 & hanoiTo!=1 -> next(t1) = t1) &
    (hanoiFrom != 2 & hanoiTo!=2 -> next(t2) = t2) ;
  
   
  hanoiSaveAll :=
    (next(t0) = t0) &
    (next(t1) = t1) &
    (next(t2) = t2) ;

 
asm
  G task = HANOI & !hanoiIsMoving -> hanoiSaveAll;
    
asm
  G hanoiIsMoving & task = HANOI -> hanoiOnExchangeSave;
    
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) ->
      hanoiSetColor(hanoiTo, hanoiFromColor) ;
asm
  G (task = HANOI & hanoiIsMoving & hanoiAsms & hanoiLegalMove) -> 
      hanoiNextFrom;

 
predicate hanoiSetColor(Int(0..2) index, Color color):
  ((index = 0) -> next(t0)=color) &
  ((index = 1) -> next(t1)=color) &
  ((index = 2) -> next(t2)=color) ;


define
  hanoiNextFrom :=
    (hanoiFrom = 0 -> nextColor(t0, r0)) &
    (hanoiFrom = 1 -> nextColor(t1, r1)) &
    (hanoiFrom = 2 -> nextColor(t2, r2)) ;
  

 
aux Int(0..3) r0;
aux Int(0..3) r1;
aux Int(0..3) r2;

 
define
  initCounters:=
    r0 = 3 &
    r1 = 0 &
    r2 = 0 ;

 
gar counterBehavior: 
  G 
    task = HANOI & hanoiIsMoving ->
    (
       
      (hanoiFrom = 0 -> next(r0) = r0 - 1) &
      (hanoiFrom = 1 -> next(r1) = r1 - 1) &
      (hanoiFrom = 2 -> next(r2) = r2 - 1)
      &
       
      (hanoiTo   = 0 -> next(r0) = r0 + 1) &
      (hanoiTo   = 1 -> next(r1) = r1 + 1) &
      (hanoiTo   = 2 -> next(r2) = r2 + 1)
       
      & 
       
      (hanoiFrom != 0 & hanoiTo != 0 -> next(r0) = r0) &
      (hanoiFrom != 1 & hanoiTo != 1 -> next(r1) = r1) &
      (hanoiFrom != 2 & hanoiTo != 2 -> next(r2) = r2) 
    );

 
gar saveCounters:
  G
  task = HANOI & !hanoiIsMoving ->
    next(r0) = r0 &
    next(r1) = r1 &
    next(r2) = r2 ;


 
 
 
asm zeroCounterImpliesEmpty: 
G
task = HANOI & hanoiIsMoving ->
  (
  (r0 = 1 & hanoiFrom = 0 -> next(t0) = EMPTY) &
  (r1 = 1 & hanoiFrom = 1 -> next(t1) = EMPTY) &
  (r2 = 1 & hanoiFrom = 2 -> next(t2) = EMPTY) 
  );

 
gar G task != HANOI -> next(initCounters);




     
  
 
predicate hanoiExists(Color color):
  t0 = color | 
  t1 = color |
  t2 = color;

 
 
predicate nextColor(Color color, Int(0..3) count):

   
  (count <= 1 -> next(color) = EMPTY) &
  
   
   
  (count > 1 ->
    (
      (!hanoiExists(RED)   & next(color) = RED  ) |  
      (!hanoiExists(GREEN) & next(color) = GREEN) |
      (!hanoiExists(BLUE)  & next(color) = BLUE ) 
    )
  );

 
asm hanoiAsms;
asm G next(hanoiAsms);

define
   
   
  hanoiStrongAsms :=
    t0 = RED &
    t1 = EMPTY &
    t2 = EMPTY;

 
asm hanoiStrongAsms;
asm G task != HANOI & next(task) = HANOI -> next(hanoiStrongAsms);


 
gar hanoiFirstOptimization:
  G !hanoiIsMoving -> hanoiFrom = 0 & hanoiTo = 1;

 
gar hanoiSecondOptimization:
  G task = HANOI -> !isMoving;
module k

env Color s1;
env Color s2;
env Color s3;
env Color s4;

env Color[4] stations;
env boolean legal;
env boolean emgoff;

sys Mode mode;
sys Int(0..3) from;
sys Int(0..3) to;

asm
  stations[0]=s1;
asm
  stations[1]=s2;
asm
  stations[2]=s3;
asm
  stations[3]=s4;





/*
 * EMPTY denotes an empty station
 * NOT_EXISTS denotes a not exists station
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};
/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * During WAITING mode, the robot waits until 'working' becomes false
 */
 
type Mode = {MOVE, STOP, INIT};

asm
  legal=true;
  
asm
  G legal = true;
  
asm
  legal=true;
  
asm
  G emgoff = false;

asm
  emgoff = false;

gar mode = INIT;

aux boolean initDone;
gar !initDone;
 
gar G next(initDone) = (mode = INIT | initDone);

gar G initDone -> mode != INIT;


aux boolean secondStep;
gar !secondStep;
gar G next(secondStep) = (mode = INIT);


 
 

 
 

gar
  GF sortingAssumptions -> sorted;
 
  

 
 
 
  
gar G (sorted & mode != INIT) -> mode = STOP;


 


gar
  G (mode = MOVE) -> (fromExists & toExists & toIsEmpty);

  
  
 

 
asm keepOnMove:
  G (mode = MOVE) -> (onExchangeKeep & swap);

asm keepOnNothing:
  G (mode = STOP) -> keepAll;










/*
 * some defines
 * 
 */
 
 define
  
  keepAll :=
    (next(stations[0]) = stations[0]) &
    (next(stations[1]) = stations[1]) &
    (next(stations[2]) = stations[2]) &
    (next(stations[3]) = stations[3]) ;
    
 onExchangeKeep :=
   
    (((from != 0) & (to!=0)) -> ((next(stations[0]) = stations[0]))) &
    (((from != 1) & (to!=1)) -> ((next(stations[1]) = stations[1]))) &
    (((from != 2) & (to!=2)) -> ((next(stations[2]) = stations[2]))) &
    (((from != 3) & (to!=3)) -> ((next(stations[3]) = stations[3]))) ;
  
  
predicate swapAux(Int(0..3) from, Int(0..3) fromVal, Color fromColor, Int(0..3) to, Color[4] toStations):
  
  (((from = fromVal) & (to = 0)) <-> (next(fromColor) = stations[0] & next(stations[0]) = fromColor)) &
  (((from = fromVal) & (to = 1)) <-> (next(fromColor) = stations[1] & next(stations[1]) = fromColor)) &
  (((from = fromVal) & (to = 2)) <-> (next(fromColor) = stations[2] & next(stations[2]) = fromColor)) &
  (((from = fromVal) & (to = 3)) <-> (next(fromColor) = stations[3] & next(stations[3]) = fromColor)) ;

 
define
  swap :=
    swapAux(from, 0, stations[0], to, stations) &
    swapAux(from, 1, stations[1], to, stations) &
    swapAux(from, 2, stations[2], to, stations) &
    swapAux(from, 3, stations[3], to, stations) ;

/*
 * The stations are ordered such that the non-existing stations are to the end 
 */
firstStationsExist :=
  ((stations[0] = NOT) -> (stations[1] = NOT)) &
  ((stations[1] = NOT) -> (stations[2] = NOT)) &
  ((stations[2] = NOT) -> (stations[3] = NOT)) ;
    
 
 somethingEmpty := 
 
    (stations[0] = EMPTY) |
    (stations[1] = EMPTY) |
    (stations[2] = EMPTY) |
    (stations[3] = EMPTY) ;
  
  toIsEmpty :=
    !somethingEmpty |
    ((stations[0] = EMPTY) & (to = 0)) |
    ((stations[1] = EMPTY) & (to = 1)) |
    ((stations[2] = EMPTY) & (to = 2)) |
    ((stations[3] = EMPTY) & (to = 3)) ;
  
  
   sorted :=
      (stations[0] <= stations[1]) &
      (stations[1] <= stations[2]) &
      (stations[2] <= stations[3]) ;
      
   fromExists :=
      exists(stations, from);
   toExists :=
      exists(stations, to);
   
   somethingExists :=
      (stations[0] != NOT) |
      (stations[1] != NOT) |
      (stations[2] != NOT) |
      (stations[3] != NOT) ;
      
  sortingAssumptions :=
     firstStationsExist & somethingExists & !equal;
         
   equal :=
      allEqual(stations,RED) |
      allEqual(stations,GREEN) |
      allEqual(stations,BLUE) ;


predicate allEqual(Color[4] stations, Color color):
  ((stations[0] = color) | (stations[0] = EMPTY) | (stations[0] = NOT)) &
  ((stations[1] = color) | (stations[1] = EMPTY) | (stations[1] = NOT)) &
  ((stations[2] = color) | (stations[2] = EMPTY) | (stations[2] = NOT)) &
  ((stations[3] = color) | (stations[3] = EMPTY) | (stations[3] = NOT)) ;
  
predicate exists(Color[4] stations, Int(0..3) index):
  (index = 0 & stations[0] != NOT) |
  (index = 1 & stations[1] != NOT) |
  (index = 2 & stations[2] != NOT) |
  (index = 3 & stations[3] != NOT) ;
  
      
/*
 * some tests
 * 
 */
 
define
  blueArray :=
    (stations[0] = BLUE) &
    (stations[1] = BLUE) &
    (stations[2] = BLUE) &
    (stations[3] = BLUE) ;
 
 
 
 
 
 
 
 
 

 
 
 

 
 

 
 
module Robot

env Color s1;
env Color s2;
env Color s3;
env Color s4;

env Color[4] stations;
env boolean legal;
env boolean emgoff;

sys Mode mode;
sys Int(0..3) from;
sys Int(0..3) to;

asm
  stations[0]=s1;
asm
  stations[1]=s2;
asm
  stations[2]=s3;
asm
  stations[3]=s4;


asm
  G secondStep->(stations[0]=s1);
asm
  G secondStep->(stations[1]=s2);
asm
  G secondStep->(stations[2]=s3);
asm
  G secondStep->(stations[3]=s4);





/*
 * EMPTY denotes an empty station
 * NOT_EXISTS denotes a not exists station
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};
/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * During WAITING mode, the robot waits until 'working' becomes false
 */
 
type Mode = {MOVE, STOP, INIT};

asm
  legal=true;
  
asm
  G legal = true;

  
asm
  G emgoff = false;

asm
  emgoff = false;

gar mode = INIT;

aux boolean initDone;
gar !initDone;
 
gar G next(initDone) = (mode = INIT | initDone);

gar G initDone -> mode != INIT;


aux boolean secondStep;
gar !secondStep;
gar G next(secondStep) = (mode = INIT);


 
 

 
 

gar
  GF sortingAssumptions -> sorted;
 
  

 
 
 
  
gar G (sorted & mode != INIT) -> mode = STOP;


 


gar
  G (mode = MOVE) -> (fromExists & toExists & toIsEmpty);

  
  
 

 
asm keepOnMove:
  G (mode = MOVE) -> (onExchangeKeep & swap);

asm keepOnNothing:
  G (mode = STOP) -> keepAll;

/*
 * some defines
 * 
 */
 
 define
  
  keepAll :=
    (next(stations[0]) = stations[0]) &
    (next(stations[1]) = stations[1]) &
    (next(stations[2]) = stations[2]) &
    (next(stations[3]) = stations[3]) ;
    
 onExchangeKeep :=
   
    (((from != 0) & (to!=0)) -> ((next(stations[0]) = stations[0]))) &
    (((from != 1) & (to!=1)) -> ((next(stations[1]) = stations[1]))) &
    (((from != 2) & (to!=2)) -> ((next(stations[2]) = stations[2]))) &
    (((from != 3) & (to!=3)) -> ((next(stations[3]) = stations[3]))) ;
  
  
predicate swapAux(Int(0..3) from, Int(0..3) fromVal, Color fromColor, Int(0..3) to, Color[4] toStations):
  
  (((from = fromVal) & (to = 0)) -> (next(fromColor) = stations[0] & next(stations[0]) = fromColor)) &
  (((from = fromVal) & (to = 1)) -> (next(fromColor) = stations[1] & next(stations[1]) = fromColor)) &
  (((from = fromVal) & (to = 2)) -> (next(fromColor) = stations[2] & next(stations[2]) = fromColor)) &
  (((from = fromVal) & (to = 3)) -> (next(fromColor) = stations[3] & next(stations[3]) = fromColor)) ;

 
define
  swap :=
    swapAux(from, 0, stations[0], to, stations) &
    swapAux(from, 1, stations[1], to, stations) &
    swapAux(from, 2, stations[2], to, stations) &
    swapAux(from, 3, stations[3], to, stations) ;

/*
 * The stations are ordered such that the non-existing stations are to the end 
 */
firstStationsExist :=
  ((stations[0] = NOT) -> (stations[1] = NOT)) &
  ((stations[1] = NOT) -> (stations[2] = NOT)) &
  ((stations[2] = NOT) -> (stations[3] = NOT)) ;
    
 
 somethingEmpty := 
 
    (stations[0] = EMPTY) |
    (stations[1] = EMPTY) |
    (stations[2] = EMPTY) |
    (stations[3] = EMPTY) ;
  
  toIsEmpty :=
    !somethingEmpty |
    ((stations[0] = EMPTY) & (to = 0)) |
    ((stations[1] = EMPTY) & (to = 1)) |
    ((stations[2] = EMPTY) & (to = 2)) |
    ((stations[3] = EMPTY) & (to = 3)) ;
  
  
   sorted :=
      (stations[0] <= stations[1]) &
      (stations[1] <= stations[2]) &
      (stations[2] <= stations[3]) ;
      
   fromExists :=
      exists(stations, from);
   toExists :=
      exists(stations, to);
   
   somethingExists :=
      (stations[0] != NOT) |
      (stations[1] != NOT) |
      (stations[2] != NOT) |
      (stations[3] != NOT) ;
      
  sortingAssumptions :=
     firstStationsExist & somethingExists & !equal;
         
   equal :=
      allEqual(stations,RED) |
      allEqual(stations,GREEN) |
      allEqual(stations,BLUE) ;


predicate allEqual(Color[4] stations, Color color):
  ((stations[0] = color) | (stations[0] = EMPTY) | (stations[0] = NOT)) &
  ((stations[1] = color) | (stations[1] = EMPTY) | (stations[1] = NOT)) &
  ((stations[2] = color) | (stations[2] = EMPTY) | (stations[2] = NOT)) &
  ((stations[3] = color) | (stations[3] = EMPTY) | (stations[3] = NOT)) ;
  
predicate exists(Color[4] stations, Int(0..3) index):
  (index = 0 & stations[0] != NOT) |
  (index = 1 & stations[1] != NOT) |
  (index = 2 & stations[2] != NOT) |
  (index = 3 & stations[3] != NOT) ;
  
      
/*
 * some tests
 * 
 */
 
define
  blueArray :=
    (stations[0] = BLUE) &
    (stations[1] = BLUE) &
    (stations[2] = BLUE) &
    (stations[3] = BLUE) ;
 
 
 
 
 
 
 
 
 

 
 
 

 
 

 
 
module Robot


env Color s0;
env Color s1;
env Color s2;
env Color s3;


env boolean legal;
env boolean emgoff;




asm 
  legal=true;
asm
  G legal=true;
  
asm 
  emgoff=false;
asm
  G emgoff=false;



sys Mode mode;
sys Int(0..5) from;
sys Int(0..5) to;


/*
 * EMPTY denotes an empty station
 * NOT_EXISTS denotes a not exists station
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};
/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * During WAITING mode, the robot waits until 'working' becomes false
 */
 
type Mode = {MOVE, NOTHING, INIT};


gar mode = INIT;

aux boolean initDone;
gar !initDone;
 
gar G next(initDone) = (mode = INIT | initDone);

gar G initDone -> mode != INIT;


aux boolean secondStep;
gar !secondStep;
gar G next(secondStep) = (mode = INIT);


 
 

 
asm sortingAssumptions;

gar
  GF sorted;
 
  

 
 
 
  
gar G (sorted & mode != INIT) -> mode = NOTHING;

 

 


gar
  G (mode = MOVE) -> (fromExists & toExists & toIsEmpty);

  
  
 

 
asm keepOnMove:
  G (mode = MOVE) -> (onExchangeKeep & swap);

asm keepOnNothing:
  G (mode = NOTHING | mode = INIT) -> keepAll;





/*
 * some defines
 * 
 */
 
 define
  
  keepAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
 onExchangeKeep :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;
  
  
predicate swapAux(Int(0..5) from, Int(0..5) fromVal, Color fromColor, Int(0..5) to, Color s0, Color s1, Color s2, Color s3):
  
  (((from = fromVal) & (to = 0)) -> (next(fromColor) = s0 & next(s0) = fromColor)) &
  (((from = fromVal) & (to = 1)) -> (next(fromColor) = s1 & next(s1) = fromColor)) &
  (((from = fromVal) & (to = 2)) -> (next(fromColor) = s2 & next(s2) = fromColor)) &
  (((from = fromVal) & (to = 3)) -> (next(fromColor) = s3 & next(s3) = fromColor)) ;

 
define
  swap :=
    swapAux(from, 0, s0, to, s0, s1, s2, s3) &
    swapAux(from, 1, s1, to, s0, s1, s2, s3) &
    swapAux(from, 2, s2, to, s0, s1, s2, s3) &
    swapAux(from, 3, s3, to, s0, s1, s2, s3) ;

/*
 * The stations are ordered such that the non-existing stations are to the end 
 */
firstStationsExist :=
  ((s0 = NOT) -> (s1 = NOT)) &
  ((s1 = NOT) -> (s2 = NOT)) &
  ((s2 = NOT) -> (s3 = NOT)) ;
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  toIsEmpty :=
    !somethingEmpty |
    ((s0 = EMPTY) & (to = 0)) |
    ((s1 = EMPTY) & (to = 1)) |
    ((s2 = EMPTY) & (to = 2)) |
    ((s3 = EMPTY) & (to = 3)) ;
  
  
   sorted :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;
      
   fromExists :=
      exists(s0, s1, s2, s3, from);
   toExists :=
      exists(s0, s1, s2, s3, to);
   
   somethingExists :=
      (s0 != NOT) |
      (s1 != NOT) |
      (s2 != NOT) |
      (s3 != NOT) ;
      
  sortingAssumptions :=
      extraAssumptions & firstStationsExist & somethingExists & !equal;
         
   equal :=
      allEqual(s0, s1, s2, s3,RED) |
      allEqual(s0, s1, s2, s3,GREEN) |
      allEqual(s0, s1, s2, s3,BLUE) ;
   
   extraAssumptions :=
     
    (s3 = EMPTY) &
    (s2 != EMPTY ) &
    (s1 != EMPTY) &
    (s0 != EMPTY);


predicate allEqual(Color s0, Color s1, Color s2, Color s3 , Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;
  
predicate exists(Color s0, Color s1, Color s2, Color s3, Int(0..5) index):
  (index = 0 & s0 != NOT) |
  (index = 1 & s1 != NOT) |
  (index = 2 & s2 != NOT) |
  (index = 3 & s3 != NOT) ;
  
      
/*
 * some tests
 * 
 */
 
define
  blueArray :=
    (s0 = BLUE) &
    (s1 = BLUE) &
    (s2 = BLUE) &
    (s3 = BLUE) ;
  
  assumedArray :=
    
    (s0 = BLUE) &
    (s1 = GREEN) &
    (s2 = RED) &
    (s3 = EMPTY) ;

 
 
 

 
 

 
 
module Robot


env Color s0;
env Color s1;
env Color s2;
env Color s3;


env boolean legal;
env boolean emgoff;




asm 
  legal=true;
asm
  G legal=true;
  
asm 
  emgoff=false;
asm
  G emgoff=false;



sys Mode mode;
sys Int(0..5) from;
sys Int(0..5) to;


/*
 * EMPTY denotes an empty station
 * NOT_EXISTS denotes a not exists station
 * 
 */
type Color = {RED, GREEN, BLUE, EMPTY, NOT};
/*
 * During the INIT mode, the robot scans the stations, and checks how many stations there're, and what are their balls' colors
 * MOVE moves the ball from 'from' to 'to', assuming 'to' is an empty station
 * During WAITING mode, the robot waits until 'working' becomes false
 */
 
type Mode = {MOVE, NOTHING, INIT};


gar mode = INIT;

aux boolean initDone;
gar !initDone;
 
gar G next(initDone) = (mode = INIT | initDone);

gar G initDone -> mode != INIT;


aux boolean secondStep;
gar !secondStep;
gar G next(secondStep) = (mode = INIT);


 
 

 
asm sortingAssumptions;

gar
  GF sorted;
 
  

 
 
 
  
gar G (sorted & mode != INIT) -> mode = NOTHING;

 

 


gar
  G (mode = MOVE) -> (fromExists & toExists & toIsEmpty);

  
  
 

 
asm keepOnMove:
  G (mode = MOVE) -> (onExchangeKeep & swap);

asm keepOnNothing:
  G (mode = NOTHING | mode = INIT) -> keepAll;





/*
 * some defines
 * 
 */
 
 define
  
  keepAll :=
    (next(s0) = s0) &
    (next(s1) = s1) &
    (next(s2) = s2) &
    (next(s3) = s3) ;
    
 onExchangeKeep :=
   
    (((from != 0) & (to!=0)) -> ((next(s0) = s0))) &
    (((from != 1) & (to!=1)) -> ((next(s1) = s1))) &
    (((from != 2) & (to!=2)) -> ((next(s2) = s2))) &
    (((from != 3) & (to!=3)) -> ((next(s3) = s3))) ;
  
  
predicate swapAux(Int(0..5) from, Int(0..5) fromVal, Color fromColor, Int(0..5) to, Color s0, Color s1, Color s2, Color s3):
  
  (((from = fromVal) & (to = 0)) -> (next(fromColor) = s0 & next(s0) = fromColor)) &
  (((from = fromVal) & (to = 1)) -> (next(fromColor) = s1 & next(s1) = fromColor)) &
  (((from = fromVal) & (to = 2)) -> (next(fromColor) = s2 & next(s2) = fromColor)) &
  (((from = fromVal) & (to = 3)) -> (next(fromColor) = s3 & next(s3) = fromColor)) ;

 
define
  swap :=
    swapAux(from, 0, s0, to, s0, s1, s2, s3) &
    swapAux(from, 1, s1, to, s0, s1, s2, s3) &
    swapAux(from, 2, s2, to, s0, s1, s2, s3) &
    swapAux(from, 3, s3, to, s0, s1, s2, s3) ;

/*
 * The stations are ordered such that the non-existing stations are to the end 
 */
firstStationsExist :=
  ((s0 = NOT) -> (s1 = NOT)) &
  ((s1 = NOT) -> (s2 = NOT)) &
  ((s2 = NOT) -> (s3 = NOT)) ;
    
 
 somethingEmpty := 
 
    (s0 = EMPTY) |
    (s1 = EMPTY) |
    (s2 = EMPTY) |
    (s3 = EMPTY) ;
  
  toIsEmpty :=
    !somethingEmpty |
    ((s0 = EMPTY) & (to = 0)) |
    ((s1 = EMPTY) & (to = 1)) |
    ((s2 = EMPTY) & (to = 2)) |
    ((s3 = EMPTY) & (to = 3)) ;
  
  
   sorted :=
      (s0 <= s1) &
      (s1 <= s2) &
      (s2 <= s3) ;
      
   fromExists :=
      exists(s0, s1, s2, s3, from);
   toExists :=
      exists(s0, s1, s2, s3, to);
   
   somethingExists :=
      (s0 != NOT) |
      (s1 != NOT) |
      (s2 != NOT) |
      (s3 != NOT) ;
      
  sortingAssumptions :=
       firstStationsExist & somethingExists & !equal;
         
   equal :=
      allEqual(s0, s1, s2, s3,RED) |
      allEqual(s0, s1, s2, s3,GREEN) |
      allEqual(s0, s1, s2, s3,BLUE) ;
   


predicate allEqual(Color s0, Color s1, Color s2, Color s3 , Color color):
  ((s0 = color) | (s0 = EMPTY) | (s0 = NOT)) &
  ((s1 = color) | (s1 = EMPTY) | (s1 = NOT)) &
  ((s2 = color) | (s2 = EMPTY) | (s2 = NOT)) &
  ((s3 = color) | (s3 = EMPTY) | (s3 = NOT)) ;
  
predicate exists(Color s0, Color s1, Color s2, Color s3, Int(0..5) index):
  (index = 0 & s0 != NOT) |
  (index = 1 & s1 != NOT) |
  (index = 2 & s2 != NOT) |
  (index = 3 & s3 != NOT) ;
  
      
/*
 * some tests
 * 
 */
 
define
  blueArray :=
    (s0 = BLUE) &
    (s1 = BLUE) &
    (s2 = BLUE) &
    (s3 = BLUE) ;
  
  assumedArray :=
    
    (s0 = BLUE) &
    (s1 = GREEN) &
    (s2 = RED) &
    (s3 = EMPTY) ;

 
 
 

 
 

 
 
import "../patterns/DwyerPatterns.spectra"

module Elevator

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 
  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds10                           :=   secondsState_c=3;
  seconds20                           :=   secondsState_c=4;
  onlyDownCalls                       :=   (floor1&(memCall0)&!(memCall1|memCall2|memCall3))|
                                           (floor2&(memCall0|memCall1)&!(memCall2|memCall3));                                        
  onlyUpCalls                         :=   (floor1&(memCall2|memCall3)&!(memCall0|memCall1))|
                                           (floor2&(memCall3)&!(memCall0|memCall1|memCall2)); 
  atEmergencyFloor                    :=   (atFloor&(memEmergency|emergency_c));
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened,doorsAreClosed))|
                                           (sabbathMode & !sabbath_c & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateSabbathMode                 :=   (!sabbathMode & sabbath_c & !emergency_c & !memEmergency);
  deActivateSabbathMode               :=   (sabbathMode  & (sabbath_c|emergency_c|memEmergency));
  


monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}


monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}


monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}


monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened,boolean doorsAreClosed):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G ((!doorsAreClosed))->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor/*&!atSabbathFloor&(!doorsAreClosed)*/)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

gar dontGoUpWhenOnlyCallsFromDown:
  G (onlyDownCalls&PREV(stayInPlace))->(goingDown|atEmergencyFloor);

gar dontGoDownWhenOnlyCallsFromUp:
  G (onlyUpCalls&PREV(stayInPlace))->(goingUp|atEmergencyFloor);


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    
 
 


gar AtDesignatedFloorInSabbathModeHoldTheDoorsFullyOpenedFor10Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3|seconds5)&!memEmergency&sabbathMode&PREV(keepDoorsState))->(keepDoorsState);


 

gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);




 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
   
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   
  
/*
weight pnaltyFloor0: -1
  memCall0&next(memCall0);

weight pnaltyFloor1: -1
  memCall1&next(memCall1);

weight pnaltyFloor2: -1
  memCall2&next(memCall2);

weight pnaltyFloor3: -1
  memCall3&next(memCall3);

   

weight rewardFloor0: 1
  memCall0&next(!memCall0);

weight rewardFloor1: 2
  memCall1&next(!memCall1);

weight rewardFloor2: 3
  memCall2&next(!memCall2);

weight rewardFloor3: 4
  memCall3&next(!memCall3);
  
*/

 
import "../patterns/DwyerPatterns.spectra"

module Elevator

 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};


 
 
env boolean calls0_c;
env boolean calls1_c;
env boolean calls2_c;
env boolean calls3_c;
env boolean emergency_c;
env boolean sabbath_c;
 
 
 
env Int(0..4) secondsState_c; 
 
 
env Int(0..6) floor_c;
env Int(0..2) doors_c;


 
sys LiftMotorCmd liftM_c;
sys DoorsMotorCmd doorsM_c;
sys boolean sound_c;
sys boolean countTime_c;


 
type DoorsMotorCmd= {CLOSE, STOP,OPEN};
type LiftMotorCmd= {UP, STOP,DOWN};



 

define 
  goingUp                             :=   (liftM_c = UP);
  goingDown                           :=   (liftM_c = DOWN);
  stayInPlace                         :=   (liftM_c=STOP);
  openingDoors                        :=   (doorsM_c = OPEN);
  closingDoors                        :=   (doorsM_c = CLOSE);
  keepDoorsState                      :=   (doorsM_c = STOP);
  doorsAreClosed                      :=   (doors_c = 0);
  doorsAreOpened                      :=   (doors_c = 1);
  doorsAreFullyOpened                 :=   (doors_c = 2);  
  floor0                              :=   (floor_c=0);
  floor1                              :=   (floor_c=2);
  floor2                              :=   (floor_c=4);
  floor3                              :=   (floor_c=6);
  atFloor                             :=   (floor0|floor1|floor2|floor3); 
  anyCalls                            :=   (calls0_c | calls1_c | calls2_c | calls3_c);
  anyMemCalls                         :=   (memCall0 | memCall1 | memCall2 | memCall3);
  atDesignatedFloor                   :=   (floor0 & memCall0) | (floor1 & memCall1)  | (floor2 & memCall2) | (floor3 & memCall3);
  firstStateAtDesignatedFloor         :=   atDesignatedFloor&doorsAreClosed&!doorsWereFullyOpened&stayInPlace;
  fullyOpenedStateAtDesignatedFloor   :=   atDesignatedFloor&doorsAreFullyOpened;
  lastStateAtDesignatedFloor          :=   atDesignatedFloor&doorsAreClosed&doorsWereFullyOpened;
  noSeconds                           :=   secondsState_c=0;
  seconds3                            :=   secondsState_c=1;
  seconds5                            :=   secondsState_c=2;
  seconds10                           :=   secondsState_c=3;
  seconds20                           :=   secondsState_c=4;
  onlyDownCalls                       :=   (floor1&(memCall0)&!(memCall1|memCall2|memCall3))|
                                           (floor2&(memCall0|memCall1)&!(memCall2|memCall3));                                        
  onlyUpCalls                         :=   (floor1&(memCall2|memCall3)&!(memCall0|memCall1))|
                                           (floor2&(memCall3)&!(memCall0|memCall1|memCall2)); 
  atEmergencyFloor                    :=   (atFloor&(memEmergency|emergency_c));
  fullyOpenedStateAtEmergencyFloor    :=   (atEmergencyFloor&doorsAreFullyOpened);
  activateMemCall0                    :=   (!sabbathMode&activateMemCall(memCall0,calls0_c,floor0,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall0 & !emergency_c & !memEmergency & (floor3|(floor1&!memCall3)));                                     
  deActivateMemCall0                  :=   (deActivateMemCall(memCall0,floor0,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall1                    :=   (!sabbathMode&activateMemCall(memCall1,calls1_c,floor1,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall1 & !emergency_c & !memEmergency & (floor0|floor3));                                       
  deActivateMemCall1                  :=   (deActivateMemCall(memCall1,floor1,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall2                    :=   (!sabbathMode&activateMemCall(memCall2,calls2_c,floor2,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall2 & !emergency_c & !memEmergency & (floor0|floor3));                                        
  deActivateMemCall2                  :=   (deActivateMemCall(memCall2,floor2,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateMemCall3                    :=   (!sabbathMode&activateMemCall(memCall3,calls3_c,floor3,memEmergency,doorsWereFullyOpened))|
                                           (sabbathMode & !sabbath_c & !memCall3 & !emergency_c & !memEmergency & (floor0|(floor2&!memCall0)));                                          
  deActivateMemCall3                  :=   (deActivateMemCall(memCall3,floor3,doorsWereFullyOpened,doorsAreClosed,fullyOpenedStateAtEmergencyFloor));
  activateSabbathMode                 :=   (!sabbathMode & sabbath_c & !emergency_c & !memEmergency);
  deActivateSabbathMode               :=   (sabbathMode  & (sabbath_c|emergency_c|memEmergency));
  


monitor boolean returnTo0
{  
  !returnTo0;
  G (!floor0 & !emergency_c & !memEmergency & ((!anyCalls&!anyMemCalls&seconds20&doorsAreClosed&!sabbathMode) | returnTo0))<->next (returnTo0); 
}


monitor boolean doorsWereFullyOpened
{
  !doorsWereFullyOpened;
  G (doorsAreFullyOpened->next(doorsWereFullyOpened));
  G ((doorsAreClosed|(doorsAreOpened&emergency_c))->next(!doorsWereFullyOpened));
  G ((doorsAreOpened&!emergency_c)->(next(doorsWereFullyOpened)=doorsWereFullyOpened));
}


monitor boolean memEmergency
{
  !memEmergency;
  G (emergency_c & !memEmergency) -> next (memEmergency);
  G (atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed) -> next (!memEmergency);
  G (!(emergency_c & !memEmergency) & !(atFloor&memEmergency&doorsWereFullyOpened&doorsAreClosed)) -> (next(memEmergency) = memEmergency);
}


monitor boolean sabbathMode
{
  !sabbathMode;
  G (activateSabbathMode)->next(sabbathMode);
  G (deActivateSabbathMode)->next(!sabbathMode);
  G (!activateSabbathMode&!deActivateSabbathMode)->(next(sabbathMode)=sabbathMode);
}


monitor boolean memCall0
{
  !memCall0;
  G (activateMemCall0)->next(memCall0);
  G (deActivateMemCall0)->next(!memCall0);
  G (!(activateMemCall0)&!deActivateMemCall0) ->  (next(memCall0) = memCall0);
}


monitor boolean memCall1
{
  !memCall1;
  G (activateMemCall1)->next(memCall1);
  G (deActivateMemCall1)->next(!memCall1);
  G (!activateMemCall1&!deActivateMemCall1) ->  (next(memCall1) = memCall1);
}

monitor boolean memCall2
{
  !memCall2;
  G (activateMemCall2)->next(memCall2);
  G (deActivateMemCall2)->next(!memCall2);
  G (!activateMemCall2&!deActivateMemCall2) ->  (next(memCall2) = memCall2);
}

monitor boolean memCall3
{
  !memCall3;
  G (activateMemCall3)->next(memCall3);
  G (deActivateMemCall3)->next(!memCall3);
  G (!activateMemCall3&!deActivateMemCall3) ->  (next(memCall3) = memCall3);
}


predicate activateMemCall(boolean memCall,boolean call_c,boolean floor,boolean memEmergency,
  boolean doorsWereFullyOpened):
    (call_c & !memCall & !emergency_c & (!memEmergency|(doorsWereFullyOpened&!floor)));
  
predicate deActivateMemCall(boolean memCall,boolean floor,
  boolean doorsWereFullyOpened,boolean doorsAreClosed,boolean fullyOpenedStateAtEmergencyFloor):
    (memCall & ((floor & doorsWereFullyOpened & doorsAreClosed)|fullyOpenedStateAtEmergencyFloor));



 
gar init_motors:
  (stayInPlace) & (keepDoorsState);


 
asm startFromFloor0:
  floor0;
  
asm startWithClosedDoors:
  doorsAreClosed;

asm timerHasNotBeenActivatedPriorStart: 
  noSeconds;


 
gar noSoundInTheBeginning:
  !sound_c;

gar soundIsOnWhenMoving: 
  G !stayInPlace -> next(sound_c);

gar soundIsOffWhenNotMoving:
  G (stayInPlace) -> (next(!sound_c));
  
  
 
gar ifFloor0DontGoDown:
  G (floor0 -> (!goingDown));

gar ifFloor3DontGoUp:
  G (floor3 -> (!goingUp));

gar ifDoorsAreClosedDontClose:
  G (doorsAreClosed -> (!closingDoors));

gar ifDoorsAreFullyOpenedDontOpen:
  G (doorsAreFullyOpened->(!openingDoors));
  
  
 
  
gar dontChangeDirectionWithoutStopping:
  G (goingUp -> next (!goingDown)) & (goingDown -> next (!goingUp));  
  
gar dontStopGoingUpWithoutAReason:
  G goingUp->next(goingUp|atDesignatedFloor|floor3|atEmergencyFloor);
  
gar dontStopGoingDownWithoutAReason:
  G goingDown->next(goingDown|atDesignatedFloor|floor0|atEmergencyFloor);

gar dontMoveWithoutAReason:
  G ((!anyMemCalls & !returnTo0 & !memEmergency) | (returnTo0 & floor0)) -> stayInPlace;

 

 
gar dontMoveDoorsWhileMoving:
  G (!stayInPlace->keepDoorsState);

gar doorsAreClosedWhileMoving:
  G ((!doorsAreClosed))->(stayInPlace);

gar dontMoveDoorsWithoutAReason:
  G (!atDesignatedFloor&!atEmergencyFloor/*&!atSabbathFloor&(!doorsAreClosed)*/)->keepDoorsState;

 
gar dontStopOpenningDoorsWithoutAReason:
 G openingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreFullyOpened)->openingDoors);
  
gar dontStopClosingDoorsWithoutAReason:
 G closingDoors->next((stayInPlace&(atDesignatedFloor|atEmergencyFloor)&!doorsAreClosed)->(closingDoors|emergency_c));
  
gar byDefaultCloseTheDoors:
 GF(doorsAreClosed|(atEmergencyFloor&!doorsWereFullyOpened));

  
 

asm keepingTheStateOfTheDoors:
  G (keepDoorsState)->(next(doors_c)=doors_c);

asm moveDoorsOnlyOneStepAtATime:
  G((doors_c=next(doors_c))|(doors_c+1=next(doors_c))|(doors_c-1=next(doors_c)));
  
asm openingDoorsWontDecDoors:
  G openingDoors->((doors_c=next(doors_c))|(doors_c+1=next(doors_c)));

asm closingDoorsWontIntDoors:
  G closingDoors->((doors_c=next(doors_c))|(doors_c-1=next(doors_c)));
 
asm openingDoorsWithoutStoppingCauseIncDoors:
  pRespondsToS(openingDoors&!doorsAreFullyOpened,(next(doors_c)=doors_c+1)|!openingDoors);
  
asm closingDoorsWithoutStoppingCauseDecDoors:
  pRespondsToS(closingDoors&!doorsAreClosed,(next(doors_c)=doors_c-1)|!closingDoors);
  

asm floorChangeCannotHappenWithoutMoving: 
  G (stayInPlace)->(next(floor_c)=floor_c);
    
asm moveOnlyOneFloorAtATime:
  G((floor_c=next(floor_c))|(floor_c+1=next(floor_c))|(floor_c-1=next(floor_c)));
 
asm goingUpWontDecFloor:
  G goingUp->((floor_c=next(floor_c))|(floor_c+1=next(floor_c)));

asm goingDownWontIncFloor:
  G goingDown->((floor_c=next(floor_c))|(floor_c-1=next(floor_c)));
  

       
asm goingUpWithoutStoppingCauseIncFloor:
  pRespondsToS(goingUp&!floor3,(next(floor_c)=floor_c+1)|!goingUp);
  
  
asm goingDownWithoutStoppingCauseDecFloor:
  pRespondsToS(goingDown&!floor0,(next(floor_c)=floor_c-1)|!goingDown);
  




 
    
gar startCountTime:
  G ((!(emergency_c|memEmergency))&(!(!stayInPlace|anyCalls|anyMemCalls|floor0|returnTo0) | 
                      firstStateAtDesignatedFloor&(!returnTo0) | fullyOpenedStateAtDesignatedFloor))->(countTime_c);
  
gar stopCountTime:
  G ((emergency_c|memEmergency)|(returnTo0)|(!atDesignatedFloor&(floor0|anyCalls|anyMemCalls))|
                      (!stayInPlace)|(lastStateAtDesignatedFloor)|(doorsAreOpened))->(!countTime_c);

asm envDoesntCountSecondsWhenNotRequired:
  G (!countTime_c) -> next(noSeconds);

asm countOnlyOneUnitAtATime:
  G (countTime_c)->((next(secondsState_c)=secondsState_c)|(next(secondsState_c)=secondsState_c+1));
  

asm takesSomeTimeToCount3SecondsFIXDELAY:
  G (PREV(!countTime_c))->next(noSeconds);

asm takesSomeTimeToCount5SecondsFIXDELAY:
  G (PREV(noSeconds))->next(!seconds5);

 
asm canCountSecondsWhenRequired:
    pRespondsToS(countTime_c&(!seconds20),next(secondsState_c)=secondsState_c+1|!countTime_c);

  

 

gar ifEnteredToDesignatedFloorDontMove:
  G (!atFloor&next(atDesignatedFloor)&(!returnTo0))->next(stayInPlace);

 
gar atDesignatedFloorAndNotMovingThenDontMove:
  G (atFloor&stayInPlace&next(atDesignatedFloor))->next(stayInPlace);

 
gar ifStartedToLeaveFloorKeepGoing:
  G (atFloor&!stayInPlace)->next(!stayInPlace|atEmergencyFloor);

gar dontGoUpWhenOnlyCallsFromDown:
  G (onlyDownCalls&PREV(stayInPlace))->(goingDown|atEmergencyFloor);

gar dontGoDownWhenOnlyCallsFromUp:
  G (onlyUpCalls&PREV(stayInPlace))->(goingUp|atEmergencyFloor);


gar AtDesignatedFloorDontOpenDoorsUntill3Seconds:
    G(firstStateAtDesignatedFloor&(noSeconds)&!atEmergencyFloor)->keepDoorsState;

    
gar AtDesignatedFloorHoldTheDoorsFullyOpenedFor5Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3)&!memEmergency&!sabbathMode)->keepDoorsState;
    
 
 


gar AtDesignatedFloorInSabbathModeHoldTheDoorsFullyOpenedFor10Seconds:
    G(fullyOpenedStateAtDesignatedFloor&(noSeconds|seconds3|seconds5)&!memEmergency&sabbathMode&PREV(keepDoorsState))->(keepDoorsState);


 

gar takeCareOfCallsFromFloor0:
  GF(!memCall0);

gar takeCareOfCallsFromFloor1:
  GF(!memCall1);
  
gar takeCareOfCallsFromFloor2:
  GF(!memCall2);
  
gar takeCareOfCallsFromFloor3:
  GF(!memCall3);




 

gar returnTo0WhenRequired:
  G (returnTo0&!floor0)->(goingDown|atEmergencyFloor);



 

asm noEmergencyInTheBeginning:
  !emergency_c;

gar atEmergencyFloorDontMove:
  G (atEmergencyFloor->stayInPlace);

gar AtEmergencyFloorOpenDoors:
   
  G (atEmergencyFloor&!doorsWereFullyOpened&!doorsAreFullyOpened&stayInPlace)->openingDoors;
 
 
 
asm noSabbathModeInTheBeginning:
  !sabbath_c;
   
  
/*
weight pnaltyFloor0: -1
  memCall0&next(memCall0);

weight pnaltyFloor1: -1
  memCall1&next(memCall1);

weight pnaltyFloor2: -1
  memCall2&next(memCall2);

weight pnaltyFloor3: -1
  memCall3&next(memCall3);

   

weight rewardFloor0: 1
  memCall0&next(!memCall0);

weight rewardFloor1: 2
  memCall1&next(!memCall1);

weight rewardFloor2: 3
  memCall2&next(!memCall2);

weight rewardFloor3: 4
  memCall3&next(!memCall3);
  
*/

 
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {NOEDGE, EDGE} atEdge ;
		
		env {ZERO, NOTZERO} num_of_cubes;
		
		env {PRESS, RELEASE} haltButton;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {RIGHT, LEFT, STOP, INITPOS} botMot ;
		
		sys boolean spec_allsleep ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {REDUCE, NOTREDUCE} reduce_num_of_cubes;
		
		sys { S0, S1, S2} spec_state ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys {WAIT, KICK, TOANGLERIGHT, TOANGLELEFT, DROP, FROMANGLE} spec_stage ;
		sys boolean spec_finished_cycle;
		
		sys boolean spec_speedButtonValidPressed ;
		sys boolean spec_haltButtonValidPressed ;
		
		sys {pause, go} spec_pausing ;

guarantee  
  spec_state=S0;

guarantee  
  G ((spec_state=S0 & ((!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(detect = spec_currentColor)) | ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP)) | (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor)) | (!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor))) & next(spec_state=S0)) |
  (spec_state=S0 & ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = spec_currentColor)) & next(spec_state=S1)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor)) & next(spec_state=S0)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = spec_currentColor)) & next(spec_state=S1)) |
  (spec_state=S1 & ((ack_ver_hor = MOVE & spec_stage = DROP)) & next(spec_state=S2)) |
  (spec_state=S2 & next(spec_state=S2)));

guarantee  
  GF (spec_state=S0|spec_state=S1);

guarantee
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_haltButtonValidPressed = true);

guarantee
	G ((spec_haltButtonValidPressed = true & spec_pausing = go) | (spec_haltButtonValidPressed = false & spec_pausing = pause)
		-> next(spec_pausing) = pause);
	
guarantee
	G ((spec_haltButtonValidPressed = false & spec_pausing = go) | (spec_haltButtonValidPressed = true & spec_pausing = pause)
		-> next(spec_pausing) = go);

guarantee  
  respondsTo(spec_haltButtonValidPressed=true&spec_pausing=go,(spec_haltButtonValidPressed=true));
	
guarantee  
	G (spec_pausing = pause | ack_ver_hor = MOVE -> 
		spec_allsleep = true & next(spec_stage) = spec_stage);
	
guarantee  
	G (spec_stage != WAIT -> next(spec_currentColor) = spec_currentColor);

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (spec_allsleep = true <-> verMot = SLEEP  & horMot = SLEEP & botMot = STOP);
	
guarantee  
	motSpeed = LEVEL1 & spec_stage = WAIT & spec_pausing = go;
	
 

 

guarantee  
	G ((color = BLACK | num_of_cubes = ZERO) & spec_stage = WAIT -> 
		spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (color != BLACK & num_of_cubes != ZERO & spec_stage = WAIT  & spec_pausing = go  ->
		verMot = MOVE  & color = next(spec_currentColor) & next(spec_stage) = KICK);

guarantee  
	G (ack_ver_hor = SLEEP & spec_stage = KICK  & spec_pausing = go  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

 
 
guarantee  
	G (atEdge != EDGE & spec_stage = TOANGLERIGHT & detect != spec_currentColor & spec_pausing = go  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

guarantee  
	G (atEdge = EDGE & spec_stage = TOANGLERIGHT & spec_pausing = go  & detect != spec_currentColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);
 
guarantee  
	G (spec_stage = TOANGLELEFT & spec_pausing = go  & detect != spec_currentColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);

guarantee  
	G ((spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & spec_pausing = go & detect = spec_currentColor ->
		verMot = SLEEP & horMot = MOVE & botMot = STOP & next(spec_stage) = DROP );

 
	 
guarantee  
	G (((ack_ver_hor = SLEEP & spec_stage = DROP) | ((ack_bot = MOVE | (ack_bot = SLEEP & PREV(spec_pausing = pause))) & spec_stage = FROMANGLE)) & spec_pausing = go ->
		botMot = INITPOS & next(spec_stage) = FROMANGLE);

guarantee
	G (spec_finished_cycle <-> ack_bot = SLEEP & PREV(spec_pausing = go) & spec_stage = FROMANGLE & spec_pausing = go);

guarantee  
	G (spec_finished_cycle -> spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (spec_finished_cycle <-> reduce_num_of_cubes = REDUCE);

 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed = true);


guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);

 

assumption  
  respondsTo(ack_ver_hor=MOVE,(ack_ver_hor=SLEEP));
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption
	G (spec_stage != KICK & spec_stage != DROP -> ack_ver_hor = SLEEP);
	
assumption  
  respondsTo(num_of_cubes!=ZERO,(num_of_cubes=ZERO));

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
module ColorSort
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} color ;
		env {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} detect ;
		env {MOVE, SLEEP} ack_ver_hor ;
		env {MOVE, SLEEP} ack_bot ;
		env {NOEDGE, EDGE} atEdge ;
		
		env {ZERO, NOTZERO} num_of_cubes;
		
		env {PRESS, RELEASE} haltButton;
		
		env {PRESS, RELEASE} speedButton;
		sys {MOVE, SLEEP} verMot ;
		sys {MOVE, SLEEP} horMot ;
		sys {RIGHT, LEFT, STOP, INITPOS} botMot ;
		
		sys boolean spec_allsleep ;
		
		sys {LEVEL1, LEVEL2, LEVEL3} motSpeed;
		
		sys {REDUCE, NOTREDUCE} reduce_num_of_cubes;
		
		sys { S0, S1, S2} spec_state ;
		
		sys {RED, GREEN, BLUE, BLACK, YELLOW , WHITE} spec_currentColor;
		sys {WAIT, KICK, TOANGLERIGHT, TOANGLELEFT, DROP, FROMANGLE} spec_stage ;
		sys boolean spec_finished_cycle;
		
		sys boolean spec_speedButtonValidPressed ;
		sys boolean spec_haltButtonValidPressed ;
		
		sys {pause, go} spec_pausing ;

guarantee  
  spec_state=S0;

guarantee  
  G ((spec_state=S0 & ((!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(detect = spec_currentColor)) | ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP)) | (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor)) | (!(ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & (ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor))) & next(spec_state=S0)) |
  (spec_state=S0 & ((ack_ver_hor = SLEEP & spec_stage = KICK & spec_pausing = go) & !(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = spec_currentColor)) & next(spec_state=S1)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & (detect = spec_currentColor)) & next(spec_state=S0)) |
  (spec_state=S1 & (!(ack_ver_hor = MOVE & spec_stage = DROP) & !(detect = spec_currentColor)) & next(spec_state=S1)) |
  (spec_state=S1 & ((ack_ver_hor = MOVE & spec_stage = DROP)) & next(spec_state=S2)) |
  (spec_state=S2 & next(spec_state=S2)));

guarantee  
  GF (spec_state=S0|spec_state=S1);

guarantee
	G (haltButton = PRESS & PREV(haltButton = RELEASE) <-> spec_haltButtonValidPressed = true);

guarantee
	G ((spec_haltButtonValidPressed = true & spec_pausing = go) | (spec_haltButtonValidPressed = false & spec_pausing = pause)
		-> next(spec_pausing) = pause);
	
guarantee
	G ((spec_haltButtonValidPressed = false & spec_pausing = go) | (spec_haltButtonValidPressed = true & spec_pausing = pause)
		-> next(spec_pausing) = go);

guarantee  
  respondsTo(spec_haltButtonValidPressed=true&spec_pausing=go,(spec_haltButtonValidPressed=true));
	
guarantee  
	G (spec_pausing = pause | ack_ver_hor = MOVE -> 
		spec_allsleep = true & next(spec_stage) = spec_stage);
	
guarantee  
	G (spec_stage != WAIT -> next(spec_currentColor) = spec_currentColor);

guarantee  
	G (verMot = MOVE -> (botMot = STOP & horMot = SLEEP));
	
guarantee 
	G (horMot = MOVE -> (botMot = STOP & verMot = SLEEP));
	
guarantee 
	G (botMot != STOP -> (verMot = SLEEP & horMot = SLEEP));
	
guarantee  
	G (spec_allsleep = true <-> verMot = SLEEP  & horMot = SLEEP & botMot = STOP);
	
guarantee  
	motSpeed = LEVEL1 & spec_stage = WAIT & spec_pausing = go;
	
 

 

guarantee  
	G ((color = BLACK | num_of_cubes = ZERO) & spec_stage = WAIT -> 
		spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (color != BLACK & num_of_cubes != ZERO & spec_stage = WAIT  & spec_pausing = go  ->
		verMot = MOVE  & color = next(spec_currentColor) & next(spec_stage) = KICK);

guarantee  
	G (ack_ver_hor = SLEEP & spec_stage = KICK  & spec_pausing = go  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

 
 
guarantee  
	G (atEdge != EDGE & spec_stage = TOANGLERIGHT & detect != spec_currentColor & spec_pausing = go  ->
		botMot = RIGHT & next(spec_stage) = TOANGLERIGHT);

guarantee  
	G (atEdge = EDGE & spec_stage = TOANGLERIGHT & spec_pausing = go  & detect != spec_currentColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);
 
guarantee  
	G (spec_stage = TOANGLELEFT & spec_pausing = go  & detect != spec_currentColor ->
		botMot = LEFT & next(spec_stage) = TOANGLELEFT);

guarantee  
	G ((spec_stage = TOANGLERIGHT | spec_stage = TOANGLELEFT) & spec_pausing = go & detect = spec_currentColor ->
		verMot = SLEEP & horMot = MOVE & botMot = STOP & next(spec_stage) = DROP );

 
	 
guarantee  
	G (((ack_ver_hor = SLEEP & spec_stage = DROP) | ((ack_bot = MOVE | (ack_bot = SLEEP & PREV(spec_pausing = pause))) & spec_stage = FROMANGLE)) & spec_pausing = go ->
		botMot = INITPOS & next(spec_stage) = FROMANGLE);

guarantee
	G (spec_finished_cycle <-> ack_bot = SLEEP & PREV(spec_pausing = go) & spec_stage = FROMANGLE & spec_pausing = go);

guarantee  
	G (spec_finished_cycle -> spec_allsleep = true & next(spec_stage) = WAIT);

guarantee  
	G (spec_finished_cycle <-> reduce_num_of_cubes = REDUCE);

 

guarantee
	G (speedButton = PRESS & PREV(speedButton = RELEASE) <-> spec_speedButtonValidPressed = true);


guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL3);
	
guarantee  
	G (spec_speedButtonValidPressed = true & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL1);
	 
	 
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL1) -> motSpeed = LEVEL1);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL2) -> motSpeed = LEVEL2);
	
guarantee  
	G (spec_speedButtonValidPressed = false & PREV(motSpeed = LEVEL3) -> motSpeed = LEVEL3);

 

assumption  
  respondsTo(ack_ver_hor=MOVE,(ack_ver_hor=SLEEP));
assumption
  respondsTo(ack_bot=MOVE,(ack_bot=SLEEP));

assumption
	G (spec_stage != KICK & spec_stage != DROP -> ack_ver_hor = SLEEP);
	
assumption  
  respondsTo(num_of_cubes!=ZERO,(num_of_cubes=ZERO));

assumption  
  GF (color!=BLACK);

pattern respondsTo(trigger, response) {
  var boolean responded;
  responded;
  G (next(responded) iff (response or responded and !trigger));
  GF (responded);
}
