Skip to content

Commit 584b3a3

Browse files
committed
Merge branch 'feature/refactor-solver' into release/0.6.0
2 parents daf2b0f + 1ba7191 commit 584b3a3

84 files changed

Lines changed: 3306 additions & 938 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 714 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ rand = "0.9" # Updated from 0.8
4949
rand_chacha = "0.9" # Updated from 0.3
5050
rayon = "1.11" # New - for parallel move evaluation
5151
smallvec = "1.15" # Updated from 1.11
52+
cranelift-codegen = "0.116"
53+
cranelift-frontend = "0.116"
54+
cranelift-module = "0.116"
55+
cranelift-jit = "0.116"
56+
cranelift-native = "0.116"
5257

5358
# Proc-macro dependencies
5459
syn = { version = "2.0", features = ["full", "extra-traits"] }

crates/solverforge-console/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ pub fn init() {
3838

3939
let filter = EnvFilter::builder()
4040
.with_default_directive("solverforge_solver=info".parse().unwrap())
41-
.from_env_lossy();
41+
.from_env_lossy()
42+
.add_directive("solverforge_dynamic=info".parse().unwrap());
4243

4344
let _ = tracing_subscriber::registry()
4445
.with(filter)

crates/solverforge-core/src/score/hard_medium_soft.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ impl Score for HardMediumSoftScore {
156156
_ => panic!("HardMediumSoftScore has 3 levels, got index {}", index),
157157
}
158158
}
159+
160+
#[inline]
161+
fn to_scalar(&self) -> f64 {
162+
self.hard as f64 * 1_000_000_000_000.0 + self.medium as f64 * 1_000_000.0 + self.soft as f64
163+
}
159164
}
160165

161166
impl Ord for HardMediumSoftScore {

crates/solverforge-core/src/score/hard_soft.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ impl Score for HardSoftScore {
121121
_ => panic!("HardSoftScore has 2 levels, got index {}", index),
122122
}
123123
}
124+
125+
#[inline]
126+
fn to_scalar(&self) -> f64 {
127+
self.hard as f64 * 1_000_000.0 + self.soft as f64
128+
}
124129
}
125130

126131
impl Ord for HardSoftScore {

crates/solverforge-core/src/score/simple.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ impl Score for SimpleScore {
8181
_ => panic!("SimpleScore has 1 level, got index {}", index),
8282
}
8383
}
84+
85+
#[inline]
86+
fn to_scalar(&self) -> f64 {
87+
self.score as f64
88+
}
8489
}
8590

8691
impl Ord for SimpleScore {

crates/solverforge-core/src/score/traits.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ use std::cmp::Ordering;
44
use std::fmt::{Debug, Display};
55
use std::ops::{Add, Neg, Sub};
66

7-
use super::ScoreLevel;
8-
97
/// Core trait for all score types in SolverForge.
108
///
119
/// Scores represent the quality of a planning solution. They are used to:
@@ -79,14 +77,28 @@ pub trait Score:
7977
/// Returns the absolute value of this score.
8078
fn abs(&self) -> Self;
8179

82-
/// Returns the semantic label for the score level at the given index.
83-
///
84-
/// Level indices follow the same order as `to_level_numbers()`:
85-
/// highest priority first.
80+
/// Converts this score to a single scalar f64 for algorithms like
81+
/// Simulated Annealing that need a continuous representation.
8682
///
87-
/// # Panics
88-
/// Panics if `index >= levels_count()`.
89-
fn level_label(index: usize) -> ScoreLevel;
83+
/// Higher-priority levels are weighted exponentially more (10^6 per level).
84+
/// Override for zero-allocation implementations on fixed-level score types.
85+
#[inline]
86+
fn to_scalar(&self) -> f64 {
87+
let levels = self.to_level_numbers();
88+
if levels.is_empty() {
89+
return 0.0;
90+
}
91+
if levels.len() == 1 {
92+
return levels[0] as f64;
93+
}
94+
let n = levels.len();
95+
let mut scalar = 0.0f64;
96+
for (i, &level) in levels.iter().enumerate() {
97+
let weight = 10.0f64.powi(6 * (n - 1 - i) as i32);
98+
scalar += level as f64 * weight;
99+
}
100+
scalar
101+
}
90102

91103
/// Compares two scores, returning the ordering.
92104
///

crates/solverforge-dynamic/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@ thiserror.workspace = true
1818
tracing.workspace = true
1919
rand.workspace = true
2020
rand_chacha.workspace = true
21+
cranelift-codegen.workspace = true
22+
cranelift-frontend.workspace = true
23+
cranelift-module.workspace = true
24+
cranelift-jit.workspace = true
25+
cranelift-native.workspace = true
2126

2227
[dev-dependencies]

crates/solverforge-dynamic/src/constraint/closures_bi.rs

Lines changed: 0 additions & 129 deletions
This file was deleted.

crates/solverforge-dynamic/src/constraint/closures_cross.rs

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,7 @@ pub fn make_cross_key_a(key_expr: Expr, descriptor: DynamicDescriptor) -> DynCro
221221
);
222222
}
223223

224-
// Create minimal solution with only descriptor (no entities/facts).
225-
// This is intentional - join keys should be stable entity attributes.
226-
let minimal_solution = DynamicSolution {
227-
descriptor,
228-
entities: Vec::new(),
229-
facts: Vec::new(),
230-
score: None,
231-
id_to_location: std::collections::HashMap::new(),
232-
};
224+
let minimal_solution = DynamicSolution::empty(descriptor);
233225

234226
Box::new(move |entity: &DynamicEntity| {
235227
crate::eval::eval_entity_expr(&key_expr, &minimal_solution, entity)
@@ -293,15 +285,7 @@ pub fn make_cross_key_b(key_expr: Expr, descriptor: DynamicDescriptor) -> DynCro
293285
);
294286
}
295287

296-
// Create minimal solution with only descriptor (no entities/facts).
297-
// This is intentional - join keys should be stable entity attributes.
298-
let minimal_solution = DynamicSolution {
299-
descriptor,
300-
entities: Vec::new(),
301-
facts: Vec::new(),
302-
score: None,
303-
id_to_location: std::collections::HashMap::new(),
304-
};
288+
let minimal_solution = DynamicSolution::empty(descriptor);
305289

306290
Box::new(move |entity: &DynamicEntity| {
307291
crate::eval::eval_entity_expr(&key_expr, &minimal_solution, entity)

0 commit comments

Comments
 (0)