[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [tlaplus] pluscal overhead



The main measure of complexity relevant in this context is the number of states that TLC needs to generate and store, and this is determined by the number of labels that appear in a PlusCal algorithm, since every label corresponds to an atomic transition. In turn, the number of labels is mostly related to the "grain of atomicity" that the modeler wishes to enforce. (However, the translation algorithm from PlusCal to TLA+ dictates certain positions that must be labeled, such as the entry point of a procedure or a loop.) The translation of procedures themselves is quite standard, based on a stack of parameters, local variables, and return address that is made explicit in the generated TLA+ specification.

For simple "straight-line" code such as your procedure Foo, you may prefer using macros or definitions rather than procedures, and these alternative constructs do not involve any overhead. Procedures are the construct of choice if you explicitly need to model their computational behavior, including possible interleaving in a parallel setting, rather than just the input-output relation of a subroutine.

Hope this helps,
Stephan

On 03 May 2015, at 07:33, Y2i <yur...@xxxxxxxxx> wrote:

There seems to be significant housekeeping in translated PlusCal code, especially when using procedures.  Does anyone know the average cost of this housekeeping when running TLC model checker?  By how much on average the state space that needs to be checked increases?  How does this increase affect average running time?

Thank you,
Yuri

-------------------------------- MODULE Func --------------------------------
EXTENDS Naturals, TLC, Sequences
Procs == 1..3

(*--algorithm Func
procedure Foo(x, y, z)
  variable w;
begin
  Foo1: w := x + y + z;
  Foo2: return;
end procedure
process Bar \in Procs
  variables a;
begin
    Bar1: call Foo(1,2,3);
end process
end algorithm
*)
\* BEGIN TRANSLATION
CONSTANT defaultInitValue
VARIABLES pc, stack, x, y, z, w, a

vars == << pc, stack, x, y, z, w, a >>

ProcSet == (Procs)

Init == (* Procedure Foo *)
        /\ x = [ self \in ProcSet |-> defaultInitValue]
        /\ y = [ self \in ProcSet |-> defaultInitValue]
        /\ z = [ self \in ProcSet |-> defaultInitValue]
        /\ w = [ self \in ProcSet |-> defaultInitValue]
        (* Process Bar *)
        /\ a = [self \in Procs |-> defaultInitValue]
        /\ stack = [self \in ProcSet |-> << >>]
        /\ pc = [self \in ProcSet |-> "Bar1"]

Foo1(self) == /\ pc[self] = "Foo1"
              /\ w' = [w EXCEPT ![self] = x[self] + y[self] + z[self]]
              /\ pc' = [pc EXCEPT ![self] = "Foo2"]
              /\ UNCHANGED << stack, x, y, z, a >>

Foo2(self) == /\ pc[self] = "Foo2"
              /\ pc' = [pc EXCEPT ![self] = Head(stack[self]).pc]
              /\ w' = [w EXCEPT ![self] = Head(stack[self]).w]
              /\ x' = [x EXCEPT ![self] = Head(stack[self]).x]
              /\ y' = [y EXCEPT ![self] = Head(stack[self]).y]
              /\ z' = [z EXCEPT ![self] = Head(stack[self]).z]
              /\ stack' = [stack EXCEPT ![self] = Tail(stack[self])]
              /\ a' = a

Foo(self) == Foo1(self) \/ Foo2(self)

Bar1(self) == /\ pc[self] = "Bar1"
              /\ /\ stack' = [stack EXCEPT ![self] = << [ procedure |->  "Foo",
                                                          pc        |->  "Done",
                                                          w         |->  w[self],
                                                          x         |->  x[self],
                                                          y         |->  y[self],
                                                          z         |->  z[self] ] >>
                                                      \o stack[self]]
                 /\ x' = [x EXCEPT ![self] = 1]
                 /\ y' = [y EXCEPT ![self] = 2]
                 /\ z' = [z EXCEPT ![self] = 3]
              /\ w' = [w EXCEPT ![self] = defaultInitValue]
              /\ pc' = [pc EXCEPT ![self] = "Foo1"]
              /\ a' = a

Bar(self) == Bar1(self)

Next == (\E self \in ProcSet: Foo(self))
           \/ (\E self \in Procs: Bar(self))
           \/ (* Disjunct to prevent deadlock on termination *)
              ((\A self \in ProcSet: pc[self] = "Done") /\ UNCHANGED vars)

Spec == Init /\ [][Next]_vars

Termination == <>(\A self \in ProcSet: pc[self] = "Done")

\* END TRANSLATION

--
You received this message because you are subscribed to the Google Groups "tlaplus" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tlaplus+u...@xxxxxxxxxxxxxxxx.
To post to this group, send email to tla...@xxxxxxxxxxxxxxxx.
Visit this group at http://groups.google.com/group/tlaplus.
For more options, visit https://groups.google.com/d/optout.

--
Stephan Merz