Crate selen

Crate selen 

Source
Expand description

§CSP Solver

A constraint satisfaction problem (CSP) solver library in Rust.

§Safety & Resource Management

All models have automatic memory and timeout limits to prevent system exhaustion:

  • Default memory limit: 2GB
  • Default timeout: 60 seconds
  • Memory tracking: During variable creation (prevents crashes)
  • Early failure: Clear error messages when limits exceeded
use selen::prelude::*;

// Automatic safety limits
let mut m = Model::default(); // 2GB memory, 60s timeout

// Custom limits
let config = SolverConfig::default()
    .with_max_memory_mb(512)      // 512MB limit
    .with_timeout_seconds(30);    // 30 second timeout
let mut m = Model::with_config(config);

§Variable Types

  • Integer variables: m.int(min, max) - continuous range
  • Float variables: m.float(min, max) - continuous range with precision control
  • Custom domains: m.ints(vec![values]) - specific integer values only
  • Boolean variables: m.bool() - equivalent to m.int(0, 1)

§Constraint Types

  • Arithmetic: +, -, *, /, %, abs(), min(), max(), sum()
  • Comparison: ==, !=, <, <=, >, >=
  • Boolean logic: and(), or(), not() - supports array and variadic syntax
  • Global constraints: alldiff(), allequal(), element()

§Post a mathematical constraint to the model

post() - Post single contrraint to the model. postall() - Post multiple constraints to the model in a single call. Accepts comma-separated constraint expressions, each following the same patterns as post!

Supported constraint patterns: Basic comparisons: var op var, var op literal, var op (expr), var op int(value), var op float(value) Arithmetic: var op var +/- var, var op var */÷ var, var op var % divisor Functions: func(var) op target where func is abs, min, max, sum Boolean: and(vars...), or(vars...), not(var) - supports arrays and([a,b,c]) and variadic and(a,b,c,d) Global: alldiff([vars...]), allequal([vars...]), element(array, index, value) Multiplication with constants: target op var * int(value), target op var * float(value)

Where op is any of: ==, !=, <, <=, >, >=

§Example 1: Basic Integer Problem

use selen::prelude::*;

let mut m = Model::default();
let x = m.int(1, 10);
let y = m.int(1, 10);

post!(m, x + y == int(12));
post!(m, x > y);

if let Ok(solution) = m.solve() {
    println!("x = {:?}, y = {:?}", solution[x], solution[y]);
}

§Example 2: Mixed Integer-Float Optimization

use selen::prelude::*;

let mut m = Model::default();
let items = m.int(1, 100);        // Number of items
let cost = m.float(0.0, 1000.0);  // Total cost

post!(m, cost == items * float(12.5));  // $12.50 per item
post!(m, cost <= float(500.0));         // Budget constraint

// Maximize number of items within budget
if let Ok(solution) = m.maximize(items) {
    println!("Optimal: {:?} items, cost: {:?}", 
             solution[items], solution[cost]);
}

§Example 3: Custom Domains and Global Constraints

use selen::prelude::*;

let mut m = Model::default();
 
// Variables with custom domains
let red = m.ints(vec![1, 3, 5, 7]);      // Odd numbers
let blue = m.ints(vec![2, 4, 6, 8]);     // Even numbers  
let green = m.ints(vec![2, 3, 5, 7]);    // Prime numbers

// All must be different
post!(m, alldiff([red, blue, green]));

if let Ok(solution) = m.solve() {
    println!("Red: {:?}, Blue: {:?}, Green: {:?}",
             solution[red], solution[blue], solution[green]);
}

§Example 4: Programmatic API - Basic Constraints

For developers who prefer explicit, method-based constraint building:

use selen::prelude::*;

let mut m = Model::default();
let x = m.int(1, 10);
let y = m.int(1, 10);

// Build constraints programmatically
m.new(x.add(y).eq(12));        // x + y == 12
m.new(x.gt(y));                // x > y
m.new(x.mul(2).le(15));        // x * 2 <= 15

if let Ok(solution) = m.solve() {
    println!("x = {:?}, y = {:?}", solution[x], solution[y]);
}

§Example 5: Programmatic API - Global Constraints

use selen::prelude::*;

let mut m = Model::default();
let vars = vec![m.int(1, 5), m.int(1, 5), m.int(1, 5)];

// Global constraints using programmatic API
m.alldiff(&vars);               // All variables must be different

// Mathematical functions
let sum_result = m.sum(&vars);
m.new(sum_result.le(10));      // sum(vars) <= 10

let max_result = m.max(&vars).expect("non-empty variable list");
m.new(max_result.ge(3));       // max(vars) >= 3

if let Ok(solution) = m.solve() {
    println!("Variables: {:?}", vars.iter().map(|&v| solution[v]).collect::<Vec<_>>());
}

§Example 6: Programmatic API - Complex Operations

use selen::prelude::*;

let mut m = Model::default();
let x = m.int(-10, 10);
let y = m.int(1, 10);
let z = m.int(1, 20);

// Arithmetic and mathematical functions
let abs_x = m.abs(x);
m.new(abs_x.ge(5));            // abs(x) >= 5

// Modulo operations
let mod_result = m.modulo(z, Val::from(3));
m.new(mod_result.eq(1));       // z % 3 == 1

// Logical operations on constraints
let constraint1 = x.gt(0);
let constraint2 = y.lt(5);
m.new(constraint1.and(constraint2));  // (x > 0) && (y < 5)

if let Ok(solution) = m.solve() {
    println!("x = {:?}, y = {:?}, z = {:?}", solution[x], solution[y], solution[z]);
}

Modules§

api
API module
core
Core functionality
model
Model core module
prelude
Prelude module for CSP solver
runtime_api
Runtime Constraint API
solvers
Specialized solvers for common problem domains.