lib-nested/lib-nested-core/src/repr_tree/builder.rs
2025-03-10 18:19:09 +01:00

114 lines
4.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use {
super::{context::{TYPEID_char, TYPEID_edittree, TYPEID_list, TYPEID_u64, TYPEID_vec}, Context, ReprLeaf, ReprTree, ReprTreeExt}, laddertypes::{steiner_tree, sugar::*, unparser::UnparseLadderType as _, TypeID, TypeTerm}, r3vi::{
buffer::{singleton::*, vec::*}, view::{
list::*, port::UpdateTask, sequence::*, singleton::*, AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, Observer, OuterViewPort, View, ViewPort
}
}, std::{
any::Any, collections::HashMap, sync::{Arc, RwLock}
}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
#[derive(Clone)]
pub struct ReprTreeBuilder {
ctx: Arc<RwLock<Context>>,
pub required_leaves: Vec<TypeTerm>,
}
#[derive(Debug)]
pub enum ReprTreeError {
MissingMorphism
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl ReprTreeBuilder {
pub fn new(ctx: Arc<RwLock<Context>>) -> Self {
ReprTreeBuilder {
ctx,
required_leaves: Vec::new()
}
}
/// Add a type to the set of required representations.
pub fn require(mut self, mut t: TypeTerm) -> Self {
t = t.normalize();
if !self.required_leaves.contains(&t) {
self.required_leaves.push(t);
}
self
}
/// (re)build steiner tree with `required_leaves`,
/// and apply it to the projections in the ReprTree.
/// Updating and keeping existing nodes, while
/// adding new ones if required.
pub fn update(
&self,
rt: &Arc<RwLock<ReprTree>>,
master_leaf_type: impl Into<TypeTerm>
) -> Result< Arc<RwLock<ReprTree>>, ReprTreeError > {
rt.write().unwrap().detach( &self.ctx );
let morphism_base = &self.ctx.read().unwrap().morphisms;
let mt = master_leaf_type.into().normalize().param_normalize();
eprintln!("REBUILD repr tree from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
let mut leaves = self.required_leaves.clone();
leaves.retain(|t| t != &mt);
let mut st_problem = laddertypes::steiner_tree::PathApproxSteinerTreeSolver::new(
mt.clone(),
leaves
);
if let Some( steiner_tree ) = st_problem.solve( &morphism_base ) {
eprintln!("--> from {}", self.ctx.read().unwrap().type_term_to_str(&mt));
let edges = steiner_tree.into_edges();
eprintln!("steiner tree has {} edges", edges.len());
for morphism_type in edges {
eprintln!("--> morph to {}",
self.ctx.read().unwrap().type_term_to_str(&morphism_type.dst_type));
let mut dict = self.ctx.read().unwrap().type_dict.clone();
if let Some(morph_inst) =
morphism_base.find_morphism( &morphism_type, &mut dict )
{
eprintln!("setup morph");
let halo = laddertypes::common_halo(
&morphism_type.src_type,
&morphism_type.dst_type
).unwrap_or(TypeTerm::unit());
eprintln!("halo = {}", dict.read().unwrap().unparse(&halo));
let mut rt = rt.descend_create( halo ).expect("descend src repr");
eprintln!("{}", rt.read().unwrap().fmt(&self.ctx, 0));
(morph_inst.m.setup_projection)( &mut rt, &morph_inst.σ );
} else {
eprintln!("failed to get morphism");
return Err(ReprTreeError::MissingMorphism);
}
}
Ok( rt.clone() )
} else {
eprintln!("could not find steiner tree to build the requested repr tree");
Err(ReprTreeError::MissingMorphism)
}
}
/// Build fresh ReprTree from a master representation.
pub fn build_from(
&self,
mut master_rt: Arc<RwLock<ReprTree>>
) -> Result< Arc<RwLock<ReprTree>>, ReprTreeError > {
let master_leaf_type = master_rt.get_full_type();
self.update( &ReprTree::rise( master_rt ), master_leaf_type )
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>