Skip to content

Commit 039abc5

Browse files
committed
Fix readme
1 parent 6ecf9e5 commit 039abc5

3 files changed

Lines changed: 128 additions & 7 deletions

File tree

README.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ This library provides efficient algorithms and data structures for solving const
1717
- **Comparison**: `==`, `!=`, `<`, `<=`, `>`, `>=` (natural syntax)
1818
- **Boolean Logic**: `and()`, `or()`, `not()` with array syntax `and([a,b,c])` and variadic syntax `and(a,b,c,d)`
1919
- **Global**: `alldiff()`, `allequal()`, element `x[y] = z`, `count(vars, value, count)`, `table(vars, tuples)`
20-
- **Ordering**: `between(lower, middle, upper)` for ternary ordering constraints
20+
- **Ordering**: `a <= b <= c`, `a < b < c`, `a >= b >= c`, `a > b > c` (natural `between` constraints)
2121
- **Cardinality**: `at_least(vars, value, count)`, `at_most(vars, value, count)`, `exactly(vars, value, count)`
2222
- **Conditional**: `if_then(condition, constraint)`, `if_then_else(condition, then_constraint, else_constraint)`
2323

@@ -33,16 +33,18 @@ cspsolver = "0.5.15"
3333

3434
## Examples
3535

36+
3637
```bash
3738
cargo run --release --example sudoku
3839
cargo run --release --example n_queens
39-
cargo run --release --example count_demo # Count constraint demonstrations
40-
cargo run --release --example table_demo # Table constraint with practical examples
41-
cargo run --release --example magic_square # Magic squares with enhanced constraints
40+
cargo run --release --example count_demo
41+
cargo run --release --example table_demo
42+
cargo run --release --example magic_square
4243
```
4344

4445

4546

