• Keine Ergebnisse gefunden

0 1 2 3

0 2 1 3

Figure 5.2: Two possible functions to be picked by a selecting function Definition 5.1.2 (Selection Function). Let f ∈ IK(Z4) and z the first essential variable4 of f. The selection function STADD is defined by:

STADD(f) =















f if f ∈IF(4)1

f if f ∈IF(4)2 and f|z=1 < f|z=2) ϕS◦f if f ∈IF(4)2 and f|z=1 > f|z=2

f if f ∈IF(4)2 , f|z=1 =f|z=2 and f|z=0 < f|z=3 ϕS◦f otherwise

After defining the selection function we now have a new HOWDD instance that performs the swap of neighboring variables in constant time. At the same time, Toggling Algebraic Decision Diagrams (TADDs) provide a unique and canonical form.

5.2 Implementation

We will now focus on some facts that are important for an efficient implementa-tion. All necessary algorithms will be presented in this secimplementa-tion. The main difference between this variant and all others mentioned before is that it uses four succes-sor pointers. For every successor pointer a flag is used to identify if the swap function is active or not. Only one Boolean flag is needed because the function is self inverse5. An active swap flag changes the way successors are calculated6. As mentioned in Section 4.1.1.1 we can use the pure node rather than the tuple implementation to increase the system’s performance. The idea relies on the fact that objects are aligned to word sized chunks [24]. That means that the last bit

4Remember, that this variable represents all possible combinations of xi andyi.

5comparable to OBDDs with negative edges

6see Table 5.1 for more information

of the memory addresses used in the operating system is always zero. For a com-pact representation of a node we use the successor pointers to store the Boolean flag7. JINC utilizes the TraversalHelper approach described in Section 4.1.3 to eliminate most of the occurrences of programming errors accompanied with pointer arithmetic. TheHelpermodule defines all methods needed to access the appropriate pointer8 and the Boolean flag. The TraversalHelper can easily be provided with the use of JINC’s helper classes. Listing 5.1 shows the complete implementation of the TraversalHelper for TADDs.

1 t e m p l a t e < >

2 s t r u c t T r a v e r s a l H e l p e r < T A D D B a s e N o d e > {

3 T r a v e r s a l H e l p e r ( c o n s t T A D D B a s e N o d e * n ) : n o d e ( n ) {}

4 T r a v e r s a l H e l p e r g e t S u c c ( c o n s t u n s i g n e d s h o r t s u c c X ) c o n s t { 5 if ( C o m m o n :: b i t S e t ( n o d e . ptr )){

6 T A D D B a s e N o d e * s u c c ;

7 if (( s u c c X = = 1 ) || ( s u c c X = = 2 ) ) { 8 s u c c = node - > g e t S u c c (3 - s u c c X );

9 } e l s e {

10 s u c c = node - > g e t S u c c ( s u c c X );

11 }

12

13 if ( C o m m o n :: S m a r t A c c e s s < T A D D B a s e N o d e >( s u c c ) - > i s S y m m e t r i c ( ) ) { 14 r e t u r n T r a v e r s a l H e l p e r ( s u c c );

15 } e l s e {

16 r e t u r n T r a v e r s a l H e l p e r ( C o m m o n :: f l i p B i t ( s u c c ));

17 }

18 } e l s e {

19 r e t u r n T r a v e r s a l H e l p e r ( node - > g e t S u c c ( s u c c X ));

20 }

21 }

22 c o n s t T A D D B a s e N o d e * g e t S u c c P t r ( c o n s t u n s i g n e d s h o r t s u c c X ) c o n s t { 23 r e t u r n g e t S u c c ( s u c c X ). g e t P t r ();

24 }

25 b o o l i s D r a i n () c o n s t { r e t u r n node - > i s D r a i n ( ) ; }

26 d o u b l e g e t V a l u e () c o n s t { r e t u r n node - > i s D r a i n ()? node - > g e t V a l u e ( ) : 0 . 0 ; } 27 c o n s t T A D D B a s e N o d e * g e t P t r () c o n s t { r e t u r n n o d e . g e t P t r ( ) ; }

28 V a r i a b l e I n d e x T y p e g e t L e v e l () c o n s t { r e t u r n node - > g e t L e v e l ( ) ; } 29

30 s t a t i c c o n s t u n s i g n e d s h o r t N =4;

31 C o m m o n :: S m a r t A c c e s s < T A D D B a s e N o d e > n o d e ; 32 };

Listing 5.1: TraversalHelperhTADDi

One of the most important features a HOWDD instance has to provide is that the partition of a function can be easily identified (otherwise the identification phase would be a serious performance issue). Line 13 uses the isSymmetric() method which identifies the equivalence class membership of the function represented by this node9. The partitions of TADDs can be recognized with the observations that every path of the representation of a IF(4)2 function leads to a IF(4)1 function10 and that no node representing a IF(4)2 function can be reached by a node representing a IF(4)1 function.

