Skip to content

Commit fa3d614

Browse files
Ovascosahmed-irfan
andauthored
Fixes by SMT-RAT (#105)
* fixes provided by SMT-RAT * code updates * update comment * Added C++ interface and test for lp_polynomial_constraint_evaluate_subs and added missing `Value(int)` constructor. --------- Co-authored-by: Thomas Hader <[email protected]> Co-authored-by: Ahmed Irfan <[email protected]>
1 parent adb1094 commit fa3d614

File tree

8 files changed

+113
-7
lines changed

8 files changed

+113
-7
lines changed

include/polynomial.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ void lp_polynomial_lc_constant(const lp_polynomial_t* A, lp_integer_t *out);
109109
/** Get the context of the given polynomial */
110110
const lp_polynomial_context_t* lp_polynomial_get_context(const lp_polynomial_t* A);
111111

112+
/**
113+
* Sets the context of a polynomial.
114+
* Warning: variable DB indexes are not checked. Use with caution.
115+
*/
116+
void lp_polynomial_set_context(lp_polynomial_t* A, const lp_polynomial_context_t* ctx);
117+
112118
/** Returns all the variables (it will not clear the output list vars) */
113119
void lp_polynomial_get_variables(const lp_polynomial_t* A, lp_variable_list_t* vars);
114120

@@ -375,6 +381,12 @@ lp_polynomial_t* lp_polynomial_constraint_explain_infer_bounds(const lp_polynomi
375381
*/
376382
int lp_polynomial_constraint_evaluate(const lp_polynomial_t* A, lp_sign_condition_t sgn_condition, const lp_assignment_t* M);
377383

384+
/**
385+
* Substitutes the polynomial with M and checks the sign of the resulting real number.
386+
* If M does not fully evaluate A to a real, -1 is returned.
387+
*/
388+
int lp_polynomial_constraint_evaluate_subs(const lp_polynomial_t* A, lp_sign_condition_t sgn_condition, const lp_assignment_t* M);
389+
378390
/**
379391
* Given a polynomial constraint over an integer ring Zp, evaluate its truth value.
380392
* sgn_condition must either be (== 0) or (!= 0) and M must assign to Zp.

include/polyxx/polynomial.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ namespace poly {
117117
* assignment. */
118118
bool is_assigned_over_assignment(const Polynomial& p, const Assignment& a);
119119
/** Evaluates p over a given assignment and returns an univariate polynomial.
120-
* Assumes that a assigns all variable in p but the top variable.
121-
* Assumes that a assigns to integer only. */
120+
* Assumes that 'a' assigns all variable in p but the top variable.
121+
* Assumes that 'a' assigns to integer only. */
122122
UPolynomial to_univariate(const Polynomial& p, const Assignment& a);
123123
/** Compute the sign of a polynomial over an assignment. */
124124
int sgn(const Polynomial& p, const Assignment& a);
@@ -127,6 +127,11 @@ namespace poly {
127127
/** Evaluate a polynomial constraint over an assignment. */
128128
bool evaluate_constraint(const Polynomial& p, const Assignment& a,
129129
SignCondition sc);
130+
/** Checks if a polynomial constraint is fully evaluated over assignment.
131+
* Returns -1 if 'a' does not fully evaluate the constraint.
132+
* Otherwise, returns true if the constraint holds under 'a'. */
133+
int evaluate_constraint_subs(const Polynomial& p, const Assignment& a,
134+
SignCondition sc);
130135
/** Evaluate a polynomial over an interval assignment. The result is only an
131136
* approximation. */
132137
Interval evaluate(const Polynomial& p, const IntervalAssignment& a);

include/polyxx/value.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ namespace poly {
2929
/** Construct a none value. */
3030
Value();
3131
/** Construct from a native integer. */
32+
Value(int i);
33+
/** Construct from a native integer. */
3234
Value(long i);
3335
/** Copy from the given Value. */
3436
Value(const Value& val);

src/polynomial/polynomial.c

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,14 @@ void lp_polynomial_roots_isolate(const lp_polynomial_t* A, const lp_assignment_t
11771177
lp_value_construct_none(&x_value_backup);
11781178
}
11791179

1180+
lp_polynomial_t B;
1181+
lp_polynomial_construct(&B, A->ctx);
1182+
1183+
lp_integer_t multiplier;
1184+
integer_construct(&multiplier);
1185+
coefficient_evaluate_rationals(A->ctx, &A->data, M, &B.data, &multiplier);
1186+
integer_destruct(&multiplier);
1187+
11801188
size_t i;
11811189

11821190
lp_polynomial_t** factors = 0;
@@ -1190,11 +1198,12 @@ void lp_polynomial_roots_isolate(const lp_polynomial_t* A, const lp_assignment_t
11901198
// Get the reduced polynomial
11911199
lp_polynomial_t A_r;
11921200
lp_polynomial_construct(&A_r, A->ctx);
1193-
lp_polynomial_reductum_m(&A_r, A, M);
1194-
assert(x == lp_polynomial_top_variable(A));
1195-
1196-
// Get the square-free factorization
1197-
lp_polynomial_factor_square_free(&A_r, &factors, &multiplicities, &factors_size);
1201+
if (x == lp_polynomial_top_variable(&B)) {
1202+
lp_polynomial_reductum_m(&A_r, &B, M);
1203+
assert(x == lp_polynomial_top_variable(&B));
1204+
// Get the square-free factorization
1205+
lp_polynomial_factor_square_free(&A_r, &factors, &multiplicities, &factors_size);
1206+
}
11981207

11991208
// Count the max number of roots
12001209
size_t total_degree = 0;
@@ -1297,6 +1306,7 @@ void lp_polynomial_roots_isolate(const lp_polynomial_t* A, const lp_assignment_t
12971306
free(roots_tmp);
12981307
lp_value_destruct(&x_value_backup);
12991308
lp_polynomial_destruct(&A_r);
1309+
lp_polynomial_destruct(&B);
13001310
}
13011311

13021312
lp_feasibility_set_t* lp_polynomial_constraint_get_feasible_set(const lp_polynomial_t* A, lp_sign_condition_t sgn_condition, int negated, const lp_assignment_t* M) {
@@ -2134,6 +2144,29 @@ int lp_polynomial_constraint_evaluate(const lp_polynomial_t* A, lp_sign_conditio
21342144
return lp_sign_condition_consistent(sgn_condition, p_sign);
21352145
}
21362146

2147+
int lp_polynomial_constraint_evaluate_subs(const lp_polynomial_t* A, lp_sign_condition_t sgn_condition, const lp_assignment_t* M) {
2148+
coefficient_t A_rat;
2149+
lp_integer_t multiplier;
2150+
2151+
lp_polynomial_external_clean(A);
2152+
assert(A->ctx->K == lp_Z);
2153+
2154+
integer_construct(&multiplier);
2155+
coefficient_construct(A->ctx, &A_rat);
2156+
coefficient_evaluate_rationals(A->ctx, &A->data, M, &A_rat, &multiplier);
2157+
integer_destruct(&multiplier);
2158+
2159+
int res = -1;
2160+
if (A_rat.type == COEFFICIENT_NUMERIC) {
2161+
int sgn = integer_sgn(lp_Z, &A_rat.value.num);
2162+
res = lp_sign_condition_consistent(sgn_condition, sgn);
2163+
assert(res >= 0);
2164+
}
2165+
2166+
coefficient_destruct(&A_rat);
2167+
return res;
2168+
}
2169+
21372170
int lp_polynomial_constraint_evaluate_Zp(const lp_polynomial_t* A, lp_sign_condition_t sgn_condition, const lp_assignment_t* m) {
21382171

21392172
lp_polynomial_external_clean(A);

src/polyxx/polynomial.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ namespace poly {
165165
return lp_polynomial_constraint_evaluate(
166166
p.get_internal(), to_sign_condition(sc), a.get_internal());
167167
}
168+
int evaluate_constraint_subs(const Polynomial& p, const Assignment& a,
169+
SignCondition sc) {
170+
return lp_polynomial_constraint_evaluate_subs(
171+
p.get_internal(), to_sign_condition(sc), a.get_internal());
172+
}
168173
Interval evaluate(const Polynomial& p, const IntervalAssignment& a) {
169174
Interval res;
170175
lp_polynomial_interval_value(p.get_internal(), a.get_internal(),

src/polyxx/value.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace poly {
1313
}
1414

1515
Value::Value() { lp_value_construct_none(&mValue); }
16+
Value::Value(int i) { lp_value_construct_int(get_internal(), i); }
1617
Value::Value(long i) { lp_value_construct_int(get_internal(), i); }
1718
Value::Value(const Value& val) {
1819
lp_value_construct_copy(get_internal(), val.get_internal());

src/variable/variable_db.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ void lp_variable_db_add_variable(lp_variable_db_t* var_db, lp_variable_t var, co
6363
assert(var_db);
6464
while (var >= var_db->capacity) {
6565
lp_variable_db_resize(var_db, 2*var_db->capacity);
66+
var_db->size = var_db->capacity < var ? var_db->capacity : var;
6667
}
6768
assert(var_db->variable_names[var] == 0);
6869
var_db->variable_names[var] = strdup(name);
70+
var_db->size = var_db->size < var ? var : var_db->size;
6971
}
7072

7173
void lp_variable_db_construct(lp_variable_db_t* var_db) {

test/polyxx/test_polynomial.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,49 @@ TEST_CASE("polynomial::constructor") {
100100
CHECK(p_cp == p_cp_a);
101101
CHECK(ptr == p_mv_a.get_internal());
102102
}
103+
104+
TEST_CASE("polynomial::evaluate") {
105+
Variable x("x");
106+
Variable y("y");
107+
Polynomial p1 = 1 * pow(x, 6) + 2 * pow(x, 5) + 3 * y - 1;
108+
Polynomial p2 = 1 * y * pow(x + 1, 4);
109+
110+
// full assignment
111+
Assignment a;
112+
a.set(x, -1);
113+
a.set(y, 2);
114+
CHECK(a.has(x));
115+
CHECK(a.has(y));
116+
117+
CHECK(evaluate(p1, a) == Value(4));
118+
CHECK(evaluate_constraint(p1, a, SignCondition::GE) == true);
119+
CHECK(evaluate_constraint(p1, a, SignCondition::LT) == false);
120+
CHECK(evaluate_constraint(p1, a, SignCondition::EQ) == false);
121+
CHECK(evaluate_constraint_subs(p1, a, SignCondition::GE) == 1);
122+
CHECK(evaluate_constraint_subs(p1, a, SignCondition::LT) == 0);
123+
CHECK(evaluate_constraint_subs(p1, a, SignCondition::EQ) == 0);
124+
125+
CHECK(evaluate(p2, a) == Value(0));
126+
CHECK(evaluate_constraint(p2, a, SignCondition::GE) == true);
127+
CHECK(evaluate_constraint(p2, a, SignCondition::LT) == false);
128+
CHECK(evaluate_constraint(p2, a, SignCondition::EQ) == true);
129+
CHECK(evaluate_constraint_subs(p2, a, SignCondition::GE) == 1);
130+
CHECK(evaluate_constraint_subs(p2, a, SignCondition::LT) == 0);
131+
CHECK(evaluate_constraint_subs(p2, a, SignCondition::EQ) == 1);
132+
133+
// partial assignment
134+
a.unset(y);
135+
CHECK(a.has(x));
136+
CHECK(!a.has(y));
137+
138+
CHECK(evaluate_constraint_subs(p1, a, SignCondition::GE) == -1);
139+
CHECK(evaluate_constraint_subs(p1, a, SignCondition::LT) == -1);
140+
CHECK(evaluate_constraint_subs(p1, a, SignCondition::EQ) == -1);
141+
142+
CHECK(evaluate_constraint(p2, a, SignCondition::GE) == true);
143+
CHECK(evaluate_constraint(p2, a, SignCondition::LT) == false);
144+
CHECK(evaluate_constraint(p2, a, SignCondition::EQ) == true);
145+
CHECK(evaluate_constraint_subs(p2, a, SignCondition::GE) == 1);
146+
CHECK(evaluate_constraint_subs(p2, a, SignCondition::LT) == 0);
147+
CHECK(evaluate_constraint_subs(p2, a, SignCondition::EQ) == 1);
148+
}

0 commit comments

Comments
 (0)