solverforge-solver 0.9.0

Solver engine for SolverForge
Documentation
use super::{ConstructionListElementId, ConstructionSlotId};

#[derive(Debug, Default, Clone)]
pub(crate) struct ConstructionFrontier {
    scalar_completed_at_revision: Vec<Vec<u64>>,
    list_completed_at_revision: Vec<Vec<u64>>,
}

impl ConstructionFrontier {
    pub(crate) fn new() -> Self {
        Self::default()
    }

    pub(crate) fn reset(&mut self) {
        for slots in &mut self.scalar_completed_at_revision {
            slots.clear();
        }
        for elements in &mut self.list_completed_at_revision {
            elements.clear();
        }
    }

    pub(crate) fn is_scalar_completed(
        &self,
        slot_id: ConstructionSlotId,
        solution_revision: u64,
    ) -> bool {
        self.scalar_completed_at_revision
            .get(slot_id.binding_index())
            .and_then(|slots| slots.get(slot_id.entity_index()))
            .is_some_and(|completed_revision| *completed_revision == solution_revision)
    }

    pub(crate) fn mark_scalar_completed(
        &mut self,
        slot_id: ConstructionSlotId,
        solution_revision: u64,
    ) {
        let slot = self.ensure_scalar_slot(slot_id);
        *slot = solution_revision;
    }

    pub(crate) fn is_list_completed(
        &self,
        element_id: ConstructionListElementId,
        solution_revision: u64,
    ) -> bool {
        self.list_completed_at_revision
            .get(element_id.list_index())
            .and_then(|elements| elements.get(element_id.element_index()))
            .is_some_and(|completed_revision| *completed_revision == solution_revision)
    }

    pub(crate) fn mark_list_completed(
        &mut self,
        element_id: ConstructionListElementId,
        solution_revision: u64,
    ) {
        let element = self.ensure_list_element(element_id);
        *element = solution_revision;
    }

    fn ensure_scalar_slot(&mut self, slot_id: ConstructionSlotId) -> &mut u64 {
        if self.scalar_completed_at_revision.len() <= slot_id.binding_index() {
            self.scalar_completed_at_revision
                .resize_with(slot_id.binding_index() + 1, Vec::new);
        }
        let slots = &mut self.scalar_completed_at_revision[slot_id.binding_index()];
        if slots.len() <= slot_id.entity_index() {
            slots.resize(slot_id.entity_index() + 1, 0);
        }
        &mut slots[slot_id.entity_index()]
    }

    fn ensure_list_element(&mut self, element_id: ConstructionListElementId) -> &mut u64 {
        if self.list_completed_at_revision.len() <= element_id.list_index() {
            self.list_completed_at_revision
                .resize_with(element_id.list_index() + 1, Vec::new);
        }
        let elements = &mut self.list_completed_at_revision[element_id.list_index()];
        if elements.len() <= element_id.element_index() {
            elements.resize(element_id.element_index() + 1, 0);
        }
        &mut elements[element_id.element_index()]
    }
}