0

My professor decide to give us math student a code to change into NuSMV and i can't seem to find anywhere else for help and i read the textbook it like 6 pages only and only describe what certain property does. Module main is an example of NuSMV code and he said to use that format example to write the psuedo code. I don't know how to write the while loop and set what to be true? and would flag1 be a state and turn be also another state?

 while(true) do
  flag1 := true
    while flag2 do
     if turn=2
       flag1 := false;
       wait until turn = 1;
       flag1 := true
  Critical section
  turn := 2
  flag1 := false;
Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40
Darkflame
  • 79
  • 2
  • 11

1 Answers1

1

It looks like you're trying to model Dekker/Dijkstra's algorithm for mutual exclusion among two processes.

The steps of your interest, based on your question, should only be 1-4. I added some more to provide a more complete picture of what can be achieved with NuSMV.

I used a slightly different version of the same algorithm, though the underlying idea is the same.


IDEA: there exists a methodology for converting pseudo-code into a NuSMV model:

  1. Label the entry and exit point of each statement in your code:

    --     void p(iflag, turn, id) {
    -- l0:   while(true) do
    -- l1:     flag := true
    -- l2:     while iflag do
    -- l3:       if turn != id
    -- l4:         flag := false;
    -- l5:         wait until turn = id;
    -- l6:         flag := true
    -- l7:     // Critical section
    -- l8:     turn := 1 - id
    -- l9:     flag := false;
    --     }
    

    Note that some statements, e.g. while iflag do, might have more than one exit point depending on the value of the guard: if iflag is true, then the exit point is l3, otherwise the exit point is l7.

  2. Create a corresponding module that takes the same inputs and has a state variable which evaluates to the newly introduced labels.

    MODULE p(iflag, turn, id)
    VAR
      state : { l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, error };
      flag : boolean;
    

    Here, notice that i added the special state error. This is only to ensure that during the definition the transition relation for state we are not leaving out any correct transition step. In general, it should be omitted as it does not belong to the original code.

  3. Define the transition relation for state:

    ASSIGN
      init(state) := l0;
      next(state) := case
        state = l0              : l1;
        state = l1              : l2;
        state = l2 & iflag      : l3;
        state = l2 & !iflag     : l7;
        state = l3 & turn != id : l4;
        state = l3 & turn = id  : l2;
        state = l4              : l5;
        state = l5 & turn != id : l5;
        state = l5 & turn = id  : l6;
        state = l6              : l2;
        state = l7              : l8;
        state = l8              : l9;
        state = l9              : l0;
        TRUE                    : error; -- if you match this then the above
                                         -- description of transitions are incomplete
      esac;
    

    As you can see, I simply connected every entry point with the corresponding exit point. Moreover, wherever more than one exit point is defined for a given entry point I also added other state conditions to determine what line is executed next.

  4. Add the transition relation for flag:

    init(flag) := FALSE;
    next(flag) := case
      state = l1 | state = l6 : TRUE;
      state = l4 | state = l9 : FALSE;
      TRUE                    : flag;
    esac;
    
  5. Add some definitions to identify which sections of code the process is executing:

    DEFINE
      critical_section := (state = l7);
      trying_section := (state = l1 | state = l2 | state = l3 |
                         state = l4 | state = l5 | state = l6);
    
  6. Create a main module which creates two instances of p:

    MODULE main ()
    VAR
      turn : {0, 1};
      p1   : p(p2.flag, turn, 0);
      p2   : p(p1.flag, turn, 1);
    
    ASSIGN
      init(turn) := 0;
      next(turn) := case
        p1.state = l8 : 1;
        p2.state = l8 : 0;
        TRUE          : turn;
      esac;
    
  7. Add some very typical mutual exclusion properties to be verified by the model checker:

      --*-- PROPERTIES --*--
    
    -- Safety: two processes are never in the critical section at the same time
    CTLSPEC AG !(p1.critical_section & p2.critical_section);
    
    -- Liveness: if a process is in the trying section, then sooner or later
    --           it will access the critical section.
    CTLSPEC AG (p1.trying_section -> AF p1.critical_section);
    
    -- Absence of Starvation
    CTLSPEC ! EF AG (p1.trying_section & p2.trying_section);
    
    -- Never in Error State 
    CTLSPEC AG !(p1.state = error);
    
  8. Run the tool

    ~$ NuSMV -int
    

    and check that all properties are verified:

    NuSMV > reset; read_model -i dekker.smv; go; check_property
    -- specification AG !(p1.critical_section & p2.critical_section)  is true
    -- specification AG (p1.trying_section -> AF p1.critical_section)  is true
    -- specification !(EF (AG (p1.trying_section & p2.trying_section)))  is true
    -- specification AG !(p1.state = error)  is true 
    

NOTES:

  1. If you look closely at steps 1 and 3, several states look redundant. For instance, it is always possible to collapse contiguous states that have only one entry and exit points. I'll leave this to you as an exercise.

  2. Notice that I used the synchronous composition of modules for simplicity. In practice the verification would be more meaningful by letting the two processes to be run asynchronously. However, this would require making the model more complex than your question really required, and it is thus beyond the scope of my answer.

  3. If you would like to learn more about NuSMV, you can take a look at its documentation or look at the second part of this course.

Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40
  • THANK YOU SO MUCH I UNDERSTAND THIS BETTER THAN THE TUTORIAL. SO in general it basically like states that jump to the next state which is basically the instruction and i know that there is more complex way to run this more smoothly but i couldn't understand how to do it so this helps alot! – Darkflame May 28 '16 at 21:26
  • @Darkflame you are welcome, if the answer solved your issue then I would invite you to mark it as accepted. Otherwise, if you need further assistance, feel free to integrate your question or drop a comment here. – Patrick Trentin May 28 '16 at 23:53
  • Is it possible for me to put 2 commands into 1 state like state = l0 : l1; state = l1 : l2; it would become state = l0 & state = l1 ; l2 – Darkflame May 29 '16 at 00:43
  • @Darkflame `state = l0 : l1; state = l1 : l2` is not equivalent to `state = l0 & state = l1 : l2`. In fact, `state = l0 & state = l1` is a trivially false condition, since variable `state` can only have one value at any given time. What you can do is to merge labels `l0` and `l1` into a unique label `l01`, by substituting all their occurrences within the model (see note #1). Notice that a false condition is simply ignored, and thus NuSMV would then evaluate the next condition in the *case/esac* block of code. – Patrick Trentin May 29 '16 at 01:29
  • hey Can you help with more CLTSPEC what AG and all the other stands for and i wrote the code but i keep getting line 4 syntax error when running it do you mind checking it? – Darkflame May 31 '16 at 14:41