These observations lead to the following criteria to identify whether a non-terminal nodev (with first essential variable z) is representing a IF(4)1 function.

(a) fv|z=1 =fv|z=2

(b) For all η ∈ {0,1,2,3} holds fv|zi=η ∈IF(4)1 .

7the same technique is used in CUDD for the representation of negated edged

8with the template helper object Common::SmartAccesshTi

9The TADD implementation only differentiates between inner and terminal nodes. This differ-entiation is reasonable because it simplifies the implementation of algorithms. The partitions are not taken as an distinctive feature because it does not simplify the implementation.

10constant functions are always IF(4)1 functions

5.2. IMPLEMENTATION

xy

i

0 1 2 3

xy

i

0 1 2 3

xy

i

0 1 2 3

Figure 5.3: How to classify if a node is a IF1 or IF2 node

The first condition means that the node must beϕS-invariant. The second condition is a result from the observation that all cofactors have to be IF1 functions. These criteria can be used to implement an efficient findOrAdd algorithm11. Each node also uses one Boolean flag to identify if it is representing a IF1 function or a IF2 function12.

Figure 5.3 shows different situations to illustrate the identification process. The marked nodes13 are representing IF1 functions. The first example shows that this node cannot represent a IF1 function because succ1(node) 6= succ2(node). The second example shows the only situation where the node represents a IF1 function (succ1(node) = succ2(node) and all sub-trees represent IF1 functions). The third example shows the situation where not all sub-trees represent IF1 functions and therefore the node must represent a IF2 function.

5.2.1 FindOrAdd

The selection function defined in the section above uses a function order to ensure uniqueness. The implementation uses a similar idea. We will define an order on the nodes, e.g., the topological sorting. The basis algorithm to provide a unique data structure is thefindOrAddalgorithm. ThefindOrAddalgorithm for TADDs is slightly more complex than for ordinary BDD variants. It has to deal with four nodes and toggling information on the edges. The handling of four parameters instead of two increases the number of possible situations to deal with. The possible situations and the results are presented in Figure 5.4. In this example, all cofactors are IF2

functions14. The mentioned situations are the cases where the algorithm has to alter the input parameters.

11as the identification rules just look at the already created sub-nodes

12This is needed to identify the node in constant time. Otherwise a whole traversal would be needed.

13or sub-trees

14the situation with IF1 functions is handled analogously

w w w1 w2

I II

> w2 w1 w1 w2

III

> w1 w2

Figure 5.4: Possible input parameters for thefindOrAddalgorithm and the resulting structure

The findOrAdd algorithm is shown in Algorithm 2. The algorithm first checks if the second condition is violated. This information is essential to mark a node as a IF1 orIF2 node. The toggle function is used to calculate the right transformation function. If the successor is aIF1 node the transformation function will always beid. In the other case, it calculates ϕS◦φi to adjust the already existing transformation function. The functionsetSymm marks a node to be aIF1 node. By default a node is assumed to be aIF2 node. The different cases are labeled with the corresponding number from Figure 5.4. Case IV15 handles the cases where the transformation function is always the identity function. There is also a check if the newly created node is aIF1 node.

5.2.2 Algorithms and Operators

The algorithm concept of JINC is efficient and flexible16. We will discuss the imple-mentation of a genericAPPLYalgorithm for TADDs, other algorithms (e.g., a generic ABSTRACTalgorithm) follow the same pattern.

Listing 5.2 shows the implementation of a generic APPLY algorithm on TADDs.

The template argument of the APPLY algorithm provides the handling of termi-nal cases and the operator ID for computed-table look-ups. It also provides if a cache optimization should be performed. In the case of a commutative operator T::cacheOpt() will provide a normalization of the input parameters for a better computed-table hit ratio. In the case of a non-commutative operator the template argument provides an empty implementation which will be eliminated by the com-piler and leads to no run-time overhead. Listing 5.3 shows the implementation of the plus operator as an example. TheHelper module provides base-classes that im-plement the cache optimization. The plus operator is commutative and thus derived fromCommon::COMMUTATIVE<TADDBaseNode>. Line 10 checks if both arguments are equal. In that particular case JINC provides an optimized one argument plus op-erator. Figure 5.5 illustrates the algorithm concept on the example of the plus operator. TheAPPLY algorithm in Listing 5.2 does not take pure node pointer as an argument. It uses the TraversalHelper to provide convenient methods for imple-mentation (e.g., for successor access). Every pointer will automatically converted to

15not shown in Figure 5.4

16through policy-based-design [4] which can be seen as a compile-time variant of the strategy pattern

5.2. IMPLEMENTATION

Algorithm 2 findOrAdd

