CUADRO DE PRECIOS 1
CAPÍTULO 01 DESMONTAJES Y DEMOLICIONES
By definition, a local action a ∈ Ac,l is independent of Vc\Vc, and therefore δa(s) depends
only on sVc. Furthermore, by the restriction we introduced earlier, all immediate transitions
are local. Finally, note that all SVs in Vc are encoded in level c of the MDD. These properties
imply that in order to generate a set of states that are visited by completion of action a, we only need to manipulate the nodes in level c of the MDD.
Suppose that a (tangible) substate sc can lead to a tangible substate s0c by a sequence
of actions in Ac,l. Hence, if state (s1, . . . , sc−1, sc, sc+1, . . . , sm) is reachable, then state
(s1, . . . , sc−1, s0c, sc+1, . . . , sm) is also reachable. To implement this local state exploration on
the MDD, we perform the “saturation” operation on all nodes u in level c: u[s0c] := u[sc]∪u[s0c]
for all possible values of sc and s0c, where u is a non-terminal node and u[sc] (called a child
of node u) denotes the node to which the scth pointer of u points. In that operation, values
of sj’s (j 6= c) are implicit; all state paths that go through node u constitute all states of
the form (s1, . . . , sc−1, sc, sc+1, . . . , sm).
Figure 4.2(a) shows LocalSSE, which explores the state space using only local actions Ac,l of every atomic component c. Therefore, LocalSSE iterates through all nodes uc of
levels that correspond to atomic components in depth-first search (DFS) order. For each node uc that encodes a set of substates of the form sc, it saturates usat, the node that is
LocalSSE(U )
1 foreach non-root node u visited in a DFS order starting from from node r, root of U
2 c := level of u in the MDD 3 if c ∈ AM
4 usat := copy of u
5 Saturate(usat)
6 if u 6= usat
7 replace u with usat (a) Main pseudocode
Saturate(u) 1 c := level of u in the MDD 2 Y := {0, . . . , |Sc| − 1} 3 while Y 6= ∅ 4 pick sc from Y 5 foreach s0c s.t. B∗c(sc, s0c) = 1 6 u0 := u[sc] ∪ u[s0c] 7 if u0 6= u[s0 c] 8 u[s0c] := u0 9 Y := Y ∪ {s0c} 10 Y := Y − {sc} (b) Saturation pseudocode
Figure 4.2: Pseudocodes for the local state-space exploration
uc is replaced by its saturated version usat.4 The reason for iterating through all nodes in
DFS order is that implementation issues make it necessary for us to ensure that a node is saturated after all its children have been saturated.
Saturate(u) (shown in Figure 4.2(b)) fires local actions until no further local action firing can add any substate to the set. Lines 3-10 perform the above mentioned saturation operation on u in a “symbolic” manner, i.e., for each s0c, lines 6-8 add all states of the form (s1, . . . , sc−1, s0c, sc+1, . . . , sm) to U . Notice that during the saturation operation, we may
need to increase the size of u (i.e., the number of its pointers), since we do not know the final value of |Sc| in advance. The important point is that due to the locality of the actions,
we can expand the set of reachable states of the system only by (local) changes to u. Repetitive computations related to local state exploration might occur, since the same substate may be explored many times for different nodes throughout the execution of SSSE. In order to avoid the extra computations, we need an efficient data structure for each atomic component c that stores the reachability relation among substate indices of that component. More formally, we need to know, for every sc, the set of all substate indices s0c that we can
reach from the substate with index sc by a (finite) sequence of local action firings. We can
4In the actual implementation, u
c is not replaced by usat in one step. Instead, uc is replaced by usat for
each of the pointers coming from the upper level. Hence, eventually, no node will point to uc, uc will be
determine that by computing the reflexive and transitive closure of a square Boolean-valued matrix denoted by Bc. Bc is defined on the (reachable tangible) state space of Mc, which
means that Bc has |Sc| rows and columns. Bc(sc, s0c) = true if and only if, starting from
substate sc, there is a sequence of local action firings (in which the first is timed and the
others, if any, are immediate) that leads to substate s0c. Otherwise, Bc(sc, s0c) = false. Let
B∗c be the reflexive and transitive closure of Bc. That means B∗c(sc, s0c) = true if and only
if there is a (possibly empty) sequence of local action firings that takes component c from substate sc to s0c.
Entries of Bcare updated as we explore the atomic component state space, and computing
the transitive closure from scratch is expensive; it takes O(|Sc|3) time for each update of Bc.
That excessively large running time is the reason why we use a simple but rather efficient online algorithm given by Ibaraki and Katoh [59] to maintain B∗c as we update Bc. Their
algorithm takes at most O(|Sc|3) for at most O(|Sc|2) updates to Bc. Notice that O(|Sc|2)
is the maximum possible number of updates.
The pseudocode of InsertElementAndUpdate for computing B∗c, which is based on
the algorithm given in [59], is shown in Figure 4.3. InsertElementAndUpdate(sc, s0c)
sets Bc(sc, s0c) to true and updates B ∗
c accordingly. One way to understand how InsertEle-
mentAndUpdate is called by our algorithm is to assume that accessing B∗c(sc, s0c) in line
5 of Saturate causes a function call if substate sc has not already been explored. That
function explores substate sc by firing actions in Ac,l, computes one row of Bc as defined
above, and calls InsertElementAndUpdate for each element of Bc that is set to true.
Note that only B∗c is stored in memory during the running time of SSSE and there is no need to store Bc; this is explained here to make the above discussion easier to understand.