use selen::prelude::*;
fn main() {
println!("🚀 Runtime Constraint API Demo - Phase 1 & 2");
println!("===============================================\n");
example_1_basic_runtime_building();
example_2_dynamic_from_data();
example_3_expression_chaining();
example_4_constraint_composition();
example_5_model_c_syntax();
example_6_builder_fluent_interface();
example_7_global_constraints();
example_8_mixed_phase_usage();
}
fn example_1_basic_runtime_building() {
println!("📝 Example 1: Basic Runtime Constraint Building");
let mut m = Model::default();
let x = m.int(0, 10);
let y = m.int(0, 10);
let z = m.int(0, 20);
m.new(x.add(y).eq(z)); m.new(x.gt(int(5))); m.new(y.le(int(8)));
if let Ok(solution) = m.solve() {
println!("✓ Solution found:");
println!(" x = {:?}", solution[x]);
println!(" y = {:?}", solution[y]);
println!(" z = {:?}", solution[z]);
} else {
println!("❌ No solution found");
}
println!();
}
fn example_2_dynamic_from_data() {
println!("📝 Example 2: Dynamic Constraints from Data");
let mut m = Model::default();
let x = m.int(0, 10);
let y = m.int(0, 10);
let rules = vec![
("x", "gt", 3), ("y", "le", 7), ("x", "ne", 5), ];
println!(" Building constraints from data: {:?}", rules);
for (var_name, op, value) in rules {
let var_id = match var_name {
"x" => x,
"y" => y,
_ => continue,
};
let constraint = match op {
"gt" => var_id.gt(int(value)),
"le" => var_id.le(int(value)),
"eq" => var_id.eq(int(value)),
"ne" => var_id.ne(int(value)),
"ge" => var_id.ge(int(value)),
"lt" => var_id.lt(int(value)),
_ => {
println!(" ⚠️ Unknown operator: {}", op);
continue;
}
};
m.new(constraint);
println!(" ✓ Posted: {} {} {}", var_name, op, value);
}
if let Ok(solution) = m.solve() {
println!("✓ Solution found:");
println!(" x = {:?}", solution[x]);
println!(" y = {:?}", solution[y]);
} else {
println!("❌ No solution found");
}
println!();
}
fn example_3_expression_chaining() {
println!("📝 Example 3: Expression Chaining");
let mut m = Model::default();
let a = m.int(1, 10); let b = m.int(1, 10); let result = m.int(0, 100);
m.new(a.eq(int(5))); m.new(b.eq(int(5))); m.new(result.eq(int(10)));
if let Ok(solution) = m.solve() {
println!("✓ Found simple values:");
println!(" a = {:?}", solution[a]);
println!(" b = {:?}", solution[b]);
println!(" result = {:?}", solution[result]);
} else {
println!("❌ No solution found");
}
println!();
}
fn example_4_constraint_composition() {
println!("📝 Example 4: Constraint Composition");
let mut m = Model::default();
let x = m.int(0, 20);
let y = m.int(0, 20);
let c1 = x.gt(int(5)); let c2 = x.lt(int(15)); let c3 = y.ge(int(10));
let range_constraint = c1.and(c2);
let combined = range_constraint.and(c3);
m.new(combined);
if let Ok(solution) = m.solve() {
println!("✓ Solution with composed constraints:");
println!(" x = {:?} (should be 6-14)", solution[x]);
println!(" y = {:?} (should be >= 10)", solution[y]);
} else {
println!("❌ No solution found");
}
println!();
}
fn example_5_model_c_syntax() {
println!("📝 Example 5: Model::c() Ultra-Short Syntax (Phase 2)");
let mut m = Model::default();
let x = m.int(1, 10);
let y = m.int(1, 10);
let sum = m.int(2, 20);
m.c(x).gt(int(3)); m.c(y).le(int(8)); m.c(x).add(y).eq(sum); m.c(sum).eq(int(12));
if let Ok(solution) = m.solve() {
println!("✓ Solution found:");
println!(" x = {:?}", solution[x]);
println!(" y = {:?}", solution[y]);
println!(" sum = {:?}", solution[sum]);
} else {
println!("❌ No solution found");
}
println!();
}
fn example_6_builder_fluent_interface() {
println!("📝 Example 6: Builder Fluent Interface (Phase 2)");
let mut m = Model::default();
let a = m.int(0, 20);
let b = m.int(0, 20);
let result = m.int(0, 100);
m.c(a).mul(int(3)).add(int(5)).le(int(50)); m.c(b).div(int(2)).sub(int(1)).ge(int(2)); m.c(a).add(b).mul(int(2)).eq(result); m.c(result).ne(int(20));
if let Ok(solution) = m.solve() {
println!("✓ Complex fluent constraints satisfied:");
println!(" a = {:?}", solution[a]);
println!(" b = {:?}", solution[b]);
println!(" result = {:?}", solution[result]);
} else {
println!("❌ No solution found");
}
println!();
}
fn example_7_global_constraints() {
println!("📝 Example 7: Global Constraint Shortcuts (Phase 2)");
let mut m = Model::default();
let digits = m.ints(4, 1, 4);
m.alldiff(&digits); m.c(digits[0]).gt(digits[1]); m.c(digits[2]).add(digits[3]).eq(int(5));
if let Ok(solution) = m.solve() {
println!("✓ Global constraint solution:");
for (i, &digit) in digits.iter().enumerate() {
println!(" digit[{}] = {:?}", i, solution[digit]);
}
} else {
println!("❌ No solution found");
}
println!();
}
fn example_8_mixed_phase_usage() {
println!("📝 Example 8: Mixed Phase 1 & 2 Usage");
let mut m = Model::default();
let x = m.int(1, 10);
let y = m.int(1, 10);
let z = m.int(1, 10);
let constraint1 = x.add(y).gt(int(5));
m.new(constraint1);
m.c(y).mul(int(2)).le(z.add(int(3)));
m.alldiff(&[x, y, z]);
let c1 = x.lt(int(8));
let c2 = y.ge(int(2));
let combined = c1.and(c2);
m.new(combined);
if let Ok(solution) = m.solve() {
println!("✓ Mixed API solution:");
println!(" x = {:?}", solution[x]);
println!(" y = {:?}", solution[y]);
println!(" z = {:?}", solution[z]);
} else {
println!("❌ No solution found");
}
println!();
}