@@ -80,113 +80,175 @@ namespace nla {
80
80
81
81
lbool powers::check (lpvar r, lpvar x, lpvar y, vector<lemma>& lemmas) {
82
82
TRACE (" nla" , tout << r << " == " << x << " ^" << y << " \n " );
83
- core& c = m_core;
83
+ core& c = m_core;
84
84
if (x == null_lpvar || y == null_lpvar || r == null_lpvar)
85
85
return l_undef;
86
- if (c.lra .column_has_term (x) || c.lra .column_has_term (y) || c.lra .column_has_term (r))
87
- return l_undef;
88
-
89
- if (c.use_nra_model ())
90
- return l_undef;
91
-
92
- auto xval = c.val (x);
93
- auto yval = c.val (y);
94
- auto rval = c.val (r);
86
+ // if (c.lra.column_has_term(x) || c.lra.column_has_term(y) || c.lra.column_has_term(r))
87
+ // return l_undef;
95
88
96
89
lemmas.reset ();
97
90
98
- if (xval != 0 && yval == 0 && rval != 1 ) {
91
+ auto x_exp_0 = [&]( ) {
99
92
new_lemma lemma (c, " x != 0 => x^0 = 1" );
100
93
lemma |= ineq (x, llc::EQ, rational::zero ());
101
94
lemma |= ineq (y, llc::NE, rational::zero ());
102
95
lemma |= ineq (r, llc::EQ, rational::one ());
103
96
return l_false;
104
- }
97
+ };
105
98
106
- if (xval == 0 && yval != 0 && rval != 0 ) {
99
+ auto zero_exp_y = [&]( ) {
107
100
new_lemma lemma (c, " y != 0 => 0^y = 0" );
108
101
lemma |= ineq (x, llc::NE, rational::zero ());
109
102
lemma |= ineq (y, llc::EQ, rational::zero ());
110
103
lemma |= ineq (r, llc::EQ, rational::zero ());
111
104
return l_false;
112
- }
105
+ };
113
106
114
- if (xval > 0 && rval <= 0 ) {
107
+ auto x_gt_0 = [&]( ) {
115
108
new_lemma lemma (c, " x > 0 => x^y > 0" );
116
109
lemma |= ineq (x, llc::LE, rational::zero ());
117
110
lemma |= ineq (r, llc::GT, rational::zero ());
118
111
return l_false;
119
- }
112
+ };
120
113
121
- if (xval > 1 && yval < 0 && rval >= 1 ) {
114
+ auto y_lt_1 = [&]( ) {
122
115
new_lemma lemma (c, " x > 1, y < 0 => x^y < 1" );
123
116
lemma |= ineq (x, llc::LE, rational::one ());
124
117
lemma |= ineq (y, llc::GE, rational::zero ());
125
118
lemma |= ineq (r, llc::LT, rational::one ());
126
119
return l_false;
127
- }
120
+ };
128
121
129
- if (xval > 1 && yval > 0 && rval <= 1 ) {
122
+ auto y_gt_1 = [&]( ) {
130
123
new_lemma lemma (c, " x > 1, y > 0 => x^y > 1" );
131
124
lemma |= ineq (x, llc::LE, rational::one ());
132
125
lemma |= ineq (y, llc::LE, rational::zero ());
133
126
lemma |= ineq (r, llc::GT, rational::one ());
134
127
return l_false;
135
- }
128
+ };
136
129
137
- if (xval >= 3 && yval != 0 && rval <= yval + 1 ) {
130
+ auto x_ge_3 = [&]( ) {
138
131
new_lemma lemma (c, " x >= 3, y != 0 => x^y > ln(x)y + 1" );
139
132
lemma |= ineq (x, llc::LT, rational (3 ));
140
133
lemma |= ineq (y, llc::EQ, rational::zero ());
141
134
lemma |= ineq (lp::lar_term (r, rational::minus_one (), y), llc::GT, rational::one ());
142
135
return l_false;
136
+ };
137
+
138
+ bool use_rational = !c.use_nra_model ();
139
+ rational xval, yval, rval;
140
+ if (use_rational) {
141
+ xval = c.val (x);
142
+ yval = c.val (y);
143
+ rval = c.val (r);
144
+ }
145
+ else {
146
+ auto & am = c.m_nra .am ();
147
+ if (am.is_rational (c.m_nra .value (x)) &&
148
+ am.is_rational (c.m_nra .value (y)) &&
149
+ am.is_rational (c.m_nra .value (r))) {
150
+ am.to_rational (c.m_nra .value (x), xval);
151
+ am.to_rational (c.m_nra .value (y), yval);
152
+ am.to_rational (c.m_nra .value (r), rval);
153
+ use_rational = true ;
154
+ }
143
155
}
144
156
145
- if (xval > 0 && yval.is_unsigned ()) {
146
- auto r2val = power (xval, yval.get_unsigned ());
147
- if (rval == r2val)
148
- return l_true;
149
- if (c.random () % 2 == 0 ) {
150
- new_lemma lemma (c, " x == x0, y == y0 => r = x0^y0" );
151
- lemma |= ineq (x, llc::NE, xval);
152
- lemma |= ineq (y, llc::NE, yval);
153
- lemma |= ineq (r, llc::EQ, r2val);
154
- return l_false;
157
+ if (use_rational) {
158
+ auto xval = c.val (x);
159
+ auto yval = c.val (y);
160
+ auto rval = c.val (r);
161
+ if (xval != 0 && yval == 0 && rval != 1 )
162
+ return x_exp_0 ();
163
+ else if (xval == 0 && yval != 0 && rval != 0 )
164
+ return zero_exp_y ();
165
+ else if (xval > 0 && rval <= 0 )
166
+ return x_gt_0 ();
167
+ else if (xval > 1 && yval < 0 && rval >= 1 )
168
+ return y_lt_1 ();
169
+ else if (xval > 1 && yval > 0 && rval <= 1 )
170
+ return y_gt_1 ();
171
+ else if (xval >= 3 && yval != 0 && rval <= yval + 1 )
172
+ return x_ge_3 ();
173
+ else if (xval > 0 && yval.is_unsigned ()) {
174
+ auto r2val = power (xval, yval.get_unsigned ());
175
+ if (rval == r2val)
176
+ return l_true;
177
+ if (c.random () % 2 == 0 ) {
178
+ new_lemma lemma (c, " x == x0, y == y0 => r = x0^y0" );
179
+ lemma |= ineq (x, llc::NE, xval);
180
+ lemma |= ineq (y, llc::NE, yval);
181
+ lemma |= ineq (r, llc::EQ, r2val);
182
+ return l_false;
183
+ }
184
+ if (yval > 0 && r2val > rval) {
185
+ new_lemma lemma (c, " x >= x0 > 0, y >= y0 > 0 => r >= x0^y0" );
186
+ lemma |= ineq (x, llc::LT, xval);
187
+ lemma |= ineq (y, llc::LT, yval);
188
+ lemma |= ineq (r, llc::GE, r2val);
189
+ return l_false;
190
+ }
191
+ if (r2val < rval) {
192
+ new_lemma lemma (c, " 0 < x <= x0, y <= y0 => r <= x0^y0" );
193
+ lemma |= ineq (x, llc::LE, rational::zero ());
194
+ lemma |= ineq (x, llc::GT, xval);
195
+ lemma |= ineq (y, llc::GT, yval);
196
+ lemma |= ineq (r, llc::LE, r2val);
197
+ return l_false;
198
+ }
155
199
}
156
- if (yval > 0 && r2val > rval) {
157
- new_lemma lemma (c, " x >= x0 > 0, y >= y0 > 0 => r >= x0^y0" );
158
- lemma |= ineq (x, llc::LT, xval);
159
- lemma |= ineq (y, llc::LT, yval);
160
- lemma |= ineq (r, llc::GE, r2val);
161
- return l_false;
200
+ if (xval > 0 && yval > 0 && !yval.is_int ()) {
201
+ auto ynum = numerator (yval);
202
+ auto yden = denominator (yval);
203
+ // r = x^{yn/yd}
204
+ // <=>
205
+ // r^yd = x^yn
206
+ if (ynum.is_unsigned () && yden.is_unsigned ()) {
207
+ auto ryd = power (rval, yden.get_unsigned ());
208
+ auto xyn = power (xval, ynum.get_unsigned ());
209
+ if (ryd == xyn)
210
+ return l_true;
211
+ }
162
212
}
163
- if (r2val < rval) {
164
- new_lemma lemma (c, " 0 < x <= x0, y <= y0 => r <= x0^y0" );
165
- lemma |= ineq (x, llc::LE, rational::zero ());
166
- lemma |= ineq (x, llc::GT, xval);
167
- lemma |= ineq (y, llc::GT, yval);
168
- lemma |= ineq (r, llc::LE, r2val);
169
- return l_false;
170
- }
171
- }
172
- if (xval > 0 && yval > 0 && !yval.is_int ()) {
173
- auto ynum = numerator (yval);
174
- auto yden = denominator (yval);
175
- if (!ynum.is_unsigned ())
176
- return l_undef;
177
- if (!yden.is_unsigned ())
178
- return l_undef;
179
- // r = x^{yn/yd}
180
- // <=>
181
- // r^yd = x^yn
182
- auto ryd = power (rval, yden.get_unsigned ());
183
- auto xyn = power (xval, ynum.get_unsigned ());
184
- if (ryd == xyn)
185
- return l_true;
186
213
}
187
214
188
- return l_undef;
215
+ if (!use_rational) {
216
+ auto & am = c.m_nra .am ();
217
+ scoped_anum xval (am), yval (am), rval (am);
218
+ am.set (xval, c.m_nra .value (x));
219
+ am.set (yval, c.m_nra .value (y));
220
+ am.set (rval, c.m_nra .value (r));
221
+ if (xval != 0 && yval == 0 && rval != 1 )
222
+ return x_exp_0 ();
223
+ else if (xval == 0 && yval != 0 && rval != 0 )
224
+ return zero_exp_y ();
225
+ else if (xval > 0 && rval <= 0 )
226
+ return x_gt_0 ();
227
+ else if (xval > 1 && yval < 0 && rval >= 1 )
228
+ return y_lt_1 ();
229
+ else if (xval > 1 && yval > 0 && rval <= 1 )
230
+ return y_gt_1 ();
231
+ else if (xval >= 3 && yval != 0 && rval <= yval + 1 )
232
+ return x_ge_3 ();
233
+ else if (xval > 0 && yval > 0 && am.is_rational (yval)) {
234
+ rational yr;
235
+ am.to_rational (yval, yr);
236
+ auto ynum = numerator (yr);
237
+ auto yden = denominator (yr);
238
+ // r = x^{yn/yd}
239
+ // <=>
240
+ // r^yd = x^yn
241
+ if (ynum.is_unsigned () && yden.is_unsigned ()) {
242
+ am.set (rval, power (rval, yden.get_unsigned ()));
243
+ am.set (xval, power (xval, ynum.get_unsigned ()));
244
+ if (rval == xval)
245
+ return l_true;
246
+ }
247
+ }
248
+ }
189
249
250
+ return l_undef;
190
251
}
252
+
191
253
192
254
}
0 commit comments