diff --git a/src/lib.rs b/src/lib.rs index 11a001f..a06c3d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,3 +27,70 @@ pub use { unification::*, morphism::* }; + + +pub fn common_halo( + a: &TypeTerm, + b: &TypeTerm +) -> Option< TypeTerm > { + match (a,b) { + (TypeTerm::Ladder(rs1), TypeTerm::Ladder(rs2)) => { + let mut halo_rungs = Vec::new(); + + for (r1, r2) in rs1.iter().zip(rs2.iter()) { + if let Some(h) = common_halo(r1, r2) { + halo_rungs.push(h); + } else { + return Some(TypeTerm::Ladder(halo_rungs).normalize()); + } + } + + if halo_rungs.len() == 0 { + None + } else { + Some(TypeTerm::Ladder(halo_rungs).normalize()) + } + } + + (TypeTerm::App(a1), TypeTerm::App(a2)) => { + let mut halo_args = Vec::new(); + + for (r1, r2) in a1.iter().zip(a2.iter()) { + if let Some(h) = common_halo(r1, r2) { + halo_args.push(h); + } else { + return Some(TypeTerm::Ladder(halo_args).normalize()); + } + } + + if halo_args.len() == 0 { + None + } else { + Some(TypeTerm::App(halo_args).normalize()) + } + } + + (TypeTerm::Ladder(rsl), r) => { + if rsl.first().unwrap() == r { + Some(r.clone()) + } else { + None + } + } + (l, TypeTerm::Ladder(rsr)) => { + if rsr.first().unwrap() == l { + Some(l.clone()) + } else { + None + } + } + + (a1, a2) => { + if a1 == a2 { + Some(a1.clone()) + } else { + None + } + } + } +} diff --git a/src/morphism.rs b/src/morphism.rs index 8cf6a02..4a7d87e 100644 --- a/src/morphism.rs +++ b/src/morphism.rs @@ -1,8 +1,6 @@ use { crate::{ - unification::UnificationProblem, TypeDict, TypeID, TypeTerm, - pretty::*, - sugar::SugaredTypeTerm, + subtype_unify, sugar::SugaredTypeTerm, unification::UnificationProblem, unparser::*, TypeDict, TypeID, TypeTerm }, std::{collections::HashMap, u64} }; @@ -135,13 +133,17 @@ impl<M: Morphism + Clone> MorphismBase<M> { ])); } - dst_types.push( - MorphismInstance { - halo: TypeTerm::Ladder(dst_halo_ladder).normalize(), - m: item_morph_inst.m.map_morphism(seq_type.clone()).expect("couldnt get map morphism"), - σ: item_morph_inst.σ - } - ); + if let Some( map_morph ) = item_morph_inst.m.map_morphism( seq_type.clone() ) { + dst_types.push( + MorphismInstance { + halo: TypeTerm::Ladder(dst_halo_ladder).normalize(), + m: map_morph, + σ: item_morph_inst.σ + } + ); + } else { + eprintln!("could not get map morphism"); + } } } } @@ -245,28 +247,54 @@ impl<M: Morphism + Clone> MorphismBase<M> { None } -/* - pub fn find_direct_morphism(&self, ty: &MorphismType) -> Option< (M, HashMap<TypeID, TypeTerm>) > { - for m in self.morphisms.iter() { - let unification_problem = UnificationProblem::new( - vec![ - ( ty.src_type.clone(), m.get_type().src_type.clone() ), - ( m.get_type().dst_type.clone(), ty.dst_type.clone() ) - ] - ); - let unification_result = unification_problem.solve_subtype(); - if let Ok((halo, σ)) = unification_result { - return Some((m.clone(), σ)); + pub fn find_direct_morphism(&self, + ty: &MorphismType, + dict: &mut impl TypeDict + ) -> Option< MorphismInstance<M> > { + eprintln!("find direct morph"); + for m in self.morphisms.iter() { + let ty = ty.clone().normalize(); + let morph_type = m.get_type().normalize(); + + eprintln!("find direct morph:\n {} <= {}", + dict.unparse(&ty.src_type), dict.unparse(&morph_type.src_type), + ); + + if let Ok((halo, σ)) = subtype_unify(&ty.src_type, &morph_type.src_type) { + eprintln!("halo: {}", dict.unparse(&halo)); + + let dst_type = TypeTerm::Ladder(vec![ + halo.clone(), + morph_type.dst_type.clone() + ]); + eprintln!("-----------> {} <= {}", + dict.unparse(&dst_type), dict.unparse(&ty.dst_type) + ); + + /* + let unification_problem = UnificationProblem::new( + vec![ + ( ty.src_type, morph_type.src_type ), + ( morph_type.dst_type, ty.dst_type ) + ] + );*/ + + if let Ok((halo2, σ2)) = subtype_unify(&dst_type, &ty.dst_type) { + eprintln!("match. halo2 = {}", dict.unparse(&halo2)); + return Some(MorphismInstance { + m: m.clone(), + halo: halo2, + σ, + }); + } } } None } - pub fn find_map_morphism(&self, ty: &MorphismType) -> Option< (M, HashMap<TypeID, TypeTerm>) > { + pub fn find_map_morphism(&self, ty: &MorphismType, dict: &mut impl TypeDict) -> Option< MorphismInstance<M> > { for seq_type in self.seq_types.iter() { - eprintln!("try seq type {:?}", seq_type); - if let Ok((halo, σ)) = UnificationProblem::new(vec![ (ty.src_type.clone().param_normalize(), TypeTerm::App(vec![ seq_type.clone(), TypeTerm::TypeID(TypeID::Var(100)) ])), @@ -281,9 +309,13 @@ impl<M: Morphism + Clone> MorphismBase<M> { }.normalize(); //eprintln!("Map Morph: try to find item-morph with type {:?}", item_morph_type); - if let Some((m, σ)) = self.find_morphism( &item_morph_type ) { - if let Some(list_morph) = m.map_morphism( seq_type.clone() ) { - return Some( (list_morph, σ) ); + if let Some(item_morph_inst) = self.find_morphism( &item_morph_type, dict ) { + if let Some( list_morph ) = item_morph_inst.m.map_morphism( seq_type.clone() ) { + return Some( MorphismInstance { + m: list_morph, + σ, + halo + } ); } } } @@ -292,17 +324,18 @@ impl<M: Morphism + Clone> MorphismBase<M> { None } - pub fn find_morphism(&self, ty: &MorphismType) - -> Option< ( M, HashMap<TypeID, TypeTerm> ) > { - if let Some((m,σ)) = self.find_direct_morphism(ty) { - return Some((m,σ)); + pub fn find_morphism(&self, ty: &MorphismType, + dict: &mut impl TypeDict + ) + -> Option< MorphismInstance<M> > { + if let Some(m) = self.find_direct_morphism(ty, dict) { + return Some(m); } - if let Some((m,σ)) = self.find_map_morphism(ty) { - return Some((m, σ)); + if let Some(m) = self.find_map_morphism(ty, dict) { + return Some(m); } None } - */ } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ diff --git a/src/steiner_tree.rs b/src/steiner_tree.rs index 091d764..f3fa931 100644 --- a/src/steiner_tree.rs +++ b/src/steiner_tree.rs @@ -1,14 +1,9 @@ use { - std::collections::HashMap, crate::{ - TypeID, - TypeTerm, morphism::{ - MorphismType, - Morphism, - MorphismBase - } - } + Morphism, MorphismBase, MorphismType + }, MorphismInstance, TypeID, TypeTerm + }, std::collections::HashMap }; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ @@ -91,10 +86,11 @@ impl PathApproxSteinerTreeSolver { } } - pub fn solve<M: Morphism + Clone>(self, morphisms: &MorphismBase<M>) -> Option< SteinerTree > { - let mut tree = Vec::<MorphismType>::new(); + pub fn solve<M: Morphism + Clone + PartialEq>(self, morphisms: &MorphismBase<M>) -> Option< SteinerTree > { + let mut edges = Vec::<MorphismType>::new(); for goal in self.leaves { + eprintln!("solve steiner tree: find path to goal {:?}", goal); // try to find shortest path from root to current leaf if let Some(new_path) = morphisms.find_morphism_path( MorphismType { @@ -102,6 +98,15 @@ impl PathApproxSteinerTreeSolver { dst_type: goal.clone() } ) { + eprintln!("path to {:?} has len {}", goal.clone(), new_path.len()); + for morph_inst in new_path { + let t = morph_inst.get_type(); + if ! edges.contains(&t) { + eprintln!("add edge {:?}", t); + edges.push(t); + } + } +/* // reduce new path so that it does not collide with any existing path let mut src_type = self.root.clone(); let mut new_path_iter = new_path.into_iter().peekable(); @@ -109,12 +114,14 @@ impl PathApproxSteinerTreeSolver { // check all existing nodes.. if new_path_iter.peek().unwrap().get_type().src_type == src_type { + eprintln!("skip initial node.."); new_path_iter.next(); } for mt in tree.iter() { //assert!( mt.src_type == &src_type ); if let Some(t) = new_path_iter.peek() { + eprintln!(""); if &mt.dst_type == &t.get_type().src_type { // eliminate this node from new path src_type = new_path_iter.next().unwrap().get_type().src_type; @@ -127,6 +134,7 @@ impl PathApproxSteinerTreeSolver { for m in new_path_iter { tree.push(m.get_type()); } +*/ } else { eprintln!("could not find path\nfrom {:?}\nto {:?}", &self.root, &goal); return None; @@ -136,7 +144,7 @@ impl PathApproxSteinerTreeSolver { Some(SteinerTree { weight: 0, goals: vec![], - edges: tree + edges }) } } diff --git a/src/test/halo.rs b/src/test/halo.rs new file mode 100644 index 0000000..780b7fd --- /dev/null +++ b/src/test/halo.rs @@ -0,0 +1,39 @@ +use crate::{dict::BimapTypeDict, parser::*, unparser::*}; + +#[test] +fn test_common_halo() { + let mut dict = BimapTypeDict::new(); + + assert_eq!( + crate::common_halo( + &dict.parse("A~B~C").expect("parse error"), + &dict.parse("A~B~C").expect("parse error") + ), + Some(dict.parse("A~B~C").expect("parse error")) + ); + + assert_eq!( + crate::common_halo( + &dict.parse("A~B~X").expect("parse error"), + &dict.parse("A~B~Y").expect("parse error") + ), + Some(dict.parse("A~B").expect("parse error")) + ); + + assert_eq!( + crate::common_halo( + &dict.parse("A~<B C~D>").expect("parse error"), + &dict.parse("A~<B C~E>").expect("parse error") + ), + Some(dict.parse("A~<B C>").expect("parse error")) + ); + + + assert_eq!( + crate::common_halo( + &dict.parse("A").expect("parse error"), + &dict.parse("A~<B C~E>").expect("parse error") + ), + Some(dict.parse("A").expect("parse error")) + ); +} diff --git a/src/test/mod.rs b/src/test/mod.rs index 41f5e71..1cd4673 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -8,4 +8,4 @@ pub mod subtype; pub mod substitution; pub mod unification; pub mod morphism; - +pub mod halo; diff --git a/src/test/unification.rs b/src/test/unification.rs index 56e88e2..7811647 100644 --- a/src/test/unification.rs +++ b/src/test/unification.rs @@ -173,12 +173,12 @@ fn test_subtype_unification() { UnificationProblem::new(vec![ (dict.parse("<Seq T>").unwrap(), dict.parse("<Seq W~<Seq Char>>").unwrap()), - (dict.parse("<Seq ℕ~<PosInt 10 BigEndian>>").unwrap(), - dict.parse("<Seq~<LengthPrefix x86.UInt64> W>").unwrap()), + (dict.parse("<Seq~<LengthPrefix x86.UInt64> ℕ~<PosInt 10 BigEndian>>").unwrap(), + dict.parse("<<LengthPrefix x86.UInt64> W>").unwrap()), ]).solve_subtype(), Ok(( dict.parse(" - <Seq~<LengthPrefix x86.UInt64> ℕ~<PosInt 10 BigEndian>> + <Seq ℕ~<PosInt 10 BigEndian>> ").unwrap(), vec![ // W diff --git a/src/unification.rs b/src/unification.rs index e605af4..850d76c 100644 --- a/src/unification.rs +++ b/src/unification.rs @@ -92,16 +92,19 @@ impl UnificationProblem { }, (t, TypeTerm::Ladder(mut a1)) => { - if let Ok(mut halo) = self.eval_subtype( t.clone(), a1.first().unwrap().clone(), addr.clone() ) { + /* + if let Ok(mut halo) = self.eval_subtype( t.clone(), a1.first().unwrap().clone(), addr.clone() ) a1.append(&mut halo); Ok(a1) } else { + */ Err(UnificationError{ addr, t1: t, t2: TypeTerm::Ladder(a1) }) - } + //} } (TypeTerm::Ladder(mut a1), t) => { if let Ok(mut halo) = self.eval_subtype( a1.pop().unwrap(), t.clone(), addr.clone() ) { + a1.append(&mut halo); Ok(a1) } else {