Module library_integration

Module library_integration 

Source
Expand description

§Using diagrams from the compiler

The tididi crate owns diagrams and their operations, and the vitri crate owns the formula: vitri::cnf defines CnfFormula, Clause, Literal, the header metadata and the DIMACS reader and writer, and this crate takes those types as they are. What this crate adds is tididi_cnf::compile — compile_cnf with its CompileOptions, ComponentPlan and Output, and what it returns, Compiled or a GiveUp — and tididi_cnf::vtree, the vtree requests (build_vtree and build_vtree_with_components, with their VtreeOptions, returning a tree or a VtreeBuild, and an Error when the construction fails) and the two component descriptors, ComponentVtree and Component. tididi_cnf::tididi and tididi_cnf::vitri re-export the two libraries, so a caller uses the versions this crate compiles against. The public count entry runs the same complete task as the binary and returns an Answer under the caller’s Limits; the individual counting stages remain internal.

A diagram the compiler returns is an ordinary Tdd. The library’s API overview covers composing, counting and querying it. A result may come back on a rotated or grafted vtree, so build any new operand against the result’s own vtree rather than the one passed in; compile_cnf’s rustdoc says exactly when the two differ.

§A bounded compile

The compiler checks out one Engine for the whole run and passes it through compilation, queries and recovery, so one set of limits, memory hooks and scratch covers every operation. To do the same, pass the engine that Context::run or Context::with_limits supplies to compile_cnf and to every query that should share its limits; a free function or diagram method starts a separate checkout without them.

use std::sync::Arc;
use std::time::Instant;

use tididi_cnf::compile::{CompileOptions, ComponentPlan, compile_cnf};
use tididi_cnf::tididi::limits::LimitConfig;
use tididi_cnf::tididi::{Context, Vtree};
use tididi_cnf::vitri::cnf::CnfFormula;

/// The model count of `formula` compiled on `vtree`, in decimal, or `None`
/// when the compile or the count gives up by `deadline`.
fn compile_and_count(
    context: &Arc<Context>,
    formula: &CnfFormula,
    vtree: Vtree,
    deadline: Instant,
) -> Option<String> {
    let vtree = context.bind(vtree);
    context.with_limits(LimitConfig::none().with_deadline(Some(deadline)), |engine| {
        let opts = CompileOptions {
            plan: ComponentPlan::Whole,
            deadline: Some(deadline),
            ..CompileOptions::default()
        };
        let compiled = compile_cnf(engine, formula, &vtree, opts).ok()?;
        Some(engine.model_count(&compiled.diagram).ok()?.to_string())
    })
}

ComponentPlan::Whole compiles against the supplied vtree. CompileOptions::default() instead detects components itself and compiles each on a balanced vtree of its own. Each CompileOptions field’s rustdoc says what it turns on. The binary builds its vtree with vtree::build_vtree_with_components, and passes the component trees of the VtreeBuild it returns as ComponentPlan::from_components.

Invalid compile inputs return GiveUp::Invalid: a projection must name variables in 1..=formula.num_vars(), literal weights must cover every formula variable, and a supplied split must partition the formula. These checks also apply to constant formulas. An expired deadline stops a constant compile too, including a deadline inherited from the enclosing batch.

A diagram returned from the batch owns its storage and stays usable after the batch ends.