mcrl2-201409.0/README000770 001750 001750 00000001036 12370120011 014203 0ustar00outisoutis000000 000000 This directory contains the mCRL2 toolset. See the file INSTALL for compilation and installation instructions. Report bugs at . Please include the version number from `mcrl22lps --version', and a complete, self-contained test case in each bug report. If you have questions about using the mCRL2 toolset which the documentation does not answer, send mail to . ----- Copyright (C) 2005-2013 Eindhoven University of Technology See the file COPYING for license information. mcrl2-201409.0/LICENSE_1_0.txt000770 001750 001750 00000002472 12370120011 015612 0ustar00outisoutis000000 000000 Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mcrl2-201409.0/postflight.sh.in000770 001750 001750 00000000627 12370120020 016454 0ustar00outisoutis000000 000000 #!/bin/bash # Create Alias for mCRL2-gui in root of installation directory #osascript -e "tell application \"System Events\" to display dialog {\"$2@CMAKE_INSTALL_PREFIX@\"}"; #<< Debug for testing installation path. osascript -e "tell application \"Finder\" to make alias file to POSIX file {\"$2@CMAKE_INSTALL_PREFIX@/Applications/mcrl2-gui.app\"} at POSIX file {\"$2@CMAKE_INSTALL_PREFIX@\"}"; exit 0 mcrl2-201409.0/INSTALL000770 001750 001750 00000000226 12370120030 014355 0ustar00outisoutis000000 000000 Installation Instructions ************************* For up-to-date compilation and installation instructions, please refer to http://www.mcrl2.org . mcrl2-201409.0/examples/project/abp/abp.mcrl2000770 001750 001750 00000001674 12370120075 021076 0ustar00outisoutis000000 000000 % This file contains the alternating bit protocol, as described in W.J. % Fokkink, J.F. Groote and M.A. Reniers, Modelling Reactive Systems. % % The only exception is that the domain D consists of two data elements to % facilitate simulation. sort D = struct d1 | d2; Error = struct e; act r1,s4: D; s2,r2,c2: D # Bool; s3,r3,c3: D # Bool; s3,r3,c3: Error; s5,r5,c5: Bool; s6,r6,c6: Bool; s6,r6,c6: Error; i; proc S(b:Bool) = sum d:D. r1(d).T(d,b); T(d:D,b:Bool) = s2(d,b).(r6(b).S(!b)+(r6(!b)+r6(e)).T(d,b)); R(b:Bool) = sum d:D. r3(d,b).s4(d).s5(b).R(!b)+ (sum d:D.r3(d,!b)+r3(e)).s5(!b).R(b); K = sum d:D,b:Bool. r2(d,b).(i.s3(d,b)+i.s3(e)).K; L = sum b:Bool. r5(b).(i.s6(b)+i.s6(e)).L; init hide({c2,c3,c5,c6,i}, allow({r1,s4,c2,c3,c5,c6,i}, comm({r2|s2->c2, r3|s3->c3, r5|s5->c5, r6|s6->c6}, S(true) || K || L || R(true) ) ) ); mcrl2-201409.0/examples/project/abp/abp.dgd000770 001750 001750 00000065447 12370120075 020625 0ustar00outisoutis000000 000000 abp.fsm -0.580176 0.225624 0.128928 0.096696 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 s30 0.160494 0.679012 0.0895062 0.697842 0.683453 0.366906 0.25 0.75 0 0 0.386784 0.225624 0.128928 0.096696 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 s33 0.16358 0.990741 0.67284 0.493827 0.827338 -0.582734 0.827338 0.798561 0.25 0.75 0 0 -0.096696 0.48348 0.225624 0.096696 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 s31 0.160494 0.666667 0.990741 0.311728 0.438849 0.410072 0.381295 -0.194245 0.25 0.75 0 0 -0.096696 -0.032232 0.225624 0.096696 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 s32 0.160494 0.675926 0.996914 0.29321 0.741007 0.71223 0.726619 0.165468 0.25 0.75 0 0 -0.386784 0.354552 0.064464 -0.096696 0 0 0 TYPE_ARROW 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.193392 0.354552 0.064464 0.096696 0 0 0 TYPE_ARROW 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.193392 0.096696 -0.064464 0.096696 0 0 0 TYPE_ARROW 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.386784 0.096696 -0.064464 -0.096696 0 0 0 TYPE_ARROW 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.064464 0.515712 0.064464 0.064464 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 b4 0.299383 0.993827 0.467626 0.467626 0.25 0.75 0 0 -0.064464 0.515712 0.064464 0.064464 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 d7 0.669753 0.166667 0.669065 -0.107914 0.25 0.75 0 0 -0.515712 0.257856 0.064464 0.064464 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 b 0.299383 0.993827 0.395683 0.338129 0.25 0.75 0 0 -0.64464 0.257856 0.064464 0.064464 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 d 0.67284 0.169753 0.568345 -0.00719424 0.25 0.75 0 0 0.451248 0.257856 0.064464 0.064464 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 b2 0.314815 0.996914 0.352518 0.352518 0.25 0.75 0 0 0.32232 0.257856 0.064464 0.064464 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0.000442391 0 0 0 0 0 0 0 0 d6 0.666667 0.169753 0.582734 -0.0791367 0.25 0.75 0 0 0.064464 0 0.064464 0.064464 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 b3 0.299383 0.990741 0.366906 0.280576 0.25 0.75 0 0 mcrl2-201409.0/examples/project/abp/abp.dgc000770 001750 001750 00000014175 12370120075 020614 0ustar00outisoutis000000 000000 abp.fsm s30 Pos 3 1 2 3 0 1 2 d D 2 d1 d2 0 1 b Bool 2 true false 0 1 s31 Pos 4 1 2 4 3 0 1 2 3 d7 D 2 d1 d2 0 1 b4 Bool 2 true false 0 1 s32 Pos 4 1 2 4 3 0 1 2 3 b3 Bool 2 true false 0 1 s33 Pos 4 1 4 2 3 0 1 2 3 d6 D 2 d1 d2 0 1 b2 Bool 2 true false 0 1 fan_in Nat 4 0 1 2 3 0 1 2 3 fan_out Nat 3 0 1 2 0 1 2 node_nr Unspecified 0 mcrl2-201409.0/examples/project/wafer_stepper/wafer_stepper.mcrl2000770 001750 001750 00000011007 12370120075 025275 0ustar00outisoutis000000 000000 map MaximumWafers: Nat; eqn MaximumWafers = 5; sort WaferState = struct fresh?is_fresh | measured?is_measured | exposed?is_exposed; sort Wafer = struct wafer(status : WaferState); map DummyWafer: Wafer; IsFresh,IsMeasured,IsExposed: Wafer -> Bool; MakeMeasured,MakeExposed: Wafer -> Wafer; var s : WaferState; w : Wafer; eqn IsFresh(wafer(s)) = is_fresh(s); IsMeasured(wafer(s)) = is_measured(s); IsExposed(wafer(s)) = is_exposed(s); MakeMeasured(wafer(s)) = wafer(measured); MakeExposed(wafer(s)) = wafer(exposed); sort WaferList = List (Wafer); map InitWaferList: Nat -> WaferList; var n : Nat; eqn InitWaferList(0) = []; 0 < n -> InitWaferList(n) = wafer(fresh) |> InitWaferList(max(n - 1,0)); sort LockID = struct L0 | L1 | L2 | L3; sort RobotID = struct R0 | R1; act ALLE_HENS_AAN_BOORD; Measure,Expose,Swap; Rotate : RobotID; T2L,L2T: Wafer#LockID; L2R,R2L: Wafer#LockID#RobotID; R2C,C2R: Wafer#RobotID; T2L_T,L2T_T,T2L_L,L2T_L: Wafer#LockID; L2R_L,R2L_L,L2R_R,R2L_R: Wafer#LockID#RobotID; R2C_R,C2R_R,R2C_C,C2R_C: Wafer#RobotID; proc % Tray process T(wl:WaferList,n:Nat) = (sum l:LockID. (wl != []) -> T2L_T(head(wl),l).T(tail(wl),n)) + (n == 0) -> ALLE_HENS_AAN_BOORD.T(wl,n) <> (sum w:Wafer, l:LockID. L2T_T(w,l).T(wl,max(n - 1,0))); % Lock process L(id:LockID,occupied:Bool,w:Wafer)= occupied -> (IsExposed(w) -> L2T_L(w, id) + IsFresh(w) -> L2R_L(w,id,if(id == L0 || id == L1,R0,R1)) ).L(id,false,DummyWafer) <> (sum x:Wafer.(T2L_L(x,id) + R2L_L(x,id,if(id == L0 || id == L1,R0,R1))).L(id,true,x)); % Robot process R(id:RobotID,occupiedA:Bool,wA:Wafer,occupiedB:Bool,wB:Wafer,reversed:Bool) = (sum w:Wafer, lid:LockID. (!if(reversed,occupiedB,occupiedA)) -> L2R_R(w,lid,id). R(id,if(reversed,occupiedA,true),if(reversed,wA,w), if(reversed,true,occupiedB),if(reversed,w,wB),reversed)) + (sum lid:LockID. (if(reversed,occupiedB && IsExposed(wB),occupiedA && IsExposed(wA))) -> R2L_R(if(reversed,wB,wA),lid,id). R(id,if(reversed,occupiedA,false),if(reversed,wA,DummyWafer), if(reversed,false,occupiedB),if(reversed,DummyWafer,wB),reversed)) + (if(reversed, ((occupiedA && IsExposed(wA)) && (!occupiedB || IsFresh(wB))) || ((occupiedB && IsFresh(wB)) && (!occupiedA)), ((occupiedB && IsExposed(wB)) && (!occupiedA || IsFresh(wA))) || ((occupiedA && IsFresh(wA)) && (!occupiedB)))) -> Rotate(id).R(id,occupiedA,wA,occupiedB,wB,!reversed) + (if(reversed,occupiedA && IsFresh(wA),occupiedB && IsFresh(wB))) -> R2C_R(if(reversed,wA,wB),id). R(id,if(reversed,false,occupiedA),if(reversed,DummyWafer,wA), if(reversed,occupiedB,false),if(reversed,wB,DummyWafer),reversed) + (sum w:Wafer. ((!if(reversed,occupiedA,occupiedB)) -> C2R_R(w,id). R(id,if(reversed,true,occupiedA),if(reversed,w,wA), if(reversed,occupiedB,true),if(reversed,wB,w),reversed))); % Wafer stages C(occupiedC0:Bool,w0:Wafer,occupiedC1:Bool,w1:Wafer) = (occupiedC0 && IsFresh(w0)) -> Measure.C(occupiedC0,MakeMeasured(w0),occupiedC1,w1) + (occupiedC1 && IsMeasured(w1)) -> Expose.C(occupiedC0,w0,occupiedC1,MakeExposed(w1)) + ((occupiedC0 && !occupiedC1 && IsMeasured(w0)) || (occupiedC1 && if(occupiedC0,IsMeasured(w0),true) && IsExposed(w1))) -> Swap.C(occupiedC1,w1,occupiedC0,w0) + (sum rid:RobotID. (occupiedC0 && IsExposed(w0)) -> C2R_C(w0,rid).C(false,DummyWafer,occupiedC1,w1)) + (sum w:Wafer, rid:RobotID. (!occupiedC0) -> R2C_C(w,rid).C(true,w,occupiedC1,w1)); init hide({Measure,Expose,Swap,Rotate}, allow({T2L,L2T,L2R,R2L,R2C,C2R,Measure,Expose,Rotate,Swap,ALLE_HENS_AAN_BOORD}, comm({T2L_T|T2L_L -> T2L, L2T_T|L2T_L -> L2T, L2R_L|L2R_R -> L2R, R2L_L|R2L_R -> R2L, R2C_R|R2C_C -> R2C, C2R_R|C2R_C -> C2R }, T(InitWaferList(MaximumWafers),MaximumWafers) || L(L0,false,DummyWafer) || L(L1,false,DummyWafer) || L(L2,false,DummyWafer) || L(L3,false,DummyWafer) || R(R0,false,DummyWafer,false,DummyWafer,false) || R(R1,false,DummyWafer,false,DummyWafer,false) || C(false,DummyWafer,false,DummyWafer) ) ) ); mcrl2-201409.0/examples/project/wafer_stepper/wafer_stepper.dgc000770 001750 001750 00000020465 12370120075 025023 0ustar00outisoutis000000 000000 WaferStepper.fsm fan_out Naturals 14 Deadlock No deadlock 0 1 1 1 1 1 1 1 1 1 1 1 1 1 fresh_wafer_list WaferList 7 [] [wafer(fresh)] [wafer(fresh), wafer(fresh)] [wafer(fresh), wafer(fresh), wafer(fresh)] [wafer(fresh), wafer(fresh), wafer(fresh), wafer(fresh)] [wafer(fresh), wafer(fresh), wafer(fresh), wafer(fresh), wafer(fresh)] [wafer(fresh), wafer(fresh), wafer(fresh), wafer(fresh), wafer(fresh), wafer(fresh)] 6 5 4 3 2 1 0 wafers_in_system Nat 7 0 1 2 3 4 5 6 6 5 4 3 2 1 0 lock_1 Wafer 3 empty fresh processed 0 1 2 lock_2 Wafer 3 empty fresh processed 0 1 2 lock_3 Wafer 3 empty fresh processed 0 1 2 lock_4 Wafer 3 empty fresh processed 0 1 2 robot_1_arm_a Wafer 3 empty fresh processed 0 1 2 robot_1_arm_b Wafer 3 empty fresh processed 0 1 2 robot_2_arm_a Wafer 3 empty fresh processed 0 1 2 robot_2_arm_b Wafer 3 empty fresh processed 0 1 2 prep_stage Wafer 4 empty fresh prepared processed 0 1 2 3 proc_stage Wafer 3 empty prepared processed 0 1 2 fan_in Unspecified 0 node_nr Unspecified 0 mcrl2-201409.0/examples/project/wafer_stepper/wafer_stepper.dgd000770 001750 001750 00000222662 12370120075 025027 0ustar00outisoutis000000 000000 WaferStepper.fsm -0.67401 0.256766 0.22467 0.320957 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.770297 0.44934 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 fresh_wafer_list 0.309524 0.309524 -0.0153846 0.4 fresh_wafer_list 0.00340137 0.993197 0.979592 0.982993 0.982993 0.97619 0.979592 0 -0.923077 -0.446154 -0.138462 0.123077 0.369231 0.707692 -0.320957 0.641914 0.0962871 0.0962871 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.320957 0.385149 0.0962871 0.0962871 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.320957 -0.128383 0.0962871 0.0962871 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.0641914 0.513531 0.128383 0.128383 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.128383 0.513531 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.320957 0.513531 0.128383 0.128383 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.0641914 0 0.128383 0.128383 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.320957 0 0.128383 0.128383 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.128383 0 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.513531 0.256766 0.128383 0.128383 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 0.770297 0.256766 0.128383 0.128383 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.320957 0.641914 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 lock_1 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 lock_1 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 -0.320957 0.385149 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 lock_2 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 lock_2 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 -0.320957 0.128383 0.0962871 0.0962871 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.320957 0.128383 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 lock_3 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 lock_3 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 -0.320957 -0.128383 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 lock_4 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 lock_4 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 -0.0641914 0.513531 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 robot_1_arm_a 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 robot_1_arm_a 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 0.320957 0.513531 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 robot_1_arm_b 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 robot_1_arm_b 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 -0.0641914 0 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 robot_2_arm_a 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 robot_2_arm_a 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 0.320957 0 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 robot_2_arm_b 0.309524 0.312925 0.102041 0.492308 -0.523077 0.0307692 robot_2_arm_b 0.00340137 0.989796 0.986395 0 -0.461538 0.492308 0.513531 0.256766 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 prep_stage 0.309524 0.309524 0.163265 0.105442 0.492308 0.138462 0.138462 0.492308 prep_stage 0.00340137 0.989796 0.989796 0.986395 0 -0.461538 -0.0615385 0.430769 0.770297 0.256766 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 proc_stage 0.309524 0.163265 0.105442 0.492308 0.138462 0.492308 proc_stage 0.00340137 0.989796 0.986395 0 -0.461538 0.430769 -0.577723 0.44934 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 fresh_wafer_list 0.309524 0.309524 -0.0153846 0.4 fresh_wafer_list 0.00340137 0.00340137 0.979592 0.982993 0.982993 0.97619 0.979592 0 -0.384615 -0.446154 -0.138462 0.123077 0.369231 0.707692 -0.770297 0.256766 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 fresh_wafer_list 0.309524 0.309524 -0.0153846 0.4 fresh_wafer_list 0.00340137 0.00340137 0.00340137 0.982993 0.982993 0.97619 0.979592 0 -0.384615 -0.8 -0.138462 0.123077 0.369231 0.707692 -0.577723 0.256766 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 fresh_wafer_list 0.309524 0.309524 -0.0153846 0.4 fresh_wafer_list 0.00340137 0.00680273 0.00340137 8.71145e-009 0.982993 0.97619 0.979592 0.923077 0.661538 0.415385 -0.153846 0.123077 0.369231 0.707692 -0.770297 0.0641914 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 fresh_wafer_list 0.309524 0.309524 -0.0153846 0.4 fresh_wafer_list 0.00340137 0.00680273 0.00340137 8.71145e-009 8.71145e-009 0.97619 0.979592 0.923077 0.661538 0.415385 -0.153846 -0.523077 0.369231 0.707692 -0.577723 0.0641914 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 fresh_wafer_list 0.309524 0.309524 -0.0153846 0.4 fresh_wafer_list 0.00340137 0.00680273 0.00340137 8.71145e-009 8.71145e-009 0.00680273 0.979592 0.923077 0.661538 0.415385 -0.153846 -0.523077 -0.861538 0.707692 0.22467 -0.577723 0.609818 0.128383 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0.25 0.75 0 0 0.25 0.75 0 0 -0.256766 -0.577723 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.309524 0.309524 -0.0153846 0.4 wafers_in_system 0.00340137 0.993197 0.979592 0.982993 0.982993 0.97619 0.986395 0 -0.923077 -0.446154 -0.138462 0.123077 0.369231 0.738462 -0.0641914 -0.577723 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.309524 0.309524 -0.0153846 0.4 wafers_in_system 0.00340137 0.00340137 0.979592 0.982993 0.982993 0.97619 0.979592 0 -0.584615 -0.446154 -0.138462 0.123077 0.369231 0.615385 0.128383 -0.577723 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.309524 0.309524 -0.0153846 0.4 wafers_in_system 0.00340137 8.71145e-009 8.71145e-009 0.982993 0.982993 0.97619 0.982993 0 -0.307692 -0.692308 -0.138462 0.123077 0.369231 0.6 0.320957 -0.577723 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.309524 0.309524 -0.0153846 0.4 wafers_in_system 0.00680273 0.00340137 0.00340137 0.00340137 0.982993 0.97619 0.982993 0.830769 0.507692 0.184615 -0.0769231 -0.384615 0.369231 0.630769 0.513531 -0.577723 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.309524 0.309524 -0.0153846 0.4 wafers_in_system 0.00680273 0.00340137 0.00340137 0.00340137 0.00680273 0.986395 0.986395 0.830769 0.507692 0.184615 -0.0769231 -0.523077 -0.8 -0.246154 0.706106 -0.577723 0.0641914 0.0641914 0 0 0 TYPE_RECT 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 0.309524 0.309524 -0.0153846 0.4 wafers_in_system 0.00680273 0.00340137 0.00340137 0.00340137 0.00680273 0.00340137 0.986395 0.830769 0.507692 0.184615 -0.0769231 -0.523077 -0.815385 -0.446154 -0.770297 -0.577723 0.0641914 0.0641914 0 0 0 TYPE_ELLIPSE 1 0.5 0.5 0.5 1 0.75 0.75 0.75 1 0 0 0 0 0 0 0 0 0 0 fan_out 0.00680273 0.75 0 0 fan_out 0.982993 0.00340137 0.0102041 0.00680273 0.00680273 0.00680273 0.00680273 0.00680273 0.0102041 0.00340137 0.00680273 0.00680273 0.00680273 0.00680273 0 -0.923077 -0.707692 -0.615385 -0.430769 -0.261538 -0.123077 0 0.138462 0.276923 0.430769 0.584615 0.692308 0.8 mcrl2-201409.0/examples/timed/ball_game/ball_game.mcrl2000770 001750 001750 00000001500 12370120073 023016 0ustar00outisoutis000000 000000 % This file describes a simple ball game. % It is necessary to put as many balls into a bucket in % a finite amount of time (10 seconds). But if a player fails % to put a bal into the bucket within one second, the player % is disqualified. Actions are "put_ball", "disqualified" % and "finished". Simple properties that are valid for this % system are that if not disqualified, there will at least % be 10 balls in the bucket when finished, and for any number % n>=10, it is possible to have a run of the game in which % a player puts that number of balls into the bucket. % % Jan Friso Groote (September 2008). act put_ball,disqualified,finished; proc P(t:Real)=sum u:Real.(u<=t+1 && u<10)->put_ball@u.P(u)+ sum u:Real.(u>t+1 && u<10)->disqualified@u.delta+ (t>=9)->finished@10.delta; init P(0); mcrl2-201409.0/examples/timed/simple/simple.mcrl2000770 001750 001750 00000001047 12370120073 022000 0ustar00outisoutis000000 000000 % This file contains a simple process that can do a step, an urgent and % a reset action. After a reset, urgent steps can be performed within a period % of two seconds. Ordinary steps can always be done. A reset is also always % possible. The times of actions are only recorded in the parameter, and not % explicitly as at time tag in the actions. % % Jan Friso Groote, December 2008 act step, urgent, reset; proc P(x:Real) = sum y:Real.(xstep.P(y) + sum y:Real.(xurgent.P(y) + reset.P(0); init P(0); mcrl2-201409.0/examples/timed/light/light.mcrl2000770 001750 001750 00000002012 12370120073 021425 0ustar00outisoutis000000 000000 % This file contains an example of a timed light switch inspired by % an Uppaal tutorial. The idea is that there is light that can either % be off, dimmed or shine brightly. When the light switch is pressed % the light goes from off to on and vice versa. If off, and the switch % is pressed more than once within 5 seconds the lamp will shine brightly. % The exact time when the press action happens is always x+y time since % the last reset of x. There is no time tag in the press action to % reflect this. This example can be used as a test case for lpsrealelm % that replace parameters of sort real by finite domains. % % Jan Friso Groote, December 2008 act press_on,press_off,press_bright; status:Light; sort Light=struct off | on | bright; proc P(x:Real,l:Light) = (l==off)->press_on.P(0,on) + sum y:Real.(l!=off && 0press_bright.P(x+y,bright) + sum y:Real.(l!=off && 0=5)->press_off.P(0,off) + status(l).P(x,l); init P(0,off); mcrl2-201409.0/examples/timed/clock/clock_drift.mcrl2000770 001750 001750 00000000602 12370120073 022570 0ustar00outisoutis000000 000000 % This example specifies a clock with time drift. % This is a clock where each subsequent tick can % come up to eps too early or too late. % (Taken from Designing and Understanding the Behaviour of Systems, J.F. Groote % and M. Reniers). act tick; % Arbitrary drift map eps:Real; proc Clock (t:Real) = sum y:Real . (t+1-eps <= y && y <= t+1+eps) -> tick@y . Clock(y); init Clock(0); mcrl2-201409.0/examples/timed/clock/clock_exact.mcrl2000770 001750 001750 00000000207 12370120073 022565 0ustar00outisoutis000000 000000 % This example specifies a simple clock, ticking every time unit. act tick; proc Clock(t:Real) = tick@t . Clock(t+1); init Clock(0); mcrl2-201409.0/examples/timed/clock/clock_hasty.mcrl2000770 001750 001750 00000000325 12370120073 022612 0ustar00outisoutis000000 000000 % This example specifies a clock which ticks at an arbitrary time % with a limit of 1 unit after the last tick. act tick; proc Clock(t:Real) = sum y:Real. (t < y && y < t+1) -> tick@y . Clock(y); init Clock(0); mcrl2-201409.0/examples/timed/fischer/fischer_100.mcrl2000770 001750 001750 00000002323 12370120073 022642 0ustar00outisoutis000000 000000 % This is an MCRL2 description of Fischer's mutual exclusion protocol % for two processes. The idea is that two processes communicate within % certain time bounds to obtain exclusive access to a mututal resource. % This protocol is particularly interesting, because it crucially % relies on time, and is quite simple. This version has been made by % Yaroslav Usenko using a similar model in UPPAAL. eqn n=100; eqn k=2; sort Time=Real; map n:Pos; k:Time; act get,_get,__get:Nat; set,_set,__set:Nat; cs_in,cs_out:Pos; proc P(pid:Pos)=P_init(pid,0,0); P_init(pid:Pos,t:Time,x:Time)= sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_req(pid:Pos,t:Time,x:Time)= sum u:Time.(u_set(pid)@(t+u).P_wait(pid,t+u,0); P_wait(pid:Pos,t:Time,x:Time)= sum u:Time.(x+u>=k)->_get(pid)@(t+u).cs_in(pid)@(t+u).P_cs(pid,t+u,x+u) +sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_cs(pid:Pos,t:Time,x:Time)= sum u:Time.cs_out(pid)@(t+u)._set(0)@(t+u).P_init(pid,t+u,x+u); ID(id:Nat) = sum n:Nat.set(n).ID(n) + get(id).ID(id); nP(p:Pos)=(p>1) -> (P(p)||nP(max(p-1,1)))<>P(1); init hide({__get,__set},allow({cs_in,cs_out,__get,__set},comm({get|_get->__get,set|_set->__set},allow({cs_in,cs_out,get|_get,set|_set},nP(n)||ID(0))))); mcrl2-201409.0/examples/timed/fischer/fischer_10.mcrl2000770 001750 001750 00000002322 12370120073 022561 0ustar00outisoutis000000 000000 % This is an MCRL2 description of Fischer's mutual exclusion protocol % for two processes. The idea is that two processes communicate within % certain time bounds to obtain exclusive access to a mututal resource. % This protocol is particularly interesting, because it crucially % relies on time, and is quite simple. This version has been made by % Yaroslav Usenko using a similar model in UPPAAL. eqn n=10; eqn k=2; sort Time=Real; map n:Pos; k:Time; act get,_get,__get:Nat; set,_set,__set:Nat; cs_in,cs_out:Pos; proc P(pid:Pos)=P_init(pid,0,0); P_init(pid:Pos,t:Time,x:Time)= sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_req(pid:Pos,t:Time,x:Time)= sum u:Time.(u_set(pid)@(t+u).P_wait(pid,t+u,0); P_wait(pid:Pos,t:Time,x:Time)= sum u:Time.(x+u>=k)->_get(pid)@(t+u).cs_in(pid)@(t+u).P_cs(pid,t+u,x+u) +sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_cs(pid:Pos,t:Time,x:Time)= sum u:Time.cs_out(pid)@(t+u)._set(0)@(t+u).P_init(pid,t+u,x+u); ID(id:Nat) = sum n:Nat.set(n).ID(n) + get(id).ID(id); nP(p:Pos)=(p>1) -> (P(p)||nP(max(p-1,1)))<>P(1); init hide({__get,__set},allow({cs_in,cs_out,__get,__set},comm({get|_get->__get,set|_set->__set},allow({cs_in,cs_out,get|_get,set|_set},nP(n)||ID(0))))); mcrl2-201409.0/examples/timed/fischer/fischer_10000.mcrl2000770 001750 001750 00000002325 12370120073 023004 0ustar00outisoutis000000 000000 % This is an MCRL2 description of Fischer's mutual exclusion protocol % for two processes. The idea is that two processes communicate within % certain time bounds to obtain exclusive access to a mututal resource. % This protocol is particularly interesting, because it crucially % relies on time, and is quite simple. This version has been made by % Yaroslav Usenko using a similar model in UPPAAL. eqn n=10000; eqn k=2; sort Time=Real; map n:Pos; k:Time; act get,_get,__get:Nat; set,_set,__set:Nat; cs_in,cs_out:Pos; proc P(pid:Pos)=P_init(pid,0,0); P_init(pid:Pos,t:Time,x:Time)= sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_req(pid:Pos,t:Time,x:Time)= sum u:Time.(u_set(pid)@(t+u).P_wait(pid,t+u,0); P_wait(pid:Pos,t:Time,x:Time)= sum u:Time.(x+u>=k)->_get(pid)@(t+u).cs_in(pid)@(t+u).P_cs(pid,t+u,x+u) +sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_cs(pid:Pos,t:Time,x:Time)= sum u:Time.cs_out(pid)@(t+u)._set(0)@(t+u).P_init(pid,t+u,x+u); ID(id:Nat) = sum n:Nat.set(n).ID(n) + get(id).ID(id); nP(p:Pos)=(p>1) -> (P(p)||nP(max(p-1,1)))<>P(1); init hide({__get,__set},allow({cs_in,cs_out,__get,__set},comm({get|_get->__get,set|_set->__set},allow({cs_in,cs_out,get|_get,set|_set},nP(n)||ID(0))))); mcrl2-201409.0/examples/timed/fischer/fischer_1000.mcrl2000770 001750 001750 00000002324 12370120073 022723 0ustar00outisoutis000000 000000 % This is an MCRL2 description of Fischer's mutual exclusion protocol % for two processes. The idea is that two processes communicate within % certain time bounds to obtain exclusive access to a mututal resource. % This protocol is particularly interesting, because it crucially % relies on time, and is quite simple. This version has been made by % Yaroslav Usenko using a similar model in UPPAAL. eqn n=1000; eqn k=2; sort Time=Real; map n:Pos; k:Time; act get,_get,__get:Nat; set,_set,__set:Nat; cs_in,cs_out:Pos; proc P(pid:Pos)=P_init(pid,0,0); P_init(pid:Pos,t:Time,x:Time)= sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_req(pid:Pos,t:Time,x:Time)= sum u:Time.(u_set(pid)@(t+u).P_wait(pid,t+u,0); P_wait(pid:Pos,t:Time,x:Time)= sum u:Time.(x+u>=k)->_get(pid)@(t+u).cs_in(pid)@(t+u).P_cs(pid,t+u,x+u) +sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_cs(pid:Pos,t:Time,x:Time)= sum u:Time.cs_out(pid)@(t+u)._set(0)@(t+u).P_init(pid,t+u,x+u); ID(id:Nat) = sum n:Nat.set(n).ID(n) + get(id).ID(id); nP(p:Pos)=(p>1) -> (P(p)||nP(max(p-1,1)))<>P(1); init hide({__get,__set},allow({cs_in,cs_out,__get,__set},comm({get|_get->__get,set|_set->__set},allow({cs_in,cs_out,get|_get,set|_set},nP(n)||ID(0))))); mcrl2-201409.0/examples/timed/fischer/fischer.mcrl2000770 001750 001750 00000002602 12370120073 022262 0ustar00outisoutis000000 000000 % This is an MCRL2 description of Fischer's mutual exclusion protocol % for two processes. The idea is that two processes communicate within % certain time bounds to obtain exclusive access to a mututal resource. % This protocol is particularly interesting, because it crucially % relies on time, and is quite simple. This version has been made by % Yaroslav Usenko using a similar model in UPPAAL and the semantics of % Networks of Timed automata with shared variables in % [BW04] Timed Automata: Semantics, Algorithms and Tools, % Johan Bengtsson and Wang Yi. In Lecture Notes on Concurrency and % Petri Nets. W. Reisig and G. Rozenberg (eds.), LNCS 3098, % Springer-Verlag, 2004. eqn k=2; map k:Time; sort Time=Real; act get,_get,__get:Nat; set,_set,__set:Nat; cs_in,cs_out:Pos; proc P(pid:Pos)=P_init(pid,0); P_init(pid:Pos,t:Time)= sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_req(pid:Pos,t:Time,x:Time)= sum u:Time.(x+u_set(pid)@(t+u).P_wait(pid,t+u,0); P_wait(pid:Pos,t:Time,x:Time)= sum u:Time.(x+u>=k)->(_get(pid)|cs_in(pid))@(t+u).P_cs(pid,t+u) +sum u:Time._get(0)@(t+u).P_req(pid,t+u,0); P_cs(pid:Pos,t:Time)= sum u:Time.(cs_out(pid)|_set(0))@(t+u).P_init(pid,t+u); ID(id:Nat) = sum n:Nat.set(n).ID(n) + get(id).ID(id); init hide({__get,__set},allow({cs_in|__get,cs_out|__set,__get,__set}, comm({get|_get->__get,set|_set->__set},ID(0)||P(1)||P(2)||P(3)||P(4)))); mcrl2-201409.0/examples/visualisation/README000770 001750 001750 00000001141 12370120075 020722 0ustar00outisoutis000000 000000 Follow these steps to create an FSM file for input to the visualization tools: 1. Choose an mCRL2 specification in one of the examples directories. 2. Assuming the file name of the specification is foo.mcrl2, create an LPS using the lineariser: $ mcrl22lps foo.mcrl2 foo.lps 3. Now generate a state space in mCRL2 SVC format: $ lps2lts foo.lps foo.svc 4. Finally, convert this state space to FSM format as follows: $ ltsconvert -l foo.lps foo.svc foo.fsm Supplying the LPS to ltsconvert (via the -l option) is required to obtain correct state parameter information in the resulting FSM file. mcrl2-201409.0/examples/modal-formulas/nodeadlock.mcf000770 001750 001750 00000000142 12370120073 022662 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/modal-formulas/nolivelock.mcf000770 001750 001750 00000000143 12370120073 022725 0ustar00outisoutis000000 000000 % This formula expresses that there is no livelock % for all reachable states. [true*]mu X.[tau]X examples/industrial/ieee-11073/no_successful_transmission_in_inconsistent_operating_states.mcf000770 001750 001750 00000000421 12370120076 035724 0ustar00outisoutis000000 000000 mcrl2-201409.0[true*] forall c, c': Configuration . [operating(c)|operating(c')] [!(exists ch: ChannelId . communicate(ch, AssocAbort) ||communicate(ch, AssocRelReq) ||communicate(ch, AssocRelRsp))*] [exists d: Data . communicate(manager_in(1), data(d))] (val(c == c')) mcrl2-201409.0/examples/industrial/ieee-11073/nodeadlock.mcf000770 001750 001750 00000000022 12370120076 023476 0ustar00outisoutis000000 000000 [true*]true mcrl2-201409.0/examples/industrial/ieee-11073/no_inconsistent_operating_states.mcf000770 001750 001750 00000000124 12370120076 030245 0ustar00outisoutis000000 000000 [true*] (forall c, c': Configuration. [operating(c)|operating(c')](val(c == c'))) mcrl2-201409.0/examples/industrial/ieee-11073/data_can_be_communicated.mcf000770 001750 001750 00000000105 12370120076 026325 0ustar00outisoutis000000 000000 true mcrl2-201409.0/examples/industrial/ieee-11073/11073.mcrl2000770 001750 001750 00000114710 12370120076 022332 0ustar00outisoutis000000 000000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Model of session setup of IEEE 11073-20601 % based on IEEE 11073-20601-2008, augmented with information from the ratified % version of 2010. % % This model was analysed in J.J.A. Keiren and M. D. Klabbers, "Modelling and % verifying the IEEE Std 11073-20601 session setup using mCRL2". % % Model by Jeroen Keiren % Last change: 5 June 2012 % % The configuration has two parameters that change the behaviour, see the % accompanying report for more information. % * enableFix1: fix deadlocks in the specification by allowing the Manager % to receive ConfigEventReportReq in situations where this is not % expected. % * enableFix2: fix deadlocks in the specification by allowing the Agent to % receive ConfigEventReportRsp in situations where this is not % expected. % * enableSessionIds: Fix the protocol by introducing session ids. % * wrapSessionIds: Make the model finite by counting session ids modulo % maxSessionId + 1. % * clearBuffersOnWrap: If maxSessionId session ids has been used, and a new % session id is needed, clear the buffers if wrapSessionIds is % enabled. This models the fairness assumption that before % maxSessionId + 1 session ids have been used, a message has been % read from both buffers at least M times. % % Notes on the specification: % * Numbers in comments in processes indicate Signal IDs in the transition % tables of the IEEE standard. % * (revised) indicates that the rule corresponds to the rule in the 2010 % ratified version of the standard, rather that the 2008 version. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % System sketch % % --------- ----- ----------- % | | <--- agent_in(0) ---- |A2M| <--- manager_out(1) ---- | | % | Agent | ----- | Manager | % | (0) | ---- agent_out(0) ---> |M2A| ---- manager_in(1) ---> | (1) | % --------- ----- ----------- % Model parameters, can be used to toggle several versions of the model. map enableFix1, enableFix2, enableSessionIds, wrapSessionIds, clearBuffersOnWrap: Bool; eqn % enableFix1: if set to true, ConfigEventReportReq messages are handled by % the manager in every state, if false, this message is treated as in the % 2008 version of the standard. enableFix1 = true; % enableFix2: if set to true, ConfigEventReportRsp messages are handled by % the agent in every state, if false, this message is treated as in the % 2008 version of the standard. enableFix2 = true; % enableSessionIds: if set to true, add session ids to the AssocReq and % AssocRsp messages. This fixes correctness of the protocol. enableSessionIds = true; % wrapSessionIds: if set to true, count session ids modulo maxSessionId, % otherwise increment, leading to an infinite state space. wrapSessionIds = true; % clearBuffersOnWrap: if set to true, the buffers are emptied once the % session id is wrapped, otherwise the buffers are unchanged clearBuffersOnWrap = true; % Max buffer size map M: Nat; eqn M = 1; % The maximum session id that should be used. % Only relevant if enableSessionIds is set. map maxSessionId: Nat; eqn maxSessionId = 1; % Process identifier (for introducing multiple agents/managers) sort Id = Nat; % SessionIds to session ids. sort SessionId = Nat; map session0: Nat; eqn session0 = 0; % Compute the next session id. map next: Nat -> Nat; var n: Nat; eqn % Count modulo maxSessionId + 1, if we use session ids, and want to wrap. (enableSessionIds && wrapSessionIds) -> next(n) = (n+1) mod Nat2Pos(maxSessionId+1); % Just increment if we use session ids, and do not want to wrap. (enableSessionIds && !wrapSessionIds) -> next(n) = n+1; % Add the same session id to every message, in case we do not want to use % session ids. !enableSessionIds -> next(n) = n; % Communication channels sort ChannelId = struct agent_in(Id) | agent_out(Id) | manager_in(Id) | manager_out(Id); % Message content for association responce sort AssociationResponse = struct rejected | accepted(Configuration) | accepted_unknown_config; % Message content for configuration response sort ConfigEventReportResponse = struct accepted_config(Configuration) | unsupported_config; % Dummy configurations, used for showing differences in configurations sort Configuration = struct c1 | c2; % Abstract type for data; abstracts from concrete messages that can be sent in % the operating state. sort Data = struct datum1; % Signals that can be sent in the system sort Signal = struct sig_AssocReq(SessionId) | sig_AssocRelReq | sig_AssocAbort | sig_AssocRelRsp | sig_AssocRsp(SessionId, AssociationResponse) | sig_ConfigEventReportReq | sig_ConfigEventReportRsp(ConfigEventReportResponse); % Generic message type, to allow sending Data and Signals along the same channel sort Message = struct signal(Signal) | data(Data); % Embed the signals as described in the standard/the paper into the message % data type. map AssocReq: SessionId -> Message; AssocRelReq, AssocAbort, AssocRelRsp: Message; AssocRsp: SessionId # AssociationResponse -> Message; ConfigEventReportReq: Message; ConfigEventReportRsp: ConfigEventReportResponse -> Message; var t: SessionId; ar: AssociationResponse; cr: ConfigEventReportResponse; c: Configuration; eqn AssocReq(t) = signal(sig_AssocReq(t)); AssocRelReq = signal(sig_AssocRelReq); AssocAbort = signal(sig_AssocAbort); AssocRelRsp = signal(sig_AssocRelRsp); AssocRsp(t, ar) = signal(sig_AssocRsp(t, ar)); ConfigEventReportReq = signal(sig_ConfigEventReportReq); ConfigEventReportRsp(cr) = signal(sig_ConfigEventReportRsp(cr)); % Actions for communicating along the above mentioned channels act send, receive, communicate: ChannelId # Message; % Actions local for the Agent/Manager act assocReq; assocAbortReq; assocRelReq; sendConfigReportReq; LookupConfig; agentSuppliedUnsupportedConfigReq; agentSuppliedSupportedConfigReq; % Actions for synchronous connect and disconnect of transport act transport_connect_agent; transport_connect_manager; transport_connect_notify; transport_connect; clear; reset_buffers; Reset_Buffers; transport_disconnect_agent; transport_disconnect_manager; transport_disconnect_notify; transport_disconnect; act operating:Configuration; % Report the configuration in the operating state %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % AGENT process %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Or states of the state chart sort Agent_states = struct Agent_Disconnected | Agent_Connected | Agent_nop; sort Agent_Connected_states = struct Agent_Connected_Disassociating | Agent_Connected_Unassociated | Agent_Connected_Associating | Agent_Connected_Associated | Agent_Connected_nop; sort Agent_Connected_Associated_states = struct Agent_Connected_Associated_Operating(Configuration) | Agent_Connected_Associated_Configuring | Agent_Connected_Associated_nop; sort Agent_Connected_Associated_Configuring_states = struct Agent_Connected_Associated_Configuring_WaitingApproval | Agent_Connected_Associated_Configuring_SendingConfig | Agent_Connected_Associated_Configuring_nop; % Agent process proc Agent(id: Id, t: SessionId, Agent_state: Agent_states, Agent_Connected_state: Agent_Connected_states, Agent_Connected_Associated_state: Agent_Connected_Associated_states, Agent_Connected_Associated_Configuring_state: Agent_Connected_Associated_Configuring_states) = %%%% Disconnected (Agent_state == Agent_Disconnected) -> ( % 1.1, 2.2, 3.3, 4.2, 5.2, 8.2, 9.2 transport_connect_agent . Agent(Agent_state = Agent_Connected, Agent_Connected_state = Agent_Connected_Unassociated) ) %%%% Connected + (Agent_state == Agent_Connected) -> ( % 2.2 transport_disconnect_agent . Agent(Agent_state = Agent_Disconnected, Agent_Connected_state = Agent_Connected_nop, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) ) %%%% Connected - Dissassociating + (Agent_state == Agent_Connected && Agent_Connected_state == Agent_Connected_Disassociating) -> ( assocRelReq . Agent() % 9.6 + assocAbortReq|send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 9.7 + sum t': SessionId . receive(agent_in(id), AssocReq(t')) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 9.8 + sum r: AssociationResponse, t': SessionId . receive(agent_in(id), AssocRsp(t', r)) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 9.12 + receive(agent_in(id), AssocRelReq) . send(agent_out(id), AssocRelRsp) . Agent() % 9.16; % state chart says: % Agent(Agent_Connected_state = Agent_Connected_Unassociated) + receive(agent_in(id), AssocRelRsp) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 9.17 + receive(agent_in(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 9.18 + (enableFix2 -> sum r: ConfigEventReportResponse . receive(agent_in(id), ConfigEventReportRsp(r)) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated)) %Ignore 9.21 %Ignore 9.26 ) %%%% Connected - Unassociated + (Agent_state == Agent_Connected && Agent_Connected_state == Agent_Connected_Unassociated) -> ( (t == maxSessionId && clearBuffersOnWrap) -> reset_buffers . assocReq|send(agent_out(id), AssocReq(next(t))) . Agent(Agent_Connected_state = Agent_Connected_Associating, t = next(t)) % 2.5 <> assocReq|send(agent_out(id), AssocReq(next(t))) . Agent(Agent_Connected_state = Agent_Connected_Associating, t = next(t)) % 2.5 + assocRelReq . Agent() % 2.6 + assocAbortReq . Agent() % 2.7 Should not happen + sum t': SessionId . receive(agent_in(id), AssocReq(t')) . send(agent_out(id), AssocRsp(t', rejected)) . Agent() % 2.8 Agent-agent association + sum r: AssociationResponse, t': SessionId . receive(agent_in(id), AssocRsp(t', r)) . send(agent_out(id), AssocAbort) . Agent() % 2.12 Should not happen + receive(agent_in(id), AssocRelReq) . send(agent_out(id), AssocAbort) . Agent() % 2.16 Should not happen + receive(agent_in(id), AssocRelRsp) . Agent() % 2.17 Should not happen. Ignore + receive(agent_in(id), AssocAbort) . Agent() % 2.18 + (enableFix2 -> sum r: ConfigEventReportResponse . receive(agent_in(id), ConfigEventReportRsp(r)) . send(agent_out(id), AssocAbort) . Agent()) %Ignore 2.19 Should not happen ) %%%% Connected - Associating + (Agent_state == Agent_Connected && Agent_Connected_state == Agent_Connected_Associating) -> ( %Ignore 3.3 Timeout, retry %Ignore 3.4 Timeout, abort assocRelReq|send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 3.6 + assocAbortReq|send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 3.7 + sum t': SessionId . receive(agent_in(id), AssocReq(t')) . send(agent_out(id), AssocRsp(t', rejected)) . Agent() % 3.8 + sum c: Configuration, t': SessionId . receive(agent_in(id), AssocRsp(t', accepted(c))) . (t == t') -> Agent(Agent_Connected_state = Agent_Connected_Associated, Agent_Connected_Associated_state = Agent_Connected_Associated_Operating(c)) % 3.13 <> send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) + sum t': SessionId . receive(agent_in(id), AssocRsp(t', accepted_unknown_config)) . (t == t') -> Agent(Agent_Connected_state = Agent_Connected_Associated, Agent_Connected_Associated_state = Agent_Connected_Associated_Configuring, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_SendingConfig) % 3.14 <> send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) + sum t': SessionId . receive(agent_in(id), AssocRsp(t', rejected)) . ((t == t') -> Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 3.15 <> send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated)) + receive(agent_in(id), AssocRelReq) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 3.16 Should not happen + receive(agent_in(id), AssocRelRsp) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 3.17 Should not happen + receive(agent_in(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated) % 3.18 + (enableFix2 -> sum r: ConfigEventReportResponse . receive(agent_in(id), ConfigEventReportRsp(r)) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated)) %Ignore 3.19 Should not happen ) %%%% Connected - Associated + (Agent_state == Agent_Connected && Agent_Connected_state == Agent_Connected_Associated) -> ( assocRelReq|send(agent_out(id), AssocRelReq) . Agent(Agent_Connected_state = Agent_Connected_Disassociating, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 4.6, 5.6, 8.6 + assocAbortReq|send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 4.7, 5.7, 8.7 + sum t': SessionId . receive(agent_in(id), AssocReq(t')) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 4.8, 5.8, 8.8 + sum r: AssociationResponse, t': SessionId . receive(agent_in(id), AssocRsp(t', r)) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 4.12, 5.12, 8.12 + receive(agent_in(id), AssocRelReq) . send(agent_out(id), AssocRelRsp) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 4.16, 5.16, 8.16 + receive(agent_in(id), AssocRelRsp) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 4.17, 5.17, 8.17 + receive(agent_in(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 4.18, 5.18, 8.18 ) %%%% Connected - Associated - Operating % When operating, responses from the configuring phase need to be handled % appropriately. + sum c: Configuration . (Agent_state == Agent_Connected && Agent_Connected_state == Agent_Connected_Associated && Agent_Connected_Associated_state == Agent_Connected_Associated_Operating(c)) -> ( operating(c) . Agent() + sum d: Data . send(agent_out(id), data(d)) . Agent() + (enableFix2 -> sum r: ConfigEventReportResponse . receive(agent_in(id), ConfigEventReportRsp(r)) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop)) ) %Ignore 8.21 %Ignore 8.26 %%%% Connected - Associated - Configuring % NOP %%%% Connected - Associated - Configuring - Waiting Approval + (Agent_state == Agent_Connected && Agent_Connected_state == Agent_Connected_Associated && Agent_Connected_Associated_state == Agent_Connected_Associated_Configuring && Agent_Connected_Associated_Configuring_state == Agent_Connected_Associated_Configuring_WaitingApproval) -> ( %Ignore 5.22 %Ignore 5.23 receive(agent_in(id), ConfigEventReportRsp(unsupported_config)) . Agent(Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_SendingConfig) % 5.27 + sum c: Configuration . receive(agent_in(id), ConfigEventReportRsp(accepted_config(c))) . Agent(Agent_Connected_Associated_state = Agent_Connected_Associated_Operating(c), Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop) % 5.29 %Ignore 5.30 ) %%%% Connnected - Associated - Configuring - Sending Config + (Agent_state == Agent_Connected && Agent_Connected_state == Agent_Connected_Associated && Agent_Connected_Associated_state == Agent_Connected_Associated_Configuring && Agent_Connected_Associated_Configuring_state == Agent_Connected_Associated_Configuring_SendingConfig) -> ( %Ignore 4.22 %Ignore 4.23 %Ignore 4.26 sendConfigReportReq|send(agent_out(id), ConfigEventReportReq) . Agent(Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_WaitingApproval) % 4.32 + (enableFix2 -> sum r: ConfigEventReportResponse . receive(agent_in(id), ConfigEventReportRsp(r)) . send(agent_out(id), AssocAbort) . Agent(Agent_Connected_state = Agent_Connected_Unassociated, Agent_Connected_Associated_state = Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_state = Agent_Connected_Associated_Configuring_nop)) ) ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % MANAGER %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Or states sort Manager_states = struct Manager_Disconnected | Manager_Connected | Manager_nop; sort Manager_Connected_states = struct Manager_Connected_Disassociating | Manager_Connected_Unassociated | Manager_Connected_Associating | Manager_Connected_Associated | Manager_Connected_nop; sort Manager_Connected_Associated_states = struct Manager_Connected_Associated_Operating(Configuration) | Manager_Connected_Associated_Configuring | Manager_Connected_Associated_nop; sort Manager_Connected_Associated_Configuring_states = struct Manager_Connected_Associated_Configuring_CheckingConfig | Manager_Connected_Associated_Configuring_WaitingForConfig | Manager_Connected_Associated_Configuring_nop; % Manager process proc Manager(id: Id, t: SessionId, Manager_state: Manager_states, Manager_Connected_state: Manager_Connected_states, Manager_Connected_Associated_state: Manager_Connected_Associated_states, Manager_Connected_Associated_Configuring_state: Manager_Connected_Associated_Configuring_states) = %%%% Disconnected (Manager_state == Manager_Disconnected) -> ( transport_connect_manager . Manager(Manager_state = Manager_Connected, Manager_Connected_state = Manager_Connected_Unassociated) % 1.1 ) %%%% Connected + (Manager_state == Manager_Connected) -> ( transport_disconnect_manager . Manager(Manager_state = Manager_Disconnected, Manager_Connected_state = Manager_Connected_nop, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 1.2, 2.2, 6.2, 7.2, 8.2, 9.2 ) %%%% Connected - Disassociating + (Manager_state == Manager_Connected && Manager_Connected_state == Manager_Connected_Disassociating) -> ( %Ignore 9.4 timeout assocRelReq . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 9.6 + assocAbortReq|send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 9.7 + sum t': SessionId . receive(manager_in(id), AssocReq(t')) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 9.8 + sum r: AssociationResponse, t': SessionId . receive(manager_in(id), AssocRsp(t', r)) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 9.12 + receive(manager_in(id), AssocRelReq) . send(manager_out(id), AssocRelRsp) . Manager() % 9.16 + receive(manager_in(id), AssocRelRsp) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 9.17 + receive(manager_in(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 9.18 + (enableFix1 -> receive(manager_in(id), ConfigEventReportReq) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated)) + sum d: Data . receive(manager_in(id), data(d)) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) %Ignore 9.21 %Ignore 9.26 ) %%%% Connected - Unassociated + (Manager_state == Manager_Connected && Manager_Connected_state == Manager_Connected_Unassociated) -> ( assocRelReq . Manager() % 2.6 Should not happen. Ignore. + assocAbortReq|send(manager_out(id), AssocAbort) . Manager() % 2.7 Should not happen. Ignore. (revised send AssocAbort) + sum t': SessionId . receive(manager_in(id), AssocReq(t')) . Manager(Manager_Connected_state = Manager_Connected_Associating, t = t') % 2.8 (revised) + sum r: AssociationResponse, t': SessionId . receive(manager_in(id), AssocRsp(t', r)) . send(manager_out(id), AssocAbort) . Manager() % 2.12 Should not happen + receive(manager_in(id), AssocRelReq) . send(manager_out(id), AssocAbort) . Manager() % 2.16 Should not happen + receive(manager_in(id), AssocRelRsp) . Manager() % 2.17 Should not happen. Ignore + receive(manager_in(id), AssocAbort) . Manager() % 2.18 Should not happen. Ignore + (enableFix1 -> receive(manager_in(id), ConfigEventReportReq) . send(manager_out(id), AssocAbort) . Manager()) + sum d: Data . receive(manager_in(id), data(d)) . send(manager_out(id), AssocAbort) . Manager() %Ignore 2.19 ) %%%% Connected - Associating + (Manager_state == Manager_Connected && Manager_Connected_state == Manager_Connected_Associating) -> ( assocRelReq|send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 3.6 (revised) + assocAbortReq|send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 3.7 (revised) + sum t': SessionId . receive(manager_in(id), AssocReq(t')) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 3.8 (revised) Should not happen + sum r: AssociationResponse, t': SessionId . receive(manager_in(id), AssocRsp(t', r)) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 3.12 (revised) Should not happen + receive(manager_in(id), AssocRelReq) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 3.16 (revised) + receive(manager_in(id), AssocRelRsp) . send(manager_out(id), AssocAbort) . Manager() % 3.17 (revised) + receive(manager_in(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 3.18 (revised) + LookupConfig|send(manager_out(id), AssocRsp(t, rejected)) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) % 3.11 (revised) + sum c: Configuration . LookupConfig|send(manager_out(id), AssocRsp(t, accepted(c))) . Manager(Manager_Connected_state = Manager_Connected_Associated, Manager_Connected_Associated_state = Manager_Connected_Associated_Operating(c)) % 3.10 (revised) + LookupConfig|send(manager_out(id), AssocRsp(t, accepted_unknown_config)) . Manager(Manager_Connected_state = Manager_Connected_Associated, Manager_Connected_Associated_state = Manager_Connected_Associated_Configuring, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_WaitingForConfig) % 3.9 (revised) + (enableFix1 -> receive(manager_in(id), ConfigEventReportReq) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated)) + sum d: Data . receive(manager_in(id), data(d)) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated) ) %%%% Connected - Associated + (Manager_state == Manager_Connected && Manager_Connected_state == Manager_Connected_Associated) -> ( %Ignore 6.4, 7.4, 8.4 timeout, abort assocRelReq|send(manager_out(id), AssocRelReq) . Manager(Manager_Connected_state = Manager_Connected_Disassociating, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 6.6, 7.6, 8.6 + assocAbortReq|send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 6.7, 7.7, 8.7 + sum t': SessionId . receive(manager_in(id), AssocReq(t')) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 6.8, 7.8, 8.8 Should not happen. + sum r: AssociationResponse, t': SessionId . receive(manager_in(id), AssocRsp(t', r)) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 6.12, 7.12, 8.12 Should not happen + receive(manager_in(id), AssocRelReq) . send(manager_out(id), AssocRelRsp) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 6.16, 7.16, 8.16 + receive(manager_in(id), AssocRelRsp) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 6.17, 7.17, 8.17 Should not happen + receive(manager_in(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 6.18, 7.18, 8.18 ) %%%% Connected - Associated - Operating % When operating, responses from the configuring phase need to be handled % appropriately. + sum c: Configuration . (Manager_state == Manager_Connected && Manager_Connected_state == Manager_Connected_Associated && Manager_Connected_Associated_state == Manager_Connected_Associated_Operating(c)) -> ( operating(c) . Manager() + sum d: Data . receive(manager_in(id), data(d)) . Manager() + (enableFix1 -> receive(manager_in(id), ConfigEventReportReq) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop)) ) %Ignore 8.21 %Ignore 8.26 %%%% Connected - Associated - Configuring % No common operations %%%% Connected - Associated - Configuring - Checking Config + (Manager_state == Manager_Connected && Manager_Connected_state == Manager_Connected_Associated && Manager_Connected_Associated_state == Manager_Connected_Associated_Configuring && Manager_Connected_Associated_Configuring_state == Manager_Connected_Associated_Configuring_CheckingConfig) -> ( %Ignore 7.24 %Ignore 7.25 %Ignore 7.26 %Ignore 7.31 %Ignore 7.32 agentSuppliedUnsupportedConfigReq| send(manager_out(id), ConfigEventReportRsp(unsupported_config)) . Manager(Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_WaitingForConfig) % 7.31 + sum c: Configuration . agentSuppliedSupportedConfigReq| send(manager_out(id), ConfigEventReportRsp(accepted_config(c))) . Manager(Manager_Connected_Associated_state = Manager_Connected_Associated_Operating(c), Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) % 7.32 + (enableFix1 -> receive(manager_in(id), ConfigEventReportReq) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop)) + sum d: Data . receive(manager_in(id), ConfigEventReportReq) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) ) %%%% Connected - Associated - Configuring - Waiting for Config + (Manager_state == Manager_Connected && Manager_Connected_state == Manager_Connected_Associated && Manager_Connected_Associated_state == Manager_Connected_Associated_Configuring && Manager_Connected_Associated_Configuring_state == Manager_Connected_Associated_Configuring_WaitingForConfig) -> ( receive(manager_in(id), ConfigEventReportReq) . Manager(Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_CheckingConfig) % 6.24 + sum d: Data . receive(manager_in(id), data(d)) . send(manager_out(id), AssocAbort) . Manager(Manager_Connected_state = Manager_Connected_Unassociated, Manager_Connected_Associated_state = Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_state = Manager_Connected_Associated_Configuring_nop) %Ignore 6.25 %Ignore 6.26 ) ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Buffers for asynchronous communication %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Buffer connects to two communication channels %% ---------- % --channel_in--> | Buffer | --channel_out--> % ---------- % Internally, the buffer contents is stored as a list. proc Buffer(channel_in, channel_out: ChannelId, buf: List(Message)) = sum m: Message . (#buf < M) -> receive(channel_in, m) . Buffer(channel_in, channel_out, buf <| m) + (buf != []) -> send(channel_out, head(buf)) . Buffer(channel_in, channel_out, tail(buf)) + clear . Buffer(channel_in, channel_out, []) + reset_buffers . Buffer(channel_in, channel_out, []); proc A2M(aid, mid: Id, buf: List(Message)) = Buffer(agent_out(aid), manager_in(mid), buf); proc M2A(mid, aid: Id, buf: List(Message)) = Buffer(manager_out(mid), agent_in(aid), buf); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % System %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% init hide( { assocReq, assocAbortReq, assocRelReq, sendConfigReportReq, LookupConfig, agentSuppliedUnsupportedConfigReq, agentSuppliedSupportedConfigReq }, allow( { communicate, transport_connect, transport_disconnect, operating, operating|operating, Reset_Buffers, communicate|assocReq, communicate|assocAbortReq, communicate|assocRelReq, communicate|sendConfigReportReq, communicate|LookupConfig, communicate|agentSuppliedUnsupportedConfigReq, communicate|agentSuppliedSupportedConfigReq }, comm( { send|receive -> communicate, transport_connect_agent|transport_connect_manager->transport_connect, transport_disconnect_agent|transport_disconnect_manager| clear|clear->transport_disconnect, reset_buffers|reset_buffers|reset_buffers -> Reset_Buffers }, Agent(0, session0, Agent_Disconnected, Agent_Connected_nop, Agent_Connected_Associated_nop, Agent_Connected_Associated_Configuring_nop) || A2M(0, 1, []) || M2A(1, 0, []) || Manager(1, session0, Manager_Disconnected, Manager_Connected_nop, Manager_Connected_Associated_nop, Manager_Connected_Associated_Configuring_nop) ) ) ) ; mcrl2-201409.0/examples/industrial/ieee-11073/infinite_data_communication_is_possible.mcf000770 001750 001750 00000000271 12370120076 031517 0ustar00outisoutis000000 000000 [true*] nu X . X mcrl2-201409.0/examples/industrial/garage/garage.mcrl2000770 001750 001750 00000116546 12370120076 022764 0ustar00outisoutis000000 000000 % The following is the general specification of the safety layer of the % automated parking garage as described in [1, Appendices B and C.1]. % % Simulation or state space generation of this specification is not possible, % because of the enormous amount of possible instruction sets that can be % requested and executed. % % [1] Aad Mathijssen and A. Johannes Pretorius. Specification, Analysis and % Verification of an Automated Parking Garage. Computer Science Report % 05-25, Eindhoven University of Technology (TU/e), 2005. sort FloorRow = struct r1 | r2 | r3; FloorCol = struct c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10; FloorPosPart = struct pa | pb; FloorPos = struct pos_r1(FloorCol, FloorPosPart) | pos_r2(FloorCol) | pos_r3(FloorCol); FloorPosList = List(FloorPos); ShuttlePos = struct r1a | r2a | r3a | r1b | r2b | r3b; ShuttlePosSet = List(ShuttlePos); % representing a set of ShuttlePos elements ShuttleOrientation = struct lowered | tilted; R1Belt = struct b_r1a_sh | b_r1a | b_r1lift | b_r1b | b_r1b_sh; R2Belt = struct b_r2a_sh | b_r2 | b_r2b_sh; R3Belt = struct b_r3a_sh | b_r3 | b_r3b_sh; R1BeltSet = List(R1Belt); % representing a set of R1Belt elements R2BeltSet = List(R2Belt); % representing a set of R2Belt elements R3BeltSet = List(R3Belt); % representing a set of R3Belt elements DirCol = struct col_inc | col_dec; DirRow = struct row_inc | row_dec; MoveSize = struct full | half; LiftHeight = struct street | rotate | basement; Area = struct area(positions: FloorPosList, tilted_c1: Bool, tilted_c10: Bool); Instruction = struct move_belts(R1BeltSet, DirCol, MoveSize) | move_belts(R2BeltSet, DirCol, MoveSize) | move_belts(R3BeltSet, DirCol, MoveSize) | move_shuttles(ShuttlePosSet, ShuttleOrientation, DirRow) | tilt_shuttle(ShuttlePos, ShuttleOrientation) | move_lift(LiftHeight) | rotate_lift; InstructionSet = List(Instruction); % representing a set of instructions Event = struct add_car | remove_car; ExecResult = struct ok | fail; OccState = struct free | occupied; AvailState = struct avail | n_avail; FloorState = FloorPos -> OccState; ShuttleState = ShuttlePos # ShuttleOrientation -> AvailState; LiftState = struct lsf_street | lso_street | lsf_rotate | lso_rotate | ls_basement; GlobalState = struct glob_state(fs: FloorState, shs: ShuttleState, ls: LiftState); % FloorRow operations map index: FloorRow -> Pos; % index(fra) is the index of fra lt: FloorRow # FloorRow -> Bool; % lt(fra,frb) indicates if fra is less than frb var fra, frb: FloorRow; eqn index(r1) = 1; index(r2) = 2; index(r3) = 3; lt(fra, frb) = index(fra) < index(frb); % FloorCol operations map index: FloorCol -> Pos; % index(fca) is the index of fca lt: FloorCol # FloorCol -> Bool; % lt(fca,fcb) indicates if fca is less than fcb var fca, fcb: FloorCol; eqn index(c1) = 1; index(c2) = 2; index(c3) = 3; index(c4) = 4; index(c5) = 5; index(c6) = 6; index(c7) = 7; index(c8) = 8; index(c9) = 9; index(c10) = 10; lt(fca, fcb) = index(fca) < index(fcb); % FloorPosPart operations map index: FloorPosPart -> Pos; % index(ffpa) is the index of fppa lt: FloorPosPart # FloorPosPart -> Bool; % lt(fppa,fppb) indicates if fppa is less than fppb var fppa, fppb: FloorPosPart; eqn index(pa) = 1; index(pb) = 2; lt(fppa, fppb) = index(fppa) < index(fppb); % FloorPos operations map row: FloorPos -> FloorRow; % row(fpa) is the row of fpa col: FloorPos -> FloorCol; % col(fpa) is the column of fpa part: FloorPos -> FloorPosPart; % part(fpa) is the part of fpa lt: FloorPos # FloorPos -> Bool; % lt(fpa, fpb) indicates if fpa is less than fpb lt_r: FloorPos # FloorPos -> Bool; % lt_r(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) (auxiliary function needed by lt for efficiency) lt_rc: FloorPos # FloorPos -> Bool; % lt_rc(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) and col(fpa) = col(fpb) % (auxiliary function needed by lt_r for efficiency) gt: FloorPos # FloorPos -> Bool; % gt(fpa, fpb) indicates if fpa is greater than fpb var fca: FloorCol; fppa: FloorPosPart; fpa, fpb: FloorPos; eqn row(pos_r1(fca, fppa)) = r1; row(pos_r2(fca)) = r2; row(pos_r3(fca)) = r3; col(pos_r1(fca, fppa)) = fca; col(pos_r2(fca)) = fca; col(pos_r3(fca)) = fca; part(pos_r1(fca, fppa)) = fppa; row(fpa) == row(fpb) -> lt(fpa, fpb) = lt_r(fpa, fpb); row(fpa) != row(fpb) -> lt(fpa, fpb) = lt(row(fpa), row(fpb)); col(fpa) == col(fpb) -> lt_r(fpa, fpb) = lt_rc(fpa, fpb); col(fpa) != col(fpb) -> lt_r(fpa, fpb) = lt(col(fpa), col(fpb)); lt_rc(fpa, fpb) = row(fpa) == r1 && lt(part(fpa), part(fpb)); gt(fpa,fpb) = lt(fpb, fpa); % FloorPosList operations map contains: FloorPos # FloorPosList -> Bool; % contains(fpa, fps) indicates if fps contains fpa overlap: FloorPosList # FloorPosList -> Bool; % overlap(fps, fpt) indicates if the elements of fps and fpt overlap rev: FloorPosList -> FloorPosList; % rev(fps) is the reverse of list fps grev: FloorPosList # FloorPosList -> FloorPosList; % grev(fps, fpt) is the reverse of fps concatenated with fpt % (auxiliary function needed for efficiency by rev) var fpa, fpb: FloorPos; fps, fpt: FloorPosList; eqn contains(fpa, []) = false; contains(fpa, fpa |> fps) = true; fpa != fpb -> contains(fpa, fpb |> fps) = contains(fpa, fps); overlap([], fpt) = false; overlap(fpa |> fps, fpt) = contains(fpa, fpt) || overlap(fps, fpt); rev(fps) = grev(fps, []); grev([], fpt) = fpt; grev(fpa |> fps, fpt) = grev(fps, fpa |> fpt); % ShuttlePos operations map index: ShuttlePos -> Pos; % index(spa) is the index of spa row: ShuttlePos -> FloorRow; % row(spa) is the row of spa col: ShuttlePos -> FloorCol; % col(spa) is the column of spa lt: ShuttlePos # ShuttlePos -> Bool; % lt(spa, spb) indicates if spa is less than spb gt: ShuttlePos # ShuttlePos -> Bool; % gt(spa, spb) indicates if spa is greater than spb positions: ShuttlePos -> FloorPosList; % positions(spa) represents the floor positions corresponding to spa in % lowered position has_neighbour: ShuttlePos # DirRow -> Bool; % has_neighbour(spa, dr) indicates if spa has a successor in direction dr neighbour: ShuttlePos # DirRow -> ShuttlePos; % neighbour(spa, dr) is the neighbour of spa in directrion dr, provided it % exists connected: ShuttlePos # ShuttlePos -> Bool; % connected(spa, spb) indicates if the bottom of spa is connected to the top % of spb var spa, spb: ShuttlePos; eqn index(r1a) = 1; index(r2a) = 2; index(r3a) = 3; index(r1b) = 4; index(r2b) = 5; index(r3b) = 6; row(r1a) = r1; row(r2a) = r2; row(r3a) = r3; row(r1b) = r1; row(r2b) = r2; row(r3b) = r3; col(r1a) = c1; col(r2a) = c1; col(r3a) = c1; col(r1b) = c10; col(r2b) = c10; col(r3b) = c10; lt(spa, spb) = index(spa) < index(spb); gt(spa, spb) = index(spa) > index(spb); positions(r1a) = positions(b_r1a_sh); positions(r2a) = positions(b_r2a_sh); positions(r3a) = positions(b_r3a_sh); positions(r1b) = positions(b_r1b_sh); positions(r2b) = positions(b_r2b_sh); positions(r3b) = positions(b_r3b_sh); has_neighbour(spa, row_inc) = row(spa) != r3; has_neighbour(spa, row_dec) = row(spa) != r1; neighbour(r1a, row_inc) = r2a; neighbour(r2a, row_inc) = r3a; neighbour(r1b, row_inc) = r2b; neighbour(r2b, row_inc) = r3b; neighbour(r2a, row_dec) = r1a; neighbour(r3a, row_dec) = r2a; neighbour(r2b, row_dec) = r1b; neighbour(r3b, row_dec) = r2b; connected(spa, spb) = succ(index(spa)) == index(spb) && col(spa) == col(spb); % ShuttlePosSet operations map is_set_sps: ShuttlePosSet -> Bool; % is_set_sps(sps) indicates if sps is a set % In the remainder of the data equation section, for every ShuttlePosSet sps % is_set_sps(sps) is a precondition. contains: ShuttlePos # ShuttlePosSet -> Bool; % contains(spa, sps) indicates if sps contains spa shuttles: FloorCol -> ShuttlePosSet; % shuttles(fc) represents the shuttle positions corresponding to fc positions_sps: ShuttlePosSet -> FloorPosList; % positions_sps(sps) represents the floor positions corresponding to sps connected_sps: ShuttlePosSet -> Bool; % connected_sps(sps) indicates if all elements of sps are connected has_neighbour: ShuttlePosSet # DirRow -> Bool; % has_neighbour(sps, dr) indicates is sps has a neighbour in direction dr neighbour_sps: ShuttlePosSet # DirRow -> ShuttlePos; % neighbour_sps(sps, dr) is the neighbour of sps in direction dr, provided it % exists add_neighbour: ShuttlePosSet # DirRow -> ShuttlePosSet; % add_neighbour(sps, dr) represents the sps extended with its neighbour in % direction dr, provided it exists var spa, spb: ShuttlePos; sps: ShuttlePosSet; fc: FloorCol; eqn is_set_sps([]) = true; is_set_sps(spa |> []) = true; is_set_sps(spa |> spb |> sps) = lt(spa, spb) && is_set_sps(spb |> sps); contains(spa, []) = false; contains(spa, spa |> sps) = true; spa != spb -> contains(spa, spb |> sps) = contains(spa, sps); shuttles(fc) = if(fc == c1, [r1a,r2a,r3a], if(fc == c10, [r1b,r2b,r3b], [])); positions_sps([]) = []; positions_sps(spa |> sps) = positions(spa) ++ positions_sps(sps); connected_sps([]) = true; connected_sps([spa]) = true; connected_sps(spa |> spb |> sps) = connected(spa, spb) && connected_sps(spb |> sps); has_neighbour(sps, row_inc) = has_neighbour(rhead(sps), row_inc); has_neighbour(sps, row_dec) = has_neighbour(head(sps), row_dec); neighbour_sps(sps, row_inc) = neighbour(rhead(sps), row_inc); neighbour_sps(sps, row_dec) = neighbour(head(sps), row_dec); add_neighbour(sps, row_inc) = sps <| neighbour_sps(sps, row_inc); add_neighbour(sps, row_dec) = neighbour_sps(sps, row_dec) |> sps; % ShuttleOrientation operations map index: ShuttleOrientation -> Pos; % index(soa) is the index of soa lt: ShuttleOrientation # ShuttleOrientation -> Bool; % lt(soa, sob) indicates if soa is less than sob gt: ShuttleOrientation # ShuttleOrientation -> Bool; % gt(soa, sob) indicates if soa is greater than sob not: ShuttleOrientation -> ShuttleOrientation; % not(soa) indicates the opposite of soa var soa, sob: ShuttleOrientation; eqn index(lowered) = 1; index(tilted) = 2; lt(soa, sob) = index(soa) < index(sob); gt(soa, sob) = index(soa) > index(sob); not(lowered) = tilted; not(tilted) = lowered; % Belt operations map index: R1Belt -> Pos; index: R2Belt -> Pos; index: R3Belt -> Pos; % index(ba) is the index of belt ba row: R1Belt -> FloorRow; row: R2Belt -> FloorRow; row: R3Belt -> FloorRow; % row(ba) is the row of belt ba lt: R1Belt # R1Belt -> Bool; lt: R2Belt # R2Belt -> Bool; lt: R3Belt # R3Belt -> Bool; % lt(ba, bb) indicates if belt ba is less than belt bb positions: R1Belt -> FloorPosList; positions: R2Belt -> FloorPosList; positions: R3Belt -> FloorPosList; % positions(ba) represents the positions corresponding to belt ba connected: R1Belt # R1Belt -> Bool; connected: R2Belt # R2Belt -> Bool; connected: R3Belt # R3Belt -> Bool; % connected(ba, bb) indicates if the right of ba is connected to the left % of bb available: R1Belt # ShuttleState # LiftState -> Bool; available: R2Belt # ShuttleState # LiftState -> Bool; available: R3Belt # ShuttleState # LiftState -> Bool; % available(ba, shs, ls) indicates if belt ba is available for states shs % and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; fs: FloorState; shs: ShuttleState; ls: LiftState; ms: MoveSize; eqn index(b_r1a_sh) = 1; index(b_r1a) = 2; index(b_r1lift) = 3; index(b_r1b) = 4; index(b_r1b_sh) = 5; index(b_r2a_sh) = 1; index(b_r2) = 2; index(b_r2b_sh) = 3; index(b_r3a_sh) = 1; index(b_r3) = 2; index(b_r3b_sh) = 3; row(r1ba) = r1; row(r2ba) = r2; row(r3ba) = r3; lt(r1ba, r1bb) = index(r1ba) < index(r1bb); lt(r2ba, r2bb) = index(r2ba) < index(r2bb); lt(r3ba, r3bb) = index(r3ba) < index(r3bb); positions(b_r1a_sh) = [pos_r1(c1, pa), pos_r1(c1, pb)]; positions(b_r1a) = [pos_r1(c2, pa), pos_r1(c2, pb), pos_r1(c3, pa), pos_r1(c3, pb), pos_r1(c4, pa), pos_r1(c4, pb), pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa)]; positions(b_r1lift) = [pos_r1(c6, pb), pos_r1(c7, pa)]; positions(b_r1b) = [pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb), pos_r1(c9, pa), pos_r1(c9, pb)]; positions(b_r1b_sh) = [pos_r1(c10, pa), pos_r1(c10, pb)]; positions(b_r2a_sh) = [pos_r2(c1)]; positions(b_r2) = [pos_r2(c2), pos_r2(c3), pos_r2(c4), pos_r2(c5), pos_r2(c6), pos_r2(c7), pos_r2(c8), pos_r2(c9)]; positions(b_r2b_sh) = [pos_r2(c10)]; positions(b_r3a_sh) = [pos_r3(c1)]; positions(b_r3) = [pos_r3(c2), pos_r3(c3), pos_r3(c4), pos_r3(c5), pos_r3(c6), pos_r3(c7), pos_r3(c8), pos_r3(c9)]; positions(b_r3b_sh) = [pos_r3(c10)]; available(b_r1a_sh, shs, ls) = shs(r1a, lowered) == avail; available(b_r1a, shs, ls) = true; available(b_r1lift, shs, ls) = ls == ls_basement; available(b_r1b, shs, ls) = true; available(b_r1b_sh, shs, ls) = shs(r1b, lowered) == avail; available(b_r2a_sh, shs, ls) = shs(r2a, lowered) == avail; available(b_r2, shs, ls) = true; available(b_r2b_sh, shs, ls) = shs(r2b, lowered) == avail; available(b_r3a_sh, shs, ls) = shs(r3a, lowered) == avail; available(b_r3, shs, ls) = true; available(b_r3b_sh, shs, ls) = shs(r3b, lowered) == avail; % BeltSet operations map is_set_b_r1: R1BeltSet -> Bool; is_set_b_r2: R2BeltSet -> Bool; is_set_b_r3: R3BeltSet -> Bool; % is_set_b_rX(bs) indicates if bs is a set % In the remainder of this data equations section each belt set bs has % is_set_b_rX(bs) as a precondition. contains: R1Belt # R1BeltSet -> Bool; contains: R2Belt # R2BeltSet -> Bool; contains: R3Belt # R3BeltSet -> Bool; % contains(ba, bs) indicates if ba is an element of bs positions_b_r1: R1BeltSet -> FloorPosList; positions_b_r2: R2BeltSet -> FloorPosList; positions_b_r3: R3BeltSet -> FloorPosList; % positions_b_rX(bs) represents the floor positions corresponding to the % belts in bs connected_b_r1: R1BeltSet -> Bool; connected_b_r2: R2BeltSet -> Bool; connected_b_r3: R3BeltSet -> Bool; % connected(bs) indicates if the belts in bs are connected available_b_r1: R1BeltSet # ShuttleState # LiftState -> Bool; available_b_r2: R2BeltSet # ShuttleState # LiftState -> Bool; available_b_r3: R3BeltSet # ShuttleState # LiftState -> Bool; % available_b_rX(bs, shs, ls) indicates if all belts in bs are available for % states shs and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; fs: FloorState; shs: ShuttleState; ls: LiftState; eqn is_set_b_r1([]) = true; is_set_b_r1(r1ba |> []) = true; is_set_b_r1(r1ba |> r1bb |> r1bs) = lt(r1ba, r1bb) && is_set_b_r1(r1bb |> r1bs); is_set_b_r2([]) = true; is_set_b_r2(r2ba |> []) = true; is_set_b_r2(r2ba |> r2bb |> r2bs) = lt(r2ba, r2bb) && is_set_b_r2(r2bb |> r2bs); is_set_b_r3([]) = true; is_set_b_r3(r3ba |> []) = true; is_set_b_r3(r3ba |> r3bb |> r3bs) = lt(r3ba, r3bb) && is_set_b_r3(r3bb |> r3bs); contains(r1ba, []) = false; contains(r1ba, r1ba |> r1bs) = true; r1ba != r1bb -> contains(r1ba, r1bb |> r1bs) = contains(r1ba, r1bs); contains(r2ba, []) = false; contains(r2ba, r2ba |> r2bs) = true; r2ba != r2bb -> contains(r2ba, r2bb |> r2bs) = contains(r2ba, r2bs); contains(r3ba, []) = false; contains(r3ba, r3ba |> r3bs) = true; r3ba != r3bb -> contains(r3ba, r3bb |> r3bs) = contains(r3ba, r3bs); positions_b_r1([]) = []; positions_b_r1(r1ba |> r1bs) = positions(r1ba) ++ positions_b_r1(r1bs); positions_b_r2([]) = []; positions_b_r2(r2ba |> r2bs) = positions(r2ba) ++ positions_b_r2(r2bs); positions_b_r3([]) = []; positions_b_r3(r3ba |> r3bs) = positions(r3ba) ++ positions_b_r3(r3bs); connected_b_r1([]) = true; connected_b_r1(r1ba |> []) = true; connected_b_r1(r1ba |> r1bb |> r1bs) = connected(r1ba, r1bb) && connected_b_r1(r1bb |> r1bs); connected_b_r2([]) = true; connected_b_r2(r2ba |> []) = true; connected_b_r2(r2ba |> r2bb |> r2bs) = connected(r2ba, r2bb) && connected_b_r2(r2bb |> r2bs); connected_b_r3([]) = true; connected_b_r3(r3ba |> []) = true; connected_b_r3(r3ba |> r3bb |> r3bs) = connected(r3ba, r3bb) && connected_b_r3(r3bb |> r3bs); connected(r1ba, r1bb) = succ(index(r1ba)) == index(r1bb); connected(r2ba, r2bb) = succ(index(r2ba)) == index(r2bb); connected(r3ba, r3bb) = succ(index(r3ba)) == index(r3bb); available_b_r1([], shs, ls) = true; available_b_r1(r1ba |> r1bs, shs, ls) = available(r1ba, shs, ls) && available_b_r1(r1bs, shs, ls); available_b_r2([], shs, ls) = true; available_b_r2(r2ba |> r2bs, shs, ls) = available(r2ba, shs, ls) && available_b_r2(r2bs, shs, ls); available_b_r3([], shs, ls) = true; available_b_r3(r3ba |> r3bs, shs, ls) = available(r3ba, shs, ls) && available_b_r3(r3bs, shs, ls); % Area operations map overlap: Area # Area -> Bool; % area(a, b) indicates if area a and b overlap var fps, fpt: FloorPosList; tc1a, tc1b, tc10a, tc10b: Bool; eqn overlap(area(fps, tc1a, tc1b), area(fpt, tc10a, tc10b)) = overlap(fps, fpt) || (tc1a && tc1b) || (tc10a && tc10b); % Instruction operations map index: Instruction -> Pos; % index(i) is the index of instruction i lt: Instruction # Instruction -> Bool; % lt(i, j) indicates if i is less than j valid: Instruction -> Bool; % valid(i) indicates if instruction i is valid area: Instruction -> Area; % area(i) represents the area on which instruction i has any effect overlap: Instruction # Instruction -> Bool; % overlap(i, j) indicates if instruction i and j overlap var r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sp: ShuttlePos; sps: ShuttlePosSet; so: ShuttleOrientation; dr: DirRow; lh: LiftHeight; i,j: Instruction; eqn index(move_belts(r1bs, dc, ms)) = 1; index(move_belts(r2bs, dc, ms)) = 2; index(move_belts(r3bs, dc, ms)) = 3; index(move_shuttles(sps, so, dr)) = 4; index(tilt_shuttle(sp, so)) = 5; index(move_lift(lh)) = 6; index(rotate_lift) = 7; lt(i, j) = index(i) < index(j); valid(move_belts(r1bs, dc, ms)) = is_set_b_r1(r1bs); valid(move_belts(r2bs, dc, ms)) = is_set_b_r2(r2bs); valid(move_belts(r3bs, dc, ms)) = is_set_b_r3(r3bs); valid(move_shuttles(sps, so, dr)) = is_set_sps(sps); valid(tilt_shuttle(sp, so)) = true; valid(move_lift(lh)) = true; valid(rotate_lift) = true; area(move_belts(r1bs, dc, ms)) = area(positions_b_r1(r1bs), false, false); area(move_belts(r2bs, dc, ms)) = area(positions_b_r2(r2bs), false, false); area(move_belts(r3bs, dc, ms)) = area(positions_b_r3(r3bs), false, false); area(move_shuttles(sps, lowered, dr)) = area(positions_sps(add_neighbour(sps, dr)), false, false); area(move_shuttles(sps, tilted, dr)) = area([], col(head(sps)) == c1, col(head(sps)) == c10); area(tilt_shuttle(sp, so)) = area(positions(sp), col(sp) == c1, col(sp) == c10); area(move_lift(lh)) = area(positions(b_r1lift), false, false); area(rotate_lift) = area(positions_b_r1([b_r1a, b_r1lift, b_r1b]), false, false); overlap(i, j) = overlap(area(i), area(j)); % InstructionSet operations map is_set_is: InstructionSet -> Bool; % is_set_is(is) indicates if is is a set % In the remainder of the data equation section, for every InstructionSet is % is_set_is(is) is a precondition. valid: InstructionSet -> Bool; % valid(is) indicates if the instructions in is are valid overlap: Instruction # InstructionSet -> Bool; % overlap(i, is) indicates if instruction i overlaps with any of the % instructions in is var i,j: Instruction; is: InstructionSet; eqn is_set_is([]) = true; is_set_is(i |> []) = true; is_set_is(i |> j |> is) = lt(i, j) && is_set_is(j |> is); valid([]) = true; valid(i |> is) = valid(i) && valid(is); overlap(i, []) = false; overlap(i, j |> is) = overlap(i, j) || overlap(i, is); % AvailState operations map not: AvailState -> AvailState; % not(asa) indicates the opposite of asa eqn not(avail) = n_avail; not(n_avail) = avail; % FloorState operations map init_fs: FloorState; % init_fs is the initial floor state update: FloorPos # OccState # FloorState -> FloorState; cond_upd: FloorPos # OccState # FloorState -> FloorState; ins_upd: FloorPos # OccState # FloorState -> FloorState; % update(fpa, osa, fsa) represents fsa, where position fpa has value osa; % cond_upd and ins_upd are auxiliary functions with the same meaning that % are needed for efficiency ins_upd_fps: FloorPosList # OccState # FloorState -> FloorState; % ins_upd_fps(fps, osa, fsa) represents fsa, where positions fps have value % osa free: FloorPosList # FloorState -> Bool; % free(fps, fsa) indicates that all positions in fps are free for state fsa occupied: FloorPosList # FloorState -> Bool; % occupied(fps, fsa) indicates that all positions in fps are occupied for % state fsa end_free: FloorPosList # DirCol # Bool # FloorState -> Bool; % end_free(fps, dc, obl, fsa) indicates if the end of the list fps in % direction dc is free for state fsa; if obl then the one but last element % also needs to be free even_occ: FloorPosList # FloorState -> Bool; % even_occ(fps, fsa) indicates if the number of occupied positions in fps for % state fsa is even no_half_car: ShuttlePos # FloorState -> Bool; % no_half_car(spa, fsa) indicates if there is a half car positioned on spa % for state fsa no_half_car_sps: ShuttlePosSet # FloorState -> Bool; % no_half_car(sps, fsa) indicates if there is a half car positioned on any % of the elements of sps for state fsa shift_inc: FloorPosList # FloorState -> FloorState; % shift_inc(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the right; the first element in fps % gets state free gshift_inc: FloorPosList # FloorState # OccState -> FloorState; % gshift_inc(fps, fsa, osa) has the same meaning as shift_inc(fps, fsa), with % the exception that the first element in fps gets state osa % (auxiliary function needed by shift_inc) shift_dec: FloorPosList # FloorState -> FloorState; % shift_dec(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the left; the last element in fps gets % state free shift_inc_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_inc_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the right; % if ctw then two positions are shifted shift_dec_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_dec_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the left; % if ctw then two positions are shifted shift_inc_sps: ShuttlePosSet # FloorState -> FloorState; % shift_inc(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position downwards; the first element in sps % gets state free shift_dec_sps: ShuttlePosSet # FloorState -> FloorState; % shift_dec(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position upwards; the last element in sps gets state % free var b: Bool; fsa, fsb: FloorState; fpa, fpb: FloorPos; osa, osb: OccState; fps: FloorPosList; spa: ShuttlePos; sps: ShuttlePosSet; eqn init_fs(fpa) = free; fpa == fpb -> update(fpa, osa, fsa)(fpb) = osa; fpa != fpb -> update(fpa, osa, fsa)(fpb) = fsa(fpb); cond_upd(fpa, osa, fsa) = if(fsa(fpa) == osa, fsa, update(fpa, osa, fsa)); ins_upd(fpa, osa, init_fs) = cond_upd(fpa, osa, init_fs); lt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, update(fpb, osb, fsa)); gt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = update(fpb, osb, ins_upd(fpa, osa, fsa)); fpa == fpb -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, fsa); ins_upd_fps([], osa, fsa) = fsa; ins_upd_fps(fpa |> fps, osa, fsa) = ins_upd(fpa, osa, ins_upd_fps(fps, osa, fsa)); free([], fsa) = true; free(fpa |> fps, fsa) = fsa(fpa) == free && free(fps, fsa); occupied(fpa |> fps, fsa) = fsa(fpa) == occupied && occupied(fps, fsa); occupied([], fsa) = true; end_free(fps, col_inc, false, fsa) = fsa(head(rev(fps))) == free; end_free(fps, col_inc, true, fsa) = fsa(head(l)) == free && fsa(head(tail(l))) == free whr l = rev(fps) end; end_free(fps, col_dec, false, fsa) = fsa(head(fps)) == free; end_free(fps, col_dec, true, fsa) = fsa(head(fps)) == free && fsa(head(tail(fps))) == free; even_occ([], fsa) = true; fsa(fpa) == free -> even_occ(fpa |> fps, fsa) = even_occ(fps, fsa); fsa(fpa) == occupied -> even_occ(fpa |> fps, fsa) = !even_occ(fps, fsa); row(spa) != r1 -> no_half_car(spa, fsa) = true; row(spa) == r1 -> no_half_car(spa, fsa) = even_occ(positions(spa), fsa); no_half_car_sps([], fsa) = true; no_half_car_sps(spa |> sps, fsa) = no_half_car(spa, fsa) && no_half_car_sps(sps, fsa); shift_inc(fps, fsa) = gshift_inc(fps, fsa, free); gshift_inc([], fsa, osa) = fsa; gshift_inc([fpa], fsa, osa) = ins_upd(fpa, osa, fsa); gshift_inc(fpa |> fps, fsa, osa) = ins_upd(fpa, osa, gshift_inc(fps, fsa, fsa(fpa))); shift_dec([], fsa) = fsa; shift_dec([fpa], fsa) = ins_upd(fpa, free, fsa); shift_dec(fpa |> fpb |> fps, fsa) = ins_upd(fpa, fsa(fpb), shift_dec(fpb |> fps, fsa)); shift_inc_ctw(false, fps, fsa) = shift_inc(fps, fsa); shift_inc_ctw(true, fps, fsa) = shift_inc(fps, shift_inc(fps, fsa)); shift_dec_ctw(false, fps, fsa) = shift_dec(fps, fsa); shift_dec_ctw(true, fps, fsa) = shift_dec(fps, shift_dec(fps, fsa)); shift_inc_sps([], fsa) = fsa; row(spa) == r1 -> shift_inc_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), free, shift_inc(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_inc_sps(spa |> sps, fsa) = shift_inc(positions_sps(spa |> sps), fsa); shift_dec_sps([], fsa) = fsa; row(spa) == r1 -> shift_dec_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), fsa(head(positions(head(sps)))), shift_dec(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_dec_sps(spa |> sps, fsa) = shift_dec(positions_sps(spa |> sps), fsa); % ShuttleState operations map init_shs: ShuttleState; % initial shuttle state update: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; cond_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; ins_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; % update(spa, soa, asa, fsa) represents fsa, where position fpa in % orientation soa has value asa; cond_upd and ins_upd are auxiliary functions % with the same meaning that are needed for efficiency available: ShuttlePos # ShuttleOrientation # ShuttleState -> Bool; % available(spa, soa, shs) indicates if shuttle spa is available in % orientation soa for state shs available_sps: ShuttlePosSet # ShuttleOrientation # ShuttleState -> Bool; % available(sps, soa, shs) indicates if all shuttles in sps are available in % orientation soa for state shs shift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_inc(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle downwards in orientation soa; the first % element in sps gets state unavailable gshift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState # AvailState -> ShuttleState; % gshift_inc(sps, soa, shs, asa) has the same meaning as shift_inc(sps, soa, % shs), with the exception that the first element in sps gets state asa % (auxiliary function needed by shift_inc) shift_dec: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_dec(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle upwards in orientation soa; the last % element in sps gets state unavailable var b: Bool; shs, shsa: ShuttleState; spa, spb: ShuttlePos; sps: ShuttlePosSet; soa, sob: ShuttleOrientation; asa, asb: AvailState; eqn init_shs(spa, lowered) = if(row(spa) != r3, avail, n_avail); init_shs(spa, tilted) = if(row(spa) != r3, n_avail, avail); spa == spb && soa == sob -> update(spa, soa, asa, shs)(spb, sob) = asa; spa != spb || soa != sob -> update(spa, soa, asa, shs)(spb, sob) = shs(spb, sob); cond_upd(spa, soa, asa, shs) = if(shs(spa, soa) == asa, shs, update(spa, soa, asa, shs)); ins_upd(spa, soa, asa, init_shs) = cond_upd(spa, soa, asa, init_shs); lt(spa,spb) || (spa == spb && lt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, update(spb, sob, asb, shs)); gt(spa,spb) || (spa == spb && gt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = update(spb, sob, asb, ins_upd(spa, soa, asa, shs)); spa == spb && soa == sob -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, shs); available(spa, soa, shs) = shs(spa, soa) == avail; available_sps([], soa, shs) = true; available_sps(spa |> sps, soa, shs) = available(spa, soa, shs) && available_sps(sps, soa, shs); shift_inc(sps, soa, shs) = gshift_inc(sps, soa, shs, n_avail); gshift_inc([], soa, shs, asa) = shs; gshift_inc([spa], soa, shs, asa) = ins_upd(spa, soa, asa, shs); gshift_inc(spa |> sps, soa, shs, asa) = ins_upd(spa, soa, asa, gshift_inc(sps, soa, shs, shs(spa, soa))); shift_dec([], soa, shs) = shs; shift_dec([spa], soa, shs) = ins_upd(spa, soa, n_avail, shs); shift_dec(spa |> spb |> sps, soa, shs) = ins_upd(spa, soa, shs(spb, soa), shift_dec(spb |> sps, soa, shs)); % LiftState operations map height: LiftState -> LiftHeight; % height(ls) represents the height of state ls occupied: LiftState # FloorState -> Bool; % occupied(ls, fs) indicates if the lift is occupieed for states ls and fs make_ls: LiftHeight # OccState -> LiftState; % make_ls(lh, os) represents the lift state corresponding to height lh and % occupied state os var b: Bool; fsa: FloorState; osa: OccState; eqn height(lsf_street) = street; height(lso_street) = street; height(lsf_rotate) = rotate; height(lso_rotate) = rotate; height(ls_basement) = basement; occupied(lsf_street, fsa) = false; occupied(lso_street, fsa) = true; occupied(lsf_rotate, fsa) = false; occupied(lso_rotate, fsa) = true; occupied(ls_basement, fsa) = occupied(positions(b_r1lift), fsa); make_ls(street, occupied) = lso_street; make_ls(street, free) = lsf_street; make_ls(rotate, occupied) = lso_rotate; make_ls(rotate, free) = lsf_rotate; make_ls(basement, osa) = ls_basement; % GlobalState operations map init_gs: GlobalState; % init_gs is the initial global state allowed: Instruction # GlobalState -> Bool; % allowed(i, gs) indicates if instruction i is allowed given global state gs nextstate: Instruction # ExecResult # GlobalState -> GlobalState; % nextstate(i, r, gs) represents the global state after execution of % instruction i with result r in state gs allowed: InstructionSet # GlobalState -> Bool; % allowed(is, gs) indicates if instruction set is is allowed given global % state gs nextstate: InstructionSet # ExecResult # GlobalState -> GlobalState; % nextstate(is, r, gs) represents the global state after execution of % instruction set is with result r in state gs possible: Event # GlobalState -> Bool; % possible(e, gs) indicates if event e is possible given global state gs nextstate: Event # GlobalState -> GlobalState; % nextstate(e, gs) represents the global state after the event e has occurred % in state gs var gs, gsa: GlobalState; fs, fsa: FloorState; shs, shsa: ShuttleState; ls, lsa: LiftState; lh, lha: LiftHeight; p,q: FloorPos; s,t: OccState; i,j: Instruction; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sps: ShuttlePosSet; dr: DirRow; sp, spa, spb: ShuttlePos; so: ShuttleOrientation; is: InstructionSet; eqn init_gs = glob_state( init_fs, init_shs, lsf_street); allowed(move_belts(r1bs, dc, ms), glob_state(fs, shs, ls)) = r1bs != [] && connected_b_r1(r1bs) && available_b_r1(r1bs, shs, ls) && end_free(l, dc, ms == full, fs) && even_occ(l, fs) whr l = positions_b_r1(r1bs) end; allowed(move_belts(r2bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r2bs != [] && connected_b_r2(r2bs) && available_b_r2(r2bs, shs, ls) && end_free(positions_b_r2(r2bs), dc, false, fs); allowed(move_belts(r3bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r3bs != [] && connected_b_r3(r3bs) && available_b_r3(r3bs, shs, ls) && end_free(positions_b_r3(r3bs), dc, false, fs); allowed(move_shuttles(sps, so, dr), glob_state(fs, shs, ls)) = sps != [] && connected_sps(sps) && available_sps(sps, so, shs) && % placing a comment in front of the following conjunct allows the shuttles % to be moved even if a car is placed half on the shuttle (so == lowered => no_half_car_sps(sps, fs)) && has_neighbour(sps, dr) && !available(neighbour_sps(sps, dr), so, shs); allowed(tilt_shuttle(sp, lowered), glob_state(fs, shs, ls)) = available_sps(shuttles(col(sp)), lowered, shs) && free(positions(sp), fs); allowed(tilt_shuttle(sp, tilted), glob_state(fs, shs, ls)) = shs(sp, tilted) == avail && shs(sp, lowered) == n_avail; ls == ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls) && % replacing the following conjunct by % even_occ(positions(b_r1lift), fs); % allows the lift to move up if two cars are placed half on the lift belt if(free(positions(b_r1lift), fs), true, even_occ(positions_b_r1([b_r1a_sh, b_r1a]), fs) && even_occ(positions_b_r1([b_r1b, b_r1b_sh]), fs)); ls != ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls); allowed(rotate_lift, glob_state(fs, shs, ls)) = height(ls) == rotate && free([pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa), pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb)], fs); nextstate(move_belts(r1bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r1bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r2bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r2bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r3bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_belts(r3bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_shuttles(sps, lowered, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_sps(l, fs), shift_inc(l, lowered, shs), ls) whr l = add_neighbour(sps, row_inc) end; nextstate(move_shuttles(sps, lowered, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_sps(l, fs), shift_dec(l, lowered, shs), ls) whr l = add_neighbour(sps, row_dec) end; nextstate(move_shuttles(sps, tilted, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_inc(add_neighbour(sps, row_inc), tilted, shs), ls); nextstate(move_shuttles(sps, tilted, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_dec(add_neighbour(sps, row_dec), tilted, shs), ls); nextstate(tilt_shuttle(sp, so), ok, glob_state(fs, shs, ls)) = glob_state(fs, ins_upd(sp, so, n_avail, ins_upd(sp, not(so), avail, shs)), ls); occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state( if(height(ls) != basement && lh == basement, ins_upd_fps(positions(b_r1lift), occupied, fs), if(height(ls) == basement && lh != basement, ins_upd_fps(positions(b_r1lift), free, fs), fs ) ), shs, make_ls(lh, occupied)); !occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state(fs, shs, make_ls(lh, free)); nextstate(rotate_lift, ok, gs) = gs; nextstate(i, fail, gs) = gs; allowed([], gs) = false; allowed(i |> [], gs) = allowed(i, gs); allowed(i |> j |> is, gs) = allowed(i, gs) && !overlap(i, j |> is) && allowed(j |> is, gs); nextstate([], ok, gs) = gs; nextstate(i |> is, ok, gs) = nextstate(i, ok, nextstate(is, ok, gs)); nextstate(is, fail, gs) = gs; possible(add_car, glob_state(fs, shs, ls)) = ls == lsf_street; possible(remove_car, glob_state(fs, shs, ls)) = ls == lso_street; nextstate(add_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lso_street); nextstate(remove_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lsf_street); sort ProcState = struct ps_idle | ps_await_state | ps_ack_deny | ps_req | ps_exec | ps_ack_exec; Layer = struct logical | safety | hardware; act snd_req, rcv_req, com_req: Layer # Layer # InstructionSet; snd_ack_req, rcv_ack_req, com_ack_req: Layer # Layer # InstructionSet; snd_deny_req, rcv_deny_req, com_deny_req: Layer # Layer # InstructionSet; snd_ack_exec, rcv_ack_exec, ack_exec:Layer # Layer # InstructionSet # ExecResult; snd_state, rcv_state, com_state: Layer # Layer # GlobalState; snd_event, rcv_event, com_event: Layer # Layer # Event; proc SL(ps: ProcState, gs_sl: GlobalState, is: InstructionSet, r: ExecResult) = (ps == ps_idle) -> (sum isa: InstructionSet. valid(isa) -> rcv_req(logical, safety, isa) . SL(ps_ack_deny, gs_sl, isa, r) ) + (ps == ps_await_state) -> (sum gs: GlobalState. rcv_state(hardware, safety, gs). SL(ps_ack_deny, gs, is, r) ) + (ps == ps_ack_deny) -> (allowed(is, gs_sl) -> (snd_ack_req(safety, logical, is) . SL(ps_req, gs_sl, is, r)) <> (snd_deny_req(safety, logical, is). SL(ps_idle, gs_sl, is, r))) + (ps == ps_req) -> snd_req(safety, hardware, is) . SL(ps_exec, gs_sl, is, r) + (ps == ps_exec) -> (sum ra: ExecResult. rcv_ack_exec(safety, hardware, is, ra). SL(ps_ack_exec, nextstate(is, ra, gs_sl), is, ra) ) + (ps == ps_ack_exec) -> snd_ack_exec(safety, logical, is, r) . SL(ps_idle, gs_sl, is, r) + (ps == ps_idle) -> (sum e: Event. possible(e, gs_sl) -> rcv_event(hardware, safety, e) . SL(ps, nextstate(e, gs_sl), is, r) ) ; init SL(ps_idle, init_gs, [], ok); mcrl2-201409.0/examples/industrial/garage/movie.trc000770 001750 001750 00000005532 12370120076 022416 0ustar00outisoutis000000 000000 occur(add_car) exec(move_lift(rotate)) exec(move_lift(basement)) exec(move_belts([b_r1lift, b_r1b], col_inc, full)) exec(move_lift(street)) exec(move_belts([b_r1b], col_inc, full)) exec(move_belts([b_r1b, b_r1b_sh], col_inc, full)) exec(move_belts([b_r1b, b_r1b_sh], col_inc, half)) exec(move_shuttles([r1b, r2b], lowered, row_inc)) exec(move_belts([b_r2, b_r2b_sh], col_dec, full)) exec(move_shuttles([r2b, r3b], lowered, row_dec)) exec(move_belts([b_r2, b_r2b_sh], col_inc, full)) exec(move_shuttles([r2b], lowered, row_inc)) exec(move_belts([b_r3, b_r3b_sh], col_dec, full)) exec(move_shuttles([r3b], lowered, row_dec)) occur(add_car) exec(move_lift(basement)) exec(move_belts([b_r1lift, b_r1b], col_inc, full)) exec(move_lift(street)) exec(move_belts([b_r1b], col_inc, full)) exec(move_belts([b_r1b, b_r1b_sh], col_inc, full)) exec(move_belts([b_r1b, b_r1b_sh], col_inc, half)) exec(move_shuttles([r1b, r2b], lowered, row_inc)) exec(move_belts([b_r2, b_r2b_sh], col_dec, full)) exec(move_shuttles([r2b, r3b], lowered, row_dec)) exec(move_belts([b_r2, b_r2b_sh], col_inc, full)) exec(move_shuttles([r2b], lowered, row_inc)) exec(move_belts([b_r3, b_r3b_sh], col_dec, full)) exec(move_shuttles([r3b], lowered, row_dec)) occur(add_car) exec(move_lift(basement)) exec(move_belts([b_r1lift, b_r1b], col_inc, full)) exec(move_lift(street)) exec(move_belts([b_r1b], col_inc, full)) exec(move_belts([b_r1b, b_r1b_sh], col_inc, full)) exec(move_belts([b_r1b, b_r1b_sh], col_inc, half)) exec(move_shuttles([r1b, r2b], lowered, row_inc)) exec(move_belts([b_r2, b_r2b_sh], col_dec, full)) exec(move_shuttles([r2b, r3b], lowered, row_dec)) exec(move_belts([b_r2, b_r2b_sh], col_inc, full)) exec(move_shuttles([r2b], lowered, row_inc)) exec(move_belts([b_r3, b_r3b_sh], col_dec, full)) exec(move_shuttles([r3b], lowered, row_dec)) exec(tilt_shuttle(r3b, tilted)) exec(tilt_shuttle(r1b, lowered)) exec(move_belts([b_r3, b_r3b_sh], col_inc, full)) exec(move_shuttles([r2b, r3b], lowered, row_dec)) exec(move_belts([b_r2, b_r2b_sh], col_dec, full)) exec(move_shuttles([r2b], lowered, row_inc)) exec(move_belts([b_r3, b_r3b_sh], col_inc, full)) exec(move_shuttles([r3b], lowered, row_dec)) exec(move_belts([b_r2, b_r2b_sh], col_dec, full)) exec(move_shuttles([r1b, r2b], lowered, row_inc)) exec(move_belts([b_r2, b_r2b_sh], col_inc, full)) exec(move_shuttles([r2b, r3b], lowered, row_dec)) exec(move_belts([b_r1b, b_r1b_sh], col_dec, full)) exec(move_belts([b_r1b], col_dec, full)) exec(move_belts([b_r1b], col_dec, half)) exec(move_lift(basement)) exec(move_belts([b_r1lift, b_r1b], col_dec, full)) exec(move_lift(street)) occur(remove_car) exec(move_belts([b_r2, b_r2b_sh], col_inc, full)) exec(move_shuttles([r2b], lowered, row_inc)) exec(move_belts([b_r3, b_r3b_sh], col_dec, full)) exec(move_shuttles([r3b], lowered, row_dec)) exec(move_shuttles([r1b], tilted, row_inc)) exec(move_shuttles([r2b], tilted, row_inc)) mcrl2-201409.0/examples/industrial/garage/shuttle-error.trc000770 001750 001750 00000000432 12370120076 024110 0ustar00outisoutis000000 000000 occur(add_car) exec(move_lift(rotate)) exec(move_lift(basement)) exec(move_belts([b_r1lift, b_r1b], col_inc, full)) exec(move_lift(street)) exec(move_belts([b_r1b], col_inc, full)) exec(move_belts([b_r1b, b_r1b_sh], col_inc, full)) exec(move_shuttles([r1b, r2b], lowered, row_inc)) mcrl2-201409.0/examples/industrial/garage/garage-r3.mcrl2000770 001750 001750 00000113663 12370120076 023303 0ustar00outisoutis000000 000000 % The following is the specification of the safety layer of the automated % parking garage after reduction 3 as described in [1, Appendix D.1]. % % Simulation and state space generation are possible. The state space consists % of 3,3 * 10^6 (3,3 million) states and 9,8 * 10^7 (98 million) transitions. % % [1] Aad Mathijssen and A. Johannes Pretorius. Specification, Analysis and % Verification of an Automated Parking Garage. Computer Science Report % 05-25, Eindhoven University of Technology (TU/e), 2005. sort FloorRow = struct r1 | r2 | r3; FloorCol = struct c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10; FloorPosPart = struct pa | pb; FloorPos = struct pos_r1(FloorCol, FloorPosPart) | pos_r2(FloorCol) | pos_r3(FloorCol); FloorPosList = List(FloorPos); ShuttlePos = struct r1a | r2a | r3a | r1b | r2b | r3b; ShuttlePosSet = List(ShuttlePos); % representing a set of ShuttlePos elements ShuttleOrientation = struct lowered | tilted; R1Belt = struct b_r1a_sh | b_r1a | b_r1lift | b_r1b | b_r1b_sh; R2Belt = struct b_r2a_sh | b_r2 | b_r2b_sh; R3Belt = struct b_r3a_sh | b_r3 | b_r3b_sh; R1BeltSet = List(R1Belt); % representing a set of R1Belt elements R2BeltSet = List(R2Belt); % representing a set of R2Belt elements R3BeltSet = List(R3Belt); % representing a set of R3Belt elements DirCol = struct col_inc | col_dec; DirRow = struct row_inc | row_dec; MoveSize = struct full | half; LiftHeight = struct street | rotate | basement; Area = struct area(positions: FloorPosList, tilted_c1: Bool, tilted_c10: Bool); Instruction = struct move_belts(R1BeltSet, DirCol, MoveSize) | move_belts(R2BeltSet, DirCol, MoveSize) | move_belts(R3BeltSet, DirCol, MoveSize) | move_shuttles(ShuttlePosSet, ShuttleOrientation, DirRow) | tilt_shuttle(ShuttlePos, ShuttleOrientation) | move_lift(LiftHeight) | rotate_lift; InstructionSet = List(Instruction); % representing a set of instructions Event = struct add_car | remove_car; ExecResult = struct ok | fail; OccState = struct free | occupied; AvailState = struct avail | n_avail; FloorState = FloorPos -> OccState; ShuttleState = ShuttlePos # ShuttleOrientation -> AvailState; LiftState = struct lsf_street | lso_street | lsf_rotate | lso_rotate | ls_basement; GlobalState = struct glob_state(fs: FloorState, shs: ShuttleState, ls: LiftState); % FloorRow operations map index: FloorRow -> Pos; % index(fra) is the index of fra lt: FloorRow # FloorRow -> Bool; % lt(fra,frb) indicates if fra is less than frb var fra, frb: FloorRow; eqn index(r1) = 1; index(r2) = 2; index(r3) = 3; lt(fra, frb) = index(fra) < index(frb); % FloorCol operations map index: FloorCol -> Pos; % index(fca) is the index of fca lt: FloorCol # FloorCol -> Bool; % lt(fca,fcb) indicates if fca is less than fcb var fca, fcb: FloorCol; eqn index(c1) = 1; index(c2) = 2; index(c3) = 3; index(c4) = 4; index(c5) = 5; index(c6) = 6; index(c7) = 7; index(c8) = 8; index(c9) = 9; index(c10) = 10; lt(fca, fcb) = index(fca) < index(fcb); % FloorPosPart operations map index: FloorPosPart -> Pos; % index(ffpa) is the index of fppa lt: FloorPosPart # FloorPosPart -> Bool; % lt(fppa,fppb) indicates if fppa is less than fppb var fppa, fppb: FloorPosPart; eqn index(pa) = 1; index(pb) = 2; lt(fppa, fppb) = index(fppa) < index(fppb); % FloorPos operations map row: FloorPos -> FloorRow; % row(fpa) is the row of fpa col: FloorPos -> FloorCol; % col(fpa) is the column of fpa part: FloorPos -> FloorPosPart; % part(fpa) is the part of fpa lt: FloorPos # FloorPos -> Bool; % lt(fpa, fpb) indicates if fpa is less than fpb lt_r: FloorPos # FloorPos -> Bool; % lt_r(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) (auxiliary function needed by lt for efficiency) lt_rc: FloorPos # FloorPos -> Bool; % lt_rc(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) and col(fpa) = col(fpb) % (auxiliary function needed by lt_r for efficiency) gt: FloorPos # FloorPos -> Bool; % gt(fpa, fpb) indicates if fpa is greater than fpb var fca: FloorCol; fppa: FloorPosPart; fpa, fpb: FloorPos; eqn row(pos_r1(fca, fppa)) = r1; row(pos_r2(fca)) = r2; row(pos_r3(fca)) = r3; col(pos_r1(fca, fppa)) = fca; col(pos_r2(fca)) = fca; col(pos_r3(fca)) = fca; part(pos_r1(fca, fppa)) = fppa; row(fpa) == row(fpb) -> lt(fpa, fpb) = lt_r(fpa, fpb); row(fpa) != row(fpb) -> lt(fpa, fpb) = lt(row(fpa), row(fpb)); col(fpa) == col(fpb) -> lt_r(fpa, fpb) = lt_rc(fpa, fpb); col(fpa) != col(fpb) -> lt_r(fpa, fpb) = lt(col(fpa), col(fpb)); lt_rc(fpa, fpb) = row(fpa) == r1 && lt(part(fpa), part(fpb)); gt(fpa,fpb) = lt(fpb, fpa); % FloorPosList operations map contains: FloorPos # FloorPosList -> Bool; % contains(fpa, fps) indicates if fps contains fpa overlap: FloorPosList # FloorPosList -> Bool; % overlap(fps, fpt) indicates if the elements of fps and fpt overlap rev: FloorPosList -> FloorPosList; % rev(fps) is the reverse of list fps grev: FloorPosList # FloorPosList -> FloorPosList; % grev(fps, fpt) is the reverse of fps concatenated with fpt % (auxiliary function needed for efficiency by rev) var fpa, fpb: FloorPos; fps, fpt: FloorPosList; eqn contains(fpa, []) = false; contains(fpa, fpa |> fps) = true; fpa != fpb -> contains(fpa, fpb |> fps) = contains(fpa, fps); overlap([], fpt) = false; overlap(fpa |> fps, fpt) = contains(fpa, fpt) || overlap(fps, fpt); rev(fps) = grev(fps, []); grev([], fpt) = fpt; grev(fpa |> fps, fpt) = grev(fps, fpa |> fpt); % ShuttlePos operations map index: ShuttlePos -> Pos; % index(spa) is the index of spa row: ShuttlePos -> FloorRow; % row(spa) is the row of spa col: ShuttlePos -> FloorCol; % col(spa) is the column of spa lt: ShuttlePos # ShuttlePos -> Bool; % lt(spa, spb) indicates if spa is less than spb gt: ShuttlePos # ShuttlePos -> Bool; % gt(spa, spb) indicates if spa is greater than spb positions: ShuttlePos -> FloorPosList; % positions(spa) represents the floor positions corresponding to spa in % lowered position has_neighbour: ShuttlePos # DirRow -> Bool; % has_neighbour(spa, dr) indicates if spa has a successor in direction dr neighbour: ShuttlePos # DirRow -> ShuttlePos; % neighbour(spa, dr) is the neighbour of spa in directrion dr, provided it % exists connected: ShuttlePos # ShuttlePos -> Bool; % connected(spa, spb) indicates if the bottom of spa is connected to the top % of spb var spa, spb: ShuttlePos; eqn index(r1a) = 1; index(r2a) = 2; index(r3a) = 3; index(r1b) = 4; index(r2b) = 5; index(r3b) = 6; row(r1a) = r1; row(r2a) = r2; row(r3a) = r3; row(r1b) = r1; row(r2b) = r2; row(r3b) = r3; col(r1a) = c1; col(r2a) = c1; col(r3a) = c1; col(r1b) = c10; col(r2b) = c10; col(r3b) = c10; lt(spa, spb) = index(spa) < index(spb); gt(spa, spb) = index(spa) > index(spb); positions(r1a) = positions(b_r1a_sh); positions(r2a) = positions(b_r2a_sh); positions(r3a) = positions(b_r3a_sh); positions(r1b) = positions(b_r1b_sh); positions(r2b) = positions(b_r2b_sh); positions(r3b) = positions(b_r3b_sh); has_neighbour(spa, row_inc) = row(spa) != r3; has_neighbour(spa, row_dec) = row(spa) != r1; neighbour(r1a, row_inc) = r2a; neighbour(r2a, row_inc) = r3a; neighbour(r1b, row_inc) = r2b; neighbour(r2b, row_inc) = r3b; neighbour(r2a, row_dec) = r1a; neighbour(r3a, row_dec) = r2a; neighbour(r2b, row_dec) = r1b; neighbour(r3b, row_dec) = r2b; connected(spa, spb) = succ(index(spa)) == index(spb) && col(spa) == col(spb); % ShuttlePosSet operations map is_set_sps: ShuttlePosSet -> Bool; % is_set_sps(sps) indicates if sps is a set % In the remainder of the data equation section, for every ShuttlePosSet sps % is_set_sps(sps) is a precondition. contains: ShuttlePos # ShuttlePosSet -> Bool; % contains(spa, sps) indicates if sps contains spa shuttles: FloorCol -> ShuttlePosSet; % shuttles(fc) represents the shuttle positions corresponding to fc positions_sps: ShuttlePosSet -> FloorPosList; % positions_sps(sps) represents the floor positions corresponding to sps connected_sps: ShuttlePosSet -> Bool; % connected_sps(sps) indicates if all elements of sps are connected has_neighbour: ShuttlePosSet # DirRow -> Bool; % has_neighbour(sps, dr) indicates is sps has a neighbour in direction dr neighbour_sps: ShuttlePosSet # DirRow -> ShuttlePos; % neighbour_sps(sps, dr) is the neighbour of sps in direction dr, provided it % exists add_neighbour: ShuttlePosSet # DirRow -> ShuttlePosSet; % add_neighbour(sps, dr) represents the sps extended with its neighbour in % direction dr, provided it exists var spa, spb: ShuttlePos; sps: ShuttlePosSet; fc: FloorCol; eqn is_set_sps([]) = true; is_set_sps(spa |> []) = true; is_set_sps(spa |> spb |> sps) = lt(spa, spb) && is_set_sps(spb |> sps); contains(spa, []) = false; contains(spa, spa |> sps) = true; spa != spb -> contains(spa, spb |> sps) = contains(spa, sps); shuttles(fc) = if(fc == c1, [r1a,r2a,r3a], if(fc == c10, [r1b,r2b,r3b], [])); positions_sps([]) = []; positions_sps(spa |> sps) = positions(spa) ++ positions_sps(sps); connected_sps([]) = true; connected_sps([spa]) = true; connected_sps(spa |> spb |> sps) = connected(spa, spb) && connected_sps(spb |> sps); has_neighbour(sps, row_inc) = has_neighbour(rhead(sps), row_inc); has_neighbour(sps, row_dec) = has_neighbour(head(sps), row_dec); neighbour_sps(sps, row_inc) = neighbour(rhead(sps), row_inc); neighbour_sps(sps, row_dec) = neighbour(head(sps), row_dec); add_neighbour(sps, row_inc) = sps <| neighbour_sps(sps, row_inc); add_neighbour(sps, row_dec) = neighbour_sps(sps, row_dec) |> sps; % ShuttleOrientation operations map index: ShuttleOrientation -> Pos; % index(soa) is the index of soa lt: ShuttleOrientation # ShuttleOrientation -> Bool; % lt(soa, sob) indicates if soa is less than sob gt: ShuttleOrientation # ShuttleOrientation -> Bool; % gt(soa, sob) indicates if soa is greater than sob not: ShuttleOrientation -> ShuttleOrientation; % not(soa) indicates the opposite of soa var soa, sob: ShuttleOrientation; eqn index(lowered) = 1; index(tilted) = 2; lt(soa, sob) = index(soa) < index(sob); gt(soa, sob) = index(soa) > index(sob); not(lowered) = tilted; not(tilted) = lowered; % Belt operations map index: R1Belt -> Pos; index: R2Belt -> Pos; index: R3Belt -> Pos; % index(ba) is the index of belt ba row: R1Belt -> FloorRow; row: R2Belt -> FloorRow; row: R3Belt -> FloorRow; % row(ba) is the row of belt ba lt: R1Belt # R1Belt -> Bool; lt: R2Belt # R2Belt -> Bool; lt: R3Belt # R3Belt -> Bool; % lt(ba, bb) indicates if belt ba is less than belt bb positions: R1Belt -> FloorPosList; positions: R2Belt -> FloorPosList; positions: R3Belt -> FloorPosList; % positions(ba) represents the positions corresponding to belt ba connected: R1Belt # R1Belt -> Bool; connected: R2Belt # R2Belt -> Bool; connected: R3Belt # R3Belt -> Bool; % connected(ba, bb) indicates if the right of ba is connected to the left % of bb available: R1Belt # ShuttleState # LiftState -> Bool; available: R2Belt # ShuttleState # LiftState -> Bool; available: R3Belt # ShuttleState # LiftState -> Bool; % available(ba, shs, ls) indicates if belt ba is available for states shs % and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; fs: FloorState; shs: ShuttleState; ls: LiftState; ms: MoveSize; eqn index(b_r1a_sh) = 1; index(b_r1a) = 2; index(b_r1lift) = 3; index(b_r1b) = 4; index(b_r1b_sh) = 5; index(b_r2a_sh) = 1; index(b_r2) = 2; index(b_r2b_sh) = 3; index(b_r3a_sh) = 1; index(b_r3) = 2; index(b_r3b_sh) = 3; row(r1ba) = r1; row(r2ba) = r2; row(r3ba) = r3; lt(r1ba, r1bb) = index(r1ba) < index(r1bb); lt(r2ba, r2bb) = index(r2ba) < index(r2bb); lt(r3ba, r3bb) = index(r3ba) < index(r3bb); positions(b_r1a_sh) = [pos_r1(c1, pa), pos_r1(c1, pb)]; positions(b_r1a) = [pos_r1(c2, pa), pos_r1(c2, pb), %pos_r1(c3, pa), pos_r1(c3, pb), %pos_r1(c4, pa), pos_r1(c4, pb), %pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa)]; positions(b_r1lift) = [pos_r1(c6, pb), pos_r1(c7, pa)]; positions(b_r1b) = [pos_r1(c7, pb), %pos_r1(c8, pa), pos_r1(c8, pb), pos_r1(c9, pa), pos_r1(c9, pb)]; positions(b_r1b_sh) = [pos_r1(c10, pa), pos_r1(c10, pb)]; positions(b_r2a_sh) = [pos_r2(c1)]; positions(b_r2) = [pos_r2(c2), %pos_r2(c3), %pos_r2(c4), %pos_r2(c5), %pos_r2(c6), %pos_r2(c7), %pos_r2(c8), pos_r2(c9)]; positions(b_r2b_sh) = [pos_r2(c10)]; positions(b_r3a_sh) = [pos_r3(c1)]; positions(b_r3) = [pos_r3(c2), %pos_r3(c3), %pos_r3(c4), %pos_r3(c5), %pos_r3(c6), %pos_r3(c7), %pos_r3(c8), pos_r3(c9)]; positions(b_r3b_sh) = [pos_r3(c10)]; available(b_r1a_sh, shs, ls) = shs(r1a, lowered) == avail; available(b_r1a, shs, ls) = true; available(b_r1lift, shs, ls) = ls == ls_basement; available(b_r1b, shs, ls) = true; available(b_r1b_sh, shs, ls) = shs(r1b, lowered) == avail; available(b_r2a_sh, shs, ls) = shs(r2a, lowered) == avail; available(b_r2, shs, ls) = true; available(b_r2b_sh, shs, ls) = shs(r2b, lowered) == avail; available(b_r3a_sh, shs, ls) = shs(r3a, lowered) == avail; available(b_r3, shs, ls) = true; available(b_r3b_sh, shs, ls) = shs(r3b, lowered) == avail; % BeltSet operations map is_set_b_r1: R1BeltSet -> Bool; is_set_b_r2: R2BeltSet -> Bool; is_set_b_r3: R3BeltSet -> Bool; % is_set_b_rX(bs) indicates if bs is a set % In the remainder of this data equations section each belt set bs has % is_set_b_rX(bs) as a precondition. contains: R1Belt # R1BeltSet -> Bool; contains: R2Belt # R2BeltSet -> Bool; contains: R3Belt # R3BeltSet -> Bool; % contains(ba, bs) indicates if ba is an element of bs positions_b_r1: R1BeltSet -> FloorPosList; positions_b_r2: R2BeltSet -> FloorPosList; positions_b_r3: R3BeltSet -> FloorPosList; % positions_b_rX(bs) represents the floor positions corresponding to the % belts in bs connected_b_r1: R1BeltSet -> Bool; connected_b_r2: R2BeltSet -> Bool; connected_b_r3: R3BeltSet -> Bool; % connected(bs) indicates if the belts in bs are connected available_b_r1: R1BeltSet # ShuttleState # LiftState -> Bool; available_b_r2: R2BeltSet # ShuttleState # LiftState -> Bool; available_b_r3: R3BeltSet # ShuttleState # LiftState -> Bool; % available_b_rX(bs, shs, ls) indicates if all belts in bs are available for % states shs and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; fs: FloorState; shs: ShuttleState; ls: LiftState; eqn is_set_b_r1([]) = true; is_set_b_r1(r1ba |> []) = true; is_set_b_r1(r1ba |> r1bb |> r1bs) = lt(r1ba, r1bb) && is_set_b_r1(r1bb |> r1bs); is_set_b_r2([]) = true; is_set_b_r2(r2ba |> []) = true; is_set_b_r2(r2ba |> r2bb |> r2bs) = lt(r2ba, r2bb) && is_set_b_r2(r2bb |> r2bs); is_set_b_r3([]) = true; is_set_b_r3(r3ba |> []) = true; is_set_b_r3(r3ba |> r3bb |> r3bs) = lt(r3ba, r3bb) && is_set_b_r3(r3bb |> r3bs); contains(r1ba, []) = false; contains(r1ba, r1ba |> r1bs) = true; r1ba != r1bb -> contains(r1ba, r1bb |> r1bs) = contains(r1ba, r1bs); contains(r2ba, []) = false; contains(r2ba, r2ba |> r2bs) = true; r2ba != r2bb -> contains(r2ba, r2bb |> r2bs) = contains(r2ba, r2bs); contains(r3ba, []) = false; contains(r3ba, r3ba |> r3bs) = true; r3ba != r3bb -> contains(r3ba, r3bb |> r3bs) = contains(r3ba, r3bs); positions_b_r1([]) = []; positions_b_r1(r1ba |> r1bs) = positions(r1ba) ++ positions_b_r1(r1bs); positions_b_r2([]) = []; positions_b_r2(r2ba |> r2bs) = positions(r2ba) ++ positions_b_r2(r2bs); positions_b_r3([]) = []; positions_b_r3(r3ba |> r3bs) = positions(r3ba) ++ positions_b_r3(r3bs); connected_b_r1([]) = true; connected_b_r1(r1ba |> []) = true; connected_b_r1(r1ba |> r1bb |> r1bs) = connected(r1ba, r1bb) && connected_b_r1(r1bb |> r1bs); connected_b_r2([]) = true; connected_b_r2(r2ba |> []) = true; connected_b_r2(r2ba |> r2bb |> r2bs) = connected(r2ba, r2bb) && connected_b_r2(r2bb |> r2bs); connected_b_r3([]) = true; connected_b_r3(r3ba |> []) = true; connected_b_r3(r3ba |> r3bb |> r3bs) = connected(r3ba, r3bb) && connected_b_r3(r3bb |> r3bs); connected(r1ba, r1bb) = succ(index(r1ba)) == index(r1bb); connected(r2ba, r2bb) = succ(index(r2ba)) == index(r2bb); connected(r3ba, r3bb) = succ(index(r3ba)) == index(r3bb); available_b_r1([], shs, ls) = true; available_b_r1(r1ba |> r1bs, shs, ls) = available(r1ba, shs, ls) && available_b_r1(r1bs, shs, ls); available_b_r2([], shs, ls) = true; available_b_r2(r2ba |> r2bs, shs, ls) = available(r2ba, shs, ls) && available_b_r2(r2bs, shs, ls); available_b_r3([], shs, ls) = true; available_b_r3(r3ba |> r3bs, shs, ls) = available(r3ba, shs, ls) && available_b_r3(r3bs, shs, ls); % Area operations map overlap: Area # Area -> Bool; % area(a, b) indicates if area a and b overlap var fps, fpt: FloorPosList; tc1a, tc1b, tc10a, tc10b: Bool; eqn overlap(area(fps, tc1a, tc1b), area(fpt, tc10a, tc10b)) = overlap(fps, fpt) || (tc1a && tc1b) || (tc10a && tc10b); % Instruction operations map index: Instruction -> Pos; % index(i) is the index of instruction i lt: Instruction # Instruction -> Bool; % lt(i, j) indicates if i is less than j valid: Instruction -> Bool; % valid(i) indicates if instruction i is valid area: Instruction -> Area; % area(i) represents the area on which instruction i has any effect overlap: Instruction # Instruction -> Bool; % overlap(i, j) indicates if instruction i and j overlap var r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sp: ShuttlePos; sps: ShuttlePosSet; so: ShuttleOrientation; dr: DirRow; lh: LiftHeight; i,j: Instruction; eqn index(move_belts(r1bs, dc, ms)) = 1; index(move_belts(r2bs, dc, ms)) = 2; index(move_belts(r3bs, dc, ms)) = 3; index(move_shuttles(sps, so, dr)) = 4; index(tilt_shuttle(sp, so)) = 5; index(move_lift(lh)) = 6; index(rotate_lift) = 7; lt(i, j) = index(i) < index(j); valid(move_belts(r1bs, dc, ms)) = is_set_b_r1(r1bs); valid(move_belts(r2bs, dc, ms)) = is_set_b_r2(r2bs); valid(move_belts(r3bs, dc, ms)) = is_set_b_r3(r3bs); valid(move_shuttles(sps, so, dr)) = is_set_sps(sps); valid(tilt_shuttle(sp, so)) = true; valid(move_lift(lh)) = true; valid(rotate_lift) = true; area(move_belts(r1bs, dc, ms)) = area(positions_b_r1(r1bs), false, false); area(move_belts(r2bs, dc, ms)) = area(positions_b_r2(r2bs), false, false); area(move_belts(r3bs, dc, ms)) = area(positions_b_r3(r3bs), false, false); area(move_shuttles(sps, lowered, dr)) = area(positions_sps(add_neighbour(sps, dr)), false, false); area(move_shuttles(sps, tilted, dr)) = area([], col(head(sps)) == c1, col(head(sps)) == c10); area(tilt_shuttle(sp, so)) = area(positions(sp), col(sp) == c1, col(sp) == c10); area(move_lift(lh)) = area(positions(b_r1lift), false, false); area(rotate_lift) = area(positions_b_r1([b_r1a, b_r1lift, b_r1b]), false, false); overlap(i, j) = overlap(area(i), area(j)); % InstructionSet operations map is_set_is: InstructionSet -> Bool; % is_set_is(is) indicates if is is a set % In the remainder of the data equation section, for every InstructionSet is % is_set_is(is) is a precondition. valid: InstructionSet -> Bool; % valid(is) indicates if the instructions in is are valid overlap: Instruction # InstructionSet -> Bool; % overlap(i, is) indicates if instruction i overlaps with any of the % instructions in is var i,j: Instruction; is: InstructionSet; eqn is_set_is([]) = true; is_set_is(i |> []) = true; is_set_is(i |> j |> is) = lt(i, j) && is_set_is(j |> is); valid([]) = true; valid(i |> is) = valid(i) && valid(is); overlap(i, []) = false; overlap(i, j |> is) = overlap(i, j) || overlap(i, is); % AvailState operations map not: AvailState -> AvailState; % not(asa) indicates the opposite of asa eqn not(avail) = n_avail; not(n_avail) = avail; % FloorState operations map init_fs: FloorState; % init_fs is the initial floor state update: FloorPos # OccState # FloorState -> FloorState; cond_upd: FloorPos # OccState # FloorState -> FloorState; ins_upd: FloorPos # OccState # FloorState -> FloorState; % update(fpa, osa, fsa) represents fsa, where position fpa has value osa; % cond_upd and ins_upd are auxiliary functions with the same meaning that % are needed for efficiency ins_upd_fps: FloorPosList # OccState # FloorState -> FloorState; % ins_upd_fps(fps, osa, fsa) represents fsa, where positions fps have value % osa free: FloorPosList # FloorState -> Bool; % free(fps, fsa) indicates that all positions in fps are free for state fsa occupied: FloorPosList # FloorState -> Bool; % occupied(fps, fsa) indicates that all positions in fps are occupied for % state fsa end_free: FloorPosList # DirCol # Bool # FloorState -> Bool; % end_free(fps, dc, obl, fsa) indicates if the end of the list fps in % direction dc is free for state fsa; if obl then the one but last element % also needs to be free even_occ: FloorPosList # FloorState -> Bool; % even_occ(fps, fsa) indicates if the number of occupied positions in fps for % state fsa is even no_half_car: ShuttlePos # FloorState -> Bool; % no_half_car(spa, fsa) indicates if there is a half car positioned on spa % for state fsa no_half_car_sps: ShuttlePosSet # FloorState -> Bool; % no_half_car(sps, fsa) indicates if there is a half car positioned on any % of the elements of sps for state fsa shift_inc: FloorPosList # FloorState -> FloorState; % shift_inc(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the right; the first element in fps % gets state free gshift_inc: FloorPosList # FloorState # OccState -> FloorState; % gshift_inc(fps, fsa, osa) has the same meaning as shift_inc(fps, fsa), with % the exception that the first element in fps gets state osa % (auxiliary function needed by shift_inc) shift_dec: FloorPosList # FloorState -> FloorState; % shift_dec(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the left; the last element in fps gets % state free shift_inc_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_inc_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the right; % if ctw then two positions are shifted shift_dec_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_dec_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the left; % if ctw then two positions are shifted shift_inc_sps: ShuttlePosSet # FloorState -> FloorState; % shift_inc(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position downwards; the first element in sps % gets state free shift_dec_sps: ShuttlePosSet # FloorState -> FloorState; % shift_dec(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position upwards; the last element in sps gets state % free var b: Bool; fsa, fsb: FloorState; fpa, fpb: FloorPos; osa, osb: OccState; fps: FloorPosList; spa: ShuttlePos; sps: ShuttlePosSet; eqn init_fs(fpa) = free; fpa == fpb -> update(fpa, osa, fsa)(fpb) = osa; fpa != fpb -> update(fpa, osa, fsa)(fpb) = fsa(fpb); cond_upd(fpa, osa, fsa) = if(fsa(fpa) == osa, fsa, update(fpa, osa, fsa)); ins_upd(fpa, osa, init_fs) = cond_upd(fpa, osa, init_fs); lt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, update(fpb, osb, fsa)); gt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = update(fpb, osb, ins_upd(fpa, osa, fsa)); fpa == fpb -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, fsa); ins_upd_fps([], osa, fsa) = fsa; ins_upd_fps(fpa |> fps, osa, fsa) = ins_upd(fpa, osa, ins_upd_fps(fps, osa, fsa)); free([], fsa) = true; free(fpa |> fps, fsa) = fsa(fpa) == free && free(fps, fsa); occupied(fpa |> fps, fsa) = fsa(fpa) == occupied && occupied(fps, fsa); occupied([], fsa) = true; end_free(fps, col_inc, false, fsa) = fsa(head(rev(fps))) == free; end_free(fps, col_inc, true, fsa) = fsa(head(l)) == free && fsa(head(tail(l))) == free whr l = rev(fps) end; end_free(fps, col_dec, false, fsa) = fsa(head(fps)) == free; end_free(fps, col_dec, true, fsa) = fsa(head(fps)) == free && fsa(head(tail(fps))) == free; even_occ([], fsa) = true; fsa(fpa) == free -> even_occ(fpa |> fps, fsa) = even_occ(fps, fsa); fsa(fpa) == occupied -> even_occ(fpa |> fps, fsa) = !even_occ(fps, fsa); row(spa) != r1 -> no_half_car(spa, fsa) = true; row(spa) == r1 -> no_half_car(spa, fsa) = even_occ(positions(spa), fsa); no_half_car_sps([], fsa) = true; no_half_car_sps(spa |> sps, fsa) = no_half_car(spa, fsa) && no_half_car_sps(sps, fsa); shift_inc(fps, fsa) = gshift_inc(fps, fsa, free); gshift_inc([], fsa, osa) = fsa; gshift_inc([fpa], fsa, osa) = ins_upd(fpa, osa, fsa); gshift_inc(fpa |> fps, fsa, osa) = ins_upd(fpa, osa, gshift_inc(fps, fsa, fsa(fpa))); shift_dec([], fsa) = fsa; shift_dec([fpa], fsa) = ins_upd(fpa, free, fsa); shift_dec(fpa |> fpb |> fps, fsa) = ins_upd(fpa, fsa(fpb), shift_dec(fpb |> fps, fsa)); shift_inc_ctw(false, fps, fsa) = shift_inc(fps, fsa); shift_inc_ctw(true, fps, fsa) = shift_inc(fps, shift_inc(fps, fsa)); shift_dec_ctw(false, fps, fsa) = shift_dec(fps, fsa); shift_dec_ctw(true, fps, fsa) = shift_dec(fps, shift_dec(fps, fsa)); shift_inc_sps([], fsa) = fsa; row(spa) == r1 -> shift_inc_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), free, shift_inc(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_inc_sps(spa |> sps, fsa) = shift_inc(positions_sps(spa |> sps), fsa); shift_dec_sps([], fsa) = fsa; row(spa) == r1 -> shift_dec_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), fsa(head(positions(head(sps)))), shift_dec(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_dec_sps(spa |> sps, fsa) = shift_dec(positions_sps(spa |> sps), fsa); % ShuttleState operations map init_shs: ShuttleState; % initial shuttle state update: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; cond_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; ins_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; % update(spa, soa, asa, fsa) represents fsa, where position fpa in % orientation soa has value asa; cond_upd and ins_upd are auxiliary functions % with the same meaning that are needed for efficiency available: ShuttlePos # ShuttleOrientation # ShuttleState -> Bool; % available(spa, soa, shs) indicates if shuttle spa is available in % orientation soa for state shs available_sps: ShuttlePosSet # ShuttleOrientation # ShuttleState -> Bool; % available(sps, soa, shs) indicates if all shuttles in sps are available in % orientation soa for state shs shift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_inc(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle downwards in orientation soa; the first % element in sps gets state unavailable gshift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState # AvailState -> ShuttleState; % gshift_inc(sps, soa, shs, asa) has the same meaning as shift_inc(sps, soa, % shs), with the exception that the first element in sps gets state asa % (auxiliary function needed by shift_inc) shift_dec: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_dec(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle upwards in orientation soa; the last % element in sps gets state unavailable var b: Bool; shs, shsa: ShuttleState; spa, spb: ShuttlePos; sps: ShuttlePosSet; soa, sob: ShuttleOrientation; asa, asb: AvailState; eqn init_shs(spa, lowered) = if(row(spa) != r3, avail, n_avail); init_shs(spa, tilted) = if(row(spa) != r3, n_avail, avail); spa == spb && soa == sob -> update(spa, soa, asa, shs)(spb, sob) = asa; spa != spb || soa != sob -> update(spa, soa, asa, shs)(spb, sob) = shs(spb, sob); cond_upd(spa, soa, asa, shs) = if(shs(spa, soa) == asa, shs, update(spa, soa, asa, shs)); ins_upd(spa, soa, asa, init_shs) = cond_upd(spa, soa, asa, init_shs); lt(spa,spb) || (spa == spb && lt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, update(spb, sob, asb, shs)); gt(spa,spb) || (spa == spb && gt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = update(spb, sob, asb, ins_upd(spa, soa, asa, shs)); spa == spb && soa == sob -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, shs); available(spa, soa, shs) = shs(spa, soa) == avail; available_sps([], soa, shs) = true; available_sps(spa |> sps, soa, shs) = available(spa, soa, shs) && available_sps(sps, soa, shs); shift_inc(sps, soa, shs) = gshift_inc(sps, soa, shs, n_avail); gshift_inc([], soa, shs, asa) = shs; gshift_inc([spa], soa, shs, asa) = ins_upd(spa, soa, asa, shs); gshift_inc(spa |> sps, soa, shs, asa) = ins_upd(spa, soa, asa, gshift_inc(sps, soa, shs, shs(spa, soa))); shift_dec([], soa, shs) = shs; shift_dec([spa], soa, shs) = ins_upd(spa, soa, n_avail, shs); shift_dec(spa |> spb |> sps, soa, shs) = ins_upd(spa, soa, shs(spb, soa), shift_dec(spb |> sps, soa, shs)); % LiftState operations map height: LiftState -> LiftHeight; % height(ls) represents the height of state ls occupied: LiftState # FloorState -> Bool; % occupied(ls, fs) indicates if the lift is occupieed for states ls and fs make_ls: LiftHeight # OccState -> LiftState; % make_ls(lh, os) represents the lift state corresponding to height lh and % occupied state os var b: Bool; fsa: FloorState; osa: OccState; eqn height(lsf_street) = street; height(lso_street) = street; height(lsf_rotate) = rotate; height(lso_rotate) = rotate; height(ls_basement) = basement; occupied(lsf_street, fsa) = false; occupied(lso_street, fsa) = true; occupied(lsf_rotate, fsa) = false; occupied(lso_rotate, fsa) = true; occupied(ls_basement, fsa) = occupied(positions(b_r1lift), fsa); make_ls(street, occupied) = lso_street; make_ls(street, free) = lsf_street; make_ls(rotate, occupied) = lso_rotate; make_ls(rotate, free) = lsf_rotate; make_ls(basement, osa) = ls_basement; % GlobalState operations map init_gs: GlobalState; % init_gs is the initial global state allowed: Instruction # GlobalState -> Bool; % allowed(i, gs) indicates if instruction i is allowed given global state gs nextstate: Instruction # ExecResult # GlobalState -> GlobalState; % nextstate(i, r, gs) represents the global state after execution of % instruction i with result r in state gs allowed: InstructionSet # GlobalState -> Bool; % allowed(is, gs) indicates if instruction set is is allowed given global % state gs nextstate: InstructionSet # ExecResult # GlobalState -> GlobalState; % nextstate(is, r, gs) represents the global state after execution of % instruction set is with result r in state gs possible: Event # GlobalState -> Bool; % possible(e, gs) indicates if event e is possible given global state gs nextstate: Event # GlobalState -> GlobalState; % nextstate(e, gs) represents the global state after the event e has occurred % in state gs var gs, gsa: GlobalState; fs, fsa: FloorState; shs, shsa: ShuttleState; ls, lsa: LiftState; lh, lha: LiftHeight; p,q: FloorPos; s,t: OccState; i,j: Instruction; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sps: ShuttlePosSet; dr: DirRow; sp, spa, spb: ShuttlePos; so: ShuttleOrientation; is: InstructionSet; eqn init_gs = glob_state( init_fs, init_shs, lsf_street); allowed(move_belts(r1bs, dc, ms), glob_state(fs, shs, ls)) = r1bs != [] && connected_b_r1(r1bs) && available_b_r1(r1bs, shs, ls) && end_free(l, dc, ms == full, fs) && even_occ(l, fs) whr l = positions_b_r1(r1bs) end; allowed(move_belts(r2bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r2bs != [] && connected_b_r2(r2bs) && available_b_r2(r2bs, shs, ls) && end_free(positions_b_r2(r2bs), dc, false, fs); allowed(move_belts(r3bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r3bs != [] && connected_b_r3(r3bs) && available_b_r3(r3bs, shs, ls) && end_free(positions_b_r3(r3bs), dc, false, fs); allowed(move_shuttles(sps, so, dr), glob_state(fs, shs, ls)) = sps != [] && connected_sps(sps) && available_sps(sps, so, shs) && % placing a comment in front of the following conjunct allows the shuttles % to be moved even if a car is placed half on the shuttle (so == lowered => no_half_car_sps(sps, fs)) && has_neighbour(sps, dr) && !available(neighbour_sps(sps, dr), so, shs); allowed(tilt_shuttle(sp, lowered), glob_state(fs, shs, ls)) = available_sps(shuttles(col(sp)), lowered, shs) && free(positions(sp), fs); allowed(tilt_shuttle(sp, tilted), glob_state(fs, shs, ls)) = shs(sp, tilted) == avail && shs(sp, lowered) == n_avail; ls == ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls) && % replacing the following conjunct by % even_occ(positions(b_r1lift), fs); % allows the lift to move up if two cars are placed half on the lift belt if(free(positions(b_r1lift), fs), true, even_occ(positions_b_r1([b_r1a_sh, b_r1a]), fs) && even_occ(positions_b_r1([b_r1b, b_r1b_sh]), fs)); ls != ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls); allowed(rotate_lift, glob_state(fs, shs, ls)) = height(ls) == rotate && free([pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa), pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb)], fs); nextstate(move_belts(r1bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r1bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r2bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r2bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r3bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_belts(r3bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_shuttles(sps, lowered, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_sps(l, fs), shift_inc(l, lowered, shs), ls) whr l = add_neighbour(sps, row_inc) end; nextstate(move_shuttles(sps, lowered, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_sps(l, fs), shift_dec(l, lowered, shs), ls) whr l = add_neighbour(sps, row_dec) end; nextstate(move_shuttles(sps, tilted, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_inc(add_neighbour(sps, row_inc), tilted, shs), ls); nextstate(move_shuttles(sps, tilted, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_dec(add_neighbour(sps, row_dec), tilted, shs), ls); nextstate(tilt_shuttle(sp, so), ok, glob_state(fs, shs, ls)) = glob_state(fs, ins_upd(sp, so, n_avail, ins_upd(sp, not(so), avail, shs)), ls); occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state( if(height(ls) != basement && lh == basement, ins_upd_fps(positions(b_r1lift), occupied, fs), if(height(ls) == basement && lh != basement, ins_upd_fps(positions(b_r1lift), free, fs), fs ) ), shs, make_ls(lh, occupied)); !occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state(fs, shs, make_ls(lh, free)); nextstate(rotate_lift, ok, gs) = gs; nextstate(i, fail, gs) = gs; allowed([], gs) = false; allowed(i |> [], gs) = allowed(i, gs); allowed(i |> j |> is, gs) = allowed(i, gs) && !overlap(i, j |> is) && allowed(j |> is, gs); nextstate([], ok, gs) = gs; nextstate(i |> is, ok, gs) = nextstate(i, ok, nextstate(is, ok, gs)); nextstate(is, fail, gs) = gs; possible(add_car, glob_state(fs, shs, ls)) = ls == lsf_street; possible(remove_car, glob_state(fs, shs, ls)) = ls == lso_street; nextstate(add_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lso_street); nextstate(remove_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lsf_street); act exec: Instruction; occur: Event; proc V(gs_sl: GlobalState) = sum i: Instruction. (valid(i) && allowed(i, gs_sl)) -> exec(i) . V(nextstate(i, ok, gs_sl)) + sum e: Event. possible(e, gs_sl) -> occur(e) . V(nextstate(e, gs_sl)) ; init V(init_gs); mcrl2-201409.0/examples/industrial/garage/garage-r2-error.mcrl2000770 001750 001750 00000113734 12370120076 024430 0ustar00outisoutis000000 000000 % The following is the specification of the safety layer of the automated % parking garage after reduction 2 as described in [1, Appendices B and C.3], % containing two errors [1, Figure 7]. % % Simulation of this specification is possible. When used in combination with % the corresponding visualisation plugin, it is an effective way to find % errors. % % [1] Aad Mathijssen and A. Johannes Pretorius. Specification, Analysis and % Verification of an Automated Parking Garage. Computer Science Report % 05-25, Eindhoven University of Technology (TU/e), 2005. sort FloorRow = struct r1 | r2 | r3; FloorCol = struct c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10; FloorPosPart = struct pa | pb; FloorPos = struct pos_r1(FloorCol, FloorPosPart) | pos_r2(FloorCol) | pos_r3(FloorCol); FloorPosList = List(FloorPos); ShuttlePos = struct r1a | r2a | r3a | r1b | r2b | r3b; ShuttlePosSet = List(ShuttlePos); % representing a set of ShuttlePos elements ShuttleOrientation = struct lowered | tilted; R1Belt = struct b_r1a_sh | b_r1a | b_r1lift | b_r1b | b_r1b_sh; R2Belt = struct b_r2a_sh | b_r2 | b_r2b_sh; R3Belt = struct b_r3a_sh | b_r3 | b_r3b_sh; R1BeltSet = List(R1Belt); % representing a set of R1Belt elements R2BeltSet = List(R2Belt); % representing a set of R2Belt elements R3BeltSet = List(R3Belt); % representing a set of R3Belt elements DirCol = struct col_inc | col_dec; DirRow = struct row_inc | row_dec; MoveSize = struct full | half; LiftHeight = struct street | rotate | basement; Area = struct area(positions: FloorPosList, tilted_c1: Bool, tilted_c10: Bool); Instruction = struct move_belts(R1BeltSet, DirCol, MoveSize) | move_belts(R2BeltSet, DirCol, MoveSize) | move_belts(R3BeltSet, DirCol, MoveSize) | move_shuttles(ShuttlePosSet, ShuttleOrientation, DirRow) | tilt_shuttle(ShuttlePos, ShuttleOrientation) | move_lift(LiftHeight) | rotate_lift; InstructionSet = List(Instruction); % representing a set of instructions Event = struct add_car | remove_car; ExecResult = struct ok | fail; OccState = struct free | occupied; AvailState = struct avail | n_avail; FloorState = FloorPos -> OccState; ShuttleState = ShuttlePos # ShuttleOrientation -> AvailState; LiftState = struct lsf_street | lso_street | lsf_rotate | lso_rotate | ls_basement; GlobalState = struct glob_state(fs: FloorState, shs: ShuttleState, ls: LiftState); % FloorRow operations map index: FloorRow -> Pos; % index(fra) is the index of fra lt: FloorRow # FloorRow -> Bool; % lt(fra,frb) indicates if fra is less than frb var fra, frb: FloorRow; eqn index(r1) = 1; index(r2) = 2; index(r3) = 3; lt(fra, frb) = index(fra) < index(frb); % FloorCol operations map index: FloorCol -> Pos; % index(fca) is the index of fca lt: FloorCol # FloorCol -> Bool; % lt(fca,fcb) indicates if fca is less than fcb var fca, fcb: FloorCol; eqn index(c1) = 1; index(c2) = 2; index(c3) = 3; index(c4) = 4; index(c5) = 5; index(c6) = 6; index(c7) = 7; index(c8) = 8; index(c9) = 9; index(c10) = 10; lt(fca, fcb) = index(fca) < index(fcb); % FloorPosPart operations map index: FloorPosPart -> Pos; % index(ffpa) is the index of fppa lt: FloorPosPart # FloorPosPart -> Bool; % lt(fppa,fppb) indicates if fppa is less than fppb var fppa, fppb: FloorPosPart; eqn index(pa) = 1; index(pb) = 2; lt(fppa, fppb) = index(fppa) < index(fppb); % FloorPos operations map row: FloorPos -> FloorRow; % row(fpa) is the row of fpa col: FloorPos -> FloorCol; % col(fpa) is the column of fpa part: FloorPos -> FloorPosPart; % part(fpa) is the part of fpa lt: FloorPos # FloorPos -> Bool; % lt(fpa, fpb) indicates if fpa is less than fpb lt_r: FloorPos # FloorPos -> Bool; % lt_r(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) (auxiliary function needed by lt for efficiency) lt_rc: FloorPos # FloorPos -> Bool; % lt_rc(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) and col(fpa) = col(fpb) % (auxiliary function needed by lt_r for efficiency) gt: FloorPos # FloorPos -> Bool; % gt(fpa, fpb) indicates if fpa is greater than fpb var fca: FloorCol; fppa: FloorPosPart; fpa, fpb: FloorPos; eqn row(pos_r1(fca, fppa)) = r1; row(pos_r2(fca)) = r2; row(pos_r3(fca)) = r3; col(pos_r1(fca, fppa)) = fca; col(pos_r2(fca)) = fca; col(pos_r3(fca)) = fca; part(pos_r1(fca, fppa)) = fppa; row(fpa) == row(fpb) -> lt(fpa, fpb) = lt_r(fpa, fpb); row(fpa) != row(fpb) -> lt(fpa, fpb) = lt(row(fpa), row(fpb)); col(fpa) == col(fpb) -> lt_r(fpa, fpb) = lt_rc(fpa, fpb); col(fpa) != col(fpb) -> lt_r(fpa, fpb) = lt(col(fpa), col(fpb)); lt_rc(fpa, fpb) = row(fpa) == r1 && lt(part(fpa), part(fpb)); gt(fpa,fpb) = lt(fpb, fpa); % FloorPosList operations map contains: FloorPos # FloorPosList -> Bool; % contains(fpa, fps) indicates if fps contains fpa overlap: FloorPosList # FloorPosList -> Bool; % overlap(fps, fpt) indicates if the elements of fps and fpt overlap rev: FloorPosList -> FloorPosList; % rev(fps) is the reverse of list fps grev: FloorPosList # FloorPosList -> FloorPosList; % grev(fps, fpt) is the reverse of fps concatenated with fpt % (auxiliary function needed for efficiency by rev) var fpa, fpb: FloorPos; fps, fpt: FloorPosList; eqn contains(fpa, []) = false; contains(fpa, fpa |> fps) = true; fpa != fpb -> contains(fpa, fpb |> fps) = contains(fpa, fps); overlap([], fpt) = false; overlap(fpa |> fps, fpt) = contains(fpa, fpt) || overlap(fps, fpt); rev(fps) = grev(fps, []); grev([], fpt) = fpt; grev(fpa |> fps, fpt) = grev(fps, fpa |> fpt); % ShuttlePos operations map index: ShuttlePos -> Pos; % index(spa) is the index of spa row: ShuttlePos -> FloorRow; % row(spa) is the row of spa col: ShuttlePos -> FloorCol; % col(spa) is the column of spa lt: ShuttlePos # ShuttlePos -> Bool; % lt(spa, spb) indicates if spa is less than spb gt: ShuttlePos # ShuttlePos -> Bool; % gt(spa, spb) indicates if spa is greater than spb positions: ShuttlePos -> FloorPosList; % positions(spa) represents the floor positions corresponding to spa in % lowered position has_neighbour: ShuttlePos # DirRow -> Bool; % has_neighbour(spa, dr) indicates if spa has a successor in direction dr neighbour: ShuttlePos # DirRow -> ShuttlePos; % neighbour(spa, dr) is the neighbour of spa in directrion dr, provided it % exists connected: ShuttlePos # ShuttlePos -> Bool; % connected(spa, spb) indicates if the bottom of spa is connected to the top % of spb var spa, spb: ShuttlePos; eqn index(r1a) = 1; index(r2a) = 2; index(r3a) = 3; index(r1b) = 4; index(r2b) = 5; index(r3b) = 6; row(r1a) = r1; row(r2a) = r2; row(r3a) = r3; row(r1b) = r1; row(r2b) = r2; row(r3b) = r3; col(r1a) = c1; col(r2a) = c1; col(r3a) = c1; col(r1b) = c10; col(r2b) = c10; col(r3b) = c10; lt(spa, spb) = index(spa) < index(spb); gt(spa, spb) = index(spa) > index(spb); positions(r1a) = positions(b_r1a_sh); positions(r2a) = positions(b_r2a_sh); positions(r3a) = positions(b_r3a_sh); positions(r1b) = positions(b_r1b_sh); positions(r2b) = positions(b_r2b_sh); positions(r3b) = positions(b_r3b_sh); has_neighbour(spa, row_inc) = row(spa) != r3; has_neighbour(spa, row_dec) = row(spa) != r1; neighbour(r1a, row_inc) = r2a; neighbour(r2a, row_inc) = r3a; neighbour(r1b, row_inc) = r2b; neighbour(r2b, row_inc) = r3b; neighbour(r2a, row_dec) = r1a; neighbour(r3a, row_dec) = r2a; neighbour(r2b, row_dec) = r1b; neighbour(r3b, row_dec) = r2b; connected(spa, spb) = succ(index(spa)) == index(spb) && col(spa) == col(spb); % ShuttlePosSet operations map is_set_sps: ShuttlePosSet -> Bool; % is_set_sps(sps) indicates if sps is a set % In the remainder of the data equation section, for every ShuttlePosSet sps % is_set_sps(sps) is a precondition. contains: ShuttlePos # ShuttlePosSet -> Bool; % contains(spa, sps) indicates if sps contains spa shuttles: FloorCol -> ShuttlePosSet; % shuttles(fc) represents the shuttle positions corresponding to fc positions_sps: ShuttlePosSet -> FloorPosList; % positions_sps(sps) represents the floor positions corresponding to sps connected_sps: ShuttlePosSet -> Bool; % connected_sps(sps) indicates if all elements of sps are connected has_neighbour: ShuttlePosSet # DirRow -> Bool; % has_neighbour(sps, dr) indicates is sps has a neighbour in direction dr neighbour_sps: ShuttlePosSet # DirRow -> ShuttlePos; % neighbour_sps(sps, dr) is the neighbour of sps in direction dr, provided it % exists add_neighbour: ShuttlePosSet # DirRow -> ShuttlePosSet; % add_neighbour(sps, dr) represents the sps extended with its neighbour in % direction dr, provided it exists var spa, spb: ShuttlePos; sps: ShuttlePosSet; fc: FloorCol; eqn is_set_sps([]) = true; is_set_sps(spa |> []) = true; is_set_sps(spa |> spb |> sps) = lt(spa, spb) && is_set_sps(spb |> sps); contains(spa, []) = false; contains(spa, spa |> sps) = true; spa != spb -> contains(spa, spb |> sps) = contains(spa, sps); shuttles(fc) = if(fc == c1, [r1a,r2a,r3a], if(fc == c10, [r1b,r2b,r3b], [])); positions_sps([]) = []; positions_sps(spa |> sps) = positions(spa) ++ positions_sps(sps); connected_sps([]) = true; connected_sps([spa]) = true; connected_sps(spa |> spb |> sps) = connected(spa, spb) && connected_sps(spb |> sps); has_neighbour(sps, row_inc) = has_neighbour(rhead(sps), row_inc); has_neighbour(sps, row_dec) = has_neighbour(head(sps), row_dec); neighbour_sps(sps, row_inc) = neighbour(rhead(sps), row_inc); neighbour_sps(sps, row_dec) = neighbour(head(sps), row_dec); add_neighbour(sps, row_inc) = sps <| neighbour_sps(sps, row_inc); add_neighbour(sps, row_dec) = neighbour_sps(sps, row_dec) |> sps; % ShuttleOrientation operations map index: ShuttleOrientation -> Pos; % index(soa) is the index of soa lt: ShuttleOrientation # ShuttleOrientation -> Bool; % lt(soa, sob) indicates if soa is less than sob gt: ShuttleOrientation # ShuttleOrientation -> Bool; % gt(soa, sob) indicates if soa is greater than sob not: ShuttleOrientation -> ShuttleOrientation; % not(soa) indicates the opposite of soa var soa, sob: ShuttleOrientation; eqn index(lowered) = 1; index(tilted) = 2; lt(soa, sob) = index(soa) < index(sob); gt(soa, sob) = index(soa) > index(sob); not(lowered) = tilted; not(tilted) = lowered; % Belt operations map index: R1Belt -> Pos; index: R2Belt -> Pos; index: R3Belt -> Pos; % index(ba) is the index of belt ba row: R1Belt -> FloorRow; row: R2Belt -> FloorRow; row: R3Belt -> FloorRow; % row(ba) is the row of belt ba lt: R1Belt # R1Belt -> Bool; lt: R2Belt # R2Belt -> Bool; lt: R3Belt # R3Belt -> Bool; % lt(ba, bb) indicates if belt ba is less than belt bb positions: R1Belt -> FloorPosList; positions: R2Belt -> FloorPosList; positions: R3Belt -> FloorPosList; % positions(ba) represents the positions corresponding to belt ba connected: R1Belt # R1Belt -> Bool; connected: R2Belt # R2Belt -> Bool; connected: R3Belt # R3Belt -> Bool; % connected(ba, bb) indicates if the right of ba is connected to the left % of bb available: R1Belt # ShuttleState # LiftState -> Bool; available: R2Belt # ShuttleState # LiftState -> Bool; available: R3Belt # ShuttleState # LiftState -> Bool; % available(ba, shs, ls) indicates if belt ba is available for states shs % and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; fs: FloorState; shs: ShuttleState; ls: LiftState; ms: MoveSize; eqn index(b_r1a_sh) = 1; index(b_r1a) = 2; index(b_r1lift) = 3; index(b_r1b) = 4; index(b_r1b_sh) = 5; index(b_r2a_sh) = 1; index(b_r2) = 2; index(b_r2b_sh) = 3; index(b_r3a_sh) = 1; index(b_r3) = 2; index(b_r3b_sh) = 3; row(r1ba) = r1; row(r2ba) = r2; row(r3ba) = r3; lt(r1ba, r1bb) = index(r1ba) < index(r1bb); lt(r2ba, r2bb) = index(r2ba) < index(r2bb); lt(r3ba, r3bb) = index(r3ba) < index(r3bb); positions(b_r1a_sh) = [pos_r1(c1, pa), pos_r1(c1, pb)]; positions(b_r1a) = [pos_r1(c2, pa), pos_r1(c2, pb), pos_r1(c3, pa), pos_r1(c3, pb), pos_r1(c4, pa), pos_r1(c4, pb), pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa)]; positions(b_r1lift) = [pos_r1(c6, pb), pos_r1(c7, pa)]; positions(b_r1b) = [pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb), pos_r1(c9, pa), pos_r1(c9, pb)]; positions(b_r1b_sh) = [pos_r1(c10, pa), pos_r1(c10, pb)]; positions(b_r2a_sh) = [pos_r2(c1)]; positions(b_r2) = [pos_r2(c2), pos_r2(c3), pos_r2(c4), pos_r2(c5), pos_r2(c6), pos_r2(c7), pos_r2(c8), pos_r2(c9)]; positions(b_r2b_sh) = [pos_r2(c10)]; positions(b_r3a_sh) = [pos_r3(c1)]; positions(b_r3) = [pos_r3(c2), pos_r3(c3), pos_r3(c4), pos_r3(c5), pos_r3(c6), pos_r3(c7), pos_r3(c8), pos_r3(c9)]; positions(b_r3b_sh) = [pos_r3(c10)]; available(b_r1a_sh, shs, ls) = shs(r1a, lowered) == avail; available(b_r1a, shs, ls) = true; available(b_r1lift, shs, ls) = ls == ls_basement; available(b_r1b, shs, ls) = true; available(b_r1b_sh, shs, ls) = shs(r1b, lowered) == avail; available(b_r2a_sh, shs, ls) = shs(r2a, lowered) == avail; available(b_r2, shs, ls) = true; available(b_r2b_sh, shs, ls) = shs(r2b, lowered) == avail; available(b_r3a_sh, shs, ls) = shs(r3a, lowered) == avail; available(b_r3, shs, ls) = true; available(b_r3b_sh, shs, ls) = shs(r3b, lowered) == avail; % BeltSet operations map is_set_b_r1: R1BeltSet -> Bool; is_set_b_r2: R2BeltSet -> Bool; is_set_b_r3: R3BeltSet -> Bool; % is_set_b_rX(bs) indicates if bs is a set % In the remainder of this data equations section each belt set bs has % is_set_b_rX(bs) as a precondition. contains: R1Belt # R1BeltSet -> Bool; contains: R2Belt # R2BeltSet -> Bool; contains: R3Belt # R3BeltSet -> Bool; % contains(ba, bs) indicates if ba is an element of bs positions_b_r1: R1BeltSet -> FloorPosList; positions_b_r2: R2BeltSet -> FloorPosList; positions_b_r3: R3BeltSet -> FloorPosList; % positions_b_rX(bs) represents the floor positions corresponding to the % belts in bs connected_b_r1: R1BeltSet -> Bool; connected_b_r2: R2BeltSet -> Bool; connected_b_r3: R3BeltSet -> Bool; % connected(bs) indicates if the belts in bs are connected available_b_r1: R1BeltSet # ShuttleState # LiftState -> Bool; available_b_r2: R2BeltSet # ShuttleState # LiftState -> Bool; available_b_r3: R3BeltSet # ShuttleState # LiftState -> Bool; % available_b_rX(bs, shs, ls) indicates if all belts in bs are available for % states shs and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; fs: FloorState; shs: ShuttleState; ls: LiftState; eqn is_set_b_r1([]) = true; is_set_b_r1(r1ba |> []) = true; is_set_b_r1(r1ba |> r1bb |> r1bs) = lt(r1ba, r1bb) && is_set_b_r1(r1bb |> r1bs); is_set_b_r2([]) = true; is_set_b_r2(r2ba |> []) = true; is_set_b_r2(r2ba |> r2bb |> r2bs) = lt(r2ba, r2bb) && is_set_b_r2(r2bb |> r2bs); is_set_b_r3([]) = true; is_set_b_r3(r3ba |> []) = true; is_set_b_r3(r3ba |> r3bb |> r3bs) = lt(r3ba, r3bb) && is_set_b_r3(r3bb |> r3bs); contains(r1ba, []) = false; contains(r1ba, r1ba |> r1bs) = true; r1ba != r1bb -> contains(r1ba, r1bb |> r1bs) = contains(r1ba, r1bs); contains(r2ba, []) = false; contains(r2ba, r2ba |> r2bs) = true; r2ba != r2bb -> contains(r2ba, r2bb |> r2bs) = contains(r2ba, r2bs); contains(r3ba, []) = false; contains(r3ba, r3ba |> r3bs) = true; r3ba != r3bb -> contains(r3ba, r3bb |> r3bs) = contains(r3ba, r3bs); positions_b_r1([]) = []; positions_b_r1(r1ba |> r1bs) = positions(r1ba) ++ positions_b_r1(r1bs); positions_b_r2([]) = []; positions_b_r2(r2ba |> r2bs) = positions(r2ba) ++ positions_b_r2(r2bs); positions_b_r3([]) = []; positions_b_r3(r3ba |> r3bs) = positions(r3ba) ++ positions_b_r3(r3bs); connected_b_r1([]) = true; connected_b_r1(r1ba |> []) = true; connected_b_r1(r1ba |> r1bb |> r1bs) = connected(r1ba, r1bb) && connected_b_r1(r1bb |> r1bs); connected_b_r2([]) = true; connected_b_r2(r2ba |> []) = true; connected_b_r2(r2ba |> r2bb |> r2bs) = connected(r2ba, r2bb) && connected_b_r2(r2bb |> r2bs); connected_b_r3([]) = true; connected_b_r3(r3ba |> []) = true; connected_b_r3(r3ba |> r3bb |> r3bs) = connected(r3ba, r3bb) && connected_b_r3(r3bb |> r3bs); connected(r1ba, r1bb) = succ(index(r1ba)) == index(r1bb); connected(r2ba, r2bb) = succ(index(r2ba)) == index(r2bb); connected(r3ba, r3bb) = succ(index(r3ba)) == index(r3bb); available_b_r1([], shs, ls) = true; available_b_r1(r1ba |> r1bs, shs, ls) = available(r1ba, shs, ls) && available_b_r1(r1bs, shs, ls); available_b_r2([], shs, ls) = true; available_b_r2(r2ba |> r2bs, shs, ls) = available(r2ba, shs, ls) && available_b_r2(r2bs, shs, ls); available_b_r3([], shs, ls) = true; available_b_r3(r3ba |> r3bs, shs, ls) = available(r3ba, shs, ls) && available_b_r3(r3bs, shs, ls); % Area operations map overlap: Area # Area -> Bool; % area(a, b) indicates if area a and b overlap var fps, fpt: FloorPosList; tc1a, tc1b, tc10a, tc10b: Bool; eqn overlap(area(fps, tc1a, tc1b), area(fpt, tc10a, tc10b)) = overlap(fps, fpt) || (tc1a && tc1b) || (tc10a && tc10b); % Instruction operations map index: Instruction -> Pos; % index(i) is the index of instruction i lt: Instruction # Instruction -> Bool; % lt(i, j) indicates if i is less than j valid: Instruction -> Bool; % valid(i) indicates if instruction i is valid area: Instruction -> Area; % area(i) represents the area on which instruction i has any effect overlap: Instruction # Instruction -> Bool; % overlap(i, j) indicates if instruction i and j overlap var r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sp: ShuttlePos; sps: ShuttlePosSet; so: ShuttleOrientation; dr: DirRow; lh: LiftHeight; i,j: Instruction; eqn index(move_belts(r1bs, dc, ms)) = 1; index(move_belts(r2bs, dc, ms)) = 2; index(move_belts(r3bs, dc, ms)) = 3; index(move_shuttles(sps, so, dr)) = 4; index(tilt_shuttle(sp, so)) = 5; index(move_lift(lh)) = 6; index(rotate_lift) = 7; lt(i, j) = index(i) < index(j); valid(move_belts(r1bs, dc, ms)) = is_set_b_r1(r1bs); valid(move_belts(r2bs, dc, ms)) = is_set_b_r2(r2bs); valid(move_belts(r3bs, dc, ms)) = is_set_b_r3(r3bs); valid(move_shuttles(sps, so, dr)) = is_set_sps(sps); valid(tilt_shuttle(sp, so)) = true; valid(move_lift(lh)) = true; valid(rotate_lift) = true; area(move_belts(r1bs, dc, ms)) = area(positions_b_r1(r1bs), false, false); area(move_belts(r2bs, dc, ms)) = area(positions_b_r2(r2bs), false, false); area(move_belts(r3bs, dc, ms)) = area(positions_b_r3(r3bs), false, false); area(move_shuttles(sps, lowered, dr)) = area(positions_sps(add_neighbour(sps, dr)), false, false); area(move_shuttles(sps, tilted, dr)) = area([], col(head(sps)) == c1, col(head(sps)) == c10); area(tilt_shuttle(sp, so)) = area(positions(sp), col(sp) == c1, col(sp) == c10); area(move_lift(lh)) = area(positions(b_r1lift), false, false); area(rotate_lift) = area(positions_b_r1([b_r1a, b_r1lift, b_r1b]), false, false); overlap(i, j) = overlap(area(i), area(j)); % InstructionSet operations map is_set_is: InstructionSet -> Bool; % is_set_is(is) indicates if is is a set % In the remainder of the data equation section, for every InstructionSet is % is_set_is(is) is a precondition. valid: InstructionSet -> Bool; % valid(is) indicates if the instructions in is are valid overlap: Instruction # InstructionSet -> Bool; % overlap(i, is) indicates if instruction i overlaps with any of the % instructions in is var i,j: Instruction; is: InstructionSet; eqn is_set_is([]) = true; is_set_is(i |> []) = true; is_set_is(i |> j |> is) = lt(i, j) && is_set_is(j |> is); valid([]) = true; valid(i |> is) = valid(i) && valid(is); overlap(i, []) = false; overlap(i, j |> is) = overlap(i, j) || overlap(i, is); % AvailState operations map not: AvailState -> AvailState; % not(asa) indicates the opposite of asa eqn not(avail) = n_avail; not(n_avail) = avail; % FloorState operations map init_fs: FloorState; % init_fs is the initial floor state update: FloorPos # OccState # FloorState -> FloorState; cond_upd: FloorPos # OccState # FloorState -> FloorState; ins_upd: FloorPos # OccState # FloorState -> FloorState; % update(fpa, osa, fsa) represents fsa, where position fpa has value osa; % cond_upd and ins_upd are auxiliary functions with the same meaning that % are needed for efficiency ins_upd_fps: FloorPosList # OccState # FloorState -> FloorState; % ins_upd_fps(fps, osa, fsa) represents fsa, where positions fps have value % osa free: FloorPosList # FloorState -> Bool; % free(fps, fsa) indicates that all positions in fps are free for state fsa occupied: FloorPosList # FloorState -> Bool; % occupied(fps, fsa) indicates that all positions in fps are occupied for % state fsa end_free: FloorPosList # DirCol # Bool # FloorState -> Bool; % end_free(fps, dc, obl, fsa) indicates if the end of the list fps in % direction dc is free for state fsa; if obl then the one but last element % also needs to be free even_occ: FloorPosList # FloorState -> Bool; % even_occ(fps, fsa) indicates if the number of occupied positions in fps for % state fsa is even no_half_car: ShuttlePos # FloorState -> Bool; % no_half_car(spa, fsa) indicates if there is a half car positioned on spa % for state fsa no_half_car_sps: ShuttlePosSet # FloorState -> Bool; % no_half_car(sps, fsa) indicates if there is a half car positioned on any % of the elements of sps for state fsa shift_inc: FloorPosList # FloorState -> FloorState; % shift_inc(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the right; the first element in fps % gets state free gshift_inc: FloorPosList # FloorState # OccState -> FloorState; % gshift_inc(fps, fsa, osa) has the same meaning as shift_inc(fps, fsa), with % the exception that the first element in fps gets state osa % (auxiliary function needed by shift_inc) shift_dec: FloorPosList # FloorState -> FloorState; % shift_dec(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the left; the last element in fps gets % state free shift_inc_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_inc_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the right; % if ctw then two positions are shifted shift_dec_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_dec_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the left; % if ctw then two positions are shifted shift_inc_sps: ShuttlePosSet # FloorState -> FloorState; % shift_inc(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position downwards; the first element in sps % gets state free shift_dec_sps: ShuttlePosSet # FloorState -> FloorState; % shift_dec(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position upwards; the last element in sps gets state % free var b: Bool; fsa, fsb: FloorState; fpa, fpb: FloorPos; osa, osb: OccState; fps: FloorPosList; spa: ShuttlePos; sps: ShuttlePosSet; eqn init_fs(fpa) = free; fpa == fpb -> update(fpa, osa, fsa)(fpb) = osa; fpa != fpb -> update(fpa, osa, fsa)(fpb) = fsa(fpb); cond_upd(fpa, osa, fsa) = if(fsa(fpa) == osa, fsa, update(fpa, osa, fsa)); ins_upd(fpa, osa, init_fs) = cond_upd(fpa, osa, init_fs); lt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, update(fpb, osb, fsa)); gt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = update(fpb, osb, ins_upd(fpa, osa, fsa)); fpa == fpb -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, fsa); ins_upd_fps([], osa, fsa) = fsa; ins_upd_fps(fpa |> fps, osa, fsa) = ins_upd(fpa, osa, ins_upd_fps(fps, osa, fsa)); free([], fsa) = true; free(fpa |> fps, fsa) = fsa(fpa) == free && free(fps, fsa); occupied(fpa |> fps, fsa) = fsa(fpa) == occupied && occupied(fps, fsa); occupied([], fsa) = true; end_free(fps, col_inc, false, fsa) = fsa(head(rev(fps))) == free; end_free(fps, col_inc, true, fsa) = fsa(head(l)) == free && fsa(head(tail(l))) == free whr l = rev(fps) end; end_free(fps, col_dec, false, fsa) = fsa(head(fps)) == free; end_free(fps, col_dec, true, fsa) = fsa(head(fps)) == free && fsa(head(tail(fps))) == free; even_occ([], fsa) = true; fsa(fpa) == free -> even_occ(fpa |> fps, fsa) = even_occ(fps, fsa); fsa(fpa) == occupied -> even_occ(fpa |> fps, fsa) = !even_occ(fps, fsa); row(spa) != r1 -> no_half_car(spa, fsa) = true; row(spa) == r1 -> no_half_car(spa, fsa) = even_occ(positions(spa), fsa); no_half_car_sps([], fsa) = true; no_half_car_sps(spa |> sps, fsa) = no_half_car(spa, fsa) && no_half_car_sps(sps, fsa); shift_inc(fps, fsa) = gshift_inc(fps, fsa, free); gshift_inc([], fsa, osa) = fsa; gshift_inc([fpa], fsa, osa) = ins_upd(fpa, osa, fsa); gshift_inc(fpa |> fps, fsa, osa) = ins_upd(fpa, osa, gshift_inc(fps, fsa, fsa(fpa))); shift_dec([], fsa) = fsa; shift_dec([fpa], fsa) = ins_upd(fpa, free, fsa); shift_dec(fpa |> fpb |> fps, fsa) = ins_upd(fpa, fsa(fpb), shift_dec(fpb |> fps, fsa)); shift_inc_ctw(false, fps, fsa) = shift_inc(fps, fsa); shift_inc_ctw(true, fps, fsa) = shift_inc(fps, shift_inc(fps, fsa)); shift_dec_ctw(false, fps, fsa) = shift_dec(fps, fsa); shift_dec_ctw(true, fps, fsa) = shift_dec(fps, shift_dec(fps, fsa)); shift_inc_sps([], fsa) = fsa; row(spa) == r1 -> shift_inc_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), free, shift_inc(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_inc_sps(spa |> sps, fsa) = shift_inc(positions_sps(spa |> sps), fsa); shift_dec_sps([], fsa) = fsa; row(spa) == r1 -> shift_dec_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), fsa(head(positions(head(sps)))), shift_dec(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_dec_sps(spa |> sps, fsa) = shift_dec(positions_sps(spa |> sps), fsa); % ShuttleState operations map init_shs: ShuttleState; % initial shuttle state update: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; cond_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; ins_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; % update(spa, soa, asa, fsa) represents fsa, where position fpa in % orientation soa has value asa; cond_upd and ins_upd are auxiliary functions % with the same meaning that are needed for efficiency available: ShuttlePos # ShuttleOrientation # ShuttleState -> Bool; % available(spa, soa, shs) indicates if shuttle spa is available in % orientation soa for state shs available_sps: ShuttlePosSet # ShuttleOrientation # ShuttleState -> Bool; % available(sps, soa, shs) indicates if all shuttles in sps are available in % orientation soa for state shs shift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_inc(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle downwards in orientation soa; the first % element in sps gets state unavailable gshift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState # AvailState -> ShuttleState; % gshift_inc(sps, soa, shs, asa) has the same meaning as shift_inc(sps, soa, % shs), with the exception that the first element in sps gets state asa % (auxiliary function needed by shift_inc) shift_dec: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_dec(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle upwards in orientation soa; the last % element in sps gets state unavailable var b: Bool; shs, shsa: ShuttleState; spa, spb: ShuttlePos; sps: ShuttlePosSet; soa, sob: ShuttleOrientation; asa, asb: AvailState; eqn init_shs(spa, lowered) = if(row(spa) != r3, avail, n_avail); init_shs(spa, tilted) = if(row(spa) != r3, n_avail, avail); spa == spb && soa == sob -> update(spa, soa, asa, shs)(spb, sob) = asa; spa != spb || soa != sob -> update(spa, soa, asa, shs)(spb, sob) = shs(spb, sob); cond_upd(spa, soa, asa, shs) = if(shs(spa, soa) == asa, shs, update(spa, soa, asa, shs)); ins_upd(spa, soa, asa, init_shs) = cond_upd(spa, soa, asa, init_shs); lt(spa,spb) || (spa == spb && lt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, update(spb, sob, asb, shs)); gt(spa,spb) || (spa == spb && gt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = update(spb, sob, asb, ins_upd(spa, soa, asa, shs)); spa == spb && soa == sob -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, shs); available(spa, soa, shs) = shs(spa, soa) == avail; available_sps([], soa, shs) = true; available_sps(spa |> sps, soa, shs) = available(spa, soa, shs) && available_sps(sps, soa, shs); shift_inc(sps, soa, shs) = gshift_inc(sps, soa, shs, n_avail); gshift_inc([], soa, shs, asa) = shs; gshift_inc([spa], soa, shs, asa) = ins_upd(spa, soa, asa, shs); gshift_inc(spa |> sps, soa, shs, asa) = ins_upd(spa, soa, asa, gshift_inc(sps, soa, shs, shs(spa, soa))); shift_dec([], soa, shs) = shs; shift_dec([spa], soa, shs) = ins_upd(spa, soa, n_avail, shs); shift_dec(spa |> spb |> sps, soa, shs) = ins_upd(spa, soa, shs(spb, soa), shift_dec(spb |> sps, soa, shs)); % LiftState operations map height: LiftState -> LiftHeight; % height(ls) represents the height of state ls occupied: LiftState # FloorState -> Bool; % occupied(ls, fs) indicates if the lift is occupieed for states ls and fs make_ls: LiftHeight # OccState -> LiftState; % make_ls(lh, os) represents the lift state corresponding to height lh and % occupied state os var b: Bool; fsa: FloorState; osa: OccState; eqn height(lsf_street) = street; height(lso_street) = street; height(lsf_rotate) = rotate; height(lso_rotate) = rotate; height(ls_basement) = basement; occupied(lsf_street, fsa) = false; occupied(lso_street, fsa) = true; occupied(lsf_rotate, fsa) = false; occupied(lso_rotate, fsa) = true; occupied(ls_basement, fsa) = occupied(positions(b_r1lift), fsa); make_ls(street, occupied) = lso_street; make_ls(street, free) = lsf_street; make_ls(rotate, occupied) = lso_rotate; make_ls(rotate, free) = lsf_rotate; make_ls(basement, osa) = ls_basement; % GlobalState operations map init_gs: GlobalState; % init_gs is the initial global state allowed: Instruction # GlobalState -> Bool; % allowed(i, gs) indicates if instruction i is allowed given global state gs nextstate: Instruction # ExecResult # GlobalState -> GlobalState; % nextstate(i, r, gs) represents the global state after execution of % instruction i with result r in state gs allowed: InstructionSet # GlobalState -> Bool; % allowed(is, gs) indicates if instruction set is is allowed given global % state gs nextstate: InstructionSet # ExecResult # GlobalState -> GlobalState; % nextstate(is, r, gs) represents the global state after execution of % instruction set is with result r in state gs possible: Event # GlobalState -> Bool; % possible(e, gs) indicates if event e is possible given global state gs nextstate: Event # GlobalState -> GlobalState; % nextstate(e, gs) represents the global state after the event e has occurred % in state gs var gs, gsa: GlobalState; fs, fsa: FloorState; shs, shsa: ShuttleState; ls, lsa: LiftState; lh, lha: LiftHeight; p,q: FloorPos; s,t: OccState; i,j: Instruction; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sps: ShuttlePosSet; dr: DirRow; sp, spa, spb: ShuttlePos; so: ShuttleOrientation; is: InstructionSet; eqn init_gs = glob_state( init_fs, init_shs, lsf_street); allowed(move_belts(r1bs, dc, ms), glob_state(fs, shs, ls)) = r1bs != [] && connected_b_r1(r1bs) && available_b_r1(r1bs, shs, ls) && end_free(l, dc, ms == full, fs) && even_occ(l, fs) whr l = positions_b_r1(r1bs) end; allowed(move_belts(r2bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r2bs != [] && connected_b_r2(r2bs) && available_b_r2(r2bs, shs, ls) && end_free(positions_b_r2(r2bs), dc, false, fs); allowed(move_belts(r3bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r3bs != [] && connected_b_r3(r3bs) && available_b_r3(r3bs, shs, ls) && end_free(positions_b_r3(r3bs), dc, false, fs); allowed(move_shuttles(sps, so, dr), glob_state(fs, shs, ls)) = sps != [] && connected_sps(sps) && available_sps(sps, so, shs) && % placing a comment in front of the following conjunct allows the shuttles % to be moved even if a car is placed half on the shuttle % (so == lowered => no_half_car_sps(sps, fs)) && has_neighbour(sps, dr) && !available(neighbour_sps(sps, dr), so, shs); allowed(tilt_shuttle(sp, lowered), glob_state(fs, shs, ls)) = available_sps(shuttles(col(sp)), lowered, shs) && free(positions(sp), fs); allowed(tilt_shuttle(sp, tilted), glob_state(fs, shs, ls)) = shs(sp, tilted) == avail && shs(sp, lowered) == n_avail; ls == ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls) && % replacing the following conjunct by even_occ(positions(b_r1lift), fs); % allows the lift to move up if two cars are placed half on the lift belt %if(free(positions(b_r1lift), fs), true, % even_occ(positions_b_r1([b_r1a_sh, b_r1a]), fs) && % even_occ(positions_b_r1([b_r1b, b_r1b_sh]), fs)); ls != ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls); allowed(rotate_lift, glob_state(fs, shs, ls)) = height(ls) == rotate && free([pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa), pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb)], fs); nextstate(move_belts(r1bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r1bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r2bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r2bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r3bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_belts(r3bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_shuttles(sps, lowered, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_sps(l, fs), shift_inc(l, lowered, shs), ls) whr l = add_neighbour(sps, row_inc) end; nextstate(move_shuttles(sps, lowered, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_sps(l, fs), shift_dec(l, lowered, shs), ls) whr l = add_neighbour(sps, row_dec) end; nextstate(move_shuttles(sps, tilted, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_inc(add_neighbour(sps, row_inc), tilted, shs), ls); nextstate(move_shuttles(sps, tilted, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_dec(add_neighbour(sps, row_dec), tilted, shs), ls); nextstate(tilt_shuttle(sp, so), ok, glob_state(fs, shs, ls)) = glob_state(fs, ins_upd(sp, so, n_avail, ins_upd(sp, not(so), avail, shs)), ls); occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state( if(height(ls) != basement && lh == basement, ins_upd_fps(positions(b_r1lift), occupied, fs), if(height(ls) == basement && lh != basement, ins_upd_fps(positions(b_r1lift), free, fs), fs ) ), shs, make_ls(lh, occupied)); !occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state(fs, shs, make_ls(lh, free)); nextstate(rotate_lift, ok, gs) = gs; nextstate(i, fail, gs) = gs; allowed([], gs) = false; allowed(i |> [], gs) = allowed(i, gs); allowed(i |> j |> is, gs) = allowed(i, gs) && !overlap(i, j |> is) && allowed(j |> is, gs); nextstate([], ok, gs) = gs; nextstate(i |> is, ok, gs) = nextstate(i, ok, nextstate(is, ok, gs)); nextstate(is, fail, gs) = gs; possible(add_car, glob_state(fs, shs, ls)) = ls == lsf_street; possible(remove_car, glob_state(fs, shs, ls)) = ls == lso_street; nextstate(add_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lso_street); nextstate(remove_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lsf_street); act exec: Instruction; occur: Event; proc S(gs_sl: GlobalState) = sum i: Instruction. (valid(i) && allowed(i, gs_sl)) -> exec(i) . S(nextstate(i, ok, gs_sl)) + sum e: Event. possible(e, gs_sl) -> occur(e) . S(nextstate(e, gs_sl)) ; init S(init_gs); mcrl2-201409.0/examples/industrial/garage/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 023350 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on block. [true*]true mcrl2-201409.0/examples/industrial/garage/run.py000770 001750 001750 00000000410 12370120076 021731 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v garage-ver.mcrl2 garage-ver.lps') os.system('lps2pbes -v -f nodeadlock.mcf garage-ver.lps garage-ver.nodeadlock.pbes') os.system('pbes2bool -v garage-ver.nodeadlock.pbes') os.system('lps2lts -v garage-ver.lps garage-ver.aut') mcrl2-201409.0/examples/industrial/garage/garage-r1.mcrl2000770 001750 001750 00000116507 12370120076 023301 0ustar00outisoutis000000 000000 % The following is the specification of the safety layer of the automated % parking garage after reduction 1 as described in [1, Appendices B and C.2]. % % Simulation of this specification is possible, but it is not very effective % because of non-essential message-passing. State space generation is not % possible. % % [1] Aad Mathijssen and A. Johannes Pretorius. Specification, Analysis and % Verification of an Automated Parking Garage. Computer Science Report % 05-25, Eindhoven University of Technology (TU/e), 2005. sort FloorRow = struct r1 | r2 | r3; FloorCol = struct c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10; FloorPosPart = struct pa | pb; FloorPos = struct pos_r1(FloorCol, FloorPosPart) | pos_r2(FloorCol) | pos_r3(FloorCol); FloorPosList = List(FloorPos); ShuttlePos = struct r1a | r2a | r3a | r1b | r2b | r3b; ShuttlePosSet = List(ShuttlePos); % representing a set of ShuttlePos elements ShuttleOrientation = struct lowered | tilted; R1Belt = struct b_r1a_sh | b_r1a | b_r1lift | b_r1b | b_r1b_sh; R2Belt = struct b_r2a_sh | b_r2 | b_r2b_sh; R3Belt = struct b_r3a_sh | b_r3 | b_r3b_sh; R1BeltSet = List(R1Belt); % representing a set of R1Belt elements R2BeltSet = List(R2Belt); % representing a set of R2Belt elements R3BeltSet = List(R3Belt); % representing a set of R3Belt elements DirCol = struct col_inc | col_dec; DirRow = struct row_inc | row_dec; MoveSize = struct full | half; LiftHeight = struct street | rotate | basement; Area = struct area(positions: FloorPosList, tilted_c1: Bool, tilted_c10: Bool); Instruction = struct move_belts(R1BeltSet, DirCol, MoveSize) | move_belts(R2BeltSet, DirCol, MoveSize) | move_belts(R3BeltSet, DirCol, MoveSize) | move_shuttles(ShuttlePosSet, ShuttleOrientation, DirRow) | tilt_shuttle(ShuttlePos, ShuttleOrientation) | move_lift(LiftHeight) | rotate_lift; InstructionSet = List(Instruction); % representing a set of instructions Event = struct add_car | remove_car; ExecResult = struct ok | fail; OccState = struct free | occupied; AvailState = struct avail | n_avail; FloorState = FloorPos -> OccState; ShuttleState = ShuttlePos # ShuttleOrientation -> AvailState; LiftState = struct lsf_street | lso_street | lsf_rotate | lso_rotate | ls_basement; GlobalState = struct glob_state(fs: FloorState, shs: ShuttleState, ls: LiftState); % FloorRow operations map index: FloorRow -> Pos; % index(fra) is the index of fra lt: FloorRow # FloorRow -> Bool; % lt(fra,frb) indicates if fra is less than frb var fra, frb: FloorRow; eqn index(r1) = 1; index(r2) = 2; index(r3) = 3; lt(fra, frb) = index(fra) < index(frb); % FloorCol operations map index: FloorCol -> Pos; % index(fca) is the index of fca lt: FloorCol # FloorCol -> Bool; % lt(fca,fcb) indicates if fca is less than fcb var fca, fcb: FloorCol; eqn index(c1) = 1; index(c2) = 2; index(c3) = 3; index(c4) = 4; index(c5) = 5; index(c6) = 6; index(c7) = 7; index(c8) = 8; index(c9) = 9; index(c10) = 10; lt(fca, fcb) = index(fca) < index(fcb); % FloorPosPart operations map index: FloorPosPart -> Pos; % index(ffpa) is the index of fppa lt: FloorPosPart # FloorPosPart -> Bool; % lt(fppa,fppb) indicates if fppa is less than fppb var fppa, fppb: FloorPosPart; eqn index(pa) = 1; index(pb) = 2; lt(fppa, fppb) = index(fppa) < index(fppb); % FloorPos operations map row: FloorPos -> FloorRow; % row(fpa) is the row of fpa col: FloorPos -> FloorCol; % col(fpa) is the column of fpa part: FloorPos -> FloorPosPart; % part(fpa) is the part of fpa lt: FloorPos # FloorPos -> Bool; % lt(fpa, fpb) indicates if fpa is less than fpb lt_r: FloorPos # FloorPos -> Bool; % lt_r(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) (auxiliary function needed by lt for efficiency) lt_rc: FloorPos # FloorPos -> Bool; % lt_rc(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) and col(fpa) = col(fpb) % (auxiliary function needed by lt_r for efficiency) gt: FloorPos # FloorPos -> Bool; % gt(fpa, fpb) indicates if fpa is greater than fpb var fca: FloorCol; fppa: FloorPosPart; fpa, fpb: FloorPos; eqn row(pos_r1(fca, fppa)) = r1; row(pos_r2(fca)) = r2; row(pos_r3(fca)) = r3; col(pos_r1(fca, fppa)) = fca; col(pos_r2(fca)) = fca; col(pos_r3(fca)) = fca; part(pos_r1(fca, fppa)) = fppa; row(fpa) == row(fpb) -> lt(fpa, fpb) = lt_r(fpa, fpb); row(fpa) != row(fpb) -> lt(fpa, fpb) = lt(row(fpa), row(fpb)); col(fpa) == col(fpb) -> lt_r(fpa, fpb) = lt_rc(fpa, fpb); col(fpa) != col(fpb) -> lt_r(fpa, fpb) = lt(col(fpa), col(fpb)); lt_rc(fpa, fpb) = row(fpa) == r1 && lt(part(fpa), part(fpb)); gt(fpa,fpb) = lt(fpb, fpa); % FloorPosList operations map contains: FloorPos # FloorPosList -> Bool; % contains(fpa, fps) indicates if fps contains fpa overlap: FloorPosList # FloorPosList -> Bool; % overlap(fps, fpt) indicates if the elements of fps and fpt overlap rev: FloorPosList -> FloorPosList; % rev(fps) is the reverse of list fps grev: FloorPosList # FloorPosList -> FloorPosList; % grev(fps, fpt) is the reverse of fps concatenated with fpt % (auxiliary function needed for efficiency by rev) var fpa, fpb: FloorPos; fps, fpt: FloorPosList; eqn contains(fpa, []) = false; contains(fpa, fpa |> fps) = true; fpa != fpb -> contains(fpa, fpb |> fps) = contains(fpa, fps); overlap([], fpt) = false; overlap(fpa |> fps, fpt) = contains(fpa, fpt) || overlap(fps, fpt); rev(fps) = grev(fps, []); grev([], fpt) = fpt; grev(fpa |> fps, fpt) = grev(fps, fpa |> fpt); % ShuttlePos operations map index: ShuttlePos -> Pos; % index(spa) is the index of spa row: ShuttlePos -> FloorRow; % row(spa) is the row of spa col: ShuttlePos -> FloorCol; % col(spa) is the column of spa lt: ShuttlePos # ShuttlePos -> Bool; % lt(spa, spb) indicates if spa is less than spb gt: ShuttlePos # ShuttlePos -> Bool; % gt(spa, spb) indicates if spa is greater than spb positions: ShuttlePos -> FloorPosList; % positions(spa) represents the floor positions corresponding to spa in % lowered position has_neighbour: ShuttlePos # DirRow -> Bool; % has_neighbour(spa, dr) indicates if spa has a successor in direction dr neighbour: ShuttlePos # DirRow -> ShuttlePos; % neighbour(spa, dr) is the neighbour of spa in directrion dr, provided it % exists connected: ShuttlePos # ShuttlePos -> Bool; % connected(spa, spb) indicates if the bottom of spa is connected to the top % of spb var spa, spb: ShuttlePos; eqn index(r1a) = 1; index(r2a) = 2; index(r3a) = 3; index(r1b) = 4; index(r2b) = 5; index(r3b) = 6; row(r1a) = r1; row(r2a) = r2; row(r3a) = r3; row(r1b) = r1; row(r2b) = r2; row(r3b) = r3; col(r1a) = c1; col(r2a) = c1; col(r3a) = c1; col(r1b) = c10; col(r2b) = c10; col(r3b) = c10; lt(spa, spb) = index(spa) < index(spb); gt(spa, spb) = index(spa) > index(spb); positions(r1a) = positions(b_r1a_sh); positions(r2a) = positions(b_r2a_sh); positions(r3a) = positions(b_r3a_sh); positions(r1b) = positions(b_r1b_sh); positions(r2b) = positions(b_r2b_sh); positions(r3b) = positions(b_r3b_sh); has_neighbour(spa, row_inc) = row(spa) != r3; has_neighbour(spa, row_dec) = row(spa) != r1; neighbour(r1a, row_inc) = r2a; neighbour(r2a, row_inc) = r3a; neighbour(r1b, row_inc) = r2b; neighbour(r2b, row_inc) = r3b; neighbour(r2a, row_dec) = r1a; neighbour(r3a, row_dec) = r2a; neighbour(r2b, row_dec) = r1b; neighbour(r3b, row_dec) = r2b; connected(spa, spb) = succ(index(spa)) == index(spb) && col(spa) == col(spb); % ShuttlePosSet operations map is_set_sps: ShuttlePosSet -> Bool; % is_set_sps(sps) indicates if sps is a set % In the remainder of the data equation section, for every ShuttlePosSet sps % is_set_sps(sps) is a precondition. contains: ShuttlePos # ShuttlePosSet -> Bool; % contains(spa, sps) indicates if sps contains spa shuttles: FloorCol -> ShuttlePosSet; % shuttles(fc) represents the shuttle positions corresponding to fc positions_sps: ShuttlePosSet -> FloorPosList; % positions_sps(sps) represents the floor positions corresponding to sps connected_sps: ShuttlePosSet -> Bool; % connected_sps(sps) indicates if all elements of sps are connected has_neighbour: ShuttlePosSet # DirRow -> Bool; % has_neighbour(sps, dr) indicates is sps has a neighbour in direction dr neighbour_sps: ShuttlePosSet # DirRow -> ShuttlePos; % neighbour_sps(sps, dr) is the neighbour of sps in direction dr, provided it % exists add_neighbour: ShuttlePosSet # DirRow -> ShuttlePosSet; % add_neighbour(sps, dr) represents the sps extended with its neighbour in % direction dr, provided it exists var spa, spb: ShuttlePos; sps: ShuttlePosSet; fc: FloorCol; eqn is_set_sps([]) = true; is_set_sps(spa |> []) = true; is_set_sps(spa |> spb |> sps) = lt(spa, spb) && is_set_sps(spb |> sps); contains(spa, []) = false; contains(spa, spa |> sps) = true; spa != spb -> contains(spa, spb |> sps) = contains(spa, sps); shuttles(fc) = if(fc == c1, [r1a,r2a,r3a], if(fc == c10, [r1b,r2b,r3b], [])); positions_sps([]) = []; positions_sps(spa |> sps) = positions(spa) ++ positions_sps(sps); connected_sps([]) = true; connected_sps([spa]) = true; connected_sps(spa |> spb |> sps) = connected(spa, spb) && connected_sps(spb |> sps); has_neighbour(sps, row_inc) = has_neighbour(rhead(sps), row_inc); has_neighbour(sps, row_dec) = has_neighbour(head(sps), row_dec); neighbour_sps(sps, row_inc) = neighbour(rhead(sps), row_inc); neighbour_sps(sps, row_dec) = neighbour(head(sps), row_dec); add_neighbour(sps, row_inc) = sps <| neighbour_sps(sps, row_inc); add_neighbour(sps, row_dec) = neighbour_sps(sps, row_dec) |> sps; % ShuttleOrientation operations map index: ShuttleOrientation -> Pos; % index(soa) is the index of soa lt: ShuttleOrientation # ShuttleOrientation -> Bool; % lt(soa, sob) indicates if soa is less than sob gt: ShuttleOrientation # ShuttleOrientation -> Bool; % gt(soa, sob) indicates if soa is greater than sob not: ShuttleOrientation -> ShuttleOrientation; % not(soa) indicates the opposite of soa var soa, sob: ShuttleOrientation; eqn index(lowered) = 1; index(tilted) = 2; lt(soa, sob) = index(soa) < index(sob); gt(soa, sob) = index(soa) > index(sob); not(lowered) = tilted; not(tilted) = lowered; % Belt operations map index: R1Belt -> Pos; index: R2Belt -> Pos; index: R3Belt -> Pos; % index(ba) is the index of belt ba row: R1Belt -> FloorRow; row: R2Belt -> FloorRow; row: R3Belt -> FloorRow; % row(ba) is the row of belt ba lt: R1Belt # R1Belt -> Bool; lt: R2Belt # R2Belt -> Bool; lt: R3Belt # R3Belt -> Bool; % lt(ba, bb) indicates if belt ba is less than belt bb positions: R1Belt -> FloorPosList; positions: R2Belt -> FloorPosList; positions: R3Belt -> FloorPosList; % positions(ba) represents the positions corresponding to belt ba connected: R1Belt # R1Belt -> Bool; connected: R2Belt # R2Belt -> Bool; connected: R3Belt # R3Belt -> Bool; % connected(ba, bb) indicates if the right of ba is connected to the left % of bb available: R1Belt # ShuttleState # LiftState -> Bool; available: R2Belt # ShuttleState # LiftState -> Bool; available: R3Belt # ShuttleState # LiftState -> Bool; % available(ba, shs, ls) indicates if belt ba is available for states shs % and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; fs: FloorState; shs: ShuttleState; ls: LiftState; ms: MoveSize; eqn index(b_r1a_sh) = 1; index(b_r1a) = 2; index(b_r1lift) = 3; index(b_r1b) = 4; index(b_r1b_sh) = 5; index(b_r2a_sh) = 1; index(b_r2) = 2; index(b_r2b_sh) = 3; index(b_r3a_sh) = 1; index(b_r3) = 2; index(b_r3b_sh) = 3; row(r1ba) = r1; row(r2ba) = r2; row(r3ba) = r3; lt(r1ba, r1bb) = index(r1ba) < index(r1bb); lt(r2ba, r2bb) = index(r2ba) < index(r2bb); lt(r3ba, r3bb) = index(r3ba) < index(r3bb); positions(b_r1a_sh) = [pos_r1(c1, pa), pos_r1(c1, pb)]; positions(b_r1a) = [pos_r1(c2, pa), pos_r1(c2, pb), pos_r1(c3, pa), pos_r1(c3, pb), pos_r1(c4, pa), pos_r1(c4, pb), pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa)]; positions(b_r1lift) = [pos_r1(c6, pb), pos_r1(c7, pa)]; positions(b_r1b) = [pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb), pos_r1(c9, pa), pos_r1(c9, pb)]; positions(b_r1b_sh) = [pos_r1(c10, pa), pos_r1(c10, pb)]; positions(b_r2a_sh) = [pos_r2(c1)]; positions(b_r2) = [pos_r2(c2), pos_r2(c3), pos_r2(c4), pos_r2(c5), pos_r2(c6), pos_r2(c7), pos_r2(c8), pos_r2(c9)]; positions(b_r2b_sh) = [pos_r2(c10)]; positions(b_r3a_sh) = [pos_r3(c1)]; positions(b_r3) = [pos_r3(c2), pos_r3(c3), pos_r3(c4), pos_r3(c5), pos_r3(c6), pos_r3(c7), pos_r3(c8), pos_r3(c9)]; positions(b_r3b_sh) = [pos_r3(c10)]; available(b_r1a_sh, shs, ls) = shs(r1a, lowered) == avail; available(b_r1a, shs, ls) = true; available(b_r1lift, shs, ls) = ls == ls_basement; available(b_r1b, shs, ls) = true; available(b_r1b_sh, shs, ls) = shs(r1b, lowered) == avail; available(b_r2a_sh, shs, ls) = shs(r2a, lowered) == avail; available(b_r2, shs, ls) = true; available(b_r2b_sh, shs, ls) = shs(r2b, lowered) == avail; available(b_r3a_sh, shs, ls) = shs(r3a, lowered) == avail; available(b_r3, shs, ls) = true; available(b_r3b_sh, shs, ls) = shs(r3b, lowered) == avail; % BeltSet operations map is_set_b_r1: R1BeltSet -> Bool; is_set_b_r2: R2BeltSet -> Bool; is_set_b_r3: R3BeltSet -> Bool; % is_set_b_rX(bs) indicates if bs is a set % In the remainder of this data equations section each belt set bs has % is_set_b_rX(bs) as a precondition. contains: R1Belt # R1BeltSet -> Bool; contains: R2Belt # R2BeltSet -> Bool; contains: R3Belt # R3BeltSet -> Bool; % contains(ba, bs) indicates if ba is an element of bs positions_b_r1: R1BeltSet -> FloorPosList; positions_b_r2: R2BeltSet -> FloorPosList; positions_b_r3: R3BeltSet -> FloorPosList; % positions_b_rX(bs) represents the floor positions corresponding to the % belts in bs connected_b_r1: R1BeltSet -> Bool; connected_b_r2: R2BeltSet -> Bool; connected_b_r3: R3BeltSet -> Bool; % connected(bs) indicates if the belts in bs are connected available_b_r1: R1BeltSet # ShuttleState # LiftState -> Bool; available_b_r2: R2BeltSet # ShuttleState # LiftState -> Bool; available_b_r3: R3BeltSet # ShuttleState # LiftState -> Bool; % available_b_rX(bs, shs, ls) indicates if all belts in bs are available for % states shs and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; fs: FloorState; shs: ShuttleState; ls: LiftState; eqn is_set_b_r1([]) = true; is_set_b_r1(r1ba |> []) = true; is_set_b_r1(r1ba |> r1bb |> r1bs) = lt(r1ba, r1bb) && is_set_b_r1(r1bb |> r1bs); is_set_b_r2([]) = true; is_set_b_r2(r2ba |> []) = true; is_set_b_r2(r2ba |> r2bb |> r2bs) = lt(r2ba, r2bb) && is_set_b_r2(r2bb |> r2bs); is_set_b_r3([]) = true; is_set_b_r3(r3ba |> []) = true; is_set_b_r3(r3ba |> r3bb |> r3bs) = lt(r3ba, r3bb) && is_set_b_r3(r3bb |> r3bs); contains(r1ba, []) = false; contains(r1ba, r1ba |> r1bs) = true; r1ba != r1bb -> contains(r1ba, r1bb |> r1bs) = contains(r1ba, r1bs); contains(r2ba, []) = false; contains(r2ba, r2ba |> r2bs) = true; r2ba != r2bb -> contains(r2ba, r2bb |> r2bs) = contains(r2ba, r2bs); contains(r3ba, []) = false; contains(r3ba, r3ba |> r3bs) = true; r3ba != r3bb -> contains(r3ba, r3bb |> r3bs) = contains(r3ba, r3bs); positions_b_r1([]) = []; positions_b_r1(r1ba |> r1bs) = positions(r1ba) ++ positions_b_r1(r1bs); positions_b_r2([]) = []; positions_b_r2(r2ba |> r2bs) = positions(r2ba) ++ positions_b_r2(r2bs); positions_b_r3([]) = []; positions_b_r3(r3ba |> r3bs) = positions(r3ba) ++ positions_b_r3(r3bs); connected_b_r1([]) = true; connected_b_r1(r1ba |> []) = true; connected_b_r1(r1ba |> r1bb |> r1bs) = connected(r1ba, r1bb) && connected_b_r1(r1bb |> r1bs); connected_b_r2([]) = true; connected_b_r2(r2ba |> []) = true; connected_b_r2(r2ba |> r2bb |> r2bs) = connected(r2ba, r2bb) && connected_b_r2(r2bb |> r2bs); connected_b_r3([]) = true; connected_b_r3(r3ba |> []) = true; connected_b_r3(r3ba |> r3bb |> r3bs) = connected(r3ba, r3bb) && connected_b_r3(r3bb |> r3bs); connected(r1ba, r1bb) = succ(index(r1ba)) == index(r1bb); connected(r2ba, r2bb) = succ(index(r2ba)) == index(r2bb); connected(r3ba, r3bb) = succ(index(r3ba)) == index(r3bb); available_b_r1([], shs, ls) = true; available_b_r1(r1ba |> r1bs, shs, ls) = available(r1ba, shs, ls) && available_b_r1(r1bs, shs, ls); available_b_r2([], shs, ls) = true; available_b_r2(r2ba |> r2bs, shs, ls) = available(r2ba, shs, ls) && available_b_r2(r2bs, shs, ls); available_b_r3([], shs, ls) = true; available_b_r3(r3ba |> r3bs, shs, ls) = available(r3ba, shs, ls) && available_b_r3(r3bs, shs, ls); % Area operations map overlap: Area # Area -> Bool; % area(a, b) indicates if area a and b overlap var fps, fpt: FloorPosList; tc1a, tc1b, tc10a, tc10b: Bool; eqn overlap(area(fps, tc1a, tc1b), area(fpt, tc10a, tc10b)) = overlap(fps, fpt) || (tc1a && tc1b) || (tc10a && tc10b); % Instruction operations map index: Instruction -> Pos; % index(i) is the index of instruction i lt: Instruction # Instruction -> Bool; % lt(i, j) indicates if i is less than j valid: Instruction -> Bool; % valid(i) indicates if instruction i is valid area: Instruction -> Area; % area(i) represents the area on which instruction i has any effect overlap: Instruction # Instruction -> Bool; % overlap(i, j) indicates if instruction i and j overlap var r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sp: ShuttlePos; sps: ShuttlePosSet; so: ShuttleOrientation; dr: DirRow; lh: LiftHeight; i,j: Instruction; eqn index(move_belts(r1bs, dc, ms)) = 1; index(move_belts(r2bs, dc, ms)) = 2; index(move_belts(r3bs, dc, ms)) = 3; index(move_shuttles(sps, so, dr)) = 4; index(tilt_shuttle(sp, so)) = 5; index(move_lift(lh)) = 6; index(rotate_lift) = 7; lt(i, j) = index(i) < index(j); valid(move_belts(r1bs, dc, ms)) = is_set_b_r1(r1bs); valid(move_belts(r2bs, dc, ms)) = is_set_b_r2(r2bs); valid(move_belts(r3bs, dc, ms)) = is_set_b_r3(r3bs); valid(move_shuttles(sps, so, dr)) = is_set_sps(sps); valid(tilt_shuttle(sp, so)) = true; valid(move_lift(lh)) = true; valid(rotate_lift) = true; area(move_belts(r1bs, dc, ms)) = area(positions_b_r1(r1bs), false, false); area(move_belts(r2bs, dc, ms)) = area(positions_b_r2(r2bs), false, false); area(move_belts(r3bs, dc, ms)) = area(positions_b_r3(r3bs), false, false); area(move_shuttles(sps, lowered, dr)) = area(positions_sps(add_neighbour(sps, dr)), false, false); area(move_shuttles(sps, tilted, dr)) = area([], col(head(sps)) == c1, col(head(sps)) == c10); area(tilt_shuttle(sp, so)) = area(positions(sp), col(sp) == c1, col(sp) == c10); area(move_lift(lh)) = area(positions(b_r1lift), false, false); area(rotate_lift) = area(positions_b_r1([b_r1a, b_r1lift, b_r1b]), false, false); overlap(i, j) = overlap(area(i), area(j)); % InstructionSet operations map is_set_is: InstructionSet -> Bool; % is_set_is(is) indicates if is is a set % In the remainder of the data equation section, for every InstructionSet is % is_set_is(is) is a precondition. valid: InstructionSet -> Bool; % valid(is) indicates if the instructions in is are valid overlap: Instruction # InstructionSet -> Bool; % overlap(i, is) indicates if instruction i overlaps with any of the % instructions in is var i,j: Instruction; is: InstructionSet; eqn is_set_is([]) = true; is_set_is(i |> []) = true; is_set_is(i |> j |> is) = lt(i, j) && is_set_is(j |> is); valid([]) = true; valid(i |> is) = valid(i) && valid(is); overlap(i, []) = false; overlap(i, j |> is) = overlap(i, j) || overlap(i, is); % AvailState operations map not: AvailState -> AvailState; % not(asa) indicates the opposite of asa eqn not(avail) = n_avail; not(n_avail) = avail; % FloorState operations map init_fs: FloorState; % init_fs is the initial floor state update: FloorPos # OccState # FloorState -> FloorState; cond_upd: FloorPos # OccState # FloorState -> FloorState; ins_upd: FloorPos # OccState # FloorState -> FloorState; % update(fpa, osa, fsa) represents fsa, where position fpa has value osa; % cond_upd and ins_upd are auxiliary functions with the same meaning that % are needed for efficiency ins_upd_fps: FloorPosList # OccState # FloorState -> FloorState; % ins_upd_fps(fps, osa, fsa) represents fsa, where positions fps have value % osa free: FloorPosList # FloorState -> Bool; % free(fps, fsa) indicates that all positions in fps are free for state fsa occupied: FloorPosList # FloorState -> Bool; % occupied(fps, fsa) indicates that all positions in fps are occupied for % state fsa end_free: FloorPosList # DirCol # Bool # FloorState -> Bool; % end_free(fps, dc, obl, fsa) indicates if the end of the list fps in % direction dc is free for state fsa; if obl then the one but last element % also needs to be free even_occ: FloorPosList # FloorState -> Bool; % even_occ(fps, fsa) indicates if the number of occupied positions in fps for % state fsa is even no_half_car: ShuttlePos # FloorState -> Bool; % no_half_car(spa, fsa) indicates if there is a half car positioned on spa % for state fsa no_half_car_sps: ShuttlePosSet # FloorState -> Bool; % no_half_car(sps, fsa) indicates if there is a half car positioned on any % of the elements of sps for state fsa shift_inc: FloorPosList # FloorState -> FloorState; % shift_inc(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the right; the first element in fps % gets state free gshift_inc: FloorPosList # FloorState # OccState -> FloorState; % gshift_inc(fps, fsa, osa) has the same meaning as shift_inc(fps, fsa), with % the exception that the first element in fps gets state osa % (auxiliary function needed by shift_inc) shift_dec: FloorPosList # FloorState -> FloorState; % shift_dec(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the left; the last element in fps gets % state free shift_inc_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_inc_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the right; % if ctw then two positions are shifted shift_dec_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_dec_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the left; % if ctw then two positions are shifted shift_inc_sps: ShuttlePosSet # FloorState -> FloorState; % shift_inc(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position downwards; the first element in sps % gets state free shift_dec_sps: ShuttlePosSet # FloorState -> FloorState; % shift_dec(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position upwards; the last element in sps gets state % free var b: Bool; fsa, fsb: FloorState; fpa, fpb: FloorPos; osa, osb: OccState; fps: FloorPosList; spa: ShuttlePos; sps: ShuttlePosSet; eqn init_fs(fpa) = free; fpa == fpb -> update(fpa, osa, fsa)(fpb) = osa; fpa != fpb -> update(fpa, osa, fsa)(fpb) = fsa(fpb); cond_upd(fpa, osa, fsa) = if(fsa(fpa) == osa, fsa, update(fpa, osa, fsa)); ins_upd(fpa, osa, init_fs) = cond_upd(fpa, osa, init_fs); lt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, update(fpb, osb, fsa)); gt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = update(fpb, osb, ins_upd(fpa, osa, fsa)); fpa == fpb -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, fsa); ins_upd_fps([], osa, fsa) = fsa; ins_upd_fps(fpa |> fps, osa, fsa) = ins_upd(fpa, osa, ins_upd_fps(fps, osa, fsa)); free([], fsa) = true; free(fpa |> fps, fsa) = fsa(fpa) == free && free(fps, fsa); occupied(fpa |> fps, fsa) = fsa(fpa) == occupied && occupied(fps, fsa); occupied([], fsa) = true; end_free(fps, col_inc, false, fsa) = fsa(head(rev(fps))) == free; end_free(fps, col_inc, true, fsa) = fsa(head(l)) == free && fsa(head(tail(l))) == free whr l = rev(fps) end; end_free(fps, col_dec, false, fsa) = fsa(head(fps)) == free; end_free(fps, col_dec, true, fsa) = fsa(head(fps)) == free && fsa(head(tail(fps))) == free; even_occ([], fsa) = true; fsa(fpa) == free -> even_occ(fpa |> fps, fsa) = even_occ(fps, fsa); fsa(fpa) == occupied -> even_occ(fpa |> fps, fsa) = !even_occ(fps, fsa); row(spa) != r1 -> no_half_car(spa, fsa) = true; row(spa) == r1 -> no_half_car(spa, fsa) = even_occ(positions(spa), fsa); no_half_car_sps([], fsa) = true; no_half_car_sps(spa |> sps, fsa) = no_half_car(spa, fsa) && no_half_car_sps(sps, fsa); shift_inc(fps, fsa) = gshift_inc(fps, fsa, free); gshift_inc([], fsa, osa) = fsa; gshift_inc([fpa], fsa, osa) = ins_upd(fpa, osa, fsa); gshift_inc(fpa |> fps, fsa, osa) = ins_upd(fpa, osa, gshift_inc(fps, fsa, fsa(fpa))); shift_dec([], fsa) = fsa; shift_dec([fpa], fsa) = ins_upd(fpa, free, fsa); shift_dec(fpa |> fpb |> fps, fsa) = ins_upd(fpa, fsa(fpb), shift_dec(fpb |> fps, fsa)); shift_inc_ctw(false, fps, fsa) = shift_inc(fps, fsa); shift_inc_ctw(true, fps, fsa) = shift_inc(fps, shift_inc(fps, fsa)); shift_dec_ctw(false, fps, fsa) = shift_dec(fps, fsa); shift_dec_ctw(true, fps, fsa) = shift_dec(fps, shift_dec(fps, fsa)); shift_inc_sps([], fsa) = fsa; row(spa) == r1 -> shift_inc_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), free, shift_inc(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_inc_sps(spa |> sps, fsa) = shift_inc(positions_sps(spa |> sps), fsa); shift_dec_sps([], fsa) = fsa; row(spa) == r1 -> shift_dec_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), fsa(head(positions(head(sps)))), shift_dec(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_dec_sps(spa |> sps, fsa) = shift_dec(positions_sps(spa |> sps), fsa); % ShuttleState operations map init_shs: ShuttleState; % initial shuttle state update: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; cond_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; ins_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; % update(spa, soa, asa, fsa) represents fsa, where position fpa in % orientation soa has value asa; cond_upd and ins_upd are auxiliary functions % with the same meaning that are needed for efficiency available: ShuttlePos # ShuttleOrientation # ShuttleState -> Bool; % available(spa, soa, shs) indicates if shuttle spa is available in % orientation soa for state shs available_sps: ShuttlePosSet # ShuttleOrientation # ShuttleState -> Bool; % available(sps, soa, shs) indicates if all shuttles in sps are available in % orientation soa for state shs shift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_inc(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle downwards in orientation soa; the first % element in sps gets state unavailable gshift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState # AvailState -> ShuttleState; % gshift_inc(sps, soa, shs, asa) has the same meaning as shift_inc(sps, soa, % shs), with the exception that the first element in sps gets state asa % (auxiliary function needed by shift_inc) shift_dec: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_dec(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle upwards in orientation soa; the last % element in sps gets state unavailable var b: Bool; shs, shsa: ShuttleState; spa, spb: ShuttlePos; sps: ShuttlePosSet; soa, sob: ShuttleOrientation; asa, asb: AvailState; eqn init_shs(spa, lowered) = if(row(spa) != r3, avail, n_avail); init_shs(spa, tilted) = if(row(spa) != r3, n_avail, avail); spa == spb && soa == sob -> update(spa, soa, asa, shs)(spb, sob) = asa; spa != spb || soa != sob -> update(spa, soa, asa, shs)(spb, sob) = shs(spb, sob); cond_upd(spa, soa, asa, shs) = if(shs(spa, soa) == asa, shs, update(spa, soa, asa, shs)); ins_upd(spa, soa, asa, init_shs) = cond_upd(spa, soa, asa, init_shs); lt(spa,spb) || (spa == spb && lt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, update(spb, sob, asb, shs)); gt(spa,spb) || (spa == spb && gt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = update(spb, sob, asb, ins_upd(spa, soa, asa, shs)); spa == spb && soa == sob -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, shs); available(spa, soa, shs) = shs(spa, soa) == avail; available_sps([], soa, shs) = true; available_sps(spa |> sps, soa, shs) = available(spa, soa, shs) && available_sps(sps, soa, shs); shift_inc(sps, soa, shs) = gshift_inc(sps, soa, shs, n_avail); gshift_inc([], soa, shs, asa) = shs; gshift_inc([spa], soa, shs, asa) = ins_upd(spa, soa, asa, shs); gshift_inc(spa |> sps, soa, shs, asa) = ins_upd(spa, soa, asa, gshift_inc(sps, soa, shs, shs(spa, soa))); shift_dec([], soa, shs) = shs; shift_dec([spa], soa, shs) = ins_upd(spa, soa, n_avail, shs); shift_dec(spa |> spb |> sps, soa, shs) = ins_upd(spa, soa, shs(spb, soa), shift_dec(spb |> sps, soa, shs)); % LiftState operations map height: LiftState -> LiftHeight; % height(ls) represents the height of state ls occupied: LiftState # FloorState -> Bool; % occupied(ls, fs) indicates if the lift is occupieed for states ls and fs make_ls: LiftHeight # OccState -> LiftState; % make_ls(lh, os) represents the lift state corresponding to height lh and % occupied state os var b: Bool; fsa: FloorState; osa: OccState; eqn height(lsf_street) = street; height(lso_street) = street; height(lsf_rotate) = rotate; height(lso_rotate) = rotate; height(ls_basement) = basement; occupied(lsf_street, fsa) = false; occupied(lso_street, fsa) = true; occupied(lsf_rotate, fsa) = false; occupied(lso_rotate, fsa) = true; occupied(ls_basement, fsa) = occupied(positions(b_r1lift), fsa); make_ls(street, occupied) = lso_street; make_ls(street, free) = lsf_street; make_ls(rotate, occupied) = lso_rotate; make_ls(rotate, free) = lsf_rotate; make_ls(basement, osa) = ls_basement; % GlobalState operations map init_gs: GlobalState; % init_gs is the initial global state allowed: Instruction # GlobalState -> Bool; % allowed(i, gs) indicates if instruction i is allowed given global state gs nextstate: Instruction # ExecResult # GlobalState -> GlobalState; % nextstate(i, r, gs) represents the global state after execution of % instruction i with result r in state gs allowed: InstructionSet # GlobalState -> Bool; % allowed(is, gs) indicates if instruction set is is allowed given global % state gs nextstate: InstructionSet # ExecResult # GlobalState -> GlobalState; % nextstate(is, r, gs) represents the global state after execution of % instruction set is with result r in state gs possible: Event # GlobalState -> Bool; % possible(e, gs) indicates if event e is possible given global state gs nextstate: Event # GlobalState -> GlobalState; % nextstate(e, gs) represents the global state after the event e has occurred % in state gs var gs, gsa: GlobalState; fs, fsa: FloorState; shs, shsa: ShuttleState; ls, lsa: LiftState; lh, lha: LiftHeight; p,q: FloorPos; s,t: OccState; i,j: Instruction; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sps: ShuttlePosSet; dr: DirRow; sp, spa, spb: ShuttlePos; so: ShuttleOrientation; is: InstructionSet; eqn init_gs = glob_state( init_fs, init_shs, lsf_street); allowed(move_belts(r1bs, dc, ms), glob_state(fs, shs, ls)) = r1bs != [] && connected_b_r1(r1bs) && available_b_r1(r1bs, shs, ls) && end_free(l, dc, ms == full, fs) && even_occ(l, fs) whr l = positions_b_r1(r1bs) end; allowed(move_belts(r2bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r2bs != [] && connected_b_r2(r2bs) && available_b_r2(r2bs, shs, ls) && end_free(positions_b_r2(r2bs), dc, false, fs); allowed(move_belts(r3bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r3bs != [] && connected_b_r3(r3bs) && available_b_r3(r3bs, shs, ls) && end_free(positions_b_r3(r3bs), dc, false, fs); allowed(move_shuttles(sps, so, dr), glob_state(fs, shs, ls)) = sps != [] && connected_sps(sps) && available_sps(sps, so, shs) && % placing a comment in front of the following conjunct allows the shuttles % to be moved even if a car is placed half on the shuttle (so == lowered => no_half_car_sps(sps, fs)) && has_neighbour(sps, dr) && !available(neighbour_sps(sps, dr), so, shs); allowed(tilt_shuttle(sp, lowered), glob_state(fs, shs, ls)) = available_sps(shuttles(col(sp)), lowered, shs) && free(positions(sp), fs); allowed(tilt_shuttle(sp, tilted), glob_state(fs, shs, ls)) = shs(sp, tilted) == avail && shs(sp, lowered) == n_avail; ls == ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls) && % replacing the following conjunct by % even_occ(positions(b_r1lift), fs); % allows the lift to move up if two cars are placed half on the lift belt if(free(positions(b_r1lift), fs), true, even_occ(positions_b_r1([b_r1a_sh, b_r1a]), fs) && even_occ(positions_b_r1([b_r1b, b_r1b_sh]), fs)); ls != ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls); allowed(rotate_lift, glob_state(fs, shs, ls)) = height(ls) == rotate && free([pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa), pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb)], fs); nextstate(move_belts(r1bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r1bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r2bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r2bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r3bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_belts(r3bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_shuttles(sps, lowered, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_sps(l, fs), shift_inc(l, lowered, shs), ls) whr l = add_neighbour(sps, row_inc) end; nextstate(move_shuttles(sps, lowered, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_sps(l, fs), shift_dec(l, lowered, shs), ls) whr l = add_neighbour(sps, row_dec) end; nextstate(move_shuttles(sps, tilted, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_inc(add_neighbour(sps, row_inc), tilted, shs), ls); nextstate(move_shuttles(sps, tilted, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_dec(add_neighbour(sps, row_dec), tilted, shs), ls); nextstate(tilt_shuttle(sp, so), ok, glob_state(fs, shs, ls)) = glob_state(fs, ins_upd(sp, so, n_avail, ins_upd(sp, not(so), avail, shs)), ls); occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state( if(height(ls) != basement && lh == basement, ins_upd_fps(positions(b_r1lift), occupied, fs), if(height(ls) == basement && lh != basement, ins_upd_fps(positions(b_r1lift), free, fs), fs ) ), shs, make_ls(lh, occupied)); !occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state(fs, shs, make_ls(lh, free)); nextstate(rotate_lift, ok, gs) = gs; nextstate(i, fail, gs) = gs; allowed([], gs) = false; allowed(i |> [], gs) = allowed(i, gs); allowed(i |> j |> is, gs) = allowed(i, gs) && !overlap(i, j |> is) && allowed(j |> is, gs); nextstate([], ok, gs) = gs; nextstate(i |> is, ok, gs) = nextstate(i, ok, nextstate(is, ok, gs)); nextstate(is, fail, gs) = gs; possible(add_car, glob_state(fs, shs, ls)) = ls == lsf_street; possible(remove_car, glob_state(fs, shs, ls)) = ls == lso_street; nextstate(add_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lso_street); nextstate(remove_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lsf_street); sort ProcState = struct ps_idle | ps_await_state | ps_ack_deny | ps_req | ps_exec | ps_ack_exec; Layer = struct logical | safety | hardware; act snd_req, rcv_req, com_req: Layer # Layer # Instruction; snd_ack_req, rcv_ack_req, com_ack_req: Layer # Layer # Instruction; snd_deny_req, rcv_deny_req, com_deny_req: Layer # Layer # Instruction; snd_ack_exec, rcv_ack_exec, ack_exec:Layer # Layer # Instruction # ExecResult; snd_state, rcv_state, com_state: Layer # Layer # GlobalState; snd_event, rcv_event, com_event: Layer # Layer # Event; proc SL(ps: ProcState, gs_sl: GlobalState, i: Instruction, r: ExecResult) = (ps == ps_idle) -> (sum j: Instruction. valid(j) -> rcv_req(logical, safety, j) . SL(ps_ack_deny, gs_sl, j, r) ) + (ps == ps_await_state) -> (sum gs: GlobalState. rcv_state(hardware, safety, gs). SL(ps_ack_deny, gs, i, r) ) + (ps == ps_ack_deny) -> (allowed(i, gs_sl) -> (snd_ack_req(safety, logical, i) . SL(ps_req, gs_sl, i, r)) <> (snd_deny_req(safety, logical, i). SL(ps_idle, gs_sl, i, r))) + (ps == ps_req) -> snd_req(safety, hardware, i) . SL(ps_exec, gs_sl, i, r) + (ps == ps_exec) -> (sum ra: ExecResult. rcv_ack_exec(safety, hardware, i, ra). SL(ps_ack_exec, nextstate(i, ra, gs_sl), i, ra) ) + (ps == ps_ack_exec) -> snd_ack_exec(safety, logical, i, r) . SL(ps_idle, gs_sl, i, r) + (ps == ps_idle) -> (sum e: Event. possible(e, gs_sl) -> rcv_event(hardware, safety, e) . SL(ps, nextstate(e, gs_sl), i, r) ) ; init SL(ps_idle, init_gs, move_lift(street), ok); mcrl2-201409.0/examples/industrial/garage/garage-r2.mcrl2000770 001750 001750 00000114144 12370120076 023275 0ustar00outisoutis000000 000000 % The following is the specification of the safety layer of the automated % parking garage after reduction 2 as described in [1, Appendices B and C.3]. % % Simulation of this specification is possible. When used in combination with % the corresponding visualisation plugin, it is an effective way to get a % feeling for the specification. % % State space generation is not possible, because the state space consists of % 6,4 * 10^11 (640 billion) states, and a multiple of this in transitions. % % [1] Aad Mathijssen and A. Johannes Pretorius. Specification, Analysis and % Verification of an Automated Parking Garage. Computer Science Report % 05-25, Eindhoven University of Technology (TU/e), 2005. sort FloorRow = struct r1 | r2 | r3; FloorCol = struct c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10; FloorPosPart = struct pa | pb; FloorPos = struct pos_r1(FloorCol, FloorPosPart) | pos_r2(FloorCol) | pos_r3(FloorCol); FloorPosList = List(FloorPos); ShuttlePos = struct r1a | r2a | r3a | r1b | r2b | r3b; ShuttlePosSet = List(ShuttlePos); % representing a set of ShuttlePos elements ShuttleOrientation = struct lowered | tilted; R1Belt = struct b_r1a_sh | b_r1a | b_r1lift | b_r1b | b_r1b_sh; R2Belt = struct b_r2a_sh | b_r2 | b_r2b_sh; R3Belt = struct b_r3a_sh | b_r3 | b_r3b_sh; R1BeltSet = List(R1Belt); % representing a set of R1Belt elements R2BeltSet = List(R2Belt); % representing a set of R2Belt elements R3BeltSet = List(R3Belt); % representing a set of R3Belt elements DirCol = struct col_inc | col_dec; DirRow = struct row_inc | row_dec; MoveSize = struct full | half; LiftHeight = struct street | rotate | basement; Area = struct area(positions: FloorPosList, tilted_c1: Bool, tilted_c10: Bool); Instruction = struct move_belts(R1BeltSet, DirCol, MoveSize) | move_belts(R2BeltSet, DirCol, MoveSize) | move_belts(R3BeltSet, DirCol, MoveSize) | move_shuttles(ShuttlePosSet, ShuttleOrientation, DirRow) | tilt_shuttle(ShuttlePos, ShuttleOrientation) | move_lift(LiftHeight) | rotate_lift; InstructionSet = List(Instruction); % representing a set of instructions Event = struct add_car | remove_car; ExecResult = struct ok | fail; OccState = struct free | occupied; AvailState = struct avail | n_avail; FloorState = FloorPos -> OccState; ShuttleState = ShuttlePos # ShuttleOrientation -> AvailState; LiftState = struct lsf_street | lso_street | lsf_rotate | lso_rotate | ls_basement; GlobalState = struct glob_state(fs: FloorState, shs: ShuttleState, ls: LiftState); % FloorRow operations map index: FloorRow -> Pos; % index(fra) is the index of fra lt: FloorRow # FloorRow -> Bool; % lt(fra,frb) indicates if fra is less than frb var fra, frb: FloorRow; eqn index(r1) = 1; index(r2) = 2; index(r3) = 3; lt(fra, frb) = index(fra) < index(frb); % FloorCol operations map index: FloorCol -> Pos; % index(fca) is the index of fca lt: FloorCol # FloorCol -> Bool; % lt(fca,fcb) indicates if fca is less than fcb var fca, fcb: FloorCol; eqn index(c1) = 1; index(c2) = 2; index(c3) = 3; index(c4) = 4; index(c5) = 5; index(c6) = 6; index(c7) = 7; index(c8) = 8; index(c9) = 9; index(c10) = 10; lt(fca, fcb) = index(fca) < index(fcb); % FloorPosPart operations map index: FloorPosPart -> Pos; % index(ffpa) is the index of fppa lt: FloorPosPart # FloorPosPart -> Bool; % lt(fppa,fppb) indicates if fppa is less than fppb var fppa, fppb: FloorPosPart; eqn index(pa) = 1; index(pb) = 2; lt(fppa, fppb) = index(fppa) < index(fppb); % FloorPos operations map row: FloorPos -> FloorRow; % row(fpa) is the row of fpa col: FloorPos -> FloorCol; % col(fpa) is the column of fpa part: FloorPos -> FloorPosPart; % part(fpa) is the part of fpa lt: FloorPos # FloorPos -> Bool; % lt(fpa, fpb) indicates if fpa is less than fpb lt_r: FloorPos # FloorPos -> Bool; % lt_r(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) (auxiliary function needed by lt for efficiency) lt_rc: FloorPos # FloorPos -> Bool; % lt_rc(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) and col(fpa) = col(fpb) % (auxiliary function needed by lt_r for efficiency) gt: FloorPos # FloorPos -> Bool; % gt(fpa, fpb) indicates if fpa is greater than fpb var fca: FloorCol; fppa: FloorPosPart; fpa, fpb: FloorPos; eqn row(pos_r1(fca, fppa)) = r1; row(pos_r2(fca)) = r2; row(pos_r3(fca)) = r3; col(pos_r1(fca, fppa)) = fca; col(pos_r2(fca)) = fca; col(pos_r3(fca)) = fca; part(pos_r1(fca, fppa)) = fppa; row(fpa) == row(fpb) -> lt(fpa, fpb) = lt_r(fpa, fpb); row(fpa) != row(fpb) -> lt(fpa, fpb) = lt(row(fpa), row(fpb)); col(fpa) == col(fpb) -> lt_r(fpa, fpb) = lt_rc(fpa, fpb); col(fpa) != col(fpb) -> lt_r(fpa, fpb) = lt(col(fpa), col(fpb)); lt_rc(fpa, fpb) = row(fpa) == r1 && lt(part(fpa), part(fpb)); gt(fpa,fpb) = lt(fpb, fpa); % FloorPosList operations map contains: FloorPos # FloorPosList -> Bool; % contains(fpa, fps) indicates if fps contains fpa overlap: FloorPosList # FloorPosList -> Bool; % overlap(fps, fpt) indicates if the elements of fps and fpt overlap rev: FloorPosList -> FloorPosList; % rev(fps) is the reverse of list fps grev: FloorPosList # FloorPosList -> FloorPosList; % grev(fps, fpt) is the reverse of fps concatenated with fpt % (auxiliary function needed for efficiency by rev) var fpa, fpb: FloorPos; fps, fpt: FloorPosList; eqn contains(fpa, []) = false; contains(fpa, fpa |> fps) = true; fpa != fpb -> contains(fpa, fpb |> fps) = contains(fpa, fps); overlap([], fpt) = false; overlap(fpa |> fps, fpt) = contains(fpa, fpt) || overlap(fps, fpt); rev(fps) = grev(fps, []); grev([], fpt) = fpt; grev(fpa |> fps, fpt) = grev(fps, fpa |> fpt); % ShuttlePos operations map index: ShuttlePos -> Pos; % index(spa) is the index of spa row: ShuttlePos -> FloorRow; % row(spa) is the row of spa col: ShuttlePos -> FloorCol; % col(spa) is the column of spa lt: ShuttlePos # ShuttlePos -> Bool; % lt(spa, spb) indicates if spa is less than spb gt: ShuttlePos # ShuttlePos -> Bool; % gt(spa, spb) indicates if spa is greater than spb positions: ShuttlePos -> FloorPosList; % positions(spa) represents the floor positions corresponding to spa in % lowered position has_neighbour: ShuttlePos # DirRow -> Bool; % has_neighbour(spa, dr) indicates if spa has a successor in direction dr neighbour: ShuttlePos # DirRow -> ShuttlePos; % neighbour(spa, dr) is the neighbour of spa in directrion dr, provided it % exists connected: ShuttlePos # ShuttlePos -> Bool; % connected(spa, spb) indicates if the bottom of spa is connected to the top % of spb var spa, spb: ShuttlePos; eqn index(r1a) = 1; index(r2a) = 2; index(r3a) = 3; index(r1b) = 4; index(r2b) = 5; index(r3b) = 6; row(r1a) = r1; row(r2a) = r2; row(r3a) = r3; row(r1b) = r1; row(r2b) = r2; row(r3b) = r3; col(r1a) = c1; col(r2a) = c1; col(r3a) = c1; col(r1b) = c10; col(r2b) = c10; col(r3b) = c10; lt(spa, spb) = index(spa) < index(spb); gt(spa, spb) = index(spa) > index(spb); positions(r1a) = positions(b_r1a_sh); positions(r2a) = positions(b_r2a_sh); positions(r3a) = positions(b_r3a_sh); positions(r1b) = positions(b_r1b_sh); positions(r2b) = positions(b_r2b_sh); positions(r3b) = positions(b_r3b_sh); has_neighbour(spa, row_inc) = row(spa) != r3; has_neighbour(spa, row_dec) = row(spa) != r1; neighbour(r1a, row_inc) = r2a; neighbour(r2a, row_inc) = r3a; neighbour(r1b, row_inc) = r2b; neighbour(r2b, row_inc) = r3b; neighbour(r2a, row_dec) = r1a; neighbour(r3a, row_dec) = r2a; neighbour(r2b, row_dec) = r1b; neighbour(r3b, row_dec) = r2b; connected(spa, spb) = succ(index(spa)) == index(spb) && col(spa) == col(spb); % ShuttlePosSet operations map is_set_sps: ShuttlePosSet -> Bool; % is_set_sps(sps) indicates if sps is a set % In the remainder of the data equation section, for every ShuttlePosSet sps % is_set_sps(sps) is a precondition. contains: ShuttlePos # ShuttlePosSet -> Bool; % contains(spa, sps) indicates if sps contains spa shuttles: FloorCol -> ShuttlePosSet; % shuttles(fc) represents the shuttle positions corresponding to fc positions_sps: ShuttlePosSet -> FloorPosList; % positions_sps(sps) represents the floor positions corresponding to sps connected_sps: ShuttlePosSet -> Bool; % connected_sps(sps) indicates if all elements of sps are connected has_neighbour: ShuttlePosSet # DirRow -> Bool; % has_neighbour(sps, dr) indicates is sps has a neighbour in direction dr neighbour_sps: ShuttlePosSet # DirRow -> ShuttlePos; % neighbour_sps(sps, dr) is the neighbour of sps in direction dr, provided it % exists add_neighbour: ShuttlePosSet # DirRow -> ShuttlePosSet; % add_neighbour(sps, dr) represents the sps extended with its neighbour in % direction dr, provided it exists var spa, spb: ShuttlePos; sps: ShuttlePosSet; fc: FloorCol; eqn is_set_sps([]) = true; is_set_sps(spa |> []) = true; is_set_sps(spa |> spb |> sps) = lt(spa, spb) && is_set_sps(spb |> sps); contains(spa, []) = false; contains(spa, spa |> sps) = true; spa != spb -> contains(spa, spb |> sps) = contains(spa, sps); shuttles(fc) = if(fc == c1, [r1a,r2a,r3a], if(fc == c10, [r1b,r2b,r3b], [])); positions_sps([]) = []; positions_sps(spa |> sps) = positions(spa) ++ positions_sps(sps); connected_sps([]) = true; connected_sps([spa]) = true; connected_sps(spa |> spb |> sps) = connected(spa, spb) && connected_sps(spb |> sps); has_neighbour(sps, row_inc) = has_neighbour(rhead(sps), row_inc); has_neighbour(sps, row_dec) = has_neighbour(head(sps), row_dec); neighbour_sps(sps, row_inc) = neighbour(rhead(sps), row_inc); neighbour_sps(sps, row_dec) = neighbour(head(sps), row_dec); add_neighbour(sps, row_inc) = sps <| neighbour_sps(sps, row_inc); add_neighbour(sps, row_dec) = neighbour_sps(sps, row_dec) |> sps; % ShuttleOrientation operations map index: ShuttleOrientation -> Pos; % index(soa) is the index of soa lt: ShuttleOrientation # ShuttleOrientation -> Bool; % lt(soa, sob) indicates if soa is less than sob gt: ShuttleOrientation # ShuttleOrientation -> Bool; % gt(soa, sob) indicates if soa is greater than sob not: ShuttleOrientation -> ShuttleOrientation; % not(soa) indicates the opposite of soa var soa, sob: ShuttleOrientation; eqn index(lowered) = 1; index(tilted) = 2; lt(soa, sob) = index(soa) < index(sob); gt(soa, sob) = index(soa) > index(sob); not(lowered) = tilted; not(tilted) = lowered; % Belt operations map index: R1Belt -> Pos; index: R2Belt -> Pos; index: R3Belt -> Pos; % index(ba) is the index of belt ba row: R1Belt -> FloorRow; row: R2Belt -> FloorRow; row: R3Belt -> FloorRow; % row(ba) is the row of belt ba lt: R1Belt # R1Belt -> Bool; lt: R2Belt # R2Belt -> Bool; lt: R3Belt # R3Belt -> Bool; % lt(ba, bb) indicates if belt ba is less than belt bb positions: R1Belt -> FloorPosList; positions: R2Belt -> FloorPosList; positions: R3Belt -> FloorPosList; % positions(ba) represents the positions corresponding to belt ba connected: R1Belt # R1Belt -> Bool; connected: R2Belt # R2Belt -> Bool; connected: R3Belt # R3Belt -> Bool; % connected(ba, bb) indicates if the right of ba is connected to the left % of bb available: R1Belt # ShuttleState # LiftState -> Bool; available: R2Belt # ShuttleState # LiftState -> Bool; available: R3Belt # ShuttleState # LiftState -> Bool; % available(ba, shs, ls) indicates if belt ba is available for states shs % and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; fs: FloorState; shs: ShuttleState; ls: LiftState; ms: MoveSize; eqn index(b_r1a_sh) = 1; index(b_r1a) = 2; index(b_r1lift) = 3; index(b_r1b) = 4; index(b_r1b_sh) = 5; index(b_r2a_sh) = 1; index(b_r2) = 2; index(b_r2b_sh) = 3; index(b_r3a_sh) = 1; index(b_r3) = 2; index(b_r3b_sh) = 3; row(r1ba) = r1; row(r2ba) = r2; row(r3ba) = r3; lt(r1ba, r1bb) = index(r1ba) < index(r1bb); lt(r2ba, r2bb) = index(r2ba) < index(r2bb); lt(r3ba, r3bb) = index(r3ba) < index(r3bb); positions(b_r1a_sh) = [pos_r1(c1, pa), pos_r1(c1, pb)]; positions(b_r1a) = [pos_r1(c2, pa), pos_r1(c2, pb), pos_r1(c3, pa), pos_r1(c3, pb), pos_r1(c4, pa), pos_r1(c4, pb), pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa)]; positions(b_r1lift) = [pos_r1(c6, pb), pos_r1(c7, pa)]; positions(b_r1b) = [pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb), pos_r1(c9, pa), pos_r1(c9, pb)]; positions(b_r1b_sh) = [pos_r1(c10, pa), pos_r1(c10, pb)]; positions(b_r2a_sh) = [pos_r2(c1)]; positions(b_r2) = [pos_r2(c2), pos_r2(c3), pos_r2(c4), pos_r2(c5), pos_r2(c6), pos_r2(c7), pos_r2(c8), pos_r2(c9)]; positions(b_r2b_sh) = [pos_r2(c10)]; positions(b_r3a_sh) = [pos_r3(c1)]; positions(b_r3) = [pos_r3(c2), pos_r3(c3), pos_r3(c4), pos_r3(c5), pos_r3(c6), pos_r3(c7), pos_r3(c8), pos_r3(c9)]; positions(b_r3b_sh) = [pos_r3(c10)]; available(b_r1a_sh, shs, ls) = shs(r1a, lowered) == avail; available(b_r1a, shs, ls) = true; available(b_r1lift, shs, ls) = ls == ls_basement; available(b_r1b, shs, ls) = true; available(b_r1b_sh, shs, ls) = shs(r1b, lowered) == avail; available(b_r2a_sh, shs, ls) = shs(r2a, lowered) == avail; available(b_r2, shs, ls) = true; available(b_r2b_sh, shs, ls) = shs(r2b, lowered) == avail; available(b_r3a_sh, shs, ls) = shs(r3a, lowered) == avail; available(b_r3, shs, ls) = true; available(b_r3b_sh, shs, ls) = shs(r3b, lowered) == avail; % BeltSet operations map is_set_b_r1: R1BeltSet -> Bool; is_set_b_r2: R2BeltSet -> Bool; is_set_b_r3: R3BeltSet -> Bool; % is_set_b_rX(bs) indicates if bs is a set % In the remainder of this data equations section each belt set bs has % is_set_b_rX(bs) as a precondition. contains: R1Belt # R1BeltSet -> Bool; contains: R2Belt # R2BeltSet -> Bool; contains: R3Belt # R3BeltSet -> Bool; % contains(ba, bs) indicates if ba is an element of bs positions_b_r1: R1BeltSet -> FloorPosList; positions_b_r2: R2BeltSet -> FloorPosList; positions_b_r3: R3BeltSet -> FloorPosList; % positions_b_rX(bs) represents the floor positions corresponding to the % belts in bs connected_b_r1: R1BeltSet -> Bool; connected_b_r2: R2BeltSet -> Bool; connected_b_r3: R3BeltSet -> Bool; % connected(bs) indicates if the belts in bs are connected available_b_r1: R1BeltSet # ShuttleState # LiftState -> Bool; available_b_r2: R2BeltSet # ShuttleState # LiftState -> Bool; available_b_r3: R3BeltSet # ShuttleState # LiftState -> Bool; % available_b_rX(bs, shs, ls) indicates if all belts in bs are available for % states shs and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; fs: FloorState; shs: ShuttleState; ls: LiftState; eqn is_set_b_r1([]) = true; is_set_b_r1(r1ba |> []) = true; is_set_b_r1(r1ba |> r1bb |> r1bs) = lt(r1ba, r1bb) && is_set_b_r1(r1bb |> r1bs); is_set_b_r2([]) = true; is_set_b_r2(r2ba |> []) = true; is_set_b_r2(r2ba |> r2bb |> r2bs) = lt(r2ba, r2bb) && is_set_b_r2(r2bb |> r2bs); is_set_b_r3([]) = true; is_set_b_r3(r3ba |> []) = true; is_set_b_r3(r3ba |> r3bb |> r3bs) = lt(r3ba, r3bb) && is_set_b_r3(r3bb |> r3bs); contains(r1ba, []) = false; contains(r1ba, r1ba |> r1bs) = true; r1ba != r1bb -> contains(r1ba, r1bb |> r1bs) = contains(r1ba, r1bs); contains(r2ba, []) = false; contains(r2ba, r2ba |> r2bs) = true; r2ba != r2bb -> contains(r2ba, r2bb |> r2bs) = contains(r2ba, r2bs); contains(r3ba, []) = false; contains(r3ba, r3ba |> r3bs) = true; r3ba != r3bb -> contains(r3ba, r3bb |> r3bs) = contains(r3ba, r3bs); positions_b_r1([]) = []; positions_b_r1(r1ba |> r1bs) = positions(r1ba) ++ positions_b_r1(r1bs); positions_b_r2([]) = []; positions_b_r2(r2ba |> r2bs) = positions(r2ba) ++ positions_b_r2(r2bs); positions_b_r3([]) = []; positions_b_r3(r3ba |> r3bs) = positions(r3ba) ++ positions_b_r3(r3bs); connected_b_r1([]) = true; connected_b_r1(r1ba |> []) = true; connected_b_r1(r1ba |> r1bb |> r1bs) = connected(r1ba, r1bb) && connected_b_r1(r1bb |> r1bs); connected_b_r2([]) = true; connected_b_r2(r2ba |> []) = true; connected_b_r2(r2ba |> r2bb |> r2bs) = connected(r2ba, r2bb) && connected_b_r2(r2bb |> r2bs); connected_b_r3([]) = true; connected_b_r3(r3ba |> []) = true; connected_b_r3(r3ba |> r3bb |> r3bs) = connected(r3ba, r3bb) && connected_b_r3(r3bb |> r3bs); connected(r1ba, r1bb) = succ(index(r1ba)) == index(r1bb); connected(r2ba, r2bb) = succ(index(r2ba)) == index(r2bb); connected(r3ba, r3bb) = succ(index(r3ba)) == index(r3bb); available_b_r1([], shs, ls) = true; available_b_r1(r1ba |> r1bs, shs, ls) = available(r1ba, shs, ls) && available_b_r1(r1bs, shs, ls); available_b_r2([], shs, ls) = true; available_b_r2(r2ba |> r2bs, shs, ls) = available(r2ba, shs, ls) && available_b_r2(r2bs, shs, ls); available_b_r3([], shs, ls) = true; available_b_r3(r3ba |> r3bs, shs, ls) = available(r3ba, shs, ls) && available_b_r3(r3bs, shs, ls); % Area operations map overlap: Area # Area -> Bool; % area(a, b) indicates if area a and b overlap var fps, fpt: FloorPosList; tc1a, tc1b, tc10a, tc10b: Bool; eqn overlap(area(fps, tc1a, tc1b), area(fpt, tc10a, tc10b)) = overlap(fps, fpt) || (tc1a && tc1b) || (tc10a && tc10b); % Instruction operations map index: Instruction -> Pos; % index(i) is the index of instruction i lt: Instruction # Instruction -> Bool; % lt(i, j) indicates if i is less than j valid: Instruction -> Bool; % valid(i) indicates if instruction i is valid area: Instruction -> Area; % area(i) represents the area on which instruction i has any effect overlap: Instruction # Instruction -> Bool; % overlap(i, j) indicates if instruction i and j overlap var r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sp: ShuttlePos; sps: ShuttlePosSet; so: ShuttleOrientation; dr: DirRow; lh: LiftHeight; i,j: Instruction; eqn index(move_belts(r1bs, dc, ms)) = 1; index(move_belts(r2bs, dc, ms)) = 2; index(move_belts(r3bs, dc, ms)) = 3; index(move_shuttles(sps, so, dr)) = 4; index(tilt_shuttle(sp, so)) = 5; index(move_lift(lh)) = 6; index(rotate_lift) = 7; lt(i, j) = index(i) < index(j); valid(move_belts(r1bs, dc, ms)) = is_set_b_r1(r1bs); valid(move_belts(r2bs, dc, ms)) = is_set_b_r2(r2bs); valid(move_belts(r3bs, dc, ms)) = is_set_b_r3(r3bs); valid(move_shuttles(sps, so, dr)) = is_set_sps(sps); valid(tilt_shuttle(sp, so)) = true; valid(move_lift(lh)) = true; valid(rotate_lift) = true; area(move_belts(r1bs, dc, ms)) = area(positions_b_r1(r1bs), false, false); area(move_belts(r2bs, dc, ms)) = area(positions_b_r2(r2bs), false, false); area(move_belts(r3bs, dc, ms)) = area(positions_b_r3(r3bs), false, false); area(move_shuttles(sps, lowered, dr)) = area(positions_sps(add_neighbour(sps, dr)), false, false); area(move_shuttles(sps, tilted, dr)) = area([], col(head(sps)) == c1, col(head(sps)) == c10); area(tilt_shuttle(sp, so)) = area(positions(sp), col(sp) == c1, col(sp) == c10); area(move_lift(lh)) = area(positions(b_r1lift), false, false); area(rotate_lift) = area(positions_b_r1([b_r1a, b_r1lift, b_r1b]), false, false); overlap(i, j) = overlap(area(i), area(j)); % InstructionSet operations map is_set_is: InstructionSet -> Bool; % is_set_is(is) indicates if is is a set % In the remainder of the data equation section, for every InstructionSet is % is_set_is(is) is a precondition. valid: InstructionSet -> Bool; % valid(is) indicates if the instructions in is are valid overlap: Instruction # InstructionSet -> Bool; % overlap(i, is) indicates if instruction i overlaps with any of the % instructions in is var i,j: Instruction; is: InstructionSet; eqn is_set_is([]) = true; is_set_is(i |> []) = true; is_set_is(i |> j |> is) = lt(i, j) && is_set_is(j |> is); valid([]) = true; valid(i |> is) = valid(i) && valid(is); overlap(i, []) = false; overlap(i, j |> is) = overlap(i, j) || overlap(i, is); % AvailState operations map not: AvailState -> AvailState; % not(asa) indicates the opposite of asa eqn not(avail) = n_avail; not(n_avail) = avail; % FloorState operations map init_fs: FloorState; % init_fs is the initial floor state update: FloorPos # OccState # FloorState -> FloorState; cond_upd: FloorPos # OccState # FloorState -> FloorState; ins_upd: FloorPos # OccState # FloorState -> FloorState; % update(fpa, osa, fsa) represents fsa, where position fpa has value osa; % cond_upd and ins_upd are auxiliary functions with the same meaning that % are needed for efficiency ins_upd_fps: FloorPosList # OccState # FloorState -> FloorState; % ins_upd_fps(fps, osa, fsa) represents fsa, where positions fps have value % osa free: FloorPosList # FloorState -> Bool; % free(fps, fsa) indicates that all positions in fps are free for state fsa occupied: FloorPosList # FloorState -> Bool; % occupied(fps, fsa) indicates that all positions in fps are occupied for % state fsa end_free: FloorPosList # DirCol # Bool # FloorState -> Bool; % end_free(fps, dc, obl, fsa) indicates if the end of the list fps in % direction dc is free for state fsa; if obl then the one but last element % also needs to be free even_occ: FloorPosList # FloorState -> Bool; % even_occ(fps, fsa) indicates if the number of occupied positions in fps for % state fsa is even no_half_car: ShuttlePos # FloorState -> Bool; % no_half_car(spa, fsa) indicates if there is a half car positioned on spa % for state fsa no_half_car_sps: ShuttlePosSet # FloorState -> Bool; % no_half_car(sps, fsa) indicates if there is a half car positioned on any % of the elements of sps for state fsa shift_inc: FloorPosList # FloorState -> FloorState; % shift_inc(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the right; the first element in fps % gets state free gshift_inc: FloorPosList # FloorState # OccState -> FloorState; % gshift_inc(fps, fsa, osa) has the same meaning as shift_inc(fps, fsa), with % the exception that the first element in fps gets state osa % (auxiliary function needed by shift_inc) shift_dec: FloorPosList # FloorState -> FloorState; % shift_dec(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the left; the last element in fps gets % state free shift_inc_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_inc_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the right; % if ctw then two positions are shifted shift_dec_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_dec_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the left; % if ctw then two positions are shifted shift_inc_sps: ShuttlePosSet # FloorState -> FloorState; % shift_inc(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position downwards; the first element in sps % gets state free shift_dec_sps: ShuttlePosSet # FloorState -> FloorState; % shift_dec(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position upwards; the last element in sps gets state % free var b: Bool; fsa, fsb: FloorState; fpa, fpb: FloorPos; osa, osb: OccState; fps: FloorPosList; spa: ShuttlePos; sps: ShuttlePosSet; eqn init_fs(fpa) = free; fpa == fpb -> update(fpa, osa, fsa)(fpb) = osa; fpa != fpb -> update(fpa, osa, fsa)(fpb) = fsa(fpb); cond_upd(fpa, osa, fsa) = if(fsa(fpa) == osa, fsa, update(fpa, osa, fsa)); ins_upd(fpa, osa, init_fs) = cond_upd(fpa, osa, init_fs); lt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, update(fpb, osb, fsa)); gt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = update(fpb, osb, ins_upd(fpa, osa, fsa)); fpa == fpb -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, fsa); ins_upd_fps([], osa, fsa) = fsa; ins_upd_fps(fpa |> fps, osa, fsa) = ins_upd(fpa, osa, ins_upd_fps(fps, osa, fsa)); free([], fsa) = true; free(fpa |> fps, fsa) = fsa(fpa) == free && free(fps, fsa); occupied(fpa |> fps, fsa) = fsa(fpa) == occupied && occupied(fps, fsa); occupied([], fsa) = true; end_free(fps, col_inc, false, fsa) = fsa(head(rev(fps))) == free; end_free(fps, col_inc, true, fsa) = fsa(head(l)) == free && fsa(head(tail(l))) == free whr l = rev(fps) end; end_free(fps, col_dec, false, fsa) = fsa(head(fps)) == free; end_free(fps, col_dec, true, fsa) = fsa(head(fps)) == free && fsa(head(tail(fps))) == free; even_occ([], fsa) = true; fsa(fpa) == free -> even_occ(fpa |> fps, fsa) = even_occ(fps, fsa); fsa(fpa) == occupied -> even_occ(fpa |> fps, fsa) = !even_occ(fps, fsa); row(spa) != r1 -> no_half_car(spa, fsa) = true; row(spa) == r1 -> no_half_car(spa, fsa) = even_occ(positions(spa), fsa); no_half_car_sps([], fsa) = true; no_half_car_sps(spa |> sps, fsa) = no_half_car(spa, fsa) && no_half_car_sps(sps, fsa); shift_inc(fps, fsa) = gshift_inc(fps, fsa, free); gshift_inc([], fsa, osa) = fsa; gshift_inc([fpa], fsa, osa) = ins_upd(fpa, osa, fsa); gshift_inc(fpa |> fps, fsa, osa) = ins_upd(fpa, osa, gshift_inc(fps, fsa, fsa(fpa))); shift_dec([], fsa) = fsa; shift_dec([fpa], fsa) = ins_upd(fpa, free, fsa); shift_dec(fpa |> fpb |> fps, fsa) = ins_upd(fpa, fsa(fpb), shift_dec(fpb |> fps, fsa)); shift_inc_ctw(false, fps, fsa) = shift_inc(fps, fsa); shift_inc_ctw(true, fps, fsa) = shift_inc(fps, shift_inc(fps, fsa)); shift_dec_ctw(false, fps, fsa) = shift_dec(fps, fsa); shift_dec_ctw(true, fps, fsa) = shift_dec(fps, shift_dec(fps, fsa)); shift_inc_sps([], fsa) = fsa; row(spa) == r1 -> shift_inc_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), free, shift_inc(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_inc_sps(spa |> sps, fsa) = shift_inc(positions_sps(spa |> sps), fsa); shift_dec_sps([], fsa) = fsa; row(spa) == r1 -> shift_dec_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), fsa(head(positions(head(sps)))), shift_dec(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_dec_sps(spa |> sps, fsa) = shift_dec(positions_sps(spa |> sps), fsa); % ShuttleState operations map init_shs: ShuttleState; % initial shuttle state update: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; cond_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; ins_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; % update(spa, soa, asa, fsa) represents fsa, where position fpa in % orientation soa has value asa; cond_upd and ins_upd are auxiliary functions % with the same meaning that are needed for efficiency available: ShuttlePos # ShuttleOrientation # ShuttleState -> Bool; % available(spa, soa, shs) indicates if shuttle spa is available in % orientation soa for state shs available_sps: ShuttlePosSet # ShuttleOrientation # ShuttleState -> Bool; % available(sps, soa, shs) indicates if all shuttles in sps are available in % orientation soa for state shs shift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_inc(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle downwards in orientation soa; the first % element in sps gets state unavailable gshift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState # AvailState -> ShuttleState; % gshift_inc(sps, soa, shs, asa) has the same meaning as shift_inc(sps, soa, % shs), with the exception that the first element in sps gets state asa % (auxiliary function needed by shift_inc) shift_dec: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_dec(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle upwards in orientation soa; the last % element in sps gets state unavailable var b: Bool; shs, shsa: ShuttleState; spa, spb: ShuttlePos; sps: ShuttlePosSet; soa, sob: ShuttleOrientation; asa, asb: AvailState; eqn init_shs(spa, lowered) = if(row(spa) != r3, avail, n_avail); init_shs(spa, tilted) = if(row(spa) != r3, n_avail, avail); spa == spb && soa == sob -> update(spa, soa, asa, shs)(spb, sob) = asa; spa != spb || soa != sob -> update(spa, soa, asa, shs)(spb, sob) = shs(spb, sob); cond_upd(spa, soa, asa, shs) = if(shs(spa, soa) == asa, shs, update(spa, soa, asa, shs)); ins_upd(spa, soa, asa, init_shs) = cond_upd(spa, soa, asa, init_shs); lt(spa,spb) || (spa == spb && lt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, update(spb, sob, asb, shs)); gt(spa,spb) || (spa == spb && gt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = update(spb, sob, asb, ins_upd(spa, soa, asa, shs)); spa == spb && soa == sob -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, shs); available(spa, soa, shs) = shs(spa, soa) == avail; available_sps([], soa, shs) = true; available_sps(spa |> sps, soa, shs) = available(spa, soa, shs) && available_sps(sps, soa, shs); shift_inc(sps, soa, shs) = gshift_inc(sps, soa, shs, n_avail); gshift_inc([], soa, shs, asa) = shs; gshift_inc([spa], soa, shs, asa) = ins_upd(spa, soa, asa, shs); gshift_inc(spa |> sps, soa, shs, asa) = ins_upd(spa, soa, asa, gshift_inc(sps, soa, shs, shs(spa, soa))); shift_dec([], soa, shs) = shs; shift_dec([spa], soa, shs) = ins_upd(spa, soa, n_avail, shs); shift_dec(spa |> spb |> sps, soa, shs) = ins_upd(spa, soa, shs(spb, soa), shift_dec(spb |> sps, soa, shs)); % LiftState operations map height: LiftState -> LiftHeight; % height(ls) represents the height of state ls occupied: LiftState # FloorState -> Bool; % occupied(ls, fs) indicates if the lift is occupieed for states ls and fs make_ls: LiftHeight # OccState -> LiftState; % make_ls(lh, os) represents the lift state corresponding to height lh and % occupied state os var b: Bool; fsa: FloorState; osa: OccState; eqn height(lsf_street) = street; height(lso_street) = street; height(lsf_rotate) = rotate; height(lso_rotate) = rotate; height(ls_basement) = basement; occupied(lsf_street, fsa) = false; occupied(lso_street, fsa) = true; occupied(lsf_rotate, fsa) = false; occupied(lso_rotate, fsa) = true; occupied(ls_basement, fsa) = occupied(positions(b_r1lift), fsa); make_ls(street, occupied) = lso_street; make_ls(street, free) = lsf_street; make_ls(rotate, occupied) = lso_rotate; make_ls(rotate, free) = lsf_rotate; make_ls(basement, osa) = ls_basement; % GlobalState operations map init_gs: GlobalState; % init_gs is the initial global state allowed: Instruction # GlobalState -> Bool; % allowed(i, gs) indicates if instruction i is allowed given global state gs nextstate: Instruction # ExecResult # GlobalState -> GlobalState; % nextstate(i, r, gs) represents the global state after execution of % instruction i with result r in state gs allowed: InstructionSet # GlobalState -> Bool; % allowed(is, gs) indicates if instruction set is is allowed given global % state gs nextstate: InstructionSet # ExecResult # GlobalState -> GlobalState; % nextstate(is, r, gs) represents the global state after execution of % instruction set is with result r in state gs possible: Event # GlobalState -> Bool; % possible(e, gs) indicates if event e is possible given global state gs nextstate: Event # GlobalState -> GlobalState; % nextstate(e, gs) represents the global state after the event e has occurred % in state gs var gs, gsa: GlobalState; fs, fsa: FloorState; shs, shsa: ShuttleState; ls, lsa: LiftState; lh, lha: LiftHeight; p,q: FloorPos; s,t: OccState; i,j: Instruction; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sps: ShuttlePosSet; dr: DirRow; sp, spa, spb: ShuttlePos; so: ShuttleOrientation; is: InstructionSet; eqn init_gs = glob_state( init_fs, init_shs, lsf_street); allowed(move_belts(r1bs, dc, ms), glob_state(fs, shs, ls)) = r1bs != [] && connected_b_r1(r1bs) && available_b_r1(r1bs, shs, ls) && end_free(l, dc, ms == full, fs) && even_occ(l, fs) whr l = positions_b_r1(r1bs) end; allowed(move_belts(r2bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r2bs != [] && connected_b_r2(r2bs) && available_b_r2(r2bs, shs, ls) && end_free(positions_b_r2(r2bs), dc, false, fs); allowed(move_belts(r3bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r3bs != [] && connected_b_r3(r3bs) && available_b_r3(r3bs, shs, ls) && end_free(positions_b_r3(r3bs), dc, false, fs); allowed(move_shuttles(sps, so, dr), glob_state(fs, shs, ls)) = sps != [] && connected_sps(sps) && available_sps(sps, so, shs) && % placing a comment in front of the following conjunct allows the shuttles % to be moved even if a car is placed half on the shuttle (so == lowered => no_half_car_sps(sps, fs)) && has_neighbour(sps, dr) && !available(neighbour_sps(sps, dr), so, shs); allowed(tilt_shuttle(sp, lowered), glob_state(fs, shs, ls)) = available_sps(shuttles(col(sp)), lowered, shs) && free(positions(sp), fs); allowed(tilt_shuttle(sp, tilted), glob_state(fs, shs, ls)) = shs(sp, tilted) == avail && shs(sp, lowered) == n_avail; ls == ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls) && % replacing the following conjunct by % even_occ(positions(b_r1lift), fs); % allows the lift to move up if two cars are placed half on the lift belt if(free(positions(b_r1lift), fs), true, even_occ(positions_b_r1([b_r1a_sh, b_r1a]), fs) && even_occ(positions_b_r1([b_r1b, b_r1b_sh]), fs)); ls != ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls); allowed(rotate_lift, glob_state(fs, shs, ls)) = height(ls) == rotate && free([pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa), pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb)], fs); nextstate(move_belts(r1bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r1bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r2bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r2bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r3bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_belts(r3bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_shuttles(sps, lowered, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_sps(l, fs), shift_inc(l, lowered, shs), ls) whr l = add_neighbour(sps, row_inc) end; nextstate(move_shuttles(sps, lowered, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_sps(l, fs), shift_dec(l, lowered, shs), ls) whr l = add_neighbour(sps, row_dec) end; nextstate(move_shuttles(sps, tilted, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_inc(add_neighbour(sps, row_inc), tilted, shs), ls); nextstate(move_shuttles(sps, tilted, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_dec(add_neighbour(sps, row_dec), tilted, shs), ls); nextstate(tilt_shuttle(sp, so), ok, glob_state(fs, shs, ls)) = glob_state(fs, ins_upd(sp, so, n_avail, ins_upd(sp, not(so), avail, shs)), ls); occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state( if(height(ls) != basement && lh == basement, ins_upd_fps(positions(b_r1lift), occupied, fs), if(height(ls) == basement && lh != basement, ins_upd_fps(positions(b_r1lift), free, fs), fs ) ), shs, make_ls(lh, occupied)); !occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state(fs, shs, make_ls(lh, free)); nextstate(rotate_lift, ok, gs) = gs; nextstate(i, fail, gs) = gs; allowed([], gs) = false; allowed(i |> [], gs) = allowed(i, gs); allowed(i |> j |> is, gs) = allowed(i, gs) && !overlap(i, j |> is) && allowed(j |> is, gs); nextstate([], ok, gs) = gs; nextstate(i |> is, ok, gs) = nextstate(i, ok, nextstate(is, ok, gs)); nextstate(is, fail, gs) = gs; possible(add_car, glob_state(fs, shs, ls)) = ls == lsf_street; possible(remove_car, glob_state(fs, shs, ls)) = ls == lso_street; nextstate(add_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lso_street); nextstate(remove_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lsf_street); act exec: Instruction; occur: Event; proc S(gs_sl: GlobalState) = sum i: Instruction. (valid(i) && allowed(i, gs_sl)) -> exec(i) . S(nextstate(i, ok, gs_sl)) + sum e: Event. possible(e, gs_sl) -> occur(e) . S(nextstate(e, gs_sl)) ; init S(init_gs); mcrl2-201409.0/examples/industrial/garage/garage-ver.mcrl2000770 001750 001750 00000132510 12370120076 023543 0ustar00outisoutis000000 000000 % The following is the specification used for verification of the safety layer % of the automated parking garage as described in [1, Appendix D.2]. % % This specification is the specification from [1, Appendix D.1] extended with % error actions. Verification amounts to generating the state space, and % checking that either: % - no error actions occur in it; % - or the number of states and transitions are equivalent to the state space % generated from the specification of [1, Appendix D.1]. % % [1] Aad Mathijssen and A. Johannes Pretorius. Specification, Analysis and % Verification of an Automated Parking Garage. Computer Science Report % 05-25, Eindhoven University of Technology (TU/e), 2005. sort FloorRow = struct r1 | r2 | r3; FloorCol = struct c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10; FloorPosPart = struct pa | pb; FloorPos = struct pos_r1(FloorCol, FloorPosPart) | pos_r2(FloorCol) | pos_r3(FloorCol); FloorPosList = List(FloorPos); ShuttlePos = struct r1a | r2a | r3a | r1b | r2b | r3b; ShuttlePosSet = List(ShuttlePos); % representing a set of ShuttlePos elements ShuttleOrientation = struct lowered | tilted; R1Belt = struct b_r1a_sh | b_r1a | b_r1lift | b_r1b | b_r1b_sh; R2Belt = struct b_r2a_sh | b_r2 | b_r2b_sh; R3Belt = struct b_r3a_sh | b_r3 | b_r3b_sh; R1BeltSet = List(R1Belt); % representing a set of R1Belt elements R2BeltSet = List(R2Belt); % representing a set of R2Belt elements R3BeltSet = List(R3Belt); % representing a set of R3Belt elements DirCol = struct col_inc | col_dec; DirRow = struct row_inc | row_dec; MoveSize = struct full | half; LiftHeight = struct street | rotate | basement; Area = struct area(positions: FloorPosList, tilted_c1: Bool, tilted_c10: Bool); Instruction = struct move_belts(R1BeltSet, DirCol, MoveSize) | move_belts(R2BeltSet, DirCol, MoveSize) | move_belts(R3BeltSet, DirCol, MoveSize) | move_shuttles(ShuttlePosSet, ShuttleOrientation, DirRow) | tilt_shuttle(ShuttlePos, ShuttleOrientation) | move_lift(LiftHeight) | rotate_lift; InstructionSet = List(Instruction); % representing a set of instructions Event = struct add_car | remove_car; ExecResult = struct ok | fail; OccState = struct free | occupied; AvailState = struct avail | n_avail; FloorState = FloorPos -> OccState; ShuttleState = ShuttlePos # ShuttleOrientation -> AvailState; LiftState = struct lsf_street | lso_street | lsf_rotate | lso_rotate | ls_basement; GlobalState = struct glob_state(fs: FloorState, shs: ShuttleState, ls: LiftState); % FloorRow operations map index: FloorRow -> Pos; % index(fra) is the index of fra lt: FloorRow # FloorRow -> Bool; % lt(fra,frb) indicates if fra is less than frb var fra, frb: FloorRow; eqn index(r1) = 1; index(r2) = 2; index(r3) = 3; lt(fra, frb) = index(fra) < index(frb); % FloorCol operations map index: FloorCol -> Pos; % index(fca) is the index of fca lt: FloorCol # FloorCol -> Bool; % lt(fca,fcb) indicates if fca is less than fcb var fca, fcb: FloorCol; eqn index(c1) = 1; index(c2) = 2; index(c3) = 3; index(c4) = 4; index(c5) = 5; index(c6) = 6; index(c7) = 7; index(c8) = 8; index(c9) = 9; index(c10) = 10; lt(fca, fcb) = index(fca) < index(fcb); % FloorPosPart operations map index: FloorPosPart -> Pos; % index(ffpa) is the index of fppa lt: FloorPosPart # FloorPosPart -> Bool; % lt(fppa,fppb) indicates if fppa is less than fppb var fppa, fppb: FloorPosPart; eqn index(pa) = 1; index(pb) = 2; lt(fppa, fppb) = index(fppa) < index(fppb); % FloorPos operations map row: FloorPos -> FloorRow; % row(fpa) is the row of fpa col: FloorPos -> FloorCol; % col(fpa) is the column of fpa part: FloorPos -> FloorPosPart; % part(fpa) is the part of fpa lt: FloorPos # FloorPos -> Bool; % lt(fpa, fpb) indicates if fpa is less than fpb lt_r: FloorPos # FloorPos -> Bool; % lt_r(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) (auxiliary function needed by lt for efficiency) lt_rc: FloorPos # FloorPos -> Bool; % lt_rc(fpa, fpb) indicates if fpa is less than fpb, provided % row(fpa) = row(fpb) and col(fpa) = col(fpb) % (auxiliary function needed by lt_r for efficiency) gt: FloorPos # FloorPos -> Bool; % gt(fpa, fpb) indicates if fpa is greater than fpb var fca: FloorCol; fppa: FloorPosPart; fpa, fpb: FloorPos; eqn row(pos_r1(fca, fppa)) = r1; row(pos_r2(fca)) = r2; row(pos_r3(fca)) = r3; col(pos_r1(fca, fppa)) = fca; col(pos_r2(fca)) = fca; col(pos_r3(fca)) = fca; part(pos_r1(fca, fppa)) = fppa; row(fpa) == row(fpb) -> lt(fpa, fpb) = lt_r(fpa, fpb); row(fpa) != row(fpb) -> lt(fpa, fpb) = lt(row(fpa), row(fpb)); col(fpa) == col(fpb) -> lt_r(fpa, fpb) = lt_rc(fpa, fpb); col(fpa) != col(fpb) -> lt_r(fpa, fpb) = lt(col(fpa), col(fpb)); lt_rc(fpa, fpb) = row(fpa) == r1 && lt(part(fpa), part(fpb)); gt(fpa,fpb) = lt(fpb, fpa); % FloorPosList operations map contains: FloorPos # FloorPosList -> Bool; % contains(fpa, fps) indicates if fps contains fpa overlap: FloorPosList # FloorPosList -> Bool; % overlap(fps, fpt) indicates if the elements of fps and fpt overlap rev: FloorPosList -> FloorPosList; % rev(fps) is the reverse of list fps grev: FloorPosList # FloorPosList -> FloorPosList; % grev(fps, fpt) is the reverse of fps concatenated with fpt % (auxiliary function needed for efficiency by rev) var fpa, fpb: FloorPos; fps, fpt: FloorPosList; eqn contains(fpa, []) = false; contains(fpa, fpa |> fps) = true; fpa != fpb -> contains(fpa, fpb |> fps) = contains(fpa, fps); overlap([], fpt) = false; overlap(fpa |> fps, fpt) = contains(fpa, fpt) || overlap(fps, fpt); rev(fps) = grev(fps, []); grev([], fpt) = fpt; grev(fpa |> fps, fpt) = grev(fps, fpa |> fpt); % ShuttlePos operations map index: ShuttlePos -> Pos; % index(spa) is the index of spa row: ShuttlePos -> FloorRow; % row(spa) is the row of spa col: ShuttlePos -> FloorCol; % col(spa) is the column of spa lt: ShuttlePos # ShuttlePos -> Bool; % lt(spa, spb) indicates if spa is less than spb gt: ShuttlePos # ShuttlePos -> Bool; % gt(spa, spb) indicates if spa is greater than spb positions: ShuttlePos -> FloorPosList; % positions(spa) represents the floor positions corresponding to spa in % lowered position has_neighbour: ShuttlePos # DirRow -> Bool; % has_neighbour(spa, dr) indicates if spa has a successor in direction dr neighbour: ShuttlePos # DirRow -> ShuttlePos; % neighbour(spa, dr) is the neighbour of spa in directrion dr, provided it % exists connected: ShuttlePos # ShuttlePos -> Bool; % connected(spa, spb) indicates if the bottom of spa is connected to the top % of spb var spa, spb: ShuttlePos; eqn index(r1a) = 1; index(r2a) = 2; index(r3a) = 3; index(r1b) = 4; index(r2b) = 5; index(r3b) = 6; row(r1a) = r1; row(r2a) = r2; row(r3a) = r3; row(r1b) = r1; row(r2b) = r2; row(r3b) = r3; col(r1a) = c1; col(r2a) = c1; col(r3a) = c1; col(r1b) = c10; col(r2b) = c10; col(r3b) = c10; lt(spa, spb) = index(spa) < index(spb); gt(spa, spb) = index(spa) > index(spb); positions(r1a) = positions(b_r1a_sh); positions(r2a) = positions(b_r2a_sh); positions(r3a) = positions(b_r3a_sh); positions(r1b) = positions(b_r1b_sh); positions(r2b) = positions(b_r2b_sh); positions(r3b) = positions(b_r3b_sh); has_neighbour(spa, row_inc) = row(spa) != r3; has_neighbour(spa, row_dec) = row(spa) != r1; neighbour(r1a, row_inc) = r2a; neighbour(r2a, row_inc) = r3a; neighbour(r1b, row_inc) = r2b; neighbour(r2b, row_inc) = r3b; neighbour(r2a, row_dec) = r1a; neighbour(r3a, row_dec) = r2a; neighbour(r2b, row_dec) = r1b; neighbour(r3b, row_dec) = r2b; connected(spa, spb) = succ(index(spa)) == index(spb) && col(spa) == col(spb); % ShuttlePosSet operations map is_set_sps: ShuttlePosSet -> Bool; % is_set_sps(sps) indicates if sps is a set % In the remainder of the data equation section, for every ShuttlePosSet sps % is_set_sps(sps) is a precondition. contains: ShuttlePos # ShuttlePosSet -> Bool; % contains(spa, sps) indicates if sps contains spa shuttles: FloorCol -> ShuttlePosSet; % shuttles(fc) represents the shuttle positions corresponding to fc positions_sps: ShuttlePosSet -> FloorPosList; % positions_sps(sps) represents the floor positions corresponding to sps connected_sps: ShuttlePosSet -> Bool; % connected_sps(sps) indicates if all elements of sps are connected has_neighbour: ShuttlePosSet # DirRow -> Bool; % has_neighbour(sps, dr) indicates is sps has a neighbour in direction dr neighbour_sps: ShuttlePosSet # DirRow -> ShuttlePos; % neighbour_sps(sps, dr) is the neighbour of sps in direction dr, provided it % exists add_neighbour: ShuttlePosSet # DirRow -> ShuttlePosSet; % add_neighbour(sps, dr) represents the sps extended with its neighbour in % direction dr, provided it exists var spa, spb: ShuttlePos; sps: ShuttlePosSet; fc: FloorCol; eqn is_set_sps([]) = true; is_set_sps(spa |> []) = true; is_set_sps(spa |> spb |> sps) = lt(spa, spb) && is_set_sps(spb |> sps); contains(spa, []) = false; contains(spa, spa |> sps) = true; spa != spb -> contains(spa, spb |> sps) = contains(spa, sps); shuttles(fc) = if(fc == c1, [r1a,r2a,r3a], if(fc == c10, [r1b,r2b,r3b], [])); positions_sps([]) = []; positions_sps(spa |> sps) = positions(spa) ++ positions_sps(sps); connected_sps([]) = true; connected_sps([spa]) = true; connected_sps(spa |> spb |> sps) = connected(spa, spb) && connected_sps(spb |> sps); has_neighbour(sps, row_inc) = has_neighbour(rhead(sps), row_inc); has_neighbour(sps, row_dec) = has_neighbour(head(sps), row_dec); neighbour_sps(sps, row_inc) = neighbour(rhead(sps), row_inc); neighbour_sps(sps, row_dec) = neighbour(head(sps), row_dec); add_neighbour(sps, row_inc) = sps <| neighbour_sps(sps, row_inc); add_neighbour(sps, row_dec) = neighbour_sps(sps, row_dec) |> sps; % ShuttleOrientation operations map index: ShuttleOrientation -> Pos; % index(soa) is the index of soa lt: ShuttleOrientation # ShuttleOrientation -> Bool; % lt(soa, sob) indicates if soa is less than sob gt: ShuttleOrientation # ShuttleOrientation -> Bool; % gt(soa, sob) indicates if soa is greater than sob not: ShuttleOrientation -> ShuttleOrientation; % not(soa) indicates the opposite of soa var soa, sob: ShuttleOrientation; eqn index(lowered) = 1; index(tilted) = 2; lt(soa, sob) = index(soa) < index(sob); gt(soa, sob) = index(soa) > index(sob); not(lowered) = tilted; not(tilted) = lowered; % Belt operations map index: R1Belt -> Pos; index: R2Belt -> Pos; index: R3Belt -> Pos; % index(ba) is the index of belt ba row: R1Belt -> FloorRow; row: R2Belt -> FloorRow; row: R3Belt -> FloorRow; % row(ba) is the row of belt ba lt: R1Belt # R1Belt -> Bool; lt: R2Belt # R2Belt -> Bool; lt: R3Belt # R3Belt -> Bool; % lt(ba, bb) indicates if belt ba is less than belt bb positions: R1Belt -> FloorPosList; positions: R2Belt -> FloorPosList; positions: R3Belt -> FloorPosList; % positions(ba) represents the positions corresponding to belt ba connected: R1Belt # R1Belt -> Bool; connected: R2Belt # R2Belt -> Bool; connected: R3Belt # R3Belt -> Bool; % connected(ba, bb) indicates if the right of ba is connected to the left % of bb available: R1Belt # ShuttleState # LiftState -> Bool; available: R2Belt # ShuttleState # LiftState -> Bool; available: R3Belt # ShuttleState # LiftState -> Bool; % available(ba, shs, ls) indicates if belt ba is available for states shs % and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; fs: FloorState; shs: ShuttleState; ls: LiftState; ms: MoveSize; eqn index(b_r1a_sh) = 1; index(b_r1a) = 2; index(b_r1lift) = 3; index(b_r1b) = 4; index(b_r1b_sh) = 5; index(b_r2a_sh) = 1; index(b_r2) = 2; index(b_r2b_sh) = 3; index(b_r3a_sh) = 1; index(b_r3) = 2; index(b_r3b_sh) = 3; row(r1ba) = r1; row(r2ba) = r2; row(r3ba) = r3; lt(r1ba, r1bb) = index(r1ba) < index(r1bb); lt(r2ba, r2bb) = index(r2ba) < index(r2bb); lt(r3ba, r3bb) = index(r3ba) < index(r3bb); positions(b_r1a_sh) = [pos_r1(c1, pa), pos_r1(c1, pb)]; positions(b_r1a) = [pos_r1(c2, pa), pos_r1(c2, pb), %pos_r1(c3, pa), pos_r1(c3, pb), %pos_r1(c4, pa), pos_r1(c4, pb), %pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa)]; positions(b_r1lift) = [pos_r1(c6, pb), pos_r1(c7, pa)]; positions(b_r1b) = [pos_r1(c7, pb), %pos_r1(c8, pa), pos_r1(c8, pb), pos_r1(c9, pa), pos_r1(c9, pb)]; positions(b_r1b_sh) = [pos_r1(c10, pa), pos_r1(c10, pb)]; positions(b_r2a_sh) = [pos_r2(c1)]; positions(b_r2) = [pos_r2(c2), %pos_r2(c3), %pos_r2(c4), %pos_r2(c5), %pos_r2(c6), %pos_r2(c7), %pos_r2(c8), pos_r2(c9)]; positions(b_r2b_sh) = [pos_r2(c10)]; positions(b_r3a_sh) = [pos_r3(c1)]; positions(b_r3) = [pos_r3(c2), %pos_r3(c3), %pos_r3(c4), %pos_r3(c5), %pos_r3(c6), %pos_r3(c7), %pos_r3(c8), pos_r3(c9)]; positions(b_r3b_sh) = [pos_r3(c10)]; available(b_r1a_sh, shs, ls) = shs(r1a, lowered) == avail; available(b_r1a, shs, ls) = true; available(b_r1lift, shs, ls) = ls == ls_basement; available(b_r1b, shs, ls) = true; available(b_r1b_sh, shs, ls) = shs(r1b, lowered) == avail; available(b_r2a_sh, shs, ls) = shs(r2a, lowered) == avail; available(b_r2, shs, ls) = true; available(b_r2b_sh, shs, ls) = shs(r2b, lowered) == avail; available(b_r3a_sh, shs, ls) = shs(r3a, lowered) == avail; available(b_r3, shs, ls) = true; available(b_r3b_sh, shs, ls) = shs(r3b, lowered) == avail; % BeltSet operations map is_set_b_r1: R1BeltSet -> Bool; is_set_b_r2: R2BeltSet -> Bool; is_set_b_r3: R3BeltSet -> Bool; % is_set_b_rX(bs) indicates if bs is a set % In the remainder of this data equations section each belt set bs has % is_set_b_rX(bs) as a precondition. contains: R1Belt # R1BeltSet -> Bool; contains: R2Belt # R2BeltSet -> Bool; contains: R3Belt # R3BeltSet -> Bool; % contains(ba, bs) indicates if ba is an element of bs positions_b_r1: R1BeltSet -> FloorPosList; positions_b_r2: R2BeltSet -> FloorPosList; positions_b_r3: R3BeltSet -> FloorPosList; % positions_b_rX(bs) represents the floor positions corresponding to the % belts in bs connected_b_r1: R1BeltSet -> Bool; connected_b_r2: R2BeltSet -> Bool; connected_b_r3: R3BeltSet -> Bool; % connected(bs) indicates if the belts in bs are connected available_b_r1: R1BeltSet # ShuttleState # LiftState -> Bool; available_b_r2: R2BeltSet # ShuttleState # LiftState -> Bool; available_b_r3: R3BeltSet # ShuttleState # LiftState -> Bool; % available_b_rX(bs, shs, ls) indicates if all belts in bs are available for % states shs and ls var r1ba, r1bb: R1Belt; r2ba, r2bb: R2Belt; r3ba, r3bb: R3Belt; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; fs: FloorState; shs: ShuttleState; ls: LiftState; eqn is_set_b_r1([]) = true; is_set_b_r1(r1ba |> []) = true; is_set_b_r1(r1ba |> r1bb |> r1bs) = lt(r1ba, r1bb) && is_set_b_r1(r1bb |> r1bs); is_set_b_r2([]) = true; is_set_b_r2(r2ba |> []) = true; is_set_b_r2(r2ba |> r2bb |> r2bs) = lt(r2ba, r2bb) && is_set_b_r2(r2bb |> r2bs); is_set_b_r3([]) = true; is_set_b_r3(r3ba |> []) = true; is_set_b_r3(r3ba |> r3bb |> r3bs) = lt(r3ba, r3bb) && is_set_b_r3(r3bb |> r3bs); contains(r1ba, []) = false; contains(r1ba, r1ba |> r1bs) = true; r1ba != r1bb -> contains(r1ba, r1bb |> r1bs) = contains(r1ba, r1bs); contains(r2ba, []) = false; contains(r2ba, r2ba |> r2bs) = true; r2ba != r2bb -> contains(r2ba, r2bb |> r2bs) = contains(r2ba, r2bs); contains(r3ba, []) = false; contains(r3ba, r3ba |> r3bs) = true; r3ba != r3bb -> contains(r3ba, r3bb |> r3bs) = contains(r3ba, r3bs); positions_b_r1([]) = []; positions_b_r1(r1ba |> r1bs) = positions(r1ba) ++ positions_b_r1(r1bs); positions_b_r2([]) = []; positions_b_r2(r2ba |> r2bs) = positions(r2ba) ++ positions_b_r2(r2bs); positions_b_r3([]) = []; positions_b_r3(r3ba |> r3bs) = positions(r3ba) ++ positions_b_r3(r3bs); connected_b_r1([]) = true; connected_b_r1(r1ba |> []) = true; connected_b_r1(r1ba |> r1bb |> r1bs) = connected(r1ba, r1bb) && connected_b_r1(r1bb |> r1bs); connected_b_r2([]) = true; connected_b_r2(r2ba |> []) = true; connected_b_r2(r2ba |> r2bb |> r2bs) = connected(r2ba, r2bb) && connected_b_r2(r2bb |> r2bs); connected_b_r3([]) = true; connected_b_r3(r3ba |> []) = true; connected_b_r3(r3ba |> r3bb |> r3bs) = connected(r3ba, r3bb) && connected_b_r3(r3bb |> r3bs); connected(r1ba, r1bb) = succ(index(r1ba)) == index(r1bb); connected(r2ba, r2bb) = succ(index(r2ba)) == index(r2bb); connected(r3ba, r3bb) = succ(index(r3ba)) == index(r3bb); available_b_r1([], shs, ls) = true; available_b_r1(r1ba |> r1bs, shs, ls) = available(r1ba, shs, ls) && available_b_r1(r1bs, shs, ls); available_b_r2([], shs, ls) = true; available_b_r2(r2ba |> r2bs, shs, ls) = available(r2ba, shs, ls) && available_b_r2(r2bs, shs, ls); available_b_r3([], shs, ls) = true; available_b_r3(r3ba |> r3bs, shs, ls) = available(r3ba, shs, ls) && available_b_r3(r3bs, shs, ls); % Area operations map overlap: Area # Area -> Bool; % area(a, b) indicates if area a and b overlap var fps, fpt: FloorPosList; tc1a, tc1b, tc10a, tc10b: Bool; eqn overlap(area(fps, tc1a, tc1b), area(fpt, tc10a, tc10b)) = overlap(fps, fpt) || (tc1a && tc1b) || (tc10a && tc10b); % Instruction operations map index: Instruction -> Pos; % index(i) is the index of instruction i lt: Instruction # Instruction -> Bool; % lt(i, j) indicates if i is less than j valid: Instruction -> Bool; % valid(i) indicates if instruction i is valid area: Instruction -> Area; % area(i) represents the area on which instruction i has any effect overlap: Instruction # Instruction -> Bool; % overlap(i, j) indicates if instruction i and j overlap var r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sp: ShuttlePos; sps: ShuttlePosSet; so: ShuttleOrientation; dr: DirRow; lh: LiftHeight; i,j: Instruction; eqn index(move_belts(r1bs, dc, ms)) = 1; index(move_belts(r2bs, dc, ms)) = 2; index(move_belts(r3bs, dc, ms)) = 3; index(move_shuttles(sps, so, dr)) = 4; index(tilt_shuttle(sp, so)) = 5; index(move_lift(lh)) = 6; index(rotate_lift) = 7; lt(i, j) = index(i) < index(j); valid(move_belts(r1bs, dc, ms)) = is_set_b_r1(r1bs); valid(move_belts(r2bs, dc, ms)) = is_set_b_r2(r2bs); valid(move_belts(r3bs, dc, ms)) = is_set_b_r3(r3bs); valid(move_shuttles(sps, so, dr)) = is_set_sps(sps); valid(tilt_shuttle(sp, so)) = true; valid(move_lift(lh)) = true; valid(rotate_lift) = true; area(move_belts(r1bs, dc, ms)) = area(positions_b_r1(r1bs), false, false); area(move_belts(r2bs, dc, ms)) = area(positions_b_r2(r2bs), false, false); area(move_belts(r3bs, dc, ms)) = area(positions_b_r3(r3bs), false, false); area(move_shuttles(sps, lowered, dr)) = area(positions_sps(add_neighbour(sps, dr)), false, false); area(move_shuttles(sps, tilted, dr)) = area([], col(head(sps)) == c1, col(head(sps)) == c10); area(tilt_shuttle(sp, so)) = area(positions(sp), col(sp) == c1, col(sp) == c10); area(move_lift(lh)) = area(positions(b_r1lift), false, false); area(rotate_lift) = area(positions_b_r1([b_r1a, b_r1lift, b_r1b]), false, false); overlap(i, j) = overlap(area(i), area(j)); % InstructionSet operations map is_set_is: InstructionSet -> Bool; % is_set_is(is) indicates if is is a set % In the remainder of the data equation section, for every InstructionSet is % is_set_is(is) is a precondition. valid: InstructionSet -> Bool; % valid(is) indicates if the instructions in is are valid overlap: Instruction # InstructionSet -> Bool; % overlap(i, is) indicates if instruction i overlaps with any of the % instructions in is var i,j: Instruction; is: InstructionSet; eqn is_set_is([]) = true; is_set_is(i |> []) = true; is_set_is(i |> j |> is) = lt(i, j) && is_set_is(j |> is); valid([]) = true; valid(i |> is) = valid(i) && valid(is); overlap(i, []) = false; overlap(i, j |> is) = overlap(i, j) || overlap(i, is); % AvailState operations map not: AvailState -> AvailState; % not(asa) indicates the opposite of asa eqn not(avail) = n_avail; not(n_avail) = avail; % FloorState operations map init_fs: FloorState; % init_fs is the initial floor state update: FloorPos # OccState # FloorState -> FloorState; cond_upd: FloorPos # OccState # FloorState -> FloorState; ins_upd: FloorPos # OccState # FloorState -> FloorState; % update(fpa, osa, fsa) represents fsa, where position fpa has value osa; % cond_upd and ins_upd are auxiliary functions with the same meaning that % are needed for efficiency ins_upd_fps: FloorPosList # OccState # FloorState -> FloorState; % ins_upd_fps(fps, osa, fsa) represents fsa, where positions fps have value % osa free: FloorPosList # FloorState -> Bool; % free(fps, fsa) indicates that all positions in fps are free for state fsa occupied: FloorPosList # FloorState -> Bool; % occupied(fps, fsa) indicates that all positions in fps are occupied for % state fsa end_free: FloorPosList # DirCol # Bool # FloorState -> Bool; % end_free(fps, dc, obl, fsa) indicates if the end of the list fps in % direction dc is free for state fsa; if obl then the one but last element % also needs to be free even_occ: FloorPosList # FloorState -> Bool; % even_occ(fps, fsa) indicates if the number of occupied positions in fps for % state fsa is even no_half_car: ShuttlePos # FloorState -> Bool; % no_half_car(spa, fsa) indicates if there is a half car positioned on spa % for state fsa no_half_car_sps: ShuttlePosSet # FloorState -> Bool; % no_half_car(sps, fsa) indicates if there is a half car positioned on any % of the elements of sps for state fsa shift_inc: FloorPosList # FloorState -> FloorState; % shift_inc(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the right; the first element in fps % gets state free gshift_inc: FloorPosList # FloorState # OccState -> FloorState; % gshift_inc(fps, fsa, osa) has the same meaning as shift_inc(fps, fsa), with % the exception that the first element in fps gets state osa % (auxiliary function needed by shift_inc) shift_dec: FloorPosList # FloorState -> FloorState; % shift_dec(fps, fsa) represents fsa, where the states of the positions in % fps are shifted one position to the left; the last element in fps gets % state free shift_inc_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_inc_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the right; % if ctw then two positions are shifted shift_dec_ctw: Bool # FloorPosList # FloorState -> FloorState; % shift_dec_ctw(ctw, fps, fsa) represents fsa where the states of the % positions in fps are shifted one position to the left; % if ctw then two positions are shifted shift_inc_sps: ShuttlePosSet # FloorState -> FloorState; % shift_inc(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position downwards; the first element in sps % gets state free shift_dec_sps: ShuttlePosSet # FloorState -> FloorState; % shift_dec(sps, fsa) represents fsa, where the states of the shuttles in % sps are shifted one position upwards; the last element in sps gets state % free var b: Bool; fsa, fsb: FloorState; fpa, fpb: FloorPos; osa, osb: OccState; fps: FloorPosList; spa: ShuttlePos; sps: ShuttlePosSet; eqn init_fs(fpa) = free; fpa == fpb -> update(fpa, osa, fsa)(fpb) = osa; fpa != fpb -> update(fpa, osa, fsa)(fpb) = fsa(fpb); cond_upd(fpa, osa, fsa) = if(fsa(fpa) == osa, fsa, update(fpa, osa, fsa)); ins_upd(fpa, osa, init_fs) = cond_upd(fpa, osa, init_fs); lt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, update(fpb, osb, fsa)); gt(fpa,fpb) -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = update(fpb, osb, ins_upd(fpa, osa, fsa)); fpa == fpb -> ins_upd(fpa, osa, update(fpb, osb, fsa)) = cond_upd(fpa, osa, fsa); ins_upd_fps([], osa, fsa) = fsa; ins_upd_fps(fpa |> fps, osa, fsa) = ins_upd(fpa, osa, ins_upd_fps(fps, osa, fsa)); free([], fsa) = true; free(fpa |> fps, fsa) = fsa(fpa) == free && free(fps, fsa); occupied(fpa |> fps, fsa) = fsa(fpa) == occupied && occupied(fps, fsa); occupied([], fsa) = true; end_free(fps, col_inc, false, fsa) = fsa(head(rev(fps))) == free; end_free(fps, col_inc, true, fsa) = fsa(head(l)) == free && fsa(head(tail(l))) == free whr l = rev(fps) end; end_free(fps, col_dec, false, fsa) = fsa(head(fps)) == free; end_free(fps, col_dec, true, fsa) = fsa(head(fps)) == free && fsa(head(tail(fps))) == free; even_occ([], fsa) = true; fsa(fpa) == free -> even_occ(fpa |> fps, fsa) = even_occ(fps, fsa); fsa(fpa) == occupied -> even_occ(fpa |> fps, fsa) = !even_occ(fps, fsa); row(spa) != r1 -> no_half_car(spa, fsa) = true; row(spa) == r1 -> no_half_car(spa, fsa) = even_occ(positions(spa), fsa); no_half_car_sps([], fsa) = true; no_half_car_sps(spa |> sps, fsa) = no_half_car(spa, fsa) && no_half_car_sps(sps, fsa); shift_inc(fps, fsa) = gshift_inc(fps, fsa, free); gshift_inc([], fsa, osa) = fsa; gshift_inc([fpa], fsa, osa) = ins_upd(fpa, osa, fsa); gshift_inc(fpa |> fps, fsa, osa) = ins_upd(fpa, osa, gshift_inc(fps, fsa, fsa(fpa))); shift_dec([], fsa) = fsa; shift_dec([fpa], fsa) = ins_upd(fpa, free, fsa); shift_dec(fpa |> fpb |> fps, fsa) = ins_upd(fpa, fsa(fpb), shift_dec(fpb |> fps, fsa)); shift_inc_ctw(false, fps, fsa) = shift_inc(fps, fsa); shift_inc_ctw(true, fps, fsa) = shift_inc(fps, shift_inc(fps, fsa)); shift_dec_ctw(false, fps, fsa) = shift_dec(fps, fsa); shift_dec_ctw(true, fps, fsa) = shift_dec(fps, shift_dec(fps, fsa)); shift_inc_sps([], fsa) = fsa; row(spa) == r1 -> shift_inc_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), free, shift_inc(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_inc_sps(spa |> sps, fsa) = shift_inc(positions_sps(spa |> sps), fsa); shift_dec_sps([], fsa) = fsa; row(spa) == r1 -> shift_dec_sps(spa |> sps, fsa) = ins_upd_fps(positions(spa), fsa(head(positions(head(sps)))), shift_dec(positions_sps(spa |> sps), fsa)); row(spa) != r1 -> shift_dec_sps(spa |> sps, fsa) = shift_dec(positions_sps(spa |> sps), fsa); % ShuttleState operations map init_shs: ShuttleState; % initial shuttle state update: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; cond_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; ins_upd: ShuttlePos # ShuttleOrientation # AvailState # ShuttleState -> ShuttleState; % update(spa, soa, asa, fsa) represents fsa, where position fpa in % orientation soa has value asa; cond_upd and ins_upd are auxiliary functions % with the same meaning that are needed for efficiency available: ShuttlePos # ShuttleOrientation # ShuttleState -> Bool; % available(spa, soa, shs) indicates if shuttle spa is available in % orientation soa for state shs available_sps: ShuttlePosSet # ShuttleOrientation # ShuttleState -> Bool; % available(sps, soa, shs) indicates if all shuttles in sps are available in % orientation soa for state shs shift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_inc(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle downwards in orientation soa; the first % element in sps gets state unavailable gshift_inc: ShuttlePosSet # ShuttleOrientation # ShuttleState # AvailState -> ShuttleState; % gshift_inc(sps, soa, shs, asa) has the same meaning as shift_inc(sps, soa, % shs), with the exception that the first element in sps gets state asa % (auxiliary function needed by shift_inc) shift_dec: ShuttlePosSet # ShuttleOrientation # ShuttleState -> ShuttleState; % shift_dec(sps, soa, shs) represents shs, where the states of the shuttles % in sps are shifted one shuttle upwards in orientation soa; the last % element in sps gets state unavailable var b: Bool; shs, shsa: ShuttleState; spa, spb: ShuttlePos; sps: ShuttlePosSet; soa, sob: ShuttleOrientation; asa, asb: AvailState; eqn init_shs(spa, lowered) = if(row(spa) != r3, avail, n_avail); init_shs(spa, tilted) = if(row(spa) != r3, n_avail, avail); spa == spb && soa == sob -> update(spa, soa, asa, shs)(spb, sob) = asa; spa != spb || soa != sob -> update(spa, soa, asa, shs)(spb, sob) = shs(spb, sob); cond_upd(spa, soa, asa, shs) = if(shs(spa, soa) == asa, shs, update(spa, soa, asa, shs)); ins_upd(spa, soa, asa, init_shs) = cond_upd(spa, soa, asa, init_shs); lt(spa,spb) || (spa == spb && lt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, update(spb, sob, asb, shs)); gt(spa,spb) || (spa == spb && gt(soa, sob)) -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = update(spb, sob, asb, ins_upd(spa, soa, asa, shs)); spa == spb && soa == sob -> ins_upd(spa, soa, asa, update(spb, sob, asb, shs)) = cond_upd(spa, soa, asa, shs); available(spa, soa, shs) = shs(spa, soa) == avail; available_sps([], soa, shs) = true; available_sps(spa |> sps, soa, shs) = available(spa, soa, shs) && available_sps(sps, soa, shs); shift_inc(sps, soa, shs) = gshift_inc(sps, soa, shs, n_avail); gshift_inc([], soa, shs, asa) = shs; gshift_inc([spa], soa, shs, asa) = ins_upd(spa, soa, asa, shs); gshift_inc(spa |> sps, soa, shs, asa) = ins_upd(spa, soa, asa, gshift_inc(sps, soa, shs, shs(spa, soa))); shift_dec([], soa, shs) = shs; shift_dec([spa], soa, shs) = ins_upd(spa, soa, n_avail, shs); shift_dec(spa |> spb |> sps, soa, shs) = ins_upd(spa, soa, shs(spb, soa), shift_dec(spb |> sps, soa, shs)); % LiftState operations map height: LiftState -> LiftHeight; % height(ls) represents the height of state ls occupied: LiftState # FloorState -> Bool; % occupied(ls, fs) indicates if the lift is occupieed for states ls and fs make_ls: LiftHeight # OccState -> LiftState; % make_ls(lh, os) represents the lift state corresponding to height lh and % occupied state os var b: Bool; fsa: FloorState; osa: OccState; eqn height(lsf_street) = street; height(lso_street) = street; height(lsf_rotate) = rotate; height(lso_rotate) = rotate; height(ls_basement) = basement; occupied(lsf_street, fsa) = false; occupied(lso_street, fsa) = true; occupied(lsf_rotate, fsa) = false; occupied(lso_rotate, fsa) = true; occupied(ls_basement, fsa) = occupied(positions(b_r1lift), fsa); make_ls(street, occupied) = lso_street; make_ls(street, free) = lsf_street; make_ls(rotate, occupied) = lso_rotate; make_ls(rotate, free) = lsf_rotate; make_ls(basement, osa) = ls_basement; % GlobalState operations map init_gs: GlobalState; % init_gs is the initial global state allowed: Instruction # GlobalState -> Bool; % allowed(i, gs) indicates if instruction i is allowed given global state gs nextstate: Instruction # ExecResult # GlobalState -> GlobalState; % nextstate(i, r, gs) represents the global state after execution of % instruction i with result r in state gs allowed: InstructionSet # GlobalState -> Bool; % allowed(is, gs) indicates if instruction set is is allowed given global % state gs nextstate: InstructionSet # ExecResult # GlobalState -> GlobalState; % nextstate(is, r, gs) represents the global state after execution of % instruction set is with result r in state gs possible: Event # GlobalState -> Bool; % possible(e, gs) indicates if event e is possible given global state gs nextstate: Event # GlobalState -> GlobalState; % nextstate(e, gs) represents the global state after the event e has occurred % in state gs var gs, gsa: GlobalState; fs, fsa: FloorState; shs, shsa: ShuttleState; ls, lsa: LiftState; lh, lha: LiftHeight; p,q: FloorPos; s,t: OccState; i,j: Instruction; r1bs: R1BeltSet; r2bs: R2BeltSet; r3bs: R3BeltSet; dc: DirCol; ms: MoveSize; sps: ShuttlePosSet; dr: DirRow; sp, spa, spb: ShuttlePos; so: ShuttleOrientation; is: InstructionSet; eqn init_gs = glob_state( init_fs, init_shs, lsf_street); allowed(move_belts(r1bs, dc, ms), glob_state(fs, shs, ls)) = r1bs != [] && connected_b_r1(r1bs) && available_b_r1(r1bs, shs, ls) && end_free(l, dc, ms == full, fs) && even_occ(l, fs) whr l = positions_b_r1(r1bs) end; allowed(move_belts(r2bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r2bs != [] && connected_b_r2(r2bs) && available_b_r2(r2bs, shs, ls) && end_free(positions_b_r2(r2bs), dc, false, fs); allowed(move_belts(r3bs, dc, ms), glob_state(fs, shs, ls)) = ms == full && r3bs != [] && connected_b_r3(r3bs) && available_b_r3(r3bs, shs, ls) && end_free(positions_b_r3(r3bs), dc, false, fs); allowed(move_shuttles(sps, so, dr), glob_state(fs, shs, ls)) = sps != [] && connected_sps(sps) && available_sps(sps, so, shs) && % placing a comment in front of the following conjunct allows the shuttles % to be moved even if a car is placed half on the shuttle (so == lowered => no_half_car_sps(sps, fs)) && has_neighbour(sps, dr) && !available(neighbour_sps(sps, dr), so, shs); allowed(tilt_shuttle(sp, lowered), glob_state(fs, shs, ls)) = available_sps(shuttles(col(sp)), lowered, shs) && free(positions(sp), fs); allowed(tilt_shuttle(sp, tilted), glob_state(fs, shs, ls)) = shs(sp, tilted) == avail && shs(sp, lowered) == n_avail; ls == ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls) && % replacing the following conjunct by % even_occ(positions(b_r1lift), fs); % allows the lift to move up if two cars are placed half on the lift belt if(free(positions(b_r1lift), fs), true, even_occ(positions_b_r1([b_r1a_sh, b_r1a]), fs) && even_occ(positions_b_r1([b_r1b, b_r1b_sh]), fs)); ls != ls_basement -> allowed(move_lift(lh), glob_state(fs, shs, ls)) = lh != height(ls); allowed(rotate_lift, glob_state(fs, shs, ls)) = height(ls) == rotate && free([pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa), pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb)], fs); nextstate(move_belts(r1bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r1bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_ctw(ms == full, positions_b_r1(r1bs), fs), shs, ls); nextstate(move_belts(r2bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r2bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r2(r2bs), fs), shs, ls); nextstate(move_belts(r3bs, col_inc, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_belts(r3bs, col_dec, ms), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec(positions_b_r3(r3bs), fs), shs, ls); nextstate(move_shuttles(sps, lowered, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(shift_inc_sps(l, fs), shift_inc(l, lowered, shs), ls) whr l = add_neighbour(sps, row_inc) end; nextstate(move_shuttles(sps, lowered, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(shift_dec_sps(l, fs), shift_dec(l, lowered, shs), ls) whr l = add_neighbour(sps, row_dec) end; nextstate(move_shuttles(sps, tilted, row_inc), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_inc(add_neighbour(sps, row_inc), tilted, shs), ls); nextstate(move_shuttles(sps, tilted, row_dec), ok, glob_state(fs, shs, ls)) = glob_state(fs, shift_dec(add_neighbour(sps, row_dec), tilted, shs), ls); nextstate(tilt_shuttle(sp, so), ok, glob_state(fs, shs, ls)) = glob_state(fs, ins_upd(sp, so, n_avail, ins_upd(sp, not(so), avail, shs)), ls); occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state( if(height(ls) != basement && lh == basement, ins_upd_fps(positions(b_r1lift), occupied, fs), if(height(ls) == basement && lh != basement, ins_upd_fps(positions(b_r1lift), free, fs), fs ) ), shs, make_ls(lh, occupied)); !occupied(ls, fs) -> nextstate(move_lift(lh), ok, glob_state(fs, shs, ls)) = glob_state(fs, shs, make_ls(lh, free)); nextstate(rotate_lift, ok, gs) = gs; nextstate(i, fail, gs) = gs; allowed([], gs) = false; allowed(i |> [], gs) = allowed(i, gs); allowed(i |> j |> is, gs) = allowed(i, gs) && !overlap(i, j |> is) && allowed(j |> is, gs); nextstate([], ok, gs) = gs; nextstate(i |> is, ok, gs) = nextstate(i, ok, nextstate(is, ok, gs)); nextstate(is, fail, gs) = gs; possible(add_car, glob_state(fs, shs, ls)) = ls == lsf_street; possible(remove_car, glob_state(fs, shs, ls)) = ls == lso_street; nextstate(add_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lso_street); nextstate(remove_car, glob_state(fs, shs, ls)) = glob_state(fs, shs, lsf_street); sort Requirement = struct req1a | req1b | req1c | req2a | req2b | req2c | req2d | req2e | req3a | req3b; act exec: Instruction; occur: Event; error: Requirement # Pos; proc V(gs_sl: GlobalState) = % normal behaviour sum i: Instruction. (valid(i) && allowed(i, gs_sl)) -> exec(i) . V(nextstate(i, ok, gs_sl)) + sum e: Event. possible(e, gs_sl) -> occur(e) . V(nextstate(e, gs_sl)) % added behaviour with the purpose of checking the requirements; % if this results in more behaviour, a requirement is not satisfied % Requirement 1a + sum i: Instruction, b: R1Belt, ms: MoveSize, bs: R1BeltSet. (!end_free(positions(b), col_inc, ms == full, fs(gs_sl)) && rhead(bs) == b && i == move_belts(bs, col_inc, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1a, 1) . delta + sum i: Instruction, b: R1Belt, ms: MoveSize, bs: R1BeltSet. (!end_free(positions(b), col_dec, ms == full, fs(gs_sl)) && head(bs) == b && i == move_belts(bs, col_dec, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1a, 2) . delta + sum i: Instruction, b: R2Belt, ms: MoveSize, bs: R2BeltSet. (!end_free(positions(b), col_inc, false, fs(gs_sl)) && rhead(bs) == b && i == move_belts(bs, col_inc, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1a, 3) . delta + sum i: Instruction, b: R2Belt, ms: MoveSize, bs: R2BeltSet. (!end_free(positions(b), col_dec, false, fs(gs_sl)) && head(bs) == b && i == move_belts(bs, col_dec, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1a, 4) . delta + sum i: Instruction, b: R3Belt, ms: MoveSize, bs: R3BeltSet. (!end_free(positions(b), col_inc, false, fs(gs_sl)) && rhead(bs) == b && i == move_belts(bs, col_inc, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1a, 5) . delta + sum i: Instruction, b: R3Belt, ms: MoveSize, bs: R3BeltSet. (!end_free(positions(b), col_dec, false, fs(gs_sl)) && head(bs) == b && i == move_belts(bs, col_dec, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1a, 6) . delta % Requirement 1b + sum i: Instruction, ms: MoveSize, bs: R1BeltSet. (available(r1a, lowered, shs(gs_sl)) && !free(positions(r1a), fs(gs_sl)) && i == move_belts(bs, col_dec, if(!occupied(positions(r1a), fs(gs_sl)), full, ms)) && contains(b_r1a_sh, bs) && valid(i) && allowed(i, gs_sl) ) -> error(req1b, 1) . delta + sum i: Instruction, ms: MoveSize, bs: R1BeltSet. (available(r1b, lowered, shs(gs_sl)) && !free(positions(r1b), fs(gs_sl)) && i == move_belts(bs, col_inc, if(!occupied(positions(r1b), fs(gs_sl)), full, ms)) && contains(b_r1b_sh, bs) && valid(i) && allowed(i, gs_sl) ) -> error(req1b, 2) . delta + sum i: Instruction, ms: MoveSize, bs: R2BeltSet. (available(r2a, lowered, shs(gs_sl)) && !free(positions(r2a), fs(gs_sl)) && i == move_belts(bs, col_dec, ms) && contains(b_r2a_sh, bs) && valid(i) && allowed(i, gs_sl) ) -> error(req1b, 3) . delta + sum i: Instruction, ms: MoveSize, bs: R2BeltSet. (available(r2b, lowered, shs(gs_sl)) && !free(positions(r2b), fs(gs_sl)) && i == move_belts(bs, col_inc, ms) && contains(b_r2b_sh, bs) && valid(i) && allowed(i, gs_sl) ) -> error(req1b, 4) . delta + sum i: Instruction, ms: MoveSize, bs: R3BeltSet. (available(r3a, lowered, shs(gs_sl)) && !free(positions(r3a), fs(gs_sl)) && i == move_belts(bs, col_dec, ms) && contains(b_r3a_sh, bs) && valid(i) && allowed(i, gs_sl) ) -> error(req1b, 5) . delta + sum i: Instruction, ms: MoveSize, bs: R3BeltSet. (available(r3b, lowered, shs(gs_sl)) && !free(positions(r3b), fs(gs_sl)) && i == move_belts(bs, col_inc, ms) && contains(b_r3b_sh, bs) && valid(i) && allowed(i, gs_sl) ) -> error(req1b, 6) . delta % Requirement 1c + sum i: Instruction, dc: DirCol, ms: MoveSize, bs: R1BeltSet. (!available_b_r1(bs, shs(gs_sl), ls(gs_sl)) && i == move_belts(bs, dc, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1c, 1) . delta + sum i: Instruction, dc: DirCol, ms: MoveSize, bs: R2BeltSet. (!available_b_r2(bs, shs(gs_sl), ls(gs_sl)) && i == move_belts(bs, dc, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1c, 2) . delta + sum i: Instruction, dc: DirCol, ms: MoveSize, bs: R3BeltSet. (!available_b_r3(bs, shs(gs_sl), ls(gs_sl)) && i == move_belts(bs, dc, ms) && valid(i) && allowed(i, gs_sl) ) -> error(req1c, 3) . delta % Requirement 2a + sum i: Instruction, sps: ShuttlePosSet, so: ShuttleOrientation. ((contains(r1a, sps) || contains(r1b, sps)) && i == move_shuttles(sps, so, row_dec) && valid(i) && allowed(i, gs_sl) ) -> error(req2a, 1) . delta + sum i: Instruction, sps: ShuttlePosSet, so: ShuttleOrientation. ((contains(r3a, sps) || contains(r3b, sps)) && i == move_shuttles(sps, so, row_inc) && valid(i) && allowed(i, gs_sl) ) -> error(req2a, 2) . delta % Requirement 2b + sum i: Instruction, sp: ShuttlePos, sps: ShuttlePosSet. (available(sp, lowered, shs(gs_sl)) && connected(rhead(sps), sp) && i == move_shuttles(sps, lowered, row_inc) && valid(i) && allowed(i, gs_sl) ) -> error(req2b, 1) . delta + sum i: Instruction, sp: ShuttlePos, sps: ShuttlePosSet. (available(sp, lowered, shs(gs_sl)) && connected(sp, head(sps)) && i == move_shuttles(sps, lowered, row_dec) && valid(i) && allowed(i, gs_sl) ) -> error(req2b, 2) . delta % Requirement 2c + sum i: Instruction, sp: ShuttlePos, sps: ShuttlePosSet, dr: DirRow. (!free(positions(sp),fs(gs_sl)) && !occupied(positions(sp),fs(gs_sl)) && contains(sp, sps) && i == move_shuttles(sps, lowered, dr) && valid(i) && allowed(i, gs_sl) ) -> error(req2c, 1) . delta % Requirement 2d + sum i: Instruction, sp: ShuttlePos, so: ShuttleOrientation. (!free(positions(sp),fs(gs_sl)) && i == tilt_shuttle(sp, so) && valid(i) && allowed(i, gs_sl) ) -> error(req2d, 1) . delta % Requirement 2e + sum i: Instruction, sp: ShuttlePos, so: ShuttleOrientation. (available(sp, so, shs(gs_sl)) && available(sp, not(so), shs(gs_sl)) && i == tilt_shuttle(sp, so) && valid(i) && allowed(i, gs_sl) ) -> error(req2e, 1) . delta % Requirement 3a + sum i: Instruction, lh: LiftHeight. (ls(gs_sl) == ls_basement && !free(positions(b_r1lift), fs(gs_sl)) && !(even_occ(positions_b_r1([b_r1a_sh, b_r1a]), fs(gs_sl)) && even_occ(positions_b_r1([b_r1b, b_r1b_sh]), fs(gs_sl))) && i == move_lift(lh) && valid(i) && allowed(i, gs_sl) ) -> error(req3a, 1) . delta % Requirement 3b + sum i: Instruction. ((height(ls(gs_sl)) != rotate || !free([pos_r1(c5, pa), pos_r1(c5, pb), pos_r1(c6, pa), pos_r1(c7, pb), pos_r1(c8, pa), pos_r1(c8, pb)], fs(gs_sl)) ) && i == rotate_lift && valid(i) && allowed(i, gs_sl) ) -> error(req3b, 1) . delta ; init V(init_gs); mcrl2-201409.0/examples/industrial/garage/readme.txt000770 001750 001750 00000002715 12370120076 022563 0ustar00outisoutis000000 000000 This directory contains specifications of the safety layer of the automated parking garage as described in [1,2]. Also some trace files are provided to give more insight in the specifications. Each specification (.mcrl2 file) can be linearised to an LPS (.lps file) using mcrl22lps. After that, the possibilities are listed in the following table. LPS xsim traces lps2lts -------------------------------------------- garage no no no garage-r1 yes no no garage-r2 yes yes/no* no garage-r2-error yes yes no garage-r3 yes no yes garage-ver yes no yes * For this LPS, the error traces do not work. This means that the errors cannot occur in the LPS. For the LPS's where traces can be used, an xsim plugin can be used that represents the visualization of the floorplan of the garage. After opening xsim, it can be loaded by choosing the "Views" menu, then "Load Plugin..." and then "libxsim_garage_view.so". References ---------- [1] Aad Mathijssen and A. Johannes Pretorius. Verified Design of an Automated Parking Garage. In Proc. FMICS and PDMC 2006, LNCS 4346, pp 165-180, Springer-Verlag, 2007. [2] Aad Mathijssen and A. Johannes Pretorius. Specification, Analysis and Verification of an Automated Parking Garage. Computer Science Report 05-25, Eindhoven University of Technology (TU/e), 2005. mcrl2-201409.0/examples/industrial/garage/lift-error.trc000770 001750 001750 00000000421 12370120076 023354 0ustar00outisoutis000000 000000 occur(add_car) exec(move_lift(rotate)) exec(move_lift(basement)) exec(move_belts([b_r1lift, b_r1b], col_inc, full)) exec(move_lift(street)) occur(add_car) exec(move_lift(basement)) exec(move_belts([b_r1a, b_r1lift, b_r1b, b_r1b_sh], col_dec, half)) exec(move_lift(street)) mcrl2-201409.0/examples/industrial/brp/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 022705 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on block. [true*]true mcrl2-201409.0/examples/industrial/brp/run.py000770 001750 001750 00000000327 12370120076 021275 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v brp.mcrl2 brp.lps') os.system('lps2pbes -v -f nodeadlock.mcf brp.lps brp.nodeadlock.pbes') os.system('pbes2bool -v brp.nodeadlock.pbes') os.system('lps2lts -v brp.lps brp.aut') mcrl2-201409.0/examples/industrial/brp/brp.mcrl2000770 001750 001750 00000005336 12370120076 021650 0ustar00outisoutis000000 000000 % Bounded retransmission protocol % % Article: % J.F. Groote and J. van de Pol. A bounded retransmission protocol % for large data packets. In M. Wirsing and M. Nivat,editors, % Algebraic Methodology and Software Technology, LNCS, pages 536-550 % Springer Verlag, 1996 sort Bit = struct e0?is_e0 | e1?is_e1; sort D = struct d0 | d1 | d2; sort Ind = struct I_fst | I_ok | I_nok | I_inc | I_dk; sort TComm = struct set | reset | ready | signal | lost; map inv: Bit -> Bit; indl: List(D) -> Bit; last: List(D) -> Bool; C_ind: List(D) -> Ind; I_ind: Bit # Bit -> Ind; var l: List(D); b0,b1: Bit; eqn inv(e0) = e1; inv(e1) = e0; indl(l) = if(#l < 2, e1, e0); last(l) = #l < 2; C_ind(l) = if( is_e0(indl(l)), I_nok, I_dk ); I_ind(b0, e1) = I_ok; I_ind(e0, e0) = I_inc; I_ind(e1, e0) = I_fst; act r1: List(D); s1,s4: Ind; s4: D # Ind; r2,s2,c2,s3,r3,c3: Bit # Bit #Bit # D; r7,s7,c7,r8,s8,c8,r9,s9,c9,r10,s10,c10: TComm; r5,s5,c5,r6,s6,c6,a; proc K = sum b0:Bit, b1:Bit, b2:Bit, d:D. r2(b0,b1,b2,d).(a.s3(b0,b1,b2,d) + a.s9(lost)).K; L = r5.(a.s6 + a.s9(lost)).L; S(b2:Bit,max:Nat) = sum l:List(D). (#l < 4) -> r1(l).S1(l,e1,b2,0,max)<>delta; S1(l:List(D), b0:Bit, b2:Bit, rn:Nat, max:Nat) = s7(set).s2(b0,indl(l),b2,head(l)).S2(l,b0,b2,rn,max); S2(l:List(D), b0:Bit, b2:Bit, rn:Nat, max:Nat) = r6.s7(reset). ( last(l) -> s1(I_ok).S(inv(b2),max) <> S1(tail(l),e0,inv(b2),rn,max) ) + r7(signal).S3(l,b0,b2,rn,max,C_ind(l)); S3(l:List(D) , b0:Bit, b2:Bit, rn:Nat ,max:Nat , c:Ind) = (rn == max) -> s1(c) . s10(ready) . r10(signal) . S(inv(b2),max) <> S1(l,b0, b2, rn + 1, max); T1 = ( r7(set).(r9(lost).(s7(signal) + r7(reset)) + r7(reset)) + r7(reset) + r9(lost) ).T1; R = sum b1:Bit, b2:Bit, d:D. r3(e1,b1,b2,d).R2(b1, b2, d, I_ind(e1,b1)); R1(b0:Bit,b2:Bit) = sum b1:Bit, d:D. (r3(b0,b1,b2,d) . s8(reset) . R2(b1,b2,d,I_ind(b0,b1)) + sum ff:Bit. r3(ff,b1,inv(b2),d).s5.R1(b0,b2)) + r8(signal).(is_e0(b0) -> s4(I_nok).s8(ready).R <> s8(ready).R); R2(b1:Bit, b2:Bit, d:D, i:Ind) = s4(d,i).s8(set).s5.R1(b1,inv(b2)); T2 = ( r8(set). ( r10(ready).( s8(signal).r8(ready) + r8(reset) ). s10(signal) + r8(reset) ) + r10(ready).s10(signal) + r8(reset) ).T2; init hide({c2,c3,c5,c6,c7,c8,c9,c10,a,r1,s4}, allow({c2,c3,c5,c6,c7,c8,c9,c10,a,r1,s1,s4}, comm({r2|s2->c2, r3|s3->c3, r5|s5->c5, r6|s6->c6, r7|s7->c7, s8|r8->c8, r9|s9->c9, r10|s10->c10 }, T1 || S(e0,3) || K || L || R || T2 ))); mcrl2-201409.0/examples/industrial/lift/lift3-final.mcrl2000770 001750 001750 00000017100 12370120076 023340 0ustar00outisoutis000000 000000 % Specification of a system for lifting trucks % Based on the original specification in muCRL by Arno Wouters and Pang Jun, 12 % February 2001 % Translated to mCRL2 by Bas Ploeger % % Main modification: % 1) The sync message is used to finish the startup phase in old specification, % this is removed. % 2) Using move(n,s) to replace move_down(n), move_up(n), move_not(n) % % This is the final specification used for model checking. % % In this specification the following problems are solved (or avoided): % % (1) Station 2 sends startup message before relay between 1 and 2 closed. % Solved by adding a sync action after closing the relay. This models % a delay (before station 2 sends its startup message) which is long % enough to be sure that the relay is closed % (2) Errors resulting from more than one setref button pressed in the initial % phase. This made impossible by adding a Setref_monitor process. % This models the situation that the operators conform to the instruction % in the manual which states that they must assure sure that the system % is started from one lift only. % (3) The problem that releasing a button at the wrong moment may lead to a % state in which all stations are UP or DOWN but no one is active. % This is solved as follows: after release the station waits until it % is its turn to use the bus before it becomes passive % (4) The problem that pressing two up buttons or two down buttons at different % lifts may result in one lift remaining motion less while the others move % (if one button is released at the wrong moment). This is solved as follows: % after a button being pressed the station waits till it is turn to % use the bus before it becomes active and it becomes active only % if it is sure that there is no other station active (i.e. if the % message it received from the station just before it was a STANDBY message). % % The real system measures the height of the lifts and broadcasts these. This is % not taken into account in this specification. % % This specification models two kinds of movements: % - movement of all lifts together % - movement of a single lift % The real system has, in addition, the possibility to move an axis. This % is not modelled in this specification. % % For more information, please refer to the following publication: % % J.F. Groote, J. Pang and A.G. Wouters. Analysis of a distributed system % for lifting trucks. The Journal of Logic and Algebraic Programming % 55:21-56, 2003. This article also appeared as Technical report % SEN-R0111, CWI, Amsterdam, 2001. sort State = struct STANDBY | STOP | STARTUP | UP | DOWN | SYNC; map N: Pos; eqn N = 3; map S: Nat -> Nat; P: Nat -> Nat; var n: Nat; eqn n < N -> S(n) = n+1; n == N -> S(n) = 1; n > 1 -> P(n) = Int2Nat(n-1); n == 1 -> P(n) = Pos2Nat(N); map remove: Nat # List(Nat) -> List(Nat); inl: Nat # List(Nat) -> Bool; var n:Nat; l:List(Nat); eqn remove(n,[]) = []; n == head(l) -> remove(n,l) = remove(n,tail(l)); n != head(l) -> remove(n,l) = head(l) |> remove(n,tail(l)); inl(n,[]) = false; n == head(l) -> inl(n,l) = true; n != head(l) -> inl(n,l) = inl(n,tail(l)); map Addresses: List(Nat) # Nat -> List(Nat); Addresses_up: List(Nat) # Nat # Nat -> List(Nat); Addresses_down: List(Nat) # Nat # Nat -> List(Nat); var a,a': Nat; A,A': List(Nat); b: Bool; eqn Addresses(A,a) = Addresses_up(A,a,a) ++ Addresses_down(A,a,a); (inl(a,A) && a' == S(a)) -> Addresses_up(A,a,a') = [ S(a) ]; (inl(a,A) && a' != S(a)) -> Addresses_up(A,a,a') = S(a) |> Addresses_up(A,S(a),a'); !(inl(a,A)) -> Addresses_up(A,a,a') = []; P(a) == a' -> Addresses_down(A,a,a') = []; (P(a) != a' && inl(P(a),A)) -> Addresses_down(A,a,a') = P(a) |> Addresses_down(A,P(a),a'); (P(a) != a' && !inl(P(a),A)) -> Addresses_down(A,a,a') = []; sort Message = struct mes(address:Nat,state:State); act r_stob,s_stob,c_stob: Message # Nat; r_btos,s_btos,c_btos: Message # Nat; r_open_relay ,s_open_relay ,c_open_relay : Nat; r_close_relay,s_close_relay,c_close_relay: Nat; s_init,r_init,c_init: Nat; setref,setrefup,setrefdown,up,down,unlockup,unlockdown,released: Nat; move: Nat # State; s_sync,r_sync,c_sync; s_stable,r_stable,c_stable; proc Bus(R:List(Nat)) = sum msg:Message,a:Nat . r_stob(msg,a). ( (Addresses(R,a) == []) -> Bus(R) <> Deliver(msg,R,Addresses(R,a)) ) + sum a:Nat . ( r_open_relay(a).Bus(remove(a,R)) + r_close_relay(a).Bus(a |> R) ); proc Deliver(m:Message, R:List(Nat), A:List(Nat) ) = sum a:Nat . ( ( (inl(a,A)) -> s_btos(m,a). ( (remove(a,A) == []) -> Bus(R) <> Deliver(m,R,remove(a,A)) )<>delta ) + r_open_relay(a).Deliver(m,remove(a,R),A) + r_close_relay(a).Deliver(m,a|>R,A) ); proc Lift0(n:Nat) = s_init(n).s_close_relay(n).s_stob(mes(1,STARTUP),n).s_open_relay(n). s_sync. ( sum msg:Message . r_btos(msg,n). ( (state(msg) == STARTUP) -> s_stable.s_stob(mes(1,STANDBY),n). Lift2(n,1,address(msg),STANDBY,false)<>delta ) ) + sum msg:Message . r_btos(msg,n). ( (state(msg) == STARTUP) -> s_close_relay(n). ( (address(msg) == 1) -> r_sync.s_stob(mes(2,STARTUP),n). Lift1(n,S(address(msg)),S(address(msg))) <> s_stob(mes(S(address(msg)),STARTUP),n). Lift1(n,S(address(msg)),S(address(msg))) )<>delta ); proc Lift1(n:Nat,m:Nat,nos:Nat) = sum msg:Message . r_btos(msg,n). ( (state(msg) == STARTUP) -> Lift1(n,m,address(msg)) <> ( (state(msg) == STANDBY) -> ( (address(msg) == P(m)) -> s_stob(mes(m,STANDBY),n).Lift2(n,m,nos,STANDBY,false) <> Lift2(n,m,nos,STANDBY,false) )<>delta ) ); proc Lift2(n:Nat,m:Nat,nos:Nat,s:State,c:Bool) = (s == STANDBY) -> ( up(n).Lift2(n,m,nos,UP,true) + down(n).Lift2(n,m,nos,DOWN,true) ) <> delta + sum msg:Message . r_btos(msg,n). ( (state(msg) == SYNC) -> move(n,s).Lift2(n,m,nos,s,c) <> ( (address(msg) == P(m)) -> ( c -> ( (state(msg) == STANDBY) -> s_stob(mes(m,s),n).Lift3(n,m,nos,s,nos) <> s_stob(mes(m,state(msg)),n).Lift2(n,m,nos,state(msg),false) ) <> s_stob(mes(m,state(msg)),n).Lift2(n,m,nos,state(msg),c) ) <> ( c -> Lift2(n,m,nos,s,c) <> Lift2(n,m,nos,state(msg),c) ) ) ); proc Lift3(n:Nat,m:Nat,nos:Nat,s:State,count:Nat) = (s != STANDBY ) -> released(n).Lift3(n,m,nos,STANDBY,nos)<>delta + sum msg:Message. r_btos(msg,n). %move(n,s).Lift3(n,m,nos,s,count) ( (address(msg) == P(m)) -> ( (s == STANDBY) -> s_stob(mes(m,STANDBY),n).Lift2(n,m,nos,STANDBY,false) <> ( (state(msg) == s && count == 2) -> s_stob(mes(m,SYNC),n).move(n,s).s_stob(mes(m,s),n). Lift3(n,m,nos,s,nos) <> s_stob(mes(m,s),n).Lift3(n,m,nos,s,nos) ) ) <> ( (state(msg) == s) -> Lift3(n,m,nos,s,P(count)) <> Lift3(n,m,nos,s,count) ) ); proc Setref_monitor = sum n:Nat . r_init(n).r_stable.Setref_monitor; init hide ( { c_stob,c_btos,c_open_relay,c_close_relay,c_sync,c_init,c_stable }, allow ( { c_stob,c_btos,c_open_relay,c_close_relay,c_sync,c_init,c_stable, setref,setrefup,setrefdown,up,down,unlockup,unlockdown,released, move }, comm ( { s_stob|r_stob->c_stob, s_btos|r_btos->c_btos, s_open_relay|r_open_relay->c_open_relay, s_close_relay|r_close_relay->c_close_relay, s_sync|r_sync->c_sync, s_init|r_init->c_init, s_stable|r_stable->c_stable }, Bus([]) || Lift0(1) || Lift0(2) || Lift0(3) || Setref_monitor ) ) ); mcrl2-201409.0/examples/industrial/lift/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 023060 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on block. [true*]true mcrl2-201409.0/examples/industrial/lift/run.py000770 001750 001750 00000001353 12370120076 021450 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vn lift3-final.mcrl2 lift3-final.lps') os.system('lps2pbes -v -f nodeadlock.mcf lift3-final.lps lift3-final.nodeadlock.pbes') os.system('pbes2bool -vrjittyc lift3-final.nodeadlock.pbes') os.system('lps2lts -vrjittyc lift3-final.lps lift3-final.aut') os.system('mcrl22lps -vn lift3-init.mcrl2 lift3-init.lps') os.system('lps2pbes -v -f nodeadlock.mcf lift3-init.lps lift3-init.nodeadlock.pbes') os.system('pbes2bool -vrjittyc lift3-init.nodeadlock.pbes') os.system('lps2lts -vrjittyc lift3-init.lps lift3-init.aut') os.system('ltscompare -vebisim lift3-init.aut lift3-final.aut') os.system('lpsbisim2pbes -v lift3-init.lps lift3-final.lps lift3-bisim.pbes') os.system('pbes2bool -vrjittyc lift3-bisim.pbes') mcrl2-201409.0/examples/industrial/lift/lift3-init.mcrl2000770 001750 001750 00000012205 12370120076 023213 0ustar00outisoutis000000 000000 % Specification of a system for lifting trucks % Based on the original specification in muCRL by Arno Wouters and Pang Jun, 13 % November 2000 % Translated to mCRL2 by Bas Ploeger % % This is the initial specification of the system in which no problems have been % solved. % % The real system measures the height of the lifts and broadcasts these. This is % not taken into account in this specification. % % This specification models: % - movement of all lifts together % The real system has, in addition, two other possibilities which % are not modelled in the present specification % - movement of a single lift % - movement of an axis % % For more information, please refer to the following publication: % % J.F. Groote, J. Pang and A.G. Wouters. Analysis of a distributed system % for lifting trucks. The Journal of Logic and Algebraic Programming % 55:21-56, 2003. This article also appeared as Technical report % SEN-R0111, CWI, Amsterdam, 2001. sort State = struct STANDBY | STOP | STARTUP | UP | DOWN | SYNC; map N: Pos; eqn N = 3; map S: Nat -> Nat; P: Nat -> Nat; var n: Nat; eqn n < N -> S(n) = n+1; n == N -> S(n) = 1; n > 1 -> P(n) = Int2Nat(n-1); n == 1 -> P(n) = Pos2Nat(N); map remove: Nat # List(Nat) -> List(Nat); inl: Nat # List(Nat) -> Bool; var n:Nat; l:List(Nat); eqn remove(n,[]) = []; n == head(l) -> remove(n,l) = remove(n,tail(l)); n != head(l) -> remove(n,l) = head(l) |> remove(n,tail(l)); inl(n,[]) = false; n == head(l) -> inl(n,l) = true; n != head(l) -> inl(n,l) = inl(n,tail(l)); map Addresses: List(Nat) # Nat -> List(Nat); Addresses_up: List(Nat) # Nat # Nat -> List(Nat); Addresses_down: List(Nat) # Nat # Nat -> List(Nat); var a,a': Nat; A,A': List(Nat); b: Bool; eqn Addresses(A,a) = Addresses_up(A,a,a) ++ Addresses_down(A,a,a); (inl(a,A) && a' == S(a)) -> Addresses_up(A,a,a') = [ S(a) ]; (inl(a,A) && a' != S(a)) -> Addresses_up(A,a,a') = S(a) |> Addresses_up(A,S(a),a'); !(inl(a,A)) -> Addresses_up(A,a,a') = []; P(a) == a' -> Addresses_down(A,a,a') = []; (P(a) != a' && inl(P(a),A)) -> Addresses_down(A,a,a') = P(a) |> Addresses_down(A,P(a),a'); (P(a) != a' && !inl(P(a),A)) -> Addresses_down(A,a,a') = []; sort Message = struct mes(address:Nat,state:State); act r_stob,s_stob,c_stob: Message # Nat; r_btos,s_btos,c_btos: Message # Nat; r_open_relay ,s_open_relay ,c_open_relay : Nat; r_close_relay,s_close_relay,c_close_relay: Nat; protocol_error: Nat; setref,up,down,released: Nat; move: Nat # State; proc Bus(R:List(Nat)) = sum msg:Message,a:Nat . r_stob(msg,a). ( (Addresses(R,a) == []) -> Bus(R) <> Deliver(msg,R,Addresses(R,a)) ) + sum a:Nat . ( r_open_relay(a).Bus(remove(a,R)) + r_close_relay(a).Bus(a |> R) ); proc Deliver(m:Message, R:List(Nat), A:List(Nat) ) = sum a:Nat . ( s_btos(m,a). ( (inl(a,A)) -> ( (remove(a,A) == []) -> Bus(R) <> Deliver(m,R,remove(a,A)) ) <> delta) + r_open_relay(a).Deliver(m,remove(a,R),A) + r_close_relay(a).Deliver(m,a|>R,A) ); proc Lift0(n:Nat) = setref(n).s_close_relay(n).s_stob(mes(1,STARTUP),n).s_open_relay(n). ( sum msg:Message . r_btos(msg,n). ( (state(msg) == STARTUP) -> s_stob(mes(1,SYNC),n).s_stob(mes(1,STANDBY),n).Lift2(n,1,address(msg),STANDBY) <> protocol_error(n).Lift2(n,1,1,STOP) ) ) + sum msg:Message . r_btos(msg,n). ( (state(msg) == STARTUP) -> s_close_relay(n).s_stob(mes(S(address(msg)),STARTUP),n). Lift1(n,S(address(msg)),S(address(msg))) <> protocol_error(n).Lift2(n,1,1,STOP) ); proc Lift1(n:Nat,m:Nat,nos:Nat) = sum msg:Message . r_btos(msg,n). ( (state(msg) == STARTUP) -> Lift1(n,m,address(msg)) <> ( (state(msg) == SYNC) -> Lift2(n,m,nos,STANDBY) <> protocol_error(n).Lift2(n,m,1,STOP) ) ); proc Lift2(n:Nat,m:Nat,nos:Nat,s:State) = (s == STANDBY) -> ( up(n).Lift3(n,m,nos,UP,nos) + down(n).Lift3(n,m,nos,DOWN,nos) )<>delta + sum msg:Message . r_btos(msg,n). ( (state(msg) == SYNC) -> move(n,s).Lift2(n,m,nos,s) <> ( (address(msg) == P(m)) -> s_stob(mes(m,state(msg)),n).Lift2(n,m,nos,state(msg)) <> Lift2(n,m,nos,state(msg)) ) ); proc Lift3(n:Nat,m:Nat,nos:Nat,s:State,count:Nat) = released(n).Lift2(n,m,nos,STANDBY) + sum msg:Message. r_btos(msg,n). ( (state(msg) == SYNC) -> move(n,s).Lift3(n,m,nos,s,count) <> ( (address(msg) == P(m)) -> ( (state(msg) == s && count == 2) -> s_stob(mes(m,SYNC),n).move(n,s).s_stob(mes(m,s),n). Lift3(n,m,nos,s,nos) <> s_stob(mes(m,s),n).Lift3(n,m,nos,s,nos) ) <> ( (state(msg) == s) -> Lift3(n,m,nos,s,P(count)) <> Lift3(n,m,nos,s,count) ) ) ); init hide ( { c_stob,c_btos,c_open_relay,c_close_relay }, allow ( { c_stob,c_btos,c_open_relay,c_close_relay,protocol_error, setref,up,down,released, move }, comm ( { s_stob|r_stob->c_stob, s_btos|r_btos->c_btos, s_open_relay|r_open_relay->c_open_relay, s_close_relay|r_close_relay->c_close_relay }, Bus([]) || Lift0(1) || Lift0(2) || Lift0(3) ) ) ); mcrl2-201409.0/examples/industrial/DIRAC/SMS.mcrl2000770 001750 001750 00000046523 12370120076 021571 0ustar00outisoutis000000 000000 % Specification of the Storage Management System of the DIRAC Community Grid Solution [1] % for the LHCb [2] experiment at CERN. This subsystem provides the logic for pre-staging files % from tape to a disk cache frontend, before a job is able to process them. % A series of agents (modeled as recursive processes) observe and update the states of the % centralized storage entities (Tasks and CacheReplicas). These shared storage entities are % modeled as processes continuously listening and responding to requests from other processes (agents). % % [1] A. Tsaregorodtsev et al. ""DIRAC: A community grid solution,"" in Proc. Computing in % High Energy Physics, 2007 % % [2] Large Hadron Collider beauty experiment. % [Online] http://lhcb-public.web.cern.ch/lhcb-public % % % Authors: Daniela Remenska, Tim Willemse % October 2011 % % The following commands will generate a state space: % mcrl22lps SMS.mcrl2 SMS.lps % lps2lts -vrjittyc SMS.lps % State space statistics: 36 levels, 18417 states and 123478 transitions sort CacheReplicas = struct Start?is_start | New?is_new | Waiting?is_waiting | StageSubmitted?is_stageSubmitted | Staged?is_staged | Failed?is_failed | Deleted?is_deleted; sort Tasks = struct tStart?is_tStart | tNew?is_tNew | tStageSubmitted?is_tStageSubmitted | tStaged?is_tStaged | tDone?is_tDone | tFailed?is_tFailed | tDeleted?is_tdeleted; sort Tuple = struct p(t:Nat,r:Nat,link:Bool); % tasks-to-ids mapping: given a list of Tasks, and a Tasks value, get the positions of the list matching the value % example t2id([one,two,two,three],two)->[1,2] map t2id:List(Tasks)#Tasks->List(Nat); map t2id':List(Tasks)#Tasks#Nat->List(Nat); var t:List(Tasks); s:Tasks; n:Nat; a:Tasks; l:List(Tasks); eqn t2id(t,s) = t2id'(t,s,0); t2id'([],s,n) = []; a == s -> t2id'(a|>l,s,n) = n|>t2id'(l,s,n+1); a != s -> t2id'(a|>l,s,n) = t2id'(l,s,n+1); % ids-to-tasks mapping: given a list of Tasks, a list of positions(IDs) in the list, and a Tasks value, update those positions with the new value %example id2t([2,3],[two,three,three,two],one)->[two,three,one,one] map id2t:List(Nat)#List(Tasks)#Tasks->List(Tasks); map id2t':List(Nat)#List(Tasks)#Tasks#Nat->List(Tasks); var listIDs:List(Nat); listTasks:List(Tasks); newState:Tasks; n:Nat; a:Tasks; l:List(Tasks); eqn id2t(listIDs,listTasks,newState) = id2t'(listIDs,listTasks,newState,0); id2t'(listIDs,[],newState,n) = []; n in listIDs -> id2t'(listIDs,a|>l,newState,n) = newState|>id2t'(listIDs,l,newState,n+1); !(n in listIDs) -> id2t'(listIDs,a|>l,newState,n) = a|>id2t'(listIDs,l,newState,n+1); %--------------------------------------------- % same as t2id only mapping from List(CacheReplicas) instead of List(Tasks) map cr2id:List(CacheReplicas)#CacheReplicas->List(Nat); map cr2id':List(CacheReplicas)#CacheReplicas#Nat->List(Nat); var t:List(CacheReplicas); s:CacheReplicas; n:Nat; a:CacheReplicas; l:List(CacheReplicas); eqn cr2id(t,s) = cr2id'(t,s,0); cr2id'([],s,n) = []; a == s -> cr2id'(a|>l,s,n) = n|>cr2id'(l,s,n+1); a != s -> cr2id'(a|>l,s,n) = cr2id'(l,s,n+1); %example id2cr([2,3],[two,three,three,two],one)->[two,three,one,one] map id2cr:List(Nat)#List(CacheReplicas)#CacheReplicas->List(CacheReplicas); map id2cr':List(Nat)#List(CacheReplicas)#CacheReplicas#Nat->List(CacheReplicas); var listIDs:List(Nat); listCR:List(CacheReplicas); newState:CacheReplicas; n:Nat; a:CacheReplicas; l:List(CacheReplicas); eqn id2cr(listIDs,listCR,newState) = id2cr'(listIDs,listCR,newState,0); id2cr'(listIDs,[],newState,n) = []; n in listIDs -> id2cr'(listIDs,a|>l,newState,n) = newState|>id2cr'(listIDs,l,newState,n+1); !(n in listIDs) -> id2cr'(listIDs,a|>l,newState,n) = a|>id2cr'(listIDs,l,newState,n+1); %------------------------------------ %example id2cr1([0,1],[four,one,two,three]->[four,one]) map id2cr1:List(Nat)#List(CacheReplicas)->List(CacheReplicas); map id2cr1':List(Nat)#List(CacheReplicas)#Nat->List(CacheReplicas); var listIDs,l:List(Nat); n,a:Nat; listCR:List(CacheReplicas); eqn id2cr1(listIDs,listCR) = id2cr1'(listIDs,listCR,0); id2cr1'([],listCR,n) = []; id2cr1'(a|>l,listCR,n) = listCR.n|>id2cr1'(l,listCR,n+1); %------------------------------------ %example allStaged([Staged,Staged,Staged])->True; allStaged([Staged,New])->False; map allStaged:List(CacheReplicas)->Bool; map allStaged':List(CacheReplicas)#Nat->Bool; var listCR,l:List(CacheReplicas); cr:CacheReplicas; n:Nat; eqn allStaged(listCR) = allStaged'(listCR,0); allStaged'([],n) = true; is_staged(cr) -> allStaged'(cr|>l,n) = allStaged'(l,n+1) && true; !is_staged(cr) -> allStaged'(cr|>l,n) = allStaged'(l,n+1) && false; %------------------------------------ %tasks-for-replicas: given a list of tuples of the form p(taskID,replicaID) [many-to-many relation possible], and a list of replica positions(IDs), return a list of all task IDs corresponding to the replica IDs. %example t4r([p(0, 0), p(0, 1), p(1, 0), p(1, 1), p(0, 2), p(2, 3)],[0,3])->[0,1,2] map t4r:List(Tuple)#List(Nat)->List(Nat); map t4r':List(Tuple)#List(Nat)#Nat->List(Nat); var lt,listTuples:List(Tuple); RepIDs:List(Nat); n:Nat; tuple:Tuple; eqn %listTuples = [p(0,0),p(0,1),p(1,0),p(1,1),p(0,2),p(2,3)]; t4r(listTuples,RepIDs) = t4r'(listTuples,RepIDs,0); t4r'([],RepIDs,n) = []; r(tuple) in RepIDs -> t4r'(tuple|>lt,RepIDs,n) = t(tuple)|>t4r'(lt,RepIDs,n+1); !(r(tuple) in RepIDs) -> t4r'(tuple|>lt,RepIDs,n) = t4r'(lt,RepIDs,n+1); %------------------------------------ %given a list of tuples of the form p(taskID,replicaID) , and a list of Task IDs, set all tuples with the corresponding TaskIDs to false (third parameter of the tuple) %example removeLinks([p(0,0,true),p(0,1,true),p(1,0,true),p(1,1,true)],[0])-> [p(0,0,false),p(0,1,false),p(1,0,true),p(1,1,true)] map removeLinks:List(Tuple)#List(Nat)->List(Tuple); map removeLinks':List(Tuple)#List(Nat)#Nat->List(Tuple); var lt,listTuples:List(Tuple); TaskIDs:List(Nat); n:Nat; tuple:Tuple; eqn removeLinks(listTuples,TaskIDs) = removeLinks'(listTuples,TaskIDs,0); removeLinks'([],TaskIDs,n) = []; t(tuple) in TaskIDs -> removeLinks'(tuple|>lt,TaskIDs,n) = p(t(tuple),r(tuple),false)|>removeLinks'(lt,TaskIDs,n+1); !(t(tuple) in TaskIDs) -> removeLinks'(tuple|>lt,TaskIDs,n) = tuple|>removeLinks'(lt,TaskIDs,n+1); %------------------------------------ %given a list of tuples of the form p(taskID,replicaID,bool) , select a list of replica IDs such that there is no link(third parameter of the tuple is false) between a replica and any task %example selectUnlinked([p(0,0,true),p(0,1,true),p(1,0,false),p(1,1,false),p(2,2,false)])->[2] map selectUnlinked:List(Tuple)->List(Nat); map selectUnlinked':List(Tuple)#List(Nat)#Nat->List(Nat); %helper transformation to select all the linked replica IDs map selectLinked:List(Tuple)->List(Nat); map selectLinked':List(Tuple)#Nat->List(Nat); var lt,listTuples:List(Tuple); linked:List(Nat); n,m:Nat; tuple:Tuple; eqn selectLinked(listTuples) = selectLinked'(listTuples,0); selectLinked'([],n) = []; link(tuple) -> selectLinked'(tuple|>lt,n) = r(tuple)|>selectLinked'(lt,n+1); !link(tuple) -> selectLinked'(tuple|>lt,n) = selectLinked'(lt,n+1); selectUnlinked(listTuples) = selectUnlinked'(listTuples,selectLinked(listTuples),0); selectUnlinked'([],linked,m) = []; !(link(tuple)) && !(r(tuple) in linked) -> selectUnlinked'(tuple|>lt,linked,m) = r(tuple)|>selectUnlinked'(lt,linked,m+1); link(tuple) || r(tuple) in linked -> selectUnlinked'(tuple|>lt,linked,m) = selectUnlinked'(lt,linked,m+1); %------------------------------------ act RPAgent_selectTasks_,_RPAgent_selectTasks:List(Nat)#Tasks; act RPAgent_selectTasks:List(Nat)#Tasks; act RPAgent_prepareNewReplicasT_,_RPAgent_prepareNewReplicasT,RPAgent_prepareNewReplicasT:List(Nat)#Tasks; act SRAgent_selectTasks_,_SRAgent_selectTasks:List(Nat)#Tasks; act SRAgent_selectTasks:List(Nat)#Tasks; act SRAgent_issuePrestageRequestsT_,_SRAgent_issuePrestageRequestsT,SRAgent_issuePrestageRequestsT:List(Nat)#Tasks; act SMAgent_selectTasks_,_SMAgent_selectTasks:List(Nat)#Tasks; act SMAgent_selectTasks:List(Nat)#Tasks; act SMAgent_monitorStageRequestsT_,_SMAgent_monitorStageRequestsT,SMAgent_monitorStageRequestsT:List(Nat)#Tasks; act RFAgent_selectTasks_,_RFAgent_selectTasks:List(Nat)#Tasks; act RFAgent_selectTasks:List(Nat)#Tasks; act RFAgent_clearFailedTasksT_,_RFAgent_clearFailedTasksT,RFAgent_clearFailedTasksT:List(Nat)#Tasks; act RFAgent_callbackStagedTasksT_,_RFAgent_callbackStagedTasksT,RFAgent_callbackStagedTasksT:List(Nat)#Tasks; act RPAgent_selectCacheReplicas_,_RPAgent_selectCacheReplicas:List(Nat)#CacheReplicas; act RPAgent_selectCacheReplicas:List(Nat)#CacheReplicas; act RPAgent_prepareNewReplicas_,_RPAgent_prepareNewReplicas,RPAgent_prepareNewReplicas:List(Nat)#CacheReplicas; act SRAgent_selectCacheReplicas_,_SRAgent_selectCacheReplicas:List(Nat)#CacheReplicas; act SRAgent_selectCacheReplicas:List(Nat)#CacheReplicas; act SRAgent_issuePrestageRequests_,_SRAgent_issuePrestageRequests,SRAgent_issuePrestageRequests:List(Nat)#CacheReplicas; act SMAgent_selectCacheReplicas_,_SMAgent_selectCacheReplicas:List(Nat)#CacheReplicas; act SMAgent_selectCacheReplicas:List(Nat)#CacheReplicas; act SMAgent_monitorStageRequests_,_SMAgent_monitorStageRequests,SMAgent_monitorStageRequests:List(Nat)#CacheReplicas; act RPAgent_selectTaskReplicas_,_RPAgent_selectTaskReplicas:List(Nat)#List(Nat); act RPAgent_selectTaskReplicas:List(Nat)#List(Nat); act SRAgent_selectTaskReplicas_,_SRAgent_selectTaskReplicas:List(Nat)#List(Nat); act SRAgent_selectTaskReplicas:List(Nat)#List(Nat); act SMAgent_selectTaskReplicas_,_SMAgent_selectTaskReplicas:List(Nat)#List(Nat); act SMAgent_selectTaskReplicas:List(Nat)#List(Nat); act RFAgent_removeLinks_,_RFAgent_removeLinks:List(Nat); act RFAgent_removeLinks:List(Nat); act RFAgent_selectUnlinkedReplicas_,_RFAgent_selectUnlinkedReplicas:List(Nat); act RFAgent_selectUnlinkedReplicas:List(Nat); act RFAgent_removeUnlinkedReplicas_,_RFAgent_removeUnlinkedReplicas:List(Nat)#CacheReplicas; act RFAgent_removeUnlinkedReplicas:List(Nat)#CacheReplicas; act StorageManagerHandler_createTask_,_StorageManagerHandler_createTask:Tasks; act StorageManagerHandler_createTask:Tasks; act StorageManagerHandler_setRequest; act StorageManagerHandler_insertReplicaInfo_,_StorageManagerHandler_insertReplicaInfo:List(CacheReplicas); act StorageManagerHandler_insertReplicaInfo:List(CacheReplicas); act StorageManagerHandler_insertTaskReplicaInfo_,_StorageManagerHandler_insertTaskReplicaInfo:List(Tuple); act StorageManagerHandler_insertTaskReplicaInfo:List(Tuple); act StorageManagerHandler_getReplicaStates_,_StorageManagerHandler_getReplicaStates:List(Nat)#List(CacheReplicas); act StorageManagerHandler_getReplicaStates:List(Nat)#List(CacheReplicas); act StorageManagerHandler_updateTaskStatus_,_StorageManagerHandler_updateTaskStatus:List(Nat)#Tasks; StorageManagerHandler_updateTaskStatus:List(Nat)#Tasks; act internal; act state:List(Tasks); % for verification act stateCR:List(CacheReplicas); % for verification %----------------------Tasks memory simulation via process proc Tasksproc(d:List(Tasks)) = sum t:Tasks. RPAgent_selectTasks_(t2id(d,t),t).Tasksproc(d) + sum l:List(Nat),t:Tasks. RPAgent_prepareNewReplicasT_(l,t).Tasksproc(id2t(l,d,t))+ sum t:Tasks. SRAgent_selectTasks_(t2id(d,t),t).Tasksproc(d) + sum l:List(Nat),t:Tasks. SRAgent_issuePrestageRequestsT_(l,t).Tasksproc(id2t(l,d,t)) + sum t:Tasks. SMAgent_selectTasks_(t2id(d,t),t).Tasksproc(d) + sum l:List(Nat),t:Tasks. SMAgent_monitorStageRequestsT_(l,t).Tasksproc(id2t(l,d,t)) + sum t:Tasks. RFAgent_selectTasks_(t2id(d,t),t).Tasksproc(d) + sum l:List(Nat),t:Tasks. RFAgent_clearFailedTasksT_(l,t).Tasksproc(id2t(l,d,t)) + sum l:List(Nat),t:Tasks. RFAgent_callbackStagedTasksT_(l,t).Tasksproc(id2t(l,d,t))+ sum t:Tasks. StorageManagerHandler_createTask_(t).Tasksproc(d<|t) + sum l:List(Nat),t:Tasks. StorageManagerHandler_updateTaskStatus_(l,t).Tasksproc(id2t(l,d,t)) + state(d).Tasksproc(d); %----------------------CacheReplicas memory simulation via process proc CacheReplicasproc(d:List(CacheReplicas)) = sum t:CacheReplicas. RPAgent_selectCacheReplicas_(cr2id(d,t),t).CacheReplicasproc(d) + sum l:List(Nat),t:CacheReplicas. RPAgent_prepareNewReplicas_(l,t).CacheReplicasproc(id2cr(l,d,t))+ sum t:CacheReplicas. SRAgent_selectCacheReplicas_(cr2id(d,t),t).CacheReplicasproc(d) + sum l:List(Nat),t:CacheReplicas. SRAgent_issuePrestageRequests_(l,t).CacheReplicasproc(id2cr(l,d,t)) + sum t:CacheReplicas. SMAgent_selectCacheReplicas_(cr2id(d,t),t).CacheReplicasproc(d) + sum l:List(Nat),t:CacheReplicas. SMAgent_monitorStageRequests_(l,t).CacheReplicasproc(id2cr(l,d,t)) + sum l:List(Nat),t:CacheReplicas. RFAgent_removeUnlinkedReplicas_(l,t).CacheReplicasproc(id2cr(l,d,t))+ sum l:List(CacheReplicas). StorageManagerHandler_insertReplicaInfo_(l).CacheReplicasproc(d++l)+ sum l:List(Nat). StorageManagerHandler_getReplicaStates_(l,id2cr1(l,d)).CacheReplicasproc(d)+ stateCR(d).CacheReplicasproc(d); %----------------------TaskReplicas memory simulation via process proc TaskReplicasproc(tuple:List(Tuple)) = sum c:List(Nat). RPAgent_selectTaskReplicas_(t4r(tuple,c),c).TaskReplicasproc(tuple) + sum c:List(Nat). SRAgent_selectTaskReplicas_(t4r(tuple,c),c).TaskReplicasproc(tuple) + sum c:List(Nat). SMAgent_selectTaskReplicas_(t4r(tuple,c),c).TaskReplicasproc(tuple) + sum c:List(Nat). RFAgent_removeLinks_(c).TaskReplicasproc(removeLinks(tuple,c)) + RFAgent_selectUnlinkedReplicas_(selectUnlinked(tuple)).TaskReplicasproc(tuple) + sum l:List(Tuple). StorageManagerHandler_insertTaskReplicaInfo_(l).TaskReplicasproc(tuple++l); %---------------------- RPAgent = sum cc:List(Nat)._RPAgent_selectCacheReplicas(cc,New). ((cc!=[])-> (_RPAgent_prepareNewReplicas(cc,Failed). sum tt:List(Nat)._RPAgent_selectTaskReplicas(tt,cc). ((tt!=[])->_RPAgent_prepareNewReplicasT(tt,tFailed) <> internal) + _RPAgent_prepareNewReplicas(cc,Waiting)) <> internal) .RPAgent; %---------------------- SRAgent = sum cc:List(Nat)._SRAgent_selectCacheReplicas(cc,Waiting). ((cc!=[])-> (_SRAgent_issuePrestageRequests(cc,Failed). sum tt:List(Nat)._SRAgent_selectTaskReplicas(tt,cc). ((tt!=[])->_SRAgent_issuePrestageRequestsT(tt,tFailed) <> internal) + _SRAgent_issuePrestageRequests(cc,StageSubmitted). sum tt:List(Nat)._SRAgent_selectTaskReplicas(tt,cc). ((tt!=[])->_SRAgent_issuePrestageRequestsT(tt,tStageSubmitted) <> internal) %here the two actions action1.action2 should happen without interleaving ) <> internal) .SRAgent; %---------------------- SMAgent = sum cc:List(Nat)._SMAgent_selectCacheReplicas(cc,StageSubmitted). ((cc!=[])-> (_SMAgent_monitorStageRequests(cc,Failed). sum tt:List(Nat)._SMAgent_selectTaskReplicas(tt,cc). ((tt!=[])->_SMAgent_monitorStageRequestsT(tt,tFailed) <> internal) + _SMAgent_monitorStageRequests(cc,Staged). sum tt:List(Nat)._SMAgent_selectTaskReplicas(tt,cc). ((tt!=[])->_SMAgent_monitorStageRequestsT(tt,tStaged) <> internal) ) <> internal) .SMAgent; %---------------------- RFAgent = sum tf:List(Nat)._RFAgent_selectTasks(tf,tFailed).((tf!=[])->_RFAgent_clearFailedTasksT(tf,tDeleted)<>internal). sum ts:List(Nat)._RFAgent_selectTasks(ts,tStaged).((ts!=[])->_RFAgent_callbackStagedTasksT(ts,tDeleted)<>internal). sum td:List(Nat)._RFAgent_selectTasks(td,tDeleted).((td!=[])->_RFAgent_removeLinks(td)<>internal). sum ulr:List(Nat)._RFAgent_selectUnlinkedReplicas(ulr) .((ulr!=[])->_RFAgent_removeUnlinkedReplicas(ulr,Deleted)<>internal) .RFAgent; %---------------------- StorageManagerHandler = StorageManagerHandler_setRequest. _StorageManagerHandler_createTask(tNew). _StorageManagerHandler_insertReplicaInfo([New,New]). _StorageManagerHandler_insertTaskReplicaInfo([p(0, 0, true), p(0, 1, true)]). sum repStates:List(CacheReplicas)._StorageManagerHandler_getReplicaStates([0,1],repStates). (Failed in repStates)->_StorageManagerHandler_updateTaskStatus([0],tFailed) <> (allStaged(repStates))->_StorageManagerHandler_updateTaskStatus([0],tDone) <> internal; % should be added: select all replica states, if all of them are Staged, then move to tDone state, else internal % if some CR is Failed, move to tFailed %---------------------- init hide ({internal}, allow({internal,state,stateCR,RPAgent_selectTasks,RPAgent_prepareNewReplicasT,SRAgent_selectTasks,SRAgent_issuePrestageRequestsT, RPAgent_selectCacheReplicas,RPAgent_prepareNewReplicas,SRAgent_selectCacheReplicas,SRAgent_issuePrestageRequests, RPAgent_selectTaskReplicas,SRAgent_selectTaskReplicas, SMAgent_selectTasks,SMAgent_monitorStageRequestsT,SMAgent_monitorStageRequests,SMAgent_selectCacheReplicas, SMAgent_selectTaskReplicas, RFAgent_selectTasks, RFAgent_clearFailedTasksT, RFAgent_callbackStagedTasksT, RFAgent_removeLinks,RFAgent_selectUnlinkedReplicas,RFAgent_removeUnlinkedReplicas, StorageManagerHandler_setRequest, StorageManagerHandler_createTask, StorageManagerHandler_insertReplicaInfo, StorageManagerHandler_insertTaskReplicaInfo, StorageManagerHandler_getReplicaStates, StorageManagerHandler_updateTaskStatus }, comm({ RPAgent_selectTasks_|_RPAgent_selectTasks-> RPAgent_selectTasks, RPAgent_prepareNewReplicasT_|_RPAgent_prepareNewReplicasT-> RPAgent_prepareNewReplicasT, SRAgent_selectTasks_|_SRAgent_selectTasks-> SRAgent_selectTasks, SRAgent_issuePrestageRequestsT_|_SRAgent_issuePrestageRequestsT-> SRAgent_issuePrestageRequestsT, RPAgent_selectTaskReplicas_|_RPAgent_selectTaskReplicas-> RPAgent_selectTaskReplicas, SRAgent_selectTaskReplicas_|_SRAgent_selectTaskReplicas-> SRAgent_selectTaskReplicas, RPAgent_selectCacheReplicas_|_RPAgent_selectCacheReplicas-> RPAgent_selectCacheReplicas, RPAgent_prepareNewReplicas_|_RPAgent_prepareNewReplicas-> RPAgent_prepareNewReplicas, SRAgent_selectCacheReplicas_|_SRAgent_selectCacheReplicas-> SRAgent_selectCacheReplicas, SRAgent_issuePrestageRequests_|_SRAgent_issuePrestageRequests-> SRAgent_issuePrestageRequests, SMAgent_selectTasks_|_SMAgent_selectTasks-> SMAgent_selectTasks, SMAgent_monitorStageRequestsT_|_SMAgent_monitorStageRequestsT-> SMAgent_monitorStageRequestsT, SMAgent_selectTaskReplicas_|_SMAgent_selectTaskReplicas-> SMAgent_selectTaskReplicas, SMAgent_selectCacheReplicas_|_SMAgent_selectCacheReplicas-> SMAgent_selectCacheReplicas, SMAgent_monitorStageRequests_|_SMAgent_monitorStageRequests-> SMAgent_monitorStageRequests, RFAgent_selectTasks_|_RFAgent_selectTasks-> RFAgent_selectTasks, RFAgent_clearFailedTasksT_|_RFAgent_clearFailedTasksT-> RFAgent_clearFailedTasksT, RFAgent_callbackStagedTasksT_|_RFAgent_callbackStagedTasksT-> RFAgent_callbackStagedTasksT, RFAgent_selectUnlinkedReplicas_|_RFAgent_selectUnlinkedReplicas-> RFAgent_selectUnlinkedReplicas, RFAgent_removeLinks_|_RFAgent_removeLinks-> RFAgent_removeLinks, RFAgent_removeUnlinkedReplicas_|_RFAgent_removeUnlinkedReplicas-> RFAgent_removeUnlinkedReplicas, StorageManagerHandler_createTask_|_StorageManagerHandler_createTask-> StorageManagerHandler_createTask, StorageManagerHandler_insertReplicaInfo_|_StorageManagerHandler_insertReplicaInfo-> StorageManagerHandler_insertReplicaInfo, StorageManagerHandler_insertTaskReplicaInfo_|_StorageManagerHandler_insertTaskReplicaInfo-> StorageManagerHandler_insertTaskReplicaInfo, StorageManagerHandler_getReplicaStates_|_StorageManagerHandler_getReplicaStates-> StorageManagerHandler_getReplicaStates, StorageManagerHandler_updateTaskStatus_|_StorageManagerHandler_updateTaskStatus-> StorageManagerHandler_updateTaskStatus }, StorageManagerHandler || Tasksproc([]) || CacheReplicasproc([]) || RPAgent || SRAgent || SMAgent || RFAgent || TaskReplicasproc([]) ))); mcrl2-201409.0/examples/industrial/DIRAC/WMS.mcrl2000770 001750 001750 00000073167 12370120076 021601 0ustar00outisoutis000000 000000 % Specification of the Workload Management System of the DIRAC Community Grid Solution [1] % for the LHCb [2] experiment at CERN. This subsystem is the backbone of DIRAC, managing % the lifecycle of all jobs submitted to the Grid resources. % A series of agents (modeled as recursive processes) observe and update the states of the % centralized storage entity (Job). The shared storage is modeled as a process % continuously listening and responding to requests from other processes (agents). % % [1] A. Tsaregorodtsev et al. ""DIRAC: A community grid solution,"" in Proc. Computing in % High Energy Physics, 2007 % % [2] Large Hadron Collider beauty experiment. % [Online] http://lhcb-public.web.cern.ch/lhcb-public % % % Authors: Daniela Remenska, Tim Willemse % October 2011 % % IMPORTANT: the action "state" is present only for the purpose of verification and is not % in any way part of the behaviour of the system; % % The following commands will generate a state space: % mcrl22lps WMS.mcrl2 WMS.lps % lps2lts -vrjittyc WMS.lps % State space statistics: 160148696 states % % NOTE: The above method takes roughly 50 hours (December 2011); % lps-reach with chaining and/or saturation of the LTSmin toolset is able to take % advantage of the asynchronous nature of the state space, allowing the tool to % exhaustively explore the state space symbolically in approx. 10 seconds. sort Status = struct Stalled?is_stalled | Running?is_running | Received?is_received | Failed?is_failed | Rescheduled?is_rescheduled | Done?is_done | Matched?is_matched | Checking?is_checking | Waiting?is_waiting | Staging?is_staging | Deleted?is_deleted | Removed?is_removed | Killed?is_killed | Completed?is_completed; sort MinorStatus = struct PilotNotRunning?is_pilotNotRunning | StallingMoreThanXSec?is_stallingMoreThanXSec | ErrorMsg?is_errorMsg | JobSanity?is_jobSanity | JobAccepted?is_jobAccepted | JobScheduling?is_jobScheduling | InputData?is_inputData | TaskQueue?is_taskQueue | Application?is_application | InstallingSoftware?is_installingSoftware | StagingRequestSent?is_stagingRequestSent | PilotAgentSubmission?is_pilotAgentSubmission | Assigned?is_assigned | JDLProblem?is_JDLProblem | JobReceivedByAgent?is_jobReceivedByAgent | MaxReschedulings?is_maxReschedulings | JobRescheduled?is_jobRescheduled | SubmittedToCE?is_submittedToCE | JobInitialization?is_jobInitialization | DownloadingInputSandbox?is_downloadingInputSandbox | FailedDownloadingInputSandbox?is_failedDownloadingInputSandbox | InputDataResolution?is_inputDataResolution | ExceptionDuringExecution?is_exceptionDuringExecution | WatchdogStalled?is_watchdogStalled | ApplicationSuccess?is_applicationSuccess | ApplicationErrors?is_applicationErrors | Exception?is_exception | FailoverRequestFailed?is_failoverRequestFailed | ResolvingOutputSandbox?is_resolvingOutputSandbox | UploadingOutputSandbox?is_uploadingOutputSandbox | OutputSandboxUploaded?is_outputSandboxUploaded | UploadingOutputData?is_uploadingOutputData | OutputDataUploaded?is_outputDataUploaded | PendingRequests?is_pendingRequests | ExecutionComplete?is_executionComplete | RequestsDone?is_requestsDone | MarkedForTermination?is_markedForTermination | StagingInputFilesFailed?is_stagingInputFilesFailed | CheckingAccounting? is_checkingAccounting ; sort Job = struct jobstatus(js:Status,ms:MinorStatus); sort WrapperState = struct StartWrapper?is_startWrapper | Fault?is_fault | InitializeOK?is_initializeOK | InputSandboxOK?is_inputSandboxOK | ResolveInputDataOK?is_resolveInputDataOK | ExecuteOK?is_executeOK | CompletedOK?is_completedOK | OutputSandboxOK?is_outputSandboxOK | OutputDataOK?is_outputDataOK | FinalizeOK?is_finalizeOK; %------------------------------------ % jobs-to-ids mapping, based on selection for the major status % example j2id([jobstatus(Checking,InputData),jobstatus(Matched,Assigned),jobstatus(Checking,JobSanity)],Checking) -> [0,2] map j2id:List(Job)#Status->List(Nat); map j2id':List(Job)#Status#Nat->List(Nat); var jobs,l:List(Job); s:Status; n:Nat; a:Job; eqn j2id(jobs,s) = j2id'(jobs,s,0); j2id'([],s,n) = []; js(a) == s -> j2id'(a|>l,s,n) = n|>j2id'(l,s,n+1); js(a) != s -> j2id'(a|>l,s,n) = j2id'(l,s,n+1); %------------------------------------ % jobs-to-ids mapping, based on selection for the major status AND minor status % example j2id2([jobstatus(Checking,InputData),jobstatus(Matched,Assigned),jobstatus(Checking,JobSanity)],Checking,JobSanity) -> [2] map j2id2:List(Job)#Job->List(Nat); map j2id2':List(Job)#Job#Nat->List(Nat); var jobs,l:List(Job); j,a:Job; n:Nat; eqn j2id2(jobs,j) = j2id2'(jobs,j,0); j2id2'([],j,n) = []; a == j -> j2id2'(a|>l,j,n) = n|>j2id2'(l,j,n+1); a != j -> j2id2'(a|>l,j,n) = j2id2'(l,j,n+1); %------------------------------------ %ids-to-jobs mapping, based on a list of IDs and major status %example id2j2([0,2],[jobstatus(Checking,InputData),jobstatus(Matched,Assigned),jobstatus(Checking,JobSanity)],Failed)-> %[jobstatus(Failed,InputData),jobstatus(Matched,Assigned),jobstatus(Failed,InputData)] map id2j2:List(Nat)#List(Job)#Status->List(Job); map id2j2':List(Nat)#List(Job)#Status#Nat->List(Job); var listIDs:List(Nat); jobs,l:List(Job); n:Nat; a:Job; st:Status; eqn id2j2(listIDs,jobs,st) = id2j2'(listIDs,jobs,st,0); id2j2'(listIDs,[],st,n) = []; n in listIDs -> id2j2'(listIDs,a|>l,st,n) = jobstatus(st,ms(a))|>id2j2'(listIDs,l,st,n+1); !(n in listIDs) -> id2j2'(listIDs,a|>l,st,n) = a|>id2j2'(listIDs,l,st,n+1); %------------------------------------ %ids-to-jobs mapping, based on a list of IDs and MINOR status %example id2j3([0,2],[jobstatus(Checking,InputData),jobstatus(Matched,Assigned),jobstatus(Checking,JobSanity)],RequestsDone)-> %[jobstatus(Failed,RequestsDone),jobstatus(Matched,Assigned),jobstatus(Failed,RequestsDone)] map id2j3:List(Nat)#List(Job)#MinorStatus->List(Job); map id2j3':List(Nat)#List(Job)#MinorStatus#Nat->List(Job); var listIDs:List(Nat); jobs,l:List(Job); n:Nat; a:Job; mst:MinorStatus; eqn id2j3(listIDs,jobs,mst) = id2j3'(listIDs,jobs,mst,0); id2j3'(listIDs,[],mst,n) = []; n in listIDs -> id2j3'(listIDs,a|>l,mst,n) = jobstatus(js(a),mst)|>id2j3'(listIDs,l,mst,n+1); !(n in listIDs) -> id2j3'(listIDs,a|>l,mst,n) = a|>id2j3'(listIDs,l,mst,n+1); %------------------------------------ %ids-to-jobs mapping, based on a list of IDs, major status AND minor status update %example id2j([0,2],[jobstatus(Checking,InputData),jobstatus(Matched,Assigned),jobstatus(Checking,JobSanity)],jobstatus(Failed,ErrorMsg))-> %[jobstatus(Failed,ErrorMsg),jobstatus(Matched,Assigned),jobstatus(Failed,ErrorMsg)] map id2j:List(Nat)#List(Job)#Job->List(Job); map id2j':List(Nat)#List(Job)#Job#Nat->List(Job); var listIDs:List(Nat); jobs,l:List(Job); n:Nat; a,j:Job; eqn id2j(listIDs,jobs,j) = id2j'(listIDs,jobs,j,0); id2j'(listIDs,[],j,n) = []; n in listIDs -> id2j'(listIDs,a|>l,j,n) = j|>id2j'(listIDs,l,j,n+1); !(n in listIDs) -> id2j'(listIDs,a|>l,j,n) = a|>id2j'(listIDs,l,j,n+1); %------------------------------------ act internal; act JobPathAgent_selectJobs_,_JobPathAgent_selectJobs,JobPathAgent_selectJobs:List(Nat)#Status; act JobPathAgent_checkJob_,_JobPathAgent_checkJob,JobPathAgent_checkJob:List(Nat)#Job; act JobPathAgent_setNextOptimizer_,_JobPathAgent_setNextOptimizer,JobPathAgent_setNextOptimizer:List(Nat)#Job; act JobSanityAgent_selectJobs_,_JobSanityAgent_selectJobs,JobSanityAgent_selectJobs:List(Nat)#Job; act JobSanityAgent_checkInputData_,_JobSanityAgent_checkInputData,JobSanityAgent_checkInputData:List(Nat)#Job; act JobSanityAgent_checkInputSandbox_,_JobSanityAgent_checkInputSandbox,JobSanityAgent_checkInputSandbox:List(Nat)#Job; act JobSanityAgent_setNextOptimizer_,_JobSanityAgent_setNextOptimizer,JobSanityAgent_setNextOptimizer:List(Nat)#Job; act InputDataAgent_selectJobs_,_InputDataAgent_selectJobs,InputDataAgent_selectJobs:List(Nat)#Job; act InputDataAgent_checkJob_,_InputDataAgent_checkJob,InputDataAgent_checkJob:List(Nat)#Job; act InputDataAgent_setNextOptimizer_,_InputDataAgent_setNextOptimizer,InputDataAgent_setNextOptimizer:List(Nat)#Job; act JobSchedulingAgent_selectJobs_,_JobSchedulingAgent_selectJobs,JobSchedulingAgent_selectJobs:List(Nat)#Job; act JobSchedulingAgent_checkJob_,_JobSchedulingAgent_checkJob,JobSchedulingAgent_checkJob:List(Nat)#Job; act JobSchedulingAgent_sendToTaskQueue_,_JobSchedulingAgent_sendToTaskQueue,JobSchedulingAgent_sendToTaskQueue:List(Nat)#Job; act JobSchedulingAgent_setStagingRequest_,_JobSchedulingAgent_setStagingRequest,JobSchedulingAgent_setStagingRequest:List(Nat)#Job; act TaskQueueAgent_selectJobs_,_TaskQueueAgent_selectJobs,TaskQueueAgent_selectJobs:List(Nat)#Job; act TaskQueueAgent_checkJob_,_TaskQueueAgent_checkJob,TaskQueueAgent_checkJob:List(Nat)#Job; act TaskQueueAgent_insertJobInQueue_,_TaskQueueAgent_insertJobInQueue,TaskQueueAgent_insertJobInQueue:List(Nat)#Job; act StalledJobAgent_selectJobs_,_StalledJobAgent_selectJobs,StalledJobAgent_selectJobs:List(Nat)#Status; act StalledJobAgent_markStalledJobs_,_StalledJobAgent_markStalledJobs,StalledJobAgent_markStalledJobs:List(Nat)#Status; act StalledJobAgent_failStalledJobs_,_StalledJobAgent_failStalledJobs,StalledJobAgent_failStalledJobs:List(Nat)#Job; act JobCleaningAgent_selectJobs_,_JobCleaningAgent_selectJobs,JobCleaningAgent_selectJobs:List(Nat)#Status; act JobCleaningAgent_removeJobs_,_JobCleaningAgent_removeJobs,JobCleaningAgent_removeJobs:List(Nat)#Status; act RequestAgentMixIn_selectJobs_,_RequestAgentMixIn_selectJobs,RequestAgentMixIn_selectJobs:List(Nat)#Job; act RequestAgentMixIn_setJobStatus_,_RequestAgentMixIn_setJobStatus,RequestAgentMixIn_setJobStatus:List(Nat)#Job; act RequestAgentMixIn_setMinorStatus_,_RequestAgentMixIn_setMinorStatus,RequestAgentMixIn_setMinorStatus:List(Nat)#MinorStatus; act JobAgent_selectJobs_,_JobAgent_selectJobs,JobAgent_selectJobs:List(Nat)#Status; act JobAgent_matchJobs_,_JobAgent_matchJobs,JobAgent_matchJobs:List(Nat)#Job; act JobAgent_updateStatus_,_JobAgent_updateStatus,JobAgent_updateStatus:List(Nat)#Job; act JobAgent_rescheduleJob_,_JobAgent_rescheduleJob,JobAgent_rescheduleJob:List(Nat)#Job; act JobAgent_setupProxy_,_JobAgent_setupProxy,JobAgent_setupProxy:List(Nat)#Job; act JobAgent_checkInstallSoftware_,_JobAgent_checkInstallSoftware,JobAgent_checkInstallSoftware:List(Nat)#Job; act JobAgent_submitJob_,_JobAgent_submitJob,JobAgent_submitJob:List(Nat)#Job; act JobWrapper_initialize_,_JobWrapper_initialize,JobWrapper_initialize:List(Nat)#Job; act JobWrapper_rescheduleJob_,_JobWrapper_rescheduleJob,JobWrapper_rescheduleJob:List(Nat)#Job; act JobWrapper_transferInputSandbox_,_JobWrapper_transferInputSandbox,JobWrapper_transferInputSandbox:List(Nat)#Job; act JobWrapper_resolveInputData_,_JobWrapper_resolveInputData,JobWrapper_resolveInputData:List(Nat)#Job; act JobWrapper_execute_,_JobWrapper_execute,JobWrapper_execute:List(Nat)#Job; act JobWrapper_processJobOutputs_,_JobWrapper_processJobOutputs,JobWrapper_processJobOutputs:List(Nat)#Job; act JobWrapper_finalize_,_JobWrapper_finalize,JobWrapper_finalize:List(Nat)#Job; act _DIRAC_API_delete,DIRAC_API_delete_,DIRAC_API_delete:Nat#Job; act _DIRAC_API_reschedule,DIRAC_API_reschedule_,DIRAC_API_reschedule:Nat#Job; act _DIRAC_API_kill,DIRAC_API_kill_,DIRAC_API_kill:Nat#Job; act getRandomJob_,_getRandomJob,getRandomJob:Nat; act StagerSystem_selectJobs_,_StagerSystem_selectJobs,StagerSystem_selectJobs:List(Nat)#Status; act StagerSystem_updateJobFromStager_,_StagerSystem_updateJobFromStager,StagerSystem_updateJobFromStager:List(Nat)#Job; act JobManager_submitJob_,_JobManager_submitJob, JobManager_submitJob:Job; act state:List(Job); act runApp; %----------------------Jobs memory simulation via process proc Jobsproc(s:List(Job)) = sum j:Job. JobManager_submitJob_(j).Jobsproc(s<|j) + sum st:Status. JobPathAgent_selectJobs_(j2id(s,st),st).Jobsproc(s) + sum l:List(Nat),j:Job. JobPathAgent_checkJob_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobPathAgent_setNextOptimizer_(l,j).Jobsproc(id2j(l,s,j)) + sum j:Job. JobSanityAgent_selectJobs_(j2id2(s,j),j).Jobsproc(s) + sum l:List(Nat),j:Job. JobSanityAgent_checkInputData_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobSanityAgent_checkInputSandbox_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobSanityAgent_setNextOptimizer_(l,j).Jobsproc(id2j(l,s,j)) + sum j:Job. InputDataAgent_selectJobs_(j2id2(s,j),j).Jobsproc(s) + sum l:List(Nat),j:Job. InputDataAgent_checkJob_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. InputDataAgent_setNextOptimizer_(l,j).Jobsproc(id2j(l,s,j)) + sum j:Job. JobSchedulingAgent_selectJobs_(j2id2(s,j),j).Jobsproc(s) + sum l:List(Nat),j:Job. JobSchedulingAgent_checkJob_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobSchedulingAgent_sendToTaskQueue_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobSchedulingAgent_setStagingRequest_(l,j).Jobsproc(id2j(l,s,j)) + sum j:Job. TaskQueueAgent_selectJobs_(j2id2(s,j),j).Jobsproc(s) + sum l:List(Nat),j:Job. TaskQueueAgent_checkJob_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. TaskQueueAgent_insertJobInQueue_(l,j).Jobsproc(id2j(l,s,j)) + sum st:Status. StalledJobAgent_selectJobs_(j2id(s,st),st).Jobsproc(s) + sum l:List(Nat),st:Status. StalledJobAgent_markStalledJobs_(l,st).Jobsproc(id2j2(l,s,st)) + sum l:List(Nat),j:Job. StalledJobAgent_failStalledJobs_(l,j).Jobsproc(id2j(l,s,j)) + sum st:Status. JobCleaningAgent_selectJobs_(j2id(s,st),st).Jobsproc(s) + sum l:List(Nat),st:Status. JobCleaningAgent_removeJobs_(l,st).Jobsproc(id2j2(l,s,st)) + sum j:Job. RequestAgentMixIn_selectJobs_(j2id2(s,j),j).Jobsproc(s) + sum l:List(Nat),j:Job. RequestAgentMixIn_setJobStatus_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),mst:MinorStatus. RequestAgentMixIn_setMinorStatus_(l,mst).Jobsproc(id2j3(l,s,mst)) + sum st:Status. JobAgent_selectJobs_(j2id(s,st),st).Jobsproc(s) + sum l:List(Nat),j:Job. JobAgent_matchJobs_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobAgent_updateStatus_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobAgent_rescheduleJob_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobAgent_submitJob_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobWrapper_initialize_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobWrapper_rescheduleJob_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobAgent_setupProxy_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobAgent_checkInstallSoftware_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobWrapper_transferInputSandbox_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobWrapper_resolveInputData_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobWrapper_execute_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobWrapper_processJobOutputs_(l,j).Jobsproc(id2j(l,s,j)) + sum l:List(Nat),j:Job. JobWrapper_finalize_(l,j).Jobsproc(id2j(l,s,j)) + sum i:Nat,j:Job. DIRAC_API_delete_(i,j).Jobsproc(id2j([i],s,j)) + sum i:Nat,j:Job. DIRAC_API_kill_(i,j).Jobsproc(id2j([i],s,j)) + sum i:Nat,j:Job. DIRAC_API_reschedule_(i,j).Jobsproc(id2j([i],s,j)) + sum st:Status. StagerSystem_selectJobs_(j2id(s,st),st).Jobsproc(s) + sum l:List(Nat),j:Job. StagerSystem_updateJobFromStager_(l,j).Jobsproc(id2j(l,s,j)) + %getRandomJob_(0).Jobsproc(s) + getRandomJob_(0).Jobsproc(s) + state(s).Jobsproc(s); proc JobPathAgent = sum cc:List(Nat). _JobPathAgent_selectJobs(cc,Received). ( (cc!=[])-> ( _JobPathAgent_checkJob(cc,jobstatus(Failed,ErrorMsg)) + _JobPathAgent_setNextOptimizer(cc,jobstatus(Checking,JobSanity)) ) <> internal ) .JobPathAgent; %---------------------- proc JobSanityAgent = sum cc:List(Nat). _JobSanityAgent_selectJobs(cc,jobstatus(Checking,JobSanity)). ( (cc!=[])-> ( _JobSanityAgent_checkInputData(cc,jobstatus(Failed,ErrorMsg)) + _JobSanityAgent_checkInputSandbox(cc,jobstatus(Failed,ErrorMsg)) + _JobSanityAgent_setNextOptimizer(cc,jobstatus(Checking,InputData)) + _JobSanityAgent_setNextOptimizer(cc,jobstatus(Checking,JobScheduling)) ) <> internal ) .JobSanityAgent; %---------------------- proc InputDataAgent = sum cc:List(Nat). _InputDataAgent_selectJobs(cc,jobstatus(Checking,InputData)). ( (cc!=[])-> ( _InputDataAgent_checkJob(cc,jobstatus(Failed,ErrorMsg)) + _InputDataAgent_setNextOptimizer(cc,jobstatus(Checking,JobScheduling)) ) <> internal ) .InputDataAgent; %---------------------- proc JobSchedulingAgent = sum cc:List(Nat). _JobSchedulingAgent_selectJobs(cc,jobstatus(Checking,JobScheduling)). ( (cc!=[])-> ( _JobSchedulingAgent_checkJob(cc,jobstatus(Failed,ErrorMsg)) + _JobSchedulingAgent_setStagingRequest(cc,jobstatus(Staging,StagingRequestSent)) + _JobSchedulingAgent_setStagingRequest(cc,jobstatus(Failed,ErrorMsg)) + _JobSchedulingAgent_sendToTaskQueue(cc,jobstatus(Checking,TaskQueue)) ) <> internal ) .JobSchedulingAgent; %---------------------- proc TaskQueueAgent = sum cc:List(Nat). _TaskQueueAgent_selectJobs(cc,jobstatus(Checking,TaskQueue)). ( (cc!=[])-> ( _TaskQueueAgent_checkJob(cc,jobstatus(Failed,ErrorMsg)) + _TaskQueueAgent_insertJobInQueue(cc,jobstatus(Waiting,PilotAgentSubmission)) ) <> internal ) .TaskQueueAgent; %---------------------- proc StalledJobAgent = sum cc:List(Nat). _StalledJobAgent_selectJobs(cc,Running). ( (cc!=[])-> (_StalledJobAgent_markStalledJobs(cc,Stalled) + internal) <> internal ). sum cc:List(Nat). _StalledJobAgent_selectJobs(cc,Stalled). ( (cc!=[])-> ( _StalledJobAgent_failStalledJobs(cc,jobstatus(Failed,PilotNotRunning)) + _StalledJobAgent_failStalledJobs(cc,jobstatus(Failed,StallingMoreThanXSec)) ) <> internal ) .StalledJobAgent; %---------------------- proc JobCleaningAgent = sum cc:List(Nat). _JobCleaningAgent_selectJobs(cc,Deleted). ( (cc!=[])->_JobCleaningAgent_removeJobs(cc,Removed) <> internal ). sum cc:List(Nat). _JobCleaningAgent_selectJobs(cc,Done). ( (cc!=[])->_JobCleaningAgent_removeJobs(cc,Removed) <> internal ). sum cc:List(Nat). _JobCleaningAgent_selectJobs(cc,Killed). ( (cc!=[])->_JobCleaningAgent_removeJobs(cc,Removed) <> internal ). sum cc:List(Nat). _JobCleaningAgent_selectJobs(cc,Failed). ( (cc!=[])->_JobCleaningAgent_removeJobs(cc,Removed)<> internal ) .JobCleaningAgent; %---------------------- proc RequestAgentMixIn = sum cc:List(Nat). _RequestAgentMixIn_selectJobs(cc,jobstatus(Completed,PendingRequests)). ( (cc!=[])-> _RequestAgentMixIn_setJobStatus(cc,jobstatus(Done,RequestsDone)) <> internal ). sum cc:List(Nat). _RequestAgentMixIn_selectJobs(cc,jobstatus(Failed,PendingRequests)). ( (cc!=[])-> _RequestAgentMixIn_setMinorStatus(cc,RequestsDone) <> internal ) .RequestAgentMixIn; %---------------------- JobAgent = sum cc:List(Nat). _JobAgent_selectJobs(cc,Waiting). ( (cc!=[])-> _JobAgent_matchJobs(cc,jobstatus(Matched,Assigned)). ( _JobAgent_updateStatus(cc,jobstatus(Failed,JDLProblem)).JobAgent + _JobAgent_updateStatus(cc,jobstatus(Matched,JobReceivedByAgent)). ( % setupProxy fails _JobAgent_setupProxy(cc,jobstatus(Rescheduled,JobRescheduled)).JobAgent + _JobAgent_setupProxy(cc,jobstatus(Failed,MaxReschedulings)).JobAgent + % or it doesn't internal ). ( % check install software fails _JobAgent_checkInstallSoftware(cc,jobstatus(Rescheduled,JobRescheduled)).JobAgent + _JobAgent_checkInstallSoftware(cc,jobstatus(Failed,MaxReschedulings)).JobAgent + % or it doesn't _JobAgent_checkInstallSoftware(cc,jobstatus(Matched,InstallingSoftware)) ). ( _JobAgent_submitJob(cc,jobstatus(Matched,SubmittedToCE)).JobWrapper(cc,StartWrapper) + _JobAgent_submitJob(cc,jobstatus(Failed,MaxReschedulings)).JobAgent + _JobAgent_submitJob(cc,jobstatus(Rescheduled,JobRescheduled)).JobAgent ) ) <> internal ) .JobAgent; %---------------------- proc JobWrapper(cc:List(Nat),state:WrapperState) = is_startWrapper(state)-> ( _JobWrapper_initialize(cc,jobstatus(Running,JobInitialization)). ( _JobWrapper_initialize(cc,jobstatus(Received,JobRescheduled)).JobWrapper(cc,Fault) + _JobWrapper_initialize(cc,jobstatus(Failed,MaxReschedulings)).JobWrapper(cc,Fault) + JobWrapper(cc,InitializeOK) ) ) + is_initializeOK(state)-> ( _JobWrapper_transferInputSandbox(cc,jobstatus(Running,DownloadingInputSandbox)). ( _JobWrapper_transferInputSandbox(cc,jobstatus(Received,JobRescheduled)).JobWrapper(cc,Fault) + _JobWrapper_transferInputSandbox(cc,jobstatus(Failed,MaxReschedulings)).JobWrapper(cc,Fault) + JobWrapper(cc,InputSandboxOK) ) ) + is_inputSandboxOK(state)-> ( _JobWrapper_resolveInputData(cc,jobstatus(Running,InputDataResolution)). ( _JobWrapper_resolveInputData(cc,jobstatus(Received,JobRescheduled)).JobWrapper(cc,Fault) + _JobWrapper_resolveInputData(cc,jobstatus(Failed,MaxReschedulings)).JobWrapper(cc,Fault) + JobWrapper(cc,ResolveInputDataOK) ) ) + is_resolveInputDataOK(state)-> ( _JobWrapper_execute(cc,jobstatus(Running,Application)). ( AppPayload.JobWrapper(cc,ExecuteOK) + _JobWrapper_execute(cc,jobstatus(Failed,ExceptionDuringExecution)).JobWrapper(cc,Fault) ) ) + % creates an execution thread % passes the execution thread to a Watchdog instance (TBW) is_executeOK(state)-> ( _JobWrapper_execute(cc,jobstatus(Completed,ApplicationSuccess)).JobWrapper(cc,CompletedOK) + _JobWrapper_execute(cc,jobstatus(Completed,ApplicationErrors)).JobWrapper(cc,CompletedOK) + _JobWrapper_execute(cc,jobstatus(Failed,WatchdogStalled)).JobWrapper(cc,Fault) ) + is_completedOK(state)-> ( _JobWrapper_processJobOutputs(cc,jobstatus(Completed,UploadingOutputSandbox)). _JobWrapper_processJobOutputs(cc,jobstatus(Completed,OutputSandboxUploaded)).JobWrapper(cc,OutputSandboxOK) + _JobWrapper_processJobOutputs(cc,jobstatus(Failed,ResolvingOutputSandbox)).JobWrapper(cc,Fault) ) + is_outputSandboxOK(state)-> ( _JobWrapper_processJobOutputs(cc,jobstatus(Completed,UploadingOutputData)). _JobWrapper_processJobOutputs(cc,jobstatus(Completed,OutputDataUploaded)).JobWrapper(cc,OutputDataOK) + _JobWrapper_processJobOutputs(cc,jobstatus(Failed,UploadingOutputData)).JobWrapper(cc,Fault) ) + is_outputDataOK(state)-> ( _JobWrapper_finalize(cc,jobstatus(Done,ExecutionComplete)) + _JobWrapper_finalize(cc,jobstatus(Failed,PendingRequests)) + _JobWrapper_finalize(cc,jobstatus(Completed,PendingRequests)) ).JobWrapper(cc,FinalizeOK) ; %---------------------- proc AppPayload = runApp; proc DIRAC_API = sum job:Nat. _getRandomJob(job). (_DIRAC_API_delete(job,jobstatus(Deleted,CheckingAccounting)) + _DIRAC_API_reschedule(job,jobstatus(Received,JobRescheduled)) + _DIRAC_API_kill(job,jobstatus(Killed,MarkedForTermination))) .DIRAC_API; %---------------------- proc JobManager = _JobManager_submitJob(jobstatus(Received,JobAccepted)); %could add more submissions._JobManager_submitJob(jobstatus(Failed,FailedDownloadingInputSandbox)); %---------------------- proc StagerSystem = sum cc:List(Nat). _StagerSystem_selectJobs(cc,Staging). ( (cc!=[])-> ( _StagerSystem_updateJobFromStager(cc,jobstatus(Failed,StagingInputFilesFailed)) + _StagerSystem_updateJobFromStager(cc,jobstatus(Checking,JobScheduling)) ) <> internal ) .StagerSystem; %---------------------- % Generic monitor for formulae of the form [true*. state(l1). true*. state(l2)]false % By default not included in the 'init' section act found: List(Job)#List(Job); act monitor: List(Job); proc Monitor(l1,l2:List(Job), b:Bool) = tau.Monitor(l1,l2,b) % use mCRL2's facility to have tau synchronise with any action +(!b -> (sum l:List(Job). (l == l1)-> (monitor(l). Monitor(l1,l2,true)) <> (monitor(l). Monitor(l1,l2,b) )) <> (sum l:List(Job). (l == l2)-> (monitor(l). found(l1,l2). delta) <> monitor(l). Monitor(l1,l2,b) )); %---------------------- init hide ({internal}, allow({internal,state,getRandomJob,found, JobPathAgent_selectJobs,JobPathAgent_checkJob,JobPathAgent_setNextOptimizer, JobSanityAgent_selectJobs,JobSanityAgent_checkInputData,JobSanityAgent_checkInputSandbox,JobSanityAgent_setNextOptimizer, InputDataAgent_selectJobs,InputDataAgent_checkJob,InputDataAgent_setNextOptimizer, JobSchedulingAgent_selectJobs,JobSchedulingAgent_checkJob,JobSchedulingAgent_sendToTaskQueue,JobSchedulingAgent_setStagingRequest, TaskQueueAgent_selectJobs,TaskQueueAgent_checkJob,TaskQueueAgent_insertJobInQueue, StalledJobAgent_selectJobs,StalledJobAgent_markStalledJobs,StalledJobAgent_failStalledJobs, JobCleaningAgent_selectJobs,JobCleaningAgent_removeJobs, RequestAgentMixIn_selectJobs,RequestAgentMixIn_setJobStatus,RequestAgentMixIn_setMinorStatus, JobAgent_selectJobs,JobAgent_matchJobs,JobAgent_updateStatus,JobAgent_rescheduleJob,JobAgent_setupProxy,JobAgent_checkInstallSoftware, JobAgent_submitJob, JobWrapper_initialize,JobWrapper_rescheduleJob,JobWrapper_transferInputSandbox,JobWrapper_resolveInputData,JobWrapper_execute,JobWrapper_processJobOutputs,JobWrapper_finalize, DIRAC_API_delete,DIRAC_API_reschedule,DIRAC_API_kill, StagerSystem_selectJobs,StagerSystem_updateJobFromStager, JobManager_submitJob, runApp }, comm({ state|monitor -> state, JobPathAgent_selectJobs_|_JobPathAgent_selectJobs-> JobPathAgent_selectJobs, JobPathAgent_checkJob_|_JobPathAgent_checkJob-> JobPathAgent_checkJob, JobPathAgent_setNextOptimizer_|_JobPathAgent_setNextOptimizer-> JobPathAgent_setNextOptimizer, JobSanityAgent_selectJobs_|_JobSanityAgent_selectJobs-> JobSanityAgent_selectJobs, JobSanityAgent_checkInputData_|_JobSanityAgent_checkInputData-> JobSanityAgent_checkInputData, JobSanityAgent_checkInputSandbox_|_JobSanityAgent_checkInputSandbox-> JobSanityAgent_checkInputSandbox, JobSanityAgent_setNextOptimizer_|_JobSanityAgent_setNextOptimizer-> JobSanityAgent_setNextOptimizer, InputDataAgent_selectJobs_|_InputDataAgent_selectJobs-> InputDataAgent_selectJobs, InputDataAgent_checkJob_|_InputDataAgent_checkJob-> InputDataAgent_checkJob, InputDataAgent_setNextOptimizer_|_InputDataAgent_setNextOptimizer-> InputDataAgent_setNextOptimizer, JobSchedulingAgent_selectJobs_|_JobSchedulingAgent_selectJobs-> JobSchedulingAgent_selectJobs, JobSchedulingAgent_checkJob_|_JobSchedulingAgent_checkJob-> JobSchedulingAgent_checkJob, JobSchedulingAgent_sendToTaskQueue_|_JobSchedulingAgent_sendToTaskQueue-> JobSchedulingAgent_sendToTaskQueue, JobSchedulingAgent_setStagingRequest_|_JobSchedulingAgent_setStagingRequest-> JobSchedulingAgent_setStagingRequest, TaskQueueAgent_selectJobs_|_TaskQueueAgent_selectJobs-> TaskQueueAgent_selectJobs, TaskQueueAgent_checkJob_|_TaskQueueAgent_checkJob-> TaskQueueAgent_checkJob, TaskQueueAgent_insertJobInQueue_|_TaskQueueAgent_insertJobInQueue-> TaskQueueAgent_insertJobInQueue, StalledJobAgent_selectJobs_|_StalledJobAgent_selectJobs-> StalledJobAgent_selectJobs, StalledJobAgent_markStalledJobs_|_StalledJobAgent_markStalledJobs-> StalledJobAgent_markStalledJobs, StalledJobAgent_failStalledJobs_|_StalledJobAgent_failStalledJobs-> StalledJobAgent_failStalledJobs, JobCleaningAgent_selectJobs_|_JobCleaningAgent_selectJobs-> JobCleaningAgent_selectJobs, JobCleaningAgent_removeJobs_|_JobCleaningAgent_removeJobs-> JobCleaningAgent_removeJobs, RequestAgentMixIn_selectJobs_|_RequestAgentMixIn_selectJobs-> RequestAgentMixIn_selectJobs, RequestAgentMixIn_setJobStatus_|_RequestAgentMixIn_setJobStatus-> RequestAgentMixIn_setJobStatus, RequestAgentMixIn_setMinorStatus_|_RequestAgentMixIn_setMinorStatus-> RequestAgentMixIn_setMinorStatus, JobAgent_selectJobs_|_JobAgent_selectJobs-> JobAgent_selectJobs, JobAgent_matchJobs_|_JobAgent_matchJobs-> JobAgent_matchJobs, JobAgent_updateStatus_|_JobAgent_updateStatus-> JobAgent_updateStatus, JobAgent_rescheduleJob_|_JobAgent_rescheduleJob-> JobAgent_rescheduleJob, JobAgent_setupProxy_|_JobAgent_setupProxy-> JobAgent_setupProxy, JobAgent_checkInstallSoftware_|_JobAgent_checkInstallSoftware-> JobAgent_checkInstallSoftware, JobAgent_submitJob_|_JobAgent_submitJob-> JobAgent_submitJob, JobWrapper_initialize_|_JobWrapper_initialize-> JobWrapper_initialize, JobWrapper_rescheduleJob_|_JobWrapper_rescheduleJob-> JobWrapper_rescheduleJob, JobWrapper_transferInputSandbox_|_JobWrapper_transferInputSandbox-> JobWrapper_transferInputSandbox, JobWrapper_resolveInputData_|_JobWrapper_resolveInputData-> JobWrapper_resolveInputData, JobWrapper_execute_|_JobWrapper_execute-> JobWrapper_execute, JobWrapper_processJobOutputs_|_JobWrapper_processJobOutputs-> JobWrapper_processJobOutputs, JobWrapper_finalize_|_JobWrapper_finalize-> JobWrapper_finalize, DIRAC_API_delete_|_DIRAC_API_delete-> DIRAC_API_delete, DIRAC_API_reschedule_|_DIRAC_API_reschedule-> DIRAC_API_reschedule, DIRAC_API_kill_|_DIRAC_API_kill-> DIRAC_API_kill, getRandomJob_|_getRandomJob-> getRandomJob, StagerSystem_selectJobs_|_StagerSystem_selectJobs-> StagerSystem_selectJobs, StagerSystem_updateJobFromStager_|_StagerSystem_updateJobFromStager-> StagerSystem_updateJobFromStager, JobManager_submitJob_|_JobManager_submitJob -> JobManager_submitJob }, JobManager || Jobsproc([]) || JobPathAgent || JobSanityAgent || InputDataAgent || JobSchedulingAgent || TaskQueueAgent || StalledJobAgent || JobCleaningAgent || RequestAgentMixIn || JobAgent || StagerSystem || DIRAC_API %|| Monitor([jobstatus(Killed,MarkedForTermination)],[jobstatus(Checking,JobScheduling)],false) % For the purpose of verification only %||Monitor([jobstatus(Failed,PilotNotRunning)], [jobstatus(Done,ExecutionComplete)],false) % For the purpose of verification only ))); mcrl2-201409.0/examples/industrial/DIRAC/properties_SMS/noTransitFromDeleted.trc000770 001750 001750 00000004321 12370120076 027700 0ustar00outisoutis000000 000000 mCRL2Trace‹¯ƒZ¥[_,_]€’YXV[] CacheReplicasNewWaitingStageSubmittedStagedTaskstNewtStageSubmittedtStagedtFailedtDeletedTuplepSortId NatBoolNilOpId  W SortArrowSortConsSortListPos DataVarId""=8743trueDataAppl@c0[]|>@cNat@c1falseActId"%$#-+*,)('&210./SRAgent_issuePrestageRequestsTSMAgent_monitorStageRequestsTRFAgent_selectTasksRFAgent_callbackStagedTasksTRPAgent_selectCacheReplicasRPAgent_prepareNewReplicasSRAgent_selectCacheReplicasSRAgent_issuePrestageRequestsSMAgent_selectCacheReplicasSMAgent_monitorStageRequestsSRAgent_selectTaskReplicasSMAgent_selectTaskReplicas StorageManagerHandler_createTask StorageManagerHandler_setRequest'StorageManagerHandler_insertReplicaInfo+StorageManagerHandler_insertTaskReplicaInfo&StorageManagerHandler_getReplicaStatesdc0dc1dc2dc3dc16dc17dc18dc20dc23dc33dc34dc36dc37dc38dc40dc43dc53dc54dc56dc57dc58dc59dc60dc61dc62dc72dc74dc75dc76dc77dc100dc101dc102dc103MultActAction!@cDubSTATEpairU€Z„2E  Ê€Cå`òr¨9@ceÂÊdÈ2°€`j true mcrl2-201409.0/examples/industrial/DIRAC/properties_SMS/noTransitFromDeleted.mcf000770 001750 001750 00000000557 12370120076 027664 0ustar00outisoutis000000 000000 % A deleted task will never be referenced for transition to any other state. (safety) % - the property violation trace (noTransitFromDeleted.trc) % shows a situation in which the Task is referenced by an % agent, after it has been deleted. [true*.state([tDeleted]). true*. (state([tNew]) || state([tStageSubmitted]) || state([tStaged]) || state([tFailed]) )]false mcrl2-201409.0/examples/industrial/DIRAC/properties_SMS/eventuallyDeleted.trc000770 001750 001750 00000003461 12370120076 027267 0ustar00outisoutis000000 000000 mCRL2Trace‹¯ƒJa[_,_]IH F[] CacheReplicasNewWaitingStageSubmittedFailedTaskstNewtStageSubmittedtFailedTuplepSortId NatBoolNilOpId  G SortArrow SortCons SortListPos DataVarId98@?>=<76521DCBA;:430/trueDataAppl@c0[]|>@cNat@c1falseActId !)'&(%$#".-,*+SRAgent_issuePrestageRequestsTSMAgent_monitorStageRequestsTRPAgent_selectCacheReplicasRPAgent_prepareNewReplicasSRAgent_selectCacheReplicasSRAgent_issuePrestageRequestsSMAgent_selectCacheReplicasSMAgent_monitorStageRequestsSRAgent_selectTaskReplicasSMAgent_selectTaskReplicas StorageManagerHandler_createTask StorageManagerHandler_setRequest'StorageManagerHandler_insertReplicaInfo+StorageManagerHandler_insertTaskReplicaInfo&StorageManagerHandler_getReplicaStatesdc0dc1dc2dc3dc16dc17dc18dc20dc23dc33dc34dc36dc37dc38dc40dc43dc53dc54dc56dc57dc58dc59MultActAction@cDubSTATEpairE€äZ„2E «*P$eXJ* PåÇ!YHÊìa|`P~@,‚¦ „ˆ¡Eˆ*œ¬ÄGe !f™Bø‚x¦˜ DQa# ˆ¡Eˆ*œ¬Â!Fˆe#"$¤'¨J",H!Qࢨ0P ˆ€B‹"T8)X;ŒÆO3N›E$­HÃ):’a¸— .&[Eá³\6F%-"B0#câã¨XÀ!U á ‘áP@H¡Eˆ*œ…ÁfD ¬‹¥oHj®%e ѱiÆ— D.• ¼ â&4#-B@,@‰P à¤(Î*»:© dfª+ЍO8@@ Ò-Eˆ*œ…Ã2æÌ!br°8ÄŠ <àáexÄ<½-Æ'Š”‹@‘bJ€g!G±Üù÷pXà‡E€F’-%@3‚¢Ø‚ÄX,V?áT’ Lˆ”˜Td„¤ñ@Ñc$bhQP«  ÁHQ¬LÙs4qÈ”Uò“bJ/„›£Jµ â‡E†‘ÉáD¬î(*œ…¯–ªA` š L Vp ÌE€Î BŽcu+ÝÀ±X r…PÎp€rªr]–S“ÅE†•œB `3‚¢˜3jÌÐâ‚rÄ¢ÃJÎ(V‰ÁHQŒ]­wpuÈ MU’Á”#ŽL[IMàh°Ò³ I²„pRCï[¸Kª¡ÓP2€sÃ…‹é©   ¨ 6@Î B mcrl2-201409.0/examples/industrial/DIRAC/properties_WMS/noZombieJobs.trc000770 001750 001750 00000003372 12370120076 026215 0ustar00outisoutis000000 000000 mCRL2Trace‹¯ƒK#[_,_]]JIF[]StatusReceivedCheckingStagingKilled MinorStatus JobSanity JobAccepted JobScheduling InputDataStagingRequestSentMarkedForTerminationJob jobstatusSortIdNil WrapperStateOpId   HG  SortArrowSortConsSortListNatPosBool DataVarIdBD531/CA@?>=<;:9876420.DataAppl@c0[]|>@c1ActId ,)*+('&%$#"!-JobPathAgent_selectJobsJobPathAgent_setNextOptimizerJobSanityAgent_selectJobsJobSanityAgent_setNextOptimizerInputDataAgent_selectJobsInputDataAgent_setNextOptimizerJobSchedulingAgent_selectJobs$JobSchedulingAgent_setStagingRequestDIRAC_API_kill getRandomJobStagerSystem_selectJobs StagerSystem_updateJobFromStagerJobManager_submitJobdcdc1dc3dc6dc9dc11dc13dc16dc19dc23dc24dc40dc41dc42dc43dc89dc90dc102dc103dc149dc150dc153dc156MultAct Action  @cDubfalseSTATEpair E(t=À€ÚF Ô ¨3@"h04z„ê•©F kTeP-#g  ^å@‚Á@ `¨C€”@vT!qd˜) Ú…²¦ˆ!°pb‚ŠÅ,‘A ÉÆ„@àb XF‚’£Îzhˆé¢4" Í FHÑQ²Œ•^¨©q@Ø„A(@‘À 0” t Ð B%̈£8pØI .¸’e3PÖaqá"Ä 4¨ H` JŒ :èJ£3æÌ‘‡ ¬" Dƒ H` JŒ :èL ˆ–"˜Ž‹"Ð Ú¨K(ƒ¹H±bIP$@°Œ%Fô$QTËUpÌP1@£I@°Œ%Fô'Í«30ÅG DP*èå\FÔ9œA<4D±Œ 0,â XF‚’£ÎzÈîµ»¨b¨3‚`Q&’ F‚’£ÎzHM„Hdc€b¨õ}„ލPÚ…2H7™Š– Q&˜Q@ (ÀpRP4`YÐ/@‚I-´Î¬p-}@˜¤Œ 0,ÀŠŒ%FœA œB¬ìªš‡YPÆiÀ£L 0"€€£ÁI@ÑgaŠ#wöÝ…ÍY‰ õŒn©jà ¾&XF˜`EF‚’£Î È`#3ƒŒÀb¨C,‚`Q&˜@@Q€à¤ hÀ³ M@«mcrl2-201409.0/examples/industrial/DIRAC/properties_WMS/jobFailedToDone.mcf000770 001750 001750 00000001017 12370120076 026554 0ustar00outisoutis000000 000000 % No transit between two terminating states (Failed to Done) % The property fails, as exemplified by the trace jobFailedToDone.trc % % Currently (December 2011), verifying the property using pbes2bool or pbes2bes requires % too much time (> 50 hours) and is very memory-hungry. The violation can be detected % much faster by specifying a monitor process and searching for the presence of an action % using lps2lts. [true*.state([jobstatus(Failed,PilotNotRunning)]). true*. state([jobstatus(Done,ExecutionComplete)]) ]false mcrl2-201409.0/examples/industrial/DIRAC/properties_WMS/noZombieJobs.mcf000770 001750 001750 00000001040 12370120076 026160 0ustar00outisoutis000000 000000 % Once a job has been killed, it cannot resurrect and start running. (safety) % The property fails, as exemplified by the trace noZombieJobs.trc % % Currently (December 2011), verifying the property using pbes2bool or pbes2bes requires % too much time (> 50 hours) and is very memory-hungry. The violation can be detected % much faster by specifying a monitor process and searching for the presence of an action % using lps2lts. [true*.state([jobstatus(Killed,MarkedForTermination)]). true*. state([jobstatus(Checking,JobScheduling)]) ]false mcrl2-201409.0/examples/industrial/DIRAC/properties_WMS/jobFailedToDone.trc000770 001750 001750 00000010432 12370120076 026600 0ustar00outisoutis000000 000000 mCRL2Trace‹¯ƒ€‰‚Ì[_,_]€ˆ€‡2€„90&[]StatusStalledRunningReceivedFailedDoneMatchedCheckingWaitingStaging Completed MinorStatusPilotNotRunning JobSanity JobAccepted JobScheduling InputData TaskQueue ApplicationInstallingSoftwareStagingRequestSentPilotAgentSubmissionAssignedJobReceivedByAgent SubmittedToCEJobInitializationDownloadingInputSandboxInputDataResolutionApplicationSuccessUploadingOutputSandboxOutputSandboxUploadedUploadingOutputDataOutputDataUploadedExecutionCompleteJob jobstatusSortId6 (4$5Nil WrapperState StartWrapperFault ExecuteOK CompletedOKOutputSandboxOK OutputDataOK FinalizeOKOpId1//#."!- , +*)8   :<€†€…%;=12& SortArrow2&SortCons3&SortListNatPosBool DataVarId''}|mlkji~{zxywvfd€ca_]€‚€€utsrqponhgeb`^\&2trueDataAppl;0@c0[]|>@c1ActIdWV[ULKJTSRQPONMIHFYXGEDCBA@?ZJobPathAgent_selectJobsJobPathAgent_setNextOptimizerJobSanityAgent_selectJobsJobSanityAgent_setNextOptimizerInputDataAgent_selectJobsInputDataAgent_setNextOptimizerJobSchedulingAgent_selectJobs"JobSchedulingAgent_sendToTaskQueue$JobSchedulingAgent_setStagingRequestTaskQueueAgent_selectJobsTaskQueueAgent_insertJobInQueueStalledJobAgent_selectJobsStalledJobAgent_markStalledJobsStalledJobAgent_failStalledJobsJobAgent_selectJobsJobAgent_matchJobsJobAgent_updateStatusJobAgent_checkInstallSoftwareJobAgent_submitJobJobWrapper_initializeJobWrapper_transferInputSandboxJobWrapper_resolveInputDataJobWrapper_executeJobWrapper_processJobOutputsJobWrapper_finalizeStagerSystem_selectJobs StagerSystem_updateJobFromStagerJobManager_submitJobrunAppdcdc1dc3dc6dc9dc11dc13dc16dc17dc19dc21dc23dc24dc25dc26dc27dc33dc34dc40dc41dc42dc43dc89dc90dc102dc103dc104dc105dc106dc110dc120dc125dc129dc130dc139dc146dc149dc150dc153MultAct#Action">@cDubfalseSTATE%90909097909790979097909790979707777077900797909707pair#€ƒ'€@:‡AlKÍ#AM@HPÔB5Q L@qõõIu(u¦ÔbÕY1´àÕyÕB0 &€U€ @2ˆ²¡áªL!VÔ dJA`à1AAXd‚qÈŒ@à  A!aQ0H Y9xDAÐÐCpAGšhäɈ‚¢(YQª[QP¸Pˆ@P@H@X@D@TLÀ’(†@VN@^þ!\2\0PŽ`HAat¥$˜KjÓŽ‚ÁEU@P@H@X@D@TLÀ’(†@VN@^~a|6œ0Ž~„@Q@H@X@D@TLÀ’(†@VN@^¾10±XBtÌ[P¾”qH, ( "ªBÂ"¢`‘@42²rð‰ð¢‰‘¨§a…ˆô`€âŠH€ÂÂ"¢`‘@42²rðŽða‹Q˜ca„¨8‚"‹¡È®"Ú†ôà€“ƒA°@Q@I@YePp$Š¡“€W‡VÇ+ %D „PPDp$Š¡“€g€‚IŒ ‹ (ÁÀ ô_!Hè¡Ú„ô€ÓŒÁP°@Q@I@Y@E%Pp$Š¡“€G„’M$³*ÁÀ,_(E ( $ , " " *&àIC +' ÷»E&JˆwM ( $ , " " *&àIC +' *¢ -Ã€Ý $€¢€’€² 0€ˆ€¨˜$P €¬œ€ª#\4Ò60 radio telescopes on a plane % high up in the mountains of Chili for radio astronomy. % % An explanation of this specification can be found in % % B.~Ploeger. Analysis of ACS using mCRL2. % Technical Report 09-11, Computer Science Reports, % Department of Mathematics and Computer Science, Eindhoven % University of Technology, Eindhoven, The Netherlands, 2009. % % Author: Bas Ploeger % September 2009 % Data sort for the state of a container or component sort State = struct dead | loggingin | running; % Data sort for identifying the various processes in the system % (Manager threads, components, etc.) sort ID = struct none | Comp1 | Comp2 | Cont1 | MT1 | MT2 | ContLogin; % Functions for checking if an ID indicates a component/container map is_component: ID -> Bool; is_container: ID -> Bool; var x: ID; eqn is_component(x) = (x in {Comp1,Comp2}); is_container(x) = (x in {Cont1}); % Function returning the container of a component map getCont: ID -> ID; eqn getCont(Comp1) = Cont1; getCont(Comp2) = Cont1; % Function for adding elements to a list of IDs. It is ensured that the % list contains no duplicates and remains sorted. map add_sorted: ID # List(ID) -> List(ID); var c,d:ID; L:List(ID); eqn add_sorted(c,[]) = [c]; add_sorted(c,d |> L) = if( c < d , c |> d |> L , d |> if(c==d , L , add_sorted(c,L)) ); %%% Action declarations %%% act % For container life cycle rcv_startup_container, snd_startup_container, startup_container, rcv_login, snd_login, login, rcv_authenticate, snd_authenticate, authenticate, rcv_auth_ok, snd_auth_ok, auth_ok, rcv_auth_not_ok, snd_auth_not_ok, auth_not_ok: ID # ID; % For component life cycle rcv_activate_component, snd_activate_component, activate_component: ID # ID # ID; rcv_create, snd_create, create, rcv_initialize, snd_initialize, initialize, rcv_execute, snd_execute, execute: ID # ID; % For accessing/manipulating data stored in the Manager rcv_has_component_man, snd_has_component_man, has_component_man, rcv_no_component_man, snd_no_component_man, no_component_man, rcv_add_component_man, snd_add_component_man, add_component_man, rcv_has_container_man, snd_has_container_man, has_container_man, rcv_no_container_man, snd_no_container_man, no_container_man, rcv_add_container_man, snd_add_container_man, add_container_man, rcv_acquire_actsync_lock, snd_acquire_actsync_lock, acquire_actsync_lock, rcv_release_actsync_lock, snd_release_actsync_lock, release_actsync_lock: ID # ID; % For synchronization of access to data stored in the Manager rcv_free_container, snd_free_container, free_container, rcv_lock_container, snd_lock_container, lock_container, rcv_free_component, snd_free_component, free_component, rcv_lock_component, snd_lock_component, lock_component: ID; % For synchronization on monitor objects rcv_wake_up, snd_wake_up, wake_up, rcv_notify_all, snd_notify_all, notify_all, rcv_wait, snd_wait, wait: ID # ID; timeout: ID; % External triggers get_component: ID # ID; %%% Process definitions %%% % A monitor object proc Monitor(m:ID,waitlist:List(ID)) = sum n:ID . ( rcv_wait(n,m) . Monitor(m,add_sorted(n,waitlist)) + rcv_notify_all(n,m) . ( (waitlist == []) -> Monitor(m,waitlist) <> Monitor_NotifyAll(m,waitlist) ) ); proc Monitor_NotifyAll(m:ID,waitlist:List(ID)) = snd_wake_up(head(waitlist),m) . ( (tail(waitlist) != []) -> Monitor_NotifyAll(m,tail(waitlist)) <> Monitor(m,[]) ); % Manager % The activation synchronization locks proc ManagerActSync(actsync:Set(ID)) = sum m,n:ID . (n in actsync) -> rcv_release_actsync_lock(m,n) . ManagerActSync(actsync - {n}) <> rcv_acquire_actsync_lock(m,n) . ManagerActSync(actsync + {n}); % The component store proc ManagerComponents(comps:Set(ID),lock:ID) = (lock == none) -> sum m:ID . snd_lock_component(m) . ManagerComponents(comps,m) + rcv_free_component(lock) . ManagerComponents(comps,none) + sum c:ID . is_component(c) -> ((c in comps) -> snd_has_component_man(lock,c) . ManagerComponents(comps,lock) <> snd_no_component_man(lock,c) . ManagerComponents(comps,lock) + rcv_add_component_man(lock,c) . ManagerComponents(comps + {c},lock) ); % The container store proc ManagerContainers(conts:Set(ID),lock:ID) = (lock == none) -> sum m:ID . snd_lock_container(m) . ManagerContainers(conts,m) + rcv_free_container(lock) . ManagerContainers(conts,none) + sum c:ID . is_container(c) -> ( (c in conts) -> snd_has_container_man(lock,c) . ManagerContainers(conts,lock) <> snd_no_container_man(lock,c) . ManagerContainers(conts,lock) + rcv_add_container_man(lock,c) . ManagerContainers(conts + {c},lock) ); % Manager thread proc ManagerThread(m:ID) = sum c:ID . is_component(c) -> ( get_component(m,c) .(timeout(m) + snd_acquire_actsync_lock(m,c) . rcv_lock_component(m) .(rcv_has_component_man(m,c) . snd_free_component(m) + rcv_no_component_man(m,c) . snd_free_component(m) . rcv_lock_container(m) .(rcv_has_container_man(m,getCont(c)) . snd_free_container(m) . MT_ActivateComponent(m,c) + rcv_no_container_man(m,getCont(c)) . snd_free_container(m) .(timeout(m) + snd_acquire_actsync_lock(m,getCont(c)) . snd_startup_container(m,getCont(c)) . snd_wait(m,ContLogin) . rcv_wake_up(m,ContLogin) . snd_release_actsync_lock(m,getCont(c)) . MT_ActivateComponent(m,c) ) ) ) . snd_release_actsync_lock(m,c) ) . ManagerThread(m) ) + sum c:ID . is_container(c) -> ( rcv_login(m,c) . snd_authenticate(m,c) .(snd_auth_not_ok(m,c) + snd_auth_ok(m,c) . rcv_lock_container(m) .(rcv_has_container_man(m,c) + rcv_no_container_man(m,c) . snd_add_container_man(m,c) ) . snd_free_container(m) . snd_notify_all(m,ContLogin) ) . ManagerThread(m) ); % Activate a component proc MT_ActivateComponent(m:ID,c:ID) = snd_activate_component(m,getCont(c),c) . rcv_lock_component(m) . snd_add_component_man(m,c) . snd_free_component(m); % Container proc Container(c:ID, s:State, comps:Set(ID)) = sum m:ID . ( (s == dead) -> rcv_startup_container(m,c) . Container(c,loggingin,comps) + (s == loggingin) -> snd_login(m,c) . rcv_authenticate(m,c) .( rcv_auth_ok(m,c) . Container(c,running,comps) + rcv_auth_not_ok(m,c) . Container(c,dead,comps) ) + (s == running) -> sum d:ID . is_component(d) -> rcv_activate_component(m,c,d) . snd_create(c,d) . snd_initialize(c,d) . snd_execute(c,d) . Container(c,s,comps + {d}) ); % Component proc Component(c:ID,s:State) = (s == dead) -> sum d:ID . rcv_create(d,c) . rcv_initialize(d,c) . rcv_execute(d,c) . Component(c,running); %%% Initial process specification %%% init % Allow only these actions, block all others allow( { login, authenticate, auth_ok, auth_not_ok, startup_container, activate_component, create, initialize, execute, get_component, has_component_man, no_component_man, add_component_man, has_container_man, no_container_man, add_container_man, acquire_actsync_lock, release_actsync_lock, free_container, lock_container, free_component, lock_component, notify_all, wake_up, wait, timeout }, % Synchronously communicating actions comm( { rcv_login|snd_login -> login, rcv_authenticate|snd_authenticate -> authenticate, rcv_auth_ok|snd_auth_ok -> auth_ok, rcv_auth_not_ok|snd_auth_not_ok -> auth_not_ok, rcv_startup_container|snd_startup_container -> startup_container, rcv_activate_component|snd_activate_component -> activate_component, rcv_create|snd_create -> create, rcv_initialize|snd_initialize -> initialize, rcv_execute|snd_execute -> execute, rcv_has_component_man|snd_has_component_man -> has_component_man, rcv_no_component_man|snd_no_component_man -> no_component_man, rcv_add_component_man|snd_add_component_man -> add_component_man, rcv_has_container_man|snd_has_container_man -> has_container_man, rcv_no_container_man|snd_no_container_man -> no_container_man, rcv_add_container_man|snd_add_container_man -> add_container_man, rcv_acquire_actsync_lock|snd_acquire_actsync_lock -> acquire_actsync_lock, rcv_release_actsync_lock|snd_release_actsync_lock -> release_actsync_lock, rcv_free_container|snd_free_container -> free_container, rcv_lock_container|snd_lock_container -> lock_container, rcv_free_component|snd_free_component -> free_component, rcv_lock_component|snd_lock_component -> lock_component, rcv_wake_up|snd_wake_up -> wake_up, rcv_notify_all|snd_notify_all -> notify_all, rcv_wait|snd_wait -> wait }, % The parallel processes that constitute the system, along with their % initial states ManagerActSync({}) || ManagerComponents({},none) || ManagerContainers({},none) || ManagerThread(MT1) || ManagerThread(MT2) || Container(Cont1,dead,{}) || Component(Comp1,dead) || Component(Comp2,dead) || Monitor(ContLogin,[]) )); mcrl2-201409.0/examples/industrial/alma/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 023034 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on block. [true*]true mcrl2-201409.0/examples/industrial/alma/run.py000770 001750 001750 00000000336 12370120076 021424 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v alma.mcrl2 alma.lps') os.system('lps2pbes -v -f nodeadlock.mcf alma.lps alma.nodeadlock.pbes') os.system('pbes2bool -v alma.nodeadlock.pbes') os.system('lps2lts -v alma.lps alma.aut') mcrl2-201409.0/examples/industrial/1394/1394-fin.mcrl2000770 001750 001750 00000034563 12370120076 022060 0ustar00outisoutis000000 000000 % This file contains a description of the physical layer service % of the 1394 or firewire protocol and also a description of the link % layer protocol entities. This decription has been published % as S.P. Luttik in $\mu$CRL, and adapted to mCRL. Description % and formal specification of the link layer % of P1394. Technical Report SEN-R9706, CWI, Amsterdam, 1997. % The state space of the description as given, with 2 link % protocol entities and the domains DATA, ACK and HEADER all having % two elements has approximately 380.000 states. For 3 link protocols % and the domains DATA, ACK and HEADER having only one element % the state space has less than 300.000 states. % % This description has been analysed in M. Sighireanu and R. Mateescu, % Verification of the Link Layer Protocol of the IEEE-1394 Serial Bus % (``FireWire''): an Experiment with E-LOTOS. Springer International % Journal on Software Tools for Technology Transfer (STTT), 1998. % 1996, where they showed a mistake in the description, which could % be traced back to a mistake in the standard. % % The description in this file differs on a few points from the % description by Luttik to facilitate the generation of the state % space. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% DATA/CONTROL/ACKNOWLEDGE ELEMENTS AND THERE CRC COMPUTATION %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sort CHECK = struct bottom | check; sort DATA = struct d1 | d2; map crc : DATA -> CHECK; eqn crc(d1)=check; crc(d2)=check; sort HEADER = struct h1 | h2; map crc : HEADER -> CHECK; eqn crc(h1)=check; crc(h2)=check; sort ACK = struct a1 | a2; map crc : ACK -> CHECK; eqn crc(a1)=check; crc(a2)=check; sort SIGNAL = struct sig(getdest:Nat) ? is_dest | sig(gethead:HEADER,gethcrc:CHECK) ? is_header | sig(getdata:DATA,getdcrc:CHECK) ? is_data | sig(getack:ACK,getacrc:CHECK) ? is_ack | Start ? is_start | End ? is_end | Prefix ? is_prefix | subactgap ? is_sagap | dhead ? is_dhead | Dummy ? is_dummy; map is_physig,is_terminator : SIGNAL -> Bool; getcrc : SIGNAL -> CHECK; var s : SIGNAL; eqn is_physig(s) = is_start(s) || is_end(s) || is_prefix(s) || is_sagap(s); is_terminator(s)=is_end(s) || is_prefix(s); getcrc(s)=if(is_header(s),gethcrc(s), if(is_data(s),getdcrc(s), if(is_ack(s),getacrc(s), bottom))); map is_hda : SIGNAL -> Bool; valid_hpart, valid_ack : SIGNAL -> Bool; var s : SIGNAL; eqn is_hda(s)=is_header(s) || is_data(s) || is_ack(s); valid_ack(s)=if(is_ack(s),getacrc(s)==check,false); valid_hpart(s)=if(is_header(s),gethcrc(s)==check,false); map corrupt : SIGNAL -> SIGNAL; var h : HEADER; d : DATA; a : ACK; c : CHECK; eqn corrupt(sig(h,c)) = sig(h,bottom); corrupt(sig(d,c)) = sig(d,bottom); corrupt(sig(a,c)) = sig(a,bottom); sort SIG_TUPLE = struct quadruple (first:SIGNAL, second:SIGNAL, third:SIGNAL, fourth:SIGNAL) | void ? is_void; sort PAR = struct fair | immediate; sort PAC = struct won | lost; sort LDC = struct ackrec(ACK) | ackmiss | broadsent; sort LDI = struct good (HEADER,DATA) | broadrec (HEADER,DATA) | dcrc_err (HEADER); sort BOC = struct release | hold; act LDreq : Nat#Nat#HEADER#DATA; LDcon : Nat#LDC; LDind : Nat#LDI; LDres : Nat#ACK#BOC; sPDreq,rPDind : Nat#SIGNAL; sPAreq : Nat#PAR; rPAcon : Nat#PAC; rPCind : Nat; proc Link0(n:Nat,id:Nat,buffer:SIG_TUPLE)= is_void(buffer) -> ( sum dest:Nat,h:HEADER,d:DATA. ( dest<=n) -> LDreq(id,dest,h,d). Link0(n,id,quadruple(dhead, sig(dest), sig(h,crc(h)), sig(d,crc(d))))<>delta) <> sPAreq(id,fair).Link1(n,id,buffer) + sum p:SIGNAL. rPDind(id,p). (is_start(p) -> Link4(n,id,buffer) <> Link0(n,id,buffer)); Link1(n:Nat,id:Nat,p:SIG_TUPLE)= rPAcon(id,won).Link2req(n,id,p) + rPAcon(id,lost).Link0(n,id,p); Link2req(n:Nat,id:Nat,p:SIG_TUPLE)= rPCind(id).sPDreq(id,Start). rPCind(id).sPDreq(id,first(p)). rPCind(id).sPDreq(id,second(p)) . rPCind(id).sPDreq(id,third(p)). rPCind(id).sPDreq(id,fourth(p)). rPCind(id).sPDreq(id,End). ( (getdest(second(p))==n) -> LDcon(id,broadsent).Link0(n,id,void) <> Link3(n,id,void)); Link3(n:Nat,id:Nat,buffer:SIG_TUPLE)= sum p:SIGNAL. rPDind(id,p). ( is_prefix(p) -> Link3(n,id,buffer) <> ( is_start(p) -> Link3RA(n,id,buffer) <> ( is_sagap(p) -> LDcon(id,ackmiss).Link0(n,id,buffer) <> LDcon(id,ackmiss).LinkWSA(n,id,buffer,n) ))); Link3RA(n:Nat,id:Nat,buffer:SIG_TUPLE)= sum a:SIGNAL. rPDind(id,a). ( is_sagap(a) -> LDcon(id,ackmiss).Link0(n,id,buffer) <> ( is_physig(a) -> LDcon(id,ackmiss).LinkWSA(n,id,buffer,n) <> Link3RE(n,id,buffer,a))); Link3RE(n:Nat,id:Nat,buffer:SIG_TUPLE,a:SIGNAL)= sum e:SIGNAL. rPDind(id,e). ((valid_ack(a) && is_terminator(e)) -> LDcon(id,ackrec(getack(a))).LinkWSA(n,id,buffer,n) <> ( is_sagap(e) -> LDcon(id,ackmiss).Link0(n,id,buffer) <> LDcon(id,ackmiss).LinkWSA(n,id,buffer,n) ) ); Link4(n:Nat,id:Nat,buffer:SIG_TUPLE)= sum dh:SIGNAL. rPDind(id,dh). ( is_physig(dh) -> ( is_sagap(dh) -> Link0(n,id,buffer) <> LinkWSA(n,id,buffer,n)) <> Link4DH(n,id,buffer)); Link4DH(n:Nat,id:Nat,buffer:SIG_TUPLE)= sum dest:SIGNAL.rPDind(id,dest). ( is_dest(dest) -> ( (getdest(dest)==id) -> sPAreq(id,immediate).Link4RH(n,id,buffer,id) <> ( (getdest(dest)==n) -> Link4RH(n,id,buffer,n) <> LinkWSA(n,id,buffer,n) ) ) <> ( is_sagap(dest) -> Link0(n,id,buffer) <> LinkWSA(n,id,buffer,n) ) ); Link4RH(n:Nat,id:Nat,buffer:SIG_TUPLE,dest:Nat)= sum h:SIGNAL.rPDind(id,h). ( valid_hpart(h) -> Link4RD(n,id,buffer,dest,h) <> LinkWSA(n,id,buffer,dest) ); Link4RD(n:Nat,id:Nat,buffer:SIG_TUPLE,dest:Nat,h:SIGNAL)= sum d:SIGNAL. rPDind(id,d). ( is_data(d) -> Link4RE(n,id,buffer,dest,h,d) <> LinkWSA(n,id,buffer,dest) ); Link4RE(n,id:Nat,buffer:SIG_TUPLE,dest:Nat,h:SIGNAL,d:SIGNAL)= sum e:SIGNAL. rPDind(id,e). ( is_terminator(e) -> ( (dest==id) -> Link4DRec(n,id,buffer,h,d) <> Link4BRec(n,id,buffer,h,d) ) <> LinkWSA(n,id,buffer,dest) ); Link4DRec(n:Nat,id:Nat,buffer:SIG_TUPLE,h:SIGNAL,d:SIGNAL)= (getcrc(d)==check) -> LDind(id,good(gethead(h),getdata(d))).rPAcon(id,won).Link5(n,id,buffer) <> LDind(id,dcrc_err(gethead(h))).rPAcon(id,won).Link5(n,id,buffer); Link4BRec(n:Nat,id:Nat,buffer:SIG_TUPLE,h:SIGNAL,d:SIGNAL)= (getcrc(d)==check) -> LDind(id,broadrec(gethead(h),getdata(d))).Link0(n,id,buffer) <> Link0(n,id,buffer); Link5(n,id:Nat,buffer:SIG_TUPLE)= sum a:ACK,b:BOC.LDres(id,a,b).Link6(n,id,buffer,sig(a,crc(a)),b) + rPCind(id).sPDreq(id,Prefix).Link5(n,id,buffer); Link6(n:Nat,id:Nat,buffer:SIG_TUPLE,p:SIGNAL,b:BOC)= rPCind(id).sPDreq(id,Start).rPCind(id).sPDreq(id,p).rPCind(id). ( (b==release) -> sPDreq(id,End).Link0(n,id,buffer) <> sPDreq(id,Prefix).Link7(n,id,buffer) ); Link7(n,id:Nat,buffer:SIG_TUPLE)= rPCind(id).sPDreq(id,Prefix).Link7(n,id,buffer) + sum dest:Nat,h:HEADER,d:DATA. (dest<=n) -> LDreq(id,dest,h,d). Link2resp(n,id,buffer, quadruple(dhead,sig(dest),sig(h,crc(h)),sig(d,crc(d))))<>delta; Link2resp(n:Nat,id:Nat,buffer:SIG_TUPLE,p:SIG_TUPLE)= rPCind(id).sPDreq(id,Start). rPCind(id).sPDreq(id,first(p)). rPCind(id).sPDreq(id,second(p)). rPCind(id).sPDreq(id,third(p)). rPCind(id).sPDreq(id,fourth(p)). rPCind(id).sPDreq(id,End). ( (getdest(second(p))==n) -> LDcon(id,broadsent).Link0(n,id,buffer) <> Link3(n,id,buffer) ); LinkWSA(n:Nat,id:Nat,buffer:SIG_TUPLE,dest:Nat)= sum p:SIGNAL.rPDind(id,p). ( is_sagap(p) -> Link0(n,id,buffer) <> LinkWSA(n,id,buffer,dest) ) + (dest==id) -> rPAcon(id,won).rPCind(id).sPDreq(id,End).Link0(n,id,buffer)<>delta; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% AUXILIARY SPECIFICATION OF BUS %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sort BoolTABLE = List(struct pair(Nat,getbool:Bool)); map inita : Nat -> BoolTABLE; invert : Nat#BoolTABLE -> BoolTABLE; get : Nat#BoolTABLE -> Bool; var n,m : Nat; b : Bool; bt1,bt2 : BoolTABLE; eqn inita(0)=[]; n>0 -> inita(n)=pair(Int2Nat(n-1),false)|>inita(Int2Nat(n-1)); invert(n,[])=[]; invert(n,pair(m,b)|>bt1)= if(n==m,pair(m,!b)|>bt1,pair(m,b)|>invert(n,bt1)); get(n,[])=false; get(n,pair(m,b)|>bt1)=if(n==m,b,get(n,bt1)); map zero,one,more: BoolTABLE -> Bool; var n : Nat; bt : BoolTABLE; eqn zero([])=true; zero(pair(n,true)|>bt)=false; zero(pair(n,false)|>bt)=zero(bt); one([])=false; one(pair(n,true)|>bt)=zero(bt); one(pair(n,false)|>bt)=one(bt); more(bt)=!zero(bt) && !one(bt); act rPAreq: Nat#PAR; rPDreq,sPDind: Nat#SIGNAL; sPAcon: Nat#PAC; sPCind: Nat; arbresgap; losesignal; internal; proc BusIdle(n:Nat,t:BoolTABLE)= sum id:Nat,astat:PAR.(id<=n) ->rPAreq(id,astat).DecideIdle(n,t,id,astat)<>delta + !zero(t)->arbresgap.BusIdle(n,inita(n))<>delta; DecideIdle(n:Nat,t:BoolTABLE,id:Nat,astat:PAR)= (!get(id,t)) -> sPAcon(id,won).BusBusy(n,invert(id,t),inita(n),inita(n),id) <> sPAcon(id,lost).BusIdle(n,t); BusBusy(n:Nat,t,next,destfault:BoolTABLE,busy:Nat)= (busy ( sPCind(busy). (sum p:SIGNAL.rPDreq(busy,p).Distribute(n,t,next,destfault,busy,p,0)) ) <> ( zero(next) -> SubactionGap(n,t,0) <> Resolve(n,t,next,0) ) + sum j:Nat.(j<=n) -> rPAreq(j,fair).sPAcon(j,lost).BusBusy(n,t,next,destfault,busy)<>delta + sum j:Nat.(j<=n) -> rPAreq(j,immediate). (!get(j,next) -> BusBusy(n,t,invert(j,next),destfault,busy)<>delta)<>delta; SubactionGap(n:Nat,t:BoolTABLE,i:Nat)= (i==n) -> BusIdle(n,t) <> sPDind(i,subactgap).SubactionGap(n,t,i+1); Resolve(n:Nat,t,next:BoolTABLE,i:Nat)= (i (get(i,next) -> sPAcon(i,won).sPCind(i).Resolve(n,t,next,i+1) <> internal.Resolve(n,t,next,i+1) ) <> Resolve2(n,t,next); Resolve2(n:Nat,t:BoolTABLE,next:BoolTABLE)= more(next) -> (sum j:Nat.(j<=n) -> rPDreq(j,End).(get(j,next) -> Resolve2(n,t,invert(j,next))<>delta)<>delta) <> (sum j:Nat,p:SIGNAL.(j<=n) -> rPDreq(j,p). (is_end(p) -> SubactionGap(n,t,0) <> Distribute(n,t,inita(n),inita(n),j,p,0) )<>delta); Distribute(n:Nat,t,next,destfault:BoolTABLE,busy:Nat,p:SIGNAL,i:Nat)= (i ( (i!=busy) -> ( %% Signals can be handed over correctly (!is_header(p) || !get(i,destfault)) -> sPDind(i,p).Distribute(n,t,next,destfault,busy,p,i+1)<>delta + %% Destination signals may be corrupted sum dest:Nat.(is_dest(p) && dest<=n) -> sPDind(i,sig(dest)). Distribute(n,t,next,invert(i,destfault),busy,p,i+1)<>delta + %% Headers/Data/Acks may be corrupted is_hda(p) -> sPDind(i,corrupt(p)). Distribute(n,t,next,destfault,busy,p,i+1)<>delta + %% Headers/Data/Acks may get lost is_hda(p) -> losesignal.Distribute(n,t,next,destfault,busy,p,i+1)<>delta + %% Packets may be too large is_data(p) -> sPDind(i,p).sPDind(i,Dummy). Distribute(n,t,next,destfault,busy,p,i+1)<>delta + (!get(i,next)) -> rPAreq(i,immediate). Distribute(n,t,invert(i,next),destfault,busy,p,i)<>delta ) <> %% i==busy internal.Distribute(n,t,next,destfault,busy,p,i+1) ) <> %% i>=n ( is_end(p) -> BusBusy(n,t,next,destfault,n) <> BusBusy(n,t,next,destfault,busy) ); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% SPECIFICATION OF n LINK LAYERS CONNECTED BY A BUS %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% act cPDreq,cPDind : Nat#SIGNAL; cPAreq : Nat#PAR; cPAcon : Nat#PAC; cPCind : Nat; proc LINK(n:Nat,i:Nat)=Link0(n,i,void); BUS(n:Nat)=BusIdle(n, inita(n)); P1394(n:Nat)= allow({LDreq,LDcon,LDind,LDres}, hide({arbresgap,losesignal,internal,cPDind,cPDreq,cPAcon,cPAreq,cPCind}, comm({rPDind|sPDind->cPDind,rPDreq|sPDreq->cPDreq,rPAcon|sPAcon->cPAcon, rPAreq|sPAreq->cPAreq,rPCind|sPCind->cPCind}, allow({LDreq,LDcon,LDind,LDres,arbresgap,losesignal,internal, rPDind|sPDind,rPDreq|sPDreq,rPAcon|sPAcon, rPAreq|sPAreq,rPCind|sPCind}, BUS(2) || LINK(2,0) || LINK(2,1))))); init P1394(2); mcrl2-201409.0/examples/industrial/1394/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 022522 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on block. [true*]true mcrl2-201409.0/examples/industrial/1394/run.py000770 001750 001750 00000000372 12370120076 021112 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v 1394-fin.mcrl2 1394-fin.lps') os.system('lps2pbes -v -f nodeadlock.mcf 1394-fin.lps 1394-fin.nodeadlock.pbes') os.system('pbes2bool -v 1394-fin.nodeadlock.pbes') os.system('lps2lts -v 1394-fin.lps 1394-fin.aut') mcrl2-201409.0/examples/industrial/chatbox/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 023552 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on block. [true*]true mcrl2-201409.0/examples/industrial/chatbox/run.py000770 001750 001750 00000000363 12370120076 022142 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v chatbox.mcrl2 chatbox.lps') os.system('lps2pbes -v -f nodeadlock.mcf chatbox.lps chatbox.nodeadlock.pbes') os.system('pbes2bool -v chatbox.nodeadlock.pbes') os.system('lps2lts -v chatbox.lps chatbox.aut') mcrl2-201409.0/examples/industrial/chatbox/chatbox.mcrl2000770 001750 001750 00000066521 12370120076 023365 0ustar00outisoutis000000 000000 % This is an MCRL2 description of a chatbox provided by Judi Romijn. Users can % JOIN and LEAVE a discussion, and if joined can send each other % messages and acknowledgements. The system has exactly 2^16 states. % In this description the JOIN, LEAVE and DREQ actions have been hidden. % State space generation is most efficient using -nocluster when linearising. sort Mes = struct MES | ACK; sort Output = struct NO_OUTPUT | OK | DIND; act JOIN, LEAVE: Nat # Output; DREQ: Nat # Nat # Mes # Output; proc Chatbox(pres0: Bool, pres1: Bool, pres2: Bool, pres3: Bool, sentto01: Bool, sentto02: Bool, sentto03: Bool, sentto10: Bool, sentto12: Bool, sentto13: Bool, sentto20: Bool, sentto21: Bool, sentto23: Bool, sentto30: Bool, sentto31: Bool, sentto32: Bool) = pres0 -> JOIN(0,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> JOIN(0,OK) . Chatbox(!pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + pres1 -> JOIN(1,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> JOIN(1,OK) . Chatbox(pres0, !pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + pres2 -> JOIN(2,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> JOIN(2,OK) . Chatbox(pres0, pres1, !pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + pres3 -> JOIN(3,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> JOIN(3,OK) . Chatbox(pres0, pres1, pres2, !pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (!pres0) -> LEAVE(0,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> LEAVE(0,OK) . Chatbox(!pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (!pres1) -> LEAVE(1,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> LEAVE(1,OK) . Chatbox(pres0, !pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (!pres2) -> LEAVE(2,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> LEAVE(2,OK) . Chatbox(pres0, pres1, !pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (!pres3) -> LEAVE(3,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> LEAVE(3,OK) . Chatbox(pres0, pres1, pres2, !pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(0,0,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(1,1,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(2,2,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(3,3,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres0 && pres1 && !sentto01) -> DREQ(0,1,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, !sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(0,1,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres0 && pres2 && !sentto02) -> DREQ(0,2,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, !sentto02,sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(0,2,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres0 && pres3 && !sentto03) -> DREQ(0,3,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, !sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(0,3,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres1 && pres0 && !sentto10) -> DREQ(1,0,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, !sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(1,0,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres1 && pres2 && !sentto12) -> DREQ(1,2,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, !sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(1,2,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres1 && pres3 && !sentto13) -> DREQ(1,3,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, !sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(1,3,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres2 && pres0 && !sentto20) -> DREQ(2,0,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, !sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(2,0,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres2 && pres1 && !sentto21) -> DREQ(2,1,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, !sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(2,1,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres2 && pres3 && !sentto23) -> DREQ(2,3,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, !sentto23, sentto30, sentto31, sentto32) <> DREQ(2,3,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres3 && pres0 && !sentto30) -> DREQ(3,0,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, !sentto30, sentto31, sentto32) <> DREQ(3,0,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres3 && pres1 && !sentto31) -> DREQ(3,1,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, !sentto31, sentto32) <> DREQ(3,1,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres3 && pres2 && !sentto32) -> DREQ(3,2,MES,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, !sentto32) <> DREQ(3,2,MES,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(0,0,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(1,1,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(2,2,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + DREQ(3,3,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres0 && pres1 && sentto10) -> DREQ(0,1,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, !sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(0,1,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres0 && pres2 && sentto20) -> DREQ(0,2,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02,sentto03, sentto10, sentto12, sentto13, !sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(0,2,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres0 && pres3 && sentto30) -> DREQ(0,3,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, !sentto30, sentto31, sentto32) <> DREQ(0,3,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres1 && pres0 && sentto01) -> DREQ(1,0,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, !sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(1,0,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres1 && pres2 && sentto21) -> DREQ(1,2,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, !sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(1,2,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres1 && pres3 && sentto31) -> DREQ(1,3,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, !sentto31, sentto32) <> DREQ(1,3,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres2 && pres0 && sentto02) -> DREQ(2,0,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, !sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(2,0,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres2 && pres1 && sentto12) -> DREQ(2,1,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, !sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(2,1,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres2 && pres3 && sentto32) -> DREQ(2,3,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, !sentto32) <> DREQ(2,3,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres3 && pres0 && sentto03) -> DREQ(3,0,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, !sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(3,0,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres3 && pres1 && sentto13) -> DREQ(3,1,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, !sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) <> DREQ(3,1,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32) + (pres3 && pres2 && sentto23) -> DREQ(3,2,ACK,OK) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, !sentto23, sentto30, sentto31, sentto32) <> DREQ(3,2,ACK,NO_OUTPUT) . Chatbox(pres0, pres1, pres2, pres3, sentto01, sentto02, sentto03, sentto10, sentto12, sentto13, sentto20, sentto21, sentto23, sentto30, sentto31, sentto32); init hide({JOIN,LEAVE,DREQ},Chatbox(false,false,false,false, false,false,false, false,false, false, false,false,false, false,false,false)); mcrl2-201409.0/examples/academic/commprot/commprot.mcrl2000770 001750 001750 00000043041 12370120074 023343 0ustar00outisoutis000000 000000 % This is a translation to mCRL2 of the mCRL specification of the % conference protocol that originally was specified in LOTOS. % The translation to mCRL2 was done by Jan Friso Groote in % February 2006. % % A description of the protocol can be found on http://fmt.cs.utwente.nl/tools/torx/confcase.html. % The description below is a summary from this page. % % The conference service provides a multicast service, resembling a `chatbox', to users % participating in a conference. A conference is a group of users that can exchange messages % to all conference partners in that conference. So, every user can send messages to, or % receive messages from, all its conference partners. % % The actions of each user are to join or leave a conference and to send a message % (datareq) or to receive a message (dataind). % % This conference service protocol has extensively been used for testing software using % Torx. The first paper on this topic is: Formal Test Automation: A Simple Experiment, by % A. Belinfante, J. Feenstra, R.G. de Vries, J. Tretmans, N. Goga, L. Feijs, S. Mauw and % L. Heerink. In: G. Csopaki and S. Dibuz and K. Tarnay, editors, Int. Workshop on Testing % of Communicating Systems XII, Kluwer Academic Publishers, pages: 179 - 196, published in 1999. % % Note: on 13/2/2006 Axel Belinfante detected a flaw in the datatypes by testing the % specification in mCRL2 against the one in mCRL. %******************************************************************************************** %*********************** standard definitions *********************************************** %******************************************************************************************** map IsUDPaddrIn:UDPAddress # List(CFPartner) -> Bool; var c1,c2:UDPAddress; s,s': List(CFPartner); u:UserTitle; f,f':CFPartner; eqn IsUDPaddrIn(c1,[])=false; IsUDPaddrIn(c1,Pair(c2,u)|>s)= c1==c2 || IsUDPaddrIn(c1,s); sort Queue = List(CFsp); sort UDPspQ=List(UDPsp); sort UOQ=List(CFsp); sort LOQ=List(LOQItem); sort Pair=struct Pair(fst:CFsp,snd:PDU); %******************************************************************************************** %************************ type definitions ************************************************** %******************************************************************************************** sort PduType = struct J | A | L | D; sort UserTitleOpt = struct noUt | yesUt(UtOf:UserTitle); sort ConfIdentOpt = struct noCi | yesCi(CiOf:ConfIdent); %******************************************************************************************** %****************** Definition of Service Primitives and PDUs ******************************* %******************************************************************************************** sort CFsp = struct datareq(MsgOf1:DataField)?IsDataReq | dataind(UtOf1:UserTitle,MsgOf2:DataField)?IsDataInd | join(UtOf2:UserTitle,CiOf:ConfIdent)?IsJoin | leave?IsLeave; map UtOf:CFsp -> UserTitle; MsgOf:CFsp -> DataField; var u:CFsp; eqn UtOf(u)=if(IsDataInd(u),UtOf1(u),UtOf2(u)); MsgOf(u)=if(IsDataReq(u),MsgOf1(u),MsgOf2(u)); % definition of PDUs and operations on these PDUs sort PDU = struct PDU_J(UtOf_J:UserTitle,CiOf_J:ConfIdent)?IsPDU_J | PDU_A(UtOf_A:UserTitle,CiOf_A:ConfIdent)?IsPDU_A | PDU_L(UtOf_L:UserTitle,CiOf_L:ConfIdent)?IsPDU_L | PDU_D(DataFieldLenOf:DataFieldLen,DataFieldOf:DataField)?IsPDU_D; map TypeOf : PDU -> PduType; CiOf : PDU -> ConfIdent; UtOf : PDU -> UserTitle; var u:UserTitle; c:ConfIdent; df:DataField; dl:DataFieldLen; p : PDU; eqn TypeOf(PDU_J(u, c)) = J; TypeOf(PDU_L(u, c)) = L; TypeOf(PDU_A(u, c)) = A; TypeOf(PDU_D(dl, df)) = D; CiOf(p)=if(IsPDU_J(p),CiOf_J(p), if(IsPDU_A(p),CiOf_A(p), if(IsPDU_L(p),CiOf_L(p),CiOf_L(p)))); UtOf(p)=if(IsPDU_J(p),UtOf_J(p), if(IsPDU_A(p),UtOf_A(p), if(IsPDU_L(p),UtOf_L(p),UtOf_L(p)))); % definition of conference service SPs and operations on these SPs sort UDPsp = struct udp_datareq(DestOf1:UDPAddress,PduOf1:PDU)?IsDataReq | udp_dataind(DestOf2:UDPAddress,PduOf2:PDU)?IsDataInd; map SrcOf,DestOf : UDPsp -> UDPAddress; PduOf : UDPsp -> PDU; var sp:UDPsp; eqn DestOf(sp)=if(IsDataReq(sp),DestOf1(sp),DestOf2(sp)); SrcOf(sp)=DestOf(sp); PduOf(sp)=if(IsDataReq(sp),PduOf1(sp),PduOf2(sp)); %******************************************************************************************** %***************************** Sets and Queues ********************************************** %******************************************************************************************** % definition of an address-pair consists of a CFAddress and a Nat sort AddressPair=struct Pair(CFaddrOf:CFAddress,UDPaddrOf:UDPAddress); % definition of a conference partner set item: pair of Nat and user title sort CFPartner=struct Pair(AddrOf:UDPAddress,UtOf:UserTitle); map RemovePartnerByUDPaddr : UDPAddress# List(CFPartner) -> List(CFPartner); IsIn : CFPartner # List(CFPartner) -> Bool; var a, b : UDPAddress; c,c' : CFPartner; xs : List(CFPartner); u:UserTitle; eqn RemovePartnerByUDPaddr(a, Pair(b, u)|>xs)= if(a==b,xs,Pair(b,u)|>RemovePartnerByUDPaddr(a, xs)); RemovePartnerByUDPaddr(a, []) = []; IsIn(c,[])=false; IsIn(c,c'|>xs)= c==c' || IsIn(c,xs); %******************************************************************************************** sort LOQItem=struct Pair(AddrSetOf:List(UDPAddress),PduOf:PDU); map MakeRemoteAddrSet : List(CFPartner) -> List(UDPAddress); MakeRemoteAddrSet2 : UDPAddress # List(AddressPair) -> List(UDPAddress); var u:UDPAddress; x:CFPartner; xs:List(CFPartner); y:AddressPair; ys:List(AddressPair); eqn MakeRemoteAddrSet(x|>xs) = AddrOf(x)|>MakeRemoteAddrSet(xs); MakeRemoteAddrSet([]) = []; MakeRemoteAddrSet2(u, []) = []; MakeRemoteAddrSet2(u, y|>ys) = if(u==UDPaddrOf(y), MakeRemoteAddrSet2(u, ys), UDPaddrOf(y)|>MakeRemoteAddrSet2(u, ys)); %********************************************************************************************* %************************* constant definitions for simulation only ************************** %********************************************************************************************* sort DataField = struct m1 | m2 | m3 | m4; sort UserTitle = struct ut_A | ut_B | ut_C | ut_D; sort ConfIdent = struct ci_one | ci_two; sort DataFieldLen = struct l_1; sort CFAddress = struct cf4 | cf2 | cf3 | cf1; sort UDPAddress = struct udp1 | udp2 | udp3; map ConfigurationSet : List(AddressPair); ChooseConfig : List(AddressPair) -> AddressPair; IsIn : UDPAddress # List(UDPAddress) -> Bool; Remove : UDPAddress # List(UDPAddress) -> List(UDPAddress); var r : List(AddressPair); ap : AddressPair; xs : List(UDPAddress); u,u' : UDPAddress; eqn ChooseConfig(ap|>r) = ap; ConfigurationSet = [Pair(cf1, udp1), Pair(cf2, udp2), Pair(cf3, udp3)]; IsIn(u,[])=false; IsIn(u,u'|>xs)= u==u' || IsIn(u,xs); Remove(u,[])=[]; Remove(u,u'|>xs)= if(u==u',xs,u'|>Remove(u,xs)); map TestSet : List(UDPAddress); eqn TestSet = [udp1,udp2,udp3]; %*************************************************************************************** %**************************** End of Data Type Part ************************************ %*************************************************************************************** act UTin_buffer, UTin_LSI, UTin : CFAddress # CFsp; CFSAP_out_UpperLSI, CFSAP_out_ProtocolFunctions, UTout : CFAddress # CFsp; LTin_UDPLC_LT, LTin_UDP, LTin_LowerTestContext : UDPAddress # UDPsp; LTout_UDPLC_LT, LTout_UDP, LTout_LowerTestContext : UDPAddress # UDPsp; CFSAP_in_UpperLSI, CFSAP_in_ProtocolFunctions, Xin_Buffer, Xin, tempabXin, tempacXin : CFAddress # CFsp; Yin_UDPLC_Y, Yin_UDP, udp_in_LowerLSI , udp_in_ProtocolFunctions, tempabYin, tempacYin, tempadYin, tempbcYin, tempbdYin, tempcdYin, tempabcYin, tempabdYin, tempbcdYin, Yin : UDPAddress # UDPsp; Yout_UDPLC_Y , Yout_UDP, udp_out_LowerLSI , udp_out_ProtocolFunctions, tempabYout, tempacYout, tempadYout, tempbcYout, tempbdYout, tempcdYout, tempabcYout, tempabdYout, tempbcdYout, Yout : UDPAddress # UDPsp; udp_in,udp_out : UDPAddress # UDPsp; CFSAP_in, CFSAP_out : CFAddress # CFsp; init rename( { LTout_LowerTestContext->udp_out, LTin_LowerTestContext->udp_in, UTin->CFSAP_in, UTout->CFSAP_out}, SystemUnderTest); proc SystemUnderTest= hide({Xin, Yin, Yout}, allow({Xin, Yin, Yout, UTin, UTout, LTin_LowerTestContext, LTout_LowerTestContext}, comm({ UTin_buffer | UTin_LSI -> UTin, CFSAP_out_UpperLSI | CFSAP_out_ProtocolFunctions -> UTout, LTin_UDPLC_LT | LTin_UDP -> LTin_LowerTestContext, LTout_UDPLC_LT | LTout_UDP -> LTout_LowerTestContext, CFSAP_in_UpperLSI | CFSAP_in_ProtocolFunctions | Xin_Buffer -> Xin, Yin_UDPLC_Y | Yin_UDP | udp_in_LowerLSI | udp_in_ProtocolFunctions -> Yin, Yout_UDPLC_Y | Yout_UDP | udp_out_LowerLSI | udp_out_ProtocolFunctions -> Yout}, UpperTestContext|| ConferenceProtocolEntity(cf1, udp1)|| LowerTestContext ))); proc ConferenceProtocolEntity(myCFaddr:CFAddress, myUDPaddr:UDPAddress)= UpperLSI(myCFaddr)|| LowerLSI(myUDPaddr)|| ProtocolFunctions([], [], [], noUt, noCi, myCFaddr, myUDPaddr); proc UpperLSI(myCFaddr:CFAddress)= sum addr:CFAddress,sp:CFsp.(IsJoin(sp) && myCFaddr==addr)-> CFSAP_in_UpperLSI(addr,sp).EngagedUpperLSI(myCFaddr); proc EngagedUpperLSI(myCFaddr:CFAddress)= sum addr:CFAddress, sp:CFsp.(IsDataReq(sp) && myCFaddr==addr)-> CFSAP_in_UpperLSI(addr,sp).EngagedUpperLSI(myCFaddr)+ sum addr:CFAddress, sp:CFsp.(IsDataInd(sp) && myCFaddr==addr)-> CFSAP_out_UpperLSI(addr,sp).EngagedUpperLSI(myCFaddr)+ sum addr:CFAddress, sp:CFsp.(IsLeave(sp) && myCFaddr==addr) -> CFSAP_in_UpperLSI(addr,sp).IdleUpperLSI(myCFaddr); proc IdleUpperLSI(myCFaddr:CFAddress)= sum addr:CFAddress, sp:CFsp.(IsDataInd(sp) && myCFaddr==addr)-> CFSAP_out_UpperLSI(addr,sp).EngagedUpperLSI(myCFaddr)+ sum addr:CFAddress, sp:CFsp.(IsJoin(sp) && myCFaddr==addr)-> CFSAP_in_UpperLSI(addr,sp).EngagedUpperLSI(myCFaddr); proc LowerLSI(myUDPaddr:UDPAddress)= sum addr:UDPAddress, sp:UDPsp.(IsDataInd(sp) && myUDPaddr==addr)-> udp_in_LowerLSI(addr,sp).LowerLSI(myUDPaddr)+ sum addr:UDPAddress, sp:UDPsp.(IsDataReq(sp) && myUDPaddr==addr)-> udp_out_LowerLSI(addr,sp).LowerLSI(myUDPaddr); proc ProtocolFunctions(Qyo:LOQ, Qxo:UOQ, CPs:List(CFPartner), myUt:UserTitleOpt, myCi:ConfIdentOpt, myCFaddr:CFAddress, myUDPaddr:UDPAddress)= sum addr:CFAddress, sp:CFsp. (addr==myCFaddr && !IsDataInd(sp))->CFSAP_in_ProtocolFunctions(addr,sp). ( IsJoin(sp)-> ( (MakeRemoteAddrSet2(myUDPaddr, ConfigurationSet)!=[])-> ProtocolFunctions(Pair(MakeRemoteAddrSet2(myUDPaddr, ConfigurationSet), PDU_J(UtOf(sp), CiOf(sp)))|>Qyo,Qxo, CPs, yesUt(UtOf(sp)), yesCi(CiOf(sp)), myCFaddr, myUDPaddr) <> ProtocolFunctions(Qyo, Qxo, CPs, yesUt(UtOf(sp)), yesCi(CiOf(sp)), myCFaddr, myUDPaddr) )+ IsLeave(sp)-> ( (MakeRemoteAddrSet(CPs)!=[])-> ProtocolFunctions(Pair(MakeRemoteAddrSet(CPs),PDU_L(UtOf(myUt), CiOf(myCi)))|>Qyo, Qxo, [], noUt, noCi, myCFaddr, myUDPaddr) <> ProtocolFunctions(Qyo, Qxo, [], noUt, noCi, myCFaddr, myUDPaddr) ) + IsDataReq(sp)-> ( (MakeRemoteAddrSet(CPs)!=[])-> ProtocolFunctions(Pair(MakeRemoteAddrSet(CPs), PDU_D(l_1, MsgOf(sp)))|>Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) <> ProtocolFunctions(Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) ) ) + sum addr:UDPAddress, sp:UDPsp. (IsDataInd(sp) && addr==myUDPaddr) -> udp_in_ProtocolFunctions(addr,sp). ( (myCi==noCi) -> ProtocolFunctions(Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) + ( TypeOf(PduOf(sp))==J && myCi!=noCi)-> ( (CiOf(PduOf(sp))==CiOf(myCi))-> ( IsUDPaddrIn(SrcOf(sp),CPs)-> ProtocolFunctions(Pair([SrcOf(sp)], PDU_A(UtOf(myUt), CiOf(myCi)))|>Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) <> ProtocolFunctions(Pair([SrcOf(sp)],PDU_A(UtOf(myUt), CiOf(myCi)))|>Qyo, Qxo, Pair(SrcOf(sp),UtOf(PduOf(sp)))|>CPs, myUt, myCi, myCFaddr, myUDPaddr) ) <> ProtocolFunctions(Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) )+ ( TypeOf(PduOf(sp))==L && myCi!=noCi)-> ( (CiOf(PduOf(sp))==CiOf(myCi))-> ProtocolFunctions(Qyo, Qxo, RemovePartnerByUDPaddr(SrcOf(sp), CPs), myUt, myCi, myCFaddr, myUDPaddr) <> ProtocolFunctions(Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) )+ ( TypeOf(PduOf(sp))==A && myCi!=noCi)-> ( (CiOf(PduOf(sp))==CiOf(myCi))-> ( IsUDPaddrIn(SrcOf(sp),CPs)-> ProtocolFunctions(Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) <> ProtocolFunctions(Qyo, Qxo, Pair(SrcOf(sp), UtOf(PduOf(sp)))|>CPs, myUt, myCi, myCFaddr, myUDPaddr) ) <> ProtocolFunctions(Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) )+ ( TypeOf(PduOf(sp))==D && myCi!=noCi)-> ( (IsUDPaddrIn(SrcOf(sp),CPs))-> ( sum p:CFPartner. %receive from a conference partner (IsIn(p,CPs) && AddrOf(p)==SrcOf(sp))-> ProtocolFunctions(Qyo, dataind(UtOf(p), DataFieldOf(PduOf(sp)))|>Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) ) <> ProtocolFunctions(Pair([SrcOf(sp)], PDU_J(UtOf(myUt), CiOf(myCi)))|>Qyo, Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) ) ) + (Qxo!=[])-> CFSAP_out_ProtocolFunctions(myCFaddr, rhead(Qxo)). ProtocolFunctions(Qyo, rtail(Qxo), CPs, myUt, myCi, myCFaddr, myUDPaddr)+ (Qyo!=[])-> ( sum dest:UDPAddress. IsIn(dest,AddrSetOf(rhead(Qyo)))-> udp_out_ProtocolFunctions(myUDPaddr,udp_datareq(dest, PduOf(rhead(Qyo)))). ( (Remove(dest, AddrSetOf(rhead(Qyo)))==[])-> ProtocolFunctions(rtail(Qyo), Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) <> ProtocolFunctions(rtail(Qyo)<|Pair(Remove(dest, AddrSetOf(rhead(Qyo))), PduOf(rhead(Qyo))), Qxo, CPs, myUt, myCi, myCFaddr, myUDPaddr) ) ); proc LowerTestContext= (UDPLC_Y(udp1)||UDPLC_LT(udp2, udp1)||UDPLC_LT(udp3, udp1)) || (UDP(udp1, [])||UDP(udp2, [])||UDP(udp3, [])); proc UDP(dest_addr:UDPAddress, q:UDPspQ)= sum sp:UDPsp. (IsDataReq(sp) && DestOf(sp)==dest_addr && udp1!=dest_addr)-> Yout_UDP(udp1,sp).UDP(dest_addr, udp_dataind(udp1, PduOf(sp))|>q)+ sum addr:UDPAddress, sp:UDPsp. (IsDataReq(sp) && DestOf(sp)==dest_addr && udp1==dest_addr && addr!=udp1)-> LTin_UDP(addr,sp).UDP(dest_addr, udp_dataind(addr, PduOf(sp))|>q)+ ((q!=[]) && dest_addr==udp1)-> Yin_UDP(dest_addr,rhead(q)).UDP(dest_addr, rtail(q))+ ((q!=[]) && dest_addr!=udp1)-> LTout_UDP(dest_addr,rhead(q)).UDP(dest_addr, rtail(q)); proc UDPLC_LT(an_addr:UDPAddress, dest_addr:UDPAddress)= sum addr:UDPAddress, sp:UDPsp. (IsDataReq(sp) && addr==an_addr && DestOf(sp)==dest_addr)-> LTin_UDPLC_LT(addr,sp).UDPLC_LT(an_addr, dest_addr)+ sum addr:UDPAddress, sp:UDPsp. (IsDataInd(sp) && addr==an_addr && SrcOf(sp)==dest_addr)-> LTout_UDPLC_LT(addr,sp).UDPLC_LT(an_addr, dest_addr); proc UDPLC_Y(an_addr:UDPAddress)= sum addr:UDPAddress, sp:UDPsp. (IsDataReq(sp) && addr==an_addr)-> Yout_UDPLC_Y(addr,sp).UDPLC_Y(an_addr)+ sum addr:UDPAddress, sp:UDPsp. (IsDataInd(sp) && addr==an_addr)-> Yin_UDPLC_Y(addr,sp).UDPLC_Y(an_addr); proc UpperTestContext=InputUpperLSI(cf1)|| Buffer(cf1, []); proc Buffer(my_addr:CFAddress, q:UOQ)= sum sp:CFsp. (IsJoin(sp) || IsLeave(sp) || IsDataReq(sp))-> UTin_buffer(my_addr,sp).Buffer(my_addr, sp|>q)+ (q!=[])-> Xin_Buffer(my_addr,rhead(q)).Buffer(my_addr, rtail(q)); proc InputUpperLSI(myCFaddr:CFAddress)= sum addr:CFAddress, sp:CFsp. (IsJoin(sp) && myCFaddr==addr)-> UTin_LSI(addr,sp).NextInputUpperLSI(myCFaddr); proc NextInputUpperLSI(myCFaddr:CFAddress)= sum addr:CFAddress, sp:CFsp. (IsDataReq(sp) && myCFaddr==addr)-> UTin_LSI(addr,sp).NextInputUpperLSI(myCFaddr)+ sum addr:CFAddress, sp:CFsp. (IsLeave(sp) && myCFaddr==addr)->UTin_LSI(addr,sp). ( sum addr:CFAddress, sp:CFsp. (IsJoin(sp) && myCFaddr==addr)-> UTin_LSI(addr,sp).NextInputUpperLSI(myCFaddr)); mcrl2-201409.0/examples/academic/commprot/run.py000770 001750 001750 00000000310 12370120074 021710 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v commprot.mcrl2 commprot.lps') os.system('lps2pbes -v -f nodeadlock.mcf commprot.lps commprot.nodeadlock.pbes') os.system('pbes2bool -v commprot.nodeadlock.pbes') mcrl2-201409.0/examples/academic/goback/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022716 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/goback/run.py000770 001750 001750 00000000276 12370120074 021311 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v goback.mcrl2 goback.lps') os.system('lps2pbes -v -f nodeadlock.mcf goback.lps goback.nodeadlock.pbes') os.system('pbes2bool -v goback.nodeadlock.pbes') mcrl2-201409.0/examples/academic/goback/goback.mcrl2000770 001750 001750 00000000640 12370120074 022315 0ustar00outisoutis000000 000000 % This is a process with states 1,...,N, where % each state i has transitions to all states 1,...,i+1. % This means its transitions go maximally back to % already detected states, and only one transition % goes to a new state (i.e. i+1) when doing a breadth % first search. % Jan Friso Groote, September 3, 2006. act a; map N:Pos; eqn N=1000; proc X(i:Pos)=sum j:Pos.(j<=i+1 && j<=N)->a.X(j)<>delta; init X(1); mcrl2-201409.0/examples/academic/food_distribution/run.py000770 001750 001750 00000001011 12370120074 023575 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v food_package.mcrl2 food_package.lps') os.system('lpssuminst food_package.lps food_package.lpssuminst.lps') os.system('lps2pbes -v -f sustained_delivery.mcf food_package.lpssuminst.lps sustained_delivery.pbes') os.system('pbesconstelm -ve sustained_delivery.pbes sustained_delivery.pbesconstelm.pbes') # If possible use -rjittyc below, which does work on linux and mac, and not on windows, as # the generated bes is huge. os.system('pbes2bool -v sustained_delivery.pbesconstelm.pbes') mcrl2-201409.0/examples/academic/food_distribution/food_package.mcrl2000770 001750 001750 00000007653 12370120074 026004 0ustar00outisoutis000000 000000 % This model describes an exercise for the course Automatic Reasoning, % formulated by Hans Zantema. % Three non-self-supporting villages A, B and C in the middle of nowhere % consume one food package each per time unit. The required food packages % are delivered by a truck, having a capacity of 300 or 320 food packages. The loca- % tions of the villages are given in the following picture, in which the numbers % indicate the distance, more precisely, the number of time units the truck % needs to travel from one village to another, including loading or delivering. % The truck has to pick up its food packages at location S containing an un- % bounded supply. The villages only have a limited capacity to store food % packages: for A and B this capacity is 120, for C it is 200. Initially, the % truck is in S and is fully loaded, and in A, B and C there are 50, 40 and 150 % food packages, respectively. % % B % / | \ % 21 | 37 % / | \ % S 17 C % \ | / % 29 | 32 % \ | / % A % % % (a) Show that it is impossible to deliver food packages in such a way % that forever each of the villages may consume one food package each per % time unit. % (b) Show that this is possible if the capacity of the truck is increased % to 320 food packages. (Note that a finite graph contains an infinite path % starting in a node v if and only if there is a path from v to a node w for % which there is a non-empty path from w to itself.) sort Place = struct S | A | B | C; map TRUCK_CAPACITY:Pos; eqn TRUCK_CAPACITY=320; % If 300 starvation must take place. If 320 sustained delivery without starvation is possible. act starve; moveS,moveA,moveB,moveC; proc P(villageA,villageB,villageC,truck:Int,where_is_truck:Place)= (where_is_truck == S) -> ((villageA<29 || villageB<21 || villageC<58) -> starve.delta <> (sum unload:Nat.(42<=unload && unload<=120-villageB+21 && unload<=141) -> moveB.P(villageA-21,villageB-21+unload,villageC-21,TRUCK_CAPACITY-unload,B)+ sum unload:Nat.(58<=unload && unload<=120-villageA+29 && unload<=149) -> moveA.P(villageA-29+unload,villageB-29,villageC-29,TRUCK_CAPACITY-unload,A)))+ (where_is_truck == B) -> ((villageA<17 || villageC<37) -> starve.delta <> (moveS.P(villageA-21,villageB-21,villageC-21,0,S)+ sum unload:Nat.(58<=unload && unload<=120-villageA+17 && unload<=truck && unload<=137) -> moveA.P(villageA-17+unload,villageB-17,villageC-17,truck-unload,A)+ sum unload:Nat.(116<=unload && unload<=200-villageC+37 && unload<=truck && unload<=237) -> moveC.P(villageA-37,villageB-37,villageC-37+unload,truck-unload,C)))+ (where_is_truck == A) -> ((villageB<17 || villageC<32) -> starve.delta <> (moveS.P(villageA-29,villageB-29,villageC-29,0,S)+ sum unload:Nat.(42<=unload && unload<=120-villageB+17 && unload<=truck && unload<=137) -> moveB.P(villageA-17,villageB-17+unload,villageC-17,truck-unload,B)+ sum unload:Nat.(118<=unload && unload<=200-villageC+32 && unload<=truck && unload<=232) -> moveC.P(villageA-32,villageB-32,villageC-32+unload,truck-unload,C)))+ (where_is_truck == C) -> ((villageA<32 || villageB<37) -> starve.delta <> (sum unload:Nat.(42<=unload && unload<=120-villageB+37 && unload<=truck && unload<=157) -> moveB.P(villageA-37,villageB-37+unload,villageC-37,truck-unload,B)+ sum unload:Nat.(58<=unload && unload<=120-villageA+32 && unload<=truck && unload<=152) -> moveA.P(villageA-32+unload,villageB-32,villageC-32,truck-unload,A))); init P(50,40,150,0,S); % A formula modelling sustained delivery is % % nu X.X && [starve]false mcrl2-201409.0/examples/academic/food_distribution/sustained_delivery.mcf000770 001750 001750 00000000250 12370120074 027014 0ustar00outisoutis000000 000000 % This formula expresses that sustained delivery of foodpackages is possible, % where no village will ever starve. nu X.X && [starve]false mcrl2-201409.0/examples/academic/trains/trains.mcrl2000770 001750 001750 00000014604 12370120074 022446 0ustar00outisoutis000000 000000 % This file describes several mostly incorrect algorithms to establish mutual exclusion. % The correct version is also known as Peterson's mutual exclusion algorithm. % For illustrative purposes the algorithm has been shaped as a pair of trains % that must enter a common piece of track: % % ------------>>-Train_p->>--------------------- % / --------------------<<-Train_q-<<------------- \ % / / \ \ % | |q0 | | % | | | |p0 % | | | | % \ \ q1 q2 / / % \ --- --- / % ---\-------------------------------------/--- % p2 leave_p enter_p p1 % enter_q leave_q % % There are two trains, Train_p and Train_q, which must enter the common piece % of track. Train p first passes detector p0 and p1. After that, it must wait % for a semaphore Guard_p to allow the train to pass. It enters the critical % section using an enter_p action, and leaves it using a leave_p action. Using % a detector p2 train p indicates that it has left the critical section. % Train q drives in the other direction and passes detectors q0, q1 and q2 respectively. % Moreover, it passes guard Guard q and carries out enter_q and leave_q to % indicate that it enters and leaves the critical section. % % The description below provides four different mutual exclusion algorithms, % which can be indicated by the variable Invariant. % Variant 1 is a strict alternation algorithm (access is strictly alternating) % Variant 2 is the safe sluice (with total deadlock) % Variant 3 is a correct version of Peterson's algorithm % Variant 4 is a wrong version of Peterson's algorithm (no mutual exclusion) % % For each train there is a process and an auxiliary process (Train_p and Guard_p, % Train_q and Guard_q). Furthermore there are three variables. A common boolean variable % V and boolean variables Xp and Xq that can only be set by p, resp. q. % % In variant 1 the variable V is the only one that is used to determine access to % the critical section. If V is true, train p can enter, and if V is false, train % q can enter. Using the actions p1 and q1 trains indicate that they have left % the critical section allowing entrance of the other train. What can nicely be seen % when generating the reduced state space of this example, is that trains can only % alternatingly access the critical region, and no train can access the critical % region twice without the other having been in the critical region in between. % Note the initial tau's that determine which train must enter the critical region % first. The commands to generate the state space are (set Variant below to 1): % mcrl22lps trains.mcrl2 trains.lps % lps2lts trains.lps trains.svc % ltsconvert -b trains.svc trainsr.svc % ltsgraph trainsr.svc % % In variant 2 (safe sluice) access to the critical region is regulated through the variables % Xp and Xq. Trains indicate their desire to enter the critical region through % p0 (resp. q0) setting Xp (resp. Xq) to true. In the guard they check whether % the other train did not indicate the desire to enter the critical region. If % so, the train can safely enter (i.e. pass the Guard). % There is an awkward situation in this case. If both trains indicate their % desire to enter the critical region simultaneously, they both block the entrance % for the other train, and the whole system will end up in deadlock. This is also % clearly visible in the reduced state space. Another way to obtain the deadlock % and a trace to it, is by using lps2lts -td trains.lps. It is also interesting % to try to find the deadlock situation using the simulator (xsim). The deadlock % can be reached in a very small number of steps. It turns out to be very hard % to find using the simulator, if it is not known where the deadlock resides. % % The third variant is Peterson's mutual exclusion protocol. It is a combination % of both access mechanisms above. On the one hand processes can enter through % the mechanism of the safe sluice, where trains indicate their desire to enter. % On top of that there is the variable V that guarantees alternated access if % both trains want to enter. This yields a correct, deadlockfree protocol. % % In the fourth variant the sensors p1 and p0 are exchanged. This causes the % protocol to be incorrect, as mutual exclusion is not guaranteed anymore. This % on the one hand shows how subtle Peterson's algorithm is. On the other hand % it shows the effectiveness of tools. It is very hard to detect by human reasoning % whether exchanging the detectors is safe. When generating the reduced state % space, it is obvious that it is not safe. act p0, p1, p2, enter_p, leave_p, p0_, p1_, p2_, q0, q1, q2, enter_q, leave_q, q0_, q1_, q2_, set_xp_, set_xq_, set_v_, reset_xp_, reset_xq_, reset_v_; get_xp, get_xq, get_v, get_xp_, get_xq_, get_v_, get_xp__, get_xq__, get_v__ : Bool; map Variant:Pos; eqn Variant=2; proc Train_p= ((Variant==4) -> p1 . p0 <> p0 . p1 ). Guard_p . enter_p . leave_p . p2 . Train_p; Train_q= q0 . q1 . Guard_q . enter_q . leave_q . q2 . Train_q; Guard_p= (Variant!=1) -> get_xq(false)<>delta+ (Variant!=2) -> get_v(true)<>delta; Guard_q= (Variant!=1) -> get_xp(false)<>delta+ (Variant!=2) -> get_v(false)<>delta; Xp(b:Bool)= set_xp_ . Xp(true)+ reset_xp_ . Xp(false)+ get_xp_(b) . Xp(b); Xq(b:Bool)= set_xq_ . Xq(true)+ reset_xq_ . Xq(false)+ get_xq_(b) . Xq(b); V(b:Bool)= set_v_ . V(true)+ reset_v_ . V(false)+ get_v_(b) . V(b); init hide({p0_, p1_, p2_, q0_, q1_, q2_, get_xp__, get_xq__, get_v__}, allow({p0_, p1_, p2_, q0_, q1_, q2_, get_xp__, get_xq__, get_v__, enter_p,leave_p,enter_q,leave_q}, comm({p0 | set_xp_ -> p0_, p1 | reset_v_ -> p1_, p2 | reset_xp_ -> p2_, q0 | set_xq_ -> q0_, q1 | set_v_ -> q1_, q2 | reset_xq_ -> q2_, get_xp | get_xp_ -> get_xp__, get_xq | get_xq_ -> get_xq__, get_v | get_v_ -> get_v__}, Train_p || Train_q || Xp(false) || Xq(false) || V(false)))); examples/academic/trains/infinitely_often_enabled_then_infinitely_often_taken_enter.mcf000770 001750 001750 00000000556 12370120074 034657 0ustar00outisoutis000000 000000 mcrl2-201409.0% Infinitely often enabled means infinitely often taken % Formula from "Modal logics and mu-calculi: an introduction", Bradfield and % Stirling. % % Can be applied to trains.mcrl2 ([true*] nu X. mu Y. nu Z. ([enter_p]X && ([enter_p]false || [!enter_p]Y) && [!enter_p]Z)) && ([true*] nu X. mu Y. nu Z. ([enter_q]X && ([enter_q]false || [!enter_q]Y) && [!enter_q]Z)) mcrl2-201409.0/examples/academic/trains/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022770 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/trains/run.py000770 001750 001750 00000001132 12370120074 021353 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v trains.mcrl2 trains.lps') os.system('lps2pbes -v -f nodeadlock.mcf trains.lps trains.nodeadlock.pbes') os.system('pbes2bool -v trains.nodeadlock.pbes') os.system('lps2pbes -v -f infinitely_often_enable_then_infinitely_often_taken_enter.mcf trains.lps trains.infinitely_often_enable_then_infinitely_often_taken_enter.pbes') os.system('pbes2bool -v trains.infinitely_often_enable_then_infinitely_often_taken_enter.pbes') os.system('lps2pbes -v -f mutual_exclusion.mcf trains.lps trains.mutual_exclusion.pbes') os.system('pbes2bool -v trains.mutual_exclusion.pbes') mcrl2-201409.0/examples/academic/trains/mutual_exclusion.mcf000770 001750 001750 00000000124 12370120074 024264 0ustar00outisoutis000000 000000 [true*](true => mu X . ([enter_q]false && (true || [!leave_p]X))) mcrl2-201409.0/examples/academic/mpsu/mpsu2.mcf000770 001750 001750 00000000446 12370120074 021425 0ustar00outisoutis000000 000000 % This file describes the modal formulas for property 2 used in section % 5.3 of Designing and understanding the behaviour of systems % by J.F. Groote and M.A. Reniers. ([true*.pressStop]mu X.[!motorOff]X) && ([true*.pressStop]mu X.[!releaseBrake]X) && ([true*.pressStop]mu X.[!unlockDock]X) mcrl2-201409.0/examples/academic/mpsu/mpsu4.mcf000770 001750 001750 00000000440 12370120074 021421 0ustar00outisoutis000000 000000 % This file describes the modal formulas for property 4 used in section % 5.3 of Designing and understanding the behaviour of systems % by J.F. Groote and M.A. Reniers. [true*.atInnermost.!(motorLeft||releaseBrake)*.pressUndock] mu X.[!unlockDock && !motorLeft && !releaseBrake]X mcrl2-201409.0/examples/academic/mpsu/mpsu6.mcf000770 001750 001750 00000001314 12370120074 021424 0ustar00outisoutis000000 000000 % This file describes the modal formulas for property 5 used in section % 5.3 of Designing and understanding the behaviour of systems % by J.F. Groote and M.A. Reniers. nu X(b1:Bool=false, b2:Bool=true,b3:Bool=true,b4:Bool=true). ([isDocked]X(true,b2,b3,b4) && [unlockDock]X(false,b2,b3,b4)&& [pressResume]X(b1,true,b3,b4)&& [pressStop]X(b1,false,b3,b4)&& [atOutermost]X(b1,b2,true,b4)&& [motorLeft]X(b1,b2,false,b4)&& [motorOff+motorLeft]X(b1,b2,b3,true)&& [motorRight]X(b1,b2,b3,false)&& (val(b1 && b2 && b3 && b4) => [pressRight] mu Y.[!motorRight && !unlockDock && !pressStop && !atOutermost]Y)) mcrl2-201409.0/examples/academic/mpsu/mpsu5.mcf000770 001750 001750 00000001313 12370120074 021422 0ustar00outisoutis000000 000000 % This file describes the modal formulas for property 5 used in section % 5.3 of Designing and understanding the behaviour of systems % by J.F. Groote and M.A. Reniers. nu X(b1:Bool=false, b2:Bool=true,b3:Bool=true,b4:Bool=true). ([isDocked]X(true,b2,b3,b4) && [unlockDock]X(false,b2,b3,b4)&& [pressResume]X(b1,true,b3,b4)&& [pressStop]X(b1,false,b3,b4)&& [atInnermost]X(b1,b2,true,b4)&& [motorRight]X(b1,b2,false,b4)&& [motorOff+motorRight]X(b1,b2,b3,true)&& [motorLeft]X(b1,b2,b3,false)&& (val(b1 && b2 && b3 && b4) => [pressLeft] mu Y.[!motorLeft && !unlockDock && !pressStop && !atInnermost]Y)) mcrl2-201409.0/examples/academic/mpsu/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022454 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/mpsu/run.py000770 001750 001750 00000001457 12370120074 021051 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v mpsu.mcrl2 mpsu.lps') os.system('lps2pbes -v -f nodeadlock.mcf mpsu.lps mpsu.nodeadlock.pbes') os.system('pbes2bool -v mpsu.nodeadlock.pbes') os.system('lps2pbes -v -f mpsu1.mcf mpsu.lps mpsu.mpsu1.pbes') os.system('pbes2bool -v mpsu.mpsu1.pbes') os.system('lps2pbes -v -f mpsu2.mcf mpsu.lps mpsu.mpsu2.pbes') os.system('pbes2bool -v mpsu.mpsu2.pbes') os.system('lps2pbes -v -f mpsu3.mcf mpsu.lps mpsu.mpsu3.pbes') os.system('pbes2bool -v mpsu.mpsu3.pbes') os.system('lps2pbes -v -f mpsu4.mcf mpsu.lps mpsu.mpsu4.pbes') os.system('pbes2bool -v mpsu.mpsu4.pbes') os.system('lps2pbes -v -f mpsu5.mcf mpsu.lps mpsu.mpsu5.pbes') os.system('pbes2bool -v mpsu.mpsu5.pbes') os.system('lps2pbes -v -f mpsu6.mcf mpsu.lps mpsu.mpsu6.pbes') os.system('pbes2bool -v mpsu.mpsu6.pbes') mcrl2-201409.0/examples/academic/mpsu/mpsu.mcrl2000770 001750 001750 00000003250 12370120074 021611 0ustar00outisoutis000000 000000 % This file describes a controller for a simplified Movable Patient % Support Unit. It is described in Fokkink, Groote and Reniers, % Modelling reactive systems. % % Jan Friso Groote, September, 2006. sort Mode = struct Normal | Emergency ; MotorStatus = struct moveleft | moveright | stopped ; act pressStop, pressResume, pressUndock, pressLeft, pressRight, motorLeft, motorRight, motorOff, applyBrake, releaseBrake, isDocked, unlockDock, atInnermost, atOutermost; proc Controller(m:Mode,docked,rightmost,leftmost:Bool,ms:MotorStatus)= pressStop.releaseBrake.motorOff.Controller(Emergency,docked,rightmost,leftmost,ms)+ pressResume.Controller(Normal,docked,rightmost,leftmost,ms)+ pressUndock. (docked && rightmost) -> applyBrake.unlockDock.Controller(m,false,rightmost,leftmost,ms) <> Controller(m,docked,rightmost,leftmost,ms)+ pressLeft. (docked && ms!=moveleft && !leftmost && m==Normal) -> releaseBrake.motorLeft. Controller(m,docked,false,leftmost,moveleft) <> Controller(m,docked,rightmost,leftmost,ms)+ pressRight. (docked && ms!=moveright && !rightmost && m==Normal) -> releaseBrake.motorRight. Controller(m,docked,rightmost,false,moveright) <> Controller(m,docked,rightmost,leftmost,ms)+ isDocked.Controller(m,true,rightmost,leftmost,ms)+ atInnermost.motorOff.applyBrake.Controller(m,docked,true,false,stopped)+ atOutermost.motorOff.applyBrake.Controller(m,docked,false,true,stopped); init Controller(Normal,true,false,false,stopped); mcrl2-201409.0/examples/academic/mpsu/mpsu1.mcf000770 001750 001750 00000000661 12370120074 021423 0ustar00outisoutis000000 000000 % This file describes the modal formulas for property 1 used in section % 5.3 of Designing and understanding the behaviour of systems % by J.F. Groote and M.A. Reniers. [!applyBrake*.unlockDock]false && [!atOutermost*.unlockDock]false && [!motorOff*.unlockDock]false && [true*.releaseBrake.!applyBrake*.unlockDock]false && [true*.motorLeft.!atOutermost*.unlockDock]false && [true*.(motorLeft+motorRight).!motorOff*.unlockDock]false mcrl2-201409.0/examples/academic/mpsu/mpsu3.mcf000770 001750 001750 00000000335 12370120074 021423 0ustar00outisoutis000000 000000 % This file describes the modal formulas for property 3 used in section % 5.3 of Designing and understanding the behaviour of systems % by J.F. Groote and M.A. Reniers. [true*.(atOutermost+atInnermost)]mu X.[!motorOff]X mcrl2-201409.0/examples/academic/parallel/parallel.mcrl2000770 001750 001750 00000000326 12370120074 023232 0ustar00outisoutis000000 000000 % This process consists of 3 parallel processes % that iteratively carry out 10 consequtive actions. % Jan Friso Groote, September 3, 2006. act a,b,c,d,e,f,g,h,i,j; proc X=a.b.c.d.e.f.g.h.i.j.X; init X||X||X; mcrl2-201409.0/examples/academic/parallel/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 023264 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/parallel/run.py000770 001750 001750 00000000501 12370120074 021646 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v parallel.mcrl2 parallel.lps') os.system('lps2pbes -v -f nodeadlock.mcf parallel.lps parallel.nodeadlock.pbes') os.system('pbes2bool -v parallel.nodeadlock.pbes') # The following creates state space, and stores trace to deadlock. os.system('lps2lts -v -Dt parallel.lps parallel.aut') mcrl2-201409.0/examples/academic/leader/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022724 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/leader/run.py000770 001750 001750 00000001312 12370120074 021307 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -nv leader.mcrl2 leader.lps') os.system('lps2pbes -v -f nodeadlock.mcf leader.lps leader.nodeadlock.pbes') os.system('pbes2bool -v leader.nodeadlock.pbes') # This indicates the size of the non-reduces state space os.system('lps2lts -v leader.lps') # Find and eliminate the constants representing process id's os.system('lpsconstelm -v leader.lps temp.lps') # Find confluent taus and rename these to ctau. The flag -o enables induction on # lists, which is necessary to prove confluence os.system('lpsconfcheck -o temp.lps temp1.lps') # This shows the dramatically reduced statespace, generated by giving priority # to ctaus. os.system('lps2lts -vcctau temp1.lps temp1.svc') mcrl2-201409.0/examples/academic/leader/leader.mcrl2000770 001750 001750 00000005200 12370120074 022326 0ustar00outisoutis000000 000000 % This process contains a very simple leader election protocol % in a ring topology. Processes have initial numbers that are sent % around in the ring. Each process let values higher than their % own pass, and block values smaller than their own. If a process % receives its own initial number, it has the highest number, and % it must be the leader. More efficient versions of this protocol % exist, such as the Dolev, Klawe and Rodeh leader election protocol. % An important feature of this protocol is that the links between % the nodes are modelled by unbounded queues. As processes work in % parallel, the number of states of this protocol is exponential % in the number of processes. However, applying confluence will % reduce this number back to a linear number. As a consequence % rings of hundreds of nodes can be verified. % The following commands illustrate how to effectively generate % the state space using confluence reduction. % mcrl22lps -nv leader.mcrl2 leader.lps % lps2lts -v leader.lps // This indicates the % // size of the non-reduced % // state space % lpsconstelm -v leader.lps temp.lps // find and eliminate the % // constants representing % // process id's % lpsconfcheck -o temp.lps temp1.lps // find confluent tau's % // and rename these to ctau's. % // The flag -o enables induction % // on lists, which is necessary % // to prove confluence % lps2lts -vcctau temp1.lps temp1.svc // This shows the dramatically % // reduced statespace, generated % // by giving priority to ctau's % Jan Friso Groote (28/12/2006) map N:Pos; f:Pos->Pos; var n:Pos; eqn N=5; f(n)=(7*n mod N)+1; act rN,sN,rQ,sQ,c : Pos#Pos; leader; proc N(i:Pos,v:Pos)=sN((i mod N)+1,v).M(i,v); M(i:Pos,v:Pos)= sum w:Pos.rN(i,w). (w==v) -> leader.delta <> (w sN((i mod N)+1,w).M(i,v) <> M(i,v); proc Q(i:Pos,q:List(Pos))= sum w:Pos.rQ(i,w).Q(i,w|>q)+ (q!=[]) -> sQ(i,rhead(q)).Q(i,rtail(q))<>delta; init hide({c}, allow({c,leader}, comm({rN|sQ->c, sN|rQ->c}, N(1,f(1)) || Q(1,[]) || N(2,f(2)) || Q(2,[]) || N(3,f(3)) || Q(3,[]) || N(4,f(4)) || Q(4,[]) || N(5,f(5)) || Q(5,[])))); mcrl2-201409.0/examples/academic/scheduler/nodeadlock.mcf000770 001750 001750 00000000224 12370120075 023447 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/scheduler/run.py000770 001750 001750 00000001023 12370120075 022031 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v scheduler.mcrl2 scheduler.lps') os.system('lps2pbes -v -f nodeadlock.mcf scheduler.lps scheduler.nodeadlock.pbes') os.system('pbes2bool -v scheduler.nodeadlock.pbes') os.system('lps2pbes -v -f infinitely_often_enabled_then_infinitely_often_taken_a.mcf scheduler.lps scheduler.infinitely_often_enabled_then_infinitely_often_taken_a.pbes') # Heavily used expansion of universal quantifiers os.system('pbes2bool -v -rjittyc scheduler.infinitely_often_enabled_then_infinitely_often_taken_a.pbes') mcrl2-201409.0/examples/academic/scheduler/scheduler.mcrl2000770 001750 001750 00000002103 12370120075 023572 0ustar00outisoutis000000 000000 % This is a specification of Milner's well known scheduler % that can already be found in Milner's famous Lecture Note in Computer Science % 92, A Calculus of Communicating Systems, Springer, 1980. act a,b,t,tcomm:Nat; proc Cycler(i:Nat,n:Pos) = t(i).a(i). (t((i+1) mod n).b(i)+ b(i).t((i+1) mod n)).Cycler(i,n); Start = t(0).delta; Scheduler2=allow({a,b,tcomm},comm({t|t->tcomm},Start||Cycler(0,2)||Cycler(1,2))); Scheduler3=allow({a,b,tcomm},comm({t|t->tcomm},Start||Cycler(0,3)||Cycler(1,3)||Cycler(2,3))); Scheduler4=allow({a,b,tcomm},comm({t|t->tcomm},Start||Cycler(0,4)||Cycler(1,4)||Cycler(2,4)|| Cycler(3,4))); Scheduler5=allow({a,b,tcomm},comm({t|t->tcomm},Start||Cycler(0,5)||Cycler(1,5)||Cycler(2,5)|| Cycler(3,5)||Cycler(4,5))); Scheduler6=allow({a,b,tcomm},comm({t|t->tcomm},Start||Cycler(0,6)||Cycler(1,6)||Cycler(2,6)|| Cycler(3,6)||Cycler(4,6)||Cycler(5,6))); init hide({tcomm},Scheduler2); examples/academic/scheduler/infinitely_often_enabled_then_infinitely_often_taken_a.mcf000770 001750 001750 00000000360 12370120075 034432 0ustar00outisoutis000000 000000 mcrl2-201409.0% Infinitely often enabled means infinitely often taken % Formula from "Modal logics and mu-calculi: an introduction", Bradfield and % Stirling. % forall i:Nat.([true*] nu X. mu Y. nu Z. ([a(i)]X && ([a(i)]false || [!a(i)]Y) && [!a(i)]Z)) mcrl2-201409.0/examples/academic/onebit/infinitely_often_receive_for_all_d.mcf000770 001750 001750 00000000233 12370120073 027714 0ustar00outisoutis000000 000000 % For all messages d, it is possible to infinitely often start % sending message d (through action r1). % forall d:D . nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/onebit/read_then_eventually_send_if_fair.mcf000770 001750 001750 00000000673 12370120073 027545 0ustar00outisoutis000000 000000 % All messages d are (once they have been read through action ra) % inevitably sent through action sb, if not permanently lost (via % internal action i_lost). % % Essentially this is the same property as the one in % "read_then_eventually_send.mcf", but it adds a fairness assumption % (a message is not lost infinitely often). nu X. ( [true]X && forall d:D. ([ra(d)]( nu Y. mu Z. ([(!sb(d)) && (!i_lost)]Z && [i_lost]Y) ) ) ) mcrl2-201409.0/examples/academic/onebit/nodeadlock.mcf000770 001750 001750 00000000142 12370120073 022746 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/onebit/run.py000770 001750 001750 00000003330 12370120073 021334 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v onebit.mcrl2 onebit.lps') os.system('lps2pbes -v -f nodeadlock.mcf onebit.lps onebit.nodeadlock.pbes') os.system('pbes2bool -v onebit.nodeadlock.pbes') # Solving the following using pbes2bool is slow! os.system('lps2pbes -v -f infinitely_often_enabled_then_infinitely_often_taken.mcf onebit.lps onebit.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('pbes2bool -v -s2 onebit.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('lps2pbes -v -f infinitely_often_lost.mcf onebit.lps onebit.infinitely_often_lost.pbes') os.system('pbes2bool -v onebit.infinitely_often_lost.pbes') os.system('lps2pbes -v -f infinitely_often_receive_dat1.mcf onebit.lps onebit.infinitely_often_receive_dat1.pbes') os.system('pbes2bool -v onebit.infinitely_often_receive_dat1.pbes') os.system('lps2pbes -v -f infinitely_often_receive_for_all_d.mcf onebit.lps onebit.infinitely_often_receive_for_all_d.pbes') os.system('pbes2bool -v onebit.infinitely_often_receive_for_all_d.pbes') os.system('lps2pbes -v -f read_then_eventually_send.mcf onebit.lps onebit.read_then_eventually_send.pbes') os.system('pbes2bool -v onebit.read_then_eventually_send.pbes') os.system('lps2pbes -v -f read_then_eventually_send_if_fair.mcf onebit.lps onebit.read_then_eventually_send_if_fair.pbes') os.system('pbes2bool -v onebit.read_then_eventually_send_if_fair.pbes') os.system('lps2pbes -v -f no_generation_of_messages.mcf onebit.lps onebit.no_generation_of_messages.pbes') os.system('pbes2bool -v onebit.no_generation_of_messages.pbes') os.system('lps2pbes -v -f no_duplication_of_messages.mcf onebit.lps onebit.no_duplication_of_messages.pbes') os.system('pbes2bool -v onebit.no_duplication_of_messages.pbes') mcrl2-201409.0/examples/academic/onebit/no_duplication_of_messages.mcf000770 001750 001750 00000000325 12370120073 026230 0ustar00outisoutis000000 000000 % The protocol does not duplicate messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis [true*] forall d:D. [ra(d).(!ra(d) && !sb(d))*.sb(d).(!ra(d))*.sb(d)]false mcrl2-201409.0/examples/academic/onebit/infinitely_often_lost.mcf000770 001750 001750 00000000310 12370120073 025246 0ustar00outisoutis000000 000000 % There is a path along which a message (after reading through % action ra) can be lost infinitely often (through c3). % (exists d:D .(nu X. mu Y. (X || Y))) mcrl2-201409.0/examples/academic/onebit/no_generation_of_messages.mcf000770 001750 001750 00000000276 12370120073 026055 0ustar00outisoutis000000 000000 % The protocol does not generate new messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis forall d: D. nu X. (([!ra(d)]X && [sb(d)]false)) mcrl2-201409.0/examples/academic/onebit/onebit.mcrl2000770 001750 001750 00000004666 12370120073 022414 0ustar00outisoutis000000 000000 % This file describes the onebit sliding window protocol as documented % M.A. Bezem and J.F. Groote. A correctness proof of a one bit sliding % window protocol in muCRL. The Computer Journal, 37(4): 289-307, 1994. % This sliding window protocol is a bidirectional sliding window protocol % with piggy backing, where the window sizes at the receiving and % sending side have size 1. The behaviour of this sliding window protocol % is that of two bidirectional buffers sending data from channel ra to % sb, and from rc to sd. Both buffers have capacity 2. % The external behaviour of the onebit protocol is rather complex. % However, making only the behaviour visible at gates ra and sb reduced % modulo branching bisimulation clearly shows the behaviour of % a buffer of capacity 2. % % Jan Friso Groote, translated from muCRL 30/12/2006 sort Bit = struct e0 | e1; D= struct dat0 | dat1; Frame=struct frame(dat:D,bit1:Bit,bit2:Bit); Status=struct read?eq_read | choice?eq_choice | del?eq_del; map inv:Bit-> Bit; eqn inv(e0)=e1; inv(e1)=e0; act ra,sb,rc,sd:D; rcl,scl,i_del,i_lost,ccl; r,s,c,s2,r2,c2,s4,r4,c4:Frame; proc S(ready:Bool,rec:Bool,sts:Bool,d:D,e:D,p:Bit,q:Bit)= ready -> sum d:D.ra(d).S(false,rec,false,d,e,inv(p),q) + !rec -> sb(e).S(ready,true,sts,d,e,p,q) + rcl.S(ready,rec,false,d,e,p,q)+ sum f:D,b1:Bit,b2:Bit. r4(frame(f,b1,b2)). (rec && b1==inv(q)) -> S(b2==p,false,sts,d,f,p,inv(q)) <> S(b2==p,rec,sts,d,e,p,q) + !sts -> s(frame(d,p,q)).S(ready,rec,true,d,e,p,q) + delta; proc Tim= scl.Tim; proc C(f:Frame,st:Status)= eq_read(st) -> sum f:Frame.r(f).C(f,choice)<>delta+ eq_choice(st) -> (i_del.C(f,del)+i_lost.C(f,read))<>delta+ eq_del(st) -> s2(f).C(f,read)<>delta ; init hide ({c4,c2,ccl,c,i_del}, allow({c,ccl,c2,c4,i_del,i_lost,ra,sb,rc,sd}, comm({r2|s2->c2,r4|s4->c4}, rename({sb->sd}, allow({c,ccl,ra,sb,s2,r4,i_del,i_lost}, comm({rcl|scl->ccl,r|s->c}, S(true,true,true,dat0,dat0,e0,e0)|| Tim|| C(frame(dat0,e0,e0),read))))|| rename({ra->rc,s2->s4,r4->r2}, allow({c,ccl,ra,sb,s2,r4,i_del,i_lost}, comm({rcl|scl->ccl,r|s->c}, S(true,true,true,dat0,dat0,e0,e0)|| Tim|| C(frame(dat0,e0,e0) ,read))))))); mcrl2-201409.0/examples/academic/onebit/infinitely_often_receive_dat1.mcf000770 001750 001750 00000000202 12370120073 026620 0ustar00outisoutis000000 000000 % It is possible to infinitely often start sending a d1 message % (through action r1) % nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/onebit/read_then_eventually_send.mcf000770 001750 001750 00000000710 12370120073 026056 0ustar00outisoutis000000 000000 % Formula that expresses that if a message is read through ra, then it is % eventually send through sb. % This property does not hold for the onebit protocol, as it does not % assume fairness. This can be shown by the formula "infinitely_often_lost.mcf" % % The file "read_then_eventually_send_if_fair.mcf" contains a formula that % shows that the property holds if fairness is assumed. [true*](forall d:D .([ra(d)](nu X. mu Y. ([sb(d)]X && [!sb(d)]Y)))) mcrl2-201409.0/examples/academic/onebit/infinitely_often_enabled_then_infinitely_often_taken.mcf000770 001750 001750 00000000463 12370120073 033515 0ustar00outisoutis000000 000000 % If an ra action is enabled infinitely often, then it is also % taken infinitely often, independent of the message d % Taken from: "Modal logics and mu-calculi: an introduction", % by Bradfield and Stirling. % forall d:D . ([true*] nu X. mu Y. nu Z. ([ra(d)]X && ([ra(d)]false || [!ra(d)]Y) && [!ra(d)]Z)) mcrl2-201409.0/examples/academic/cabp/infinitely_often_receive_for_all_d.mcf000770 001750 001750 00000000326 12370120074 027345 0ustar00outisoutis000000 000000 % For all messages d, it is possible to infinitely often start % sending message d (through action r1). % % This property holds for the alternating bit protocol. forall d:DATA . nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/cabp/read_then_eventually_send_if_fair.mcf000770 001750 001750 00000000662 12370120074 027171 0ustar00outisoutis000000 000000 % All messages d are (once they have been read through action r1) % inevitably sent through action s2, if not permanently lost. % % Essentially this is the same property as the one in % "read_then_eventually_send.mcf", but it adds a fairness assumption % (a message is not lost infinitely often). nu X. ( [true]X && forall d:DATA. ([r1(d)]( nu Y. mu Z. ([(!s2(d)) && (!(c4(ce)||c7(ae)))]Z && [c4(ce)||c7(ae)]Y) ) ) ) mcrl2-201409.0/examples/academic/cabp/nodeadlock.mcf000770 001750 001750 00000000142 12370120074 022374 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/cabp/run.py000770 001750 001750 00000003143 12370120074 020764 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v cabp.mcrl2 cabp.lps') os.system('lps2pbes -v -f nodeadlock.mcf cabp.lps cabp.nodeadlock.pbes') os.system('pbes2bool -v cabp.nodeadlock.pbes') os.system('lps2pbes -v -f infinitely_often_enabled_then_infinitely_often_taken.mcf cabp.lps cabp.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('pbes2bool -v cabp.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('lps2pbes -v -f infinitely_often_lost.mcf cabp.lps cabp.infinitely_often_lost.pbes') os.system('pbes2bool -v cabp.infinitely_often_lost.pbes') os.system('lps2pbes -v -f infinitely_often_receive_d1.mcf cabp.lps cabp.infinitely_often_receive_d1.pbes') os.system('pbes2bool -v cabp.infinitely_often_receive_d1.pbes') os.system('lps2pbes -v -f infinitely_often_receive_for_all_d.mcf cabp.lps cabp.infinitely_often_receive_for_all_d.pbes') os.system('pbes2bool -v cabp.infinitely_often_receive_for_all_d.pbes') os.system('lps2pbes -v -f read_then_eventually_send.mcf cabp.lps cabp.read_then_eventually_send.pbes') os.system('pbes2bool -v cabp.read_then_eventually_send.pbes') os.system('lps2pbes -v -f read_then_eventually_send_if_fair.mcf cabp.lps cabp.read_then_eventually_send_if_fair.pbes') os.system('pbes2bool -v cabp.read_then_eventually_send_if_fair.pbes') os.system('lps2pbes -v -f no_generation_of_messages.mcf cabp.lps cabp.no_generation_of_messages.pbes') os.system('pbes2bool -v cabp.no_generation_of_messages.pbes') os.system('lps2pbes -v -f no_duplication_of_messages.mcf cabp.lps cabp.no_duplication_of_messages.pbes') os.system('pbes2bool -v cabp.no_duplication_of_messages.pbes') mcrl2-201409.0/examples/academic/cabp/no_duplication_of_messages.mcf000770 001750 001750 00000000330 12370120074 025652 0ustar00outisoutis000000 000000 % The protocol does not duplicate messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis [true*] forall d:DATA. [r1(d).(!r1(d) && !s2(d))*.s2(d).(!r1(d))*.s2(d)]false mcrl2-201409.0/examples/academic/cabp/cabp.mcrl2000770 001750 001750 00000005337 12370120074 021463 0ustar00outisoutis000000 000000 % This file contains the cabp protocol as described in section 3.5 of % S. Mauw and G.J. Veltink, editors, Algebraic Specification of Communication % Protocols, Cambridge tracts in theoretical computer science 36, Cambridge % University Press, Cambridge 1993. % % With two data elements, the generated transition system has 464 states. % % It is interesting to see the clustering of this statespace in ltsgraph. % The statespace after branching bisimulation contains 3 states and is % exactly the same as the reduced statespace of the alternating bit protocol. % % Note that it is interesting to compare the differences of the alternating % bit protocol (abp), concurrent alternating bit protocol (cabp), one bit % sliding window protocol (onebit) and the alternating bit protocol with % independent acknowledgements (par), regarding the implementation, the % the number of states and the external behaviour. %------------------------------- DATA ---------------------------------- sort DATA = struct d1 | d2; %------------------------------- error ---------------------------------- sort error = struct ce | ae; %------------------------------- bit ------------------------------------ sort bit = struct bit0 | bit1; map invert:bit -> bit; eqn invert(bit1)=bit0; invert(bit0)=bit1; %------------------------------- Frame ---------------------------------- sort Frame = struct frame(getd : DATA, getb: bit); %------------------------------ ACK ----------------------------------- sort ACK = struct ac; %------------------------------ act ----------------------------------- act r1,s2 : DATA; c3,r3,s3,c4,r4,s4 : Frame; c4,r4,s4,c7,r7,s7 : error; c5,r5,s5,c8,r8,s8 : ACK; c6,r6,s6,c7,r7,s7 : bit; skip; %------------------------------ proc ----------------------------------- proc S = RM(bit0); RM(b:bit) = sum d:DATA.r1(d).SF(frame(d,b)); SF(f:Frame) = s3(f).SF(f) + r8(ac).RM(invert(getb(f))); K = sum f:Frame.r3(f).K(f); K(f:Frame) = (skip.s4(f)+skip.s4(ce)+skip).K; R = RF(bit0); RF(b:bit) = sum d:DATA.r4(frame(d,b)).s2(d).s5(ac).RF(invert(b)) + sum d:DATA. r4(frame(d,invert(b))).RF(b) + r4(ce).RF(b); AS = AS(bit1); AS(b:bit) = r5(ac).AS(invert(b)) + s6(b).AS(b); L = sum b:bit.r6(b) . L(b); L(b:bit) = ( skip.s7(b) + skip.s7(ae) + skip ).L; AR = AR(bit0); AR(b:bit) = ( r7(ae) + r7(invert(b))) . AR(b) + r7(b).s8(ac).AR(invert(b)); init hide({c3,c4,c5,c6,c7,c8,skip}, allow({c3,c4,c5,c6,c7,c8,skip,r1,s2}, comm({r3|s3->c3, r4|s4->c4, r5|s5->c5, r6|s6->c6, r7|s7->c7, r8|s8->c8}, S || K || R || AS || L || AR ))); mcrl2-201409.0/examples/academic/cabp/infinitely_often_lost.mcf000770 001750 001750 00000001001 12370120074 024672 0ustar00outisoutis000000 000000 % There is a path along which a message (after reading through % action r1) can be lost infinitely often (through c3). % % This property is true for the alternating bit protocol, because there is % no fairness assumption. % % Note: e as parameter of c3 means an error is communicated, hence a message % was lost. % % This requires that c4 and c7 are removed from the hide set in cabp.mcrl2 % before running mcrl22lps and lps2pbes. (exists d:DATA .(nu X. mu Y. (X || Y))) mcrl2-201409.0/examples/academic/cabp/no_generation_of_messages.mcf000770 001750 001750 00000000301 12370120074 025470 0ustar00outisoutis000000 000000 % The protocol does not generate new messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis forall d: DATA. nu X. (([!r1(d)]X && [s2(d)]false)) mcrl2-201409.0/examples/academic/cabp/infinitely_often_receive_d1.mcf000770 001750 001750 00000000266 12370120074 025733 0ustar00outisoutis000000 000000 % It is possible to infinitely often start sending a d1 message % (through action r1) % % This property holds for the alternating bit protocol. nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/cabp/read_then_eventually_send.mcf000770 001750 001750 00000000724 12370120074 025511 0ustar00outisoutis000000 000000 % Formula that expresses that if a message is read through r1, then it is % eventually send through s4. % This property does not hold for the alternating bit protocol, as it does not % assume fairness. This can be shown by the formula "infinitely_often_lost.mcf" % % The file "read_then_eventually_send_if_fair.mcf" contains a formula that % shows that the property holds if fairness is assumed. [true*](forall d:DATA .([r1(d)](nu X. mu Y. ([s2(d)]X && [!s2(d)]Y)))) mcrl2-201409.0/examples/academic/cabp/infinitely_often_enabled_then_infinitely_often_taken.mcf000770 001750 001750 00000000644 12370120074 033144 0ustar00outisoutis000000 000000 % If an r1 action is enabled infinitely often, then it is also % taken infinitely often, independent of the message d % Taken from: "Modal logics and mu-calculi: an introduction", % by Bradfield and Stirling. % % This formula is not true for the concurrent alternating bit protocol, % as there is no fairness assumption. forall d:DATA . ([true*] nu X. mu Y. nu Z. ([r1(d)]X && ([r1(d)]false || [!r1(d)]Y) && [!r1(d)]Z)) mcrl2-201409.0/examples/academic/bakery/aggressive_abstraction.txt000770 001750 001750 00000001143 12370120075 025446 0ustar00outisoutis000000 000000 sort AbsNat = struct arbitrary; var an: AbsNat; n : Nat; eqn absplus (an,an) = {an}; abslt (an,an) = {false,true}; absle (an,an) = {false,true}; abseqn (an,an) = {false,true}; h(n) = arbitrary; absmap h: Nat -> AbsNat; absfunc +: Nat # Nat -> Nat := absplus :AbsNat # AbsNat -> Set(AbsNat) <: Nat # Nat -> Bool := abslt : AbsNat # AbsNat -> Set(Bool) <=: Nat # Nat -> Bool := absle : AbsNat # AbsNat -> Set(Bool) ==: Nat # Nat -> Bool := abseqn : AbsNat # AbsNat -> Set(Bool) mcrl2-201409.0/examples/academic/bakery/nodeadlock/run.aggressive000770 001750 001750 00000001134 12370120075 025145 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f no_deadlock.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.no_deadlock.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../aggressive_abstraction.txt bakery.no_deadlock.pbes bakery.no_deadlock.absinthe.pbes pbes2bool bakery.no_deadlock.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../aggressive_abstraction.txt bakery.no_deadlock.pbes bakery.no_deadlock.absinthe.pbes pbes2bool bakery.no_deadlock.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/nodeadlock/run000770 001750 001750 00000001116 12370120075 023007 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f no_deadlock.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.no_deadlock.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../abstraction.txt bakery.no_deadlock.pbes bakery.no_deadlock.absinthe.pbes pbes2bool -s3 bakery.no_deadlock.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../abstraction.txt bakery.no_deadlock.pbes bakery.no_deadlock.absinthe.pbes pbes2bool -s3 bakery.no_deadlock.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/nodeadlock/no_deadlock.mcf000770 001750 001750 00000000142 12370120075 025207 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/bakery/get_at_least_number_circulating.mcf000770 001750 001750 00000000523 12370120075 027234 0ustar00outisoutis000000 000000 % It is attainable for a process to always get a number that is at least the % number that is currently circulating % Taken from "Model-Checking Processes with Data" % J.F. Groote and T.A.C. Willemse (nu Z(i: Nat).(exists b:Bool. exists n:Nat. (n >= i && Z(n))) || Z(i))(0) mcrl2-201409.0/examples/academic/bakery/request_can_eventually_enter/run.aggressive000770 001750 001750 00000001346 12370120075 031025 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f request_can_eventually_enter.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.request_can_eventually_enter.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../aggressive_abstraction.txt bakery.request_can_eventually_enter.pbes bakery.request_can_eventually_enter.absinthe.pbes pbes2bool bakery.request_can_eventually_enter.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../aggressive_abstraction.txt bakery.request_can_eventually_enter.pbes bakery.request_can_eventually_enter.absinthe.pbes pbes2bool bakery.request_can_eventually_enter.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/request_can_eventually_enter/run000770 001750 001750 00000001330 12370120075 026660 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f request_can_eventually_enter.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.request_can_eventually_enter.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../abstraction.txt bakery.request_can_eventually_enter.pbes bakery.request_can_eventually_enter.absinthe.pbes pbes2bool -s3 bakery.request_can_eventually_enter.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../abstraction.txt bakery.request_can_eventually_enter.pbes bakery.request_can_eventually_enter.absinthe.pbes pbes2bool -s3 bakery.request_can_eventually_enter.absinthe.pbes rm *.pbes rm ../*.lps examples/academic/bakery/request_can_eventually_enter/request_can_eventually_enter.mcf000770 001750 001750 00000000412 12370120075 034517 0ustar00outisoutis000000 000000 mcrl2-201409.0% All processes requesting a number can eventually enter the critical section % Described in "A Checker for Modal Formulas on Processed with Data", % J.F. Groote and T.A.C. Willemse nu X . ([true]X && forall b:Bool. [request(b)]mu Y. ( Y || true)) mcrl2-201409.0/examples/academic/bakery/nodeadlock.mcf000770 001750 001750 00000000142 12370120075 022745 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/bakery/run.py000770 001750 001750 00000002157 12370120075 021341 0ustar00outisoutis000000 000000 import os # Not all of the below terminate! os.system('mcrl22lps -v bakery.mcrl2 bakery.lps') os.system('lps2pbes -v -f nodeadlock.mcf bakery.lps bakery.nodeadlock.pbes') os.system('pbes2bool -v -rjittyc bakery.nodeadlock.pbes') os.system('lps2pbes -v -f request_can_eventually_enter.mcf bakery.lps bakery.request_can_eventually_enter.pbes') os.system('pbes2bool -v -rjittyc bakery.request_can_eventually_enter.pbes') os.system('lps2pbes -v -f request_must_eventually_enter.mcf bakery.lps bakery.request_must_eventually_enter.pbes') os.system('pbes2bool -v -rjittyc bakery.request_must_eventually_enter.pbes') os.system('lps2pbes -v -f mutual_exclusion.mcf bakery.lps bakery.mutual_exclusion.pbes') os.system('pbes2bool -v -rjittyc bakery.mutual_exclusion.pbes') os.system('lps2pbes -v -f always_can_get_number.mcf bakery.lps bakery.always_can_get_number.pbes') os.system('pbes2bool -v -rjittyc bakery.always_can_get_number.pbes') os.system('lps2pbes -v -f get_at_least_number_circulating.mcf bakery.lps bakery.get_at_least_number_circulating.pbes') os.system('pbes2bool -v -rjittyc bakery.get_at_least_number_circulating.pbes') mcrl2-201409.0/examples/academic/bakery/abstraction.txt000770 001750 001750 00000001553 12370120075 023234 0ustar00outisoutis000000 000000 sort AbsNat = struct nul | meer; var n: Nat; an,an': AbsNat; eqn absplus (nul,nul) = {nul}; absplus (meer,meer) = {meer}; absplus (meer,nul) = {meer}; absplus (nul,meer) = {meer}; abslt (nul,meer) = {true}; abslt (meer,meer) = {false,true}; abslt (an,nul) = {false}; absle (an,nul) = {an == nul}; absle (meer,meer) = {false,true}; absle (nul,meer) = {true}; abseqn (nul,nul) = {true}; an != an' -> abseqn (an, an') = {false}; abseqn (meer,meer) = {false,true}; h(0) = nul; (n > 0) -> h(n) = meer; absmap h: Nat -> AbsNat; absfunc +: Nat # Nat -> Nat := absplus :AbsNat # AbsNat -> Set(AbsNat) <: Nat # Nat -> Bool := abslt : AbsNat # AbsNat -> Set(Bool) <=: Nat # Nat -> Bool := absle : AbsNat # AbsNat -> Set(Bool) ==: Nat # Nat -> Bool := abseqn : AbsNat # AbsNat -> Set(Bool) mcrl2-201409.0/examples/academic/bakery/bakery.mcrl2000770 001750 001750 00000001553 12370120075 022400 0ustar00outisoutis000000 000000 % This file describes the original bakery protocol as described by Lamport for % two parties that want to gain mutual access. The processes are called % P(true) and P(false). % % The state space of this system is infinite, and as such it is a good and % simple example to apply symbolic methods in the broadest sense. act send,get,c: Bool # Nat; request,enter,leave: Bool; proc P(b:Bool) = request(b).P0(b,0) + send(b,0).P(b); P0(b:Bool,n:Nat) = (sum m:Nat. get(!b,m).P1(b,m + 1)) + send(b,n).P0(b,n); P1(b:Bool,n:Nat) = (sum m:Nat. get(!(b),m). ((n < m || m == 0) -> C1(b,n) <> P1(b,n))) + send(b,n).P1(b,n); C1(b:Bool,n:Nat) = enter(b).C2(b,n) + send(b,n).C1(b,n); C2(b:Bool,n:Nat) = leave(b).P(b) + send(b,n).C2(b,n); init allow({request,enter,leave,c}, comm({get|send->c}, P(true) || P(false)) ); mcrl2-201409.0/examples/academic/bakery/mutual_exclusion.mcf000770 001750 001750 00000000362 12370120075 024246 0ustar00outisoutis000000 000000 % Two processes can never be in the critical section at the same time. % Taken from "Model-Checking Processes with Data" % J.F. Groote and T.A.C. Willemse nu X.([true]X && forall b:Bool . ([enter(b)] nu Y.([enter(!b)]false && [!leave(b)]Y))) mcrl2-201409.0/examples/academic/bakery/get_at_least_number_circulating/run.aggressive000770 001750 001750 00000001412 12370120075 031430 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f get_at_least_number_circulating.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.get_at_least_number_circulating.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../aggressive_abstraction.txt bakery.get_at_least_number_circulating.pbes bakery.get_at_least_number_circulating.absinthe.pbes pbes2bool -s3 bakery.get_at_least_number_circulating.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../aggressive_abstraction.txt bakery.get_at_least_number_circulating.pbes bakery.get_at_least_number_circulating.absinthe.pbes pbes2bool -s3 bakery.get_at_least_number_circulating.absinthe.pbes #rm *.pbes #rm ../*.lps mcrl2-201409.0/examples/academic/bakery/get_at_least_number_circulating/run000770 001750 001750 00000001362 12370120075 027276 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f get_at_least_number_circulating.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.get_at_least_number_circulating.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../abstraction.txt bakery.get_at_least_number_circulating.pbes bakery.get_at_least_number_circulating.absinthe.pbes pbes2bool -s3 bakery.get_at_least_number_circulating.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../abstraction.txt bakery.get_at_least_number_circulating.pbes bakery.get_at_least_number_circulating.absinthe.pbes pbes2bool -s3 bakery.get_at_least_number_circulating.absinthe.pbes rm *.pbes rm ../*.lps examples/academic/bakery/get_at_least_number_circulating/get_at_least_number_circulating.mcf000770 001750 001750 00000000544 12370120075 035547 0ustar00outisoutis000000 000000 mcrl2-201409.0% It is attainable for a process to always get a number that is at least the % number that is currently circulating % Taken from "Model-Checking Processes with Data" % J.F. Groote and T.A.C. Willemse nu Z(i: Nat= 0).((exists b:Bool. exists n:Nat. (val(n + Pos2Nat(1) > i) && Z(n))) || Z(i)) mcrl2-201409.0/examples/academic/bakery/mutual_exclusion/run.aggressive000770 001750 001750 00000001243 12370120075 026443 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f mutual_exclusion.mcf ../bakery.lps | pbesrewr -pquantifier-finite | pbesconstelm | pbesparelm | pbesrewr -psimplify > bakery.mutual_exclusion.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../aggressive_abstraction.txt bakery.mutual_exclusion.pbes bakery.mutual_exclusion.absinthe.pbes pbes2bool bakery.mutual_exclusion.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../aggressive_abstraction.txt bakery.mutual_exclusion.pbes bakery.mutual_exclusion.absinthe.pbes pbes2bool bakery.mutual_exclusion.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/mutual_exclusion/run000770 001750 001750 00000001215 12370120075 024304 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f mutual_exclusion.mcf ../bakery.lps | pbesrewr -pquantifier-finite | pbesconstelm | pbesparelm | pbesrewr -psimplify > bakery.mutual_exclusion.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../abstraction.txt bakery.mutual_exclusion.pbes bakery.mutual_exclusion.absinthe.pbes pbes2bool bakery.mutual_exclusion.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../abstraction.txt bakery.mutual_exclusion.pbes bakery.mutual_exclusion.absinthe.pbes pbes2bool bakery.mutual_exclusion.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/mutual_exclusion/mutual_exclusion.mcf000770 001750 001750 00000000362 12370120075 027646 0ustar00outisoutis000000 000000 % Two processes can never be in the critical section at the same time. % Taken from "Model-Checking Processes with Data" % J.F. Groote and T.A.C. Willemse nu X.([true]X && forall b:Bool . ([enter(b)] nu Y.([enter(!b)]false && [!leave(b)]Y))) mcrl2-201409.0/examples/academic/bakery/request_can_eventually_enter.mcf000770 001750 001750 00000000410 12370120075 026616 0ustar00outisoutis000000 000000 % All processes requesting a number can eventually enter the critical section % Described in "A Checker for Modal Formulas on Processed with Data", % J.F. Groote and T.A.C. Willemse nu X . ([true]X && forall b:Bool. [request(b)]mu Y. Y || true) mcrl2-201409.0/examples/academic/bakery/request_must_eventually_enter.mcf000770 001750 001750 00000000421 12370120075 027047 0ustar00outisoutis000000 000000 % All processes requesting a number inevitably enter the critical section. % Described in "A Checker for Modal Formulas on Processed with Data", % J.F. Groote and T.A.C. Willemse nu X.([true]X && forall b:Bool.[request(b)] mu Y.(([true]Y && true) || true)) mcrl2-201409.0/examples/academic/bakery/request_must_eventually_enter/run.aggressive000770 001750 001750 00000001355 12370120075 031254 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f request_must_eventually_enter.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.request_must_eventually_enter.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../aggressive_abstraction.txt bakery.request_must_eventually_enter.pbes bakery.request_must_eventually_enter.absinthe.pbes pbes2bool bakery.request_must_eventually_enter.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../aggressive_abstraction.txt bakery.request_must_eventually_enter.pbes bakery.request_must_eventually_enter.absinthe.pbes pbes2bool bakery.request_must_eventually_enter.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/request_must_eventually_enter/run000770 001750 001750 00000001337 12370120075 027116 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f request_must_eventually_enter.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.request_must_eventually_enter.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../abstraction.txt bakery.request_must_eventually_enter.pbes bakery.request_must_eventually_enter.absinthe.pbes pbes2bool -s3 bakery.request_must_eventually_enter.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../abstraction.txt bakery.request_must_eventually_enter.pbes bakery.request_must_eventually_enter.absinthe.pbes pbes2bool -s3 bakery.request_must_eventually_enter.absinthe.pbes rm *.pbes rm ../*.lps examples/academic/bakery/request_must_eventually_enter/request_must_eventually_enter.mcf000770 001750 001750 00000000421 12370120075 035175 0ustar00outisoutis000000 000000 mcrl2-201409.0% All processes requesting a number inevitably enter the critical section. % Described in "A Checker for Modal Formulas on Processed with Data", % J.F. Groote and T.A.C. Willemse nu X.([true]X && forall b:Bool.[request(b)] mu Y.(([true]Y && true) || true)) mcrl2-201409.0/examples/academic/bakery/always_can_get_number/run.aggressive000770 001750 001750 00000001260 12370120075 027372 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f always_can_get_number.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.always_can_get_number.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../aggressive_abstraction.txt bakery.always_can_get_number.pbes bakery.always_can_get_number.absinthe.pbes pbes2bool bakery.always_can_get_number.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../aggressive_abstraction.txt bakery.always_can_get_number.pbes bakery.always_can_get_number.absinthe.pbes pbes2bool bakery.always_can_get_number.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/always_can_get_number/run000770 001750 001750 00000001242 12370120075 025234 0ustar00outisoutis000000 000000 mcrl22lps -fDnw ../bakery.mcrl2 |lpsconstelm | lpsparelm > ../bakery.lps lps2pbes -f always_can_get_number.mcf ../bakery.lps | pbesrewr -psimplify | pbesconstelm | pbesparelm > bakery.always_can_get_number.pbes echo -ne 'Answer by under-approximation: ' pbesabsinthe -sunder -a../abstraction.txt bakery.always_can_get_number.pbes bakery.always_can_get_number.absinthe.pbes pbes2bool -s3 bakery.always_can_get_number.absinthe.pbes echo -ne 'Answer by over-approximation: ' pbesabsinthe -sover -a../abstraction.txt bakery.always_can_get_number.pbes bakery.always_can_get_number.absinthe.pbes pbes2bool -s3 bakery.always_can_get_number.absinthe.pbes rm *.pbes rm ../*.lps mcrl2-201409.0/examples/academic/bakery/always_can_get_number/always_can_get_number.mcf000770 001750 001750 00000000332 12370120075 031523 0ustar00outisoutis000000 000000 % It is always possible to get a number % Taken from "Model-Checking Processes with Data" % J.F. Groote and T.A.C. Willemse nu X.([true]X && forall b:Bool. mu Y.(([true]Y && true) || exists n:Nat. true)) mcrl2-201409.0/examples/academic/bakery/always_can_get_number.mcf000770 001750 001750 00000000332 12370120075 025173 0ustar00outisoutis000000 000000 % It is always possible to get a number % Taken from "Model-Checking Processes with Data" % J.F. Groote and T.A.C. Willemse nu X.([true]X && forall b:Bool. mu Y.(([true]Y && true) || exists n:Nat. true)) mcrl2-201409.0/examples/academic/tree/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022427 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/tree/run.py000770 001750 001750 00000001126 12370120074 021015 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v tree.mcrl2 tree.lps') os.system('lps2pbes -v -f nodeadlock.mcf tree.lps tree.nodeadlock.pbes') os.system('pbes2bool -v tree.nodeadlock.pbes') # The above shows that there is a deadlock in the specification. # Let's investigate os.system('lps2lts -v tree.lps tree.aut') # The following creates state space, and stores traces to 512 deadlocks. #os.system('lps2lts -v -Dt tree.lps tree.aut') # Print the trace and find out what's wrong: #os.system('tracepp tree.lps_dlk_0.trc') # The state space in ltsview resembles modern art... os.system('ltsview tree.aut') mcrl2-201409.0/examples/academic/tree/tree.mcrl2000770 001750 001750 00000001002 12370120074 021530 0ustar00outisoutis000000 000000 % This process has the behaviour of a binary tree. % It has in total 2N+1 states and 2N transitions. % Each node is represented by a positive number, % which if written as a binary number indicates % the path from the root to the node. The first % digit is always one, and must be ignored. If a % subsequent digit is 0 go to the left, and if % 1 go to the right. % Jan Friso Groote, September 3, 2006. act left,right; map N:Pos; eqn N=512; proc X(n:Pos)=(n<=N)->(left.X(2*n)+right.X(2*n+1))<>delta; init X(1); mcrl2-201409.0/examples/academic/abp_bw/infinitely_often_receive_for_all_d.mcf000770 001750 001750 00000000275 12370120074 027675 0ustar00outisoutis000000 000000 % For all messages d, it is possible to infinitely often start % sending message d (through action r1). % % This property holds for abp_bw. forall d:D . nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/abp_bw/read_then_eventually_send_if_fair.mcf000770 001750 001750 00000001005 12370120074 027506 0ustar00outisoutis000000 000000 % All messages d are (once they have been read through action r1) % inevitably sent through action s4, if not permanently lost (via % internal actions tau_s3e or tau_s6e). % % Essentially this is the same property as the one in % "read_then_eventually_send.mcf", but it adds a fairness assumption % (a message is not lost infinitely often). % % This property holds for abp_bw nu X. ( [true]X && forall d:D. ([r1(d)]( nu Y. mu Z. ([(!s4(d)) && (!tau_s3e) && (!tau_s6e)]Z && [tau_s3e || tau_s6e]Y) ) ) mcrl2-201409.0/examples/academic/abp_bw/nodeadlock.mcf000770 001750 001750 00000000142 12370120074 022721 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/abp_bw/run.py000770 001750 001750 00000003234 12370120074 021312 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v abp_bw.mcrl2 abp_bw.lps') os.system('lps2pbes -v -f nodeadlock.mcf abp_bw.lps abp_bw.nodeadlock.pbes') os.system('pbes2bool -v abp_bw.nodeadlock.pbes') os.system('lps2pbes -v -f infinitely_often_enabled_then_infinitely_often_taken.mcf abp_bw.lps abp_bw.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('pbes2bool -v abp_bw.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('lps2pbes -v -f infinitely_often_lost.mcf abp_bw.lps abp_bw.infinitely_often_lost.pbes') os.system('pbes2bool -v abp_bw.infinitely_often_lost.pbes') os.system('lps2pbes -v -f infinitely_often_receive_d1.mcf abp_bw.lps abp_bw.infinitely_often_receive_d1.pbes') os.system('pbes2bool -v abp_bw.infinitely_often_receive_d1.pbes') os.system('lps2pbes -v -f infinitely_often_receive_for_all_d.mcf abp_bw.lps abp_bw.infinitely_often_receive_for_all_d.pbes') os.system('pbes2bool -v abp_bw.infinitely_often_receive_for_all_d.pbes') os.system('lps2pbes -v -f read_then_eventually_send.mcf abp_bw.lps abp_bw.read_then_eventually_send.pbes') os.system('pbes2bool -v abp_bw.read_then_eventually_send.pbes') os.system('lps2pbes -v -f read_then_eventually_send_if_fair.mcf abp_bw.lps abp_bw.read_then_eventually_send_if_fair.pbes') os.system('pbes2bool -v abp_bw.read_then_eventually_send_if_fair.pbes') os.system('lps2pbes -v -f no_generation_of_messages.mcf abp_bw.lps abp_bw.no_generation_of_messages.pbes') os.system('pbes2bool -v abp_bw.no_generation_of_messages.pbes') os.system('lps2pbes -v -f no_duplication_of_messages.mcf abp_bw.lps abp_bw.no_duplication_of_messages.pbes') os.system('pbes2bool -v abp_bw.no_duplication_of_messages.pbes') mcrl2-201409.0/examples/academic/abp_bw/no_duplication_of_messages.mcf000770 001750 001750 00000000325 12370120074 026203 0ustar00outisoutis000000 000000 % The protocol does not duplicate messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis [true*] forall d:D. [r1(d).(!r1(d) && !s4(d))*.s4(d).(!r1(d))*.s4(d)]false mcrl2-201409.0/examples/academic/abp_bw/infinitely_often_lost.mcf000770 001750 001750 00000000560 12370120074 025230 0ustar00outisoutis000000 000000 % There is a path along which a message (after reading through % action r1) can be lost infinitely often (through c3). % % This property is true for abp_bw, because there is % no fairness assumption. % % Note: e as parameter of c3 means an error is communicated, hence a message % was lost. (exists d:D .(nu X. mu Y. (X || Y))) mcrl2-201409.0/examples/academic/abp_bw/no_generation_of_messages.mcf000770 001750 001750 00000000276 12370120074 026030 0ustar00outisoutis000000 000000 % The protocol does not generate new messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis forall d: D. nu X. (([!r1(d)]X && [s4(d)]false)) mcrl2-201409.0/examples/academic/abp_bw/infinitely_often_receive_d1.mcf000770 001750 001750 00000000240 12370120074 026250 0ustar00outisoutis000000 000000 % It is possible to infinitely often start sending a d1 message % (through action r1) % % This property holds for abp_bw. nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/abp_bw/read_then_eventually_send.mcf000770 001750 001750 00000000673 12370120074 026041 0ustar00outisoutis000000 000000 % Formula that expresses that if a message is read through r1, then it is % eventually send through s4. % This property does not hold for abp_bw, as it does not % assume fairness. This can be shown by the formula "infinitely_often_lost.mcf" % % The file "read_then_eventually_send_if_fair.mcf" contains a formula that % shows that the property holds if fairness is assumed. [true*](forall d:D .([r1(d)](nu X. mu Y. ([s4(d)]X && [!s4(d)]Y)))) mcrl2-201409.0/examples/academic/abp_bw/abp_bw.mcrl2000770 001750 001750 00000002310 12370120074 022321 0ustar00outisoutis000000 000000 % This file contains the alternating bit protocol, as described in J.C.M. % Baeten and W.P. Weijland, Process Algebra, Cambridge Tracts in Theoretical % Computer Science 18, Cambridge University Press, 1990. % % The only exception is that the domain D consists of two data elements to % facilitate simulation. sort D = struct d1 | d2; Error = struct e; Bit = struct b0 | b1; map invert: Bit -> Bit; eqn invert(b1)= b0; invert(b0)= b1; act r1,s4: D; s2,r2,c2: D # Bit; s3,r3,c3: D # Bit; s3,r3,c3: Error; s5,r5,c5: Bit; s6,r6,c6: Bit; s6,r6,c6: Error; tau_s3db,tau_s3e,tau_s6b,tau_s6e; proc S = S(b0).S(b1).S; S(b:Bit) = sum d:D. r1(d).S(d,b); S(d:D,b:Bit) = s2(d,b).((r6(invert(b))+r6(e)).S(d,b)+r6(b)); R = R(b1).R(b0).R; R(b:Bit) = (sum d:D. r3(d,b) + r3(e)).s5(b).R(b) + sum d:D. r3(d,invert(b)).s4(d).s5(invert(b)); K = sum d:D,b:Bit. r2(d,b).(tau_s3db.s3(d,b)+tau_s3e.s3(e)).K; L = sum b:Bit. r5(b).(tau_s6b.s6(b)+tau_s6e.s6(e)).L; init allow({r1,s4,tau_s3db, tau_s3e, tau_s6b, tau_s6e,c2,c3,c5,c6}, comm({r2|s2->c2, r3|s3->c3, r5|s5->c5, r6|s6->c6}, S || K || L || R ) ); mcrl2-201409.0/examples/academic/abp_bw/infinitely_often_enabled_then_infinitely_often_taken.mcf000770 001750 001750 00000000600 12370120074 033461 0ustar00outisoutis000000 000000 % If an r1 action is enabled infinitely often, then it is also % taken infinitely often, independent of the message d % Taken from: "Modal logics and mu-calculi: an introduction", % by Bradfield and Stirling. % % This formula is not true for abp_bw, as there is no % fairness assumption. forall d:D . ([true*] nu X. mu Y. nu Z. ([r1(d)]X && ([r1(d)]false || [!r1(d)]Y) && [!r1(d)]Z)) mcrl2-201409.0/examples/academic/cellular_automata/run.py000770 001750 001750 00000000127 12370120074 023554 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v cellular_automata.mcrl2 cellular_automata.lps') mcrl2-201409.0/examples/academic/cellular_automata/cellular_automata.mcrl2000770 001750 001750 00000004502 12370120074 027036 0ustar00outisoutis000000 000000 % This file contains a generator of state machines for cellular % automata according to pages 277 and following of Stephen Wolfram's % book `A new kind of science', Wolfram media, inc. 2002. The automaton % generated by P(i,s) represents all the sequences of black and white % squares that exist when applying the cellular automaton represented % by `rule' i times to any arbitrary such sequence. The state s is % the initial point. % % From a mCRL2 perspective, the description below is interesting % because it heavily uses functions and sets. As it stands (September % 2005) the toolset can only generate the automata for i=0. For % higher i the existential quantifiers need to be resolved, which % currently is outside the capacities of the mCRL2 tools. This % specification can therefore best be seen as a challenge for future % releases of the toolset. map rule:Bool#Bool#Bool -> Bool; eqn rule(true,true,true)=true; rule(true,true,false)=true; rule(true,false,true)=true; rule(true,false,false)=true; rule(false,true,true)=true; rule(false,true,false)=true; rule(false,false,true)=true; rule(false,false,false)=true; sort State = Nat -> Bool; sort Transition = struct trans(src:State,label:Bool,tar:State); sort Transitions = Nat -> Set(Transition); map s0:State; eqn s0=lambda i:Nat.false; map T:Transitions; var i:Nat; eqn T(i)=if(i==0, { trans(s0,false,s0),trans(s0,true,s0) }, { t:Transition | exists g,g1:State. (src(t)(2*i+2)==tar(t)(2*i+1) && rule(src(t)(2*i+1),src(t)(2*i+2),tar(t)(2*i+2))==label(t) && trans( lambda j:Nat.if(j>=2*i+1,false,src(t)(j)), src(t)(2*i+1), lambda j:Nat.if(j>=2*i+1,false,tar(t)(j))) in T(Int2Nat(i-1)) && trans( lambda j:Nat.if(j>=2*i+1,false,tar(t)(j)), src(t)(2*i+2), g) in T(Int2Nat(i-1)) && trans( g, tar(t)(2*i+2), g1) in T(Int2Nat(i-1))) }); act WHITE,BLACK; proc P(i:Nat,s:State)= sum s1:State. (trans(s,true,s1) in T(i)) -> WHITE.P(i,s1)+ sum s1:State. (trans(s,false,s1) in T(i)) -> BLACK.P(i,s1); init P(1,s0); mcrl2-201409.0/examples/academic/dining/dining3_ns.mcrl2000770 001750 001750 00000001334 12370120075 023146 0ustar00outisoutis000000 000000 % This is a naive solution to the dining philosophers problem for % 3 philosophers. sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f3; rf(p2) = f1; rf(p3) = f2; act get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = get(p,lf(p)) . get(p,rf(p)) . eat(p) . put(p,lf(p)) . put(p,rf(p)) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); init block( { get, put, up, down }, comm( { get|up->lock, put|down->free }, P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/dining3_cs_seq.mcrl2000770 001750 001750 00000001617 12370120075 024007 0ustar00outisoutis000000 000000 % This is a corrected version of the naive solution to % the dining philosophers problem for 3 philosophers (sequential version). sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f2; rf(p2) = f3; rf(p3) = f1; act get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = (p == p1) -> get(p,rf(p)) . get(p,lf(p)) . eat(p) . put(p,rf(p)) . put(p,lf(p)) . P_Phil(p) <> get(p,lf(p)) . get(p,rf(p)) . eat(p) . put(p,lf(p)) . put(p,rf(p)) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); init allow( { lock, free, eat }, comm( { get|up->lock, put|down->free }, P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/dining3_schedule_seq.mcrl2000770 001750 001750 00000002027 12370120075 025172 0ustar00outisoutis000000 000000 % This is a specification of a solution to the dining philosophers % problem for 3 philosophers using a scheduler (sequential version). sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f3; rf(p2) = f1; rf(p3) = f2; act ack_get, get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = (get(p,lf(p)).get(p,rf(p)) + get(p,rf(p)).get(p,lf(p))) . eat(p) . (put(p,lf(p)).put(p,rf(p)) + put(p,rf(p)).put(p,lf(p))) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); Waiter = ack_get(p1, lf(p1)) . ack_get(p1, rf(p1)) . ack_get(p2, lf(p2)) . ack_get(p2, rf(p2)) . ack_get(p3, lf(p3)) . ack_get(p3, rf(p3)) . Waiter; init allow ( { lock, free, eat }, comm( { ack_get|get|up->lock, put|down->free }, Waiter || P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/dining3_ns_seq.mcrl2000770 001750 001750 00000001357 12370120075 024023 0ustar00outisoutis000000 000000 % This is a naive solution to the dining philosophers problem % for 3 philosophers (sequential version). sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f2; rf(p2) = f3; rf(p3) = f1; act get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = get(p,lf(p)) . get(p,rf(p)) . eat(p) . put(p,lf(p)) . put(p,rf(p)) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); init allow ( { lock, free, eat }, comm( { get|up->lock, put|down->free }, P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/nodeadlock.mcf000770 001750 001750 00000000142 12370120075 022740 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/dining/run.py000770 001750 001750 00000001656 12370120075 021337 0ustar00outisoutis000000 000000 import os def run_dining(specification_version = "dining3"): os.system('mcrl22lps -v %s.mcrl2 %s.lps' % (specification_version, specification_version)) os.system('lps2pbes -v -f nodeadlock.mcf %s.lps %s.nodeadlock.pbes' % (specification_version, specification_version)) os.system('pbes2bool -v %s.nodeadlock.pbes' % (specification_version)) os.system('lps2pbes -v -f nostuffing.mcf %s.lps %s.nostuffing.pbes' % (specification_version, specification_version)) os.system('pbes2bool -v %s.nostuffing.pbes' % (specification_version)) os.system('lps2pbes -v -f nostarvation.mcf %s.lps %s.nostarvation.pbes' % (specification_version, specification_version)) os.system('pbes2bool -v %s.nostarvation.pbes' % (specification_version)) run_dining("dining3") run_dining("dining3_cs") run_dining("dining3_cs_seq") run_dining("dining3_ns") run_dining("dining3_ns_seq") run_dining("dining3_schedule") run_dining("dining3_schedule_seq") mcrl2-201409.0/examples/academic/dining/nostuffing.mcf000770 001750 001750 00000000314 12370120075 023020 0ustar00outisoutis000000 000000 % This formula says that a philosopher can only eat for a finite consecutive % amount of time. % This can be used with all dining philosophers examples. forall p:Phil. nu X. mu Y. [eat(p)]Y && [!eat(p)]X mcrl2-201409.0/examples/academic/dining/dining3.mcrl2000770 001750 001750 00000001764 12370120075 022455 0ustar00outisoutis000000 000000 % This is a specification of the dining philosophers problem % for 3 philosophers. sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f3; rf(p2) = f1; rf(p3) = f2; act get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = %The following line implements the expression (get(p,lf(p))||get(p,rf(p))) (get(p,lf(p)).get(p,rf(p)) + get(p,rf(p)).get(p,lf(p)) + get(p,lf(p))|get(p,rf(p))) . eat(p) . %The following line implements the expression (put(p,lf(p))||put(p,rf(p))) (put(p,lf(p)).put(p,rf(p)) + put(p,rf(p)).put(p,lf(p)) + put(p,lf(p))|put(p,rf(p))) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); init block( { get, put, up, down }, comm( { get|up->lock, put|down->free }, P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/dining_10.mcrl2000770 001750 001750 00000002116 12370120075 022662 0ustar00outisoutis000000 000000 % This is the dining philosophers problem % Variable K indicates the number of philosophers (and forks) % % Note: When changing the value of K, change the KForkPhil process accordingly! % % Note: Since revision 9975 the construct as used below to describe K processes in parallel % has been disabled. This example can not be linearised as it stands. eqn K = 10; map K: Pos; act get,_get,__get,put,_put,__put: Pos#Pos; eat: Pos; proc Phil(n:Pos) = _get(n,n)._get(n,if(n==K,1,n+1)).eat(n)._put(n,n)._put(n,if(n==K,1,n+1)).Phil(n); Fork(n:Pos) = sum m:Pos.get(m,n).put(m,n).Fork(n); ForkPhil(n:Pos) = Fork(n) || Phil(n); KForkPhil(p:Pos) =ForkPhil(1) || ForkPhil(2) || ForkPhil(3) || ForkPhil(4) || ForkPhil(5) || ForkPhil(6) || ForkPhil(7) || ForkPhil(8) || ForkPhil(9) || ForkPhil(10); init allow( { __get, __put, eat }, comm( { get|_get->__get, put|_put->__put }, KForkPhil(K) )); mcrl2-201409.0/examples/academic/dining/dining3_cs.mcrl2000770 001750 001750 00000001575 12370120075 023142 0ustar00outisoutis000000 000000 % This is a corrected version of the naive solution to % the dining philosophers problem for 3 philosophers. sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f3; rf(p2) = f1; rf(p3) = f2; act get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = (p == p1) -> get(p,rf(p)) . get(p,lf(p)) . eat(p) . put(p,rf(p)) . put(p,lf(p)) . P_Phil(p) <> get(p,lf(p)) . get(p,rf(p)) . eat(p) . put(p,lf(p)) . put(p,rf(p)) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); init block( { get, put, up, down }, comm( { get|up->lock, put|down->free }, P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/dining3_schedule.mcrl2000770 001750 001750 00000002354 12370120075 024325 0ustar00outisoutis000000 000000 % This is a specification of a solution to the dining philosophers % problem for 3 philosophers using a scheduler. sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f3; rf(p2) = f1; rf(p3) = f2; act ack_get, get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = %The following line implements the expression (get(p,lf(p))||get(p,rf(p))) (get(p,lf(p)).get(p,rf(p)) + get(p,rf(p)).get(p,lf(p)) + get(p,lf(p))|get(p,rf(p))) . eat(p) . %The following line implements the expression (put(p,lf(p))||put(p,rf(p))) (put(p,lf(p)).put(p,rf(p)) + put(p,rf(p)).put(p,lf(p)) + put(p,lf(p))|put(p,rf(p))) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); Waiter = ack_get(p1, lf(p1)) . ack_get(p1, rf(p1)) . ack_get(p2, lf(p2)) . ack_get(p2, rf(p2)) . ack_get(p3, lf(p3)) . ack_get(p3, rf(p3)) . Waiter; init allow ( { lock, free, eat }, comm( { ack_get|get|up->lock, put|down->free }, Waiter || P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/dining3_seq.mcrl2000770 001750 001750 00000001435 12370120075 023320 0ustar00outisoutis000000 000000 % This is a specification of the dining philosophers problem % for 3 philosophers (sequential version). sort Phil = struct p1 | p2 | p3; Fork = struct f1 | f2 | f3; map lf, rf: Phil -> Fork; eqn lf(p1) = f1; lf(p2) = f2; lf(p3) = f3; rf(p1) = f3; rf(p2) = f1; rf(p3) = f2; act get, put, up, down, lock, free: Phil # Fork; eat: Phil; proc P_Phil(p: Phil) = (get(p,lf(p)).get(p,rf(p)) + get(p,rf(p)).get(p,lf(p))) . eat(p) . (put(p,lf(p)).put(p,rf(p)) + put(p,rf(p)).put(p,lf(p))) . P_Phil(p); P_Fork(f: Fork) = sum p:Phil. up(p,f) . down(p,f) . P_Fork(f); init allow ( { lock, free, eat }, comm( { get|up->lock, put|down->free }, P_Fork(f1) || P_Fork(f2) || P_Fork(f3) || P_Phil(p1) || P_Phil(p2) || P_Phil(p3) )); mcrl2-201409.0/examples/academic/dining/dining8.mcrl2000770 001750 001750 00000001545 12370120075 022457 0ustar00outisoutis000000 000000 % This is the dining philosophers problem % Variable K indicates the number of philosophers (and forks) % % Note: When changing the value of K, change the KForkPhil process accordingly! eqn K = 8; map K: Pos; act get,put,up,down,lock,free: Pos#Pos; eat: Pos; proc Phil(n:Pos) = get(n,n).get(n,if(n==K,1,n+1)).eat(n).put(n,n).put(n,if(n==K,1,n+1)).Phil(n); Fork(n:Pos) = sum m:Pos.up(m,n).down(m,n).Fork(n); ForkPhil(n:Pos) = Fork(n) || Phil(n); KForkPhil(k:Pos) = % ForkPhil(1) || ... || ForkPhil(k); % or % (k>1) -> (ForkPhil(k)||KForkPhil(max(k-1,1))) <> ForkPhil(k); ForkPhil(1) || ForkPhil(2) || ForkPhil(3) || ForkPhil(4) || ForkPhil(5) || ForkPhil(6) || ForkPhil(7) || ForkPhil(8); init allow( { lock, free, eat }, comm( { get|up->lock, put|down->free }, KForkPhil(K) )); mcrl2-201409.0/examples/academic/dining/nostarvation.mcf000770 001750 001750 00000000454 12370120075 023372 0ustar00outisoutis000000 000000 % This formula expresses that there is no starvation: for all reachable % states it should be possible to eventually perform an eat(p) for each % possible value of p: Phil. % % This example can be used with all dining philosophers examples. [true*](forall p: Phil. mu Y. ([!eat(p)]Y && true)) mcrl2-201409.0/examples/academic/swp/infinitely_often_receive_for_all_d.mcf000770 001750 001750 00000000323 12370120075 027247 0ustar00outisoutis000000 000000 % For all messages d, it is possible to infinitely often start % sending message d (through action r1). % % This property holds for the alternating bit protocol. forall d:D . nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/swp/read_then_eventually_send_if_fair.mcf000770 001750 001750 00000001004 12370120075 027065 0ustar00outisoutis000000 000000 % All messages d are (once they have been read through action r1) % inevitably sent through action s4, if not permanently lost (via % internal action i). % % Essentially this is the same property as the one in % "read_then_eventually_send.mcf", but it adds a fairness assumption % (a message is not lost infinitely often). nu X. ( [true]X && forall d:D. ([r1(d)]( nu Y. mu Z. ([!(exists m: Nat . val(m < 2*n) && c3(d,m)) && !i]Z && [i]([!(exists m: Nat . val( m < 2*n) && c3(d,m))]false => Y) ) )) ) mcrl2-201409.0/examples/academic/swp/nodeadlock.mcf000770 001750 001750 00000000142 12370120075 022301 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/swp/run.py000770 001750 001750 00000004407 12370120075 020675 0ustar00outisoutis000000 000000 import os # SWP_lists os.system('mcrl22lps -v swp_lists.mcrl2 swp_lists.lps') os.system('lps2pbes -v -f nodeadlock.mcf swp_lists.lps swp_lists.nodeadlock.pbes') os.system('pbes2bool -v swp_lists.nodeadlock.pbes') os.system('lps2pbes -v -f infinitely_often_enabled_then_infinitely_often_taken.mcf swp_lists.lps swp_lists.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('pbes2bool -v swp_lists.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('lps2pbes -v -f infinitely_often_lost.mcf swp_lists.lps swp_lists.infinitely_often_lost.pbes') os.system('pbes2bool -v swp_lists.infinitely_often_lost.pbes') os.system('lps2pbes -v -f infinitely_often_receive_d1.mcf swp_lists.lps swp_lists.infinitely_often_receive_d1.pbes') os.system('pbes2bool -v swp_lists.infinitely_often_receive_d1.pbes') os.system('lps2pbes -v -f infinitely_often_receive_for_all_d.mcf swp_lists.lps swp_lists.infinitely_often_receive_for_all_d.pbes') os.system('pbes2bool -v swp_lists.infinitely_often_receive_for_all_d.pbes') os.system('lps2pbes -v -f read_then_eventually_send.mcf swp_lists.lps swp_lists.read_then_eventually_send.pbes') os.system('pbes2bool -v swp_lists.read_then_eventually_send.pbes') os.system('lps2pbes -v -f read_then_eventually_send_if_fair.mcf swp_lists.lps swp_lists.read_then_eventually_send_if_fair.pbes') os.system('pbes2bool -v swp_lists.read_then_eventually_send_if_fair.pbes') os.system('lps2pbes -v -f no_generation_of_messages.mcf swp_lists.lps swp_lists.no_generation_of_messages.pbes') os.system('pbes2bool -v swp_lists.no_generation_of_messages.pbes') os.system('lps2pbes -v -f no_duplication_of_messages.mcf swp_lists.lps swp_lists.no_duplication_of_messages.pbes') os.system('pbes2bool -v swp_lists.no_duplication_of_messages.pbes') # SWP with Tanenbaum's bug os.system('mcrl22lps -v swp_with_tanenbaums_bug.mcrl2 swp_with_tanenbaums_bug.lps') os.system('lps2pbes -v -f nodeadlock.mcf swp_with_tanenbaums_bug.lps swp_with_tanenbaums_bug.nodeadlock.pbes') os.system('pbes2bool -v swp_with_tanenbaums_bug.nodeadlock.pbes') # Generate state space, and look for occurrence of error action. Store trace, # and stop generating after finding a single trace os.system('lps2lts -v -aerror -t1 -rjittyc swp_with_tanenbaums_bug.lps swp_with_tanenbaums_bug.aut') mcrl2-201409.0/examples/academic/swp/no_duplication_of_messages.mcf000770 001750 001750 00000000325 12370120075 025563 0ustar00outisoutis000000 000000 % The protocol does not duplicate messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis [true*] forall d:D. [r1(d).(!r1(d) && !s4(d))*.s4(d).(!r1(d))*.s4(d)]false mcrl2-201409.0/examples/academic/swp/swp_fgpbp.mcrl2000770 001750 001750 00000004712 12370120075 022446 0ustar00outisoutis000000 000000 % This file contains an mCRL2 version of the sliding window protocol % as used in Fokkink, Groote, Pang, Badban and van de Pol, % Verifying a sliding window protocol in mCRL, Report SENR0308, CWI, % Amsterdam, 2003. % The `constant' n is the size of the buffers in the protocol. % This specification differs from older specifications in the sense that % it uses functions to update the buffers. The internal lambda expressions % representing the buffers will grow with every insertion and removal, % meaning that in this form the state space generation will not terminate. % For a terminating state space, the function update mechanism must be % used: f[v->w], representing lambda x.if(x==v,w,f(x)); % % The system has states. map n: Pos; eqn n=2; sort D = struct d1 | d2; Buf = Nat -> struct data(getdata:D) | empty; map emptyBuf: Buf; insert: D#Nat#Buf -> Buf; remove: Nat#Buf -> Buf; release: Nat#Nat#Buf -> Buf; nextempty: Nat#Buf -> Nat; nextempty_rec: Nat#Buf#Nat -> Nat; inWindow: Nat#Nat#Nat -> Bool; var i,j,k: Nat; d: D; q: Buf; eqn emptyBuf = lambda j:Nat.empty; insert(d,i,q) = lambda j:Nat.if(i==j,data(d),q(j)); remove(i,q) = lambda j:Nat.if(i==j,empty,q(j)); i mod 2*n==j mod 2*n -> release(i,j,q) = q; i mod 2*n!=j mod 2*n -> release(i,j,q) = release((i+1) mod 2*n,j,remove(i,q)); k nextempty_rec(i,q,k) = if(q(i)==empty,i,nextempty_rec((i+1) mod n,q,k+1)); k==n -> nextempty_rec(i,q,k)=i; nextempty(i,q) = nextempty_rec(i,q,0); inWindow(i,j,k) = (i<=j && j rA(d).S(l,(m+1) mod 2*n,insert(d,m,q))<>delta+ sum k:Nat. (q(k)!=empty && k<2*n) -> sB(getdata(q(k)),k).S(l,m,q)<>delta+ sum k:Nat. rF(k).S(k,m,release(l,k,q)); R(l:Nat,q:Buf) = sum d:D,k:Nat. rC(d,k). (inWindow(l,k,(l+n) mod 2*n) -> R(l,insert(d,k,q)) <> R(l,q))+ (q(l)!=empty) -> sD(getdata(q(l))).R((l+1) mod 2*n,remove(l,q))<>delta+ sE(nextempty(l,q)).R(l,q); K = sum d:D,k:Nat. rB(d,k).(j.sC(d,k)+j).K; L = sum k:Nat. rE(k).(j.sF(k)+j).L; init allow({cB,cC,cE,cF,j,rA,sD}, comm({rB|sB->cB, rC|sC->cC, rE|sE->cE, rF|sF->cF}, S(0,0,emptyBuf) || K || L || R(0,emptyBuf))); mcrl2-201409.0/examples/academic/swp/swp_func.mcrl2000770 001750 001750 00000004220 12370120075 022275 0ustar00outisoutis000000 000000 % This file contains an mCRL2 version of the sliding window protocol % as it occurs in the book "Modelling Reactive Systems" by Groote and Mousavi. % The buffers in this description are modelled using functions. % % The `constant' n is the size of the buffers in the protocol, set to 2. % There is a domain D of data elements. In this specification it is made % finite. It has two data elements d1 and d2. It also contains two % unspecified functions q1 and q2, which represent initial buffers with % garbage content. % % State space generation is currently (Oct 2008) impossible, even though % all buffers contain finitely many elements and only two data elements % are considered. % Proving absence of deadlock automatically is currently impossible; map n: Pos; eqn n=2; sort D = struct d1 | d2; DBuf = Nat -> D; BBuf = Nat -> Bool; map empty: BBuf; nextempty_mod: Nat#BBuf#Nat#Pos -> Nat; q1,q2:DBuf; var d:D; i,j,m: Nat; q: DBuf; c:Bool; n':Pos; b:BBuf; eqn empty(m) = false; b(i mod n') && m>0 -> nextempty_mod(i,b,m,n') = nextempty_mod((i+1) mod 2*n', b,Int2Nat(m-1),n'); !(b(i mod n') && m>0) -> nextempty_mod(i,b,m,n') =i mod 2*n'; act r1,s4: D; s2,r2,c2,s3,r3,c3: D#Nat; s5,r5,c5,s6,r6,c6: Nat; i; proc S(l,m:Nat,q:DBuf) = sum d:D. (m r1(d).S(l,m+1,q[((l+m) mod n)->d])<>delta+ sum k:Nat. (k s2(q((l+k) mod n),(l+k) mod 2*n).S(l,m,q)<>delta+ sum k:Nat. r6(k).S(k,(m-k+l) mod 2*n,q); R(l':Nat,q':DBuf,b:BBuf) = sum d:D,k:Nat. r3(d,k).(((k-l') mod (2*n) < n) -> R(l',q'[(k mod n)->d],b[(k mod n)->true]) <> R(l',q',b))+ b(l' mod n) -> s4(q'(l' mod n)). R((l'+1) mod 2*n,q',b[(l' mod n)->false])<>delta+ s5(nextempty_mod(l',b,n,n)).R(l',q',b); K = sum d:D,k:Nat. r2(d,k).(i.s3(d,k)+i).K; L = sum k:Nat. r5(k).(i.s6(k)+i).L; SWP(q,q':DBuf)= allow({c2,c3,c5,c6,i,r1,s4}, comm({r2|s2->c2, r3|s3->c3, r5|s5->c5, r6|s6->c6}, S(0,0,q) || K || L || R(0,q',empty))); init SWP(q1,q2); mcrl2-201409.0/examples/academic/swp/infinitely_often_lost.mcf000770 001750 001750 00000000543 12370120075 024611 0ustar00outisoutis000000 000000 % There is a path along which a message (after reading through % action r1) can be lost infinitely often (through i, not followed by c3). % % This property is true for the alternating bit protocol, because there is % no fairness assumption. (exists d:D .(nu X. mu Y. ((X || Y)))) mcrl2-201409.0/examples/academic/swp/no_generation_of_messages.mcf000770 001750 001750 00000000276 12370120075 025410 0ustar00outisoutis000000 000000 % The protocol does not generate new messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis forall d: D. nu X. (([!r1(d)]X && [s4(d)]false)) mcrl2-201409.0/examples/academic/swp/infinitely_often_receive_d1.mcf000770 001750 001750 00000000266 12370120075 025640 0ustar00outisoutis000000 000000 % It is possible to infinitely often start sending a d1 message % (through action r1) % % This property holds for the alternating bit protocol. nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/swp/read_then_eventually_send.mcf000770 001750 001750 00000000721 12370120075 025413 0ustar00outisoutis000000 000000 % Formula that expresses that if a message is read through r1, then it is % eventually send through s4. % This property does not hold for the alternating bit protocol, as it does not % assume fairness. This can be shown by the formula "infinitely_often_lost.mcf" % % The file "read_then_eventually_send_if_fair.mcf" contains a formula that % shows that the property holds if fairness is assumed. [true*](forall d:D .([r1(d)](nu X. mu Y. ([s4(d)]X && [!s4(d)]Y)))) mcrl2-201409.0/examples/academic/swp/swp_lists.mcrl2000770 001750 001750 00000005142 12370120075 022504 0ustar00outisoutis000000 000000 % This file contains a variant of the mCRL2 version of the sliding window protocol % as it occurs in the book "Modelling Reactive Systems" by Fokkink, Groote % and Reniers. The buffers are modelled using lists instead of functions as is % done in swp_func.mcrl2. % % The `constant' n is the size of the buffers in the protocol, set to 2. % There is a domain D of data elements. In this specification it is made % finite. It has an infinite number of data elements, modelled by the natural % numbers. It also contains two unspecified lists q1 and q2, which represent % initial buffers with garbage content. % % State space generation is impossible, but is feasible if the domain D is % a finite set, e.g. by setting D = struct d1|d2; % Absence of deadlock can be checked via translation to pbes and removing the % data domain D using pbesparelm. map n: Pos; eqn n=2; sort %D = Nat; D = struct d1 | d2; DBuf = List(D); BBuf = List(Bool); map empty: BBuf; insert: D#Nat#DBuf -> DBuf; insert: Bool#Nat#BBuf -> BBuf; nextempty_mod: Nat#BBuf#Nat#Pos -> Nat; q1,q2:DBuf; var d,d':D; i,j,m: Nat; q: DBuf; c,c':Bool; n':Pos; b:BBuf; eqn q1 = [d1, d1]; q2 = q1; empty = [false,false]; i == 0 -> insert(d,i,q) = d |> tail(q); i > 0 -> insert(d,i, d'|>q) = d' |> insert(d,Int2Nat(i-1),q); i == 0 -> insert(c,i,b) = c |> tail(b); i > 0 -> insert(c,i,c'|>b) = c' |> insert(c,Int2Nat(i-1),b); b.(i mod n') && m>0 -> nextempty_mod(i,b,m,n') = nextempty_mod((i+1) mod 2*n', b,Int2Nat(m-1),n'); !(b.(i mod n') && m>0) -> nextempty_mod(i,b,m,n') =i mod 2*n'; act r1,s4: D; s2,r2,c2,s3,r3,c3: D#Nat; s5,r5,c5,s6,r6,c6: Nat; i; proc S(l,m:Nat,q:DBuf) = sum d:D. (m r1(d).S(l,m+1,insert(d,(l+m) mod n,q))<>delta+ sum k:Nat. (k s2(q.((l+k) mod n),(l+k) mod 2*n).S(l,m,q)<>delta+ sum k:Nat. r6(k).S(k,(m-k+l) mod 2*n,q); R(l':Nat,q':DBuf,b:BBuf) = sum d:D,k:Nat. r3(d,k).(((k-l') mod (2*n) < n) -> R(l',insert(d,k mod n,q'),insert(true,k mod n,b)) <> R(l',q',b))+ (b.(l' mod n)) -> s4(q'.(l' mod n)). R((l'+1) mod 2*n,q',insert(false,l' mod n,b))<>delta+ s5(nextempty_mod(l',b,n,n)).R(l',q',b); K = sum d:D,k:Nat. r2(d,k).(i.s3(d,k)+i).K; L = sum k:Nat. r5(k).(i.s6(k)+i).L; SWP(q,q':DBuf)= allow({c2,c3,c5,c6,i,r1,s4}, comm({r2|s2->c2, r3|s3->c3, r5|s5->c5, r6|s6->c6}, S(0,0,q) || K || L || R(0,q',empty))); init SWP(q1,q1); mcrl2-201409.0/examples/academic/swp/swp_with_tanenbaums_bug.mcrl2000770 001750 001750 00000026014 12370120075 025374 0ustar00outisoutis000000 000000 % This file describes the third sliding window protocol in Computer Networks % by A.S. Tanenbaum, Prentice Hall, 1988. In earlier editions of this book % (up till the fourth edition) the most complex sliding window protocol % (i.e. the protocol using selective repeat, section 4.2.3 (first edition), % 4.4.3 (second editions) and section 3.4.3 (fourth edition)) % exhibits a nasty livelock. This livelock occurs when the acknowledgement % timer is switched off, after a first acknowledgement is lost in transmission. % The comment in the code says in Tanenbaum's enjoyable writing style % "no need for separate ack frame". If the protocol is used unidirectionally, % i.e., when no piggy backing can be used, no acknowledgements are sent from % this point, unless new data is transmitted and received. In the rare case % that the timer is switched off when all data in the sender has been % received by the receiving entity, retransmitted data by the sender % is ignored. Therefore, no new data is received at the sender, and % the acknowledgement timer is not switched on again. The result is that % data is continuously being retransmitted from sender to receiver and % never acknowledged. % The protocol has been described in PSF (Process Specification Formalism, % defined by S. Mauw and G.J. Veltink). This has been done by J.J. Brunekreef, % a formal specification of three sliding window protocols, technical report % P9102, programming research group, university of Amsterdam, 1991. This % description (of >>750 lines) is translated to mCRL2 below (this file % unfortunately is also quite lengthy, appr. 200 lines). It is expected that % using functions, instead of lists, a more compact specification is possible, % but then the description would divert too much from the description of % Brunekreef. % The livelock in Tanenbaum's protocol was detected in an attempt to % prove the correctness of this protocol by me in the summer of 1991. The error was % communicated to Tanenbaum, but he indicated not to be interested in it, % as he indicated: "For a decade this protocol has been implemented by several % groups of students. None of these students ever came to me indicating that % there is a problem with this protocol. And now you say that you found a % bug with formal techniques. Clearly this cannot be a serious problem". However, % others have apparently detected the bug in "more ordinary" ways, as, as said above, % from edition 4 of Computer Networks, the bug does not occur anymore. % Below the bug occurs when the action "error" can occur. Actually, as the % problem takes place when the sender's buffer is full, the receiver received % all data the sender sent, and the timer is switched off, the error is % a communication of three actions, error1, error2 and error3. For larger % values of MaxBuf, it is interesting to see how effective bughunting % strategies are. For MaxBuf=1, the problem occurs after 9 interactions, % for MaxBuf=2 the problem occurs after 17 actions, etc. % Besides the bug, the protocol is also interesting for another reason. % The external behaviour of the protocol is appalling. The protocol can % unpredictably force the processes that use the protocol to accept sequences % of data, without being able to send data in the mean time. As such it % is my expectation that this external behaviour of the sliding window % protocol below can only be most compactly described by the processes below. % An acceptable external behaviour would consist of two independent queues. % Minor changes in the sliding window protocol can already have this effect, % by decoupling delivery and acceptance of data. % % Jan Friso Groote, February 2007. % Translation is revised in May 2007, by removing an error in the translation % and by making channels and lists finite, such that a finite state space % can be generated. sort CS=struct accept | deliver | error | lost; % Data packets sort DP = struct d1 | d2; % restricted to two data packets, for simulation. % The constants MaxSeq en MaxBuf map MaxSeq,MaxBuf,ChannelBufferSize : Pos; eqn MaxBuf = 2; % An arbitrary constant MaxSeq = MaxBuf + MaxBuf; ChannelBufferSize=1; % The inWindow condition map inWindow:Nat#Nat#Nat -> Bool; seq:Nat#Nat#Nat -> Bool; wrap:Nat#Nat#Nat -> Bool; var fr,low,upp:Nat; eqn inWindow(fr,low,upp) = seq(fr,low,upp) || wrap(fr,low,upp); seq(fr,low,upp) = upp>low && fr>=low && fr=low || frBool; retr:Nat#Buffer->DP; del:Nat#Buffer->Buffer; insert:DP#Nat#Buffer->Buffer; var k,k':Nat; p,p':DP; b:Buffer; eqn b==[] -> in_table(k,b) = false; in_table(k,item(p,k')|>b) = (k==k')||in_table(k,b); b==[] -> del(k,b) = []; del(k,item(p,k')|>b) = if(k==k',del(k,b),item(p,k')|>del(k,b)); retr(k,item(p,k')|>b) = if(k==k',p,retr(k,b)); b==[] -> insert(p,k,b) = [item(p,k)]; insert(p,k,item(p',k')|>b) = if(kitem(p',k')|>b, if(k==k',item(p,k)|>b, item(p',k')|>insert(p,k,b))); % TTAB contains a list of indices for which a timer is set sort TTAB=List(Nat); map in_table:Nat#TTAB->Bool; del:Nat#TTAB->TTAB; insert:Nat#TTAB->TTAB; var n,n':Nat; t:TTAB; eqn t==[] -> in_table(n,t) = false; in_table(n,n'|>t) = (n==n')|| in_table(n,t); t==[] -> del(n,t) = []; del(n,n'|>t) = if(n==n',del(n,t),n'|>del(n,t)); t==[] -> insert(n,t) = [n]; insert(n,n'|>t) = if(nn'|>t,if(n==n',n|>t,n'|>insert(n,t))); % The data type for Frames sort Fid = struct dat | ack | nak; Frame = struct ce | defr | dframe(Fid,DP,Nat,Nat) | naframe(Fid,Nat); % Timer data types sort Tis = struct start | stop; Act = struct act_; % The description of a channel. act skip,lost; rc1,sc2:Frame; % This is a channel with limited capacity. If the channel is full, % the newly entered element replaces the last element that was entered into the channel. proc CH(cq:List(Frame),cs:CS) = sum fr:Frame.rc1(fr).((#cq CH(fr|>cq,cs) <> CH(fr|>tail(cq),cs)) + (cs==accept && (#cq)!=0) -> (skip.CH(cq,deliver) + skip.CH(cq,lost) + skip.CH(cq,error))<>delta+ (cs==deliver && #cq!=0) -> sc2(rhead(cq)).CH(rtail(cq),accept)<>delta+ (cs==error && #cq!=0) -> sc2(ce).CH(rtail(cq),accept)<>delta+ (cs==lost && #cq!=0) -> lost.CH(rtail(cq),accept)<>delta; % The sliding window protocol entity act ri1,si2 : DP; si3,ri4 : Frame; si5 : Tis # Nat; si5 : Tis # Act; ri6 : Nat; ri6 : Act; proc IMP = IMP(0,0,0,[],[],false); IMP(fts,fta,ftr:Nat,sbuf,rbuf:Buffer,nfs:Bool) = ((fta+MaxBuf) mod MaxSeq==fts) -> error2(fts).IMP(fts,fta,ftr,sbuf,rbuf,nfs)<>delta+ error3(ftr).IMP(fts,fta,ftr,sbuf,rbuf,nfs)+ ((((fts+MaxBuf) mod MaxSeq)!=fta) -> ( sum d:DP.ri1(d). si3(dframe(dat,d,fts,(ftr-1) mod MaxSeq)). si5(start,fts). IMP((fts+1) mod MaxSeq,fta,ftr,insert(d,fts,sbuf),rbuf,nfs))<>delta) + sum e:DP,rfr:Nat,rac:Nat. ri4(dframe(dat,e,rfr,rac)). ((ftr==rfr)->DEL(fts,fta,ftr,rac,sbuf,insert(e,rfr,rbuf),nfs) <>(nfs -> TORB(fts,fta,ftr,rfr,rac,e,sbuf,rbuf,true) <> si3(naframe(nak,(ftr-1) mod MaxSeq)). si5(stop,act_). TORB(fts,fta,ftr,rfr,rac,e,sbuf,rbuf,true)))+ sum rac:Nat. ri4(naframe(nak,rac)). (inWindow((rac+1) mod MaxSeq,fta,fts) -> si3(dframe(dat,retr((rac+1) mod MaxSeq,sbuf),(rac+1) mod MaxSeq,(ftr-1) mod MaxSeq)). si5(start,(rac+1) mod MaxSeq). ACK(fts,fta,ftr,rac,sbuf,rbuf,nfs) <> ACK(fts,fta,ftr,rac,sbuf,rbuf,nfs)) + sum rac:Nat.ri4(naframe(ack,rac)).ACK(fts,fta,ftr,rac,sbuf,rbuf,nfs) + ri4(ce).(nfs -> IMP(fts,fta,ftr,sbuf,rbuf,true) <> si3(naframe(nak,(ftr-1) mod MaxSeq)). si5(stop,act_). IMP(fts,fta,ftr,sbuf,rbuf,true))+ sum tfs:Nat.ri6(tfs). si3(dframe(dat,retr(tfs,sbuf),tfs,(ftr-1) mod MaxSeq)). si5(start,tfs). IMP(fts,fta,ftr,sbuf,rbuf,nfs) + ri6(act_).si3(naframe(ack,(ftr-1) mod MaxSeq)).IMP(fts,fta,ftr,sbuf,rbuf,nfs) ; DEL(fts,fta,ftr,rac:Nat,sbuf,rbuf:Buffer,nfs:Bool) = in_table(ftr,rbuf) -> si2(retr(ftr,rbuf)).DEL(fts,fta,(ftr+1) mod MaxSeq,rac,sbuf,del(ftr,rbuf),false) <> si5(start,act_).ACK(fts,fta,ftr,rac,sbuf,rbuf,nfs); TORB(fts,fta,ftr,rfr,rac:Nat,e:DP,sbuf,rbuf:Buffer,nfs:Bool) = (inWindow(rfr,ftr,(ftr+MaxBuf) mod MaxSeq) && !in_table(rfr,rbuf)) -> ACK(fts,fta,ftr,rac,sbuf,insert(e,rfr,rbuf),nfs) <> ACK(fts,fta,ftr,rac,sbuf,rbuf,nfs); ACK(fts,fta,ftr,rac:Nat,sbuf,rbuf:Buffer,nfs:Bool) = inWindow(rac,fta,fts) -> si5(stop,fta).ACK(fts,(fta+1) mod MaxSeq,ftr,rac,sbuf,rbuf,nfs) <> IMP(fts,fta,ftr,sbuf,rbuf,nfs); % The specification of a timer. act rt1 : Tis # Nat; rt1 : Tis # Act; st2 : Nat; st2 : Act; proc TIM = TIM([],false); TIM(ttab:TTAB,atr:Bool) = sum fn1:Nat.rt1(start,fn1).TIM(insert(fn1,ttab),false) + rt1(start,act_).TIM(ttab,true) + rt1(stop,act_).TIM(ttab,false) + sum fn2:Nat.in_table(fn2,ttab) -> (rt1(stop,fn2) + st2(fn2)).TIM(del(fn2,ttab),atr)<>delta + atr -> st2(act_).TIM(ttab,false) <> sum n:Nat.error1(n).TIM(ttab,atr); % Below all the components above are combined into one process. act ra,rd,sb,sc:DP; s1,r1,c1:Frame; s2,r2,c2:Frame; s3,r3,c3:Tis#Nat; s3,r3,c3:Tis#Act; s4,r4,c4:Nat; s4,r4,c4:Act; s5,r5,c5:Frame; s6,r6,c6:Frame; s7,r7,c7:Tis#Nat; s7,r7,c7:Tis#Act; s8,r8,c8:Nat; s8,r8,c8:Act; error,error1,error2,error3:Nat; proc IMPa=block({error3},rename({ri1->ra, si2->sb, si3->s1, ri4->r2, si5->s3, ri6->r4},IMP)); IMPb=block({error2},rename({ri1->rd, si2->sc, si3->s6, ri4->r5, si5->s7, ri6->r8},IMP)); CHab=rename({rc1->r1, sc2->s5},CH([],accept)); CHba=rename({rc1->r6, sc2->s2},CH([],accept)); TIMa=block({error1},rename({rt1->r3, st2->s4},TIM)); TIMb=rename({rt1->r7, st2->s8},TIM); SWP3 = hide({c1,c2,c3,c4,c5,c6,c7,c8,skip,lost}, allow({ra,rd,sb,sc,c1,c2,c3,c4,c5,c6,c7,c8,skip,lost,error}, comm({ s1|r1 -> c1, s2|r2 -> c2, s3|r3 -> c3, s4|r4 -> c4, s5|r5 -> c5, s6|r6 -> c6, s7|r7 -> c7, s8|r8 -> c8, error1|error2|error3 -> error}, IMPa || TIMa || CHab || IMPb || TIMb || CHba))); init SWP3; mcrl2-201409.0/examples/academic/swp/infinitely_often_enabled_then_infinitely_often_taken.mcf000770 001750 001750 00000000626 12370120075 033051 0ustar00outisoutis000000 000000 % If an r1 action is enabled infinitely often, then it is also % taken infinitely often, independent of the message d % Taken from: "Modal logics and mu-calculi: an introduction", % by Bradfield and Stirling. % % This formula is not true for the alternating bit protocol, as there is no % fairness assumption. forall d:D . ([true*] nu X. mu Y. nu Z. ([r1(d)]X && ([r1(d)]false || [!r1(d)]Y) && [!r1(d)]Z)) mcrl2-201409.0/examples/academic/abp/infinitely_often_receive_for_all_d.mcf000770 001750 001750 00000000323 12370120074 027177 0ustar00outisoutis000000 000000 % For all messages d, it is possible to infinitely often start % sending message d (through action r1). % % This property holds for the alternating bit protocol. forall d:D . nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/abp/read_then_eventually_send_if_fair.mcf000770 001750 001750 00000000654 12370120074 027027 0ustar00outisoutis000000 000000 % All messages d are (once they have been read through action r1) % inevitably sent through action s4, if not permanently lost (via % internal action i). % % Essentially this is the same property as the one in % "read_then_eventually_send.mcf", but it adds a fairness assumption % (a message is not lost infinitely often). nu X. ( [true]X && forall d:D. ([r1(d)]( nu Y. mu Z. ([(!s4(d)) && (!i)]Z && [i]Y) ) ) ) mcrl2-201409.0/examples/academic/abp/nodeadlock.mcf000770 001750 001750 00000000142 12370120074 022231 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. [true*]true mcrl2-201409.0/examples/academic/abp/run.py000770 001750 001750 00000003106 12370120074 020620 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v abp.mcrl2 abp.lps') os.system('lps2pbes -v -f nodeadlock.mcf abp.lps abp.nodeadlock.pbes') os.system('pbes2bool -v abp.nodeadlock.pbes') os.system('lps2pbes -v -f infinitely_often_enabled_then_infinitely_often_taken.mcf abp.lps abp.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('pbes2bool -v abp.infinitely_often_enabled_then_infinitely_often_taken.pbes') os.system('lps2pbes -v -f infinitely_often_lost.mcf abp.lps abp.infinitely_often_lost.pbes') os.system('pbes2bool -v abp.infinitely_often_lost.pbes') os.system('lps2pbes -v -f infinitely_often_receive_d1.mcf abp.lps abp.infinitely_often_receive_d1.pbes') os.system('pbes2bool -v abp.infinitely_often_receive_d1.pbes') os.system('lps2pbes -v -f infinitely_often_receive_for_all_d.mcf abp.lps abp.infinitely_often_receive_for_all_d.pbes') os.system('pbes2bool -v abp.infinitely_often_receive_for_all_d.pbes') os.system('lps2pbes -v -f read_then_eventually_send.mcf abp.lps abp.read_then_eventually_send.pbes') os.system('pbes2bool -v abp.read_then_eventually_send.pbes') os.system('lps2pbes -v -f read_then_eventually_send_if_fair.mcf abp.lps abp.read_then_eventually_send_if_fair.pbes') os.system('pbes2bool -v abp.read_then_eventually_send_if_fair.pbes') os.system('lps2pbes -v -f no_generation_of_messages.mcf abp.lps abp.no_generation_of_messages.pbes') os.system('pbes2bool -v abp.no_generation_of_messages.pbes') os.system('lps2pbes -v -f no_duplication_of_messages.mcf abp.lps abp.no_duplication_of_messages.pbes') os.system('pbes2bool -v abp.no_duplication_of_messages.pbes') mcrl2-201409.0/examples/academic/abp/no_duplication_of_messages.mcf000770 001750 001750 00000000325 12370120074 025513 0ustar00outisoutis000000 000000 % The protocol does not duplicate messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis [true*] forall d:D. [r1(d).(!r1(d) && !s4(d))*.s4(d).(!r1(d))*.s4(d)]false mcrl2-201409.0/examples/academic/abp/abp.mcrl2000770 001750 001750 00000001630 12370120074 021145 0ustar00outisoutis000000 000000 % This file contains the alternating bit protocol, as described in W.J. % Fokkink, J.F. Groote and M.A. Reniers, Modelling Reactive Systems. % % The only exception is that the domain D consists of two data elements to % facilitate simulation. sort D = struct d1 | d2; Error = struct e; act r1,s4: D; s2,r2,c2: D # Bool; s3,r3,c3: D # Bool; s3,r3,c3: Error; s5,r5,c5: Bool; s6,r6,c6: Bool; s6,r6,c6: Error; i; proc S(b:Bool) = sum d:D. r1(d).T(d,b); T(d:D,b:Bool) = s2(d,b).(r6(b).S(!b)+(r6(!b)+r6(e)).T(d,b)); R(b:Bool) = sum d:D. r3(d,b).s4(d).s5(b).R(!b)+ (sum d:D.r3(d,!b)+r3(e)).s5(!b).R(b); K = sum d:D,b:Bool. r2(d,b).(i.s3(d,b)+i.s3(e)).K; L = sum b:Bool. r5(b).(i.s6(b)+i.s6(e)).L; init allow({r1,s4,c2,c3,c5,c6,i}, comm({r2|s2->c2, r3|s3->c3, r5|s5->c5, r6|s6->c6}, S(true) || K || L || R(true) ) ); mcrl2-201409.0/examples/academic/abp/infinitely_often_lost.mcf000770 001750 001750 00000000606 12370120074 024541 0ustar00outisoutis000000 000000 % There is a path along which a message (after reading through % action r1) can be lost infinitely often (through c3). % % This property is true for the alternating bit protocol, because there is % no fairness assumption. % % Note: e as parameter of c3 means an error is communicated, hence a message % was lost. (exists d:D .(nu X. mu Y. (X || Y))) mcrl2-201409.0/examples/academic/abp/no_generation_of_messages.mcf000770 001750 001750 00000000276 12370120074 025340 0ustar00outisoutis000000 000000 % The protocol does not generate new messages % Obtained from: "Tools for parameterized Boolean Equation Systems", % S. Janssen, MSc. thesis forall d: D. nu X. (([!r1(d)]X && [s4(d)]false)) mcrl2-201409.0/examples/academic/abp/infinitely_often_receive_d1.mcf000770 001750 001750 00000000266 12370120074 025570 0ustar00outisoutis000000 000000 % It is possible to infinitely often start sending a d1 message % (through action r1) % % This property holds for the alternating bit protocol. nu X. mu Y. (X || Y) mcrl2-201409.0/examples/academic/abp/read_then_eventually_send.mcf000770 001750 001750 00000000721 12370120074 025343 0ustar00outisoutis000000 000000 % Formula that expresses that if a message is read through r1, then it is % eventually send through s4. % This property does not hold for the alternating bit protocol, as it does not % assume fairness. This can be shown by the formula "infinitely_often_lost.mcf" % % The file "read_then_eventually_send_if_fair.mcf" contains a formula that % shows that the property holds if fairness is assumed. [true*](forall d:D .([r1(d)](nu X. mu Y. ([s4(d)]X && [!s4(d)]Y)))) mcrl2-201409.0/examples/academic/abp/infinitely_often_enabled_then_infinitely_often_taken.mcf000770 001750 001750 00000000626 12370120074 033001 0ustar00outisoutis000000 000000 % If an r1 action is enabled infinitely often, then it is also % taken infinitely often, independent of the message d % Taken from: "Modal logics and mu-calculi: an introduction", % by Bradfield and Stirling. % % This formula is not true for the alternating bit protocol, as there is no % fairness assumption. forall d:D . ([true*] nu X. mu Y. nu Z. ([r1(d)]X && ([r1(d)]false || [!r1(d)]Y) && [!r1(d)]Z)) mcrl2-201409.0/examples/academic/allow/allow.mcrl2000770 001750 001750 00000003221 12370120075 022074 0ustar00outisoutis000000 000000 % Workers (allow-specification) % % This is an artificial constructed specification with workers. Each worker % executes a particular task and has a unique ID. Some tasks require % that other workers are put to work. % If a worker needs to address another worker, it selects the worker % with the lowest ID, that is not occupied. When a worker has completed % a task, it sends a notification to the worker that has delegated the task. % There are three kinds of workers: % * A hard worker: Immediately executes an addressed task. (S) % * A messenger: Takes a task and delivers it to another worker. A messenger % cannot accept a new task until the delegated task has been % completed. (P) % * A lazy worker: Takes a task and delivers it simultaneously to two other % workers. A lazy worker cannot accept a new task, when it has % delegated a task. A lazy worker only accepts the % notification of delegated tasks when both task are completed. (M1) % Only hard workers require resources. This specification allows up to 4 % hard workers to execute tasks. % % Created by Frank Stappers, % 16 June 2009 act s,s',d,d': Nat; proc P(n: Nat) = s(n).s(n+1).d(n+1).d(n).P(n); proc M1(n: Nat) = s(n). s(n+1)|s(n+2). d(n+1)|d(n+2).d(n).M1(n); proc S(n: Nat) = s(n).d(n).S(n); init allow( { s' , s' | s' , s' | s' | s' , s' | s' | s' | s' , d' , d' | d' , d' | d' | d' , d' | d' | d' | d' }, comm( { s | s -> s' , d | d -> d' } , P(0) || M1(1) || S(2) || S(3) || P(4) || P(5) || S(6) || (s(0).s(0)) ) ) ; mcrl2-201409.0/examples/academic/allow/nodeadlock.mcf000770 001750 001750 00000000224 12370120075 022607 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/allow/run.py000770 001750 001750 00000001076 12370120075 021201 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v allow.mcrl2 allow.lps') os.system('lps2pbes -v -f nodeadlock.mcf allow.lps allow.nodeadlock.pbes') os.system('pbes2bool -v allow.nodeadlock.pbes') # The above shows that there is a deadlock in the specification. # Let's investigate # The following creates state space, and stores trace to deadlock. os.system('lps2lts -v -Dt allow.lps allow.aut') # Print the trace and find out what's wrong: os.system('tracepp allow.lps_dlk_0.trc') # The same is also immediately clear if we visualise the state space os.system('ltsgraph allow.aut') mcrl2-201409.0/examples/academic/par/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022252 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/par/run.py000770 001750 001750 00000000436 12370120074 020643 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v par.mcrl2 par.lps') os.system('lps2pbes -v -f nodeadlock.mcf par.lps par.nodeadlock.pbes') os.system('pbes2bool -v par.nodeadlock.pbes') # The following creates state space, and stores trace to deadlock. os.system('lps2lts -v -Dt par.lps par.aut') mcrl2-201409.0/examples/academic/par/par.mcrl2000770 001750 001750 00000005240 12370120074 021206 0ustar00outisoutis000000 000000 % This file contains the par protocol as described in section 3.4 of % S. Mauw and G.J. Veltink, editors, Algebraic Specification of Communication % Protocols, Cambridge tracts in theoretical computer science 36, Cambridge % University Press, Cambridge 1993. % % With two data elements, the generated transition system has 91 states. % % Note that the protocol is slightly different from the alternating bit protocol. % Is is interesting to see the subtle, but definitive differences between the % two implementations of the protocols, although the external behaviour is the % same. % % Translated from muCRL, 30/12/2006, Jan Friso Groote %------------------------------- DATA ---------------------------------- sort DATA = struct d1 | d2; %------------------------------- error ---------------------------------- sort error = struct ce | ae; %------------------------------- Bit ------------------------------------ sort Bit = struct bit0 | bit1; map invert:Bit -> Bit; eqn invert(bit1)=bit0; invert(bit0)=bit1; %------------------------------- Frame ---------------------------------- sort Frame = struct frame (getd:DATA,getb:Bit); %------------------------------ ACK ----------------------------------- sort ACK = struct ac; %------------------------------ TimerSignal ----------------------------- sort TimerSignal = struct st | ti | eto; %------------------------------ act ----------------------------------- act r1,s2 : DATA; c3,r3,s3,c4,s4,r4 : Frame; c5,r5,s5,c6,r6,s6 : ACK; c4,r4,s4,c6,r6,s6 : error; c7,r7,s7,c8,r8,s8,c9,r9,s9 : TimerSignal; skip; %------------------------------ proc ----------------------------------- proc S = RM(bit0); RM(b:Bit) = sum d:DATA.r1(d).ST(frame(d,b)); ST(f:Frame) = s7(st).SF(f); SF(f:Frame) = s3(f).RA(f); RA(f:Frame) = (r9(ti)+r6(ae)).ST(f)+r6(ac).RM(invert(getb(f))); Ti = r7(st).TR; TR = r7(st).TR+r8(eto).TE; TE = s9(ti).Ti; K = sum f:Frame.r3(f).K1(f); K1(f:Frame) = (skip+skip.s4(ce)).K2 + skip.s4(f).K; K2 = s8(eto).K; R = RF(bit0); RF(b:Bit) = sum d:DATA.r4(frame(d,b)).SM(frame(d,b)) + sum d:DATA.r4(frame(d,invert(b))).SA(b) + r4(ce).RF(b); SA(b:Bit) = s5(ac).RF(b); SM(f:Frame) = s2(getd(f)).SA(invert(getb(f))); L = r5(ac).L1; L1 = ( skip.s6(ae) + skip.s6(ac) ). L + skip.L2; L2 = s8(eto).L; init hide({c3,c4,c5,c6,c7,c8,c9,skip}, allow({r1,s2,c3,c4,c5,c6,c7,c8,c9,skip}, comm({r3|s3->c3, r4|s4->c4, r5|s5->c5, r6|s6->c6, r7|s7->c7, r8|s8->c8, r9|s9->c9}, S || K || R || L || Ti ))); mcrl2-201409.0/examples/academic/parallel_proc_with_global_var/parallel_counting.mcf000770 001750 001750 00000000340 12370120074 031130 0ustar00outisoutis000000 000000 % Check that the number 738 can be reached. < true*. report_c(738)>true % The formula below expresses that any value % can be reached, but this cannot be solved % automatically % % forall n:Pos. < true*. report_c(n)>true mcrl2-201409.0/examples/academic/parallel_proc_with_global_var/run.py000770 001750 001750 00000000345 12370120074 026122 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vnf parallel_counting.mcrl2 temp.lps') os.system('lps2pbes -v -fparallel_counting.mcf temp.lps temp.pbes') os.system('pbes2bool -v -rjittyc -s2 temp.pbes') os.system('rm -f temp.lps temp.pbes') mcrl2-201409.0/examples/academic/parallel_proc_with_global_var/parallel_counting.mcrl2000770 001750 001750 00000002274 12370120074 031412 0ustar00outisoutis000000 000000 % This example describes a parallel counting process, % with a global variable c and local variables x. % A single counter is best described as % % do forever { x:=c; x:=x+c; c:=x }. % % If only one counter is running, then the values for % c can only be 1, 2, 4, 8, 16, etc. A remarkable % observation by Hans Zantema (who provided this example) % is that if the two processes are put in parallel, % c can attain any value. % % Using the modal formula % % true % % it can be checked that an particular value can % be reached. This property can easily be checked % using pbes2bool (still requiring >500.000) bes % variables. % % The formula % % forall n:Pos.true % % expresses that any value can be attained. As it % stands this can not be solved using the model % checking tools % % April 26, 2014. Jan Friso Groote act set_c,set_c_,set,get_c,get_c_,get,report_c:Pos; proc P= sum x:Pos.get_c(x). sum x':Pos.get_c(x'). set_c(x+x').P; proc C(c:Pos)=get_c_(c).C(c)+ sum c':Pos.set_c_(c').C(c')+ report_c(c).C(c); init allow({get,set,report_c}, comm({get_c|get_c_->get,set_c|set_c_->set}, P||P||C(1))); mcrl2-201409.0/examples/academic/producer_consumer/producer_consumer.mcrl2000770 001750 001750 00000001052 12370120074 027133 0ustar00outisoutis000000 000000 % producer consumer example % Chilo van Best, June 2008 % % This is a simple example of a process containing a deadlock. % Actions act P_in_start, P_out_started, Q_out_started, Q_in_start; act c1, c2; % Processes. proc % P P = P_in_start.P_out_started.P; % Q okay % Q = Q_out_started.Q_in_start.Q; % Q deadlock Q = Q_in_start.Q_out_started.Q; % And now make a network init allow({ c1, c2 }, comm({ P_in_start | Q_out_started -> c1, P_out_started | Q_in_start -> c2 }, P || Q )); mcrl2-201409.0/examples/academic/producer_consumer/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 025226 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/producer_consumer/run.py000770 001750 001750 00000001011 12370120074 023605 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v producer_consumer.mcrl2 producer_consumer.lps') os.system('lps2pbes -v -f nodeadlock.mcf producer_consumer.lps producer_consumer.nodeadlock.pbes') os.system('pbes2bool -v producer_consumer.nodeadlock.pbes') # The following creates state space, and stores trace to deadlock. os.system('lps2lts -v -Dt producer_consumer.lps producer_consumer.aut') # Print trace to deadlock os.system('tracepp producer_consumer.lps_dlk_0.trc') # The initial state is a deadlock, so the trace is empty mcrl2-201409.0/examples/academic/block/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022562 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on block. [true*]true mcrl2-201409.0/examples/academic/block/run.py000770 001750 001750 00000001076 12370120074 021154 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v block.mcrl2 block.lps') os.system('lps2pbes -v -f nodeadlock.mcf block.lps block.nodeadlock.pbes') os.system('pbes2bool -v block.nodeadlock.pbes') # The above shows that there is a deadlock in the specification. # Let's investigate # The following creates state space, and stores trace to deadlock. os.system('lps2lts -v -Dt block.lps block.aut') # Print the trace and find out what's wrong: os.system('tracepp block.lps_dlk_0.trc') # The same is also immediately clear if we visualise the state space os.system('ltsgraph block.aut') mcrl2-201409.0/examples/academic/block/block.mcrl2000770 001750 001750 00000002773 12370120074 022036 0ustar00outisoutis000000 000000 % Workers (block-specification) % % This is an artificial constructed specification with workers. Each worker % executes a particular task and has a unique ID. Some tasks required % that other workers are put to work. % If a worker needs to address another worker, it selects a worker % with the lowest ID value, which is not occupied. When a worker has completed % a task, it sends a notification to the worker that has delegated a task. % There are three kind of workers: % * A hard worker: Immediately executes an addressed task. (S) % * A messenger: Takes a task and delivers it to another worker. A messenger % cannot accept a new task until the delegated task has been % completed. (P) % * A lazy worker: Takes a task and delivers it simultaneously to two other % workers. A lazy worker cannot accept a new task, when it has % delegated a task. A lazy worker only accepts the % notification of delegated tasks when both task are completed. (M1) % Only hard workers require resources. This specification specifies unlimited % resources for hard workers. % % Created by Frank Stappers, % 16 June 2009 act s,s',d,d': Nat; proc P(n: Nat) = s(n).s(n+1).d(n+1).d(n).P(n); proc M1(n: Nat) = s(n). s(n+1)|s(n+2). d(n+1)|d(n+2).d(n).M1(n); proc S(n: Nat) = s(n).d(n).S(n); init block({s,d}, comm( { s | s -> s' , d | d -> d' } , P(0) || M1(1) || S(2) || P(3) || S(4) || (s(0).d(0)) ) ) ; mcrl2-201409.0/examples/academic/bke/nodeadlock.mcf000770 001750 001750 00000000224 12370120074 022231 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/academic/bke/run.py000770 001750 001750 00000000617 12370120074 020623 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vD bke.mcrl2 bke.lps') # Running any transformation does not have any effect, due to the following # error: # Error while exploring state space: error: term does not evaluate to true or false: address(E) == bad_address # (JK: Checked 14/9/2010) #os.system('lps2pbes -v -f nodeadlock.mcf bke.lps bke.nodeadlock.pbes') #os.system('pbes2bool -v bke.nodeadlock.pbes') mcrl2-201409.0/examples/academic/bke/bke.mcrl2000770 001750 001750 00000027555 12370120074 021161 0ustar00outisoutis000000 000000 % This model is translated from the mCRL model used for analysing the Bilateral % Key Exchange (BKE) protocol. The analysis is described in a paper with the % name "Analysing the BKE-security protocol with muCRL", by Jan Friso Groote, % Sjouke Mauw and Alexander Serebrenik. % % The translation of the existing mCRL model into this mCRL2 model has been % performed manually. The purpose was making use of the additional language % features of mCRL2 with respect to mCRL. % % The behaviour of this model should be bisimular with the original mcrl model % after renaming actions. Though this is not verified for all system % configurations below. % % Eindhoven, June 11, 2008, Jeroen van der Wulp % Agents. There are exactly three agents - A, B, E An order E < A < B is % imposed on agents to reduce the size of the state space. sort Agent = struct A | B | E; map less : Agent # Agent -> Bool; var a: Agent; eqn less(A,a) = (a == B); less(B,a) = false; less(E,a) = (a != E); sort Address = struct address(agent : Agent); map bad_address : Address; % A nonce is a random, unpredictable value which is used to make the % exchanged messages unique and thus helps to counter replay attacks. sort Nonce = struct nonce(value : Nat); % There are two kinds of keys used in the protocol: symmetric and % asymmetric ones (functional keys). % Symmetric keys have form K(n) where n is a natural number. sort SymmetricKey = struct symmetric_key(value : Nat); % Sort for representing asymmetric keys sort AsymmetricKey = struct public_key(Agent)?is_public | secret_key(Agent)?is_secret | hash(value : Nonce)?is_hash; map has_complementary_key: AsymmetricKey -> Bool; complementary_key : AsymmetricKey -> AsymmetricKey; var a : Agent; n : Nonce; eqn has_complementary_key(public_key(a)) = true; has_complementary_key(secret_key(a)) = true; has_complementary_key(hash(n)) = false; complementary_key(public_key(a)) = secret_key(a); complementary_key(secret_key(a)) = public_key(a); sort Key = struct key(SymmetricKey)?is_symmetric | key(AsymmetricKey)?is_asymmetric; map has_complementary_key: Key -> Bool; complementary_key : Key -> Key; % gets the complementary key if key is asymmetric var a,a1 : Agent; n,n1 : Nat; k,k1 : Key; ak,ak1 : AsymmetricKey; eqn % gets the complementary key if key is asymmetric complementary_key(key(ak)) = key(complementary_key(ak)); has_complementary_key(key(ak)) = has_complementary_key(ak); sort Message = struct encrypt(Nonce, Address, AsymmetricKey)?is_message_1 | encrypt(AsymmetricKey, Nonce, SymmetricKey, AsymmetricKey)?is_message_2 | encrypt(AsymmetricKey, SymmetricKey)?is_message_3; map valid_message_1 : Message # AsymmetricKey -> Bool; valid_message_2 : Message # AsymmetricKey -> Bool; valid_message_3 : Message # SymmetricKey -> Bool; used_key : Message -> Key; % key used to encrypt var sk, sk1 : SymmetricKey; ak, ak1, ak2 : AsymmetricKey; n, n1 : Nonce; m, m1 : Message; a, a1 : Address; eqn used_key(encrypt(n,a,ak)) = key(ak); used_key(encrypt(ak,n1,sk,ak1)) = key(ak1); used_key(encrypt(ak,sk)) = key(sk); valid_message_1(m, ak) = is_message_1(m) && (used_key(m) == key(ak)); valid_message_2(m, ak) = is_message_2(m) && (used_key(m) == key(ak)); valid_message_3(m, sk) = is_message_3(m) && (used_key(m) == key(sk)); % Type for message sets; currently cannot use Set() because set iteration is not possible sort MessageSet = List(Message); map insert : Message # MessageSet -> MessageSet; select_crypted_by : Key # MessageSet -> MessageSet; select_not_crypted_by : Key # MessageSet -> MessageSet; select : (Message -> Bool) # MessageSet -> MessageSet; var k,k1 : Key; m,m1 : Message; ms : MessageSet; c : Message -> Bool; eqn % inserts a message m, if it is not in the list insert(m,[]) = [m]; m < m1 -> insert(m,m1|>ms) = m|>m1|>ms; m == m1 -> insert(m,m1|>ms) = m1|>ms; m1 < m -> insert(m,m1|>ms) = m1|>insert(m,ms); % the set (as ordered list) of messages in m that are signed by sk select_crypted_by(k,ms) = select(lambda x : Message.k == used_key(x),ms); select_not_crypted_by(k,ms) = select(lambda x : Message.k != used_key(x),ms); select(c,[]) = []; select(c,m|>ms) = if(c(m),m|>r,r) whr r = select(c, ms) end; % The eavesdropper's knowledge consists of: % * a list of addresses % * a list of nonces % * a list of keys (both symmetric and asymmetric) % * a list of messages of which the key is not known sort Knowledge = struct knowledge(addresses : Set(Address), nonces : Set(Nonce), keys : Set(Key), messages : MessageSet); map update_knowledge : Message # Knowledge -> Knowledge; propagate : MessageSet # Knowledge -> Knowledge; propagate : Key # Knowledge -> Knowledge; add_key : Key # Knowledge -> Knowledge; add_nonce : Nonce # Knowledge -> Knowledge; add_address : Address # Knowledge -> Knowledge; var m : Message; as : Set(Address); ns : Set(Nonce); ks : Set(Key); ms : MessageSet; k : Knowledge; sk : SymmetricKey; ak,hk : AsymmetricKey; ck : Key; n, n1 : Nonce; a : Address; eqn % adds keys to knowledge that are part of known messages encrypted with a new key has_complementary_key(ak) && complementary_key(key(ak)) in keys(k) -> update_knowledge(encrypt(n,a,ak),k) = propagate(key(ak), add_key(key(ak), add_address(a, add_nonce(n, k)))); has_complementary_key(ak) && complementary_key(key(ak)) in keys(k) -> update_knowledge(encrypt(hk,n1,sk,ak),k) = propagate(key(sk), propagate(key(ak), add_key(key(sk),add_key(key(ak),k)))); key(sk) in keys(k) -> update_knowledge(encrypt(ak,sk),k) = propagate(key(ak), add_key(key(ak),k)); % adds a message that cannot be decrypted with any known key ((is_symmetric(ck) && !(ck in keys(k))) || (is_asymmetric(ck) && !(has_complementary_key(ck) && (complementary_key(ck) in keys(k))))) whr ck = used_key(m) end -> update_knowledge(m,k) = knowledge(addresses(k),nonces(k),keys(k),insert(m,messages(k))); % adds a key to knowledge add_key(ck,knowledge(as,ns,ks,ms)) = knowledge(as,ns,ks + {ck},ms); add_nonce(n,knowledge(as,ns,ks,ms)) = knowledge(as,ns + {n},ks,ms); add_address(a,knowledge(as,ns,ks,ms)) = knowledge(as + {a},ns,ks,ms); % adds keys to knowledge that are part of messages encrypted with a key k propagate([],k) = k; propagate(m|>ms,k) = propagate(ms, update_knowledge(m, k)); propagate(ck,knowledge(as,ns,ks,ms)) = propagate(select_crypted_by(ck,ms), knowledge(as,ns,ks,select_not_crypted_by(ck,ms))); act call_secret, hear_secret, secrecy_claim : SymmetricKey; % result handshake send, receive, communicate : Agent # Message; % (sender, message) send, receive, communicate : Agent # Nat; % (sender, nonce) not_secret; % forbidden action proc Initiator(self : Agent, n : Nat) = (sum a : Agent. receive(a, n). % initialisation send(self, encrypt(nonce(n),address(self),public_key(a))). (sum ak, ak1 : AsymmetricKey, nr : Nonce, sk : SymmetricKey. (ak == hash(nonce(n)) && valid_message_2(encrypt(ak,nr,sk,ak1),public_key(self))) -> receive(E, encrypt(ak,nr,sk,ak1)). send(self, encrypt(hash(nr), sk)). ((a != E) -> call_secret(sk)))); proc Responder(self : Agent, n : Nat) = (sum a : Agent. receive(a, n). % initialisation (sum ni : Nonce, ai : Address, aki : AsymmetricKey. (ai == address(a) && valid_message_1(encrypt(ni,ai,aki),public_key(self))) -> receive(E,encrypt(ni,ai,aki)). send(self,encrypt(hash(ni),nonce(n),symmetric_key(n),public_key(a))). (sum ak : AsymmetricKey, sk : SymmetricKey. ((a != E && ak == hash(nonce(n)) && valid_message_3(encrypt(ak,sk),symmetric_key(n))) -> receive(E, encrypt(ak,sk)). call_secret(symmetric_key(n)))))); % initialisation of processes % p is the number of parties proc InitialEavesdropper(p : Nat, aI : Agent, aR : Agent) = (p == 0) -> Eavesdropper(knowledge({address(A),address(B),address(E)}, {nonce(0)},{key(public_key(A)), key(public_key(B)), key(public_key(E)), key(secret_key(E)), key(symmetric_key(0))},[])) <> (sum a : Agent. send(a,p). (p mod 2 == 0) -> ((!less(a,aR)) -> InitialEavesdropper(Int2Nat(p - 1),aI,if(p == 2,E,a))) <> ((!less(a,aI) && ((p == 1 && aI == E) => (a != E))) -> InitialEavesdropper(Int2Nat(p - 1),if(p == 1,E,a),aR))); proc Eavesdropper(k : Knowledge) = % receives message and adds to knowledge (sum a : Agent, m : Message. receive(a, m). Eavesdropper(update_knowledge(m,k))) + % send an message of type 1 by combining arbitrary known information (sum n : Nonce.(n in nonces(k)) -> (sum a1 : Address.(a1 in addresses(k)) -> (sum ak : AsymmetricKey.(key(ak) in keys(k)) -> send(E, encrypt(n,a1,ak)).Eavesdropper(k)))) + % send an message of type 2 by combining arbitrary known information (sum n : Nonce.(n in nonces(k)) -> (sum sk : SymmetricKey.(key(sk) in keys(k)) -> (sum ak : AsymmetricKey.(key(ak) in keys(k)) -> ((sum n1 : Nonce.(n1 in nonces(k)) -> send(E,encrypt(hash(n1),n,sk,ak)).Eavesdropper(k)) + (sum ak1 : AsymmetricKey.(key(ak1) in keys(k)) -> send(E,encrypt(ak1,n,sk,ak)).Eavesdropper(k)))))) + % send an message of type 3 by combining arbitrary known information (sum sk : SymmetricKey.(key(sk) in keys(k)) -> ((sum n : Nonce.(n in nonces(k)) -> send(E,encrypt(hash(n),sk)).Eavesdropper(k)) + (sum ak : AsymmetricKey.(key(ak) in keys(k)) -> send(E,encrypt(ak,sk)).Eavesdropper(k)))) + % send a known message (unchanged) (sum m : Message.(m in messages(k)) -> send(E,m).Eavesdropper(k)) + % deal with secrecy claim (sum sk : SymmetricKey.hear_secret(sk). (key(sk) in keys(k)) -> not_secret.Eavesdropper(k) <> Eavesdropper(k)); proc System1 = InitialEavesdropper(1,E,E) || Initiator(A,1); proc System2 = InitialEavesdropper(2,E,E) || Initiator(A,1) || Responder(B,2); proc System3 = InitialEavesdropper(3,E,E) || Initiator(A,1) || Responder(B,2) || Initiator(A,3); proc System4 = InitialEavesdropper(4,E,E) || Initiator(A,1) || Responder(B,2) || Initiator(A,3) || Responder(B,4); proc System5 = InitialEavesdropper(5,E,E) || Initiator(A,1) || Responder(B,2) || Initiator(A,3) || Responder(B,4) || Initiator(A,5); proc System6 = InitialEavesdropper(6,E,E) || Initiator(A,1) || Responder(B,2) || Initiator(A,3) || Responder(B,4) || Initiator(A,5) || Responder(B,6); proc System7 = InitialEavesdropper(7,E,E) || Initiator(A,1) || Responder(B,2) || Initiator(A,3) || Responder(B,4) || Initiator(A,5) || Responder(B,6) || Initiator(A,7); proc System8 = InitialEavesdropper(8,E,E) || Initiator(A,1) || Responder(B,2) || Initiator(A,3) || Responder(B,4) || Initiator(A,5) || Responder(B,6) || Initiator(A,7) || Responder(B,8); proc System9 = InitialEavesdropper(9,E,E) || Initiator(A,1) || Responder(B,2) || Initiator(A,3) || Responder(B,4) || Initiator(A,5) || Responder(B,6) || Initiator(A,7) || Responder(B,8) || Initiator(A,9); init allow({communicate,secrecy_claim,not_secret}, comm({call_secret|hear_secret->secrecy_claim, send|receive->communicate}, System4 )); mcrl2-201409.0/examples/pbes/datatypes.txt000770 001750 001750 00000000342 12370120075 020642 0ustar00outisoutis000000 000000 % The following PBES shows how user-defined types can be used in PBESs. sort D = struct d1 | d2; map invert: D -> D; eqn invert(d1) = d2; invert(d2) = d1; pbes nu X(d: D) = val(d == d1) && X(invert(d)); init X(d1); mcrl2-201409.0/examples/pbes/pbes_inst_tr_4.txt000770 001750 001750 00000000612 12370120075 021562 0ustar00outisoutis000000 000000 % This file contains PBES example 4, as described in: % % A. van Dam, B. Ploeger and T.A.C. Willemse. Instantiation for % Parameterised Boolean Equation Systems. Computer Science Report % 08-11, Eindhoven University of Technology (TU/e), 2008. pbes mu X(b: Bool, n: Nat) = (forall i: Nat. val(!b) || X(!b, i)) && (val(b) || val(n == 0) || X(b, Int2Nat(n-1))); init X(true, 0); mcrl2-201409.0/examples/pbes/pbes_inst_tr_1.txt000770 001750 001750 00000000532 12370120075 021560 0ustar00outisoutis000000 000000 % This file contains PBES example 1, as described in: % % A. van Dam, B. Ploeger and T.A.C. Willemse. Instantiation for % Parameterised Boolean Equation Systems. Computer Science Report % 08-11, Eindhoven University of Technology (TU/e), 2008. pbes nu X(b: Bool) = exists n: Nat. Y(n) && val(b); mu Y(n: Nat) = X(n >= 10); init X(true); mcrl2-201409.0/examples/pbes/overloading.txt000770 001750 001750 00000000341 12370120075 021154 0ustar00outisoutis000000 000000 % The following PBES shows how overloading of propositional variables % can be used in PBESs. pbes mu X = X(true); nu X(b: Bool) = X(b,false); mu X(b,c: Bool) = val(b) && val(c) && X(!b, !c); init X; mcrl2-201409.0/examples/pbes/pbes_inst_tr_5.txt000770 001750 001750 00000000747 12370120075 021574 0ustar00outisoutis000000 000000 % This file contains PBES example 5, as described in: % % A. van Dam, B. Ploeger and T.A.C. Willemse. Instantiation for % Parameterised Boolean Equation Systems. Computer Science Report % 08-11, Eindhoven University of Technology (TU/e), 2008. pbes mu X(b: Bool, n: Nat) = Y(b, n); nu Y(b: Bool, n: Nat) = (val(!b) || X(!b, n)) && (val(!b) || Y(b, n+1)) && (val(b) || val(n == 0) || Y(b, Int2Nat(n-1))); init X(true, 0); mcrl2-201409.0/examples/pbes/nonmonotonic.txt000770 001750 001750 00000000101 12370120075 021355 0ustar00outisoutis000000 000000 % The following PBES is not monotonic. pbes mu X = !X; init X; mcrl2-201409.0/examples/pbes/true.txt000770 001750 001750 00000000147 12370120075 017626 0ustar00outisoutis000000 000000 % The following is the simplest possible PBES: one that is vacuously true. pbes mu X = true; init X; mcrl2-201409.0/examples/pbes/pbes_inst_tr_3.txt000770 001750 001750 00000000457 12370120075 021570 0ustar00outisoutis000000 000000 % This file contains PBES example 3, as described in: % % A. van Dam, B. Ploeger and T.A.C. Willemse. Instantiation for % Parameterised Boolean Equation Systems. Computer Science Report % 08-11, Eindhoven University of Technology (TU/e), 2008. pbes nu X(n: Nat) = val(n != 1) && X(n + 1); init X(0); mcrl2-201409.0/examples/pbes/pbes_inst_tr_2.txt000770 001750 001750 00000000522 12370120075 021560 0ustar00outisoutis000000 000000 % This file contains PBES example 2, as described in: % % A. van Dam, B. Ploeger and T.A.C. Willemse. Instantiation for % Parameterised Boolean Equation Systems. Computer Science Report % 08-11, Eindhoven University of Technology (TU/e), 2008. pbes nu X(b: Bool) = val(b) && Y(!b); mu Y(b: Bool) = val(!b) || X(b); init X(true); mcrl2-201409.0/examples/games/knights/knights.mcrl2000770 001750 001750 00000012002 12370120141 022313 0ustar00outisoutis000000 000000 % This file describes a small puzzle. % Given a chess board filled with black and white knights as indicated % below by initialBoard. Can the knights change place, without % capturing opponent's pieces. This is modelled by the situation % indicated by finalBoard. % The process X below models two moves in a row, one for black and % one for white via the action jump. The action ready takes place % if the final situation has been reached. % The most effective way to do a state space search is using % % mcrl22lps -n knights.mcrl2 | lpsuntime > temp.lps % lpssuminst temp.lps temp1.lps % lpsstructelm -depth 10 temp1.lps temp2.lps [to replace the % list structure of the Board by explicit variables] % lps2lts -Rjittyc -v -aready temp2.lps | less % % There are 35144889 states at 19 levels. The action ready % is found at the end. There are 36 moves necessary to % exchange the positions of the black and white horses. %------------------------------------------------------------------ % differ1 and differ2 are used to check whether a move of a % knight is valid %------------------------------------------------------------------ map differ1,differ2:Pos#Pos->Bool; var p,p':Pos; eqn differ1(p,p')=if(p>p',p-p'==1,p'-p==1); differ2(p,p')=if(p>p',p-p'==2,p'-p==2); %------------------------------------------------------------------ % definition of the playing board %------------------------------------------------------------------ sort Piece = struct black | white | empty; Row = struct row(Piece,Piece,Piece,Piece,Piece); Board = struct col(Row,Row,Row,Row,Row); %------------------------------------------------------------------ % Dedicated definitions %------------------------------------------------------------------ map getPiece:Pos#Pos#Board -> Piece; setPiece:Pos#Pos#Piece#Board->Board; var p:Pos; r1,r2,r3,r4,r5:Row; pc:Piece; eqn getPiece(1,p,col(r1,r2,r3,r4,r5))=getPiece(p,r1); getPiece(2,p,col(r1,r2,r3,r4,r5))=getPiece(p,r2); getPiece(3,p,col(r1,r2,r3,r4,r5))=getPiece(p,r3); getPiece(4,p,col(r1,r2,r3,r4,r5))=getPiece(p,r4); getPiece(5,p,col(r1,r2,r3,r4,r5))=getPiece(p,r5); setPiece(1,p,pc,col(r1,r2,r3,r4,r5))= col(setPiece(p,pc,r1),r2,r3,r4,r5); setPiece(2,p,pc,col(r1,r2,r3,r4,r5))= col(r1,setPiece(p,pc,r2),r3,r4,r5); setPiece(3,p,pc,col(r1,r2,r3,r4,r5))= col(r1,r2,setPiece(p,pc,r3),r4,r5); setPiece(4,p,pc,col(r1,r2,r3,r4,r5))= col(r1,r2,r3,setPiece(p,pc,r4),r5); setPiece(5,p,pc,col(r1,r2,r3,r4,r5))= col(r1,r2,r3,r4,setPiece(p,pc,r5)); map getPiece:Pos#Row -> Piece; setPiece:Pos#Piece#Row -> Row; var p:Pos; p1,p2,p3,p4,p5: Piece; pc:Piece; eqn setPiece(1,pc,row(p1,p2,p3,p4,p5))=row(pc,p2,p3,p4,p5); setPiece(2,pc,row(p1,p2,p3,p4,p5))=row(p1,pc,p3,p4,p5); setPiece(3,pc,row(p1,p2,p3,p4,p5))=row(p1,p2,pc,p4,p5); setPiece(4,pc,row(p1,p2,p3,p4,p5))=row(p1,p2,p3,pc,p5); setPiece(5,pc,row(p1,p2,p3,p4,p5))=row(p1,p2,p3,p4,pc); getPiece(1,row(p1,p2,p3,p4,p5))=p1; getPiece(2,row(p1,p2,p3,p4,p5))=p2; getPiece(3,row(p1,p2,p3,p4,p5))=p3; getPiece(4,row(p1,p2,p3,p4,p5))=p4; getPiece(5,row(p1,p2,p3,p4,p5))=p5; map initialBoard,finalBoard:Board; eqn initialBoard=col(row(black,black,black,black,black), row(white,black,black,black,black), row(white,white,empty,black,black), row(white,white,white,white,black), row(white,white,white,white,white)); finalBoard=col(row(white,white,white,white,white), row(black,white,white,white,white), row(black,black,empty,white,white), row(black,black,black,black,white), row(black,black,black,black,black)); map isOccupied:Pos#Pos#Board->Bool; var p1,p2:Pos; f:Board; eqn isOccupied(p1,p2,f)= getPiece(p1,p2,f)!=empty; map isKnight'sMove:Pos#Pos#Pos#Pos->Bool; var p1,p2,q1,q2:Pos; eqn isKnight'sMove(p1,p2,q1,q2)= (differ1(p1,q1) && differ2(p2,q2)) || (differ2(p1,q1) && differ1(p2,q2)); %------------------------------------------------------------------ act jump, ready; % Jump from p1,p2 to q1,q2 and then from r1,r2 to p1,p2. % The final situation can only be reached after an even % number of moves (with each move the empty position moves % an odd number of steps, and therefore, the empty position % can never come back to the center after an odd number of % moves). Therefore, we can combine two moves into one, % reducing the state space by a factor 2. proc X(f:Board)= sum p1,p2,q1,q2,r1,r2:Pos. (p1<=5 && p2<=5 && q1<=5 && q2 <=5 && r1<=5 && r2<=5 && (r1!=q1 || r2!=q2) && !isOccupied(q1,q2,f) && isKnight'sMove(p1,p2,q1,q2) && isKnight'sMove(r1,r2,p1,p2) && f!=finalBoard) -> jump. X(setPiece(r1,r2,empty, setPiece(p1,p2,getPiece(r1,r2,f), setPiece(q1,q2,getPiece(p1,p2,f),f))))<>delta+ (f==finalBoard) -> ready.delta<>delta; init hide({jump},X(initialBoard)); mcrl2-201409.0/examples/games/knights/run.py000770 001750 001750 00000000101 12370120076 021065 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v knights.mcrl2 knights.lps') mcrl2-201409.0/examples/games/clobber/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 022450 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/games/clobber/run.py000770 001750 001750 00000000404 12370120076 021034 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v clobber.mcrl2 clobber.lps') os.system('lps2lts -vrjittyc clobber.lps clobber.svc') os.system('lps2pbes -v -f nodeadlock.mcf clobber.lps clobber.nodeadlock.pbes') os.system('pbes2bool -vrjittyc -s1 clobber.nodeadlock.pbes') mcrl2-201409.0/examples/games/clobber/clobber.mcrl2000770 001750 001750 00000007533 12370120076 022241 0ustar00outisoutis000000 000000 % This specification describes the game `Clobber', which is a two % player board game. There is a board of 8 by 8 (although below % we describe a board of 4 by 4, as otherwise the state space is % prohibitively big). One player has white pieces (0) and the % other has black pieces (X). Initially, the board is set up as: % % 0 X 0 X 0 X 0 X % X 0 X 0 X 0 X 0 % 0 X 0 X 0 X 0 X % X 0 X 0 X 0 X 0 % 0 X 0 X 0 X 0 X % X 0 X 0 X 0 X 0 % 0 X 0 X 0 X 0 X % X 0 X 0 X 0 X 0 % % Black makes the first move and players alternatingly make a move. A % player makes a turn by moving a piece % of its own color horizontally or vertically to a position with a % piece of the opposite color and it removes that piece. This is % the only move that is allowed. The first player that cannot do a % move looses the game. % % Thanks go to Mark Winands for explaining the game. % % Reijkjavik, May 9, 2006, Jan Friso Groote sort Position = struct Black | White | Empty; sort Direction = struct Up | Right | Down | Left; map N,M:Pos; eqn N=4; M=4; sort Row=List(Position); Board=List(Row); map At:Pos#Pos#Board->Position; At:Pos#Pos#Direction#Board->Position; At:Pos#Row->Position; Put:Position#Pos#Pos#Board->Board; Put:Position#Pos#Pos#Direction#Board->Board; Put:Position#Pos#Row->Row; CanMove:Pos#Pos#Position#Position#Board->Bool; var b:Board; r:Row; p,p':Position; x,y:Pos; eqn At(x,y,Up,b)=At(x,y+1,b); At(x,y,Right,b)=At(x+1,y,b); y>1 -> At(x,y,Down,b)=At(x,Int2Pos(y-1),b); y==1 -> At(x,y,Down,b)=Empty; x>1 -> At(x,y,Left,b)=At(Int2Pos(x-1),y,b); x==1 -> At(x,y,Left,b)=Empty; At(x,y,[])=Empty; y==1 -> At(x,y,r|>b)=At(x,r); y>M -> At(x,y,b)=Empty; 1 At(x,y,r|>b)=At(x,Int2Pos(y-1),b); At(x,[])=Empty; x==1 -> At(x,p|>r)=p; x>N -> At(x,p|>r)=Empty; 1 At(x,p|>r)=At(Int2Pos(x-1),r); Put(p,x,y,Up,b)=Put(p,x,y+1,b); Put(p,x,y,Right,b)=Put(p,x+1,y,b); y>1 -> Put(p,x,y,Down,b)=Put(p,x,Int2Pos(y-1),b); x>1 -> Put(p,x,y,Left,b)=Put(p,Int2Pos(x-1),y,b); y==1 -> Put(p,x,y,r|>b)=Put(p,x,r)|>b; y>1 -> Put(p,x,y,r|>b)=r|>Put(p,x,Int2Pos(y-1),b); x==1 -> Put(p,x,p'|>r)=p|>r; x>1 -> Put(p,x,p'|>r)=p'|>Put(p,Int2Pos(x-1),r); x==N && y==M -> CanMove(x,y,p,p',b)= At(x,y,b)==p && ( At(x,y,Down,b)==p' || At(x,y,Left,b)==p'); x==N && y CanMove(x,y,p,p',b)= (At(x,y,b)==p && (At(x,y,Up,b)==p' || At(x,y,Down,b)==p' || At(x,y,Left,b)==p')) || CanMove(1,y+1,p,p',b); x CanMove(x,y,p,p',b)= (At(x,y,b)==p && (At(x,y,Up,b)==p' || At(x,y,Right,b)==p' || At(x,y,Down,b)==p' || At(x,y,Left,b)==p')) || CanMove(x+1,y,p,p',b); act WhiteMove,BlackMove:Pos#Pos#Direction; WhiteWins,BlackWins; proc Clobber(b:Board,WhiteMoves:Bool)= sum x,y:Pos, dir:Direction. (WhiteMoves && x<=N && y<=M && At(x,y,b)==White && At(x,y,dir,b)==Black)-> WhiteMove(x,y,dir). Clobber(Put(White,x,y,dir,Put(Empty,x,y,b)),false)+ sum x,y:Pos, dir:Direction. (!WhiteMoves && x<=N && y<= M && At(x,y,b)==Black && At(x,y,dir,b)==White)-> BlackMove(x,y,dir). Clobber(Put(Black,x,y,dir,Put(Empty,x,y,b)),true)+ (WhiteMoves && !CanMove(1,1,White,Black,b)) -> BlackWins.Clobber(b,WhiteMoves)+ (!WhiteMoves && !CanMove(1,1,Black,White,b)) -> WhiteWins.Clobber(b,WhiteMoves)+ delta; init Clobber([[Black,White,Black,White], [White,Black,White,Black], [Black,White,Black,White], [White,Black,White,Black]],false); mcrl2-201409.0/examples/games/snake/white_has_winning_strategy.mcf000770 001750 001750 00000000316 12370120075 025465 0ustar00outisoutis000000 000000 % This formula encodes the property that white has a winning strategy, such that % he wins in a finite number of steps. % This assumes that Black makes the first move mu X. true || [true]X mcrl2-201409.0/examples/games/snake/run.py000770 001750 001750 00000001331 12370120075 020524 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vD snake.mcrl2 snake.lps') os.system('lps2lts -vrjittyc snake.lps snake.aut') os.system('lps2pbes -v -f nodeadlock.mcf snake.lps snake.nodeadlock.pbes') os.system('pbes2bool -vrjittyc -s1 snake.nodeadlock.pbes') os.system('lps2pbes -v -f white_can_win.mcf snake.lps snake.white_can_win.pbes') os.system('pbes2bool -vrjittyc -s1 snake.white_can_win.pbes') os.system('lps2pbes -v -f black_can_win.mcf snake.lps snake.black_can_win.pbes') os.system('pbes2bool -vrjittyc -s1 snake.black_can_win.pbes') os.system('lps2pbes -v -f eventually_white_or_black_wins.mcf snake.lps snake.eventually_white_or_black_wins.pbes') os.system('pbes2bool -vrjittyc -s1 snake.eventually_white_or_black_wins.pbes') mcrl2-201409.0/examples/games/snake/black_has_winning_strategy.mcf000770 001750 001750 00000000316 12370120075 025421 0ustar00outisoutis000000 000000 % This formula encodes the property that black has a winning strategy, such that % he wins in a finite number of steps. % This assumes that Black makes the first move mu X. true || [true]X mcrl2-201409.0/examples/games/snake/snake.mcrl2000770 001750 001750 00000007736 12370120075 021427 0ustar00outisoutis000000 000000 % This specification describes the game `Snake', which is a two % player board game. There is a board of N by M. % One player has white pieces (W) and the % other has black pieces (B). Initially, the board is set up as: % % . . . B . . . . % . . . . . . . . % . . . . . . . . % . . . . . . . . % . . . . . . . . % . . . . . . . . % . . . . . . . . % . . . . W . . . % % Black makes the first move, and players each do a move in turn. % Each player can put a piece at the head of the snake in vertical % or horizontal direction (not vertically) on an empty field of the % board. The first player that cannot do a move looses the game. % % Reijkjavik, May 15, 2006, Jan Friso Groote sort Position = struct Black | White | Empty; sort Direction = struct Up | Right | Down | Left; map N,M:Pos; eqn N=5; M=5; sort Row=List(Position); Board=List(Row); map At:Pos#Pos#Board->Position; At:Pos#Pos#Direction#Board->Position; At:Pos#Row->Position; Put:Position#Pos#Pos#Board->Board; Put:Position#Pos#Pos#Direction#Board->Board; Put:Position#Pos#Row->Row; CanMove:Pos#Pos#Board->Bool; PossibleMove:Pos#Pos#Direction#Board->Bool; Xchange,Ychange:Pos#Direction->Pos; var b:Board; r:Row; p,p':Position; x,y:Pos; eqn At(x,y,Up,b)=At(x,y+1,b); At(x,y,Right,b)=At(x+1,y,b); y>1 -> At(x,y,Down,b)=At(x,Int2Pos(y-1),b); y==1 -> At(x,y,Down,b)=Empty; x>1 -> At(x,y,Left,b)=At(Int2Pos(x-1),y,b); x==1 -> At(x,y,Left,b)=Empty; At(x,y,[])=Empty; y==1 -> At(x,y,r|>b)=At(x,r); y>M -> At(x,y,b)=Empty; 1 At(x,y,r|>b)=At(x,Int2Pos(y-1),b); At(x,[])=Empty; x==1 -> At(x,p|>r)=p; x>N -> At(x,p|>r)=Empty; 1 At(x,p|>r)=At(Int2Pos(x-1),r); Put(p,x,y,Up,b)=Put(p,x,y+1,b); Put(p,x,y,Right,b)=Put(p,x+1,y,b); y>1 -> Put(p,x,y,Down,b)=Put(p,x,Int2Pos(y-1),b); x>1 -> Put(p,x,y,Left,b)=Put(p,Int2Pos(x-1),y,b); y==1 -> Put(p,x,y,r|>b)=Put(p,x,r)|>b; y>1 -> Put(p,x,y,r|>b)=r|>Put(p,x,Int2Pos(y-1),b); x==1 -> Put(p,x,p'|>r)=p|>r; x>1 -> Put(p,x,p'|>r)=p'|>Put(p,Int2Pos(x-1),r); PossibleMove(x,y,Up,b)= y+1<=M && At(x,y,Up,b)==Empty; PossibleMove(x,y,Right,b)= x+1<=N && At(x,y,Right,b)==Empty; PossibleMove(x,y,Down,b)= y>1 && At(x,y,Down,b)==Empty; PossibleMove(x,y,Left,b)= x>1 && At(x,y,Left,b)==Empty; CanMove(x,y,b)= PossibleMove(x,y,Up,b) || PossibleMove(x,y,Right,b) || PossibleMove(x,y,Down,b) || PossibleMove(x,y,Left,b); Xchange(x,Up)=x; Xchange(x,Right)=x+1; Xchange(x,Down)=x; Xchange(x,Left)=Int2Pos(x-1); Ychange(y,Up)=y+1; Ychange(y,Right)=y; Ychange(y,Down)=Int2Pos(y-1); Ychange(y,Left)=y; act WhiteMove,BlackMove:Pos#Pos#Direction; WhiteWins,BlackWins; proc Snake(xblack,yblack,xwhite,ywhite:Pos,b:Board,WhiteMoves:Bool)= sum dir:Direction. (WhiteMoves && PossibleMove(xwhite,ywhite,dir,b)) -> WhiteMove(xwhite,ywhite,dir). Snake(xblack,yblack,Xchange(xwhite,dir),Ychange(ywhite,dir), Put(White,xwhite,ywhite,dir,b),false)+ sum dir:Direction. (!WhiteMoves && PossibleMove(xblack,yblack,dir,b)) -> BlackMove(xwhite,ywhite,dir). Snake(Xchange(xblack,dir),Ychange(yblack,dir),xwhite,ywhite, Put(Black,xblack,yblack,dir,b),true)+ (WhiteMoves && !CanMove(xwhite,ywhite,b)) -> BlackWins.Snake(xblack,yblack,xwhite,ywhite,b,WhiteMoves)+ (!WhiteMoves && !CanMove(xblack,yblack,b)) -> WhiteWins.Snake(xblack,yblack,xwhite,ywhite,b,WhiteMoves)+ delta ; init Snake(3,1,3,5, [[Empty,Empty,Black,Empty,Empty], [Empty,Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty,Empty], [Empty,Empty,White,Empty,Empty]],false); mcrl2-201409.0/examples/games/snake/white_can_win.mcf000770 001750 001750 00000000041 12370120075 022650 0ustar00outisoutis000000 000000 mu X. true || X mcrl2-201409.0/examples/games/snake/eventually_white_or_black_wins.mcf000770 001750 001750 00000000055 12370120075 026323 0ustar00outisoutis000000 000000 mu X.true || [true]X mcrl2-201409.0/examples/games/snake/black_can_win.mcf000770 001750 001750 00000000040 12370120075 022603 0ustar00outisoutis000000 000000 mu X.true || X mcrl2-201409.0/examples/games/wolf_goat_cabbage/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 024445 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/games/wolf_goat_cabbage/run.py000770 001750 001750 00000000512 12370120076 023031 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v wolf_goat_cabbage.mcrl2 wolf_goat_cabbage.lps') os.system('lps2lts -vrjittyc wolf_goat_cabbage.lps wolf_goat_cabbage.svc') os.system('lps2pbes -v -f nodeadlock.mcf wolf_goat_cabbage.lps wolf_goat_cabbage.nodeadlock.pbes') os.system('pbes2bool -vrjittyc -s1 wolf_goat_cabbage.nodeadlock.pbes') mcrl2-201409.0/examples/games/wolf_goat_cabbage/wolf_goat_cabbage.mcrl2000770 001750 001750 00000003622 12370120076 026226 0ustar00outisoutis000000 000000 % This file contains a specification of the well known % problem of the wolf, the goat and the cabbage, which % dates back to the French 8th century mathematician Alcuin. % % There are a man with a wolf, a goat and a cabbage standing % at one side of a river. He wants to cross and for this % purpose he has a small boat that can only contain him and % one item. If the wolf is left with the goat, the goat will % be eaten. If the goat is left with the cabbage, the cabbage % is consumed. The question is to find a strategy to bring the % man to the other shore without losing any of his items. % % This example shows the use of sets in mCRL2. % % Jan Friso Groote & Aad Mathijssen, January 2009 % % Linearisation of this model is quickest using the -lregular2 option of % mcrl22lps sort Item = struct wolf | goat | cabbage; Position = struct left | right; Shores = struct shores(Set(Item), Set(Item)); map opp: Position -> Position; items: Shores # Position -> Set(Item); update: Shores # Position # Item -> Shores; var s,t: Set(Item); i: Item; eqn opp(left) = right; opp(right) = left; items(shores(s, t), left) = s; items(shores(s, t), right) = t; update(shores(s,t), right, i) = shores(s - {i}, t + {i}); update(shores(s,t), left, i) = shores(s + {i}, t - {i}); act is_eaten: Item; move: Position; move: Position # Item; done; proc WGC(s: Shores, p: Position) = ({wolf,goat} <= items(s, opp(p))) -> is_eaten(goat) . delta + ({goat,cabbage} <= items(s, opp(p))) -> is_eaten(cabbage) . delta + (!({wolf,goat} <= items(s, opp(p))) && !({goat,cabbage} <= items(s, opp(p)))) -> ( move(opp(p)) . WGC(s, opp(p)) + sum i:Item. (i in items(s, p)) -> move(opp(p), i) . WGC(update(s, opp(p), i), opp(p)) + (items(s, right) == {wolf,goat,cabbage}) -> done . delta ); init WGC(shores({wolf,goat,cabbage}, {}), left); mcrl2-201409.0/examples/games/domineering/player2_can_win.mcf000770 001750 001750 00000000043 12370120075 024307 0ustar00outisoutis000000 000000 mu X. true || X mcrl2-201409.0/examples/games/domineering/nodeadlock.mcf000770 001750 001750 00000000224 12370120075 023337 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/games/domineering/run.py000770 001750 001750 00000001521 12370120075 021724 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vD domineering.mcrl2 domineering.lps') os.system('lps2lts -vrjittyc domineering.lps domineering.aut') os.system('lps2pbes -v -f nodeadlock.mcf domineering.lps domineering.nodeadlock.pbes') os.system('pbes2bool -vrjittyc -s1 domineering.nodeadlock.pbes') os.system('lps2pbes -v -f player1_can_win.mcf domineering.lps domineering.player1_can_win.pbes') os.system('pbes2bool -vrjittyc -s1 domineering.player1_can_win.pbes') os.system('lps2pbes -v -f player2_can_win.mcf domineering.lps domineering.player2_can_win.pbes') os.system('pbes2bool -vrjittyc -s1 domineering.player2_can_win.pbes') os.system('lps2pbes -v -f eventually_player1_or_player2_wins.mcf domineering.lps domineering.eventually_player1_or_player2_wins.pbes') os.system('pbes2bool -vrjittyc -s1 domineering.eventually_player1_or_player2_wins.pbes') mcrl2-201409.0/examples/games/domineering/player1_can_win.mcf000770 001750 001750 00000000043 12370120075 024306 0ustar00outisoutis000000 000000 mu X. true || X mcrl2-201409.0/examples/games/domineering/eventually_player1_or_player2_wins.mcf000770 001750 001750 00000000061 12370120075 030256 0ustar00outisoutis000000 000000 mu X.true || [true]X mcrl2-201409.0/examples/games/domineering/domineering.mcrl2000770 001750 001750 00000005767 12370120075 024027 0ustar00outisoutis000000 000000 % This file describes a game called `Domineering'. The idea is that % there are two players alternatingly putting a domino tile on a % rectangular NxM board. Each domino tile covers two squares on % the board. Player 1 starts and puts its tiles horizontally. % Player 2 subsequently puts its tile vertically. The first player % that cannot put a tile anymore looses the game % % Thanks to Mark Winands. % Reijkjavik, May 13, 2006, Jan Friso Groote sort Position = struct Full | Empty; map N,M:Pos; eqn N=5; M=5; sort Row=List(Position); Board=List(Row); map At:Pos#Pos#Board->Position; At:Pos#Row->Position; Put:Position#Pos#Pos#Board->Board; Put:Position#Pos#Row->Row; NoHorizontalSpot,NoVerticalSpot:Pos#Pos#Board->Bool; var b:Board; r:Row; p,p':Position; x,y:Pos; eqn At(x,y,[])=Empty; y==1 -> At(x,y,r|>b)=At(x,r); y>1 -> At(x,y,r|>b)=At(x,Int2Pos(y-1),b); At(y,[])=Empty; x==1 -> At(x,p|>r)=p; x>1 -> At(x,p|>r)=At(Int2Pos(x-1),r); y==1 -> Put(p,x,y,r|>b)=Put(p,x,r)|>b; y>1 -> Put(p,x,y,r|>b)=r|>Put(p,x,Int2Pos(y-1),b); x==1 -> Put(p,x,p'|>r)=p|>r; x>1 -> Put(p,x,p'|>r)=p'|>Put(p,Int2Pos(x-1),r); y==M -> NoVerticalSpot(x,y,b)=true; x NoVerticalSpot(x,y,b)= (At(x,y,b)==Full || At(x,y+1,b)==Full) && NoVerticalSpot(x+1,y,b); x==N && y NoVerticalSpot(x,y,b)= (At(x,y,b)==Full || At(x,y+1,b)==Full) && NoVerticalSpot(1,y+1,b); x==N -> NoHorizontalSpot(x,y,b)=true; x NoHorizontalSpot(x,y,b)= (At(x,y,b)==Full || At(x+1,y,b)==Full) && NoHorizontalSpot(x,y+1,b); x NoHorizontalSpot(x,y,b)= (At(x,y,b)==Full || At(x+1,y,b)==Full) && NoHorizontalSpot(x+1,1,b); act Player1,Player2:Pos#Pos#Pos#Pos; Player1Wins,Player2Wins; proc Domineering(b:Board,Player1Moves:Bool)= sum x,y:Pos. (Player1Moves && x<=N && y Player1(x,y,x,y+1). Domineering(Put(Full,x,y+1,Put(Full,x,y,b)),false)+ sum x,y:Pos. (!Player1Moves && x Player2(x,y,x+1,y). Domineering(Put(Full,x+1,y,Put(Full,x,y,b)),true)+ (Player1Moves && NoVerticalSpot(1,1,b)) -> Player2Wins.Domineering(b,Player1Moves)+ (!Player1Moves && NoHorizontalSpot(1,1,b)) -> Player1Wins.Domineering(b,Player1Moves)+ delta; init Domineering([[Empty,Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty,Empty]],true); mcrl2-201409.0/examples/games/magic_square/magic_square.mcrl2000770 001750 001750 00000001660 12370120075 024313 0ustar00outisoutis000000 000000 % The magical square is a well known puzzle. % Consider the number from 1 to 10. % Can these numbers be arranged in the following form: % % n1 n2 n3 % n4 n5 n6 % n7 n8 n9 % % such that the sum of each colum, row and diagonal is 15. % The example below shows how this can be phrased in mCRL2. % % Jan Friso Groote. February 2008. map all_unique:List(Pos)->Bool; var n:Pos; L:List(Pos); eqn all_unique([])=true; all_unique(n|>L)= !(n in L) && all_unique(L); act a:Pos#Pos#Pos#Pos#Pos#Pos#Pos#Pos#Pos; init sum n1,n2,n3,n4,n5,n6,n7,n8,n9:Pos. (n1+n2+n3==15 && n4+n5+n6==15 && n7+n8+n9==15 && n1+n4+n7==15 && n2+n5+n8==15 && n3+n6+n9==15 && n1+n5+n9==15 && n7+n5+n3==15 && all_unique([n1,n2,n3,n4,n5,n6,n7,n8,n9])) -> a(n1,n2,n3,n4,n5,n6,n7,n8,n9).delta<>delta; mcrl2-201409.0/examples/games/magic_square/run.py000770 001750 001750 00000000113 12370120075 022060 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -v magic_square.mcrl2 magic_square.lps') mcrl2-201409.0/examples/games/game_of_goose/game_of_goose.mcrl2000770 001750 001750 00000017222 12370120076 024577 0ustar00outisoutis000000 000000 % The Royal Game of Goose (in Dutch: Het oudholands ganzenbord) % % We model the Royal Game of Goose in mCRL2. Using this we can determine % what the probability is of the various players to win. Roughly the rules % of the game are as follows. There are two or more players (geese) taking part in % the game. The game has fields numbered from 0 to 63. All players start at position 0 % and alternatingly throw two dice and move the indicated number of pips forward. % The first player that arrives at position 63 wins the game. % % There are a number of rules that apply in addition when moving forward. There % are actually many variants of these rules for all variants of this game that exist in % the world, including those where only one die is used. We follow the rules % for a popular Dutch version of the game, although even these rules turned % out to have been susceptible to variations. % % In the popular Dutch variant the player alternatingly throw two dice. The player % to start the game is the one who throws the hightest number first. This aspect of % determining the first player is not part of the model below. % The player moves his goose forward as many steps as the dice indicate where % he must apply the following exceptions/extensions. % % If the first throw is a 4 and a 5, the players goes to field 53. % If the first throw exists of a 6 and a 3, the player moves to field 26. % Without these rules, the player would end up immediately at position 63, winning % the game. There are variants of the Dutch rules where position 53 and 26 are % reversed. % % If a player ends on position 5, 9, 14, 18, 23, 27, 32, 36, 41, 45, 50, 54 and 59, he will move % the same numbers of steps in the same direction as he was moving. So, if one is moving backwards, % after arriving at number 63 (see below) and number 59 is reached the player moves the same number % of steps further in the backward direction. % % When the player arrives at one of the following fields he has to perform a special action. % Field 6, `the bridge'. Move forward to position 12. % Field 19, `the inn'. Skip one turn. % Field 31, `the well'. Wait until another player arrives at the well. If so, the first % player is released, and the second player must stay in the well. % Field 42, `the maze'. Go back to field 30. % Field 52, `the prison'. Wait until released by another player. % Field 58, `death'. Move to position 0. % % If a player ends up at a position which is occupied by another player, then he must go back % to its original position, except for the well and the prison. In those case the player already % at that position is released and the newly arriving player is captured. % % To win the game one must end exactly at position 63. If too many pips are thrown, the player % must count back from number 63. % % In J.F. Groote and H. Zantema, Analysing the Game of the Goose a detailed analysis is provided % of the game, partly on the basis of the code below. map number_of_players:Pos; previous,next:Pos->Pos; initial_positions:Pos->Nat; adapt_after_63:Int->Nat; next_position:Pos#(Pos->Nat)#Pos#Pos->Nat; next_position2:Pos#(Pos->Nat)#Int#Nat->Nat; occupied,occupied_pw:Pos#(Pos->Nat)->Bool; % occupied_pw is occupied, except for the prison and well. occupied_rec:Pos#(Pos->Nat)#Pos->Bool; var player,other,throw1,throw2:Pos; throw,n:Int; position:Pos->Nat; old_position:Nat; eqn number_of_players=4; next(player)=if(player==number_of_players,1,player+1); previous(player)=if(player>1,max(1,player-1),number_of_players); initial_positions(player)=0; adapt_after_63(n)=Int2Nat(if(n>63,63+63-n,n)); next_position(player,position,throw1,throw2)= % If initially a 4 and 5, or a 3 and 6 one must go to 53 and 26 respectively. if(position(player)==0 && (throw1==4 && throw2==5 || throw1==5 && throw2==4), if(occupied(player,position[player->53]),0,53), if(position(player)==0 && (throw1==3 && throw2==6 || throw1==6 && throw2==3), if(occupied(player,position[player->26]),0,26), % Otherwise do an ordinary step. next_position2(player,position[player->adapt_after_63(position(player)+throw1+throw2)], if(position(player)+throw1+throw2>63,-throw1-throw2,throw1+throw2),position(player)))); (position(player)<65) -> % Trick to prevent infinite rewriting. next_position2(player,position,throw,old_position)= % At position 5, 9, 14, 18, 23, 27, 32, 36, 41, 45, 50, 54, 59 proceed the same number of steps, in the current direction. if(position(player) in {5,9,14,18,23,27,32,36,41,45,50,54,59}, next_position2(player,position[player->adapt_after_63(position(player)+throw)],if(position(player)+throw>63,-throw,throw),old_position), % At position 6 you are at the bridge. Move to position 12. if(position(player)==6, next_position2(player,position[player->12],throw,old_position), % At position 19 you are in the inn. Skip one turn by moving the the artificial position 64. if(position(player)==19, next_position2(player,position[player->64],throw,old_position), % At position 42 you are in the maze. Go back to place 30. if(position(player)==42, next_position2(player,position[player->30],throw,old_position), % At position 58 you die. Go back to position 0. if(position(player)==58, next_position2(player,position[player->0],throw,old_position), % Otherwise if(occupied_pw(player,position),old_position,position(player))))))); % Check whether the position of the player is occupied by another player, except when the player is in the prison or well. occupied_pw(player,position)=!(position(player) in {31,52}) && occupied(player,position); % Check whether the position of the player is occupied, starting at the position of other or higher. occupied(player,position)=occupied_rec(player,position,1); occupied_rec(player,position,other)=if(otherNat)= % Indicate the positions of all players. sum player:Pos.(player<=number_of_players)->player_at(player,position(player)).delta+ % If a player won, indicate so and stop. (position(previous(player))==63)->win(previous(player)).delta<> % At position 31 you are in the well. Skip your turn, if nobody else is in the well. % At position 52 you are in prison. Also skip your turn, if nobody else is in prison. (position(player) in {31,52} && !occupied(player,position)) -> skip(player).THROW(next(player),position) <> % At position 64 you are resting in the inn. You can go back to position 19 where you can continue as usual in your next turn. (position(player)==64) -> skip(player).THROW(next(player),position[player->19])<> % Otherwise throw the dice. sum throw1,throw2:Pos.(throw1<=6 && throw2<=6)->throw(player,throw1,throw2). THROW(next(player),position[player->next_position(player,position,throw1,throw2)]); init THROW(1,initial_positions); mcrl2-201409.0/examples/games/rubiks_cube/run.py000770 001750 001750 00000000112 12370120076 021715 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vnD rubiks_cube.mcrl2 rubiks_cube.lps') mcrl2-201409.0/examples/games/rubiks_cube/rubiks_cube.mcrl2000770 001750 001750 00000015232 12370120076 024006 0ustar00outisoutis000000 000000 % The Rubik's Cube is a 3-D mechanical puzzle invented in 1974[1] by Hungarian % sculptor and professor of architecture ErnÅ‘ Rubik. Originally called the % "Magic Cube", the puzzle was licensed by Rubik to be sold by Ideal Toys in % 1980[3] and won the German Game of the Year special award for Best Puzzle % that year. As of January 2009, 350 million cubes have sold worldwide making % it the world's top-selling puzzle game. % % In a classic Rubik's Cube, each of the six faces is covered by 9 stickers, % among six solid colours (traditionally white, red, blue, orange, green, % and yellow). A pivot mechanism enables each face to turn independently, % thus mixing up the colours. For the puzzle to be solved, each face must be a % solid colour. The original 3×3×3 version celebrated its twenty-fifth % anniversary in 2005. % % [http://en.wikipedia.org/wiki/Rubik's_Cube, 09-11-09] % % This version models the clockwise and counterclockwise rotations for a solved % Rubik's cube, for which only the white pieces are taken into account. % % Eindhoven, November 09, 2009, Frank Stappers % Dimensions of the Rubik's Cube % Z % % + (0,0,2) % | % | % + % | % | % + % | % | Y % +----+----+----+ (0,2,0) % / % + % / % + % / % + (2,0,0) % % X % Rubik's Cube colors sort Color = struct white | red | blue | orange | green | yellow ; % Rubik's Cube Faces sort Face = struct X | Y | Z; sort Axis = Face; % Every visible Rubik's Cube facet has an XYZ-position and normal vector (Face) % that expresses in which the direction the face is visible. sort Position = struct pos( x: Int, y: Int, z: Int, nv: Face ); % A visible piece is a tuple of a Rubik's Cube facet and color sort Piece = struct piece( color: Color, position: Position ); map change_rotation_face: Face#Axis -> Face; var f: Face; a: Axis; eqn (f == a) -> change_rotation_face( f , a ) = f; (f != a ) && ( f == X ) && ( a == Y ) -> change_rotation_face( f , a ) = Z; (f != a ) && ( f == X ) && ( a == Z ) -> change_rotation_face( f , a ) = Y; (f != a ) && ( f == Y ) && ( a == Z ) -> change_rotation_face( f , a ) = X; (f != a ) && ( f == Y ) && ( a == X ) -> change_rotation_face( f , a ) = Z; (f != a ) && ( f == Z ) && ( a == X ) -> change_rotation_face( f , a ) = Y; (f != a ) && ( f == Z ) && ( a == Y ) -> change_rotation_face( f , a ) = X; map pos_in_rotation: Position#Axis#Int -> Bool; var a: Axis; p: Position; i: Int; eqn pos_in_rotation( p, a, i) = ((x(p) == i) && ( a == X )) || ((y(p) == i) && ( a == Y )) || ((y(p) == i) && ( a == Z )); map apply_ccw_rotate: List(Piece)#Axis#Nat -> List(Piece); apply_cw_rotate: List(Piece)#Axis#Nat -> List(Piece); var p: Piece; SP: List(Piece); a: Axis; r: Nat; eqn apply_ccw_rotate(p |> SP,a,r) = piece( color(p), single_ccw_pos_update(position(p),a,r)) |> apply_ccw_rotate( SP, a, r ); apply_cw_rotate(p |> SP,a,r) = piece( color(p), single_cw_pos_update(position(p),a,r)) |> apply_cw_rotate( SP, a, r ); apply_ccw_rotate([],a,r) = []; apply_cw_rotate([],a,r) = []; % The Rubik's cube is represented as a list of pieces. % To represent the representation in an unique way, the list is ordered. % The cube is ordered using a merge-sort algorithm map order_cube :(Piece#Piece -> Bool)#List(Piece) -> List(Piece); var x:Piece; xs:List(Piece); pred: Piece#Piece -> Bool; eqn order_cube (pred, []) = []; order_cube (pred, x |> xs) = insert_piece(pred, x, order_cube(pred, xs)); map insert_piece : (Piece#Piece -> Bool)#Piece# List(Piece) -> List(Piece); var x,y: Piece; ys: List(Piece); pred: Piece#Piece -> Bool; eqn insert_piece (pred, x, []) = [x]; pred(x, y) -> insert_piece(pred, x, y|> ys) = x |> y |> ys; (!pred(x, y)) -> insert_piece(pred, x, y|> ys) = y |> insert_piece( pred, x, ys); % The eqf function represents the criteria to which the pieces in the list Rubik's cube are ordered. map eqf: Piece#Piece->Bool; var i,j: Piece; eqn eqf(i,j) = ((x(position(i))+1)*6 + (y(position(i))+1)*3 + z(position(i))) < ((x(position(j))+1)*6 + (y(position(j))+1)*3 + z(position(j))); map single_ccw_pos_update: Position#Axis#Int -> Position; single_cw_pos_update: Position#Axis#Int -> Position; var a: Axis; p: Position; r: Int; eqn % Rotation over Z-axis (Z == a) && pos_in_rotation( p, a, r ) -> single_ccw_pos_update( p , a, r ) = pos( -y(p)+2, x(p), z(p), change_rotation_face( nv(p), Z ) ) ; % Rotation over Y-axis (Y == a) && pos_in_rotation( p, a, r ) -> single_ccw_pos_update( p , a, r ) = pos( z(p), y(p), -x(p)+2, change_rotation_face( nv(p), Y ) ) ; % Rotation over Y-axis (X == a) && pos_in_rotation( p, a, r ) -> single_ccw_pos_update( p , a, r ) = pos( x(p), -z(p)+2, y(p), change_rotation_face( nv(p), X ) ) ; !pos_in_rotation(p , a, r) -> single_ccw_pos_update(p,a,r) = p; (Z == a) && pos_in_rotation( p, a, r ) -> single_cw_pos_update( p , a, r ) = pos( y(p), -x(p)+2, z(p), change_rotation_face( nv(p), Z ) ) ; % Rotation over Y-axis (Y == a) && pos_in_rotation( p, a, r ) -> single_cw_pos_update( p , a, r ) = pos( -z(p)+2, y(p), x(p), change_rotation_face( nv(p), Y ) ) ; % Rotation over Y-axis (X == a) && pos_in_rotation( p, a, r ) -> single_cw_pos_update( p , a, r ) = pos( x(p), z(p), -y(p)+2, change_rotation_face( nv(p), X ) ) ; !pos_in_rotation(p , a, r) -> single_cw_pos_update(p,a,r) = p; act showcube: List(Piece); % Rotate clockwise rcw: Axis#Int; % Rotate counter clockwise rccw:Axis#Int; % Process P only rotates outermost rows, i.e. row 0 and row 2 proc P( p: List(Piece) ) = sum a:Axis. rcw(a,0) . P( order_cube( lambda i,j:Piece. eqf(i,j), apply_cw_rotate( p, a, 0 ) ) ) + sum a:Axis. rcw(a,2) . P( order_cube( lambda i,j:Piece. eqf(i,j), apply_cw_rotate( p, a, 2 ) ) ) + sum a:Axis. rccw(a,0) . P( order_cube( lambda i,j:Piece. eqf(i,j), apply_ccw_rotate( p, a, 0 ) ) ) + sum a:Axis. rccw(a,2) . P( order_cube( lambda i,j:Piece. eqf(i,j), apply_ccw_rotate( p, a, 2 ) ) ); % Layout of the white side of the Rubik's cube init P( order_cube( lambda i,j:Piece. eqf(i,j) ,[ piece(white, pos( 2,0,0, X )), piece(white, pos( 2,1,0, X )), piece(white, pos( 2,2,0, X )), piece(white, pos( 2,0,1, X )), piece(white, pos( 2,2,1, X )), piece(white, pos( 2,0,2, X )), piece(white, pos( 2,1,2, X )), piece(white, pos( 2,2,2, X )) ]) ); mcrl2-201409.0/examples/games/four_in_a_row/four_in_a_row.mcrl2000770 001750 001750 00000024440 12370120141 024666 0ustar00outisoutis000000 000000 % This mCRL2 specification describes the game 'four in a row'. % Four in a row is a two player game that alternatingly put a % yellow and red piece on the lowest non occupied position of % the board. Red starts the game. The player who puts a piece % first such that there % are four pieces in a row on the board in either horizontal, % vertical or diagonal direction wins the game. The standard % game has 5 rows and seven columns. A typical situation where % red wins the game is the following: % % . . . . . . . % . . . . . . . % . . . R . . . % . . R R . . . R is red % . R R Y . . . Y is yellow % R Y Y Y . . Y % % To generate the state space of this game, the following % sequence of commands can be used. Using lpsparunfold and % lpsconstelm the structure of the board is eliminated in % favour of single variables, which speeds up the generation % of the state space dramatically. The size of the state space % is much larger than 2 10^9 states. Generation of the complete % state space is technically not yet possible. % % mcrl22lps -vD four_in_a_row.mcrl2 temp.lps && % lpssuminst -v temp.lps | lpsparunfold -l -sBoard -v -n5 | lpsparunfold -l -sRow -v -n7 | lpsrewr -v > temp1.lps && % lpsconstelm -v -c -rjittyc temp1.lps temp2.lps && % lps2lts -v -rjittyc temp2.lps % % Using the following formula, it can be determined whether red has % winning strategy. % % mu X.(exists x:Pos. % (true || % ((exists y:Pos.true) && forall y:Pos.[YellowMoves(y)](X && [YellowWins]false)))) % % Using pbes2bool this formula can be verified on smaller than the full board. % The table below shows on which boards red has a winning strategy. % This has been verified using pbes2bool -rjittyc -v -s2 -zd temp1.pbes --erase=some % For 7x4 and 5x6 boards typically 40Gbyte memory was required. % % Columns % Rows 1 2 3 4 5 6 7 % 1 No No No No No No No % 2 No No No No No No No % 3 No No No No No No No % 4 No No No No No No No % 5 No No No No No No % 6 No No No No No % % Jan Friso Groote, April 6, 2010/Juli 28, 2014 sort Piece = struct Red | Yellow | None; map N,M,R:Pos; eqn N=7; %Number of columns (default 7) M=6; %Number of rows (default 6) R=4; %Length of a winning sequence of the same color (default 4) sort Row=List(Piece); Board=List(Row); map At:Nat#Nat#Board->Piece; % At(x,y,b) give the piece at position x,y. If there is no % piece, or if x,y is outside the board, give None. At:Nat#Row->Piece; % See At above. Now for a single row. PutColumn:Piece#Pos#Board->Board; % Put piece p at the indicated column in a board, assuming % that there is a free spot. PutColumn:Piece#Pos#Pos#Board->Board; % Put piece at the indicated column in a board, assuming that % there is a free spot and the second argument of type Pos % indicates the lowest position to try first. Put:Piece#Pos#Pos#Board->Board; % Put piece at the indicated position on the board. Put:Piece#Pos#Row->Row; % Put piece p at the indicated position in a row. Four_in_a_row:Piece#Board->Bool; % Indicates whether there are four pieces of sort Piece % either horizontally, vertically or diagonally in a row. Four_in_a_row_horizontally:Piece#Board->Bool; Four_in_a_row_horizontally:Piece#Pos#Board->Bool; % Check from the indicated row upwards. Count_rows_horizontally:Piece#Pos#Pos#Board#Nat->Bool; % Count the number of pieces in a row, and return % true when four in a row have been found. Four_in_a_row_vertically:Piece#Board->Bool; Four_in_a_row_vertically:Piece#Pos#Board->Bool; % Check from the indicated row upwards. Count_rows_vertically:Piece#Pos#Pos#Board#Nat->Bool; Four_in_a_row_diagonally:Piece#Board->Bool; Four_in_a_row_diagonally_column:Piece#Pos#Board->Bool; % Check from the first column diagonally. Four_in_a_row_diagonally_row:Piece#Pos#Board->Bool; % Check from the first row diagonally. Count_rows_diagonally:Piece#Pos#Pos#Board#Nat->Bool; Count_rows_diagonally':Piece#Pos#Pos#Board#Nat->Bool; var b,b':Board; r:Row; p,p',p'':Piece; x,y:Nat; c:Bool; z:Pos; eqn if(c,true,false)=c; if(c,false,true)=!c; if(c,p,p')==p'' = if(c,p==p'',p'==p''); y==1 -> At(x,y,r|>b)=At(x,r); 1 At(x,y,r|>b)=At(x,Int2Nat(y-1),b); y==0 || y>M || x==0 || x>N -> At(x,y,b)=None; At(x,y,if(c,b,b'))=if(c,At(x,y,b),At(x,y,b')); % This rewrite rule is instrumental to let lpsconstelm % reduce the system substantially, after applying lpsparunfold. x==1 -> At(x,p|>r)=p; 1 At(x,p|>r)=At(Int2Nat(x-1),r); x==0 || x>N -> At(x,p|>r)=None; At(x,Put(p,z,r))=if(x==z,p,At(x,r)); var b,b':Board; r:Row; p,p':Piece; x,y:Pos; dx,dy:Int; c,othercolorseen:Bool; count:Nat; eqn y==1 -> Put(p,x,y,r|>b)=Put(p,x,r)|>b; y>1 && y<=M -> Put(p,x,y,r|>b)=r|>Put(p,x,Int2Pos(y-1),b); Put(p,x,y,if(c,b,b'))=if(c,Put(p,x,y,b),Put(p,x,y,b')); % See comments for distribution of At over if. x==1 -> Put(p,x,p'|>r)=p|>r; x>1 && x<=N -> Put(p,x,p'|>r)=p'|>Put(p,Int2Pos(x-1),r); PutColumn(p,x,b)=PutColumn(p,x,1,b); y PutColumn(p,x,y,b)=if(At(x,y,b)==None,Put(p,x,y,b),PutColumn(p,x,y+1,b)); y==M -> PutColumn(p,x,y,b)=Put(p,x,M,b); Four_in_a_row(p,b)= Four_in_a_row_horizontally(p,b)|| Four_in_a_row_vertically(p,b)|| Four_in_a_row_diagonally(p,b); Four_in_a_row_horizontally(p,b)=Four_in_a_row_horizontally(p,1,b); y Four_in_a_row_horizontally(p,y,b)=Count_rows_horizontally(p,1,y,b,0) || Four_in_a_row_horizontally(p,y+1,b); y==M -> Four_in_a_row_horizontally(p,y,b)=Count_rows_horizontally(p,1,M,b,0); x Count_rows_horizontally(p,x,y,b,count)= if(At(x,y,b)==p, count>=R-1 || Count_rows_horizontally(p,x+1,y,b,count+1), Count_rows_horizontally(p,x+1,y,b,0)); x==N -> Count_rows_horizontally(p,x,y,b,count)=if(At(N,y,b)==p,count>=R-1,false); Four_in_a_row_vertically(p,b)=Four_in_a_row_vertically(p,1,b); x Four_in_a_row_vertically(p,x,b)=Count_rows_vertically(p,x,1,b,0) || Four_in_a_row_vertically(p,x+1,b); x==N -> Four_in_a_row_vertically(p,x,b)=Count_rows_vertically(p,N,1,b,0); y Count_rows_vertically(p,x,y,b,count)= if(At(x,y,b)==p, count>=R-1 || Count_rows_vertically(p,x,y+1,b,count+1), Count_rows_vertically(p,x,y+1,b,0)); y==M -> Count_rows_vertically(p,x,y,b,count)=if(At(x,M,b)==p,count>=R-1,false); Four_in_a_row_diagonally(p,b)=Four_in_a_row_diagonally_column(p,2,b) || Four_in_a_row_diagonally_row(p,1,b); x Four_in_a_row_diagonally_row(p,x,b)=Count_rows_diagonally(p,x,1,b,0) || Count_rows_diagonally'(p,x,1,b,0) || Four_in_a_row_diagonally_row(p,x+1,b); x==N -> Four_in_a_row_diagonally_row(p,x,b)=Count_rows_diagonally'(p,N,1,b,0); y Four_in_a_row_diagonally_column(p,y,b)=Count_rows_diagonally(p,1,y,b,0) || Count_rows_diagonally'(p,N,y,b,0) || Four_in_a_row_diagonally_column(p,y+1,b); y>=M -> Four_in_a_row_diagonally_column(p,y,b)=false; x Count_rows_diagonally(p,x,y,b,count)= if(At(x,y,b)==p, count>=R-1 || Count_rows_diagonally(p,x+1,y+1,b,count+1), Count_rows_diagonally(p,x+1,y+1,b,0)); x==N || y==M -> Count_rows_diagonally(p,x,y,b,count)=if(At(x,y,b)==p,count>=R-1,false); x>1 && y Count_rows_diagonally'(p,x,y,b,count)= if(At(x,y,b)==p, count>=R-1 || Count_rows_diagonally'(p,max(1,x-1),y+1,b,count+1), Count_rows_diagonally'(p,max(1,x-1),y+1,b,0)); x==1 || y==M -> Count_rows_diagonally'(p,x,y,b,count)=if(At(x,y,b)==p,count>=R-1,false); act YellowMoves,RedMoves:Pos; YellowWins,RedWins; proc FourInaRow(b:Board,WhoMoves:Piece)= sum x:Pos.(WhoMoves==Yellow && x<=N && At(x,M,b)==None) -> YellowMoves(x). FourInaRow(PutColumn(Yellow,x,b),Red)+ sum x:Pos.(WhoMoves==Red && x<=N && At(x,M,b)==None) -> RedMoves(x). FourInaRow(PutColumn(Red,x,b),Yellow)+ (WhoMoves==Yellow && Four_in_a_row(Red,b)) -> RedWins. FourInaRow(b,None)+ (WhoMoves==Red && Four_in_a_row(Yellow,b)) -> YellowWins. FourInaRow(b,None); % Note that the board is reversed. The bottom row is drawn at the top. map initial_board:Board; eqn initial_board= [[None, None, None, None, None, None, None ], [None, None, None, None, None, None, None ], [None, None, None, None, None, None, None ], [None, None, None, None, None, None, None ], [None, None, None, None, None, None, None ], [None, None, None, None, None, None, None ]]; init FourInaRow(initial_board,Red); mcrl2-201409.0/examples/games/four_in_a_row/run.py000770 001750 001750 00000001650 12370120141 022251 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vD four_in_a_row.mcrl2 temp.lps') os.system('lpssuminst -v temp.lps | lpsparunfold -l -sBoard -v -n6 | lpsparunfold -l -sRow -v -n8 | lpsrewr -v > temp1.lps') os.system('lpsconstelm -v -rjittyc temp1.lps temp2.lps') # The state space of four in a row is big, so the statement below will not terminate. # Reducing the number of columns, e.g. to four instead of default 7 does lead to a result. # In that case the there are 16M states. Solving the formulas red_wins.mcf requires 7M bes # variables (with result false). Five columns lead to appr. 100Mstates. #os.system('lps2lts -v -rjittyc temp2.lps') # Also pbes2bool does not tend to terminate on the full game, as it is too big. os.system('lps2pbes -vfred_wins.mcf temp2.lps temp.pbes') os.system('pbesrewr -pquantifier-all temp.pbes | pbesconstelm -v | pbesrewr -v > temp1.pbes') os.system('pbes2bool -rjittyc -v -s2 -zd temp1.pbes --erase=some') mcrl2-201409.0/examples/games/four_in_a_row/red_wins.mcf000770 001750 001750 00000000642 12370120076 023403 0ustar00outisoutis000000 000000 % This formula expresses that red has a winning strategy in the game "four in a row" % as specified in four_in_a_row.mcrl2. Note that red does not win if yellow cannot do a move % at the end of the game. This is enforced by the clause exists y:Pos.true. mu X.(exists x:Pos.(true || ((exists y:Pos.true) && forall y:Pos.[YellowMoves(y)](X && [YellowWins]false)))) mcrl2-201409.0/examples/games/peg_solitaire/run.py000770 001750 001750 00000001111 12370120076 022246 0ustar00outisoutis000000 000000 import os os.system('mcrl22lps -vn peg_solitaire.mcrl2 peg_solitaire.lps') os.system('lpssuminst -v peg_solitaire.lps temp1.lps') os.system('lpsrewr -v temp1.lps temp2.lps') os.system('lpsparunfold -v -l -sBoard temp2.lps | lpsrewr -v > temp3.lps') os.system('lpsparunfold -v -l -sRow temp3.lps |lpsrewr -v > temp4.lps') os.system('lpsparelm -v temp4.lps | lpsconstelm -v | lpsrewr -v > temp5.lps') os.system('lpsbinary temp5.lps | lpsactionrename -frename.ren | lpsrewr > temp6.lps') os.system('lpsconstelm temp6.lps -v temp7.lps') os.system('lps2lts -vrjittyc -aready temp7.lps') mcrl2-201409.0/examples/games/peg_solitaire/peg_solitaire.mcrl2000770 001750 001750 00000024361 12370120141 024664 0ustar00outisoutis000000 000000 % This file describes the well known peg solitaire game. % The question is to show how from a board that % has the shape: % % x x x % x x x % x x x x x x x % x x x . x x x % x x x x x x x % x x x % x x x % % where each `x' is a pin, and `.' an empty hole, the situation % % . . . % . . . % . . . . . . . % . . . x . . . % . . . . . . . % . . . % . . . % % can be reached. A move constists of capturing a pin by % moving one pin over another to an empty place. These moves % can both be horizontal, and vertical, but not diagonal. % So a typical first move in the game is: % % x x x % x x x % x x x x x x x % x . . x x x x % x x x x x x x % x x x % x x x % % There are three other, moves in the initial situation. % The total number of reachable board positions is 187636300. % The state spaces per level are given below (where the transition % from level 32 to level 33 is a ready transition): % % level 1 done. (1 state, 4 transitions) % level 2 done. (4 states, 12 transitions) % level 3 done. (12 states, 60 transitions) % level 4 done. (60 states, 400 transitions) % level 5 done. (296 states, 2228 transitions) % level 6 done. (1338 states, 11360 transitions) % level 7 done. (5648 states, 51952 transitions) % level 8 done. (21842 states, 213420 transitions) % level 9 done. (77559 states, 790132 transitions) % level 10 done. (249690 states, 2595424 transitions) % level 11 done. (717788 states, 7510380 transitions) % level 12 done. (1834379 states, 19116668 transitions) % level 13 done. (4138302 states, 42497988 transitions) % level 14 done. (8171208 states, 81824196 transitions) % level 15 done. (14020166 states, 135512592 transitions) % level 16 done. (20773236 states, 191887588 transitions) % level 17 done. (26482824 states, 231397620 transitions) % level 18 done. (28994876 states, 236879588 transitions) % level 19 done. (27286330 states, 205786556 transitions) % level 20 done. (22106348 states, 151783424 transitions) % level 21 done. (15425572 states, 94975656 transitions) % level 22 done. (9274496 states, 50282084 transitions) % level 23 done. (4792664 states, 22378164 transitions) % level 24 done. (2120101 states, 8318648 transitions) % level 25 done. (800152 states, 2565692 transitions) % level 26 done. (255544 states, 644556 transitions) % level 27 done. (68236 states, 127620 transitions) % level 28 done. (14727 states, 18804 transitions) % level 29 done. (2529 states, 2052 transitions) % level 30 done. (334 states, 124 transitions) % level 31 done. (32 states, 8 transitions) % level 32 done. (5 states, 1 transition) % level 33 done. (1 state, 0 transitions) % % We currently use the following commands to explore the state % space: % % mcrl22lps -n peg_solitaire.mcrl2 temps1.lps % lpssuminst temps1.lps temps2.lps % lpsrewr temps2.lps temps3.lps % lps2lts -vrjittyc -aready temps3.lps % % It is expected that the speed of state space generation will % increase a factor 10, after applying lpsstructelm to replace % the Board data structure in the parameter list of the linear % process by a sequence of variables of sort Piece. Initially, % this will yield 47 variables, but I expect that the 16 `unused' % variables representing the corners, can be removed using % lpsconstelm. This would generate an additional speedup. % The use of lpsparunfold is also expected to reduce the memory % footprint of the generation of the state space with a factor % of at least 2. % % Jan Friso Groote, 4/1/2007. % % On 3/4/2009 Jaco van de Pol analyzed this example using symbolic % state space exploration. He found a stupid copy/paste mistake % that has now been repaired. Using ltsmin (symbolic state space % generation) the necessary time was % appr. a half hour and memory requirements were approximately 8GB. % % On 9/4/2009 it turned out to be possible to generate the state % space using the recipe above (uncovering a garbage collection % bug in the aterm library slowing state space generation with % an unnecessary factor up to 1000 (sic)). The state space requirements % were 25Gbyte and the required time 24hours (svn version 5952). % Lpsstructelm (about to be called lpsparunfold) was not used, and % is expected to substantially increase the speed requirements. sort Piece = struct empty | pin | unused; Row = struct row(Piece,Piece,Piece,Piece,Piece,Piece,Piece); Board = struct col(Row,Row,Row,Row,Row,Row,Row); map getPiece:Pos#Pos#Board -> Piece; setPiece:Pos#Pos#Piece#Board->Board; var x:Pos; r1,r2,r3,r4,r5,r6,r7:Row; pc:Piece; eqn getPiece(x,1,col(r1,r2,r3,r4,r5,r6,r7))=getPiece(x,r1); getPiece(x,2,col(r1,r2,r3,r4,r5,r6,r7))=getPiece(x,r2); getPiece(x,3,col(r1,r2,r3,r4,r5,r6,r7))=getPiece(x,r3); getPiece(x,4,col(r1,r2,r3,r4,r5,r6,r7))=getPiece(x,r4); getPiece(x,5,col(r1,r2,r3,r4,r5,r6,r7))=getPiece(x,r5); getPiece(x,6,col(r1,r2,r3,r4,r5,r6,r7))=getPiece(x,r6); getPiece(x,7,col(r1,r2,r3,r4,r5,r6,r7))=getPiece(x,r7); setPiece(x,1,pc,col(r1,r2,r3,r4,r5,r6,r7))= col(setPiece(x,pc,r1),r2,r3,r4,r5,r6,r7); setPiece(x,2,pc,col(r1,r2,r3,r4,r5,r6,r7))= col(r1,setPiece(x,pc,r2),r3,r4,r5,r6,r7); setPiece(x,3,pc,col(r1,r2,r3,r4,r5,r6,r7))= col(r1,r2,setPiece(x,pc,r3),r4,r5,r6,r7); setPiece(x,4,pc,col(r1,r2,r3,r4,r5,r6,r7))= col(r1,r2,r3,setPiece(x,pc,r4),r5,r6,r7); setPiece(x,5,pc,col(r1,r2,r3,r4,r5,r6,r7))= col(r1,r2,r3,r4,setPiece(x,pc,r5),r6,r7); setPiece(x,6,pc,col(r1,r2,r3,r4,r5,r6,r7))= col(r1,r2,r3,r4,r5,setPiece(x,pc,r6),r7); setPiece(x,7,pc,col(r1,r2,r3,r4,r5,r6,r7))= col(r1,r2,r3,r4,r5,r6,setPiece(x,pc,r7)); map getPiece:Pos#Row -> Piece; setPiece:Pos#Piece#Row -> Row; var p:Pos; p1,p2,p3,p4,p5,p6,p7: Piece; pc:Piece; eqn setPiece(1,pc,row(p1,p2,p3,p4,p5,p6,p7))=row(pc,p2,p3,p4,p5,p6,p7); setPiece(2,pc,row(p1,p2,p3,p4,p5,p6,p7))=row(p1,pc,p3,p4,p5,p6,p7); setPiece(3,pc,row(p1,p2,p3,p4,p5,p6,p7))=row(p1,p2,pc,p4,p5,p6,p7); setPiece(4,pc,row(p1,p2,p3,p4,p5,p6,p7))=row(p1,p2,p3,pc,p5,p6,p7); setPiece(5,pc,row(p1,p2,p3,p4,p5,p6,p7))=row(p1,p2,p3,p4,pc,p6,p7); setPiece(6,pc,row(p1,p2,p3,p4,p5,p6,p7))=row(p1,p2,p3,p4,p5,pc,p7); setPiece(7,pc,row(p1,p2,p3,p4,p5,p6,p7))=row(p1,p2,p3,p4,p5,p6,pc); getPiece(1,row(p1,p2,p3,p4,p5,p6,p7))=p1; getPiece(2,row(p1,p2,p3,p4,p5,p6,p7))=p2; getPiece(3,row(p1,p2,p3,p4,p5,p6,p7))=p3; getPiece(4,row(p1,p2,p3,p4,p5,p6,p7))=p4; getPiece(5,row(p1,p2,p3,p4,p5,p6,p7))=p5; getPiece(6,row(p1,p2,p3,p4,p5,p6,p7))=p6; getPiece(7,row(p1,p2,p3,p4,p5,p6,p7))=p7; map initialBoard, finalBoard, emptyBoard : Board; eqn initialBoard = col(row(unused,unused,pin, pin, pin, unused,unused), row(unused,unused,pin, pin, pin, unused,unused), row(pin, pin, pin, pin, pin, pin, pin), row(pin, pin, pin, empty, pin, pin, pin), row(pin, pin, pin, pin, pin, pin, pin), row(unused,unused,pin, pin, pin, unused,unused), row(unused,unused,pin, pin, pin, unused,unused)); finalBoard = col(row(unused,unused,empty, empty, empty, unused,unused), row(unused,unused,empty, empty, empty, unused,unused), row(empty, empty, empty, empty, empty, empty, empty), row(empty, empty, empty, pin, empty, empty, empty), row(empty, empty, empty, empty, empty, empty, empty), row(unused,unused,empty, empty, empty, unused,unused), row(unused,unused,empty, empty, empty, unused,unused)); emptyBoard = col(row(unused,unused,empty, empty, empty, unused,unused), row(unused,unused,empty, empty, empty, unused,unused), row(empty, empty, empty, empty, empty, empty, empty), row(empty, empty, empty, empty, empty, empty, empty), row(empty, empty, empty, empty, empty, empty, empty), row(unused,unused,empty, empty, empty, unused,unused), row(unused,unused,empty, empty, empty, unused,unused)); map rightMovable,leftMovable,downMovable,upMovable:Pos#Pos#Board->Bool; moveRight,moveLeft,moveDown,moveUp:Pos#Pos#Board->Board; var x,y:Pos; b:Board; eqn rightMovable(x,y,b)= getPiece(x,y,b)==pin && getPiece(x+1,y,b)==pin && getPiece(x+2,y,b)==empty && x<6; moveRight(x,y,b)=setPiece(x,y,empty,setPiece(x+1,y,empty,setPiece(x+2,y,pin,b))); leftMovable(x,y,b)= getPiece(x,y,b)==pin && getPiece(Int2Pos(x-1),y,b)==pin && getPiece(Int2Pos(x-2),y,b)==empty && x>2; moveLeft(x,y,b)=setPiece(x,y,empty,setPiece(Int2Pos(x-1),y,empty, setPiece(Int2Pos(x-2),y,pin,b))); downMovable(x,y,b)= getPiece(x,y,b)==pin && getPiece(x,Int2Pos(y-1),b)==pin && getPiece(x,Int2Pos(y-2),b)==empty && y>2; moveDown(x,y,b)=setPiece(x,y,empty,setPiece(x,Int2Pos(y-1),empty, setPiece(x,Int2Pos(y-2),pin,b))); upMovable(x,y,b)= getPiece(x,y,b)==pin && getPiece(x,y+1,b)==pin && getPiece(x,y+2,b)==empty && y<6; moveUp(x,y,b)=setPiece(x,y,empty,setPiece(x,y+1,empty,setPiece(x,y+2,pin,b))); act moveright,moveleft,moveup,movedown:Pos#Pos#Piece; ready; proc X(b:Board)= (b==finalBoard) -> ready.X(emptyBoard)+ sum x,y:Pos.(x<=7 && y<=7 && rightMovable(x,y,b) ) -> moveright(x,y,getPiece(x,y,b)).X(moveRight(x,y,b))+ sum x,y:Pos.(x<=7 && y<=7 && leftMovable(x,y,b) ) -> moveleft(x,y,getPiece(x,y,b)).X(moveLeft(x,y,b))+ sum x,y:Pos.(x<=7 && y<=7 && downMovable(x,y,b) ) -> movedown(x,y,getPiece(x,y,b)).X(moveDown(x,y,b))+ sum x,y:Pos.(x<=7 && y<=7 && upMovable(x,y,b) ) -> moveup(x,y,getPiece(x,y,b)).X(moveUp(x,y,b))+ delta; init X(initialBoard); mcrl2-201409.0/examples/games/peg_solitaire/rename.ren000770 001750 001750 00000000272 12370120076 023054 0ustar00outisoutis000000 000000 var x,y,z:Piece; b,b':Bool; eqn if(b,true,false)=b; if(b,false,b')=!b && b'; if(b,x,y)==z = if(b,x==z,y==z); z==if(b,x,y) = if(b,z==x,z==x); rename ready => ready; mcrl2-201409.0/examples/games/hex/hex.mcrl2000770 001750 001750 00000007467 12370120075 020576 0ustar00outisoutis000000 000000 % This specification describes the `Hex' game, invented by Piet % Hein, said to be a descendant of a Dutch, in the Netherlands % much heralded pirate, Piet Hein. % The game has two players and a board consisting of NxM hexagonal % fields. The neighbouring fields of field (x,y) are (x+1,y), % (x+1,y-1), (x,y-1), (x-1,y), (x-1,y+1), (x,y+1). There are % two players that alternatingly put a piece on an empty field. % The first players put red pieces, the second one blue pieces. % The goal of the game for the first player is to have a % connecting sequence of red pieces from left to right. The % second player must connect the bottom with the top with blue % pieces. The player that first establishes its goal is the % winner. % A typical property of this game is that a draw is not possible. % From this it appears to be derivable that the first player % that starts the game has a winning strategy. However, this % strategy is not known. % % Thanks to Mark Winands. % Reijkjavik, 12 May 2006, Jan Friso Groote. sort Position = struct Red | Blue | Empty; map N,M:Pos; eqn N=4; M=4; sort Row=List(Position); Board=List(Row); map At:Nat#Nat#Board->Position; At:Nat#Row->Position; Put:Position#Nat#Nat#Board->Board; Put:Position#Nat#Row->Row; Wins:Position#Board->Bool; CheckRedInLeftMostColumn:Nat#Board->Bool; CheckBlueInBottomRow:Nat#Board->Bool; Connect:Nat#Nat#Board#Position->Bool; var b:Board; r:Row; p,p':Position; x,y:Nat; eqn At(x,y,[])=Empty; x==0 -> At(x,y,r|>b)=Empty; y==0 -> At(x,y,r|>b)=Empty; y==1 -> At(x,y,r|>b)=At(x,r); y>1 -> At(x,y,r|>b)=At(x,Int2Pos(y-1),b); At(x,[])=Empty; x==1 -> At(x,p|>r)=p; x>1 -> At(x,p|>r)=At(Int2Pos(x-1),r); y==1 -> Put(p,x,y,r|>b)=Put(p,x,r)|>b; y>1 -> Put(p,x,y,r|>b)=r|>Put(p,x,Int2Pos(y-1),b); x==1 -> Put(p,x,p'|>r)=p|>r; x>1 -> Put(p,x,p'|>r)=p'|>Put(p,Int2Pos(x-1),r); Wins(Red,b)=CheckRedInLeftMostColumn(1,b); y CheckRedInLeftMostColumn(y,b)= Connect(1,y,b,Red) || CheckRedInLeftMostColumn(y+1,Put(Empty,1,y,b)); y==M -> CheckRedInLeftMostColumn(y,b)=Connect(1,y,b,Red); Wins(Blue,b)=CheckBlueInBottomRow(1,b); x CheckBlueInBottomRow(x,b)= Connect(x,1,b,Blue) || CheckBlueInBottomRow(x+1,Put(Empty,x,1,b)); x==N -> CheckBlueInBottomRow(x,b)=Connect(x,1,b,Blue); At(x,y,b)!=p -> Connect(x,y,b,p)=false; x==0 -> Connect(x,y,b,p)=false; y==0 -> Connect(x,y,b,p)=false; x>N -> Connect(x,y,b,p)=false; y>M -> Connect(x,y,b,p)=false; x==N && At(x,y,b)==Red && 0 Connect(x,y,b,Red)=true; y==M && At(x,y,b)==Blue && 0 Connect(x,y,b,Blue)=true; At(x,y,b)==p && 0 Connect(x,y,b,p) = Connect(x+1,y,b',p) || Connect(x+1,Int2Nat(y-1),b',p) || Connect(x,Int2Nat(y-1),b',p) || Connect(Int2Nat(x-1),y,b',p) || Connect(Int2Nat(x-1),y+1,b',p) || Connect(x,y+1,b',p) whr b'=Put(Empty,x,y,b) end; act RedMove,BlueMove:Pos#Pos; RedWins,BlueWins; proc Hex(b:Board,RedMoves:Bool)= sum x,y:Pos. (RedMoves && x<=N && y<=M && At(x,y,b)==Empty && !Wins(Blue,b)) -> RedMove(x,y).Hex(Put(Red,x,y,b),false)+ sum x,y:Pos. (!RedMoves && x<=N && y<=M && At(x,y,b)==Empty && !Wins(Red,b)) -> BlueMove(x,y).Hex(Put(Blue,x,y,b),true)+ Wins(Red,b) -> RedWins.Hex(b,RedMoves)+ Wins(Blue,b) -> BlueWins.Hex(b,RedMoves)+ delta; init Hex([[Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty], [Empty,Empty,Empty,Empty]], true); mcrl2-201409.0/examples/games/othello/red_can_win.mcf000770 001750 001750 00000000036 12370120076 022654 0ustar00outisoutis000000 000000 true mcrl2-201409.0/examples/games/othello/white_wins_always.mcf000770 001750 001750 00000000553 12370120076 024150 0ustar00outisoutis000000 000000 % This formula is applicable to games/othello/othello.mcrl2 % % See specification for an explanation. mu X.((true) || ( (exists x,y:Nat.X) ) || ( (exists x,y:Nat.true) && (forall x,y:Nat.[Put(x, y, red)]X) ) || ((X) && ([Pass]X)) ) mcrl2-201409.0/examples/games/othello/nodeadlock.mcf000770 001750 001750 00000000224 12370120076 022506 0ustar00outisoutis000000 000000 % This formula expresses that there is no deadlock % for all reachable states. % Note that this formula does not hold on allow. [true*]true mcrl2-201409.0/examples/games/othello/red_wins_always.mcf000770 001750 001750 00000000554 12370120076 023603 0ustar00outisoutis000000 000000 % This formula is applicable to games/othello/othello.mcrl2 % % See specification for an explanation. mu X.((true) || ( (exists x,y:Nat.X) ) || ( (exists x,y:Nat.true) && (forall x,y:Nat.[Put(x, y, white)]X) ) || ((X) && ([Pass]X)) ) mcrl2-201409.0/examples/games/othello/white_can_win.mcf000770 001750 001750 00000000040 12370120076 023215 0ustar00outisoutis000000 000000 true mcrl2-201409.0/examples/games/othello/othello.mcrl2000770 001750 001750 00000015052 12370120076 022330 0ustar00outisoutis000000 000000 % This specification describes the game `Othello' or `Reversi', which is a two % player board game. There is a board of N = R + 1 by M = C + 1 where N and M % are generally both 8 (i.e., R=C=3). One player has white pieces (W) and the % other has red pieces (R). Initially, the board is set up as follows (in the % example, R=C=2): % % . . . . . . % . . . . . . % . . R W . . % . . W R . . % . . . . . . % . . . . . . % % Red makes the first move and the players alternatingly put a piece on the % board, unless a player cannot put a piece on the board, in which case he % must skip his turn. A move is made by putting a piece on the board such % that at least one piece of the opponent is enclosed with two opposite % colors. Subsequently all pieces that are enclosed will change color. % % The game ends when both players cannot do a move anymore. The player with % the largest number of pieces on the board wins. If both players have the % same number of pieces it is a draw. % % The following formula expresses that with a perfect play white can always % win the game: if white is not victorious already, then either white can do % a move to bring it closer to a victory, or red moves and all moves that red % can do will bring white closer to a victory, or a player passes, in which % case again white will be closer to victory. % % mu X.((true) || % (exists x,y:Nat.X) || % ((exists x,y:Nat.true) && % (forall x,y:Nat.[Put(x, y, red)]X)) || % ((X) && ([Pass]X))) % % On a 4x4 board this formula is true, i.e. white can always win the game. % The converse (the same formula with red and white interchanged) obviously % does not hold. % % This specification is loosely based on the 2009 specification by Jan Friso % Groote. sort Player = struct red | white; Square = struct piece(Player) | empty | invalid; Outcome = struct win(Player) | draw; Direction = List(Int); Row = List(Square); Board = List(Row); map N, M, R, C: Pos; B: Board; alldirections: List(Direction); outcome: Board -> Outcome; ccount: Board # Player -> Nat; ccount: Row # Player -> Nat; canplay: Board # Nat # Nat # Player -> Bool; at: Board # Int # Int -> Square; updated: Board # Nat # Nat # Player # Direction -> Board; update: Board # Nat # Nat # Player # List(Direction) -> Board; update: Board # Nat # Nat # Player -> Board; replace: Board # Nat # Nat # Player -> Board; replace: Row # Nat # Player -> Row; nextn, nextm: Nat # Direction -> Nat; opponent: Player -> Player; pad: Row # Nat -> Row; pad: Board # Nat -> Board; var n, m: Nat; i, j: Int; b: Board; r: Row; s: Square; P: Player; d: Direction; l: List(Direction); eqn % Directions to search in, as (n,m) vectors alldirections = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]; % Generalize the board to have sentinels ("invalid") at the borders 0 <= i && i < N && 0 <= j && j < M -> at(b, i, j) = b.Int2Nat(i).Int2Nat(j); 0 > i || i >= N || 0 > j || j >= M -> at(b, i, j) = invalid; % Calculate outcome of board outcome(b) = if(i == j, draw, if(i > j, win(red), win(white))) whr i = ccount(b, red), j = ccount(b, white) end; ccount(r |> b, P) = ccount(r, P) + ccount(b, P); b == [] -> ccount(b, P) = 0; s == piece(P) -> ccount(s |> r, P) = ccount(r, P) + 1; s != piece(P) -> ccount(s |> r, P) = ccount(r, P); r == [] -> ccount(r, P) = 0; % Calculate whether player p may place a piece on (n,m) canplay(b, n, m, P) = at(b, n, m) == empty && update(b, n, m, P) != b; % Let player P place a piece on position (n,m) of b. Return % the altered board. If this is not a valid move, the same % board is returned. update(b, n, m, P) = update(b, n, m, P, alldirections); at(b, n + d . 0, m + d . 1) == piece(opponent(P)) -> update(b, n, m, P, d |> l) = if(newboard != b, update(replace(newboard, n, m, P), n, m, P, l), update(b, n, m, P, l)) whr newboard = updated(b, n, m, P, d) end; at(b, n + d . 0, m + d . 1) != piece(opponent(P)) -> update(b, n, m, P, d |> l) = update(b, n, m, P, l); update(b, n, m, P, []) = b; ((lookahead == empty || lookahead == invalid) whr lookahead = at(b, n + d . 0, m + d . 1) end) -> updated(b, n, m, P, d) = b; (lookahead == piece(P) whr lookahead = at(b, n + d . 0, m + d . 1) end) -> updated(b, n, m, P, d) = replace(b, n, m, P); ((lookahead != empty && lookahead != invalid && lookahead != piece(P)) whr lookahead = at(b, n + d . 0, m + d . 1) end) -> updated(b, n, m, P, d) = updated(b, Int2Nat(n + d . 0), Int2Nat(m + d . 1), P, d); % Assign a piece of player P to position (n, m) of board b n > 0 -> replace(r |> b, n, m, P) = r |> replace(b, Int2Nat(n - 1), m, P); n == 0 -> replace(r |> b, n, m, P) = replace(r, m, P) |> b; m > 0 -> replace(s |> r, m, P) = s |> replace(r, Int2Nat(m - 1), P); m == 0 -> replace(s |> r, m, P) = piece(P) |> r; % Opponent definition opponent(red) = white; opponent(white) = red; % Initial board: B = pad([pad([piece(red), piece(white)], 0), pad([piece(white),piece(red)], 0)], 0); R = 1; % Extra rows C = 1; % Extra columns N = 2 * R + 2; % Board height M = 2 * C + 2; % Board width n < C -> pad(r, n) = pad(empty |> r <| empty, n + 1); n == C -> pad(r, n) = r; n < C -> pad(b, n) = pad(r |> b <| r, n + 1) whr r = pad([empty, empty], 0) end; n == C -> pad(b, n) = b; act Put: Nat # Nat # Player; % A player puts a piece on the board Outcome: Outcome; % The game has ended with this outcome Pass; % A player is forced to skip a turn proc Othello(board: Board, turn: Player, canpass: Bool) = % All next moves for the current player sum n, m: Nat . canplay(board, n, m, turn) -> Put(n, m, turn) . Othello(update(board, n, m, turn), opponent(turn), true) % If no next moves exist for the current player, and the opponent % did not pass in the last turn, then this player can pass. + ( canpass && !exists n, m: Nat . canplay(board, n, m, turn)) -> Pass . Othello(board, opponent(turn), false) % If both players have passed, then the game is finished and the % outcome is reported. + (!canpass && !exists n, m: Nat . canplay(board, n, m, turn)) -> Outcome(outcome(board)) . Othello() + delta; init Othello(B, red, true); mcrl2-201409.0/examples/games/othello/exists_draw.mcf000770 001750 001750 00000000032 12370120076 022734 0ustar00outisoutis000000 000000 true mcrl2-201409.0/examples/language/numbers.mcrl2000770 001750 001750 00000002466 12370120073 021360 0ustar00outisoutis000000 000000 % This is a simple example in which all numeric operators that are provided % in the default implementation are exercised. act a: Pos; b: Nat; c: Int; d: Real; proc P(p,p': Pos, n,n': Nat, z,z': Int, r,r':Real) = a(p) . P() + b(n) . P() + c(z) . P() + c(-p) . P() + c(-n) . P() + c(-z) . P() + d(-r) . P() + a(min(p, p')) . P() + b(min(p, n)) . P() + b(min(n, n')) . P() + c(min(p, z)) . P() + c(min(n, z)) . P() + c(min(z, z')) . P() + d(min(r, r')) . P() + a(max(p, p')) . P() + a(max(p, n)) . P() + b(max(n, n')) . P() + a(max(p, z)) . P() + b(max(n, z)) . P() + c(max(z, z')) . P() + d(max(r, r')) . P() + a(p+p') . P() + a(p+n) . P() + a(n+p) . P() + b(n+n') . P() + c(n+z) . P() + c(z+z') . P() + d(r+r') . P() + c(p-p') . P() + c(n-n') . P() + c(z-z') . P() + d(r-r') . P() + a(p*p') . P() + b(n*n') . P() + c(z*z') . P() + d(r*r') . P() + d(p/p') . P() + d(n/n') . P() + d(z/z') . P() + d(r/r') . P() + a(succ(p)) . P() + a(succ(n)) . P() + c(succ(z)) . P() + d(succ(r)) . P() + b(pred(p)) . P() + c(pred(n)) . P() + c(pred(z)) . P() + d(pred(r)) . P() + b(n div p) . P() + b(n mod p) . P() + a(exp(p, n)) . P() + b(exp(n, n')) . P() + c(exp(z, n)) . P() + d(exp(r, z)) . P() + b(abs(z)) . P() + d(abs(r)) . P() + c(floor(r)) . P() + c(ceil(r)) . P() + c(round(r)) . P(); init P(3, 2, 0, 4, -5, 5, 1/2, 1/4); mcrl2-201409.0/examples/language/rational.mcrl2000770 001750 001750 00000002622 12370120073 021510 0ustar00outisoutis000000 000000 % This is an mCRL2 process specification which can be used for testing % operations on rational numbers. % Tests for unary operations floor, ceil, round, succ, pred, -, abs, succ, pred act unary_operations : Real # Int # Int # Int # Real # Real # Real # Real; proc Test_unary_operations = sum x: Int, p: Pos, r: Real. (x >= -5 && x <= 5 && p <= 10 && r == x/p) -> unary_operations(r, floor(r), ceil(r), round(r), abs(r), -r, succ(r), pred(r)) <> delta; % Tests for binary operations <, <=, >=, >, max, min, +, -, *, / act binary_operations: Real # Real # Bool # Bool # Bool # Bool # Real # Real # Real # Real # Real # Real; left_operand: Real; proc Test_binary_operations = sum x: Int, p: Pos, r: Real. (x >= -5 && x <= 5 && p <= 10 && r == x/p) -> left_operand(r) . (sum y: Int, q: Pos, s: Real. (y >= -5 && y <= 5 && q <= 10 && s == y/q) -> binary_operations(r, s, r < s, r <= s, r >= s, r > s, min(r, s), max(r, s), r + s, r - s, r * s, r / s) <> delta ) <> delta; % Tests for exponentation act base: Real; exponent: Real # Int # Real; proc Test_exponentation = sum x: Int, p: Pos, r: Real. (x >= -5 && x <= 5 && p <= 10 && r == x/p) -> (base(r) . (sum y: Int. (y >= -5 && y <= 5) -> exponent(r, y, exp(r, y)) <> delta)) <> delta; init Test_unary_operations + Test_binary_operations + Test_exponentation; mcrl2-201409.0/examples/language/gpa_10_1.mcrl2000770 001750 001750 00000001226 12370120073 021165 0ustar00outisoutis000000 000000 % This is based on the example from Section 10.1 of the TU/e Computer Science % master's thesis titled 'GenSpect Process Algebra' by Muck van Weerdenburg. act get_i, put_k, get_l, put_j: Nat; get, put: Nat; proc Sqr_ik = sum n:Nat. get_i(n) | put_k(n*n) . Sqr_ik; Sqr_lj = sum n:Nat. get_l(n) | put_j(n*n) . Sqr_lj; P_kl(b:Bag(Nat)) = sum n:Nat. put_k(n) . P_kl(b + {n:1}) + sum n:Nat. (n in b) -> get_l(n) . P_kl(b - {n:1}); DSqr_ij = hide({put,get}, allow({get_i|put,put_j|get}, comm({put_k|put_k -> put, get_l|get_l -> get}, Sqr_ik || P_kl({:}) || Sqr_lj ) ) ); init DSqr_ij; mcrl2-201409.0/examples/language/small3.mcrl2000770 001750 001750 00000000354 12370120073 021072 0ustar00outisoutis000000 000000 % This is an example of a simple process, that describes % two parallel processes that can respectively do an a and % a b, which must communicate to c. act a, b, c; proc X = a.X; Y = b.Y; init allow({c},comm({a|b->c},X||Y)); mcrl2-201409.0/examples/language/list.mcrl2000770 001750 001750 00000000334 12370120073 020650 0ustar00outisoutis000000 000000 proc P(l: List(Nat)) = (1 in l) -> tau . P(10 |> l ++ [#l] <| 100) + (l.1 == 30) -> tau . P(tail(l)) + (head(l) == 20) -> tau . P([rhead(l)] ++ rtail(l)); init P([20, 30, 40]); mcrl2-201409.0/examples/language/funccomp.mcrl2000770 001750 001750 00000000576 12370120073 021517 0ustar00outisoutis000000 000000 % Function composition % -------------------- % % This is an mCRL2 specification of the composition f ° g for function f of % type B -> C and function g of type A -> B. sort A,B,C; map comp: (B -> C) # (A -> B) -> (A -> C); var f: B -> C; g: A -> B; eqn comp(f,g) = lambda x:A.f(g(x)); init delta; mcrl2-201409.0/examples/language/delta.mcrl2000770 001750 001750 00000000207 12370120073 020765 0ustar00outisoutis000000 000000 % This is one of the smallest examples of a specification that does absolutely % nothing. It is useful for test purposes. init delta; mcrl2-201409.0/examples/language/forall.mcrl2000770 001750 001750 00000000370 12370120073 021154 0ustar00outisoutis000000 000000 % This is a simple test case for universal quantificiation proc P = (forall x:Pos . true) -> tau . P + (forall x,y:Pos . true) -> tau . P + (forall x,y,z:Pos . true) -> tau . P + (forall x,y:Pos . x+y > 0) -> tau . P; init P; mcrl2-201409.0/examples/language/gpa_10_2.mcrl2000770 001750 001750 00000001166 12370120073 021171 0ustar00outisoutis000000 000000 % This is based on the example from Section 10.2 of the TU/e Computer Science % master's thesis titled 'GenSpect Process Algebra' by Muck van Weerdenburg. act put_i, get_k: Nat; put_k, get_j: Nat; pass_k: Nat; proc P_ik(b:Bag(Nat)) = sum n:Nat. put_i(n) . P_ik(b + {n:1}) + sum n:Nat. (n in b) -> get_k(n) . P_ik(b - {n:1}); P_kj(b:Bag(Nat)) = sum n:Nat. put_k(n) . P_kj(b + {n:1}) + sum n:Nat. (n in b) -> get_j(n) . P_kj(b - {n:1}); P2 = hide({pass_k}, allow({put_i, pass_k, get_j}, comm({get_k | put_k -> pass_k}, P_ik({:}) || P_kj({:}) ) ) ); init P2; mcrl2-201409.0/examples/language/divide2_10.mcrl2000770 001750 001750 00000000753 12370120073 021530 0ustar00outisoutis000000 000000 % This is an mCRL2 process specification showing that the representation of % rational numbers is exact. It divides a number by 2, and does this N times. % When a number after division by 2 is greater than the number itself an error % is generated... and this does not occur. % % Aad Mathijssen, February 2009. map N: Nat; eqn N = 10; act a: Real; error; proc P(n: Nat, r: Real) = (n < N) -> a(r) . P(n+1, r/2) + (r/2 >= r) -> error . delta; init P(0, 1); mcrl2-201409.0/examples/language/par.mcrl2000770 001750 001750 00000000177 12370120073 020464 0ustar00outisoutis000000 000000 % A simple process to test whether terminating processes are handled % well in the parallel composition. act a; init a || a; mcrl2-201409.0/examples/language/gpa_10_3.mcrl2000770 001750 001750 00000001150 12370120073 021163 0ustar00outisoutis000000 000000 % This is based on the example from Section 10.3 of the TU/e Computer Science % master's thesis titled 'GenSpect Process Algebra' by Muck van Weerdenburg. act r_dup, s_dup1, s_dup2, r_inc, s_inc, r_mul1, r_mul2, s_mul, c : Int; proc Dup = sum x:Int. r_dup(x) | s_dup1(x) | s_dup2(x) . Dup; Inc = sum x:Int. r_inc(x) | s_inc(x+1) . Inc; Mul = sum x,y:Int. r_mul1(x) | r_mul2(y) | s_mul(x*y) . Mul; Dim = allow({r_dup | s_mul}, hide({c}, comm({s_dup1 | r_mul1 -> c, s_dup2 | r_inc -> c, s_inc | r_mul2->c}, Dup || Inc || Mul ) ) ); init Dim; mcrl2-201409.0/examples/language/delta0.mcrl2000770 001750 001750 00000000202 12370120073 021040 0ustar00outisoutis000000 000000 % This is the smallest examples of a specification that does absolutely % nothing. It is useful for test purposes. init delta@0; mcrl2-201409.0/examples/language/divide2_100.mcrl2000770 001750 001750 00000000754 12370120073 021611 0ustar00outisoutis000000 000000 % This is an mCRL2 process specification showing that the representation of % rational numbers is exact. It divides a number by 2, and does this N times. % When a number after division by 2 is greater than the number itself an error % is generated... and this does not occur. % % Aad Mathijssen, February 2009. map N: Nat; eqn N = 100; act a: Real; error; proc P(n: Nat, r: Real) = (n < N) -> a(r) . P(n+1, r/2) + (r/2 >= r) -> error . delta; init P(0, 1); mcrl2-201409.0/examples/language/small2.mcrl2000770 001750 001750 00000000322 12370120073 021064 0ustar00outisoutis000000 000000 % This simple process describes an infinite loop of 'a' actions. % The smallest state space corresponding to this specification % consists of one state and one transition. act a; proc X = a.X; init X; mcrl2-201409.0/examples/language/sets_bags.mcrl2000770 001750 001750 00000005347 12370120073 021660 0ustar00outisoutis000000 000000 % This file contains an mCRL2 specification for testing operations % on sets and bags. % The element sort is represented by E. Change the specification of % this sort to start experimenting. sort E = struct e1 | e2 | e3; % Test set operations act insert_s: E; insert_t: E; ts1_set_equals_st: Bool; ts2_set_lt_st: Bool; ts3_set_lte_st: Bool; ts4_set_union_st: Set(E); ts5_set_inter_st: Set(E); ts6_set_diff_st: Set(E); ts7_set_compl_s: Set(E); ts8_set_compl_t: Set(E); ts9_set2bag_st: Bag(E) # Bag(E); proc Test_sets(sets_only: Bool, max_count: Nat) = Test_sets({}, {}, sets_only, max_count); Test_sets(s,t: Set(E), sets_only: Bool, max_count: Nat) = sum e: E. (insert_s(e) . Test_sets({e} + s, t, sets_only, max_count) + insert_t(e) . Test_sets(s, {e} + t, sets_only, max_count) ) + ts1_set_equals_st(s == t) . delta + ts2_set_lt_st(s < t) . delta + ts3_set_lte_st(s <= t) . delta + ts4_set_union_st(s + t) . delta + ts5_set_inter_st(s * t) . delta + ts6_set_diff_st(s - t) . delta + ts7_set_compl_s(!s) . Test_sets(!s, t, sets_only, max_count) + ts8_set_compl_t(!t) . Test_sets(s, !t, sets_only, max_count) + (!sets_only) -> ts9_set2bag_st(Set2Bag(s), Set2Bag(t)) . Test_bags(Set2Bag(s), Set2Bag(t), sets_only, max_count) <> delta ; % Test bag operations act insert_b: E; insert_c: E; tb1_bag_equals_bc: Bool; tb2_bag_lt_bc: Bool; tb3_bag_lte_bc: Bool; tb4_bag_join_bc: Bag(E); tb5_bag_inter_bc: Bag(E); tb6_bag_diff_bc: Bag(E); tb7_bag2set_bc: Set(E) # Set(E); proc Test_bags(bags_only: Bool, max_count: Nat) = Test_bags({:}, {:}, bags_only, max_count); Test_bags(b: Bag(E), c: Bag(E), bags_only: Bool, max_count: Nat) = sum e: E. (count(e, b) < max_count) -> insert_b(e) . Test_bags({e:1} + b, c, bags_only, max_count) <> delta + sum e: E. (count(e, c) < max_count) -> insert_c(e) . Test_bags(b, {e:1} + c, bags_only, max_count) <> delta + tb1_bag_equals_bc(b == c) . delta + tb2_bag_lt_bc(b < c) . delta + tb3_bag_lte_bc(b <= c) . delta + tb4_bag_join_bc(b + c) . delta + tb5_bag_inter_bc(b * c) . delta + tb6_bag_diff_bc(b - c) . delta + (!bags_only) -> tb7_bag2set_bc(Bag2Set(b), Bag2Set(c)) . Test_sets(Bag2Set(b), Bag2Set(c), bags_only, max_count) <> delta ; % Test set add/remove process act add, remove: E; proc Test_set_add_remove(s: Set(E)) = sum e: E. add(e) . Test_set_add_remove({e} + s) + sum e: E. remove(e) . Test_set_add_remove(s - {e}) ; % Initial process (to test set and bag operations) %init Test_set_add_remove({x:E | x == e2}); %init Test_set_add_remove({}); init Test_sets(false, 2); mcrl2-201409.0/examples/language/small1.mcrl2000770 001750 001750 00000001031 12370120073 021061 0ustar00outisoutis000000 000000 % This is the mCRL2 variant of the 'small1' muCRL example. % The process exhibits a simple sequence of a and b actions, % where the parameter of 'a' is a increasing number and the parameter % of 'b' can be freely chosen. The state space of this example is infinite % and it is also infinitely branching. % % Note that this specification is much shorter and more readable % than its muCRL counterpart, because of the availability of predefined % data types. act a,b: Nat; proc X(n: Nat) = sum m:Nat. a(n).b(m).X(n+1); init X(0); mcrl2-201409.0/examples/language/upcast.mcrl2000770 001750 001750 00000000554 12370120073 021200 0ustar00outisoutis000000 000000 % This is an example where numerical pattern matching is used in the implicit % upcasts of numeric types. map Np: Nat -> Nat; Ip, In: Int -> Int; Rp, Rn, Ri: Real -> Real; var p: Pos; eqn Np(p) = 0; var p: Pos; eqn Ip(p) = 0; var n: Nat; eqn In(n) = 0; var p: Pos; eqn Rp(p) = 0; var n: Nat; eqn Rn(n) = 0; var i: Int; eqn Ri(i) = 0; init delta@0; mcrl2-201409.0/examples/language/time.mcrl2000770 001750 001750 00000000212 12370120073 020626 0ustar00outisoutis000000 000000 % A simple process to see whether time is correctly handled in the % translation to linear processes. act a; proc P = a@1 . P; init P; mcrl2-201409.0/examples/language/exists.mcrl2000770 001750 001750 00000000372 12370120073 021216 0ustar00outisoutis000000 000000 % This is a simple test case for existential quantificiation proc P = (exists x:Pos . true) -> tau . P + (exists x,y:Pos . true) -> tau . P + (exists x,y,z:Pos . true) -> tau . P + (exists x,y:Pos . x+y > 0) -> tau . P; init P; mcrl2-201409.0/examples/language/tau.mcrl2000770 001750 001750 00000000170 12370120073 020464 0ustar00outisoutis000000 000000 % This is one of the smallest examples of a specification. % This specification is useful for test purposes. init tau; mcrl2-201409.0/examples/language/divide2_500.mcrl2000770 001750 001750 00000000726 12370120073 021614 0ustar00outisoutis000000 000000 % This is an mCRL2 process specification showing that the representation of % rational numbers is exact. It divides a number by 2, and does this 500 times. % When a number after division by 2 is greater than the number itself an error % is generated... and this does not occur. % % Aad Mathijssen, February 2009. act a: Real; error; proc P(n: Nat, r: Real) = (n < 500) -> a(r) . P(n+1, r/2) + (r/2 >= r) -> error . delta; init P(0, 1); mcrl2-201409.0/examples/language/struct.mcrl2000770 001750 001750 00000001470 12370120073 021223 0ustar00outisoutis000000 000000 % This is a small example showing various uses of structured sorts. % Collected from some earlier examples by Jeroen Keiren, 8/9/2009. % A simple structured sort with a single element e1 sort E = struct e1; % A structured sort recursively depending on natural numbers, % with elements of the form d1(n) and d2(n), where n is an arbitrary % natural number. Furthermore, arg2(d2(n)) = n, is_d1(d1(n)) = true, % is_d1(d2(n)) = false, and analougly for is_d2. sort D = struct d1(Nat)?is_d1 | d2(arg2:Nat)?is_d2; % Two mutually dependent sorts A and APos, whereas APos also % depends on positive natural numbers. sort A = struct a?is_a; sort APos = struct ca(a:A)?is_ca | cpos(p:Pos)?is_cpos; % In addition, structured sorts can be used inline, as is shown in the % following mapping. map f : struct c(p: Pos); init delta; mcrl2-201409.0/examples/language/lambda.mcrl2000770 001750 001750 00000000714 12370120073 021117 0ustar00outisoutis000000 000000 % This is a simple test case for lambda expressions map f: Pos -> Bool; g: Pos # Pos -> Bool; h: Pos # Pos # Pos -> Bool; j: Pos -> Pos # Pos -> Bool; eqn f = lambda x:Pos . x > 0; g = lambda x,y:Pos . if(x>y, true, false); h = lambda x,y,z:Pos . x > y && y > z; j = lambda x:Pos . lambda y,z:Pos . true; proc P = (f(1)) -> tau . P + (g(1,2)) -> tau . P + (h(3,2,1)) -> tau . P + (j(3)(2,1)) -> tau . P; init P; mcrl2-201409.0/tests/grammars/bes-op_precendence.g000770 001750 001750 00000001251 12370120021 022166 0ustar00outisoutis000000 000000 //--- BES BesSpec: [bes] BesEqnSpec BesInit ; BesEqnSpec: [eqndecls] 'pbes' BesEqnDecls ; BesEqnDecls : [eq] BesEqnDecl | [eqs] BesEqnDecl BesEqnDecls ; BesEqnDecl: [eqdecl] FixedPointOperator BesVar '=' BesExpr ';' ; BesExpr : [be_impl] BesTerm '=>' BesExpr | [be_term] BesTerm ; BesTerm : [be_disj] BesFactor '||' BesTerm | [be_conj] BesFactor '&&' BesTerm | [be_fac] BesFactor ; BesFactor : [be_true] 'true' | [be_false] 'false' | [be_var] BesVar | [be_neg] '!' BesFactor | [be_brk] '(' BesExpr ')' ; BesInit: [init] 'init' BesVar ';' ; FixedPointOperator : [fp_mu] 'mu' | [fp_nu] 'nu' ; mcrl2-201409.0/tests/grammars/pbes.g000770 001750 001750 00000007431 12370120021 017405 0ustar00outisoutis000000 000000 DataExpr : [da_id] Id | [da_numb] Number | [da_true] 'true' | [da_false] 'false' // | '[' ']' // | '{' '}' // | '[' DataExprList ']' // | '{' BagEnumEltList '}' // | '{' VarDecl '|' DataExpr '}' // | '{' DataExprList '}' | [da_brk] '(' DataExpr ')' // | DataExpr '[' DataExpr '->' DataExpr ']' $unary_left 13 // | DataExpr '(' DataExprList ')' $unary_left 13 | [da_neg] '!' DataExpr $unary_right 12 | [da_inv] '-' DataExpr $unary_right 12 // | '#' DataExpr $unary_right 12 | [da_forall] 'forall' VarsDeclList '.' DataExpr | [da_exists] 'exists' VarsDeclList '.' DataExpr // | [da_lamb] 'lambda' VarsDeclList '.' DataExpr | [da_impl] DataExpr '=>' DataExpr | [da_disj] DataExpr '||' DataExpr | [da_conj] DataExpr '&&' DataExpr | [da_eq] DataExpr '==' DataExpr | [da_neq] DataExpr '!=' DataExpr | [da_lt] DataExpr '<' DataExpr | [da_leq] DataExpr '<=' DataExpr | [da_geq] DataExpr '>=' DataExpr | [da_gt] DataExpr '>' DataExpr // | DataExpr ('in' $binary_op_left 6) DataExpr // | DataExpr ('|>' $binary_op_right 7) DataExpr // | DataExpr ('<|' $binary_op_left 8) DataExpr // | DataExpr ('++' $binary_op_left 9) DataExpr | [da_plus] DataExpr '+' DataExpr | [da_min] DataExpr '-' DataExpr | [da_divides] DataExpr '/' DataExpr // | DataExpr ('div' $binary_op_left 11) DataExpr // | DataExpr ('mod' $binary_op_left 11) DataExpr | [da_times] DataExpr '*' DataExpr // | DataExpr ('.' $binary_op_left 12) DataExpr // | [da_whr] DataExpr 'whr' AssignmentList 'end' $unary_left 0 ; // Needed to get arguments for prop var that is DataExprListInst: [dalinst] DataExpr | [dallinst] DataExpr ',' DataExprListInst ; //BagEnumElt: DataExpr ':' DataExpr ; //BagEnumEltList: BagEnumElt ( ',' BagEnumElt )* ; SimpleSortExpr : [se_bool] 'Bool' // | [se_pos] 'Pos' | [se_nat] 'Nat' | [se_int] 'Int' | [se_real] 'Real' // | [se_list] 'List' '(' SortExpr ')' // | [se_set] 'Set' '(' SortExpr ')' ; SortExpr : [se] SimpleSortExpr ; IdList: [idlid] Id | [idlids] Id ',' IdList ; VarDecl: [vdecl] IdList ':' SortExpr ; VarsDecls: [vsdecl] VarDecl | [vsdecls] VarDecl ',' VarsDecls ; VarsDeclList: [vdcl] VarsDecls ; //--- PBES PbesSpec: [pbes] PbesEqnSpec PbesInit ; PbesEqnSpec: [pbeseqnspec] 'pbes\n ' PbesEqnDecls ; PbesEqnDecls: [pbeseq] PbesEqnDecl | [pbeseqs] PbesEqnDecl PbesEqnDecls ; PbesEqnDecl: [pbeseqdecl] FixedPointOperator UniquePropVarDecl '=' Guard '&&' '(' PbesExpr ')' ';\n ' ; //PbesEqnDecl: [pbeseqdecl] FixedPointOperator UniquePropVarDecl '=' PbesExpr ';' ; Guard : [no_guard] 'true' | [guard] 'val' '(' G ')' '&&' Guard ; FixedPointOperator : 'mu' | 'nu' ; UniquePropVarDecl : [vardecl] Id | [vardecllist] Id '(' VarsDeclList ')' ; PropVarInst: [propvarinst] VarInst ; VarInst : [varinst] Id | [varinstlist] Id '(' DataExprListInst ')' ; PbesInit: [init] '\ninit' PropVarInst ';' ; DataValExpr: [dvale] 'val' '(' DataExpr ')'; PbesExpr : [pe_dv] DataValExpr | [pe_true] 'true' | [pe_false] 'false' | [pe_forall] 'forall' VarsDeclList '.' Guard '&&' PbesExpr | [pe_exists] 'exists' VarsDeclList '.' Guard '&&' PbesExpr | [pe_impl] PbesExpr '=>' PbesExpr | [pe_disj] PbesExpr '||' PbesExpr | [pe_conj] PbesExpr '&&' PbesExpr | [pe_neg] '!' PbesExpr | [pe_brk] '(' PbesExpr ')' | [pe_pv] PropVarInst ;mcrl2-201409.0/tests/grammars/bes.g000770 001750 001750 00000001120 12370120021 017212 0ustar00outisoutis000000 000000 //--- BES BesSpec: [bes] BesEqnSpec BesInit ; BesEqnSpec: [eqndecls] 'pbes' BesEqnDecls ; BesEqnDecls : [eq] BesEqnDecl | [eqs] BesEqnDecl BesEqnDecls ; BesEqnDecl: [eqdecl] FixedPointOperator BesVar '=' BesExpr ';' ; BesExpr : [be_true] 'true' | [be_false] 'false' | [be_impl] BesExpr '=>' BesExpr | [be_disj] BesExpr '||' BesExpr | [be_conj] BesExpr '&&' BesExpr | [be_neg] '!' BesExpr | [be_brk] '(' BesExpr ')' | [be_var] BesVar ; BesInit: [init] 'init' BesVar ';' ; FixedPointOperator : [fp_mu] 'mu' | [fp_nu] 'nu' ; mcrl2-201409.0/tests/grammars/mcrl2.g000770 001750 001750 00000005044 12370120021 017471 0ustar00outisoutis000000 000000 SimpleSortExpr : [se_bool] 'Bool' // | [se_pos] 'Pos' | [se_nat] 'Nat' | [se_int] 'Int' | [se_real] 'Real' | [se_ref] Id // | [se_list] 'List' '(' SortExpr ')' // | [se_set] 'Set' '(' SortExpr ')' // | [se_struct] 'struct' ConstrDeclList // structured sort ; SortExpr : [se] SimpleSortExpr ; IdList: [idlid] Id | [idlids] Id ',' IdList ; ConstrDeclList: [constdecl] Id | [constdecllist] Id '|' ConstrDeclList ; SortSpec: [sortspec] 'sort' SortDecls; SortDecls: [sortdecls1] SortDecl | [sortdecls2] SortDecl SortDecls ; SortDecl : [sortdecl1] IdList ';\n' | [sortdecl2] Id '=' SortExpr ';\n' ; VarDecl: [vdecl] IdList ':' SortExpr ; VarsDeclList : [vsdecl] VarDecl | [vsdecls] VarDecl ',' VarsDeclList ; Action: [act] Id ; ActDecls: [actdecl] IdList ';\n' // | [actspeclist] IdList ActDecls ; ActSpec: [actspec] '\nact' ActDecls ; //--- mCRL2 specification //mCRL2Spec: mCRL2SpecElt+ Init mCRL2SpecElt* ; mCRL2Spec: [mcrl2] SortSpec ActSpec ProcSpec Init; //mCRL2SpecElt // : ( SortSpec // | ConsSpec // | MapSpec // | EqnSpec // | GlobVarSpec // | ActSpec // | ProcSpec // ) ProcSpec // ; ProcDecl: [procdecl] Id '=' ProcExpr ';\n' | [procdecllist] Id '(' VarsDeclList ')' '=' ProcExpr ';\n' ; ProcSpec: [procspec] 'proc' ProcDecl | [procspecs] 'proc' ProcDecl ProcSpec ; Init: [init] '\ninit' ProcExpr ';' ; ProcVarInst : [pcinst] Id | [pcinstlist] Id '(' DataExprListInst ')' ; ProcExpr : [pre_act] Action | [pre_pv] ProcVarInst | [pre_delta] 'delta' | [pre_tau] 'tau' // | 'block' '(' ActIdSet ',' ProcExpr ')' // | 'allow' '(' MultActIdSet ',' ProcExpr ')' // | 'hide' '(' ActIdSet ',' ProcExpr ')' // | 'rename' '(' RenExprSet ',' ProcExpr ')' // | 'comm' '(' CommExprSet ',' ProcExpr ')' | [pre_brk] '(' ProcExpr ')' | [pre_choice] ProcExpr '+' ProcExpr | [pre_sum] 'sum' VarsDeclList '.' ProcExpr | [pre_pllel] ProcExpr '||' ProcExpr // | [pre_lftmrg] ProcExpr '||_' ProcExpr | [pre_cond] DataExpr '->' ProcExpr // | (DataExprUnit IfThen $unary_op_right 5) ProcExpr // | ProcExpr ('<<' $binary_op_left 6) ProcExpr | [pre_seq] ProcExpr '.' ProcExpr // | [pre_time] ProcExpr '@' DataExpr // | [pre_multact] ProcExpr '|' ProcExpr ; //IfThen: '->' ProcExprNoIf '<>' $left 0 ; mcrl2-201409.0/tests/grammars/equationstest.g000770 001750 001750 00000000014 12370120021 021352 0ustar00outisoutis000000 000000 A: a | a A ;mcrl2-201409.0/tests/grammars/data.g000770 001750 001750 00000003475 12370120021 017371 0ustar00outisoutis000000 000000 DataExpr : [da_id] Id | [da_numb] Number | [da_true] 'true' | [da_false] 'false' // | '[' ']' // | '{' '}' // | '[' DataExprList ']' // | '{' BagEnumEltList '}' // | '{' VarDecl '|' DataExpr '}' // | '{' DataExprList '}' | [da_brk] '(' DataExpr ')' // | DataExpr '[' DataExpr '->' DataExpr ']' $unary_left 13 // | DataExpr '(' DataExprList ')' $unary_left 13 | [da_neg] '!' DataExpr $unary_right 12 | [da_inv] '-' DataExpr $unary_right 12 // | '#' DataExpr $unary_right 12 | [da_forall] 'forall' VarsDeclList '.' DataExpr | [da_exists] 'exists' VarsDeclList '.' DataExpr // | [da_lamb] 'lambda' VarsDeclList '.' DataExpr | [da_impl] DataExpr '=>' DataExpr | [da_disj] DataExpr '||' DataExpr | [da_conj] DataExpr '&&' DataExpr | [da_eq] DataExpr '==' DataExpr | [da_neq] DataExpr '!=' DataExpr | [da_lt] DataExpr '<' DataExpr | [da_leq] DataExpr '<=' DataExpr | [da_geq] DataExpr '>=' DataExpr | [da_gt] DataExpr '>' DataExpr // | DataExpr ('in' $binary_op_left 6) DataExpr // | DataExpr ('|>' $binary_op_right 7) DataExpr // | DataExpr ('<|' $binary_op_left 8) DataExpr // | DataExpr ('++' $binary_op_left 9) DataExpr | [da_plus] DataExpr '+' DataExpr | [da_min] DataExpr '-' DataExpr | [da_divides] DataExpr '/' DataExpr // | DataExpr ('div' $binary_op_left 11) DataExpr // | DataExpr ('mod' $binary_op_left 11) DataExpr | [da_times] DataExpr '*' DataExpr // | DataExpr ('.' $binary_op_left 12) DataExpr // | [da_whr] DataExpr 'whr' AssignmentList 'end' $unary_left 0 ; // Needed to get arguments for prop var that is DataExprListInst: [dalinst] DataExpr | [dallinst] DataExpr ',' DataExprListInst ;mcrl2-201409.0/tests/test.py000770 001750 001750 00000025125 12370120021 016024 0ustar00outisoutis000000 000000 import randgen, yaml from subprocess import Popen, PIPE, STDOUT import shutil import psutil import time import os.path import threading import multiprocessing import exceptions import sys import re import codecs from collections import OrderedDict class ToolInputError(Exception): def __init__(self, name, value): self.tool = name self.value = value def __str__(self): return repr(self.value) class UnusedToolsError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class ToolCrashedError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class ToolTimeoutError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class MemoryError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class Node: def __init__(self, label, type, ext): self.base = label self.label = label self.iter = 0 self.type = type self.value = None self.ext = ext return class Tool: def __init__(self, name, input, output, args): self.name = name self.input = input self.output = output self.args = args self.error = '' self.executed = False self.infiles = True self.outfiles = True self.time = 0 if sys.platform.startswith("win"): # Don't display the Windows GPF dialog if the invoked program dies. # See comp.os.ms-windows.programmer.win32 # How to suppress crash notification dialog?, Raymond Chen Jan 14,2004 - import ctypes SEM_NOGPFAULTERRORBOX = 0x0002 # From MSDN ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX); self.subprocess_flags = 0x8000000 #win32con.CREATE_NO_WINDOW? else: self.subprocess_flags = 0 return def canExecute(self): for i in self.input: if i.value == None: return False return True def execute(self, dir, timeout, memlimit, verbose): args = [] if dir == None: dir = '' name = os.path.join(dir, self.name) if self.infiles: #args = [os.path.join(os.getcwd(), i.label + "." + i.ext) for i in self.input] args = [os.path.join(os.getcwd(), i.label) for i in self.input] if self.outfiles: #args = args + [os.path.join(os.getcwd(), o.label + "." + o.ext) for o in self.output] args = args + [os.path.join(os.getcwd(), o.label) for o in self.output] if verbose: print 'Executing ' + ' '.join([name] + args + self.args) p = Popen([name] + args + self.args, stdout=PIPE, stdin=PIPE, stderr=PIPE, creationflags=self.subprocess_flags) input = None if not self.infiles: input = (b' ').join([i.value for i in self.input]) t = threading.Thread(target=self.threadedExecute, args=(p, input,)) pp = psutil.Process(p.pid) descendants = list(pp.get_children(recursive=True)) descendants = descendants + [pp] t0 = time.clock() t.start() try: while t.isAlive(): if time.clock() - t0 > timeout: t.join(0) if t.isAlive(): p.terminate() t.join() raise ToolTimeoutError(name) rss_memory = 0 vms_memory = 0 self.executed = True except psutil.NoSuchProcess as e: # Process has finished self.executed = True pass except MemoryError: raise MemoryError(name) except ToolTimeoutError as e: raise e except Exception as e: pass def threadedExecute(self, process, input): res = process.communicate(input) for o in self.output: o.value = res[0] if o.value == '': o.value = res[1] if o.value == '': o.value = 'not None' self.error = self.error + res[1] class Test: def __init__(self, file, settings): # Reads a test from a YAML file self.name = file f = open(file) data = yaml.safe_load(f) self.options = data['options'] self.nodes = [] self.verbose = True if settings['verbose'] else False for n in data['nodes']: # create nodes type = data['nodes'][n] self.nodes.append(Node(n, type, '')) self.tools = [] for t in data['tools']: # create tools if isinstance(data['tools'], dict): self.__addTool(data['tools'][t]) else: self.__addTool(t) for t in self.tools: if any(x for x in t.output if x.type == 'Bool'): t.outfiles = False self.res = data['result'] f.close() self.glbs = {'value': self.value, 'last_word': self.last_word, 'file_get_contents': self.file_get_contents} for n in self.nodes: self.glbs[n.label] = n self.__calcInitials() # calculate the initial nodes def __calcInitials(self): outputs = [] inputs = [] for t in self.tools: outputs = outputs + t.output inputs = inputs + t.input self.initials = OrderedDict.fromkeys([i for i in inputs if i not in outputs]).keys() def __addTool(self, td): input = [i for i in self.nodes if i.label in td['input']] output = [o for o in self.nodes if o.label in td['output']] name = td['name'] if re.search('(W|w)in', self.options['platform']): name = name + '.exe' self.tools.append(Tool(td['name'], input, output, td['args'])) def initialize(self, randgen, max_termlength): # pre: validTermLengths(self, randgen, max_termlength) for i in self.initials: if self.verbose: print 'Generating random %s for %s' % (i.type, i.label) i.value = randgen.generate(i.type, max_termlength) while True: try: f = open(i.label, 'w') break except IOError as e: i.iter = i.iter + 1 i.label = i.base + '_' + str(i.iter) f.write(codecs.escape_decode(i.value)[0]) f.close() def replay(self, inputfiles): if len(self.initials) != len(inputfiles): print 'Invalid number of input files provided: expected %s, got %s' % (len(self.initials), len(inputfiles)) raise Exception for i in range(len(self.initials)): f = open(inputfiles[i]) self.initials[i].label = inputfiles[i] self.initials[i].value = f.read() def validTermLengths(self, randgen, termlength): for i in self.initials: if not randgen.validTermLength(i.type, termlength): return False return True def result(self): # Returns the result of the test after all tools have been executed if self.verbose: print 'Validating result' exec (self.res, self.glbs) return self.glbs['result'] def value(self, node): # Returns the value of the node. Enables 'value(l1)' in the YAML #return node.value try: if node.value or node.type == 'Bool': return node.value else: #f = open(os.path.join(os.getcwd(), node.label + "." + node.ext), 'r') f = open(os.path.join(os.getcwd(), node.label), 'r') res = f.read() f.close() return res except IOError: print 'cannot open stored value file' raise IOError def file_get_contents(self, filename): with open(filename) as f: return f.read() def record(self): for n in self.initials: if n.type != 'Bool': shutil.copyfile(os.path.join(os.getcwd(), n.label), os.path.join(os.getcwd(), 'recorded', n.label + '%0.2f' % time.clock())) def last_word(self, term): if ' ' in term: return term.split(' ')[-1] else: return None def enabled(self): # Returns a list of tools that can be executed and have not been executed before return [t for t in self.tools if not t.executed and t.canExecute()] def reset(self): # Reset the test to the initial values for n in self.nodes: n.value = None try: #os.remove(os.path.join(os.getcwd(), n.label + "." + n.ext)) os.remove(os.path.join(os.getcwd(), n.label)) except OSError as e: pass for t in self.tools: t.executed = False t.error = '' def run(self, reporterrors): # Singlecore run en = self.enabled() while len(en) > 0: t = en[0] t.execute(self.options['path'], 5, 75000, self.verbose) if reporterrors and t.error != '' and 'error' in t.error: raise ToolInputError(t.name, t.error) en = self.enabled() if reporterrors and not all(t.executed for t in self.tools): raise UnusedToolsError([t for t in self.tools if not t.executed]) else: return self.result() def run_multicore(self, max): # Multicore run en = self.enabled() while len(en) > 0: pool = multiprocessing.Pool() jobs = [] for i in range(min(len(en), max)): p = multiprocessing.Process(target=en[i].execute, args=(self.options['path'],)) p.daemon = True jobs.append(p) p.start() for j in jobs: j.join() if j.exitcode != 0: return 'Error' en = self.enabled() if not all(t.executed for t in self.tools): return 'Error' else: return self.result() def write_output(self, dir): if not os.path.exists(dir): os.makedirs(dir) for l in self.initials: fname = l.label + '_' + l.type f = open(os.path.join(dir, fname), 'w') f.write(l.value) f.close() mcrl2-201409.0/tests/randtest.py000770 001750 001750 00000004076 12370120021 016673 0ustar00outisoutis000000 000000 #~ Copyright 2013, 2014 Mark Geelen. #~ Distributed under the Boost Software License, Version 1.0. #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) from __future__ import division import sys, logging, randgen, time, os, yaml from test import Test, ToolInputError, UnusedToolsError, ToolCrashedError import argparse parser = argparse.ArgumentParser(description='Executes random tests') parser.add_argument('T', help='test file (.yml)') parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', help='print verbose output') parser.add_argument('I', type=int, help='the number of tests that is performed') parser.add_argument('N', type=int, help='the length of the randomly generated strings') parser.add_argument('-r' '--report', action='store_true', dest='reporterrors', help='capture error messages in node values') options = parser.parse_args() termlength = options.N testfile = options.T numtests = options.I reporterrors = not options.reporterrors settings = dict() settings['verbose'] = options.verbose t = Test(testfile, settings) grammarfiles = t.options['grammar'] constraintsfiles = t.options['constraints'] constraints = yaml.load(''.join([open(f).read() for f in constraintsfiles])) grammar = ''.join([open(f).read() for f in grammarfiles]) generator = randgen.RandGen(grammar, constraints) if not t.validTermLengths(generator, termlength): print 'invalid term length: ' + str(termlength) else: for i in range(numtests): if settings['verbose']: print 'Running test ' + testfile t.reset() t.initialize(generator, termlength) try: result = t.run(reporterrors) if result == True: print 'Result: success' else: print 'Result: failed' except ToolInputError as e: print 'Result: ' + next(x for x in e.value.split('\n') if 'error' in x) except UnusedToolsError as e: print 'Result: UnusedToolsError' except ToolCrashedError as e: print 'Result: ToolCrashedError'mcrl2-201409.0/tests/randgen.py000770 001750 001750 00000027550 12370120021 016467 0ustar00outisoutis000000 000000 #!/usr/bin/env python #~ Copyright 2013, 2014 Mark Geelen. #~ Distributed under the Boost Software License, Version 1.0. #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) import random import grammar import copy class dotdict(dict): def __getattr__(self, attr): return self.get(attr, None) __setattr__= dict.__setitem__ __delattr__= dict.__delitem__ class RandGen: def __init__(self, bnfgrammar, constraints): self.grammar = grammar.CFG(bnfgrammar) self.ft = dict() self.ft_ = dict() self.attributes = [] self.attrs = dict() self.names = dict() self.constraints = constraints self.secondpass = [] self.meta = dict() for i in range(1, self.grammar.r() + 1): for j in range(1, self.grammar.s(i) + 1): self.meta[(i, j)] = 0 self.glbs = {'choice': random.choice, 'odd': self.odd, 'deepcopy': copy.deepcopy} # predefined functions for use in attr rules def prep(self, n): for m in range(1, n + 1): for i in range(1, self.grammar.r()): if (i, m) not in self.ft: self.ft[(i, m)] = self.f(i, m) def f(self, i, n): # Returns [sum(f'(i, j, k, n)) for 1 <= j <= s_i] # print 'f(%s, %s)' % (i, n) if (i, n) in self.ft: return self.ft[(i, n)] res = [] for j in range(1, self.grammar.s(i) + 1): if (i, j, 1, n) not in self.ft_: self.ft_[(i, j, 1, n)] = self.f_(i, j, 1, n) res.append(sum(self.ft_[(i, j, 1, n)])) return res def f_(self, i, j, k, n): # Pre: 0 < n && 1 <= i <= r && 1 <= j <= s_i && 1 <= k <= t_ij # print 'f(%s, %s, %s, %s)' % (i, j, k, n) if (i, j, k, n) in self.ft_: return self.ft_[(i, j, k, n)] tij = self.grammar.t(i, j) xijk = self.grammar.x(i, j, k) if isinstance(xijk, grammar.AttributeRule): if k == tij: if n == 0: return [1] else: return [0] else: if (i, j, k + 1, n) not in self.ft_: self.ft_[(i, j, k + 1, n)] = self.f_(i, j, k + 1, n) return [sum(self.ft_[(i, j, k + 1, n)])] if n == 0: return [] if xijk in self.grammar.T or isinstance(xijk, grammar.AttributeValue): if k == tij: if n == 1: # hier klopt dus iets niet in de pseudocode return [1] else: return [0] else: if (i, j, k + 1, n - 1) not in self.ft_: self.ft_[(i, j, k + 1, n - 1)] = self.f_(i, j, k + 1, n - 1) return [sum(self.ft_[(i, j, k + 1, n - 1)])] if k == tij: if (xijk, n) not in self.ft: self.ft[(xijk, n)] = self.f(xijk, n) return [sum(self.ft[(xijk, n)])] else: res = [] for l in range(1, n - self.grammar.t(i,j) + k + 1): if (xijk, l) not in self.ft: self.ft[(xijk, l)] = self.f(xijk, l) if (i, j, k + 1, n - l) not in self.ft_: self.ft_[(i, j, k + 1, n - l)] = self.f_(i, j, k + 1, n - l) res.append(sum(self.ft[(xijk, l)]) * sum(self.ft_[(i, j, k + 1, n - l)])) return res def getConstraint(self, i, j, key): # try/catch better? if (i, j) not in self.grammar.labels: return [] if self.grammar.labels[(i, j)] not in self.constraints: return [] if key not in self.constraints[self.grammar.labels[(i, j)]]: return [] return self.constraints[self.grammar.labels[(i, j)]][key] def getAttrRulesForSymbol(self, i, j, k): xijk = self.grammar.x(i, j, k) rules = self.getConstraint(i, j, 'rules') if (i, j, k) not in self.names: return [] res = [] name = self.names[(i, j, k)] for r in rules: if '.' in r and r[:r.index('.')] == name: res.append(r) if ' ' in r and r[:r.index(' ')] == name: res.append(r) return res def getPreRules(self, i, j): return self.getConstraint(i, j, 'pre') def getPostRules(self, i, j): return self.getConstraint(i, j, 'post') def getSubVars(self, i): return self.getConstraint(i, 1, 'attrs') def secondPass(self, term, vars): res = [] for x in term: if isinstance(x, str): res.append(x) else: res = res + self.g_(x[0], x[1], 1, x[2], dict(x[3].items() + vars.items())) return res def Guard(self, c, i, j, subvars): g = self.getConstraint(i, j, 'guard') z = dict(self.glbs.items() + subvars.items()) if g: try: res = eval(g, z, subvars) return res except Exception as e: print 'Unable to evaluate guard "%s" in rule %s' % (g, self.grammar.labels[(i, j)]) raise e return True def g(self, i, n, subvars): c = [] j = 0 alts = [] for x in self.f(i, n): j = j + 1 w = 1 if self.getConstraint(i, j, 'weight'): w = self.getConstraint(i, j, 'weight') if x == 0: c.append(0) if self.Guard(c, i, j, subvars): alts.append(j) else: if self.Guard(c, i, j, subvars): c.append(w) else: c.append(0) # find new m heuristics if not sum(c): r = random.choice(alts) k = 1 step = 1 m = n while True: m = n + k if sum(self.f_(i, r, 1, m)) > 0: break m = max(0, n - k) if sum(self.f_(i, r, 1, m)) > 0: break k = k + step n = m else: r = self.choose(c) + 1 #r = self.choose(self.f(i, n)) self.meta[(i,r)] = self.meta[(i,r)] + 1 occurrences = dict() vars = subvars.copy() tij = self.grammar.t(i, r) for k in range(1, tij + 1): xijk = self.grammar.x(i, r, k) if not isinstance(xijk, str): if isinstance(xijk, int): name = self.grammar.lefthandsides[xijk-1] elif isinstance(xijk, grammar.AttributeValue): name = xijk.name if name in occurrences: occurrences[name] = occurrences[name] + 1 name = name + str(occurrences[name]) else: occurrences[name] = 1 vars[name] = dotdict() if (i, r, k) not in self.names: self.names[(i, r, k)] = name # calculate pre-rules for prerule in self.getPreRules(i, r): try: exec prerule in self.glbs, vars except Exception as e: print 'Unable to evaluate attribute rule "%s" for production rule %s' % (prerule, self.grammar.labels[(i, r)]) raise e sp = self.getConstraint(i, r, 'secondpass') if sp: if sp not in self.secondpass: self.secondpass.append(sp) return [(i, r, n, vars.copy())] res = self.g_(i, r, 1, n, vars) # calculate post rules for postrule in self.getPostRules(i, r): try: exec postrule in self.glbs, vars except Exception as e: print 'Unable to evaluate attribute rule "%s" for production rule %s' % (postrule, self.grammar.labels[(i, r)]) raise e # update inherited attributes for x in subvars: subvars[x] = vars[x] # if certain secondpass constraint is completed, secondpass if (i, r) in self.grammar.labels and self.grammar.labels[(i, r)] in self.secondpass: res = self.secondPass(res, vars) return res def g_(self, i, j, k, n, vars): #print '(%s, %s, %s, %s, %s)' % (i, j, k, n, str(vars.values())) tij = self.grammar.t(i, j) xijk = self.grammar.x(i, j, k) if xijk in self.grammar.T: if k == tij: return [xijk] else: return [xijk] + self.g_(i, j, k + 1, n - 1, vars) toApply = self.getAttrRulesForSymbol(i, j, k) for rule in toApply: try: exec rule in self.glbs, vars except Exception as e: print 'Unable to evaluate attribute rule "%s" in production rule %s, symbol number %s' % (rule, self.grammar.labels[(i, j)], k) raise e if isinstance(xijk, grammar.AttributeValue): # Token / attribute used as value w = '' try: w = [vars[xijk.name]] except Exception as e: print 'Unknown value for token %s in production rule %s, symbol number %s' % (xijk.name, self.grammar.labels[(i, j)], k) raise e if k == tij: return w else: return w + self.g_(i, j, k + 1, n - 1, vars) # xijk is a non-terminal subvars = dotdict() for x in self.getSubVars(xijk): try: subvars[x] = vars[self.names[(i, j, k)]][x] except Exception as e: print 'Unknown value for inherited attribute %s in production rule %s, symbol number %s' % (x, self.grammar.labels[(i, j)], k) raise e if k == tij: res = self.g(xijk, n, subvars) for x in self.getSubVars(xijk): vars[self.names[(i, j, k)]][x] = subvars[x] return res else: c = [] for x in self.f_(i, j, k, n): if x == 0: c.append(0) else: c.append(1) l = self.choose(c) + 1 #l = self.choose(self.f_(i, j, k, n)) + 1 res1 = self.g(xijk, l, subvars) # update var with attributes set in subvars for x in self.getSubVars(xijk): vars[self.names[(i, j, k)]][x] = subvars[x] return res1 + self.g_(i, j, k + 1, n - l, vars) def choose(self, l): totals = [] running_total = 0 for w in l: running_total += w totals.append(running_total) rnd = random.random() * running_total for i, total in enumerate(totals): if rnd < total: return i def validTermLength(self, sort_name, termlength): index = self.grammar.index(sort_name) return sum(self.f(index, termlength)) > 0 def generate(self, sort_name, termlength): if not self.validTermLength(sort_name, termlength): print 'Invalid string length' raise ValueError() index = self.grammar.index(sort_name) attrs = {'choice': random.choice, 'odd': self.odd} result = self.g(index, termlength, dict()) self.length = len(result) return ' '.join(result) def newAttrs(self, i, j, k, attrs): xijk = self.grammar.x(i, j, k) baseAttrs = ['__builtins__', 'choice', 'odd'] res = {x: attrs[x] for x in attrs if x in baseAttrs} for x in range(len(self.grammar.args[(i, j, k)])): res[self.grammar.lhs_args[xijk - 1][x]] = attrs[self.grammar.args[(i, j, k)][x]] return res def odd(self, a, b, c): return (a and b and c) or (a ^ b ^ c) mcrl2-201409.0/tests/tickets/1127/1.mcrl2000770 001750 001750 00000000070 12370120021 017624 0ustar00outisoutis000000 000000 map f: Bool # Bool # Bool -> Bool -> Bool; init delta; mcrl2-201409.0/tests/tickets/1241/1.mcrl2000770 001750 001750 00000000062 12370120021 017622 0ustar00outisoutis000000 000000 act a; init allow({a}, hide({a}, allow({a}, a)));mcrl2-201409.0/tests/tickets/283/1.mcrl2000770 001750 001750 00000000211 12370120021 017543 0ustar00outisoutis000000 000000 proc A = tau.B; B = tau.C + tau.D; C = tau.E; D = tau.F; E = tau.F + tau.G; F = tau.A; G = delta; init A; mcrl2-201409.0/tests/tickets/1249/1.mcrl2000770 001750 001750 00000000105 12370120021 017630 0ustar00outisoutis000000 000000 act a, V, W; proc P = a | V . P + a. P; init allow({a | W, a}, P); mcrl2-201409.0/tests/tickets/325/bug.mcrl2000770 001750 001750 00000000424 12370120021 020163 0ustar00outisoutis000000 000000 sort Z = struct B; sort I = List( Z ); act S, S': I; proc Y = tau . Y; proc X(b: Bool)= S( [ B ] ). X( true ) + tau ; init comm( { S | S -> S' }, Y || X(false) ) ; mcrl2-201409.0/tests/tickets/352/1.mcrl2000770 001750 001750 00000000071 12370120021 017544 0ustar00outisoutis000000 000000 act a, b, c; init comm({a|b -> tau}, allow({c}, c ) ); mcrl2-201409.0/tests/tickets/1248/1.mcf000770 001750 001750 00000000101 12370120021 017351 0ustar00outisoutis000000 000000 (nu X(b: Bool = true) . X(b)) && (nu X(b: Bool = false) . X(!b)) mcrl2-201409.0/tests/tickets/1122/1.mcrl2000770 001750 001750 00000000234 12370120021 017621 0ustar00outisoutis000000 000000 act a: Bool; proc X(v: Bool, s:Bool) = sum v:Bool. s -> a(v) . X(v = v, s = false) + (!s && v) -> a(v). X(s = true); glob b:Bool; init X(b, true); mcrl2-201409.0/tests/tickets/1090/spec.mcrl2000770 001750 001750 00000000114 12370120021 020414 0ustar00outisoutis000000 000000 sort D = struct d1 | d2; act a:D; proc X(f:D) = a(f).X(f); init X(d1); mcrl2-201409.0/tests/tickets/1090/form.mcf000770 001750 001750 00000000032 12370120021 020152 0ustar00outisoutis000000 000000 [!exists d:D. a(d)]false mcrl2-201409.0/tests/tickets/397/1.mcrl2000770 001750 001750 00000000071 12370120021 017555 0ustar00outisoutis000000 000000 act a; proc P = ( tau || tau ). P; init allow( {a} , P); mcrl2-201409.0/tests/tickets/1144/test2.txt000770 001750 001750 00000000137 12370120021 020330 0ustar00outisoutis000000 000000 act a: Bool; proc P(b: Bool) = a(b) . P(b = !b) + delta; init P(true); mcrl2-201409.0/tests/tickets/1144/test1.txt000770 001750 001750 00000000376 12370120021 020334 0ustar00outisoutis000000 000000 map invert: List(Bool) -> List(Bool); var b: Bool; l: List(Bool); eqn invert([]) = []; invert(b |> l) = !b |> invert(l); act a: Bool; proc P(b: List(Bool)) = a(b . 0) . P(b = invert(b)) + delta; init P([true]); mcrl2-201409.0/tests/tickets/1093/1.mcrl2000770 001750 001750 00000002522 12370120021 017632 0ustar00outisoutis000000 000000 sort Method = struct method1 | method2; act method_var_begin,method_var_end:Nat#Method; act method_call_begin,method_call_end:Nat#Method; act method_begin,method_end:Nat#Method; proc method1(id:Nat) = method_var_begin(id,method1). method_call_begin(id,method2). method_call_end(id,method2). method_var_end(id,method1) ; proc method2(id:Nat) = method_var_begin(id,method2). method_var_end(id,method2); proc P(id:Nat) = method_call_begin(id,method1). method_call_end(id,method1); proc ProcP(id:Nat) = P(id) || method1(id) || method2(id); init % allow({method_begin,method_end,method_begin|method_end,method_begin|method_begin,method_end|method_end % ,method_begin|method_begin|method_begin,method_begin|method_end|method_begin, method_end|method_end|method_begin, % method_end|method_end|method_end % % ,method_begin|method_begin|method_begin|method_begin,method_begin|method_begin|method_begin|method_end, % method_begin|method_begin|method_end|method_end, % method_begin|method_end|method_end|method_end, % method_end|method_end|method_end|method_end block({method_var_begin,method_var_end,method_call_begin,method_call_end % <-- cannot linearize }, comm({ method_call_begin|method_var_begin-> method_begin, method_call_end|method_var_end-> method_end }, ProcP(1) || ProcP(2) || ProcP(3) )); mcrl2-201409.0/tests/tickets/1247/1.mcrl2000770 001750 001750 00000000071 12370120021 017630 0ustar00outisoutis000000 000000 act a, b, c; init comm({a|b -> tau}, allow({c}, c ) ); mcrl2-201409.0/tests/tickets/1143/2.txt000770 001750 001750 00000006214 12370120021 017431 0ustar00outisoutis000000 000000 sort Policy = struct FIFO | LIFO; Floor = Pos; Requests = List(Pos); map policy: Policy; storeys: Pos; addRequest,addRequestFIFO,addRequestLIFO,remove: Requests # Pos -> Requests; newPosition: Pos # Pos -> Pos; var r: Requests; f,g,f1,f2: Pos; eqn policy = LIFO; storeys = 4; policy == FIFO -> addRequest(r, f) = addRequestFIFO(r, f); policy == LIFO -> addRequest(r, f) = addRequestLIFO(r, f); addRequestFIFO([], f) = [f]; addRequestFIFO(g |> r, f) = g |> r; addRequestFIFO(g |> r, f) = g |> addRequest(r, f); addRequestLIFO(r, f) = f |> remove(r, f); remove([], f) = []; f == g -> remove(g |> r, f) = remove(r, f); f != g -> remove(g |> r, f) = g |> remove(r, f); f1 < f2 -> newPosition(f1, f2) = f1 + 1; f1 > f2 -> newPosition(f1, f2) = Int2Pos(f1 - 1); f1 == f2 -> newPosition(f1, f2) = f1; pbes nu X(p: Pos, d: Bool, r: List(Pos)) = Y(p, d, r); mu Y(p: Pos, d: Bool, r: List(Pos)) = Z(p, d, r); nu Z(p: Pos, d: Bool, r: List(Pos)) = (forall b2: Bool, f3,newp2: Pos, r2: List(Pos). val(!false) && val(!true) || val(!(d && !(newp2 == newPosition(p, head(r2)) && !(r2 == []) && !d) && f3 <= 4 && r2 == if(b2, f3 |> remove(r, f3), r) && newp2 <= 4)) || X(p, false, r)) && (forall b3: Bool, f4,newp3: Pos, r3: List(Pos). val(!true) && val(!false) || val(!(newp3 == newPosition(p, head(r3)) && !(r3 == []) && !d && f4 <= 4 && r3 == if(b3, f4 |> remove(r, f4), r) && newp3 <= 4)) || X(newp3, newp3 == head(r3), if(newp3 == head(r3), tail(r3), r3))) && (forall f5: Pos. val(!false) && val(!false) || val(!(f5 <= 4 && f5 in r)) || X(p, d, r)) && (val(!false) && val(!false) || X(p, d, r)) && (false || false || false || val(p == storeys) || (forall b6: Bool, f9,newp6: Pos, r6: List(Pos). val(!false) && val(!true) || val(!(d && !(newp6 == newPosition(p, head(r6)) && !(r6 == []) && !d) && f9 <= 4 && r6 == if(b6, f9 |> remove(r, f9), r) && newp6 <= 4)) || Z(p, false, r)) && (forall b7: Bool, f10,newp7: Pos, r7: List(Pos). val(!true) && val(!false) || val(!(newp7 == newPosition(p, head(r7)) && !(r7 == []) && !d && f10 <= 4 && r7 == if(b7, f10 |> remove(r, f10), r) && newp7 <= 4)) || Z(newp7, newp7 == head(r7), if(newp7 == head(r7), tail(r7), r7))) && (forall f11: Pos. val(!false) && val(!false) || val(!(f11 <= 4 && f11 in r)) || Z(p, d, r)) && (val(!false) && val(!false) || Z(p, d, r)) && (false || false || false || false || (forall b10: Bool, f15,newp10: Pos, r10: List(Pos). val(!false) && val(!true) || val(!(d && !(newp10 == newPosition(p, head(r10)) && !(r10 == []) && !d) && f15 <= 4 && r10 == if(b10, f15 |> remove(r, f15), r) && newp10 <= 4)) || Y(p, false, r)) && (forall b11: Bool, f16,newp11: Pos, r11: List(Pos). val(!true) && val(!false) || val(!(newp11 == newPosition(p, head(r11)) && !(r11 == []) && !d && f16 <= 4 && r11 == if(b11, f16 |> remove(r, f16), r) && newp11 <= 4)) || Y(newp11, newp11 == head(r11), if(newp11 == head(r11), tail(r11), r11))) && (forall f17: Pos. val(!false) && val(!false) || val(!(f17 <= 4 && f17 in r)) || Y(p, d, r)) && (val(!false) && val(!false) || Y(p, d, r)))); init X(1, true, []); mcrl2-201409.0/tests/tickets/1143/bug.txt000770 001750 001750 00000012565 12370120021 020053 0ustar00outisoutis000000 000000 sort Policy = struct FIFO | LIFO; Floor = Pos; Requests = List(Pos); map policy: Policy; storeys: Pos; addRequest,addRequestFIFO,addRequestLIFO,remove: Requests # Pos -> Requests; newPosition: Pos # Pos -> Pos; var r: Requests; f,g,f1,f2: Pos; eqn policy = LIFO; storeys = 4; policy == FIFO -> addRequest(r, f) = addRequestFIFO(r, f); policy == LIFO -> addRequest(r, f) = addRequestLIFO(r, f); addRequestFIFO([], f) = [f]; addRequestFIFO(g |> r, f) = g |> r; addRequestFIFO(g |> r, f) = g |> addRequest(r, f); addRequestLIFO(r, f) = f |> remove(r, f); remove([], f) = []; f == g -> remove(g |> r, f) = remove(r, f); f != g -> remove(g |> r, f) = g |> remove(r, f); f1 < f2 -> newPosition(f1, f2) = f1 + 1; f1 > f2 -> newPosition(f1, f2) = Int2Pos(f1 - 1); f1 == f2 -> newPosition(f1, f2) = f1; pbes nu X(position_Elevator: Pos, dooropen_Elevator: Bool, requests_Elevator: List(Pos)) = Y(position_Elevator, dooropen_Elevator, requests_Elevator); mu Y(position_Elevator: Pos, dooropen_Elevator: Bool, requests_Elevator: List(Pos)) = Z(position_Elevator, dooropen_Elevator, requests_Elevator); nu Z(position_Elevator: Pos, dooropen_Elevator: Bool, requests_Elevator: List(Pos)) = (forall b_Elevator2: Bool, f_Elevator3,newposition_Elevator2: Pos, r_Elevator2: List(Pos). val(!false) && val(!true) || val(!(dooropen_Elevator && !(newposition_Elevator2 == newPosition(position_Elevator, head(r_Elevator2)) && !(r_Elevator2 == []) && !dooropen_Elevator) && f_Elevator3 <= 4 && r_Elevator2 == if(b_Elevator2, f_Elevator3 |> remove(requests_Elevator, f_Elevator3), requests_Elevator) && newposition_Elevator2 <= 4)) || X(position_Elevator, false, requests_Elevator)) && (forall b_Elevator3: Bool, f_Elevator4,newposition_Elevator3: Pos, r_Elevator3: List(Pos). val(!true) && val(!false) || val(!(newposition_Elevator3 == newPosition(position_Elevator, head(r_Elevator3)) && !(r_Elevator3 == []) && !dooropen_Elevator && f_Elevator4 <= 4 && r_Elevator3 == if(b_Elevator3, f_Elevator4 |> remove(requests_Elevator, f_Elevator4), requests_Elevator) && newposition_Elevator3 <= 4)) || X(newposition_Elevator3, newposition_Elevator3 == head(r_Elevator3), if(newposition_Elevator3 == head(r_Elevator3), tail(r_Elevator3), r_Elevator3))) && (forall f_Elevator5: Pos. val(!false) && val(!false) || val(!(f_Elevator5 <= 4 && f_Elevator5 in requests_Elevator)) || X(position_Elevator, dooropen_Elevator, requests_Elevator)) && (val(!false) && val(!false) || X(position_Elevator, dooropen_Elevator, requests_Elevator)) && (false || false || false || val(position_Elevator == storeys) || (forall b_Elevator6: Bool, f_Elevator9,newposition_Elevator6: Pos, r_Elevator6: List(Pos). val(!false) && val(!true) || val(!(dooropen_Elevator && !(newposition_Elevator6 == newPosition(position_Elevator, head(r_Elevator6)) && !(r_Elevator6 == []) && !dooropen_Elevator) && f_Elevator9 <= 4 && r_Elevator6 == if(b_Elevator6, f_Elevator9 |> remove(requests_Elevator, f_Elevator9), requests_Elevator) && newposition_Elevator6 <= 4)) || Z(position_Elevator, false, requests_Elevator)) && (forall b_Elevator7: Bool, f_Elevator10,newposition_Elevator7: Pos, r_Elevator7: List(Pos). val(!true) && val(!false) || val(!(newposition_Elevator7 == newPosition(position_Elevator, head(r_Elevator7)) && !(r_Elevator7 == []) && !dooropen_Elevator && f_Elevator10 <= 4 && r_Elevator7 == if(b_Elevator7, f_Elevator10 |> remove(requests_Elevator, f_Elevator10), requests_Elevator) && newposition_Elevator7 <= 4)) || Z(newposition_Elevator7, newposition_Elevator7 == head(r_Elevator7), if(newposition_Elevator7 == head(r_Elevator7), tail(r_Elevator7), r_Elevator7))) && (forall f_Elevator11: Pos. val(!false) && val(!false) || val(!(f_Elevator11 <= 4 && f_Elevator11 in requests_Elevator)) || Z(position_Elevator, dooropen_Elevator, requests_Elevator)) && (val(!false) && val(!false) || Z(position_Elevator, dooropen_Elevator, requests_Elevator)) && (false || false || false || false || (forall b_Elevator10: Bool, f_Elevator15,newposition_Elevator10: Pos, r_Elevator10: List(Pos). val(!false) && val(!true) || val(!(dooropen_Elevator && !(newposition_Elevator10 == newPosition(position_Elevator, head(r_Elevator10)) && !(r_Elevator10 == []) && !dooropen_Elevator) && f_Elevator15 <= 4 && r_Elevator10 == if(b_Elevator10, f_Elevator15 |> remove(requests_Elevator, f_Elevator15), requests_Elevator) && newposition_Elevator10 <= 4)) || Y(position_Elevator, false, requests_Elevator)) && (forall b_Elevator11: Bool, f_Elevator16,newposition_Elevator11: Pos, r_Elevator11: List(Pos). val(!true) && val(!false) || val(!(newposition_Elevator11 == newPosition(position_Elevator, head(r_Elevator11)) && !(r_Elevator11 == []) && !dooropen_Elevator && f_Elevator16 <= 4 && r_Elevator11 == if(b_Elevator11, f_Elevator16 |> remove(requests_Elevator, f_Elevator16), requests_Elevator) && newposition_Elevator11 <= 4)) || Y(newposition_Elevator11, newposition_Elevator11 == head(r_Elevator11), if(newposition_Elevator11 == head(r_Elevator11), tail(r_Elevator11), r_Elevator11))) && (forall f_Elevator17: Pos. val(!false) && val(!false) || val(!(f_Elevator17 <= 4 && f_Elevator17 in requests_Elevator)) || Y(position_Elevator, dooropen_Elevator, requests_Elevator)) && (val(!false) && val(!false) || Y(position_Elevator, dooropen_Elevator, requests_Elevator)))); init X(1, true, []); mcrl2-201409.0/tests/tickets/1143/3.txt000770 001750 001750 00000002122 12370120021 017424 0ustar00outisoutis000000 000000 sort Policy = struct FIFO | LIFO; Floor = Pos; Requests = List(Pos); map policy: Policy; storeys: Pos; addRequest,addRequestFIFO,addRequestLIFO,remove: Requests # Pos -> Requests; newPosition: Pos # Pos -> Pos; var r: Requests; f,g,f1,f2: Pos; eqn policy = LIFO; storeys = 4; policy == FIFO -> addRequest(r, f) = addRequestFIFO(r, f); policy == LIFO -> addRequest(r, f) = addRequestLIFO(r, f); addRequestFIFO([], f) = [f]; addRequestFIFO(g |> r, f) = g |> r; addRequestFIFO(g |> r, f) = g |> addRequest(r, f); addRequestLIFO(r, f) = f |> remove(r, f); remove([], f) = []; f == g -> remove(g |> r, f) = remove(r, f); f != g -> remove(g |> r, f) = g |> remove(r, f); f1 < f2 -> newPosition(f1, f2) = f1 + 1; f1 > f2 -> newPosition(f1, f2) = Int2Pos(f1 - 1); f1 == f2 -> newPosition(f1, f2) = f1; pbes nu X(p: Pos, d: Bool, r: List(Pos)) = forall b3: Bool, f4, newp3: Pos, r3: List(Pos). val(!(r3 == if(b3, f4 |> remove(r, f4), r))) ; init X(1, true, []); mcrl2-201409.0/tests/tickets/1143/1.txt000770 001750 001750 00000000273 12370120021 017427 0ustar00outisoutis000000 000000 pbes nu X = forall p: Bool, q: Bool. val(!( p == q && q && p == true )) ; init X; mcrl2-201409.0/tests/tickets/1143/4.txt000770 001750 001750 00000003040 12370120021 017425 0ustar00outisoutis000000 000000 sort Policy = struct FIFO | LIFO; Floor = Pos; Requests = List(Pos); map policy: Policy; storeys: Pos; addRequest,addRequestFIFO,addRequestLIFO,remove: Requests # Pos -> Requests; newPosition: Pos # Pos -> Pos; var r: Requests; f,g,f1,f2: Pos; eqn policy = LIFO; storeys = 4; policy == FIFO -> addRequest(r, f) = addRequestFIFO(r, f); policy == LIFO -> addRequest(r, f) = addRequestLIFO(r, f); addRequestFIFO([], f) = [f]; addRequestFIFO(g |> r, f) = g |> r; addRequestFIFO(g |> r, f) = g |> addRequest(r, f); addRequestLIFO(r, f) = f |> remove(r, f); remove([], f) = []; f == g -> remove(g |> r, f) = remove(r, f); f != g -> remove(g |> r, f) = g |> remove(r, f); f1 < f2 -> newPosition(f1, f2) = f1 + 1; f1 > f2 -> newPosition(f1, f2) = Int2Pos(f1 - 1); f1 == f2 -> newPosition(f1, f2) = f1; pbes nu X(p: Pos, d: Bool, r: List(Pos)) = Y(p, d, r); mu Y(p: Pos, d: Bool, r: List(Pos)) = Z(p, d, r); nu Z(p: Pos, d: Bool, r: List(Pos)) = (forall b3: Bool, f4,newp3: Pos, r3: List(Pos). val(!true) && val(!false) || val(!(newp3 == newPosition(p, head(r3)) && !(r3 == []) && !d && f4 <= 4 && r3 == if(b3, f4 |> remove(r, f4), r) && newp3 <= 4)) || X(newp3, newp3 == head(r3), if(newp3 == head(r3), tail(r3), r3))) && % (forall f5: Pos. val(!false) && val(!false) || val(!(f5 <= 4 && f5 in r)) || X(p, d, r)) && (val(!false) && val(!false) || X(p, d, r)) ; init X(1, true, []); mcrl2-201409.0/tests/grammar.py000770 001750 001750 00000014775 12370120021 016504 0ustar00outisoutis000000 000000 #!/usr/bin/env python #~ Copyright 2013, 2014 Mark Geelen. #~ Distributed under the Boost Software License, Version 1.0. #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) import mcrl2_parser2 class AttributeRule: def __init__(self, rule): self.rule = rule class AttributeValue: def __init__(self, name): self.name = name class CFG: def __init__(self, grammar): self.T = [] self.tokens = [] self.G = [] # ebnf_parser = mcrl2_parser.EBNFParser(mcrl2_parser.Mcrl2Actions()) ebnf_parser = mcrl2_parser2.EBNFParser(mcrl2_parser2.Mcrl2Actions()) self.rules = ebnf_parser(grammar) self.labels = dict() # self.attrs = dict() # self.guards = dict() # self.secondpass = [] self.lefthandsides = [] # self.args = dict() # self.lhs_args = [] for lhs in self.rules: self.lefthandsides.append(lhs.name()) # name = lhs.name() # self.lhs_args.append(lhs.args) # if name[0] == '!': # self.secondpass.append(name[1:]) # self.lefthandsides.append(name[1:]) # else: # self.lefthandsides.append(name) self.G = self.TransformRules() # self.RemoveEmptyProductions() # self.CopyGrammarWithoutAttrs() def addRepetition(self, a): lhs = len(self.rules) + 1 lf = mcrl2_parser.Argument(lhs, '', a.args) rec = mcrl2_parser.Function('', [mcrl2_parser.Argument(a.expressions, '', a.args), lf], None) eps = mcrl2_parser.Function('', [mcrl2_parser.Argument('', '', a.args)], None) af = mcrl2_parser.Function('', [mcrl2_parser.Argument(a.expressions, '', a.args)], None) rhs = [] if a.repetitions == '+': rhs = [af, rec] if a.repetitions == '*': rhs = [eps, rec] if a.repetitions == '?': rhs = [eps, af] self.rules.append(mcrl2_parser.Rule(lhs, rhs, [])) # todo return lhs def addRule(self, arg): lhs = len(self.rules) + 1 rhs = arg.expressions self.rules.append(mcrl2_parser.Rule(lhs, rhs, [])) # todo return lhs def getFunctions(self, i, fs): result = [] j = 0 for f in fs: val = self.getFunction(i, j, f) if len(val) > 0 and isinstance(val[0], list): for v in val: result.append(v) else: result.append(val) j = j + 1 return result def getFunction(self, i, j, f): dim = 1 interm = [] attr = '' k = 0 for a in f.arguments: fs = [] #self.args[(i+1, j+1, k+1)] = a.args if a.lbl != None: self.labels[(i+1, j+1)] = a.lbl continue if a.repetitions != '': fs = self.addRepetition(a) elif isinstance(a.expressions, list): fs = self.addRule(a) else: fs = a.expressions if fs in self.lefthandsides: fs = self.lefthandsides.index(fs) + 1 elif isinstance(fs, str) and fs != '': if fs[0] == '\'': fs = fs[1:-1] # remove quotes elif fs[0] == '"': fs = fs[1:-1] # remove quotes self.tokens.append(fs) elif fs[0] == '{': if (fs[1] == '?'): self.guards[(i+1,j+1)] = fs[2:-1] continue if (fs[1] == '!'): self.secondpass.append((i+1,j+1)) continue ar = AttributeRule(fs[1:-1]) interm.append(ar) k = k + 1 continue elif fs not in self.lefthandsides: # this is an attribute used as non-terminal ar = AttributeValue(fs) interm.append(ar) k = k + 1 continue self.T.append(fs) elif fs == '': self.T.append('') interm.append(fs) k = k + 1 return interm def TransformRules(self): result = [] i = 0 for r in self.rules: result.append(self.getFunctions(i, r.rhs)) i = i + 1 return result def RemoveEmptyProductions(self): while True: Ns = [x for x in range(len(self.G)) if [''] in self.G[x]] if len(Ns) == 0: break A = Ns[0] del self.G[A][self.G[A].index([''])] for p in range(len(self.G)): c = 0 while c < len(self.G[p]): for a in range(len(self.G[p][c])): if self.G[p][c][a] == (A + 1): rhs = self.G[p][c][:a] + self.G[p][c][(a+1):] if len(self.G[p][c]) == 1: rhs = [''] if rhs not in self.G[p]: self.G[p].append(rhs) c = c + 1 def CopyGrammarWithoutAttrs(self): self.G_ = [] for i in range(len(self.G)): self.G_.append([]) for j in range(len(self.G[i])): self.G_[i].append([k for k in self.G[i][j] if not isinstance(k, AttributeRule)]) # ------------------------------------------- # Getters for the random generation algorithm # ------------------------------------------- def t_(self, i, j): return len([x for x in self.G_[i - 1][j - 1] if not isinstance(x, AttributeRule)]) def x(self, i, j, k): return self.G[i - 1][j - 1][k - 1] def t(self, i, j): return len(self.G[i - 1][j - 1]) def s(self, i): return len(self.G[i - 1]) def r(self): return len(self.G) def index(self, sort_string): return self.lefthandsides.index(sort_string) + 1 def parameters(self, i): # return set of names of variables in the parameterlist of non-terminal i # as keys for the attribute dictionary return [] mcrl2-201409.0/tests/constraints/pbes-attrsdir2.yml000770 001750 001750 00000027123 12370120021 022432 0ustar00outisoutis000000 000000 # V prop variable list with arguments # W list of global datavariables that can be used pbes: order: left rules: - PbesEqnSpec.V = [] - PbesEqnSpec.W = [] - PbesInit.V = PbesEqnSpec.V - PbesInit.W = PbesEqnSpec.W pbeseqnspec: order: left attrs: [V, W] rules: - PbesEqnDecls.V = V - PbesEqnDecls.W = W - PbesEqnDecls.Iterations = 5 pbeseq: order: left attrs: [V, W, Iterations] guard: Iterations == 1 rules: - PbesEqnDecl.V = V - PbesEqnDecl.W = W pbeseqs: attrs: [V, W, Iterations] guard: Iterations > 1 rules: - PbesEqnDecl.V = V - PbesEqnDecl.W = W - PbesEqnDecls.V = PbesEqnDecl.V - PbesEqnDecls.W = PbesEqnDecl.W - PbesEqnDecls.Iterations = Iterations - 1 # todo: pass W down to UniquePropVarDecl to avoid duplicate datavariable names being declared pbeseqdecl: order: left attrs: [V, W] rules: - UniquePropVarDecl.V = V - UniquePropVarDecl.U = [] - UniquePropVarDecl.Prefix = 'u' - Guard.W = UniquePropVarDecl.U - PbesExpr.V = UniquePropVarDecl.V - PbesExpr.W = UniquePropVarDecl.U + W - PbesExpr.M = True - PbesExpr.P = 0 vardecl: order: left attrs: [V, U, Prefix] pre: - K = 'X' + str(len(V)+1) - V.append((K, [])) rules: - Id = K vardecllist: order: left attrs: [V, U, Prefix] pre: - K = 'X' + str(len(V)+1) rules: - Id = K - VarsDeclList.U = U - VarsDeclList.Prefix = Prefix post: - U = VarsDeclList.U - V.append((K, U)) vdcl: order: left attrs: [U, Prefix] rules: - VarsDecls.U = U - VarsDecls.L = len(U) - VarsDecls.Prefix = Prefix post: - U = VarsDecls.U vsdecl: order: left attrs: [U, L, Prefix] rules: - VarDecl.U = U - VarDecl.L = L - VarDecl.Prefix = Prefix post: - U = VarDecl.U - L = L + len(VarDecl.U) vsdecls: order: left attrs: [U, L, Prefix] rules: - VarDecl.U = U - VarDecl.L = L - VarDecl.Prefix = Prefix - VarsDecls.U = VarDecl.U - VarsDecls.L = L + len(VarDecl.U) - VarsDecls.Prefix = Prefix post: - U = VarsDecls.U - L = L + len(VarsDecls.U) vdecl: attrs: [U, L, Prefix] rules: - IdList.U = [] - IdList.L = L - IdList.Prefix = Prefix - SortExpr.T = None post: - | U = U + [{'name': u, 'type': SortExpr.T} for u in IdList.U] - L = L + len(U) init: attrs: [V, W] rules: - PropVarInst.V = V - PropVarInst.W = W - PropVarInst.M = True propvarinst: attrs: [V, W, M] rules: - VarInst.K = choice(V) - VarInst.W = W - VarInst.M = M varinst: attrs: [K, W, M] guard: not K[1] rules: - Id = '!' + K[0] if not M else K[0] varinstlist: attrs: [K, W, M] guard: K[1] rules: - Id = '!' + K[0] if not M else K[0] - DataExprListInst.W = W - DataExprListInst.A = K[1] dalinst: attrs: [W, A] guard: | len(A) == 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = W - DataExpr.P = 0 post: - A = [] dallinst: attrs: [W, A] guard: | len(A) > 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = W - DataExpr.P = 0 - DataExprListInst.W = W - | DataExprListInst.A = A[1:] dvale: order: left attrs: W rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 0 se: attrs: T rules: - SimpleSortExpr.T = T post: - T = SimpleSortExpr.T # SortExpr se_bool: attrs: T post: - T = 'bool' se_pos: attrs: T post: - T = 'pos' se_nat: attrs: T post: - T = 'nat' se_int: attrs: T post: - T = 'int' se_real: attrs: T post: - T = 'real' # DataExpr da_forall: attrs: [W, T, P] guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = W - VarsDeclList.Prefix = 'd' - DataExpr.W = VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_exists: attrs: [W, T, P] guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = W - VarsDeclList.Prefix = 'd' - DataExpr.W = VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_impl: attrs: [W, T, P] guard: | P <= 2 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 3 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 2 post: - T = ['bool'] da_conj: attrs: [W, T, P] guard: | P <= 4 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 4 post: - T = ['bool'] da_disj: attrs: [W, T, P] guard: | P <= 3 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 4 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 3 post: - T = ['bool'] da_eq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_neq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_lt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - "DataExpr.T = ['int', 'real', 'pos', 'nat']" - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_gt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_leq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_geq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_plus: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr2.P = 11 post: - T = ['pos'] if 'pos' in T else DataExpr2.T da_min: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 11 post: - T = DataExpr2.T da_times: attrs: [W, T, P] guard: | P <= 12 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 13 post: - T = DataExpr2.T da_divides: attrs: [W, T, P] guard: | P <= 11 and 'real' in T rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr2.P = 13 post: - T = ['real'] da_numb: attrs: [W, T, P] guard: | P <= 14 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - Number = str(choice(range(1,100))) post: - T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] da_true: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_false: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_neg: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 14 post: - T = ['bool'] da_inv: attrs: [W, T, P] guard: | P <= 14 and any(x for x in T if x in ['int', 'real']) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 14 post: - T = DataExpr.T da_brk: attrs: [W, T, P] guard: | P <= 14 rules: - DataExpr.W = W - DataExpr.T = T - DataExpr.P = 0 post: - T = DataExpr.T da_id: attrs: [W, T, P] guard: | P <= 14 and any(x for x in W if x['type'] in T) pre: - | V = choice([x for x in W if x['type'] in T]) rules: - Id = V['name'] post: - T = [V['type']] # PbesExpr pe_impl: attrs: [V, W, M, P] guard: P <= 1 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = not M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 1 pe_disj: attrs: [V, W, M, P] guard: P <= 2 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 3 pe_conj: attrs: [V, W, M, P] guard: P <= 2 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 3 pe_forall: attrs: [V, W, M, P] weight: 1 guard: P == 0 rules: - VarsDeclList.U = [] - VarsDeclList.Prefix = 'd' - Guard.W = W + VarsDeclList.U - PbesExpr.V = V - PbesExpr.W = VarsDeclList.U - PbesExpr.M = M - PbesExpr.P = 0 pe_exists: attrs: [V, W, M, P] weight: 1 guard: P == 0 rules: - VarsDeclList.U = [] - VarsDeclList.Prefix = 'd' - Guard.W = VarsDeclList.U - PbesExpr.V = V - PbesExpr.W = W + VarsDeclList.U - PbesExpr.M = M - PbesExpr.P = 0 pe_dv: attrs: [V, W, M, P] guard: P <= 3 rules: - DataValExpr.W = W pe_true: attrs: [V, W, M, P] guard: P <= 3 pe_false: attrs: [V, W, M, P] guard: P <= 3 pe_neg: attrs: [V, W, M, P] guard: P <= 3 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = not M - PbesExpr.P = 3 pe_brk: attrs: [V, W, M, P] guard: P <= 3 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 0 pe_pv: secondpass: pbes attrs: [V, W, M, P] guard: P <= 3 rules: - PropVarInst.V = V - PropVarInst.W = W - PropVarInst.M = M # IdList idlid: order: left attrs: [U, L, Prefix] pre: # - K = Prefix + str(L + 1) - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K idlids: order: left attrs: [U, L, Prefix] pre: # - K = Prefix + str(L + 1) - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K - IdList.U = U - IdList.L = L + 1 - IdList.Prefix = Prefix post: - U = IdList.U # Guard no_guard: attrs: [W] guard: not any(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) guard: attrs: [W] guard: any(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) pre: - K = next(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) rules: - G = ' '.join([K['name'], '<', str(choice(range(1,100)))]) - Guard.W = [x for x in W if x['name'] != K['name']] mcrl2-201409.0/tests/constraints/mcrl2-attrs.yml000770 001750 001750 00000017217 12370120021 021742 0ustar00outisoutis000000 000000 mcrl2: attrs: [] pre: - | E = {'proc': [], 'var': [], 'act': [], 'sort': []} rules: - SortSpec.E = E - ActSpec.E = SortSpec.E - ProcSpec.E = ActSpec.E - Init.E = ProcSpec.E init: attrs: [E] rules: - ProcExpr.E = E - ProcExpr.P = 1 - ProcExpr.G = True - ProcExpr.pcrl = '?' procspec: attrs: [E] rules: - ProcDecl.E = deepcopy(E) post: - E['proc'] = ProcDecl.E['proc'] procspecs: attrs: [E] rules: - ProcDecl.E = deepcopy(E) - ProcSpec.E = deepcopy(E) - ProcSpec.E['proc'] = ProcDecl.E['proc'] post: - E['proc'] = ProcSpec.E['proc'] procdecl: attrs: [E] pre: - K = 'P' + str(len(E['proc']) + 1) rules: - Id = K - ProcExpr.E = E - ProcExpr.E['proc'] = E['proc'] + [(K, [])] - ProcExpr.P = 1 - ProcExpr.G = False - ProcExpr.pcrl = 'pcrl' # post: # - E['proc'] = E['proc'] + [(K, [])] procdecllist: attrs: [E] pre: - K = 'P' + str(len(E['proc']) + 1) rules: - Id = K - VarsDeclList.E = E - VarsDeclList.L = len(E['var']) - VarsDeclList.U = [] - VarsDeclList.Prefix = 'v' - ProcExpr.E = E - ProcExpr.E['var'] = E['var'] + VarsDeclList.U - ProcExpr.E['proc'] = E['proc'] + [(K, VarsDeclList.U)] - ProcExpr.P = 1 - ProcExpr.G = False - ProcExpr.pcrl = 'pcrl' # post: # - E['proc'] = E['proc'] + [(K, VarsDeclList.U)] vsdecl: attrs: [E, U, L, Prefix] rules: - VarDecl.E = E - VarDecl.U = U - VarDecl.L = L + 1 - VarDecl.Prefix = Prefix post: - U = VarDecl.U vsdecls: attrs: [E, U, L, Prefix] rules: - VarDecl.E = E - VarDecl.U = [] - VarDecl.L = L - VarDecl.Prefix = Prefix - VarsDeclList.E = E - VarsDeclList.U = [] - VarsDeclList.L = VarDecl.L - VarsDeclList.Prefix = Prefix post: - | U = VarDecl.U + VarsDeclList.U vdecl: attrs: [E, U, L, Prefix] rules: - IdList.U = [] - IdList.L = L - IdList.Prefix = Prefix - SortExpr.T = None - SortExpr.Sorts = E['sort'] post: - | U = [{'name': u, 'type': SortExpr.T} for u in IdList.U] - L = L + len(IdList.U) pcinst: attrs: [K, E, A] guard: not K[1] rules: - Id = K[0] pcinstlist: attrs: [K, E, A] guard: K[1] rules: - Id = K[0] - DataExprListInst.E = E - DataExprListInst.A = K[1] act: attrs: [A] pre: - Id = A actdecl: attrs: [E] rules: - IdList.U = [] - IdList.L = len(E['act']) - IdList.Prefix = 'a' post: - E['act'] = E['act'] + IdList.U actspeclist: attrs: [E] rules: - IdList.U = [] - IdList.L = len(E['act']) - IdList.Prefix = 'a' - ActDecls.E = E - ActDecls.E['act'] = E['act'] + IdList.U post: - E = ActDecls.E actspec: attrs: [E] rules: - ActDecls.E = E post: - E = ActDecls.E sortspec: attrs: [E] rules: - SortDecls.E = E post: - E = SortDecls.E sortdecls1: attrs: [E] rules: - SortDecl.E = E post: - E = SortDecl.E sortdecls2: attrs: [E] rules: - SortDecl.E = E - SortDecls.E = SortDecl.E post: - E = SortDecls.E sortdecl1: attrs: [E] rules: - IdList.U = [] - IdList.L = len(E['sort']) - IdList.Prefix = 'D' post: - | E['sort'] = E['sort'] + [{'name': x, 'type': None} for x in IdList.U] sortdecl2: attrs: [E] pre: - K = 'D' + str(len(E['sort']) + 1) rules: - Id = K - SortExpr.T = K - SortExpr.Sorts = E['sort'] post: - | E['sort'].append({'name': K, 'type': SortExpr.T}) # ProcExpr pre_act: attrs: [E, P, G, pcrl] guard: | P <= 10 pre: - K = choice(E['act']) rules: - Action.A = K post: - G = True pre_pv: attrs: [E, P, G, pcrl] guard: | P <= 10 and G pre: - K = choice(E['proc']) rules: - ProcVarInst.E = E - ProcVarInst.K = K - ProcVarInst.A = len(K[1]) pre_delta: attrs: [E, P, G, pcrl] guard: P <= 10 pre_tau: attrs: [E, P, G, pcrl] guard: P <= 10 pre_brk: attrs: [E, P, G, pcrl] guard: P <= 10 rules: - ProcExpr.E = E - ProcExpr.P = 1 - ProcExpr.G = G - ProcExpr.pcrl = pcrl pre_choice: attrs: [E, P, G, pcrl] guard: P <= 1 and pcrl != 'parallel' rules: - ProcExpr.E = E - ProcExpr.P = 1 - ProcExpr.G = G - ProcExpr.pcrl = 'pcrl' - ProcExpr2.E = E - ProcExpr2.P = 2 - ProcExpr2.G = G - ProcExpr2.pcrl = 'pcrl' pre_sum: attrs: [E, P, G, pcrl] guard: P <= 2 and pcrl != 'parallel' rules: - VarsDeclList.E = E - VarsDeclList.U = [] - VarsDeclList.L = len(E['var']) - VarsDeclList.Prefix = 'v' - ProcExpr.E = E - ProcExpr.E['var'] = E['var'] + VarsDeclList.U - ProcExpr.P = 2 - ProcExpr.G = G - ProcExpr.pcrl = 'pcrl' pre_pllel: attrs: [E, P, G, pcrl] guard: P <= 3 and pcrl != 'pcrl' rules: - ProcExpr.E = E - ProcExpr.P = 4 - ProcExpr.G = G - ProcExpr.pcrl = 'parallel' - ProcExpr2.E = E - ProcExpr2.P = 3 - ProcExpr2.G = G - ProcExpr2.pcrl = 'parallel' pre_lftmrg: attrs: [V, W, P, G, Acts, pcrl] guard: P <= 4 and pcrl != 'parallel' rules: - ProcExpr.V = V - ProcExpr.W = W - ProcExpr.P = 5 - ProcExpr2.V = V - ProcExpr2.W = W - ProcExpr2.P = 4 pre_cond: attrs: [E, P, G, pcrl] guard: P <= 5 and pcrl != 'parallel' rules: - DataExpr.T = ['bool'] - DataExpr.W = E['var'] - DataExpr.P = 14 - ProcExpr.E = E - ProcExpr.pcrl = 'pcrl' - ProcExpr.P = 5 - ProcExpr.G = G pre_seq: attrs: [E, P, G, pcrl] guard: P <= 7 and pcrl != 'parallel' rules: - ProcExpr.E = E - ProcExpr.P = 8 - ProcExpr.G = G - ProcExpr.pcrl = 'pcrl' - ProcExpr2.E = E - ProcExpr2.P = 7 - ProcExpr2.G = True - ProcExpr2.pcrl = 'pcrl' pre_time: attrs: [E, P, G, pcrl] guard: P <= 8 rules: - ProcExpr.E = E - ProcExpr.P = 8 - DataExpr.T = ['int', 'real', 'nat', 'pos'] - DataExpr.W = E['var'] - DataExpr.P = 14 pre_multact: attrs: [V, W, P, G, Acts, pcrl] guard: P <= 9 rules: - ProcExpr.V = V - ProcExpr.W = W - ProcExpr.P = 9 - ProcExpr2.V = V - ProcExpr2.W = W - ProcExpr2.P = 10 # SortExpr constdecl: attrs: [U, L] pre: - K = 'd' + str(L) rules: - Id = K post: - U = [K] constdecllist: attrs: [U, L] pre: - K = 'd' + str(L) rules: - Id = K - ConstrDeclList.E - ConstrDeclList.U = [] - ConstrDeclList.L = L + 1 post: - U = [K] + ConstrDeclList.U se: attrs: [Sorts, T] rules: - SimpleSortExpr.Sorts = Sorts - SimpleSortExpr.T = T post: - T = SimpleSortExpr.T se_bool: attrs: [Sorts, T] post: - T = 'bool' se_pos: attrs: [Sorts, T] post: - T = 'pos' se_nat: attrs: [Sorts, T] post: - T = 'nat' se_int: attrs: [Sorts, T] post: - T = 'int' se_real: attrs: [Sorts, T] post: - T = 'real' se_ref: attrs: [Sorts, T] guard: | len(Sorts) > 0 and any(s for s in Sorts if s['type'] != None) pre: - K = choice([s for s in Sorts if s['type'] != None]) rules: - Id = K['name'] post: - T = K['type'] se_struct: attrs: [Sorts, T] guard: len(Sorts) > 0 rules: - ConstrDeclList # IdList idlid: order: left attrs: [U, L, Prefix] pre: - K = Prefix + str(L + 1) # - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K idlids: order: left attrs: [U, L, Prefix] pre: - K = Prefix + str(L + 1) # - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K - IdList.U = U - IdList.L = L + 1 - IdList.Prefix = Prefix post: - U = IdList.U mcrl2-201409.0/tests/constraints/pbes-attrs.yml000770 001750 001750 00000027123 12370120021 021651 0ustar00outisoutis000000 000000 # V prop variable list with arguments # W list of global datavariables that can be used pbes: order: left rules: - PbesEqnSpec.V = [] - PbesEqnSpec.W = [] - PbesInit.V = PbesEqnSpec.V - PbesInit.W = PbesEqnSpec.W pbeseqnspec: order: left attrs: [V, W] rules: - PbesEqnDecls.V = V - PbesEqnDecls.W = W - PbesEqnDecls.Iterations = 5 pbeseq: order: left attrs: [V, W, Iterations] guard: Iterations == 1 rules: - PbesEqnDecl.V = V - PbesEqnDecl.W = W pbeseqs: attrs: [V, W, Iterations] guard: Iterations > 1 rules: - PbesEqnDecl.V = V - PbesEqnDecl.W = W - PbesEqnDecls.V = PbesEqnDecl.V - PbesEqnDecls.W = PbesEqnDecl.W - PbesEqnDecls.Iterations = Iterations - 1 # todo: pass W down to UniquePropVarDecl to avoid duplicate datavariable names being declared pbeseqdecl: order: left attrs: [V, W] rules: - UniquePropVarDecl.V = V - UniquePropVarDecl.U = [] - UniquePropVarDecl.Prefix = 'u' - Guard.W = UniquePropVarDecl.U - PbesExpr.V = UniquePropVarDecl.V - PbesExpr.W = UniquePropVarDecl.U + W - PbesExpr.M = True - PbesExpr.P = 0 vardecl: order: left attrs: [V, U, Prefix] pre: - K = 'X' + str(len(V)+1) - V.append((K, [])) rules: - Id = K vardecllist: order: left attrs: [V, U, Prefix] pre: - K = 'X' + str(len(V)+1) rules: - Id = K - VarsDeclList.U = U - VarsDeclList.Prefix = Prefix post: - U = VarsDeclList.U - V.append((K, U)) vdcl: order: left attrs: [U, Prefix] rules: - VarsDecls.U = U - VarsDecls.L = len(U) - VarsDecls.Prefix = Prefix post: - U = VarsDecls.U vsdecl: order: left attrs: [U, L, Prefix] rules: - VarDecl.U = U - VarDecl.L = L - VarDecl.Prefix = Prefix post: - U = VarDecl.U - L = L + len(VarDecl.U) vsdecls: order: left attrs: [U, L, Prefix] rules: - VarDecl.U = U - VarDecl.L = L - VarDecl.Prefix = Prefix - VarsDecls.U = VarDecl.U - VarsDecls.L = L + len(VarDecl.U) - VarsDecls.Prefix = Prefix post: - U = VarsDecls.U - L = L + len(VarsDecls.U) vdecl: attrs: [U, L, Prefix] rules: - IdList.U = [] - IdList.L = L - IdList.Prefix = Prefix - SortExpr.T = None post: - | U = U + [{'name': u, 'type': SortExpr.T} for u in IdList.U] - L = L + len(U) init: attrs: [V, W] rules: - PropVarInst.V = V - PropVarInst.W = W - PropVarInst.M = True propvarinst: attrs: [V, W, M] rules: - VarInst.K = choice(V) - VarInst.W = W - VarInst.M = M varinst: attrs: [K, W, M] guard: not K[1] rules: - Id = '!' + K[0] if not M else K[0] varinstlist: attrs: [K, W, M] guard: K[1] rules: - Id = '!' + K[0] if not M else K[0] - DataExprListInst.W = W - DataExprListInst.A = K[1] dalinst: attrs: [W, A] guard: | len(A) == 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = W - DataExpr.P = 0 post: - A = [] dallinst: attrs: [W, A] guard: | len(A) > 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = W - DataExpr.P = 0 - DataExprListInst.W = W - | DataExprListInst.A = A[1:] dvale: order: left attrs: W rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 0 se: attrs: T rules: - SimpleSortExpr.T = T post: - T = SimpleSortExpr.T # SortExpr se_bool: attrs: T post: - T = 'bool' se_pos: attrs: T post: - T = 'pos' se_nat: attrs: T post: - T = 'nat' se_int: attrs: T post: - T = 'int' se_real: attrs: T post: - T = 'real' # DataExpr da_forall: attrs: [W, T, P] guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = W - VarsDeclList.Prefix = 'd' - DataExpr.W = VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_exists: attrs: [W, T, P] guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = W - VarsDeclList.Prefix = 'd' - DataExpr.W = VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_impl: attrs: [W, T, P] guard: | P <= 2 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 3 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 2 post: - T = ['bool'] da_conj: attrs: [W, T, P] guard: | P <= 4 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 4 post: - T = ['bool'] da_disj: attrs: [W, T, P] guard: | P <= 3 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 4 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 3 post: - T = ['bool'] da_eq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_neq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_lt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - "DataExpr.T = ['int', 'real', 'pos', 'nat']" - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_gt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_leq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_geq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_plus: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr2.P = 11 post: - T = ['pos'] if 'pos' in T else DataExpr2.T da_min: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 11 post: - T = DataExpr2.T da_times: attrs: [W, T, P] guard: | P <= 12 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 13 post: - T = DataExpr2.T da_divides: attrs: [W, T, P] guard: | P <= 11 and 'real' in T rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr2.P = 13 post: - T = ['real'] da_numb: attrs: [W, T, P] guard: | P <= 14 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - Number = str(choice(range(1,100))) post: - T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] da_true: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_false: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_neg: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 14 post: - T = ['bool'] da_inv: attrs: [W, T, P] guard: | P <= 14 and any(x for x in T if x in ['int', 'real']) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 14 post: - T = DataExpr.T da_brk: attrs: [W, T, P] guard: | P <= 14 rules: - DataExpr.W = W - DataExpr.T = T - DataExpr.P = 0 post: - T = DataExpr.T da_id: attrs: [W, T, P] guard: | P <= 14 and any(x for x in W if x['type'] in T) pre: - | V = choice([x for x in W if x['type'] in T]) rules: - Id = V['name'] post: - T = [V['type']] # PbesExpr pe_impl: attrs: [V, W, M, P] guard: P <= 1 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = not M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 1 pe_disj: attrs: [V, W, M, P] guard: P <= 2 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 3 pe_conj: attrs: [V, W, M, P] guard: P <= 2 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 3 pe_forall: attrs: [V, W, M, P] weight: 1 guard: P == 0 rules: - VarsDeclList.U = [] - VarsDeclList.Prefix = 'd' - Guard.W = W + VarsDeclList.U - PbesExpr.V = V - PbesExpr.W = VarsDeclList.U - PbesExpr.M = M - PbesExpr.P = 0 pe_exists: attrs: [V, W, M, P] weight: 1 guard: P == 0 rules: - VarsDeclList.U = [] - VarsDeclList.Prefix = 'd' - Guard.W = VarsDeclList.U - PbesExpr.V = V - PbesExpr.W = W + VarsDeclList.U - PbesExpr.M = M - PbesExpr.P = 0 pe_dv: attrs: [V, W, M, P] guard: P <= 3 rules: - DataValExpr.W = W pe_true: attrs: [V, W, M, P] guard: P <= 3 pe_false: attrs: [V, W, M, P] guard: P <= 3 pe_neg: attrs: [V, W, M, P] guard: P <= 3 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = not M - PbesExpr.P = 3 pe_brk: attrs: [V, W, M, P] guard: P <= 3 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 0 pe_pv: secondpass: pbes attrs: [V, W, M, P] guard: P <= 3 rules: - PropVarInst.V = V - PropVarInst.W = W - PropVarInst.M = M # IdList idlid: order: left attrs: [U, L, Prefix] pre: # - K = Prefix + str(L + 1) - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K idlids: order: left attrs: [U, L, Prefix] pre: # - K = Prefix + str(L + 1) - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K - IdList.U = U - IdList.L = L + 1 - IdList.Prefix = Prefix post: - U = IdList.U # Guard no_guard: attrs: [W] guard: not any(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) guard: attrs: [W] guard: any(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) pre: - K = next(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) rules: - G = ' '.join([K['name'], '<', str(choice(range(1,100)))]) - Guard.W = [x for x in W if x['name'] != K['name']] mcrl2-201409.0/tests/constraints/pbes-attrsdir1.yml000770 001750 001750 00000027320 12370120021 022430 0ustar00outisoutis000000 000000 # V prop variable list with arguments # W list of global datavariables that can be used pbes: order: left rules: - PbesEqnSpec.V = [] - PbesEqnSpec.W = [] - PbesInit.V = PbesEqnSpec.V - PbesInit.W = PbesEqnSpec.W pbeseqnspec: order: left attrs: [V, W] rules: - PbesEqnDecls.V = V - PbesEqnDecls.W = W - PbesEqnDecls.Iterations = 1 pbeseq: order: left attrs: [V, W, Iterations] guard: Iterations == 1 rules: - PbesEqnDecl.V = V - PbesEqnDecl.W = W pbeseqs: attrs: [V, W, Iterations] guard: Iterations > 1 rules: - PbesEqnDecl.V = V - PbesEqnDecl.W = W - PbesEqnDecls.V = PbesEqnDecl.V - PbesEqnDecls.W = PbesEqnDecl.W - PbesEqnDecls.Iterations = Iterations - 1 # todo: pass W down to UniquePropVarDecl to avoid duplicate datavariable names being declared pbeseqdecl: order: left attrs: [V, W] rules: - UniquePropVarDecl.V = V - UniquePropVarDecl.U = [] - UniquePropVarDecl.Iterations = 1 - UniquePropVarDecl.Prefix = 'u' - Guard.W = UniquePropVarDecl.U - PbesExpr.V = UniquePropVarDecl.V - PbesExpr.W = UniquePropVarDecl.U + W - PbesExpr.M = True - PbesExpr.P = 0 vardecl: order: left attrs: [V, U, Prefix, Iterations] guard: Iterations == 0 pre: - K = 'X' + str(len(V)+1) - V.append((K, [])) rules: - Id = K vardecllist: order: left attrs: [V, U, Prefix] guard: Iterations > 0 pre: - K = 'X' + str(len(V)+1) rules: - Id = K - VarsDeclList.U = U - VarsDeclList.Prefix = Prefix post: - U = VarsDeclList.U - V.append((K, U)) vdcl: order: left attrs: [U, Prefix] rules: - VarsDecls.U = U - VarsDecls.L = len(U) - VarsDecls.Prefix = Prefix post: - U = VarsDecls.U vsdecl: order: left attrs: [U, L, Prefix] rules: - VarDecl.U = U - VarDecl.L = L - VarDecl.Prefix = Prefix post: - U = VarDecl.U - L = L + len(VarDecl.U) vsdecls: order: left attrs: [U, L, Prefix] rules: - VarDecl.U = U - VarDecl.L = L - VarDecl.Prefix = Prefix - VarsDecls.U = VarDecl.U - VarsDecls.L = L + len(VarDecl.U) - VarsDecls.Prefix = Prefix post: - U = VarsDecls.U - L = L + len(VarsDecls.U) vdecl: attrs: [U, L, Prefix] rules: - IdList.U = [] - IdList.L = L - IdList.Prefix = Prefix - SortExpr.T = None post: - | U = U + [{'name': u, 'type': SortExpr.T} for u in IdList.U] - L = L + len(U) init: attrs: [V, W] rules: - PropVarInst.V = V - PropVarInst.W = W - PropVarInst.M = True propvarinst: attrs: [V, W, M] rules: - VarInst.K = choice(V) - VarInst.W = W - VarInst.M = M varinst: attrs: [K, W, M] guard: not K[1] rules: - Id = '!' + K[0] if not M else K[0] varinstlist: attrs: [K, W, M] guard: K[1] rules: - Id = '!' + K[0] if not M else K[0] - DataExprListInst.W = W - DataExprListInst.A = K[1] dalinst: attrs: [W, A] guard: | len(A) == 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = W - DataExpr.P = 0 post: - A = [] dallinst: attrs: [W, A] guard: | len(A) > 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = W - DataExpr.P = 0 - DataExprListInst.W = W - | DataExprListInst.A = A[1:] dvale: order: left attrs: W rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 0 se: attrs: T rules: - SimpleSortExpr.T = T post: - T = SimpleSortExpr.T # SortExpr se_bool: attrs: T post: - T = 'bool' se_pos: attrs: T post: - T = 'pos' se_nat: attrs: T post: - T = 'nat' se_int: attrs: T post: - T = 'int' se_real: attrs: T post: - T = 'real' # DataExpr da_forall: attrs: [W, T, P] weight: 1 guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = W - VarsDeclList.Prefix = 'd' - DataExpr.W = VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_exists: attrs: [W, T, P] weight: 1 guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = W - VarsDeclList.Prefix = 'd' - DataExpr.W = VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_impl: attrs: [W, T, P] guard: | P <= 2 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 3 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 2 post: - T = ['bool'] da_conj: attrs: [W, T, P] guard: | P <= 4 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 4 post: - T = ['bool'] da_disj: attrs: [W, T, P] guard: | P <= 3 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 4 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 3 post: - T = ['bool'] da_eq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_neq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_lt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - "DataExpr.T = ['int', 'real', 'pos', 'nat']" - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_gt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_leq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_geq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_plus: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr2.P = 11 post: - T = ['pos'] if 'pos' in T else DataExpr2.T da_min: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 11 post: - T = DataExpr2.T da_times: attrs: [W, T, P] guard: | P <= 12 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 13 post: - T = DataExpr2.T da_divides: attrs: [W, T, P] guard: | P <= 11 and 'real' in T rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr2.P = 13 post: - T = ['real'] da_numb: attrs: [W, T, P] guard: | P <= 14 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - Number = str(choice(range(1,100))) post: - T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] da_true: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_false: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_neg: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 14 post: - T = ['bool'] da_inv: attrs: [W, T, P] guard: | P <= 14 and any(x for x in T if x in ['int', 'real']) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 14 post: - T = DataExpr.T da_brk: attrs: [W, T, P] guard: | P <= 14 rules: - DataExpr.W = W - DataExpr.T = T - DataExpr.P = 0 post: - T = DataExpr.T da_id: attrs: [W, T, P] guard: | P <= 14 and any(x for x in W if x['type'] in T) pre: - | V = choice([x for x in W if x['type'] in T]) rules: - Id = V['name'] post: - T = [V['type']] # PbesExpr pe_impl: attrs: [V, W, M, P] guard: P <= 1 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = not M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 1 pe_disj: attrs: [V, W, M, P] guard: P <= 2 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 3 pe_conj: attrs: [V, W, M, P] guard: P <= 2 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 2 - PbesExpr2.V = V - PbesExpr2.W = W - PbesExpr2.M = M - PbesExpr2.P = 3 pe_forall: attrs: [V, W, M, P] weight: 10 guard: P == 0 rules: - VarsDeclList.U = [] - VarsDeclList.Prefix = 'd' - Guard.W = W + VarsDeclList.U - PbesExpr.V = V - PbesExpr.W = VarsDeclList.U - PbesExpr.M = M - PbesExpr.P = 0 pe_exists: attrs: [V, W, M, P] weight: 10 guard: P == 0 rules: - VarsDeclList.U = [] - VarsDeclList.Prefix = 'd' - Guard.W = VarsDeclList.U - PbesExpr.V = V - PbesExpr.W = W + VarsDeclList.U - PbesExpr.M = M - PbesExpr.P = 0 pe_dv: attrs: [V, W, M, P] guard: P <= 3 rules: - DataValExpr.W = W pe_true: attrs: [V, W, M, P] guard: P <= 3 pe_false: attrs: [V, W, M, P] guard: P <= 3 pe_neg: attrs: [V, W, M, P] guard: P <= 3 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = not M - PbesExpr.P = 3 pe_brk: attrs: [V, W, M, P] guard: P <= 3 rules: - PbesExpr.V = V - PbesExpr.W = W - PbesExpr.M = M - PbesExpr.P = 0 pe_pv: secondpass: pbes attrs: [V, W, M, P] guard: P <= 3 rules: - PropVarInst.V = V - PropVarInst.W = W - PropVarInst.M = M # IdList idlid: order: left attrs: [U, L, Prefix] pre: # - K = Prefix + str(L + 1) - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K idlids: order: left attrs: [U, L, Prefix] pre: # - K = Prefix + str(L + 1) - K = choice(['u', 'v', 'w']) - U.append(K) rules: - Id = K - IdList.U = U - IdList.L = L + 1 - IdList.Prefix = Prefix post: - U = IdList.U # Guard no_guard: attrs: [W] guard: not any(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) guard: attrs: [W] guard: any(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) pre: - K = next(x for x in W if x['type'] in ['int', 'real', 'pos', 'nat']) rules: - G = ' '.join([K['name'], '<', str(choice(range(1,100)))]) - Guard.W = [x for x in W if x['name'] != K['name']] mcrl2-201409.0/tests/constraints/bes-attrs-op_precedence.yml000770 001750 001750 00000002775 12370120021 024270 0ustar00outisoutis000000 000000 bes: order: left rules: - BesEqnSpec.V = [] - BesInit.V = BesEqnSpec.V eqndecls: order: left attrs: V rules: - BesEqnDecls.V = V eq: order: left attrs: V rules: - BesEqnDecl.V = V eqs: order: left attrs: V rules: - BesEqnDecl.V = V - BesEqnDecls.V = BesEqnDecl.V post: - V = BesEqnDecls.V eqdecl: order: left attrs: V pre: - K = 'X' + str(len(V)+1) - V.append(K) rules: - BesVar = K - BesExpr.V = V - BesExpr.M = True be_impl: order: left attrs: [V, M] rules: - BesTerm.V = V - BesTerm.M = not M - BesExpr.V = V - BesExpr.M = M be_term: attrs: [V, M] rules: - BesTerm.V = V - BesTerm.M = M be_disj: order: right attrs: [V, M] rules: - BesTerm.V = V - BesTerm.M = M - BesFactor.V = V - BesFactor.M = M be_conj: order: right attrs: [V, M] rules: - BesTerm.V = V - BesTerm.M = M - BesFactor.V = V - BesFactor.M = M be_fac: attrs: [V, M] rules: - BesFactor.V = V - BesFactor.M = M be_true: order: left attrs: [V, M] be_false: order: left attrs: [V, M] be_neg: order: left attrs: [V, M] rules: - BesFactor.V = V - BesFactor.M = not M be_brk: order: left attrs: [V, M] rules: - BesExpr.V = V - BesExpr.M = M be_var: secondpass: bes order: left attrs: [V, M] pre: - K = '!' if not M else '' rules: - BesVar = K + choice(V) init: order: left attrs: V rules: - BesVar = choice(V) mcrl2-201409.0/tests/constraints/bes-attrs.yml000770 001750 001750 00000002765 12370120021 021476 0ustar00outisoutis000000 000000 bes: rules: - BesEqnSpec.V = [] - BesInit.V = BesEqnSpec.V eqndecls: attrs: V rules: - BesEqnDecls.V = V eq: attrs: V rules: - BesEqnDecl.V = V eqs: attrs: V rules: - BesEqnDecl.V = V - BesEqnDecls.V = BesEqnDecl.V post: - V = BesEqnDecls.V eqdecl: attrs: V pre: - K = 'X' + str(len(V)+1) - V.append(K) rules: - BesVar = K - BesExpr.V = V - BesExpr.M = True - BesExpr.P = 0 be_impl: attrs: [V, M, P] guard: P == 0 rules: - BesExpr.P = 1 - BesExpr.V = V - BesExpr.M = not M - BesExpr2.P = 0 - BesExpr2.V = V - BesExpr2.M = M be_disj: attrs: [V, M, P] guard: P <= 1 rules: - BesExpr.P = 1 - BesExpr.V = V - BesExpr.M = M - BesExpr2.P = 2 - BesExpr2.V = V - BesExpr2.M = M be_conj: attrs: [V, M, P] guard: P <= 1 rules: - BesExpr.P = 1 - BesExpr.V = V - BesExpr.M = M - BesExpr2.P = 2 - BesExpr2.V = V - BesExpr2.M = M be_true: attrs: [V, M, P] guard: P <= 2 be_false: attrs: [V, M, P] guard: P <= 2 be_neg: attrs: [V, M, P] guard: P <= 2 rules: - BesExpr.P = 2 - BesExpr.V = V - BesExpr.M = not M be_brk: attrs: [V, M, P] guard: P <= 2 rules: - BesExpr.P = 0 - BesExpr.V = V - BesExpr.M = M be_var: secondpass: bes attrs: [V, M, P] guard: P <= 2 pre: - K = '!' if not M else '' rules: - BesVar = K + choice(V) init: order: left attrs: V rules: - BesVar = choice(V) mcrl2-201409.0/tests/constraints/data-attrs.yml000770 001750 001750 00000013641 12370120021 021631 0ustar00outisoutis000000 000000 dalinst: attrs: [E, A] guard: | len(A) == 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = E['var'] - DataExpr.P = 0 post: - A = [] dallinst: attrs: [E, A] guard: | len(A) > 1 rules: - DataExpr.T = [A[0]['type']] - DataExpr.W = E['var'] - DataExpr.P = 0 - DataExprListInst.E = E - | DataExprListInst.A = A[1:] # DataExpr da_forall: attrs: [W, T, P] guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = [] - VarsDeclList.L = len(W) - VarsDeclList.Prefix = 'u' - | VarsDeclList.E = {'sort': []} - DataExpr.W = W + VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_exists: attrs: [W, T, P] guard: | P <= 1 and 'bool' in T rules: - VarsDeclList.U = [] - VarsDeclList.L = len(W) - VarsDeclList.Prefix = 'u' - | VarsDeclList.E = {'sort': []} - DataExpr.W = W + VarsDeclList.U - DataExpr.T = ['bool'] - DataExpr.P = 1 post: - T = ['bool'] da_impl: attrs: [W, T, P] guard: | P <= 2 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 3 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 2 post: - T = ['bool'] da_conj: attrs: [W, T, P] guard: | P <= 4 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 4 post: - T = ['bool'] da_disj: attrs: [W, T, P] guard: | P <= 3 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 4 - DataExpr2.W = W - DataExpr2.T = ['bool'] - DataExpr2.P = 3 post: - T = ['bool'] da_eq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_neq: attrs: [W, T, P] guard: | P <= 5 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['bool', 'int', 'real', 'pos', 'nat'] - DataExpr.P = 5 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 6 post: - T = ['bool'] da_lt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - "DataExpr.T = ['int', 'real', 'pos', 'nat']" - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_gt: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_leq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_geq: attrs: [W, T, P] guard: | P <= 6 and 'bool' in T rules: - DataExpr.W = W - DataExpr.T = ['int', 'real', 'pos', 'nat'] - DataExpr.P = 6 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 7 post: - T = ['bool'] da_plus: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = ['pos', 'nat'] if 'pos' in T else T - DataExpr2.P = 11 post: - T = ['pos'] if 'pos' in T else DataExpr2.T da_min: attrs: [W, T, P] guard: | P <= 10 and any(x for x in ['int', 'real'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 10 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 11 post: - T = DataExpr2.T da_times: attrs: [W, T, P] guard: | P <= 12 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = DataExpr.T - DataExpr2.P = 13 post: - T = DataExpr2.T da_divides: attrs: [W, T, P] guard: | P <= 11 and 'real' in T rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 12 - DataExpr2.W = W - DataExpr2.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr2.P = 13 post: - T = ['real'] da_numb: attrs: [W, T, P] guard: | P <= 14 and any(x for x in ['int', 'real', 'pos', 'nat'] if x in T) rules: - Number = str(choice(range(1,100))) post: - T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] da_true: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_false: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) post: - T = ['bool'] da_neg: attrs: [W, T, P] guard: | P <= 14 and ('bool' in T) rules: - DataExpr.W = W - DataExpr.T = ['bool'] - DataExpr.P = 14 post: - T = ['bool'] da_inv: attrs: [W, T, P] guard: | P <= 14 and any(x for x in T if x in ['int', 'real']) rules: - DataExpr.W = W - DataExpr.T = [x for x in T if x in ['int', 'real', 'pos', 'nat']] - DataExpr.P = 14 post: - T = DataExpr.T da_brk: attrs: [W, T, P] guard: | P <= 14 rules: - DataExpr.W = W - DataExpr.T = T - DataExpr.P = 0 post: - T = DataExpr.T da_id: attrs: [W, T, P] guard: | P <= 14 and any(x for x in W if x['type'] in T) pre: - | V = choice([x for x in W if x['type'] in T]) rules: - Id = V['name'] post: - T = [V['type']]mcrl2-201409.0/tests/replay.py000770 001750 001750 00000002647 12370120021 016345 0ustar00outisoutis000000 000000 #!/usr/bin/env python #~ Copyright 2013, 2014 Mark Geelen. #~ Distributed under the Boost Software License, Version 1.0. #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) from __future__ import division import sys, logging, randgen, time, os, yaml from test import Test, ToolInputError, UnusedToolsError, ToolCrashedError import argparse parser = argparse.ArgumentParser(description='Executes random tests') parser.add_argument('T', help='test file (.yml)') parser.add_argument('I', help='input files', nargs='*') parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', help='print verbose output') parser.add_argument('-r' '--report', action='store_true', dest='reporterrors', help='capture error messages in node values') options = parser.parse_args() testfile = options.T inputfiles = options.I reporterrors = not options.reporterrors settings = dict() settings['verbose'] = options.verbose t = Test(testfile, settings) if settings['verbose']: print 'Running test ' + testfile t.reset() t.replay(inputfiles) try: result = t.run(reporterrors) if result == True: print 'Result: pass' else: print 'Result: fail' except ToolInputError as e: print 'Result: ' + next(x for x in e.value.split('\n') if 'error' in x) except UnusedToolsError as e: print 'Result: UnusedToolsError' except ToolCrashedError as e: print 'Result: ToolCrashedError'mcrl2-201409.0/tests/tests/pbessolve.yml000770 001750 001750 00000000620 12370120020 020352 0ustar00outisoutis000000 000000 options: version: -mcrl2.201202.0 path: C:\Program Files (x86)\mCRL2\bin platform: windows nodes: {l1: PbesSpec, l2: PBES, l3: Bool, l4: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes - input: [l2] output: [l3] args: [] name: pbes2bool - input: [l2] output: [l4] args: [] name: pbespgsolve result: | result = value(l3) == value(l4) mcrl2-201409.0/tests/tests/lpsparelm2.yml000770 001750 001750 00000001360 12370120020 020433 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml path: C:\Program Files\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3: PBES, l4: LPS, l5: PBES, l6: Bool, l7: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3] args: [] name: lps2pbes - input: [l2] output: [l4] args: [] name: lpsparelm - input: [l4] output: [l5] args: [--formula=nodeadlock.mcf] name: lps2pbes - input: [l3] output: [l6] args: [] name: pbes2bool - input: [l5] output: [l7] args: [] name: pbes2bool result: | result = 'error' in value(l3) mcrl2-201409.0/tests/tests/lpsbisim2pbes.yml000770 001750 001750 00000001112 12370120020 021123 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml path: ../tools/bin platform: linux nodes: {l1: mCRL2Spec, l2: mCRL2Spec, l3: LPS, l4: LPS, l5: PBES} tools: t1: input: [l1] output: [l3] args: [] name: txt2lps t2: input: [l2] output: [l4] args: [] name: txt2lps t3: input: [l3, l4] output: [l5] args: [-bstrong-bisim] name: lpsbisim2pbes t4: input: [l5] output: [] args: [] name: pbespp result: | result = Truemcrl2-201409.0/tests/tests/pbesstategraph.yml000770 001750 001750 00000001063 12370120020 021366 0ustar00outisoutis000000 000000 options: grammar: - grammars\pbes.g constraints: - constraints\pbes-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2okt2012\mCRL2\bin platform: windows nodes: {l1: PbesSpec, l2: PBES, l3: PBES, l4: Bool, l5: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes - input: [l2] output: [l3] args: [] name: pbesstategraph - input: [l2] output: [l4] args: [] name: pbes2bool - input: [l3] output: [l5] args: [] name: pbes2bool result: | result = value(l4) == value(l5) mcrl2-201409.0/tests/tests/nodeadlock.mcf000770 001750 001750 00000000021 12370120020 020412 0ustar00outisoutis000000 000000 [true*]truemcrl2-201409.0/tests/tests/pbespareqelm.yml000770 001750 001750 00000001107 12370120020 021031 0ustar00outisoutis000000 000000 options: grammar: - grammars\pbes.g constraints: - constraints\pbes-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2okt2012\mCRL2\bin platform: windows nodes: {l1: PbesSpec, l2: PBES, l3: PBES, l4: Bool, l5: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes - input: [l2] output: [l3] args: [] name: pbespareqelm - input: [l2] output: [l4] args: [] name: pbes2bool - input: [l3] output: [l5] args: [] name: pbes2bool result: | result = last_word(value(l4)) == last_word(value(l5)) mcrl2-201409.0/tests/tests/bespppg.yml000770 001750 001750 00000001176 12370120020 020017 0ustar00outisoutis000000 000000 options: version: -mcrl2.201102.0 # path: D:\mcrl2okt2012\mCRL2\bin path: D:\mcrl2feb2012\mCRL2\bin # path: D:\mcrl2july2011\mCRL2\bin- input platform: win32 nodes: {l1: BesSpec, l2: BES, l3: BesSpec, l4: BES, l5: Bool, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes.exe - input: [l2] output: [l3] args: [] name: bespp.exe - input: [l3] output: [l4] args: [] name: txt2pbes.exe - input: [l2] output: [l5] args: [] name: pbespgsolve.exe - input: [l4] output: [l6] args: [] name: pbespgsolve.exe result: | result = value(l5) == value(l6) mcrl2-201409.0/tests/tests/alphabet.yml000770 001750 001750 00000001336 12370120020 020135 0ustar00outisoutis000000 000000 options: grammar: - bnf-grammars/mcrl2.g - bnf-grammars/data.g constraints: - constraints/mcrl2-attrs.yml - constraints/data-attrs.yml path: ../tools/bin platform: linux nodes: {l1: mCRL2Spec, l2: LPS, l3: LPS, l4.aut: LTS, l5.aut: LTS, l6: Bool} tools: t1: input: [l1] output: [l2] args: [] name: mcrl22lps t2: input: [l1] output: [l3] args: [--no-alpha] name: mcrl22lps t3: input: [l2] output: [l4.aut] args: [-oaut] name: lps2lts t4: input: [l3] output: [l5.aut] args: [-oaut] name: lps2lts t5: input: [l4.aut, l5.aut] output: [l6] args: [-iaut, -ebisim] name: ltscompare result: | result = 'not' not in value(l6) mcrl2-201409.0/tests/tests/mcrl22lps.yml000770 001750 001750 00000000611 12370120020 020170 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml path: ../tools/bin platform: linux nodes: {l1: mCRL2Spec, l2: LPS} tools: t1: input: [l1] output: [l2] args: [] name: mcrl22lps t2: input: [l2] output: [] args: [] name: lpsinfo result: | result = True mcrl2-201409.0/tests/tests/lpssumelm.yml000770 001750 001750 00000001342 12370120020 020373 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2feb2012\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3.aut: LTS, l4: LPS, l5.aut: LTS, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3.aut] args: [-oaut] name: lps2lts - input: [l2] output: [l4] args: [] name: lpssumelm - input: [l4] output: [l5.aut] args: [-oaut] name: lps2lts - input: [l3.aut, l5.aut] output: [l6] args: [-iaut, -ebisim] name: ltscompare result: | result = 'not' not in value(l6) mcrl2-201409.0/tests/tests/bessolve.yml000770 001750 001750 00000001172 12370120020 020175 0ustar00outisoutis000000 000000 options: grammar: - grammars\bes.g constraints: - constraints\bes-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2okt2012\mCRL2\bin platform: windows nodes: {l1: BesSpec, l2: BES, l3: Bool, l4: Bool, l5: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2bes - input: [l2] output: [l3] args: [-sgauss] name: bessolve - input: [l2] output: [l4] args: [-sspm] name: bessolve - input: [l2] output: [l5] args: [] name: pbes2bool result: | result = last_word(value(l3)) == last_word(value(l4)) and last_word(value(l4)) == last_word(value(l5)) mcrl2-201409.0/tests/tests/bespp.yml000770 001750 001750 00000001055 12370120020 017464 0ustar00outisoutis000000 000000 options: version: -mcrl2.201202.0 path: C:\Program Files\mCRL2\bin platform: win32 nodes: {l1: BesSpec, l2: BES, l3: BesSpec, l4: BES, l5: Bool, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes.exe - input: [l2] output: [l3] args: [] name: bespp.exe - input: [l3] output: [l4] args: [] name: txt2pbes.exe - input: [l2] output: [l5] args: [] name: pbes2bool.exe - input: [l4] output: [l6] args: [] name: pbes2bool.exe result: | result = value(l5) == value(l6) mcrl2-201409.0/tests/tests/pbesrewr.yml000770 001750 001750 00000001147 12370120020 020206 0ustar00outisoutis000000 000000 options: grammar: - grammars\pbes.g constraints: - constraints\pbes-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2okt2012\mCRL2\bin platform: windows nodes: {l1: PbesSpec, l2: PBES, l3: BES, l4: Bool, l5: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes - input: [l2] output: [l3] args: [-ppfnf] name: pbesrewr - input: [l2] output: [l4] args: [] name: pbes2bool - input: [l3] output: [l5] args: [] name: pbes2bool result: | result = last_word(value(l4)) == last_word(value(l5)) or 'solution' not in value(l4) mcrl2-201409.0/tests/tests/lps2pbes.yml000770 001750 001750 00000000722 12370120020 020105 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\pbes.g constraints: - constraints\pbes-attrs.yml path: ../tools/bin platform: linux nodes: {l1: mCRL2Spec, l2: StateFrm, l3: LPS, l4: PBES, l5: Bool} tools: t1: input: [l1] output: [l3] args: [] name: mcrl22lps t2: input: [l2, l3] output: [l4] args: [] name: lps2pbes t3: input: [l4] output: [] args: [] name: pbespp result: | result = True mcrl2-201409.0/tests/tests/lpspp.yml000770 001750 001750 00000001447 12370120020 017516 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2feb2012\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3.aut: LTS, l4: LPS, l5: LPS, l6.aut: LTS, l7: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3.aut] args: [-oaut] name: lps2lts - input: [l2] output: [l4] args: [] name: lpspp - input: [l4] output: [l5] args: [] name: txt2lps - input: [l5] output: [l6.aut] args: [-oaut] name: lps2lts - input: [l3.aut, l6.aut] output: [l7] args: [-iaut, -ebisim] name: ltscompare result: | result = 'not' not in value(l7) mcrl2-201409.0/tests/tests/ltsconvert.yml000770 001750 001750 00000001400 12370120020 020550 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2okt2012\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3.aut: LTS, l4.fsm: LTS, l5.aut: LTS, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3.aut] args: [-oaut] name: lps2lts - input: [l3.aut] output: [l4.fsm] args: [-iaut, -ofsm] name: ltsconvert - input: [l4.fsm] output: [l5.aut] args: [-ifsm, -oaut] name: ltsconvert - input: [l3.aut, l5.aut] output: [l6] args: [-ebisim] name: ltscompare result: | result = 'not' not in value(l6)mcrl2-201409.0/tests/tests/lpssuminst.yml000770 001750 001750 00000001343 12370120020 020574 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2feb2012\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3.aut: LTS, l4: LPS, l5.aut: LTS, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3.aut] args: [-oaut] name: lps2lts - input: [l2] output: [l4] args: [] name: lpssuminst - input: [l4] output: [l5.aut] args: [-oaut] name: lps2lts - input: [l3.aut, l5.aut] output: [l6] args: [-iaut, -ebisim] name: ltscompare result: | result = 'not' not in value(l6) mcrl2-201409.0/tests/tests/pbesparelm.yml000770 001750 001750 00000001105 12370120020 020501 0ustar00outisoutis000000 000000 options: version: -mcrl2.201202.0 path: C:\Program Files (x86)\mCRL2\bin # path: D:\mcrl2okt2012\mCRL2\bin # path: D:\mcrl2feb2012\mCRL2\bin # path: D:\mcrl2july2011\mCRL2\bin platform: windows nodes: {l1: PbesSpec, l2: PBES, l3: PBES, l4: Bool, l5: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes - input: [l2] output: [l3] args: [] name: pbesparelm - input: [l2] output: [l4] args: [] name: pbes2bool - input: [l3] output: [l5] args: [] name: pbes2bool result: | result = value(l4) == value(l5) mcrl2-201409.0/tests/tests/pbesrewr-onepoint.yml000770 001750 001750 00000000705 12370120020 022036 0ustar00outisoutis000000 000000 options: grammar: - grammars\pbes.g constraints: - constraints\pbes-attrs.yml path: ../tools/bin platform: linux nodes: {l1: PbesSpec, l2: PBES, l3: PBES, l4: Bool} tools: t1: input: [l1] output: [l2] args: [-n] name: txt2pbes t2: input: [l2] output: [l3] args: [-pquantifier-one-point] name: pbesrewr t3: input: [l3] output: [l4] args: [] name: pbesinfo result: | result = True mcrl2-201409.0/tests/tests/lpsparelm.yml000770 001750 001750 00000001514 12370120020 020352 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml path: C:\Program Files\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3: PBES, l4: LPS, l5: PBES, l6: Bool, l7: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3] args: [--formula=nodeadlock.mcf] name: lps2pbes - input: [l2] output: [l4] args: [] name: lpsparelm - input: [l4] output: [l5] args: [--formula=nodeadlock.mcf] name: lps2pbes - input: [l3] output: [l6] args: [] name: pbes2bool - input: [l5] output: [l7] args: [] name: pbes2bool result: | result = value(l6) == value(l7) and value(l6).replace('\n', '') in file_get_contents('endresult') mcrl2-201409.0/tests/tests/mcrl22lps_alphabet.yml000770 001750 001750 00000001252 12370120020 022032 0ustar00outisoutis000000 000000 options: grammar: - grammars/mcrl2.g - grammars/data.g constraints: - constraints/mcrl2-attrs.yml - constraints/data-attrs.yml path: platform: linux nodes: {l1: mCRL2Spec, l2: LPS, l3: LPS, l4.aut: LTS, l5.aut: LTS, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l1] output: [l3] args: [--no-alpha] name: mcrl22lps - input: [l2] output: [l4.aut] args: [-oaut] name: lps2lts - input: [l3] output: [l5.aut] args: [-oaut] name: lps2lts - input: [l4.aut, l5.aut] output: [l6] args: [-iaut, -ebisim] name: ltscompare result: | result = 'not' not in value(l6)mcrl2-201409.0/tests/tests/lpsbinary.yml000770 001750 001750 00000001342 12370120020 020355 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2feb2012\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3.aut: LTS, l4: LPS, l5.aut: LTS, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3.aut] args: [-oaut] name: lps2lts - input: [l2] output: [l4] args: [] name: lpsbinary - input: [l4] output: [l5.aut] args: [-oaut] name: lps2lts - input: [l3.aut, l5.aut] output: [l6] args: [-iaut, -ebisim] name: ltscompare result: | result = 'not' not in value(l6) mcrl2-201409.0/tests/tests/lpsconstelm.yml000770 001750 001750 00000001344 12370120020 020717 0ustar00outisoutis000000 000000 options: grammar: - grammars\mcrl2.g - grammars\data.g constraints: - constraints\mcrl2-attrs.yml - constraints\data-attrs.yml #path: C:\Program Files\mCRL2\bin path: D:\mcrl2feb2012\mCRL2\bin platform: windows nodes: {l1: mCRL2Spec, l2: LPS, l3.aut: LTS, l4: LPS, l5.aut: LTS, l6: Bool} tools: - input: [l1] output: [l2] args: [] name: mcrl22lps - input: [l2] output: [l3.aut] args: [-oaut] name: lps2lts - input: [l2] output: [l4] args: [] name: lpsconstelm - input: [l4] output: [l5.aut] args: [-oaut] name: lps2lts - input: [l3.aut, l5.aut] output: [l6] args: [-iaut, -ebisim] name: ltscompare result: | result = 'not' not in value(l6) mcrl2-201409.0/tests/tests/pbesconstelm.yml000770 001750 001750 00000000733 12370120020 021053 0ustar00outisoutis000000 000000 options: version: -mcrl2.201202.0 path: /home/wieger/svn/mcrl2/tools/bin platform: linux nodes: {l1: PbesSpec, l2: PBES, l3: PBES, l4: Bool, l5: Bool} tools: - input: [l1] output: [l2] args: [] name: txt2pbes - input: [l2] output: [l3] args: [] name: pbesconstelm - input: [l2] output: [l4] args: [] name: pbes2bool - input: [l3] output: [l5] args: [] name: pbes2bool result: | result = value(l4) == value(l5) mcrl2-201409.0/tests/run_tickets000770 001750 001750 00000002532 12370120021 016745 0ustar00outisoutis000000 000000 echo 'ticket 325' python replay.py tests/mcrl22lps.yml tickets/325/bug.mcrl2 echo '' echo 'ticket 283' python replay.py tests/alphabet.yml tickets/283/1.mcrl2 echo '' echo 'ticket 352' python replay.py tests/alphabet.yml tickets/352/1.mcrl2 echo '' echo 'ticket 397' python replay.py tests/mcrl22lps.yml tickets/397/1.mcrl2 echo '' echo 'ticket 1090' python replay.py tests/lps2pbes.yml tickets/1090/form.mcf tickets/1090/spec.mcrl2 echo '' echo 'ticket 1093' python replay.py tests/alphabet.yml tickets/1093/1.mcrl2 echo '' echo 'ticket 1122' python replay.py tests/txt2lps.yml tickets/1122/1.mcrl2 echo '' echo 'ticket 1127' python replay.py tests/mcrl22lps.yml tickets/1127/1.mcrl2 echo '' echo 'ticket 1143' python replay.py tests/pbesrewr-onepoint.yml tickets/1143/1.txt echo '' echo 'ticket 1144' python replay.py tests/lpsbisim2pbes.yml tickets/1144/test1.txt tickets/1144/test2.txt echo '' #echo 'ticket 1167' #python replay.py tests/countstates.yml ../examples/academic/abp/abp.mcrl2 #echo '' echo 'ticket 1234' python replay.py tests/lpsbinary.yml ../examples/academic/cabp/cabp.mcrl2 echo '' echo 'ticket 1241' python replay.py tests/alphabet.yml tickets/1241/1.mcrl2 echo '' echo 'ticket 1247' python replay.py tests/alphabet.yml tickets/1247/1.mcrl2 echo '' echo 'ticket 1249' python replay.py tests/alphabet.yml tickets/1249/1.mcrl2 echo '' mcrl2-201409.0/tests/mcrl2_parser2.py000770 001750 001750 00000020747 12370120021 017527 0ustar00outisoutis000000 000000 #!/usr/bin/env python #~ Copyright 2013, 2014 Mark Geelen. #~ Distributed under the Boost Software License, Version 1.0. #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) import re import string import tpg from types import * #--------------------------------------------------------# # read_text #--------------------------------------------------------# # returns the contents of the file 'filename' as a string def read_text(filename): try: f = open(filename, 'r') except IOError, e: print 'Unable to open file ' + filename + ' ', e sys.exit(0) text = f.read() f.close() return text #--------------------------------------------------------# # read_paragraphs #--------------------------------------------------------# # returns the contents of the file 'filename' as a list of paragraphs def read_paragraphs(file): text = read_text(file) paragraphs = re.split('\n\s*\n', text) return paragraphs #---------------------------------------------------------------# # Rule #---------------------------------------------------------------# # lhs: String # rhs: List # phase: String (or None) class Rule: def __init__(self, lhs, rhs): self.lhs = lhs self.rhs = rhs def name(self): return self.lhs # returns all functions in self.rhs def functions(self): result = [] for f in self.rhs: result.append(f) return result def terminals(self, non_terminal_list): result = [] for f in self.rhs: if f.name() not in non_terminal_list: result.append(f) return result def non_terminals(self, non_terminal_list): result = [] for f in self.rhs: if f.name() in non_terminal_list: result.append(f) return result #---------------------------------------------------------------# # Function #---------------------------------------------------------------# # name: String # arguments: List class Function: def __init__(self, name, arguments, phase): self.name_ = name self.arguments = arguments self.phase = phase def full_name(self): return self.name_ def name(self): if self.name_[0] == '<': return self.name_[1:-1] else: return self.name_ def check_name(self): if self.is_rule(): return 'check_rule_' + self.name() else: return 'check_term_' + self.name() def is_rule(self): return self.name_[0] == '<' def arity(self): return len(self.arguments) def parameters(self): result = [] for i in range(len(self.arguments)): arg = self.arguments[i] result.append('%s_%d' % (arg.name(), i)) return result def types(self): return map(Argument.type, self.arguments) def default_call(self): params = self.parameters() t = [] for i in range(len(params)): t.append('%s' % (params[i])) return string.join(t, ', ') def default_declaration(self): params = self.parameters() types = self.types() t = [] for i in range(len(params)): t.append('const %s& %s' % (types[i], params[i])) return string.join(t, ', ') #---------------------------------------------------------------# # Argument #---------------------------------------------------------------# # expressions: List # repetitions: String ('+*?') class Argument: def __init__(self, expressions, repetitions, lbl): self.expressions = expressions self.repetitions = repetitions self.lbl = lbl def type(self): if self.repetitions == '*' or self.repetitions == '+': return 'aterm_list' else: return 'aterm_appl' def name(self): return self.expressions[0].name() def check_name(self): return self.expressions[0].check_name() def full_name(self): return self.expressions[0].name() + self.repetitions def __str__(self): args = [] for e in self.expressions: args.append(e.name()) return self.repetitions + ' ' + string.join(args, ' ') # expressions: List # repetitions: String ('+*?') class Term: def __init__(self, expression, repetitions): self.expression = expression self.repetitions = repetitions class AttributeRule: def __init__(self, lhs, rhs): self.lhs = lhs self.rhs = rhs #---------------------------------------------------------------# # Mcrl2Actions #---------------------------------------------------------------# class Mcrl2Actions: def make_expression(self, terms): return terms def make_term(self, name, arguments, phase): return Function(name, arguments, phase) # repetitions can be either '\*', '\?', '\+' or '' def make_factor(self, expression, repetitions, label): return Argument(expression, repetitions, label) def make_rule(self, lhs, rhs): return Rule(lhs, rhs) def make_attributerule(self, lhs, rhs): return AttributeRule(lhs, rhs) #---------------------------------------------------------------# # EBNFParser #---------------------------------------------------------------# # EBNF description by Aad Mathijsen # # // This is the description of an EBNF grammar in the same EBNF format. # // The start symbol is and C-style comments may be used anywhere. # digit ::= [0-9] # letter ::= [a-zA-Z] # reserved ::= ":" | "=" | "|" | "*" | "+" | "?" | "(" | ")" | "[" | "]" | "-" # other ::= "`" | "_" | "~" | "!" | "@" | "#" | "$" | "%" | "^" | "&" # | "\" | "{" | "}" | ";" | "," | "." | "/" | "<" | ">" # identifier ::= letter ( letter | digit )? # character ::= digit | letter | special | other # string ::= "'" ( character | '"' )+ "'" # | '"' ( character | "'" )+ '"' # range ::= "~"? "[" ( character | digit "-" digit | letter "-" letter )+ "]" # # syntax ::= ( rule )* # rule ::= identifier ":" expression # expression ::= term ( "|" term )* # term ::= ( factor ) * # factor ::= ( identifier | string | range | "(" expression ")" ) ( "*" | "+" | "?" )? class EBNFParser(tpg.Parser): r""" separator option: '\$(\{.*?\}|\S*?\s+-?[0-9]*)' ; separator space: '\s+' ; separator comments: '//.*' ; token tkn: '"(?:[^"\\]|\\.)*"' ; token literal: '\'.*?\'' ; token identifier: '!?[a-zA-Z_]\w*(\.unique)?' ; token attributerule: '\{.*?\}' ; START/rules -> $ rules = [] $ ( rule/r $ rules.append(r) $ )* ; rule/r -> identifier/i ':' expression/e '\;' $ r = self.actions.make_rule(i, e) $ ; expression/e -> $ terms = [] $ term/t $ terms.append(t) $ ( '\|' term/t $ terms.append(t) $ )* $ e = self.actions.make_expression(terms) $ ; term/t -> $ factors = []; p = None ; name = '' $ factor/f $ factors.append(f) $ ( factor/f $ factors.append(f) $ )* $ t = self.actions.make_term(name, factors, p) $ ; factor/f -> $ r = '' ; e = None; l = None $ ( identifier/e | literal/e | tkn/e | '\(' expression/e '\)' | '\[' identifier/l '\]' ) ( '\*'/r | '\+'/r | '\?'/r )? $ f = self.actions.make_factor(e, r, l) $ ; """ def __init__(self, actions): tpg.Parser.__init__(self) self.actions = actionsmcrl2-201409.0/tests/draw.py000770 001750 001750 00000003244 12370120021 016000 0ustar00outisoutis000000 000000 #!/usr/bin/env python #~ Copyright 2014 Wieger Wesselink. #~ Distributed under the Boost Software License, Version 1.0. #~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) import glob import os import os.path import re import sys import yaml import StringIO def remove_ext(name): return re.sub(r'\.\w+$', '', name) def generate_dotfile(ymlfile): out = StringIO.StringIO() out.write('digraph G {\n') f = open(ymlfile) data = yaml.safe_load(f) f.close() tools = data['tools'] nodes = data['nodes'] for node in sorted(nodes): out.write(' %s [label=%s];\n' % (remove_ext(node), nodes[node])) toolindex = 1 for name in tools: tool = tools[name] toolname = 'tool%d' % toolindex toolindex = toolindex + 1 out.write(' %s [shape=box, label="%s"];\n' % (toolname, name + ' ' + ' '.join(tool['args']))) for src in tool['input']: out.write(' %s -> %s;\n' % (remove_ext(src), toolname)) for dest in tool['output']: out.write(' %s -> %s;\n' % (toolname, remove_ext(dest))) out.write('}\n') dotfile = remove_ext(ymlfile) + '.dot' pdffile = remove_ext(ymlfile) + '.pdf' print dotfile, pdffile with open(dotfile, 'w') as text_file: text_file.write(out.getvalue()) os.system('dot -Tpdf %s -o %s' % (dotfile, pdffile)) if len(sys.argv) != 2: print('Usage: draw where is an yml file or a directory containing yml files') if os.path.isdir(sys.argv[1]): files = glob.glob('tests/*.yml') else: files = [sys.argv[1]] for ymlfile in files: generate_dotfile(ymlfile) if len(files) == 1: ymlfile = files[0] pdffile = remove_ext(ymlfile) + '.pdf' os.system('evince "%s"' % pdffile) mcrl2-201409.0/tests/replay/abc_reduction1000770 001750 001750 00000000062 12370120021 020565 0ustar00outisoutis000000 000000 act a; init allow({a}, hide({a}, allow({a}, a)));mcrl2-201409.0/cppcheck_ignore.lst000770 001750 001750 00000000327 12370120007 017201 0ustar00outisoutis000000 000000 AlgoDialog Bremen Frame GarageCanvas GarageFrame GLCanvas grape_menubar InfoDialog MainFrame MarkDialog PartitionFrame PopupFrame SavePicDialog SaveVecDialog SettingsDialog SettingsFrame SimDialog splash Visualizer mcrl2-201409.0/CTestCustom.cmake.in000770 001750 001750 00000000310 12370120020 017141 0ustar00outisoutis000000 000000 set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "2000" ) set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "200" ) set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/valgrind_external.supp" ) mcrl2-201409.0/libraries/modal_formula/test/state_formula_test.cpp000770 001750 001750 00000025175 12370120134 025527 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file rename_test.cpp /// \brief Add your file description here. #define MCRL2_STATE_FORMULA_BUILDER_DEBUG #define BOOST_TEST_MODULE state_formula #include #include #include #include #include #include "mcrl2/utilities/test_utilities.h" #include "mcrl2/modal_formula/find.h" #include "mcrl2/modal_formula/state_formula_rename.h" #include "mcrl2/modal_formula/normalize.h" #include "mcrl2/modal_formula/detail/state_formula_accessors.h" #include "mcrl2/modal_formula/parse.h" #include "mcrl2/modal_formula/count_fixpoints.h" #include "mcrl2/modal_formula/maximal_closed_subformula.h" #include "mcrl2/data/set_identifier_generator.h" #include "mcrl2/data/find.h" #include "mcrl2/data/utility.h" #include "mcrl2/lps/linearise.h" using namespace std; using namespace mcrl2; using namespace mcrl2::core; using namespace mcrl2::lps; using namespace mcrl2::lps::detail; using namespace mcrl2::state_formulas; BOOST_AUTO_TEST_CASE(test_rename) { const std::string SPECIFICATION = "act a:Nat; \n" " \n" "map smaller: Nat#Nat -> Bool; \n" " \n" "var x,y : Nat; \n" " \n" "eqn smaller(x,y) = x < y; \n" " \n" "proc P(n:Nat) = sum m: Nat. a(m). P(m); \n" " \n" "init P(0); \n" ; using mcrl2::state_formulas::pp; specification spec = linearise(SPECIFICATION); state_formula formula = parse_state_formula("(mu X. X) && (mu X. X)", spec); data::set_identifier_generator generator; generator.add_identifiers(lps::find_identifiers(spec)); formula = rename_predicate_variables(formula, generator); std::cout << "pp(formula) == " << pp(formula) << std::endl; BOOST_CHECK(pp(formula) == "(mu X1. X1) && mu X. X" || pp(formula) == "(mu X. X) && mu X1. X1"); generator = data::set_identifier_generator(); generator.add_identifiers(lps::find_identifiers(spec)); formula = parse_state_formula("mu X. mu X. X", spec, false); std::cout << "formula: " << pp(formula) << std::endl; formula = rename_predicate_variables(formula, generator); std::cout << "formula: " << pp(formula) << std::endl; BOOST_CHECK_EQUAL(pp(formula), "mu X. mu X1. X1"); } BOOST_AUTO_TEST_CASE(test_normalize) { using namespace state_formulas::detail::accessors; state_formula x = state_formulas::variable(identifier_string("X"), data::data_expression_list()); state_formula y = state_formulas::variable(identifier_string("Y"), data::data_expression_list()); state_formula f; state_formula f1; state_formula f2; f = imp(not_(x), y); f1 = normalize(f); f2 = or_(x, y); std::cout << "f = " << state_formulas::pp(f) << std::endl; std::cout << "f1 = " << state_formulas::pp(f1) << std::endl; std::cout << "f2 = " << state_formulas::pp(f2) << std::endl; BOOST_CHECK_EQUAL(f1, f2); f = not_(and_(not_(x), not_(y))); f1 = normalize(f); f2 = or_(x, y); std::cout << "f = " << state_formulas::pp(f) << std::endl; std::cout << "f1 = " << state_formulas::pp(f1) << std::endl; std::cout << "f2 = " << state_formulas::pp(f2) << std::endl; BOOST_CHECK_EQUAL(f1, f2); } BOOST_AUTO_TEST_CASE(test_type_checking) { using namespace state_formulas::detail::accessors; specification context = linearise( "sort CPU = struct p1;" "sort CPUs = Set(CPU);" "init delta;" ); state_formula formula = parse_state_formula("nu X (P : CPUs = {p1}) . val(P != {})", context); // BOOST_CHECK(is_may(formula)); // BOOST_CHECK(is_regular_formula(act(formula))); } BOOST_AUTO_TEST_CASE(test_type_checking_conversion_of_arguments) { using namespace state_formulas::detail::accessors; specification context = linearise( "sort B = struct d;" "act a: List(B);" "init a([d]);" ); state_formula formula = parse_state_formula("true", context); BOOST_CHECK(is_may(formula)); BOOST_CHECK(is_regular_formula(act(formula))); } static inline state_formula negate_variable(const variable& x) { return state_formulas::not_(x); } BOOST_AUTO_TEST_CASE(test_not) { data::data_expression_list args; variable v(core::identifier_string("v"), args); state_formula s = not_(v); BOOST_CHECK(is_not(s)); state_formula t = negate_variable(v); BOOST_CHECK_EQUAL(s, t); // The following is expected to trigger an assertion failure // aterm_appl a = v; // state_formula t = not_(a); } // test case supplied by Jan Friso, 4-1-2011 BOOST_AUTO_TEST_CASE(test_parse) { std::string spec_text = "act a:Nat; \n" "init a(1); \n" ; std::string formula_text = "true"; lps::specification spec = lps::linearise(spec_text); state_formulas::state_formula f = state_formulas::parse_state_formula(formula_text, spec); std::cerr << "--- f ---\n" << state_formulas::pp(f) << "\n\n" << f << std::endl; std::set ids = state_formulas::find_identifiers(f); BOOST_CHECK(ids.find(core::identifier_string("1")) == ids.end()); BOOST_CHECK(ids.find(core::identifier_string("@c1")) != ids.end()); } /* Not supported BOOST_AUTO_TEST_CASE(test_find_nil) { state_formula formula; specification spec; formula = parse_state_formula("(mu X. X) && (mu X. X)", spec); BOOST_CHECK(find_nil(formula) == false); formula = parse_state_formula("[nil]true", spec); BOOST_CHECK(find_nil(formula) == true); } */ BOOST_AUTO_TEST_CASE(test_count_fixpoints) { state_formula formula; specification spec; formula = parse_state_formula("(mu X. X) && (mu X. X)", spec); BOOST_CHECK_EQUAL(count_fixpoints(formula), 2); formula = parse_state_formula("exists b:Bool. (mu X. X) || forall b:Bool. (nu X. mu Y. (X || Y))", spec); BOOST_CHECK_EQUAL(count_fixpoints(formula), 3); } // Test case for bug #1094. // This is expected to fail, due to the occurrence of an unbound variable Y // in the formula. BOOST_AUTO_TEST_CASE(test_1094) { const std::string SPEC = "act a,b,c,d;\n" "\n" "proc P(s3_X: Pos) =\n" " (s3_X == 1) ->\n" " a .\n" " P(s3_X = 2)\n" " + (s3_X == 2) ->\n" " b .\n" " P(s3_X = 3)\n" " + (s3_X == 3) ->\n" " a .\n" " P(s3_X = 4)\n" " + (s3_X == 3) ->\n" " a .\n" " P(s3_X = 5)\n" " + (s3_X == 4) ->\n" " c .\n" " P(s3_X = 1)\n" " + (s3_X == 5) ->\n" " d .\n" " P(s3_X = 1)\n" " + delta;\n" "\n" "init P(1);\n" ; specification s(parse_linear_process_specification(SPEC)); const std::string FORMULA = "[true*]([b] nu X. mu X.( [!c]X && [!c]Y))"; BOOST_CHECK_THROW(parse_state_formula(FORMULA, s), mcrl2::runtime_error); } inline state_formula sigma(const state_formula& x) { variable X("X", data::data_expression_list()); return x == X ? false_() : x; } BOOST_AUTO_TEST_CASE(test_replace_state_formulas) { specification spec; state_formula f = parse_state_formula("(mu X. X) && (mu X. X)", spec); state_formula result = replace_state_formulas(f, sigma); state_formula expected_result = parse_state_formula("(mu X. false) && (mu X. false)", spec); if (!(result == expected_result)) { std::cout << "error: " << state_formulas::pp(result) << " != " << state_formulas::pp(expected_result) << std::endl; } BOOST_CHECK(result == expected_result); } BOOST_AUTO_TEST_CASE(test_find_state_variables) { specification spec; state_formula f = parse_state_formula("(mu X. nu Y. true && mu Z. X && Z)", spec); std::set v = state_formulas::find_state_variables(f); BOOST_CHECK(v.size() == 2); f = parse_state_formula("mu X. nu Y. (true && mu Z. (X && Y || Z))", spec); v = find_state_variables(f); BOOST_CHECK(v.size() == 3); state_formulas::variable X("X", data::data_expression_list()); state_formulas::variable Y("Y", data::data_expression_list()); state_formulas::variable Z("Z", data::data_expression_list()); state_formula phi = state_formulas::and_(X, Y); v = find_state_variables(phi); BOOST_CHECK(v.size() == 2); v = find_free_state_variables(phi); BOOST_CHECK(v.size() == 2); state_formula psi = state_formulas::mu("X", data::assignment_list(), phi); v = find_state_variables(psi); BOOST_CHECK(v.size() == 2); v = find_free_state_variables(psi); BOOST_CHECK(v.size() == 1); } inline bool contains(const std::set& v, const std::string& s) { for (std::set::const_iterator i = v.begin(); i != v.end(); ++i) { if (state_formulas::pp(*i) == s) { return true; } } return false; } BOOST_AUTO_TEST_CASE(test_maximal_closed_subformulas) { mcrl2::log::mcrl2_logger::set_reporting_level(mcrl2::log::debug, "state_formulas"); specification spec; state_formula f = parse_state_formula("(mu X. nu Y. true && mu Z. X && Z)", spec); std::set v = maximal_closed_subformulas(f); BOOST_CHECK(v.size() == 1); f = parse_state_formula("exists b: Bool. forall c: Bool. val(b) && (val(c) || true) && false", spec); std::cerr << "FORMULA " << f << "\n"; v = maximal_closed_subformulas(f); BOOST_CHECK(v.size() == 1); state_formula g = exists(f).body(); std::cout << "g = " << state_formulas::pp(g) << std::endl; v = maximal_closed_subformulas(g); for (std::set::const_iterator i = v.begin(); i != v.end(); ++i) { std::cout << "element " << *i << std::endl; } BOOST_CHECK(v.size() == 2); BOOST_CHECK(contains(v, "true")); BOOST_CHECK(contains(v, "false")); state_formula h = forall(g).body(); v = maximal_closed_subformulas(h); std::cout << "h = " << state_formulas::pp(h) << std::endl; for (std::set::const_iterator i = v.begin(); i != v.end(); ++i) { std::cout << "element " << *i << std::endl; } BOOST_CHECK(v.size() == 2); BOOST_CHECK(contains(v, "true")); BOOST_CHECK(contains(v, "false")); } mcrl2-201409.0/libraries/modal_formula/test/print_test.cpp000770 001750 001750 00000005423 12370120030 024003 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file print_test.cpp /// \brief Tests pretty printing of state formulas. #include #include #include #include "mcrl2/lps/linearise.h" #include "mcrl2/lps/parse.h" #include "mcrl2/lps/detail/test_input.h" #include "mcrl2/modal_formula/monotonicity.h" #include "mcrl2/modal_formula/parse.h" #include "mcrl2/modal_formula/print.h" #include "mcrl2/utilities/test_utilities.h" using namespace mcrl2; using mcrl2::utilities::collect_after_test_case; using namespace mcrl2::lps; using namespace mcrl2::state_formulas; BOOST_GLOBAL_FIXTURE(collect_after_test_case) void run_test_case(const std::string& formula, const std::string& lps_spec) { specification spec = linearise(lps_spec); bool check_monotonicity = false; bool translate_regular = false; state_formula f = parse_state_formula(formula, spec, check_monotonicity, translate_regular); std::string pp_formula = state_formulas::pp(f); if (formula != pp_formula) { std::cerr << "Error: " << formula << " is printed as " << pp_formula << std::endl; } BOOST_CHECK(formula == pp_formula); } BOOST_AUTO_TEST_CASE(test_abp) { std::string lps_spec = lps::detail::ABP_SPECIFICATION(); run_test_case("delay @ 1", lps_spec); run_test_case("true", lps_spec); run_test_case("[true*]true", lps_spec); run_test_case("mu X. !!X", lps_spec); run_test_case("nu X. [true]X && true", lps_spec); run_test_case("nu X. [true]X && forall d: D. [r1(d)]mu Y. Y || true", lps_spec); run_test_case("forall d: D. nu X. [!r1(d)]X && [s4(d)]false", lps_spec); run_test_case("nu X. [true]X && forall d: D. [r1(d)]nu Y. [!r1(d) && !s4(d)]Y && [r1(d)]false", lps_spec); run_test_case("mu X. !X", lps_spec); run_test_case("mu X. nu Y. X => Y", lps_spec); run_test_case("mu X. X || mu X. X", lps_spec); run_test_case("mu X. X || mu X. X", lps_spec); run_test_case("(mu X. X) || mu Y. Y", lps_spec); run_test_case("!(mu X. X || mu X. X)", lps_spec); run_test_case("(forall d: D. nu X. X) && false", lps_spec); run_test_case("val(true)", lps_spec); run_test_case("delay @ 4", lps_spec); run_test_case("nu Z(i: Nat = 0). Z(2)", lps_spec); run_test_case("[true]true", lps_spec); run_test_case("[true]val(true)", lps_spec); run_test_case("exists d: Nat. val(d < 0)", lps_spec); run_test_case("exists d: Nat. val(d < 0) || val(d + 1 == 5)", lps_spec); } boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { return 0; } mcrl2-201409.0/libraries/modal_formula/test/modal_formula_find_test.cpp000770 001750 001750 00000005347 12370120030 026475 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file modal_formula_find_test.cpp /// \brief Test for find functions. #include #include #include #include #include #include "mcrl2/atermpp/make_list.h" #include "mcrl2/data/detail/print_utility.h" #include "mcrl2/lps/parse.h" #include "mcrl2/modal_formula/find.h" #include "mcrl2/modal_formula/parse.h" using namespace mcrl2; using namespace mcrl2::state_formulas; std::string SPEC = "glob \n" " m: Nat; \n" " \n" "act \n" " a: Nat; \n" " \n" "proc \n" " P(n:Nat) = a(m).P(n+1); \n" " \n" "init P(0); \n" ; inline data::variable nat(std::string name) { return data::variable(core::identifier_string(name), data::sort_nat::nat()); } inline data::variable pos(std::string name) { return data::variable(core::identifier_string(name), data::sort_pos::pos()); } inline data::variable bool_(std::string name) { return data::variable(core::identifier_string(name), data::sort_bool::bool_()); } void test_find() { lps::specification spec = lps::parse_linear_process_specification(SPEC); state_formula f = parse_state_formula("(mu X. X) && (forall b:Bool. true)", spec); //--- find_all_variables ---// data::variable b = bool_("b"); std::set v = state_formulas::find_all_variables(f); BOOST_CHECK(v.find(b) != v.end()); //--- find_sort_expressions ---// std::set e = state_formulas::find_sort_expressions(f); std::cout << "e.size() = " << e.size() << std::endl; BOOST_CHECK(std::find(e.begin(), e.end(), data::sort_bool::bool_()) != e.end()); } void test_free_variables() { variable X("X", data::data_expression_list()); data::variable b = bool_("b"); data::variable c = bool_("c"); data::data_expression phi = data::equal_to(b, c); data::variable_list v = atermpp::make_list(b); state_formula f = forall(v, phi); std::set free_variables = state_formulas::find_free_variables(f); std::cout << "free variables: " << core::detail::print_set(free_variables) << std::endl; BOOST_CHECK(free_variables.find(b) == free_variables.end()); BOOST_CHECK(free_variables.find(c) != free_variables.end()); } int test_main(int argc, char* argv[]) { test_find(); test_free_variables(); return EXIT_SUCCESS; } mcrl2-201409.0/libraries/modal_formula/test/monotonicity_test.cpp000770 001750 001750 00000024467 12370120030 025413 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file monotonicity_test.cpp /// \brief Tests for the is_monotonous function for state formulas. #include #include #include #include "mcrl2/lps/linearise.h" #include "mcrl2/lps/parse.h" #include "mcrl2/lps/detail/test_input.h" #include "mcrl2/modal_formula/monotonicity.h" #include "mcrl2/modal_formula/parse.h" #include "mcrl2/modal_formula/has_name_clashes.h" #include "mcrl2/modal_formula/resolve_name_clashes.h" #include "mcrl2/utilities/test_utilities.h" using namespace mcrl2; using mcrl2::utilities::collect_after_test_case; using namespace mcrl2::lps; using namespace mcrl2::state_formulas; BOOST_GLOBAL_FIXTURE(collect_after_test_case) void run_monotonicity_test_case(const std::string& formula, const std::string& lps_spec, const bool expect_success = true) { specification spec = linearise(lps_spec); bool check_monotonicity = false; state_formula f = parse_state_formula(formula, spec, check_monotonicity); if (state_formulas::has_name_clashes(f)) { std::cerr << "Error: " << state_formulas::pp(f) << " has name clashes" << std::endl; f = state_formulas::resolve_name_clashes(f); std::cerr << "resolved to " << state_formulas::pp(f) << std::endl; } BOOST_CHECK(is_monotonous(f) == expect_success); } BOOST_AUTO_TEST_CASE(test_abp) { std::string lps_spec = lps::detail::ABP_SPECIFICATION(); run_monotonicity_test_case("true", lps_spec, true); run_monotonicity_test_case("[true*]true", lps_spec, true); run_monotonicity_test_case("mu X. !!X", lps_spec, true); run_monotonicity_test_case("nu X. ([true]X && true)", lps_spec, true); run_monotonicity_test_case("nu X. ([true]X && forall d:D. [r1(d)] mu Y. (Y || true))", lps_spec, true); run_monotonicity_test_case("forall d:D. nu X. (([!r1(d)]X && [s4(d)]false))", lps_spec, true); run_monotonicity_test_case("nu X. ([true]X && forall d:D. [r1(d)]nu Y. ([!r1(d) && !s4(d)]Y && [r1(d)]false))", lps_spec, true); run_monotonicity_test_case("mu X. !X", lps_spec, false); run_monotonicity_test_case("mu X. nu Y. (X => Y)", lps_spec, false); run_monotonicity_test_case("mu X. X || mu X. X", lps_spec, true); run_monotonicity_test_case("mu X. (X || mu X. X)", lps_spec, true); run_monotonicity_test_case("mu X. (X || mu Y. Y)", lps_spec, true); run_monotonicity_test_case("!(mu X. X || mu X. X)", lps_spec, true); run_monotonicity_test_case("!(mu X. (X || mu X. X))", lps_spec, true); run_monotonicity_test_case("!(mu X. (X || mu Y. Y))", lps_spec, true); } // Test case provided by Jeroen Keiren, 10-9-2010 BOOST_AUTO_TEST_CASE(test_elevator) { std::string lps_spec = "% Model of an elevator for n floors. \n" "% Originally described in 'Solving Parity Games in Practice' by Oliver \n" "% Friedmann and Martin Lange. \n" "% \n" "% This is the version with a first in first out policy \n" " \n" "sort Floor = Pos; \n" " DoorStatus = struct open | closed; \n" " Requests = List(Floor); \n" " \n" "map maxFloor: Floor; \n" "eqn maxFloor = 3; \n" " \n" "map addRequest : Requests # Floor -> Requests; \n" " \n" "var r: Requests; \n" " f,g: Floor; \n" " % FIFO behaviour! \n" "eqn addRequest([], f) = [f]; \n" " (f == g) -> addRequest(g |> r, f) = g |> r; \n" " (f != g) -> addRequest(g |> r, f) = g |> addRequest(r, f); \n" " \n" "map removeRequest : Requests -> Requests; \n" "var r: Requests; \n" " f: Floor; \n" "eqn removeRequest(f |> r) = r; \n" " \n" "map getNext : Requests -> Floor; \n" "var r: Requests; \n" " f: Floor; \n" "eqn getNext(f |> r) = f; \n" " \n" "act isAt: Floor; \n" " request: Floor; \n" " close, open, up, down; \n" " \n" "proc Elevator(at: Floor, status: DoorStatus, reqs: Requests, moving: Bool) = \n" " isAt(at) . Elevator() \n" " + sum f: Floor. (f <= maxFloor) -> request(f) . Elevator(reqs = addRequest(reqs, f)) \n" " + (status == open) -> close . Elevator(status = closed) \n" " + (status == closed && reqs != [] && getNext(reqs) > at) -> up . Elevator(at = at + 1, moving = true) \n" " + (status == closed && reqs != [] && getNext(reqs) < at) -> down . Elevator(at = Int2Pos(at - 1), moving = true) \n" " + (status == closed && getNext(reqs) == at) -> open. Elevator(status = open, reqs = removeRequest(reqs), moving = false); \n" " \n" "init Elevator(1, open, [], false); \n" ; run_monotonicity_test_case("nu U. [true] U && ((mu V . nu W. !([!request(maxFloor)]!W && [request(maxFloor)]!V)) || (nu X . mu Y. [!isAt(maxFloor)] Y && [isAt(maxFloor)]X))", lps_spec, true); run_monotonicity_test_case("nu U. [true] U && ((nu V . mu W. ([!request(maxFloor)]W && [request(maxFloor)]V)) => (nu X . mu Y. [!isAt(maxFloor)] Y && [isAt(maxFloor)]X))", lps_spec, true); run_monotonicity_test_case("nu U. [true] U && (!(nu V . mu W. ([!request(maxFloor)]W && [request(maxFloor)]V)) || (nu X . mu Y. [!isAt(maxFloor)] Y && [isAt(maxFloor)]X))", lps_spec, true); run_monotonicity_test_case("(nu X . mu Y. X) => true", lps_spec, true); run_monotonicity_test_case("!(nu X . mu Y. X)", lps_spec, true); #ifndef MCRL2_DISABLE_MONOTONICITY_CHECKS run_monotonicity_test_case("mu X . X", lps_spec, true); run_monotonicity_test_case("nu X . X", lps_spec, true); run_monotonicity_test_case("mu X . !X", lps_spec, false); run_monotonicity_test_case("nu X . !X", lps_spec, false); run_monotonicity_test_case("!(mu X . X)", lps_spec, true); run_monotonicity_test_case("!(nu X . X)", lps_spec, true); run_monotonicity_test_case("(mu X . X) => true", lps_spec, true); run_monotonicity_test_case("(nu X . X) => true", lps_spec, true); run_monotonicity_test_case("!(mu X. (mu X. X))", lps_spec, true); #endif } boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { return 0; } mcrl2-201409.0/libraries/modal_formula/test/CMakeLists.txt000770 001750 001750 00000001722 12370120030 023642 0ustar00outisoutis000000 000000 # Authors: Frank Stappers and Aad Mathijssen # Copyright: see the accompanying file COPYING or copy at # https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # ########## Project setup ########## project(modal_formula_tests) cmake_minimum_required(VERSION 2.6) # ######### General setup ########## set(PREFIX "modal_formula") file(GLOB TERM_OBJS "*.cpp") foreach( OBJ ${TERM_OBJS} ) get_filename_component(result "${OBJ}" NAME_WE) add_executable("${PREFIX}_${result}" EXCLUDE_FROM_ALL "${OBJ}" ) target_link_libraries("${PREFIX}_${result}" ${Boost_SYSTEM_LIBRARY} mcrl2_core mcrl2_data mcrl2_lps mcrl2_modal_formula mcrl2_syntax dparser ) # MACRO is defined in CMakeLists.txt in root of source tree build_and_run_test_target( ${PREFIX}_${result} ) endforeach( OBJ ) mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/monotonicity.h000770 001750 001750 00000012256 12370120031 030317 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/monotonicity.h /// \brief add your file description here. #ifndef MCRL2_MODAL_FORMULA_MONOTONICITY_H #define MCRL2_MODAL_FORMULA_MONOTONICITY_H #include #include "mcrl2/core/detail/print_utility.h" #include "mcrl2/modal_formula/state_formula.h" #include "mcrl2/modal_formula/detail/state_formula_accessors.h" #include "mcrl2/utilities/detail/container_utility.h" namespace mcrl2 { namespace state_formulas { /// \brief Returns true if the state formula is monotonous. /// \param f A modal formula /// \return True if the state formula is monotonous. inline bool is_monotonous(state_formula f, const std::set& negated_variables) { using namespace state_formulas::detail::accessors; using utilities::detail::contains; //--- handle negations ---// if (is_not(f)) { f = arg(f); // remove the not if (data::is_data_expression(f)) { return true; } else if (is_true(f)) { return true; } else if (is_false(f)) { return true; } else if (is_not(f)) { return is_monotonous(arg(f), negated_variables); } else if (is_and(f)) { return is_monotonous(not_(left(f)), negated_variables) && is_monotonous(not_(right(f)), negated_variables); } else if (is_or(f)) { return is_monotonous(not_(left(f)), negated_variables) && is_monotonous(not_(right(f)), negated_variables); } else if (is_imp(f)) { return is_monotonous(left(f), negated_variables) && is_monotonous(not_(right(f)), negated_variables); } else if (is_forall(f)) { return is_monotonous(not_(arg(f)), negated_variables); } else if (is_exists(f)) { return is_monotonous(not_(arg(f)), negated_variables); } else if (is_may(f)) { return is_monotonous(not_(arg(f)), negated_variables); } else if (is_must(f)) { return is_monotonous(not_(arg(f)), negated_variables); } else if (is_yaled_timed(f)) { return true; } else if (is_yaled(f)) { return true; } else if (is_delay_timed(f)) { return true; } else if (is_delay(f)) { return true; } else if (is_variable(f)) { return contains(negated_variables, name(f)); } else if (is_mu(f)) { std::set neg = negated_variables; core::identifier_string X = name(f); std::set::iterator i = neg.find(X); if (i != neg.end()) { neg.erase(i); } else { neg.insert(X); } return is_monotonous(not_(arg(f)), neg); } else if (is_nu(f)) { std::set neg = negated_variables; core::identifier_string X = name(f); std::set::iterator i = neg.find(X); if (i != neg.end()) { neg.erase(i); } else { neg.insert(X); } return is_monotonous(not_(arg(f)), neg); } } //--- handle everything except negations ---// if (data::is_data_expression(f)) { return true; } else if (is_true(f)) { return true; } else if (is_false(f)) { return true; } else if (is_and(f)) { return is_monotonous(left(f), negated_variables) && is_monotonous(right(f), negated_variables); } else if (is_or(f)) { return is_monotonous(left(f), negated_variables) && is_monotonous(right(f), negated_variables); } else if (is_imp(f)) { return is_monotonous(not_(left(f)), negated_variables) && is_monotonous(right(f), negated_variables); } else if (is_forall(f)) { return is_monotonous(arg(f), negated_variables); } else if (is_exists(f)) { return is_monotonous(arg(f), negated_variables); } else if (is_may(f)) { return is_monotonous(arg(f), negated_variables); } else if (is_must(f)) { return is_monotonous(arg(f), negated_variables); } else if (is_yaled_timed(f)) { return true; } else if (is_yaled(f)) { return true; } else if (is_delay_timed(f)) { return true; } else if (is_delay(f)) { return true; } else if (is_variable(f)) { return !contains(negated_variables, name(f)); } else if (is_mu(f)) { return is_monotonous(arg(f), negated_variables); } else if (is_nu(f)) { return is_monotonous(arg(f), negated_variables); } throw mcrl2::runtime_error(std::string("is_monotonous(state_formula) error: unknown argument ") + to_string(f)); return false; } /// \brief Returns true if the state formula is monotonous. /// \param f A modal formula /// \return True if the state formula is monotonous. inline bool is_monotonous(state_formula f) { std::set negated_variables; return is_monotonous(f, negated_variables); } } // namespace state_formulas } // namespace mcrl2 #endif // MCRL2_MODAL_FORMULA_MONOTONICITY_H mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/translate_user_notation.h000770 001750 001750 00000005741 12370120031 032533 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/translate_user_notation.h /// \brief add your file description here. #ifndef MCRL2_MODAL_FORMULA_TRANSLATE_USER_NOTATION_H #define MCRL2_MODAL_FORMULA_TRANSLATE_USER_NOTATION_H #include "mcrl2/data/translate_user_notation.h" #include "mcrl2/modal_formula/action_formula.h" #include "mcrl2/modal_formula/regular_formula.h" #include "mcrl2/modal_formula/state_formula.h" #include "mcrl2/modal_formula/builder.h" namespace mcrl2 { namespace action_formulas { template void translate_user_notation(T& x, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { core::make_update_apply_builder(data::detail::translate_user_notation_function())(x); } template T translate_user_notation(const T& x, typename std::enable_if< std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { return core::make_update_apply_builder(data::detail::translate_user_notation_function())(x); } } // namespace action_formulas namespace regular_formulas { template void translate_user_notation(T& x, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { core::make_update_apply_builder(data::detail::translate_user_notation_function())(x); } template T translate_user_notation(const T& x, typename std::enable_if< std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { return core::make_update_apply_builder(data::detail::translate_user_notation_function())(x); } } // namespace regular_formulas namespace state_formulas { template void translate_user_notation(T& x, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { core::make_update_apply_builder(data::detail::translate_user_notation_function())(x); } template T translate_user_notation(const T& x, typename std::enable_if< std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { return core::make_update_apply_builder(data::detail::translate_user_notation_function())(x); } } // namespace state_formulas } // namespace mcrl2 #endif // MCRL2_MODAL_FORMULA_TRANSLATE_USER_NOTATION_H mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/parse.h000770 001750 001750 00000035067 12401574564 026726 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/parse.h /// \brief add your file description here. #ifndef MCRL2_MODAL_FORMULA_PARSE_H #define MCRL2_MODAL_FORMULA_PARSE_H #include #include "mcrl2/core/parser_utility.h" #include "mcrl2/lps/parse.h" #include "mcrl2/modal_formula/typecheck.h" #include "mcrl2/modal_formula/state_formula.h" #include "mcrl2/modal_formula/translate_regular_formulas.h" #include "mcrl2/modal_formula/has_name_clashes.h" #include "mcrl2/modal_formula/resolve_name_clashes.h" namespace mcrl2 { namespace action_formulas { struct action_formula_actions: public lps::detail::multi_action_actions { action_formula_actions(const core::parser& parser_) : lps::detail::multi_action_actions(parser_) {} action_formulas::action_formula parse_ActFrm(const core::parse_node& node) { if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "MultAct")) { return action_formulas::untyped_multi_action(parse_ActionList(node.child(0))); } else if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "DataValExpr")) { return parse_DataValExpr(node.child(0)); } else if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "true")) { return action_formulas::true_(); } else if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "false")) { return action_formulas::false_(); } else if ((node.child_count() == 2) && (symbol_name(node.child(0)) == "!") && (symbol_name(node.child(1)) == "ActFrm")) { return action_formulas::not_(parse_ActFrm(node.child(1))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "ActFrm") && (node.child(1).string() == "=>") && (symbol_name(node.child(2)) == "ActFrm")) { return action_formulas::imp(parse_ActFrm(node.child(0)), parse_ActFrm(node.child(2))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "ActFrm") && (node.child(1).string() == "&&") && (symbol_name(node.child(2)) == "ActFrm")) { return action_formulas::and_(parse_ActFrm(node.child(0)), parse_ActFrm(node.child(2))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "ActFrm") && (node.child(1).string() == "||") && (symbol_name(node.child(2)) == "ActFrm")) { return action_formulas::or_(parse_ActFrm(node.child(0)), parse_ActFrm(node.child(2))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "forall") && (symbol_name(node.child(1)) == "VarsDeclList") && (symbol_name(node.child(2)) == ".") && (symbol_name(node.child(3)) == "ActFrm")) { return action_formulas::forall(parse_VarsDeclList(node.child(1)), parse_ActFrm(node.child(3))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "exists") && (symbol_name(node.child(1)) == "VarsDeclList") && (symbol_name(node.child(2)) == ".") && (symbol_name(node.child(3)) == "ActFrm")) { return action_formulas::exists(parse_VarsDeclList(node.child(1)), parse_ActFrm(node.child(3))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "ActFrm") && (node.child(1).string() == "@") && (symbol_name(node.child(2)) == "DataExpr")) { return action_formulas::at(parse_ActFrm(node.child(0)), parse_DataExpr(node.child(2))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "(") && (symbol_name(node.child(1)) == "ActFrm") && (symbol_name(node.child(2)) == ")")) { return parse_ActFrm(node.child(1)); } throw core::parse_node_unexpected_exception(m_parser, node); } }; inline action_formula parse_action_formula_new(const std::string& text) { core::parser p(parser_tables_mcrl2, core::detail::ambiguity_fn, core::detail::syntax_error_fn); unsigned int start_symbol_index = p.start_symbol_index("ActFrm"); bool partial_parses = false; core::parse_node node = p.parse(text, start_symbol_index, partial_parses); core::warn_and_or(node); action_formula result = action_formula_actions(p).parse_ActFrm(node); p.destroy_parse_node(node); return result; } } // namespace action_formulas namespace regular_formulas { struct regular_formula_actions: public action_formulas::action_formula_actions { regular_formula_actions(const core::parser& parser_) : action_formulas::action_formula_actions(parser_) {} regular_formulas::regular_formula parse_RegFrm(const core::parse_node& node) { if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "ActFrm")) { return parse_ActFrm(node.child(0)); } else if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "nil")) { return regular_formulas::nil(); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "(") && (symbol_name(node.child(1)) == "RegFrm") && (symbol_name(node.child(2)) == ")")) { return parse_RegFrm(node.child(1)); } else if ((node.child_count() == 2) && (symbol_name(node.child(0)) == "RegFrm") && (symbol_name(node.child(1)) == "*")) { return trans_or_nil(parse_RegFrm(node.child(0))); } else if ((node.child_count() == 2) && (symbol_name(node.child(0)) == "RegFrm") && (symbol_name(node.child(1)) == "+")) { return trans(parse_RegFrm(node.child(0))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "RegFrm") && (node.child(1).string() == ".") && (symbol_name(node.child(2)) == "RegFrm")) { return seq(parse_RegFrm(node.child(0)), parse_RegFrm(node.child(2))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "RegFrm") && (node.child(1).string() == "+") && (symbol_name(node.child(2)) == "RegFrm")) { return alt(parse_RegFrm(node.child(0)), parse_RegFrm(node.child(2))); } throw core::parse_node_unexpected_exception(m_parser, node); } }; inline regular_formula parse_regular_formula_new(const std::string& text) { core::parser p(parser_tables_mcrl2, core::detail::ambiguity_fn, core::detail::syntax_error_fn); unsigned int start_symbol_index = p.start_symbol_index("RegFrm"); bool partial_parses = false; core::parse_node node = p.parse(text, start_symbol_index, partial_parses); regular_formula result = regular_formula_actions(p).parse_RegFrm(node); p.destroy_parse_node(node); return result; } } // namespace regular_formulas namespace state_formulas { struct state_formula_actions: public regular_formulas::regular_formula_actions { state_formula_actions(const core::parser& parser_) : regular_formulas::regular_formula_actions(parser_) {} state_formula make_delay(const core::parse_node& node) { if (node.child(0)) { return delay_timed(parse_DataExpr(node.child(0).child(1))); } else { return delay(); } } state_formula make_yaled(const core::parse_node& node) { if (node.child(0)) { return yaled_timed(parse_DataExpr(node.child(0).child(1))); } else { return yaled(); } } data::assignment parse_StateVarAssignment(const core::parse_node& node) { return data::assignment(data::variable(parse_Id(node.child(0)), parse_SortExpr(node.child(2))), parse_DataExpr(node.child(4))); } data::assignment_list parse_StateVarAssignmentList(const core::parse_node& node) { return parse_list(node, "StateVarAssignment", boost::bind(&state_formula_actions::parse_StateVarAssignment, this, _1)); } state_formulas::state_formula parse_StateFrm(const core::parse_node& node) { if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "DataValExpr")) { return parse_DataValExpr(node.child(0)); } else if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "true")) { return state_formulas::true_(); } else if ((node.child_count() == 1) && (symbol_name(node.child(0)) == "false")) { return state_formulas::false_(); } else if ((node.child_count() == 2) && (symbol_name(node.child(0)) == "!") && (symbol_name(node.child(1)) == "StateFrm")) { return state_formulas::not_(parse_StateFrm(node.child(1))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "StateFrm") && (node.child(1).string() == "=>") && (symbol_name(node.child(2)) == "StateFrm")) { return state_formulas::imp(parse_StateFrm(node.child(0)), parse_StateFrm(node.child(2))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "StateFrm") && (node.child(1).string() == "&&") && (symbol_name(node.child(2)) == "StateFrm")) { return state_formulas::and_(parse_StateFrm(node.child(0)), parse_StateFrm(node.child(2))); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "StateFrm") && (node.child(1).string() == "||") && (symbol_name(node.child(2)) == "StateFrm")) { return state_formulas::or_(parse_StateFrm(node.child(0)), parse_StateFrm(node.child(2))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "forall") && (symbol_name(node.child(1)) == "VarsDeclList") && (symbol_name(node.child(2)) == ".") && (symbol_name(node.child(3)) == "StateFrm")) { return state_formulas::forall(parse_VarsDeclList(node.child(1)), parse_StateFrm(node.child(3))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "exists") && (symbol_name(node.child(1)) == "VarsDeclList") && (symbol_name(node.child(2)) == ".") && (symbol_name(node.child(3)) == "StateFrm")) { return state_formulas::exists(parse_VarsDeclList(node.child(1)), parse_StateFrm(node.child(3))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "[") && (symbol_name(node.child(1)) == "RegFrm") && (symbol_name(node.child(2)) == "]") && (symbol_name(node.child(3)) == "StateFrm")) { return state_formulas::must(parse_RegFrm(node.child(1)), parse_StateFrm(node.child(3))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "<") && (symbol_name(node.child(1)) == "RegFrm") && (symbol_name(node.child(2)) == ">") && (symbol_name(node.child(3)) == "StateFrm")) { return state_formulas::may(parse_RegFrm(node.child(1)), parse_StateFrm(node.child(3))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "mu") && (symbol_name(node.child(1)) == "StateVarDecl") && (symbol_name(node.child(2)) == ".") && (symbol_name(node.child(3)) == "StateFrm")) { return state_formulas::mu(parse_Id(node.child(1).child(0)), parse_StateVarAssignmentList(node.child(1).child(1)), parse_StateFrm(node.child(3))); } else if ((node.child_count() == 4) && (symbol_name(node.child(0)) == "nu") && (symbol_name(node.child(1)) == "StateVarDecl") && (symbol_name(node.child(2)) == ".") && (symbol_name(node.child(3)) == "StateFrm")) { return state_formulas::nu(parse_Id(node.child(1).child(0)), parse_StateVarAssignmentList(node.child(1).child(1)), parse_StateFrm(node.child(3))); } else if ((node.child_count() == 2) && (symbol_name(node.child(0)) == "Id")) { return state_formulas::variable(parse_Id(node.child(0)), parse_DataExprList(node.child(1))); } else if ((node.child_count() == 2) && (symbol_name(node.child(0)) == "delay")) { return make_delay(node.child(1)); } else if ((node.child_count() == 2) && (symbol_name(node.child(0)) == "yaled")) { return make_yaled(node.child(1)); } else if ((node.child_count() == 3) && (symbol_name(node.child(0)) == "(") && (symbol_name(node.child(1)) == "StateFrm") && (symbol_name(node.child(2)) == ")")) { return parse_StateFrm(node.child(1)); } throw core::parse_node_unexpected_exception(m_parser, node); } }; inline state_formula parse_state_formula_new(const std::string& text) { core::parser p(parser_tables_mcrl2, core::detail::ambiguity_fn, core::detail::syntax_error_fn); unsigned int start_symbol_index = p.start_symbol_index("StateFrm"); bool partial_parses = false; core::parse_node node = p.parse(text, start_symbol_index, partial_parses); core::warn_and_or(node); state_formula result = state_formula_actions(p).parse_StateFrm(node); p.destroy_parse_node(node); return result; } inline void complete_state_formula(state_formula& x, lps::specification& spec, bool check_monotonicity = true, bool translate_regular = true) { type_check(x, spec, check_monotonicity); if (translate_regular) { mCRL2log(log::debug) << "formula before translating regular formulas: " << x << std::endl; x = translate_regular_formulas(x); mCRL2log(log::debug) << "formula after translating regular formulas: " << x << std::endl; } spec.data().add_context_sorts(state_formulas::find_sort_expressions(x)); x = state_formulas::translate_user_notation(x); x = state_formulas::normalize_sorts(x, spec.data()); if (check_monotonicity && state_formulas::has_name_clashes(x)) { mCRL2log(log::debug) << "formula before resolving name clashes: " << x << std::endl; x = state_formulas::resolve_name_clashes(x); mCRL2log(log::debug) << "formula after resolving name clashes: " << x << std::endl; } } /// \brief Parses a state formula from an input stream // spec may be updated as the data implementation of the state formula // may cause internal names to change. /// \param formula_stream A stream from which can be read /// \param spec A linear process specification /// \param check_monotonicity If true, an exception will be thrown if the formula is not monotonous. Furthermore, name clashes are resolved. /// \return The converted modal formula inline state_formula parse_state_formula(std::istream& in, lps::specification& spec, bool check_monotonicity = true, bool translate_regular = true) { std::string text = utilities::read_text(in); state_formula result = parse_state_formula_new(text); if (find_nil(result)) { throw mcrl2::runtime_error("regular formulas containing nil are unsupported!"); } complete_state_formula(result, spec, check_monotonicity, translate_regular); return result; } /// \brief Parses a state formula from text // spec may be updated as the data implementation of the state formula // may cause internal names to change. /// \param formula_text A string /// \param spec A linear process specification /// \return The converted modal formula inline state_formula parse_state_formula(const std::string& formula_text, lps::specification& spec, bool check_monotonicity = true, bool translate_regular = true) { std::stringstream formula_stream(formula_text); return parse_state_formula(formula_stream, spec, check_monotonicity, translate_regular); } } // namespace state_formulas } // namespace mcrl2 #endif // MCRL2_MODAL_FORMULA_PARSE_H mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/normalize_sorts.h000770 001750 001750 00000006246 12370120031 031020 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/normalize_sorts.h /// \brief add your file description here. #ifndef MCRL2_MODAL_FORMULA_NORMALIZE_SORTS_H #define MCRL2_MODAL_FORMULA_NORMALIZE_SORTS_H #include "mcrl2/data/normalize_sorts.h" #include "mcrl2/modal_formula/action_formula.h" #include "mcrl2/modal_formula/regular_formula.h" #include "mcrl2/modal_formula/state_formula.h" #include "mcrl2/modal_formula/builder.h" namespace mcrl2 { namespace action_formulas { template void normalize_sorts(T& x, const data::data_specification& data_spec, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { core::make_update_apply_builder(data::detail::normalize_sorts_function(data_spec))(x); } template T normalize_sorts(const T& x, const data::data_specification& data_spec, typename std::enable_if< std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { return core::make_update_apply_builder(data::detail::normalize_sorts_function(data_spec))(x); } } // namespace action_formulas namespace regular_formulas { template void normalize_sorts(T& x, const data::data_specification& data_spec, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { core::make_update_apply_builder(data::detail::normalize_sorts_function(data_spec))(x); } template T normalize_sorts(const T& x, const data::data_specification& data_spec, typename std::enable_if< std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { return core::make_update_apply_builder(data::detail::normalize_sorts_function(data_spec))(x); } } // namespace regular_formulas namespace state_formulas { template void normalize_sorts(T& x, const data::data_specification& data_spec, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { core::make_update_apply_builder(data::detail::normalize_sorts_function(data_spec))(x); } template T normalize_sorts(const T& x, const data::data_specification& data_spec, typename std::enable_if< std::is_base_of< atermpp::aterm, T >::value>::type* = 0 ) { return core::make_update_apply_builder(data::detail::normalize_sorts_function(data_spec))(x); } } // namespace state_formulas } // namespace mcrl2 #endif // MCRL2_MODAL_FORMULA_NORMALIZE_SORTS_H mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/print.h000770 001750 001750 00000025211 12370120031 026713 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/print.h /// \brief add your file description here. #ifndef MCRL2_MODAL_FORMULA_PRINT_H #define MCRL2_MODAL_FORMULA_PRINT_H #include "mcrl2/core/print.h" #include "mcrl2/modal_formula/traverser.h" #include "mcrl2/lps/print.h" namespace mcrl2 { namespace action_formulas { using core::detail::precedences::max_precedence; namespace detail { template struct printer: public action_formulas::add_traverser_sort_expressions { typedef action_formulas::add_traverser_sort_expressions super; using super::enter; using super::leave; using super::operator(); using super::print_unary_operation; using super::print_binary_operation; using super::print_abstraction; using super::print_expression; using super::print_list; Derived& derived() { return static_cast(*this); } void operator()(const action_formulas::true_& x) { derived().enter(x); derived().print("true"); derived().leave(x); } void operator()(const action_formulas::false_& x) { derived().enter(x); derived().print("false"); derived().leave(x); } void operator()(const action_formulas::not_& x) { derived().enter(x); print_unary_operation(x, "!"); derived().leave(x); } void operator()(const action_formulas::and_& x) { derived().enter(x); print_binary_operation(x, " && "); derived().leave(x); } void operator()(const action_formulas::or_& x) { derived().enter(x); print_binary_operation(x, " || "); derived().leave(x); } void operator()(const action_formulas::imp& x) { derived().enter(x); print_binary_operation(x, " => "); derived().leave(x); } void operator()(const action_formulas::forall& x) { derived().enter(x); print_abstraction(x, "forall"); derived().leave(x); } void operator()(const action_formulas::exists& x) { derived().enter(x); print_abstraction(x, "exists"); derived().leave(x); } void operator()(const action_formulas::at& x) { derived().enter(x); derived()(x.operand()); derived().print(" @ "); print_expression(x.time_stamp(), max_precedence); derived().leave(x); } void operator()(const action_formulas::multi_action& x) { derived().enter(x); if (x.actions().empty()) { derived().print("tau"); } else { print_list(x.actions(), "", "", "|"); } derived().leave(x); } void operator()(const action_formulas::untyped_multi_action& x) { derived().enter(x); if (x.arguments().empty()) { derived().print("tau"); } else { print_list(x.arguments(), "", "", "|"); } derived().leave(x); } }; } // namespace detail /// \brief Prints the object t to a stream. template void pp(const T& t, std::ostream& out) { core::detail::apply_printer printer(out); printer(t); } /// \brief Returns a string representation of the object t. template std::string pp(const T& t) { std::ostringstream out; action_formulas::pp(t, out); return out.str(); } } // namespace action_formulas namespace regular_formulas { using core::detail::precedences::max_precedence; namespace detail { template struct printer: public regular_formulas::add_traverser_sort_expressions { typedef regular_formulas::add_traverser_sort_expressions super; using super::enter; using super::leave; using super::operator(); using super::print_unary_operation; using super::print_binary_operation; using super::print_expression; Derived& derived() { return static_cast(*this); } void operator()(const regular_formulas::nil& x) { derived().enter(x); derived().leave(x); } void operator()(const regular_formulas::seq& x) { derived().enter(x); print_binary_operation(x, " . "); derived().leave(x); } void operator()(const regular_formulas::alt& x) { derived().enter(x); print_binary_operation(x, " + "); derived().leave(x); } void operator()(const regular_formulas::trans& x) { derived().enter(x); print_expression(x.operand(), left_precedence(x)); derived().print("+"); derived().leave(x); } void operator()(const regular_formulas::trans_or_nil& x) { derived().enter(x); print_expression(x.operand(), left_precedence(x)); derived().print("*"); derived().leave(x); } }; } // namespace detail /// \brief Prints the object t to a stream. template void pp(const T& t, std::ostream& out) { core::detail::apply_printer printer(out); printer(t); } /// \brief Returns a string representation of the object t. template std::string pp(const T& t) { std::ostringstream out; regular_formulas::pp(t, out); return out.str(); } } // namespace regular_formulas namespace state_formulas { using core::detail::precedences::max_precedence; namespace detail { template struct printer: public state_formulas::add_traverser_sort_expressions { typedef state_formulas::add_traverser_sort_expressions super; using super::enter; using super::leave; using super::operator(); using super::print_unary_operation; using super::print_binary_operation; using super::print_abstraction; using super::print_variables; using super::print_expression; using super::print_list; // Determines whether or not data expressions should be wrapped inside 'val'. std::vector val; void disable_val() { val.push_back(false); } void enable_val() { assert(!val.empty()); val.pop_back(); } Derived& derived() { return static_cast(*this); } void operator()(const data::data_expression& x) { bool print_val = val.empty(); derived().enter(x); if (print_val) { disable_val(); derived().print("val("); } super::operator()(x); if (print_val) { derived().print(")"); enable_val(); } derived().leave(x); } void operator()(const state_formulas::true_& x) { derived().enter(x); derived().print("true"); derived().leave(x); } void operator()(const state_formulas::false_& x) { derived().enter(x); derived().print("false"); derived().leave(x); } void operator()(const state_formulas::not_& x) { derived().enter(x); print_unary_operation(x, "!"); derived().leave(x); } void operator()(const state_formulas::and_& x) { derived().enter(x); print_binary_operation(x, " && "); derived().leave(x); } void operator()(const state_formulas::or_& x) { derived().enter(x); print_binary_operation(x, " || "); derived().leave(x); } void operator()(const state_formulas::imp& x) { derived().enter(x); print_binary_operation(x, " => "); derived().leave(x); } void operator()(const state_formulas::forall& x) { derived().enter(x); print_abstraction(x, "forall"); derived().leave(x); } void operator()(const state_formulas::exists& x) { derived().enter(x); print_abstraction(x, "exists"); derived().leave(x); } void operator()(const state_formulas::must& x) { derived().enter(x); derived().print("["); disable_val(); derived()(x.formula()); enable_val(); derived().print("]"); derived()(x.operand()); derived().leave(x); } void operator()(const state_formulas::may& x) { derived().enter(x); derived().print("<"); disable_val(); derived()(x.formula()); enable_val(); derived().print(">"); derived()(x.operand()); derived().leave(x); } void operator()(const state_formulas::yaled& x) { derived().enter(x); derived().print("yaled"); derived().leave(x); } void operator()(const state_formulas::yaled_timed& x) { disable_val(); derived().enter(x); derived().print("yaled"); derived().print(" @ "); derived()(x.time_stamp()); derived().leave(x); enable_val(); } void operator()(const state_formulas::delay& x) { derived().enter(x); derived().print("delay"); derived().leave(x); } void operator()(const state_formulas::delay_timed& x) { disable_val(); derived().enter(x); derived().print("delay"); derived().print(" @ "); derived()(x.time_stamp()); derived().leave(x); enable_val(); } void operator()(const state_formulas::variable& x) { disable_val(); derived().enter(x); derived()(x.name()); print_list(x.arguments(), "(", ")", ", ", false); derived().leave(x); enable_val(); } // TODO: merge this function with the version in data/print.h (?) void print_assignments(const data::assignment_list& assignments) { disable_val(); if (assignments.empty()) { return; } derived().print("("); for (auto i = assignments.begin(); i != assignments.end(); ++i) { if (i != assignments.begin()) { derived().print(", "); } derived()(i->lhs()); derived().print(": "); derived()(i->lhs().sort()); derived().print(" = "); derived()(i->rhs()); } derived().print(")"); enable_val(); } void operator()(const state_formulas::nu& x) { derived().enter(x); derived().print("nu "); derived()(x.name()); print_assignments(x.assignments()); derived().print(". "); derived()(x.operand()); derived().leave(x); } void operator()(const state_formulas::mu& x) { derived().enter(x); derived().print("mu "); derived()(x.name()); print_assignments(x.assignments()); derived().print(". "); derived()(x.operand()); derived().leave(x); } }; } // namespace detail /// \brief Prints the object t to a stream. template void pp(const T& t, std::ostream& out) { core::detail::apply_printer printer(out); printer(t); } /// \brief Returns a string representation of the object t. template std::string pp(const T& t) { std::ostringstream out; state_formulas::pp(t, out); return out.str(); } } // namespace state_formulas } // namespace mcrl2 #endif // MCRL2_MODAL_FORMULA_PRINT_H mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/preprocess_state_formula.h000770 001750 001750 00000005354 12370120031 032677 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/preprocess_state_formula.h /// \brief add your file description here. #ifndef MCRL2_MODAL_FORMULA_PREPROCESS_STATE_FORMULA_H #define MCRL2_MODAL_FORMULA_PREPROCESS_STATE_FORMULA_H #include "mcrl2/atermpp/make_list.h" #include "mcrl2/data/detail/find.h" #include "mcrl2/data/utility.h" #include "mcrl2/data/set_identifier_generator.h" #include "mcrl2/data/xyz_identifier_generator.h" #include "mcrl2/lps/specification.h" #include "mcrl2/modal_formula/state_formula.h" #include "mcrl2/modal_formula/state_formula_rename.h" #include "mcrl2/modal_formula/detail/state_formula_accessors.h" namespace mcrl2 { namespace state_formulas { /// \brief Renames data variables and predicate variables in the formula \p f, and /// wraps the formula inside a 'nu' if needed. This is needed as a preprocessing /// step for the algorithm. /// \param formula A modal formula /// \param spec A linear process specification /// \return The preprocessed formula inline state_formulas::state_formula preprocess_state_formula(const state_formulas::state_formula& formula, const lps::specification& spec) { // using namespace state_formulas::detail::accessors; namespace s = state_formulas; state_formulas::state_formula f = formula; std::set formula_variable_names = data::detail::variable_names(state_formulas::find_all_variables(formula)); std::set spec_variable_names = data::detail::variable_names(lps::find_all_variables(spec)); std::set spec_names = lps::find_identifiers(spec); // rename data variables in f, to prevent name clashes with data variables in spec f = state_formulas::rename_variables(f, spec_variable_names); // rename predicate variables in f, to prevent name clashes data::xyz_identifier_generator xyz_generator; xyz_generator.add_identifiers(spec_names); xyz_generator.add_identifiers(formula_variable_names); f = rename_predicate_variables(f, xyz_generator); // wrap the formula inside a 'nu' if needed if (!s::is_mu(f) && !s::is_nu(f)) { data::set_identifier_generator generator; generator.add_identifiers(state_formulas::find_identifiers(f)); generator.add_identifiers(lps::find_identifiers(spec)); core::identifier_string X = generator("X"); f = s::nu(X, data::assignment_list(), f); } return f; } } // namespace state_formulas } // namespace mcrl2 #endif // MCRL2_MODAL_FORMULA_PREPROCESS_STATE_FORMULA_H mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/state_formula_rename.h000770 001750 001750 00000016061 12370120031 031756 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/state_formula_rename.h /// \brief Add your file description here. #ifndef MCRL2_MODAL_STATE_VARIABLE_RENAME_H #define MCRL2_MODAL_STATE_VARIABLE_RENAME_H #include #include "mcrl2/data/replace.h" #include "mcrl2/modal_formula/state_formula.h" #include "mcrl2/modal_formula/builder.h" #include "mcrl2/modal_formula/replace.h" #include "mcrl2/utilities/number_postfix_generator.h" #include "mcrl2/utilities/detail/container_utility.h" namespace mcrl2 { namespace state_formulas { /// Visitor that renames predicate variables using the specified identifier generator. /// \post In the generated formula, all predicate variables have different names. template struct state_formula_predicate_variable_rename_builder: public state_formulas::state_formula_builder > { typedef state_formulas::state_formula_builder > super; using super::enter; using super::leave; using super::operator(); /// \brief An identifier generator IdentifierGenerator& generator; /// \brief A stack of replacements. It may contain pairs with identical values. std::deque > replacements; /// \brief Constructor /// \param generator A generator for fresh identifiers state_formula_predicate_variable_rename_builder(IdentifierGenerator& generator) : generator(generator) {} /// \brief Generates a new name for n, and adds a replacement to the replacement stack. /// \param n A /// \return The new name. core::identifier_string push(const core::identifier_string& n) { core::identifier_string new_name = generator(n); replacements.push_front(std::make_pair(n, new_name)); return new_name; } /// \brief Removes the last added replacement. void pop() { replacements.pop_front(); } /// \brief Visit var node /// \param e A modal formula /// \param n A /// \param l A sequence of data expressions /// \return The result of visiting the node state_formula operator()(const variable& x) { core::identifier_string new_name = x.name(); for (std::deque >::iterator i = replacements.begin(); i != replacements.end(); ++i) { if (i->first == x.name()) { new_name = i->second; break; } } return variable(new_name, x.arguments()); } /// \brief Visit mu node /// \param e A modal formula /// \param n A /// \param a A sequence of assignments to data variables /// \param f A modal formula /// \return The result of visiting the node state_formula operator()(const mu& x) { core::identifier_string new_name = push(x.name()); state_formula new_formula = (*this)(x.operand()); pop(); return mu(new_name, x.assignments(), new_formula); } /// \brief Visit nu node /// \param e A modal formula /// \param n A /// \param a A sequence of assignments to data variables /// \param f A modal formula /// \return The result of visiting the node state_formula operator()(const nu& x) { core::identifier_string new_name = push(x.name()); state_formula new_formula = (*this)(x.operand()); pop(); return nu(new_name, x.assignments(), new_formula); } #ifdef BOOST_MSVC #include "mcrl2/core/detail/builder_msvc.inc.h" #endif }; /// \brief Utility function for creating a state_formula_predicate_variable_rename_builder. /// \param generator A generator for fresh identifiers /// \return a state_formula_predicate_variable_rename_builder template state_formula_predicate_variable_rename_builder make_state_formula_predicate_variable_rename_builder(IdentifierGenerator& generator) { return state_formula_predicate_variable_rename_builder(generator); } /// \brief Renames predicate variables of the formula f using the specified identifier generator. /// \post predicate variables within the same scope have different names /// \param f A modal formula /// \param generator A generator for fresh identifiers /// \return The rename result template state_formula rename_predicate_variables(const state_formula& f, IdentifierGenerator& generator) { return make_state_formula_predicate_variable_rename_builder(generator)(f); } /// Visitor that renames variables using the specified identifier generator. Also bound variables are renamed! struct state_formula_variable_rename_builder: public state_formulas::sort_expression_builder { typedef state_formulas::sort_expression_builder super; using super::enter; using super::leave; using super::operator(); /// \brief The set of identifiers that may not be used as a variable name. const std::set& forbidden_identifiers; std::map generated_identifiers; utilities::number_postfix_generator generator; core::identifier_string create_name(const core::identifier_string& x) { std::map::iterator i = generated_identifiers.find(x); if (i != generated_identifiers.end()) { return i->second; } std::string name = generator(std::string(x)); generated_identifiers[x] = core::identifier_string(name); return core::identifier_string(name); } /// \brief Constructor state_formula_variable_rename_builder(const std::set& forbidden_identifiers_) : forbidden_identifiers(forbidden_identifiers_) { for (std::set::const_iterator i = forbidden_identifiers.begin(); i != forbidden_identifiers.end(); ++i) { generator.add_identifier(std::string(*i)); } } // do not traverse sorts data::sort_expression operator()(const data::sort_expression& x) { return x; } data::variable operator()(const data::variable& x) { using utilities::detail::contains; if (!contains(forbidden_identifiers, x.name())) { return x; } return data::variable(create_name(x.name()), x.sort()); } #ifdef BOOST_MSVC #include "mcrl2/core/detail/builder_msvc.inc.h" #endif }; /// \brief Renames all data variables in the formula f such that the forbidden identifiers are not used /// \param f A modal formula /// \return The rename result inline state_formula rename_variables(const state_formula& f, const std::set& forbidden_identifiers) { return state_formula_variable_rename_builder(forbidden_identifiers)(f); } } // namespace state_formulas } // namespace mcrl2 #endif // MCRL2_MODAL_STATE_VARIABLE_RENAME_H mcrl2-201409.0/libraries/modal_formula/include/mcrl2/modal_formula/find.h000770 001750 001750 00000056003 12370120032 026503 0ustar00outisoutis000000 000000 // Author(s): Wieger Wesselink // Copyright: see the accompanying file COPYING or copy at // https://svn.win.tue.nl/trac/MCRL2/browser/trunk/COPYING // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // /// \file mcrl2/modal_formula/find.h /// \brief add your file description here. #ifndef MCRL2_MODAL_FORMULA_FIND_H #define MCRL2_MODAL_FORMULA_FIND_H #include "mcrl2/data/find.h" #include "mcrl2/data/variable.h" #include "mcrl2/modal_formula/traverser.h" #include "mcrl2/modal_formula/add_binding.h" namespace mcrl2 { namespace action_formulas { //--- start generated action_formulas find code ---// /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are written. /// \return All variables that occur in the term x template void find_all_variables(const T& x, OutputIterator o) { data::detail::make_find_all_variables_traverser(o)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \return All variables that occur in the object x template std::set find_all_variables(const T& x) { std::set result; action_formulas::find_all_variables(x, std::inserter(result, result.end())); return result; } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are added. /// \return All free variables that occur in the object x template void find_free_variables(const T& x, OutputIterator o) { data::detail::make_find_free_variables_traverser(o)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are written. /// \param[in] bound a container of variables /// \return All free variables that occur in the object x template void find_free_variables_with_bound(const T& x, OutputIterator o, const VariableContainer& bound) { data::detail::make_find_free_variables_traverser(o, bound)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \return All free variables that occur in the object x template std::set find_free_variables(const T& x) { std::set result; action_formulas::find_free_variables(x, std::inserter(result, result.end())); return result; } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in] bound a bound a container of variables /// \return All free variables that occur in the object x template std::set find_free_variables_with_bound(const T& x, VariableContainer const& bound) { std::set result; action_formulas::find_free_variables_with_bound(x, std::inserter(result, result.end()), bound); return result; } /// \brief Returns all identifiers that occur in an object /// \param[in] x an object containing identifiers /// \param[in,out] o an output iterator to which all identifiers occurring in x are written. /// \return All identifiers that occur in the term x template void find_identifiers(const T& x, OutputIterator o) { data::detail::make_find_identifiers_traverser(o)(x); } /// \brief Returns all identifiers that occur in an object /// \param[in] x an object containing identifiers /// \return All identifiers that occur in the object x template std::set find_identifiers(const T& x) { std::set result; action_formulas::find_identifiers(x, std::inserter(result, result.end())); return result; } /// \brief Returns all sort expressions that occur in an object /// \param[in] x an object containing sort expressions /// \param[in,out] o an output iterator to which all sort expressions occurring in x are written. /// \return All sort expressions that occur in the term x template void find_sort_expressions(const T& x, OutputIterator o) { data::detail::make_find_sort_expressions_traverser(o)(x); } /// \brief Returns all sort expressions that occur in an object /// \param[in] x an object containing sort expressions /// \return All sort expressions that occur in the object x template std::set find_sort_expressions(const T& x) { std::set result; action_formulas::find_sort_expressions(x, std::inserter(result, result.end())); return result; } /// \brief Returns all function symbols that occur in an object /// \param[in] x an object containing function symbols /// \param[in,out] o an output iterator to which all function symbols occurring in x are written. /// \return All function symbols that occur in the term x template void find_function_symbols(const T& x, OutputIterator o) { data::detail::make_find_function_symbols_traverser(o)(x); } /// \brief Returns all function symbols that occur in an object /// \param[in] x an object containing function symbols /// \return All function symbols that occur in the object x template std::set find_function_symbols(const T& x) { std::set result; action_formulas::find_function_symbols(x, std::inserter(result, result.end())); return result; } //--- end generated action_formulas find code ---// } // namespace action_formulas namespace regular_formulas { //--- start generated regular_formulas find code ---// /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are written. /// \return All variables that occur in the term x template void find_all_variables(const T& x, OutputIterator o) { data::detail::make_find_all_variables_traverser(o)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \return All variables that occur in the object x template std::set find_all_variables(const T& x) { std::set result; regular_formulas::find_all_variables(x, std::inserter(result, result.end())); return result; } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are added. /// \return All free variables that occur in the object x template void find_free_variables(const T& x, OutputIterator o) { data::detail::make_find_free_variables_traverser(o)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are written. /// \param[in] bound a container of variables /// \return All free variables that occur in the object x template void find_free_variables_with_bound(const T& x, OutputIterator o, const VariableContainer& bound) { data::detail::make_find_free_variables_traverser(o, bound)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \return All free variables that occur in the object x template std::set find_free_variables(const T& x) { std::set result; regular_formulas::find_free_variables(x, std::inserter(result, result.end())); return result; } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in] bound a bound a container of variables /// \return All free variables that occur in the object x template std::set find_free_variables_with_bound(const T& x, VariableContainer const& bound) { std::set result; regular_formulas::find_free_variables_with_bound(x, std::inserter(result, result.end()), bound); return result; } /// \brief Returns all identifiers that occur in an object /// \param[in] x an object containing identifiers /// \param[in,out] o an output iterator to which all identifiers occurring in x are written. /// \return All identifiers that occur in the term x template void find_identifiers(const T& x, OutputIterator o) { data::detail::make_find_identifiers_traverser(o)(x); } /// \brief Returns all identifiers that occur in an object /// \param[in] x an object containing identifiers /// \return All identifiers that occur in the object x template std::set find_identifiers(const T& x) { std::set result; regular_formulas::find_identifiers(x, std::inserter(result, result.end())); return result; } /// \brief Returns all sort expressions that occur in an object /// \param[in] x an object containing sort expressions /// \param[in,out] o an output iterator to which all sort expressions occurring in x are written. /// \return All sort expressions that occur in the term x template void find_sort_expressions(const T& x, OutputIterator o) { data::detail::make_find_sort_expressions_traverser(o)(x); } /// \brief Returns all sort expressions that occur in an object /// \param[in] x an object containing sort expressions /// \return All sort expressions that occur in the object x template std::set find_sort_expressions(const T& x) { std::set result; regular_formulas::find_sort_expressions(x, std::inserter(result, result.end())); return result; } /// \brief Returns all function symbols that occur in an object /// \param[in] x an object containing function symbols /// \param[in,out] o an output iterator to which all function symbols occurring in x are written. /// \return All function symbols that occur in the term x template void find_function_symbols(const T& x, OutputIterator o) { data::detail::make_find_function_symbols_traverser(o)(x); } /// \brief Returns all function symbols that occur in an object /// \param[in] x an object containing function symbols /// \return All function symbols that occur in the object x template std::set find_function_symbols(const T& x) { std::set result; regular_formulas::find_function_symbols(x, std::inserter(result, result.end())); return result; } //--- end generated regular_formulas find code ---// } // namespace regular_formulas namespace state_formulas { //--- start generated state_formulas find code ---// /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are written. /// \return All variables that occur in the term x template void find_all_variables(const T& x, OutputIterator o) { data::detail::make_find_all_variables_traverser(o)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \return All variables that occur in the object x template std::set find_all_variables(const T& x) { std::set result; state_formulas::find_all_variables(x, std::inserter(result, result.end())); return result; } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are added. /// \return All free variables that occur in the object x template void find_free_variables(const T& x, OutputIterator o) { data::detail::make_find_free_variables_traverser(o)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in,out] o an output iterator to which all variables occurring in x are written. /// \param[in] bound a container of variables /// \return All free variables that occur in the object x template void find_free_variables_with_bound(const T& x, OutputIterator o, const VariableContainer& bound) { data::detail::make_find_free_variables_traverser(o, bound)(x); } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \return All free variables that occur in the object x template std::set find_free_variables(const T& x) { std::set result; state_formulas::find_free_variables(x, std::inserter(result, result.end())); return result; } /// \brief Returns all variables that occur in an object /// \param[in] x an object containing variables /// \param[in] bound a bound a container of variables /// \return All free variables that occur in the object x template std::set find_free_variables_with_bound(const T& x, VariableContainer const& bound) { std::set result; state_formulas::find_free_variables_with_bound(x, std::inserter(result, result.end()), bound); return result; } /// \brief Returns all identifiers that occur in an object /// \param[in] x an object containing identifiers /// \param[in,out] o an output iterator to which all identifiers occurring in x are written. /// \return All identifiers that occur in the term x template void find_identifiers(const T& x, OutputIterator o) { data::detail::make_find_identifiers_traverser(o)(x); } /// \brief Returns all identifiers that occur in an object /// \param[in] x an object containing identifiers /// \return All identifiers that occur in the object x template std::set find_identifiers(const T& x) { std::set result; state_formulas::find_identifiers(x, std::inserter(result, result.end())); return result; } /// \brief Returns all sort expressions that occur in an object /// \param[in] x an object containing sort expressions /// \param[in,out] o an output iterator to which all sort expressions occurring in x are written. /// \return All sort expressions that occur in the term x template void find_sort_expressions(const T& x, OutputIterator o) { data::detail::make_find_sort_expressions_traverser(o)(x); } /// \brief Returns all sort expressions that occur in an object /// \param[in] x an object containing sort expressions /// \return All sort expressions that occur in the object x template std::set find_sort_expressions(const T& x) { std::set result; state_formulas::find_sort_expressions(x, std::inserter(result, result.end())); return result; } /// \brief Returns all function symbols that occur in an object /// \param[in] x an object containing function symbols /// \param[in,out] o an output iterator to which all function symbols occurring in x are written. /// \return All function symbols that occur in the term x template void find_function_symbols(const T& x, OutputIterator o) { data::detail::make_find_function_symbols_traverser(o)(x); } /// \brief Returns all function symbols that occur in an object /// \param[in] x an object containing function symbols /// \return All function symbols that occur in the object x template std::set find_function_symbols(const T& x) { std::set result; state_formulas::find_function_symbols(x, std::inserter(result, result.end())); return result; } //--- end generated state_formulas find code ---// namespace detail { /// \cond INTERNAL_DOCS struct nil_traverser: public state_formulas::regular_formula_traverser { typedef state_formulas::regular_formula_traverser super; using super::enter; using super::leave; using super::operator(); bool result; nil_traverser() : result(false) {} void operator()(const regular_formulas::nil&) { result = true; } }; // collects state variable names in a set struct state_variable_name_traverser: public state_formulas::state_formula_traverser { typedef state_formulas::state_formula_traverser super; using super::enter; using super::leave; using super::operator(); std::set names; void operator()(const state_formulas::variable& x) { names.insert(x.name()); } }; template