Input: Variable indexi and cofactor tuples < w0, φ0 >, < w1, φ1 >,

< w2, φ2 > and < w3, φ3 >

Output: Unique tuple < n, φ >

symm=areSymmetricCofactors(w0, w1, w2, w3)

if < w0, φ0 >=< w1, φ1 >=< w2, φ2 >=< w3, φ3 > then

< n, φ >=< w0, φ0 > Case I+

else if w1 > w2 then

n=find or add node on level i with successor tuples

< w0,toggle(w0, φ0)>, < w2,toggle(w2, φ2)>

< w1,toggle(w1, φ1)>, < w3,toggle(w3, φ3)>

< n, φ >=< n, ϕS > Case II+

else if w1 =w2 and w0 > w3 then

n=find or add node on level i with successor tuples

< w0,toggle(w0, φ0)>, < w1,toggle(w2, φ2)>

< w1,toggle(w1, φ1)>, < w3,toggle(w3, φ3)>

if symm=true then setSymm(n) end if

< n, φ >=< n, ϕS > Case III+

else

n=find or add node on level i with successor tuples

< w0, φ0 >, < w1, φ1 >, < w2, φ2 > and < w3, φ3 >

if w1 =w2 and symm=true then setSymm(node)

end if

< n, φ >=< n,id > Case IV+

end if

return < n, φ >

comp T

terminalCase() ID

TADD_PLUS_2 Common::COMMUTATIVE T

TADDBaseNode

terminalCase() ID

TADD_PLUS_1 comp T

2 arguments

1 argument

Figure 5.5: JINC’s algorithm concept on the example of the plus operator

TraversalHelper so that there is no possibility to use a malformed pointer.

5.2.3 Iterators

TADDs uses nodes with four successors. Therefore the TraversalHelper enables the access to logical paths with a branch range of four. Most of the HOWDD instances supported by JINC have a branch range of two. For that reason the TADD implementation also defines aTraversalHelper with a branch range of two.

This approach provides a compatible interface so that TADDs can be used like all other variants.

5.2.3.1 Swap

The approach of TADDs is based on edge weights. Therefore ordinary reordering methods cannot be applied directly. The swap algorithm has to be extended to handle the edge weights. The transformation ofxi andyi variables to onezi variable speeds up the swap operation for applications with interleaved variable orderings[42].

It is clear that both variables should not be separated and handled as a group. A swap of two neighboring groups with two variables requires four swap operations. In the case of TADDs it is performed with one swap operation. Figure 5.6 shows the idea of the TADD swap operation. (a) is the initial point. The highlighted nodes in (b) show the newly created nodes. Thex node is then moved to the y level and linked to the newly created nodes (c). The second y node (from (a)) is then no longer referenced and can be deleted. Afterwards the levels are swapped (d).

5.2. IMPLEMENTATION

1 t e m p l a t e < t y p e n a m e T >

