use selen::{
model::Model,
runtime_api::{ModelExt, VarIdExt},
};
fn main() {
println!("🚀 Global Constraints Demo - Phase 4");
println!("====================================\n");
println!("📝 Example 1: All Different Constraint");
{
let mut model = Model::default();
let vars = model.ints(4, 1, 4);
model.alldiff(&vars);
if let Ok(solution) = model.solve() {
println!("✓ All different solution:");
for (i, &var) in vars.iter().enumerate() {
let value: i32 = solution.get(var);
println!(" var[{}] = {}", i, value);
}
} else {
println!("❌ No solution found");
}
}
println!();
println!("📝 Example 2: All Equal Constraint");
{
let mut model = Model::default();
let vars = model.ints(3, 1, 10);
model.alleq(&vars);
model.new(vars[0].ge(5));
if let Ok(solution) = model.solve() {
println!("✓ All equal solution:");
for (i, &var) in vars.iter().enumerate() {
let value: i32 = solution.get(var);
println!(" var[{}] = {}", i, value);
}
} else {
println!("❌ No solution found");
}
}
println!();
println!("📝 Example 3: Element Constraint (array[index] == value)");
{
let mut model = Model::default();
let array: Vec<_> = (0..5).map(|i| model.int(i * 10, i * 10 + 9)).collect();
let index = model.int(0, 4);
let value = model.int(0, 50);
model.elem(&array, index, value);
if let Ok(solution) = model.solve() {
println!("✓ Element constraint solution:");
println!(" Array values:");
for (i, &var) in array.iter().enumerate() {
let val: i32 = solution.get(var);
println!(" array[{}] = {}", i, val);
}
let idx: i32 = solution.get(index);
let val: i32 = solution.get(value);
println!(" index = {}, value = {}", idx, val);
println!(" Verification: array[{}] = {} == {}", idx, solution.get::<i32>(array[idx as usize]), val);
} else {
println!("❌ No solution found");
}
}
println!();
println!("📝 Example 4: Count Constraint");
{
let mut model = Model::default();
let vars = model.ints(6, 1, 3);
let count_result = model.int(0, 6);
use selen::variables::Val;
model.count(&vars, Val::int(2), count_result);
model.new(count_result.eq(3));
if let Ok(solution) = model.solve() {
println!("✓ Count constraint solution:");
let mut count_2s = 0;
for (i, &var) in vars.iter().enumerate() {
let value: i32 = solution.get(var);
if value == 2 { count_2s += 1; }
println!(" var[{}] = {}", i, value);
}
let count: i32 = solution.get(count_result);
println!(" Count of 2s: {} (should be 3)", count);
println!(" Verification: actual count = {}", count_2s);
} else {
println!("❌ No solution found");
}
}
println!();
println!("📝 Example 5: Between Constraint (Cardinality)");
{
let mut model = Model::default();
let x = model.int(0, 100);
let y = model.int(0, 100);
let z = model.int(0, 100);
model.betw(x, 10, 20);
model.atmost(y, 50);
model.atleast(z, 30);
model.new(x.add(y).eq(z));
if let Ok(solution) = model.solve() {
println!("✓ Cardinality constraints solution:");
let x_val: i32 = solution.get(x);
let y_val: i32 = solution.get(y);
let z_val: i32 = solution.get(z);
println!(" x = {} (should be 10-20)", x_val);
println!(" y = {} (should be ≤ 50)", y_val);
println!(" z = {} (should be ≥ 30)", z_val);
println!(" Verification: {} + {} = {}", x_val, y_val, z_val);
} else {
println!("❌ No solution found");
}
}
println!();
println!("📝 Example 6: Global Cardinality Constraint");
{
let mut model = Model::default();
let vars = model.ints(8, 1, 4);
let values = [1, 2, 3, 4];
let counts = model.ints(4, 0, 8);
model.gcc(&vars, &values, &counts);
model.new(counts[0].eq(2)); model.new(counts[1].eq(3)); model.new(counts[2].eq(2)); model.new(counts[3].eq(1));
if let Ok(solution) = model.solve() {
println!("✓ Global cardinality constraint solution:");
print!(" vars: [");
for (i, &var) in vars.iter().enumerate() {
let value: i32 = solution.get(var);
print!("{}", value);
if i < vars.len() - 1 { print!(", "); }
}
println!("]");
println!(" Value counts:");
for (i, &count_var) in counts.iter().enumerate() {
let count: i32 = solution.get(count_var);
println!(" Value {}: {} times", values[i], count);
}
println!(" Manual verification:");
for value in 1..=4 {
let actual_count = vars.iter()
.map(|&var| solution.get::<i32>(var))
.filter(|&v| v == value)
.count();
println!(" Value {}: {} times", value, actual_count);
}
} else {
println!("❌ No solution found");
}
}
println!();
println!("📝 Example 7: Complex Global Constraint Composition");
{
let mut model = Model::default();
let tasks = model.ints(4, 1, 10); let resources = model.ints(4, 1, 3);
model.alldiff(&tasks);
let resource_counts = model.ints(3, 0, 4);
model.gcc(&resources, &[1, 2, 3], &resource_counts);
for &count_var in &resource_counts {
model.atleast(count_var, 1);
}
for &task in &tasks {
model.betw(task, 1, 8);
}
if let Ok(solution) = model.solve() {
println!("✓ Complex scheduling solution:");
println!(" Task schedule:");
for (i, &task) in tasks.iter().enumerate() {
let start_time: i32 = solution.get(task);
let resource: i32 = solution.get(resources[i]);
println!(" Task {} starts at time {} using resource {}", i, start_time, resource);
}
println!(" Resource usage:");
for (i, &count_var) in resource_counts.iter().enumerate() {
let count: i32 = solution.get(count_var);
println!(" Resource {} used {} times", i + 1, count);
}
} else {
println!("❌ No solution found");
}
}
println!("\n🎉 Phase 4 Global Constraints Demo Complete!");
println!("All constraint types working: alldiff, alleq, elem, count, betw, atmost, atleast, gcc");
}