47+
4648
```
4749
🧩 Solving PLATINUM puzzle:
4850
📊 Puzzle stats: 17 clues given, 64 empty cells
@@ -96,7 +98,8 @@ fn main() {
9698
post!(m, allequal([x, y])); // All equal
9799

98100
// Ordering constraints - powerful ternary relationships
99-
post!(m, between(x, y, z)); // x <= y <= z (ordering constraint)
101+
post!(m, x <= y <= z); // Natural chained comparison syntax
102+
post!(m, between(x, y, z)); // Alternative function syntax
100103

101104
// Cardinality constraints - counting with fine-grained control
102105
let tasks = vec![m.int(1, 3), m.int(1, 3), m.int(1, 3)]; // 1=low, 2=medium, 3=high priority
@@ -221,12 +224,21 @@ fn main() {
221224
The latest version includes powerful new constraint types for advanced modeling:
222225

223226
#### Between Constraints
224-
Enforce ternary ordering relationships with a single constraint:
227+
Enforce ternary ordering relationships with natural chained comparison syntax:
225228
```rust
226229
let start = m.int(1, 10);
227230
let middle = m.int(5, 15);
228231
let end = m.int(10, 20);
229-
post!(m, between(start, middle, end)); // start <= middle <= end
232+
233+
// Natural chained comparison syntax (recommended)
234+
post!(m, start <= middle <= end);
235+
236+
// Alternative function syntax
237+
post!(m, between(start, middle, end));
238+
239+
// Other chained comparisons
240+
post!(m, start < middle < end); // Strict inequalities
241+
post!(m, end >= middle >= start); // Reverse order
230242
```
231243

232244
#### Cardinality Constraints
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use cspsolver::prelude::*;
2+
3+
fn main() {
4+
let mut m = Model::default();
5+
6+
// Test the new chained comparison syntax
7+
let lower = m.int(1, 5);
8+
let middle = m.int(3, 8);
9+
let upper = m.int(7, 12);
10+
11+
println!("=== Testing Chained Comparison Syntax ===");
12+
13+
// Original between constraint syntax
14+
post!(m, between(lower, middle, upper));
15+
println!("✅ Original syntax: between(lower, middle, upper)");
16+
17+
// New natural chained comparison syntax
18+
let a = m.int(1, 5);
19+
let b = m.int(3, 8);
20+
let c = m.int(7, 12);
21+
22+
post!(m, a <= b <= c);
23+
println!("✅ New syntax: a <= b <= c");
24+
25+
// Test other chained comparison types
26+
let x = m.int(10, 15);
27+
let y = m.int(5, 10);
28+
let z = m.int(1, 6);
29+
30+
post!(m, x >= y >= z);
31+
println!("✅ New syntax: x >= y >= z");
32+
33+
// Test strict inequalities (these create separate constraints)
34+
let p = m.int(1, 5);
35+
let q = m.int(3, 8);
36+
let r = m.int(7, 12);
37+
38+
post!(m, p < q < r);
39+
println!("✅ New syntax: p < q < r");
40+
41+
if let Ok(solution) = m.solve() {
42+
println!("\n=== Solution Found ===");
43+
println!("lower = {:?}, middle = {:?}, upper = {:?}",
44+
solution[lower], solution[middle], solution[upper]);
45+
println!("a = {:?}, b = {:?}, c = {:?}",
46+
solution[a], solution[b], solution[c]);
47+
println!("x = {:?}, y = {:?}, z = {:?}",
48+
solution[x], solution[y], solution[z]);
49+
println!("p = {:?}, q = {:?}, r = {:?}",
50+
solution[p], solution[q], solution[r]);
51+
} else {
52+
println!("No solution found");
53+
}
54+
55+
println!("\n🎉 Chained comparison syntax working!");
56+
println!("You can now use: a <= b <= c instead of between(a, b, c)");
57+
}

src/constraint_macros.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ impl ConstraintRef {
2828
///
2929
/// **Basic comparisons**: `var op var`, `var op literal`, `var op (expr)`, `var op int(value)`, `var op float(value)`
3030
///
31+
/// **Chained comparisons**: `a <= b <= c`, `a < b < c`, `a >= b >= c`, `a > b > c` (natural between constraints)
32+
///
3133
/// **Array indexing**: `vars[i] op vars[j]`, `vars[i] op var`, `var op vars[i]`, `vars[i] op literal`, `literal op vars[i]`, `array[var] == value` (Element)
3234
///
3335
/// **Arithmetic**: `var op var +/- var`, `var op var */÷ var`, `var op var % divisor`
@@ -43,6 +45,30 @@ impl ConstraintRef {
4345
/// Where `op` is any of: `==`, `!=`, `<`, `<=`, `>`, `>=`
4446
#[macro_export]
4547
macro_rules! post {
48+
// Chained comparisons for between constraints: a <= b <= c, a < b < c, etc.
49+
($model:expr, $lower:ident <= $middle:ident <= $upper:ident) => {{
50+
$model.props.between_constraint($lower, $middle, $upper);
51+
$crate::constraint_macros::ConstraintRef::new(0)
52+
}};
53+
54+
($model:expr, $lower:ident < $middle:ident < $upper:ident) => {{
55+
$model.props.less_than($lower, $middle);
56+
$model.props.less_than($middle, $upper);
57+
$crate::constraint_macros::ConstraintRef::new(0)
58+
}};
59+
60+
($model:expr, $lower:ident >= $middle:ident >= $upper:ident) => {{
61+
$model.props.greater_than_or_equals($lower, $middle);
62+
$model.props.greater_than_or_equals($middle, $upper);
63+
$crate::constraint_macros::ConstraintRef::new(0)
64+
}};
65+
66+
($model:expr, $lower:ident > $middle:ident > $upper:ident) => {{
67+
$model.props.greater_than($lower, $middle);
68+
$model.props.greater_than($middle, $upper);
69+
$crate::constraint_macros::ConstraintRef::new(0)
70+
}};
71+
4672
// Handle simple variable comparisons: x < y, x <= y, etc.
4773
($model:expr, $left:ident < $right:ident) => {{
4874
$model.props.less_than($left, $right);
@@ -2832,6 +2858,32 @@ mod tests {
28322858
assert!(true);
28332859
}
28342860

2861+
#[test]
2862+
fn test_chained_comparison_syntax() {
2863+
let mut m = Model::default();
2864+
let a = m.int(1, 10);
2865+
let b = m.int(1, 10);
2866+
let c = m.int(1, 10);
2867+
let x = m.int(1, 10);
2868+
let y = m.int(1, 10);
2869+
let z = m.int(1, 10);
2870+
2871+
// Test chained <= (between constraint)
2872+
let _c1 = post!(m, a <= b <= c);
2873+
2874+
// Test chained >=
2875+
let _c2 = post!(m, x >= y >= z);
2876+
2877+
// Test chained < (strict inequality)
2878+
let _c3 = post!(m, a < b < c);
2879+
2880+
// Test chained > (strict inequality)
2881+
let _c4 = post!(m, x > y > z);
2882+
2883+
// Should compile without errors
2884+
assert!(true);
2885+
}
2886+
28352887
#[test]
28362888
fn test_boolean_array_operations() {
28372889
let mut m = Model::default();

0 commit comments

Comments
 (0)