solverforge 0.11.1

SolverForge - A constraint solver in Rust
Documentation
#[path = "mixed_variable_order_runtime/mod.rs"]
mod domain;

pub use domain::{Plan, Route, Visit};

use solverforge::{SolverEvent, SolverLifecycleState, SolverManager};

fn seeded_plan() -> Plan {
    Plan {
        routes: vec![Route {
            id: 0,
            visits: Vec::new(),
            first_visit: None,
        }],
        visits: vec![Visit { id: 0 }],
        score: None,
    }
}

#[test]
fn generic_construction_orders_list_variable_before_scalar_variable() {
    static MANAGER: SolverManager<Plan> = SolverManager::new();

    let descriptor = Plan::descriptor();
    let route_descriptor = descriptor
        .find_entity_descriptor("Route")
        .expect("route descriptor should exist");
    let visits_order = route_descriptor
        .variable_descriptors
        .iter()
        .position(|variable| variable.name == "visits")
        .expect("list variable descriptor should exist");
    let first_visit_order = route_descriptor
        .variable_descriptors
        .iter()
        .position(|variable| variable.name == "first_visit")
        .expect("scalar variable descriptor should exist");
    assert!(visits_order < first_visit_order);

    let (job_id, mut receiver) = MANAGER.solve(seeded_plan()).expect("job should start");
    let mut completed = None;

    while let Some(event) = receiver.blocking_recv() {
        match event {
            SolverEvent::Completed { metadata, solution } => {
                assert_eq!(metadata.lifecycle_state, SolverLifecycleState::Completed);
                completed = Some(solution);
                break;
            }
            SolverEvent::Failed { error, .. } => {
                panic!("mixed construction solve failed: {error}");
            }
            _ => {}
        }
    }

    let solution = completed.expect("expected completed solve");
    assert_eq!(solution.routes[0].visits, vec![0]);
    assert_eq!(
        solution.routes[0].first_visit,
        Some(0),
        "scalar entity-field value range should see the list mutation before it is constructed"
    );

    MANAGER.delete(job_id).expect("delete completed job");
}