Alloy Community

User login

state space explosion

 
Posted on: Mon, 03/23/2009 - 09:26
Joined: 2009-03-19
Points: 8
User is offline
state space explosion
Hello,

We are trying to simulate architectural design using the Alloy Analyzer. The architecture meta-model has been manually translated into Alloy code. An architecture design model (expressed in EMF) is transformed into Alloy code, which conforms to the meta-model expressed in Alloy code. The traces pattern (as found in http://alloy.mit.edu/alloy4/tutorial/s4_dynamic.pdf) is used to generate all the possible traces over the architecture, given an initial state. Unfortunately, we're running into tractability problems.

In our case, a single state represent the location of all the data in the architecture. These locations can be ports of components, or data instances which can hold data. A port can (in our simulation) hold only one concrete data value, while data instances can hold multiple. The
(simplified) State signature used is as follows:
sig State {
   next: lone State,
   portValues: Port -> lone Data,
   dataInstanceValues: DataInstance -> Data }

Given the large number of ports in the architecture (> 15), the number of possible states is enormous. Combine this with a large number of States for each trace (> 15), and simulation of the architecture becomes very time-consuming.

A single transition function is defined, which specifies the end-result of events from a given state, to a new state. Basically, it specifies that data is moved from one port to another port, if they are connected.
This is combined with some other expressions, which defined the 'inner-workings' of the components (such as storing data received from a port in a data instance).

It should be stated that the architecture itself is static, while only the data within the architecture is dynamic. For example, signatures for each component and port seem - at least to us - fairly restrictive. As an example:
(Meta-model)
enum PortDirection { ... }
abstract sig Port {
   direction: one PortDirection,
}
abstract sig DataPort extends Port {
   dataType: one DataType,
}

(Model)
one sig Port1 extends DataPort {
} {
   dataType = DT1
   direction = PortDirection_In
}

Can you give any hints on how to optimize the simulation? You are probably not able to give any domain specific optimizations, but hopefully you are able to give generic optimizations. We are trying to keep as much detail from the original architecture, and not remove(abstract) certain elements for the completeness of the simulation.

The untractability seems to come form the fact that the whole trace (with its states) is generated at once. A more iterative way (such as 'generating' a single new state from an single old state) seems to be the solution here. Is there any way to force Alloy/the SAT solvers into behavior such as this?
 
Posted on: Fri, 03/27/2009 - 04:45    #1
Joined: 2009-03-19
Points: 8
User is offline
I have not got any reply but is there anyone who can give advices for state space explosion problem? Is it a general problem for alloy?
 
Posted on: Fri, 03/27/2009 - 07:20    #2
Joined: 2009-03-19
Points: 8
User is offline
Additionally, in my case, since i do not know the exact number of states, i do not use the ordering module in alloy. I define my own ordering. To have the complete traces for state transitions, I have two facts in the following:

fact properStateTransitions {
   all s: State - State.last |
       transition[s,s.next]
}

fact completeTraces {
   all s: State |
      one s.next iff transitionPossible[s]
}

Is there a more efficient pattern for the performance?
 
Posted on: Sun, 03/29/2009 - 15:15    #3
dnj
dnj's picture
Joined: 2008-06-06
Points: 39
User is offline
A few things:

1. You will get much better performance if you write the constraints in a way that allows the analyzer to construct "partial instances". Just write a parameterless function to assign a value to each of the relations of the static architecture

    enum A {a1, a2, a3}
    enum B {b1, b2, b3}
    fun r[] : A -> B { a1->b2 + a2->b3 }

2. Do use the Alloy ordering module. It will fire built-in symmetry breaking, which will dramatically improve performance. It will also ensure that the states in the trace are named s0, s1, etc. To avoid the problem of having to fill out the traces, just write your spec to allow early termination (by stuttering, so that a state can repeat at the end).

3. There is an experimental feature that is not documented that does the greedy search you describe. I'll see if we can get something written up to share with you about how to use it.

Daniel
 
Posted on: Tue, 03/31/2009 - 13:02    #4
Joined: 2009-03-19
Points: 8
User is offline
I am not sure if I correctly get the point for the partial instances. According to my interpretation I am now assigning the values of relations for the static architecture by using a function. For instance I had a "conn" relation between DataPort and Connection elements in the previous version:

abstract sig DataPort extends Port {
    ...
    conn: lone PortConnection
}

one sig dataPortIn6 extends DataPort {
} {
    ...
    conn = connection9
}

In the current version I removed this conn filed from the DataPort signature and I assign the relation values in a function in the following:

fun conn[]: DataPort ->Connection {
    ...  +
    dataPortIn6 -> connection9
}

However, the performance of the state space generation is worse than the previous one.

The ordering module makes the performance much faster. However, we still have to state the exact number of states we generate. We just want to put an upper limit instead of specifying the exact number. I think you adress this issue in the following statement:

>>"To avoid the problem of having to fill out the traces, just write your spec to allow early termination (by
>>stuttering, so that a state can repeat at the end)"

Is there any link or documentation how to do this?

And lastly, I will be much appreciate if you share the the experimental feature. I am not sure how much effective the "complete traces" fact that we are using is.

Regards,

Arda
 
Posted on: Thu, 06/11/2009 - 11:41    #5
rseater's picture
Joined: 2008-01-24
Points: 59
User is offline
The underlying analysis of Alloy is (necessarily) exponential.  You can often avoid the problem (or at least mitigate it) through a combination of good abstraction and writing constraints in a style that the solver finds easier to solve (avoid deeply nested quantifiers and set comprehensions).  Writing a more finely tuned scope can help too.  That is, rather than

  run p for 30

You might specify it in more detail, such as

  run p for 3, but 10 Location, 1 Aircraft, 30 Transition

When applicable, this can help with scaling a lot.

Syndicate content  

The development of this site is supported by the National Science Foundation under Computing Research Infrastructure Grant No. 0707612.

Theme originally designed by Chris Herberte