2 T A D D B a s e N o d e * c o m p ( T r a v e r s a l H e l p e r < T A D D B a s e N o d e > v1 , T r a v e r s a l H e l p e r < T A D D B a s e N o d e > v2 , 3 P t r H a s h M a p 2 < T A D D B a s e N o d e >& c o m p u t e d T a b l e , T A D D M e m P o o l s & p o o l s ){

4

5 if ( T A D D B a s e N o d e * c o m p = T :: t e r m i n a l C a s e ( v1 . n o d e . ptr , v2 . n o d e . ptr , c o m p u t e d T a b l e , p o o l s )) 6 r e t u r n c o m p ;

7

8 T :: c a c h e O p t ( v1 . n o d e . ptr , v2 . n o d e . ptr );

9

10 if ( T A D D B a s e N o d e * c o m p = c o m p u t e d T a b l e . f i n d ( C o m m o n :: c a l c P t r ( v1 . n o d e . ptr , T :: ID ) , v2 . n o d e . ptr )) 11 r e t u r n c o m p ;

12

13 T A D D B a s e N o d e * w0 ; 14 T A D D B a s e N o d e * w1 ; 15 T A D D B a s e N o d e * w2 ; 16 T A D D B a s e N o d e * w3 ;

17 T A D D U n i q u e T a b l e * m i n T a b l e ; 18

19 if ( v1 . g e t P t r () - > g e t R e a l L e v e l () <= v2 . g e t P t r () - > g e t R e a l L e v e l ( ) ) { 20 m i n T a b l e = v1 . g e t P t r () - > g e t U n i q u e T a b l e ();

21 if ( v2 . g e t P t r () - > g e t U n i q u e T a b l e ( ) = = m i n T a b l e ){

22 w0 = comp < T >( v1 . g e t S u c c (0) , v2 . g e t S u c c (0) , c o m p u t e d T a b l e , p o o l s );

23 w1 = comp < T >( v1 . g e t S u c c (1) , v2 . g e t S u c c (1) , c o m p u t e d T a b l e , p o o l s );

24 w2 = comp < T >( v1 . g e t S u c c (2) , v2 . g e t S u c c (2) , c o m p u t e d T a b l e , p o o l s );

25 w3 = comp < T >( v1 . g e t S u c c (3) , v2 . g e t S u c c (3) , c o m p u t e d T a b l e , p o o l s );

26 } e l s e {

27 w0 = comp < T >( v1 . g e t S u c c (0) , v2 , c o m p u t e d T a b l e , p o o l s );

28 w1 = comp < T >( v1 . g e t S u c c (1) , v2 , c o m p u t e d T a b l e , p o o l s );

29 w2 = comp < T >( v1 . g e t S u c c (2) , v2 , c o m p u t e d T a b l e , p o o l s );

30 w3 = comp < T >( v1 . g e t S u c c (3) , v2 , c o m p u t e d T a b l e , p o o l s );

31 }

32 } e l s e {

33 m i n T a b l e = v2 . g e t P t r () - > g e t U n i q u e T a b l e ();

34 w0 = comp < T >( v1 , v2 . g e t S u c c (0) , c o m p u t e d T a b l e , p o o l s );

35 w1 = comp < T >( v1 , v2 . g e t S u c c (1) , c o m p u t e d T a b l e , p o o l s );

36 w2 = comp < T >( v1 , v2 . g e t S u c c (2) , c o m p u t e d T a b l e , p o o l s );

37 w3 = comp < T >( v1 , v2 . g e t S u c c (3) , c o m p u t e d T a b l e , p o o l s );

38 } 39

40 T A D D B a s e N o d e * n o d e = f i n d O r A d d ( p o o l s . i n n e r N o d e M e m P o o l , m i n T a b l e , w0 , w1 , w2 , w3 );

41

42 c o m p u t e d T a b l e . i n s e r t ( C o m m o n :: c a l c P t r ( v1 . n o d e . ptr , T :: ID ) , v2 . n o d e . ptr , n o d e );

43

44 r e t u r n n o d e ; 45 }

Listing 5.2: APPLY for TADDs

1 s t r u c t T A D D _ P L U S _ 2 : C o m m o n :: C O M M U T A T I V E < T A D D B a s e N o d e >{

2 s t a t i c c o n s t u n s i g n e d s h o r t ID = A r i t h m e t i c C o n s t a n t s :: A D D _ O P ;

3 s t a t i c i n l i n e T A D D B a s e N o d e * t e r m i n a l C a s e ( T r a v e r s a l H e l p e r < T A D D B a s e N o d e > v1 ,

4 T r a v e r s a l H e l p e r < T A D D B a s e N o d e > v2 ,

5 P t r H a s h M a p 2 < T A D D B a s e N o d e >& c o m p u t e d T a b l e ,

6 T A D D M e m P o o l s & p o o l s ){

7

8 if ( v1 . n o d e . ptr == T A D D :: z e r o D r a i n ) r e t u r n v2 . n o d e . ptr ; 9 if ( v2 . n o d e . ptr == T A D D :: z e r o D r a i n ) r e t u r n v1 . n o d e . ptr ; 10 if ( v1 . n o d e . ptr == v2 . n o d e . ptr )

11 r e t u r n :: comp < T A D D _ P L U S _ 1 >( v1 . n o d e . ptr , c o m p u t e d T a b l e , p o o l s );

12 if ( v1 . i s D r a i n () && v2 . i s D r a i n ())

13 r e t u r n f i n d O r A d d D r a i n ( p o o l s . t e r m i n a l N o d e M e m P o o l , v1 . g e t V a l u e ()+ v2 . g e t V a l u e ( ) ) ;

14 r e t u r n 0;

15 } 16 };

17

18 T A D D F u n c t i o n T A D D F u n c t i o n :: o p e r a t o r +( c o n s t T A D D F u n c t i o n & f u n c t i o n ){

19 T A D D D a t a & d a t a = g e t T A D D D a t a ();

20 r e t u r n T A D D F u n c t i o n ( 21 comp < T A D D _ P L U S _ 2 >(

22 r o o t N o d e , f u n c t i o n . r o o t N o d e ,

23 * d a t a . c o m p u t e d T a b l e s . a r i t h m e t i c H a s h M a p , d a t a . m e m P o o l s

24 )

25 );

26 }

Listing 5.3: Operator + for TADDs

0 1 2 3 0 1 2 3 x

y y

0 1 2 3

0 1 2 3 0 1 2 3 x

y y

x x x x

0 1 2 3 y y

x x x x

0

1 2

3

01 2 3 y y

x x x x

0 1 2 3

(a) (b) (c) (d)

Figure 5.6: The idea of swapping the two levels.