mirror of
https://github.com/Z3Prover/z3
synced 2025-10-08 00:41:56 +00:00
104 lines
No EOL
3.7 KiB
C++
104 lines
No EOL
3.7 KiB
C++
#include "z3++.h"
|
|
#include <iostream>
|
|
|
|
using namespace z3;
|
|
|
|
void test_pb_max_pattern() {
|
|
std::cout << "Testing PB max pattern detection\n";
|
|
|
|
context c;
|
|
|
|
// Create boolean variables
|
|
expr x1 = c.bool_const("x1");
|
|
expr x2 = c.bool_const("x2");
|
|
expr x3 = c.bool_const("x3");
|
|
expr y1 = c.bool_const("y1");
|
|
expr y2 = c.bool_const("y2");
|
|
expr z1 = c.bool_const("z1");
|
|
expr z2 = c.bool_const("z2");
|
|
expr z3 = c.bool_const("z3");
|
|
|
|
// Create PB constraints like weighted sums
|
|
expr pb1 = 2*ite(x1, c.int_val(1), c.int_val(0)) + 3*ite(x2, c.int_val(1), c.int_val(0)) + ite(x3, c.int_val(1), c.int_val(0)); // potential max = 6
|
|
expr pb2 = ite(y1, c.int_val(1), c.int_val(0)) + 2*ite(y2, c.int_val(1), c.int_val(0)); // potential max = 3
|
|
expr pb3 = ite(z1, c.int_val(1), c.int_val(0)) + ite(z2, c.int_val(1), c.int_val(0)) + ite(z3, c.int_val(1), c.int_val(0)); // potential max = 3
|
|
|
|
optimize opt(c);
|
|
|
|
// The pattern the issue might be referring to:
|
|
// Instead of maximizing pb1 + pb2 + pb3 directly,
|
|
// we should detect the pattern and introduce auxiliary variables
|
|
|
|
// Current approach: maximize pb1 + pb2 + pb3
|
|
opt.maximize(pb1 + pb2 + pb3);
|
|
|
|
std::cout << "check: " << opt.check() << std::endl;
|
|
|
|
if (opt.check() == sat) {
|
|
model m = opt.get_model();
|
|
std::cout << "Model: " << m << std::endl;
|
|
|
|
// Get objective values
|
|
std::cout << "Objectives: " << opt.objectives().size() << std::endl;
|
|
}
|
|
}
|
|
|
|
void test_pb_max_with_constraints() {
|
|
std::cout << "\nTesting what the issue might want - auxiliary variables\n";
|
|
|
|
context c;
|
|
|
|
// Create boolean variables
|
|
expr x1 = c.bool_const("x1");
|
|
expr x2 = c.bool_const("x2");
|
|
expr y1 = c.bool_const("y1");
|
|
expr y2 = c.bool_const("y2");
|
|
|
|
// PB expressions
|
|
expr pb1 = 2*ite(x1, c.int_val(1), c.int_val(0)) + ite(x2, c.int_val(1), c.int_val(0)); // max = 3
|
|
expr pb2 = ite(y1, c.int_val(1), c.int_val(0)) + 2*ite(y2, c.int_val(1), c.int_val(0)); // max = 3
|
|
|
|
optimize opt(c);
|
|
|
|
// What the issue might want: auxiliary variables p_k for each threshold k
|
|
// For pb1: p1_1, p1_2, p1_3 where pb1 >= k => p1_k
|
|
// For pb2: p2_1, p2_2, p2_3 where pb2 >= k => p2_k
|
|
// Then maximize: p1_1 + p1_2 + p1_3 + p2_1 + p2_2 + p2_3
|
|
|
|
expr p1_1 = c.bool_const("p1_1");
|
|
expr p1_2 = c.bool_const("p1_2");
|
|
expr p1_3 = c.bool_const("p1_3");
|
|
expr p2_1 = c.bool_const("p2_1");
|
|
expr p2_2 = c.bool_const("p2_2");
|
|
expr p2_3 = c.bool_const("p2_3");
|
|
|
|
// Add constraints: pb_i >= k => p_k
|
|
opt.add(implies(pb1 >= 1, p1_1));
|
|
opt.add(implies(pb1 >= 2, p1_2));
|
|
opt.add(implies(pb1 >= 3, p1_3));
|
|
opt.add(implies(pb2 >= 1, p2_1));
|
|
opt.add(implies(pb2 >= 2, p2_2));
|
|
opt.add(implies(pb2 >= 3, p2_3));
|
|
|
|
// Maximize auxiliary variables
|
|
opt.maximize(ite(p1_1, c.int_val(1), c.int_val(0)) + ite(p1_2, c.int_val(1), c.int_val(0)) + ite(p1_3, c.int_val(1), c.int_val(0)) + ite(p2_1, c.int_val(1), c.int_val(0)) + ite(p2_2, c.int_val(1), c.int_val(0)) + ite(p2_3, c.int_val(1), c.int_val(0)));
|
|
|
|
std::cout << "check: " << opt.check() << std::endl;
|
|
|
|
if (opt.check() == sat) {
|
|
model m = opt.get_model();
|
|
std::cout << "Model: " << m << std::endl;
|
|
|
|
// Evaluate original PB expressions
|
|
std::cout << "pb1 = " << m.eval(pb1) << std::endl;
|
|
std::cout << "pb2 = " << m.eval(pb2) << std::endl;
|
|
|
|
std::cout << "Objectives: " << opt.objectives().size() << std::endl;
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
test_pb_max_pattern();
|
|
test_pb_max_with_constraints();
|
|
return 0;
|
|
} |