TdZdd  1.1
A top-down/breadth-first decision diagram manipulation framework
Cardinality.hpp
1 /*
2  * TdZdd: a Top-down/Breadth-first Decision Diagram Manipulation Framework
3  * by Hiroaki Iwashita <iwashita@erato.ist.hokudai.ac.jp>
4  * Copyright (c) 2014 ERATO MINATO Project
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #pragma once
26 
27 #include <cmath>
28 #include <string>
29 
30 #include "../DdEval.hpp"
31 #include "../util/BigNumber.hpp"
32 #include "../util/MemoryPool.hpp"
33 #include "../util/MyVector.hpp"
34 
35 namespace tdzdd {
36 
37 template<typename E, typename T, int ARITY, bool BDD>
38 class CardinalityBase: public DdEval<E,T> {
39  int numVars;
40  int topLevel;
41 
42 public:
43  CardinalityBase(int numVars = 0) :
44  numVars(numVars),
45  topLevel(0) {
46  }
47 
48  void initialize(int level) {
49  topLevel = level;
50  }
51 
52  void evalTerminal(T& n, bool one) const {
53  n = one ? 1 : 0;
54  }
55 
56  void evalNode(T& n, int i, DdValues<T,ARITY> const& values) const {
57  if (BDD) {
58  n = 0;
59  for (int b = 0; b < ARITY; ++b) {
60  T tmp = values.get(b);
61  int ii = values.getLevel(b);
62  while (++ii < i) {
63  tmp *= ARITY;
64  }
65  n += tmp;
66  }
67  }
68  else {
69  n = 0;
70  for (int b = 0; b < ARITY; ++b) {
71  n += values.get(b);
72  }
73  }
74  }
75 
76  T getValue(T const& n) {
77  if (BDD) {
78  T tmp = n;
79  for (int i = topLevel; i < numVars; ++i) {
80  tmp *= ARITY;
81  }
82  return tmp;
83  }
84  else {
85  return n;
86  }
87  }
88 };
89 
90 template<typename E, int ARITY, bool BDD>
91 class CardinalityBase<E,std::string,ARITY,BDD> : public DdEval<E,BigNumber,
92  std::string> {
93  int numVars;
94  int topLevel;
95  MemoryPools pools;
96  BigNumber tmp1;
97  BigNumber tmp2;
98  BigNumber tmp3;
99 
100 public:
101  CardinalityBase(int numVars = 0) :
102  numVars(numVars),
103  topLevel(0) {
104  }
105 
106  void initialize(int level) {
107  topLevel = level;
108  pools.resize(topLevel + 1);
109 
110  int max = ceil(double(topLevel) * log2(double(ARITY)) / 63.0) + 1;
111  tmp1.setArray(pools[topLevel].template allocate<uint64_t>(max));
112  tmp2.setArray(pools[topLevel].template allocate<uint64_t>(max));
113  tmp3.setArray(pools[topLevel].template allocate<uint64_t>(max));
114  }
115 
116  void evalTerminal(BigNumber& n, int value) {
117  n.setArray(pools[0].template allocate<uint64_t>(1));
118  n.store(value);
119  }
120 
121  void evalNode(BigNumber& n,
122  int i,
123  DdValues<BigNumber,ARITY> const& values) {
124  assert(0 <= i && size_t(i) <= pools.size());
125  if (BDD) {
126  size_t w = tmp1.store(0);
127  for (int b = 0; b < ARITY; ++b) {
128  tmp2.store(values.get(b));
129  int k = i - values.getLevel(b) - 1;
130  if (ARITY == 2) {
131  tmp2.shiftLeft(k);
132  }
133  else {
134  while (--k >= 0) {
135  tmp3.store(tmp2);
136  for (int b = 1; b < ARITY; ++b) {
137  tmp2.add(tmp3);
138  }
139  }
140  }
141  w = tmp1.add(tmp2);
142  }
143  n.setArray(pools[i].template allocate<uint64_t>(w));
144  n.store(tmp1);
145  }
146  else {
147  size_t w;
148  if (ARITY <= 0) {
149  w = tmp1.store(0);
150  }
151  else {
152  w = tmp1.store(values.get(0));
153  for (int b = 1; b < ARITY; ++b) {
154  w = tmp1.add(values.get(b));
155  }
156  }
157  n.setArray(pools[i].template allocate<uint64_t>(w));
158  n.store(tmp1);
159  }
160  }
161 
162  std::string getValue(BigNumber const& n) {
163  if (BDD) {
164  tmp2.store(n);
165  int k = numVars - topLevel;
166  if (ARITY == 2) {
167  tmp2.shiftLeft(k);
168  }
169  else {
170  while (--k >= 0) {
171  tmp3.store(tmp2);
172  for (int b = 1; b < ARITY; ++b) {
173  tmp2.add(tmp3);
174  }
175  }
176  }
177  return tmp2;
178  }
179  else {
180  return n;
181  }
182  }
183 
184  void destructLevel(int i) {
185  pools[i].clear();
186  }
187 };
188 
195 template<typename T = std::string, int AR = 2>
196 struct BddCardinality: public CardinalityBase<BddCardinality<T,AR>,T,AR,true> {
197  BddCardinality(int numVars) :
198  CardinalityBase<BddCardinality<T,AR>,T,AR,true>(numVars) {
199  }
200 };
201 
208 template<typename T = std::string, int AR = 2>
209 struct ZddCardinality: public CardinalityBase<ZddCardinality<T,AR>,T,AR,false> {
210 };
211 
212 } // namespace tdzdd
ZDD evaluator that counts the number of elements.
BDD evaluator that counts the number of elements.