We consider {<1,2>, <1,3>, <1,7>, <0,4>} as a set of tuples of the relation R. Now we consider that R is represented (through its membership function) using BDD. That is, the BDD representing R depends on the variables {x1, x2, y1, y2, y3}, where {x1, x2} are used to represent the first element of each set, and {y1, y2, y3} are used to represent the second element.
Now let's look at the problem of finding a set of tuples that have unique values ββin their first element. For relationships above this set, there will be {<0.4>}. All other elements are discarded because they contain more than one value having 1 in the first component.
As a second example, consider a relationship with many sets {<1,2>, <1,3>, <1,7>, <2,3>, <2,5> <0,4>}. In this case, the expected result is still {<0.4>}, since 2 appears more than once as the first element.
The problem can also be considered as an abstraction of the variables {y1, y2, y3}, so that they remain the only values ββfor {x1, x2}. Using this result, the expected ratio can be restored by calculating the conjunction of the resulting BDD with the input.
So the question is: what are the BDD operations that must be performed on the R representation in order to get BDDs with unique tuples only.
Please note that this is the genralization of this question
EDIT 1: The following code reflects the implementation I have so far. However, I am wondering if a more efficient version can be obtained. For simplicity, I deliberately omit the processing of the computed table (it is imperative to get the best time complexity). In addition, I use &, | and! to denote conjunction, disjunction and complementation operations on BDD.
BDD uniqueAbstract(BDD f, BDD cube) { if ((f.IsZero() || f.IsOne()) && !cube.IsOne()) return zero(); BDD T = high(f); BDD E = low(f); if(level(f) == level(c)) { // current var is abstracted BDD uniqueThen = uniqueAbstract(T, high(c)); BDD existElse = existAbstract(E, high(c)); BDD existThen = existAbstract(T, high(c)); BDD uniqueElse = uniqueAbstract(E, high(c)); return (uniqueThen & !existElse) | (uniqueElse & !existThen) } else { BDD uniqueThen = uniqueAbstract(T,c); BDD uniqueElse = uniqueAbstract(E,c); return ite(top(f), uniqueThen, uniqueElse); } }
EDIT2: After three different implementations, there are still performance issues. Let me describe three of them.
- Implementation C of my approach, let me name reference implementation 4 .
- The implementation suggested by user meolic in accepted answer 3 .
- A hybrid approach between the two and the available 2 .
The purpose of this update is to analyze a little the results of using the three approaches. Since interim measures are currently misleading to judge them, I decided to evaluate the implementation for a different set of measures.
- Recursive challenges
- Cache access
- Abstract simple. The number of times a function call has been resolved without the need for existential abstraction.
- Abstract complex: the number of times a function call has been resolved, requiring existential abstraction.
- Exist abstract: the number of calls to existential abstraction.
Results for implementation 1: (21123 ms): Unique abstraction statistics: Recursive calls: 1728549.000000 Cached hits: 638745.000000 Not abstract: 67207.000000 Abstract is simple: 0.000000 Abstract complex: 0.000000 Exist abstract: 1593430.000000
Results for implementation 2: (execution time: 54727 ms) Unique abstraction statistics: Recursive calls: 191585.000000 Cached hits: 26494.000000 Abstract simple: 59788.000000 Abstract complex: 12011.000000 Exist abstract: 24022.000000
Results for implementation 3: (execution time: 20215 ms) Unique abstraction statistics: Recursive calls: 268044.000000 Cached hits: 30668.000000 Abstract simple: 78115.000000 Abstract complex: 46473.000000 Exist abstract: 92946.000000
EDIT 3: The following results were obtained after implementing each logical operation in ITE 5 terms.
uniqueAbstractRecRef (21831 ms) Unique abstraction statistics: Total calls: 1723239 Optimized calls: 0 Total abstract calls exist: 30955618 Unique abstract life calls Abstract: 2385915 Total calls: 3574555 Of the total time, uniqueAbstractRecRef takes 4001 ms (12.4%)
uniqueAbstractSERec (56761 ms) Unique abstraction statistics: Total calls: 193627 Optimized calls: 60632 Total abstract calls: 16475806 Unique abstract live calls Abstract: 24304 Total calls: 1271844 Of the total time, uniqueAbstractSERec takes 33918 ms (51.5%)
uniqueAbstractRec (20587 ms) Unique abstraction statistics: Total calls: 270205 Optimized calls: 78486 Total abstract calls: 13186348 Unique abstract existence calls Abstract: 93060 Total calls: 1256872 Of the total time, uniqueAbstractRec takes 3354 ms (10.6%)