1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Mudathir Mohamed, Gereon Kremer |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Bags theory rewriter. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY__BAGS__THEORY_BAGS_REWRITER_H |
19 |
|
#define CVC5__THEORY__BAGS__THEORY_BAGS_REWRITER_H |
20 |
|
|
21 |
|
#include "theory/bags/rewrites.h" |
22 |
|
#include "theory/theory_rewriter.h" |
23 |
|
#include "util/statistics_stats.h" |
24 |
|
|
25 |
|
namespace cvc5 { |
26 |
|
namespace theory { |
27 |
|
namespace bags { |
28 |
|
|
29 |
|
/** a class represents the result of rewriting bag nodes */ |
30 |
13944 |
struct BagsRewriteResponse |
31 |
|
{ |
32 |
|
BagsRewriteResponse(); |
33 |
|
BagsRewriteResponse(Node n, Rewrite rewrite); |
34 |
|
BagsRewriteResponse(const BagsRewriteResponse& r); |
35 |
|
/** the rewritten node */ |
36 |
|
Node d_node; |
37 |
|
/** type of rewrite used by bags */ |
38 |
|
Rewrite d_rewrite; |
39 |
|
|
40 |
|
}; /* struct BagsRewriteResponse */ |
41 |
|
|
42 |
15394 |
class BagsRewriter : public TheoryRewriter |
43 |
|
{ |
44 |
|
public: |
45 |
|
BagsRewriter(HistogramStat<Rewrite>* statistics = nullptr); |
46 |
|
|
47 |
|
/** |
48 |
|
* postRewrite nodes with kinds: MK_BAG, BAG_COUNT, UNION_MAX, UNION_DISJOINT, |
49 |
|
* INTERSECTION_MIN, DIFFERENCE_SUBTRACT, DIFFERENCE_REMOVE, BAG_CHOOSE, |
50 |
|
* BAG_CARD, BAG_IS_SINGLETON. |
51 |
|
* See the rewrite rules for these kinds below. |
52 |
|
*/ |
53 |
|
RewriteResponse postRewrite(TNode n) override; |
54 |
|
/** |
55 |
|
* preRewrite nodes with kinds: EQUAL, SUBBAG. |
56 |
|
* See the rewrite rules for these kinds below. |
57 |
|
*/ |
58 |
|
RewriteResponse preRewrite(TNode n) override; |
59 |
|
|
60 |
|
private: |
61 |
|
/** |
62 |
|
* rewrites for n include: |
63 |
|
* - (= A A) = true where A is a bag |
64 |
|
*/ |
65 |
|
BagsRewriteResponse preRewriteEqual(const TNode& n) const; |
66 |
|
|
67 |
|
/** |
68 |
|
* rewrites for n include: |
69 |
|
* - (bag.is_included A B) = ((difference_subtract A B) == emptybag) |
70 |
|
*/ |
71 |
|
BagsRewriteResponse rewriteSubBag(const TNode& n) const; |
72 |
|
|
73 |
|
/** |
74 |
|
* rewrites for n include: |
75 |
|
* - (bag x 0) = (emptybag T) where T is the type of x |
76 |
|
* - (bag x (-c)) = (emptybag T) where T is the type of x, and c > 0 is a |
77 |
|
* constant |
78 |
|
* - otherwise = n |
79 |
|
*/ |
80 |
|
BagsRewriteResponse rewriteMakeBag(const TNode& n) const; |
81 |
|
|
82 |
|
/** |
83 |
|
* rewrites for n include: |
84 |
|
* - (bag.count x emptybag) = 0 |
85 |
|
* - (bag.count x (bag x c)) = (ite (>= c 1) c 0) |
86 |
|
* - otherwise = n |
87 |
|
*/ |
88 |
|
BagsRewriteResponse rewriteBagCount(const TNode& n) const; |
89 |
|
|
90 |
|
/** |
91 |
|
* rewrites for n include: |
92 |
|
* - (duplicate_removal (bag x n)) = (bag x 1) |
93 |
|
* where n is a positive constant |
94 |
|
*/ |
95 |
|
BagsRewriteResponse rewriteDuplicateRemoval(const TNode& n) const; |
96 |
|
|
97 |
|
/** |
98 |
|
* rewrites for n include: |
99 |
|
* - (union_max A emptybag) = A |
100 |
|
* - (union_max emptybag A) = A |
101 |
|
* - (union_max A A) = A |
102 |
|
* - (union_max A (union_max A B)) = (union_max A B) |
103 |
|
* - (union_max A (union_max B A)) = (union_max B A) |
104 |
|
* - (union_max (union_max A B) A) = (union_max A B) |
105 |
|
* - (union_max (union_max B A) A) = (union_max B A) |
106 |
|
* - (union_max A (union_disjoint A B)) = (union_disjoint A B) |
107 |
|
* - (union_max A (union_disjoint B A)) = (union_disjoint B A) |
108 |
|
* - (union_max (union_disjoint A B) A) = (union_disjoint A B) |
109 |
|
* - (union_max (union_disjoint B A) A) = (union_disjoint B A) |
110 |
|
* - otherwise = n |
111 |
|
*/ |
112 |
|
BagsRewriteResponse rewriteUnionMax(const TNode& n) const; |
113 |
|
|
114 |
|
/** |
115 |
|
* rewrites for n include: |
116 |
|
* - (union_disjoint A emptybag) = A |
117 |
|
* - (union_disjoint emptybag A) = A |
118 |
|
* - (union_disjoint (union_max A B) (intersection_min A B)) = |
119 |
|
* (union_disjoint A B) // sum(a,b) = max(a,b) + min(a,b) |
120 |
|
* - other permutations of the above like swapping A and B, or swapping |
121 |
|
* intersection_min and union_max |
122 |
|
* - otherwise = n |
123 |
|
*/ |
124 |
|
BagsRewriteResponse rewriteUnionDisjoint(const TNode& n) const; |
125 |
|
|
126 |
|
/** |
127 |
|
* rewrites for n include: |
128 |
|
* - (intersection_min A emptybag) = emptybag |
129 |
|
* - (intersection_min emptybag A) = emptybag |
130 |
|
* - (intersection_min A A) = A |
131 |
|
* - (intersection_min A (union_disjoint A B)) = A |
132 |
|
* - (intersection_min A (union_disjoint B A)) = A |
133 |
|
* - (intersection_min (union_disjoint A B) A) = A |
134 |
|
* - (intersection_min (union_disjoint B A) A) = A |
135 |
|
* - (intersection_min A (union_max A B)) = A |
136 |
|
* - (intersection_min A (union_max B A)) = A |
137 |
|
* - (intersection_min (union_max A B) A) = A |
138 |
|
* - (intersection_min (union_max B A) A) = A |
139 |
|
* - otherwise = n |
140 |
|
*/ |
141 |
|
BagsRewriteResponse rewriteIntersectionMin(const TNode& n) const; |
142 |
|
|
143 |
|
/** |
144 |
|
* rewrites for n include: |
145 |
|
* - (difference_subtract A emptybag) = A |
146 |
|
* - (difference_subtract emptybag A) = emptybag |
147 |
|
* - (difference_subtract A A) = emptybag |
148 |
|
* - (difference_subtract (union_disjoint A B) A) = B |
149 |
|
* - (difference_subtract (union_disjoint B A) A) = B |
150 |
|
* - (difference_subtract A (union_disjoint A B)) = emptybag |
151 |
|
* - (difference_subtract A (union_disjoint B A)) = emptybag |
152 |
|
* - (difference_subtract A (union_max A B)) = emptybag |
153 |
|
* - (difference_subtract A (union_max B A)) = emptybag |
154 |
|
* - (difference_subtract (intersection_min A B) A) = emptybag |
155 |
|
* - (difference_subtract (intersection_min B A) A) = emptybag |
156 |
|
* - otherwise = n |
157 |
|
*/ |
158 |
|
BagsRewriteResponse rewriteDifferenceSubtract(const TNode& n) const; |
159 |
|
|
160 |
|
/** |
161 |
|
* rewrites for n include: |
162 |
|
* - (difference_remove A emptybag) = A |
163 |
|
* - (difference_remove emptybag A) = emptybag |
164 |
|
* - (difference_remove A A) = emptybag |
165 |
|
* - (difference_remove A (union_disjoint A B)) = emptybag |
166 |
|
* - (difference_remove A (union_disjoint B A)) = emptybag |
167 |
|
* - (difference_remove A (union_max A B)) = emptybag |
168 |
|
* - (difference_remove A (union_max B A)) = emptybag |
169 |
|
* - (difference_remove (intersection_min A B) A) = emptybag |
170 |
|
* - (difference_remove (intersection_min B A) A) = emptybag |
171 |
|
* - otherwise = n |
172 |
|
*/ |
173 |
|
BagsRewriteResponse rewriteDifferenceRemove(const TNode& n) const; |
174 |
|
/** |
175 |
|
* rewrites for n include: |
176 |
|
* - (bag.choose (bag x c)) = x where c is a constant > 0 |
177 |
|
* - otherwise = n |
178 |
|
*/ |
179 |
|
BagsRewriteResponse rewriteChoose(const TNode& n) const; |
180 |
|
/** |
181 |
|
* rewrites for n include: |
182 |
|
* - (bag.card (bag x c)) = c where c is a constant > 0 |
183 |
|
* - (bag.card (union-disjoint A B)) = (+ (bag.card A) (bag.card B)) |
184 |
|
* - otherwise = n |
185 |
|
*/ |
186 |
|
BagsRewriteResponse rewriteCard(const TNode& n) const; |
187 |
|
|
188 |
|
/** |
189 |
|
* rewrites for n include: |
190 |
|
* - (bag.is_singleton (bag x c)) = (c == 1) |
191 |
|
*/ |
192 |
|
BagsRewriteResponse rewriteIsSingleton(const TNode& n) const; |
193 |
|
|
194 |
|
/** |
195 |
|
* rewrites for n include: |
196 |
|
* - (bag.from_set (singleton (singleton_op Int) x)) = (bag x 1) |
197 |
|
*/ |
198 |
|
BagsRewriteResponse rewriteFromSet(const TNode& n) const; |
199 |
|
|
200 |
|
/** |
201 |
|
* rewrites for n include: |
202 |
|
* - (bag.to_set (bag x n)) = (singleton (singleton_op T) x) |
203 |
|
* where n is a positive constant and T is the type of the bag's elements |
204 |
|
*/ |
205 |
|
BagsRewriteResponse rewriteToSet(const TNode& n) const; |
206 |
|
|
207 |
|
/** |
208 |
|
* rewrites for n include: |
209 |
|
* - (= A A) = true |
210 |
|
* - (= A B) = false if A and B are different bag constants |
211 |
|
* - (= B A) = (= A B) if A < B and at least one of A or B is not a constant |
212 |
|
*/ |
213 |
|
BagsRewriteResponse postRewriteEqual(const TNode& n) const; |
214 |
|
|
215 |
|
/** |
216 |
|
* rewrites for n include: |
217 |
|
* - (bag.map (lambda ((x U)) t) emptybag) = emptybag |
218 |
|
* - (bag.map (lambda ((x U)) t) (bag y z)) = (bag (apply (lambda ((x U)) t) |
219 |
|
* y) z) |
220 |
|
* - (bag.map (lambda ((x U)) t) (union_disjoint A B)) = |
221 |
|
* (union_disjoint |
222 |
|
* (bag ((lambda ((x U)) t) "a") 3) |
223 |
|
* (bag ((lambda ((x U)) t) "b") 4)) |
224 |
|
* |
225 |
|
*/ |
226 |
|
BagsRewriteResponse postRewriteMap(const TNode& n) const; |
227 |
|
|
228 |
|
private: |
229 |
|
/** Reference to the rewriter statistics. */ |
230 |
|
NodeManager* d_nm; |
231 |
|
Node d_zero; |
232 |
|
Node d_one; |
233 |
|
/** Reference to the rewriter statistics. */ |
234 |
|
HistogramStat<Rewrite>* d_statistics; |
235 |
|
}; /* class TheoryBagsRewriter */ |
236 |
|
|
237 |
|
} // namespace bags |
238 |
|
} // namespace theory |
239 |
|
} // namespace cvc5 |
240 |
|
|
241 |
|
#endif /* CVC5__THEORY__BAGS__THEORY_BAGS_REWRITER_H */ |