solverforge-solver 0.12.0

Solver engine for SolverForge
Documentation
#[test]
fn conflict_repair_accepts_package_qualified_constraint_metadata() {
    let descriptor = descriptor(true);
    let director = create_director_with_constraint_ref(
        MixedPlan {
            shifts: vec![Shift { worker: Some(0) }, Shift { worker: Some(1) }],
            vehicles: vec![],
            score: None,
        },
        descriptor,
        "pkg",
        "testConstraint",
        true,
    );
    let model = scalar_only_model().with_conflict_repairs(vec![
        crate::builder::ConflictRepair::new("pkg/testConstraint", repair_worker_to_one),
    ]);
    let config = MoveSelectorConfig::ConflictRepairMoveSelector(
        solverforge_config::ConflictRepairMoveSelectorConfig {
            constraints: vec!["pkg/testConstraint".to_string()],
            max_matches_per_step: 2,
            max_repairs_per_match: 3,
            max_moves_per_step: 4,
            require_hard_improvement: false,
            include_soft_matches: false,
        },
    );
    let selector = build_move_selector(Some(&config), &model, None);
    let mut cursor = selector.open_cursor(&director);

    assert!(cursor.next_candidate().is_some());
}

#[test]
#[should_panic(
    expected = "conflict_repair_move_selector configured for non-hard constraint `pkg/testConstraint` while include_soft_matches is false"
)]
fn conflict_repair_rejects_soft_package_qualified_metadata() {
    let descriptor = descriptor(true);
    let director = create_director_with_constraint_ref(
        MixedPlan {
            shifts: vec![Shift { worker: Some(0) }],
            vehicles: vec![],
            score: None,
        },
        descriptor,
        "pkg",
        "testConstraint",
        false,
    );
    let model = scalar_only_model().with_conflict_repairs(vec![
        crate::builder::ConflictRepair::new(
            "pkg/testConstraint",
            repair_provider_must_not_run,
        ),
    ]);
    let config = MoveSelectorConfig::ConflictRepairMoveSelector(
        solverforge_config::ConflictRepairMoveSelectorConfig {
            constraints: vec!["pkg/testConstraint".to_string()],
            max_matches_per_step: 2,
            max_repairs_per_match: 3,
            max_moves_per_step: 4,
            require_hard_improvement: false,
            include_soft_matches: false,
        },
    );
    let selector = build_move_selector(Some(&config), &model, None);

    let _ = selector.open_cursor(&director);
}

#[test]
#[should_panic(
    expected = "conflict_repair_move_selector configured for `testConstraint`, but no matching scoring constraint was found"
)]
fn conflict_repair_rejects_short_name_for_package_qualified_metadata() {
    let descriptor = descriptor(true);
    let director = create_director_with_constraint_ref(
        MixedPlan {
            shifts: vec![Shift { worker: Some(0) }],
            vehicles: vec![],
            score: None,
        },
        descriptor,
        "pkg",
        "testConstraint",
        true,
    );
    let model = scalar_only_model().with_conflict_repairs(vec![
        crate::builder::ConflictRepair::new(
            "testConstraint",
            repair_provider_must_not_run,
        ),
    ]);
    let config = MoveSelectorConfig::ConflictRepairMoveSelector(
        solverforge_config::ConflictRepairMoveSelectorConfig {
            constraints: vec!["testConstraint".to_string()],
            max_matches_per_step: 2,
            max_repairs_per_match: 3,
            max_moves_per_step: 4,
            require_hard_improvement: false,
            include_soft_matches: false,
        },
    );
    let selector = build_move_selector(Some(&config), &model, None);

    let _ = selector.open_cursor(&director);
}