more graph search tests, try to get substitutions correct

This commit is contained in:
Michael Sippel 2025-05-30 20:17:14 +02:00
parent 0a2d77a66f
commit 0d09c74e47
Signed by: senvas
GPG key ID: F96CF119C34B64A6
6 changed files with 338 additions and 351 deletions

View file

@ -7,5 +7,8 @@ version = "0.1.0"
[dependencies]
tiny-ansi = { version = "0.1.0", optional = true }
[dev-dependencies]
pretty_assertions = "*"
[features]
pretty = ["dep:tiny-ansi"]

View file

@ -246,12 +246,11 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
TypeTerm::Ladder(vec![
ψ.clone(),
m.get_type().src_type
]).normalize(),
]),
dst_type: TypeTerm::Ladder(vec![
ψ.clone(),
m.get_type().dst_type
]).normalize(),
]),
},
MorphismInstance::Specialize { σ, m } =>
MorphismType {
@ -260,11 +259,11 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
},
MorphismInstance::Chain { path } => {
if path.len() > 0 {
let s = self.get_subst();
//let s = self.get_subst();
MorphismType {
src_type: path.first().unwrap().get_type().src_type.clone(),
dst_type: path.last().unwrap().get_type().dst_type.clone()
}.apply_subst(&s)
}//.apply_subst(&s)
} else {
MorphismType {
src_type: TypeTerm::TypeID(TypeID::Fun(45454)),

View file

@ -2,7 +2,7 @@ use {
crate::{
//morphism_path::{MorphismPath, ShortestPathProblem},
morphism::{Morphism, MorphismInstance, MorphismType}, StructMember, TypeDict, TypeID, TypeTerm
}, std::{char::decode_utf16, io::{Read, Write}}
}, std::{char::decode_utf16, collections::HashMap, io::{Read, Write}}
};
pub trait MorphBase<
@ -18,7 +18,7 @@ pub trait MorphBase<
}
}
#[derive(Debug)]
#[derive(Debug, PartialEq, Clone)]
pub enum DecomposedMorphismType {
SeqMap { item: MorphismType },
StructMap { members: Vec<(String, MorphismType)> },
@ -62,7 +62,6 @@ impl<M: Morphism + Clone> MorphismBase<M> {
}
}
eprintln!("Attempt Complex Decomposition....");
match (src_floor, dst_floor) {
(TypeTerm::Struct{ struct_repr: struct_repr_lhs, members: members_lhs},
TypeTerm::Struct { struct_repr: struct_repr_rhs, members: members_rhs })
@ -126,7 +125,7 @@ impl<M: Morphism + Clone> MorphismBase<M> {
}
}
pub fn enum_morphisms_from(&self, src_type: &TypeTerm) -> Vec< MorphismInstance<M> > {
pub fn enum_morphisms_from(&self, src_type: &TypeTerm) -> Vec< (TypeTerm, HashMap<TypeID, TypeTerm>, M) > {
let mut morphs = Vec::new();
for m in self.morphisms.iter() {
@ -139,18 +138,7 @@ impl<M: Morphism + Clone> MorphismBase<M> {
// morphisms source type,
// i.e. check if `src_type` is a subtype of `m_src_type`
if let Ok((ψ, σ)) = crate::constraint_system::subtype_unify(src_type, &m_src_type) {
let mut m = MorphismInstance::Primitive { m: m.clone() };
if !σ.is_empty() {
m = MorphismInstance::Specialize { σ, m: Box::new(m) };
}
if !ψ.is_empty() {
m = MorphismInstance::Sub { ψ, m: Box::new(m) }
}
eprintln!("..found direct morph to {:?}", m.get_type().dst_type);
morphs.push(m);
morphs.push((ψ, σ, m.clone()));
}
}
@ -164,53 +152,11 @@ impl<M: Morphism + Clone> MorphismBase<M> {
/* 2. check complex types */
if let Some(decomposition) = self.morphism_decomposition(src_type, &m_src_type) {
eprintln!("found complex morph to {:?}", decomposition);
morphs.push(decomposition);
}
}
morphs
}
/*
pub fn to_dot(&self, dict: &mut impl TypeDict) -> String {
let mut dot_source = String::new();
dot_source.push_str("digraph MorphismGraph {");
pub fn ty_to_dot_label(dict: &mut impl TypeDict, ty: &TypeTerm) -> String {
let pretty_str = ty.pretty(dict, 0);
let mut child = std::process::Command::new("aha").arg("--no-header")
.stdin( std::process::Stdio::piped() )
.stdout(std::process::Stdio::piped())
.spawn().expect("spawn child");
let mut stdin = child.stdin.take().expect("cant get stdin");
std::thread::spawn(move ||{ stdin.write_all(pretty_str.as_bytes()).expect("failed to write")});
let out = child.wait_with_output().expect("");
let html_str = String::from_utf8_lossy(&out.stdout).replace("\n", "<BR/>").replace("span", "B");
html_str
}
// add vertices
for (i,m) in self.morphisms.iter().enumerate() {
dot_source.push_str(&format!("
SRC{} [label=<{}>]
DST{} [label=<{}>]
SRC{} -> DST{} [label=\"{}\"]
", i, ty_to_dot_label(dict, &m.get_type().src_type),
i, ty_to_dot_label(dict, &m.get_type().dst_type),
i,i,i
));
}
// add edges
dot_source.push_str("}");
dot_source
}
*/
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\

View file

@ -8,19 +8,22 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
pub struct MorphismGraph<M: Morphism+Clone> {
pub struct MorphismGraph<M: Morphism+Clone+std::fmt::Debug> {
solved_paths: HashMap< MorphismType, MorphismInstance<M> >,
base: MorphismBase<M>
}
pub struct GraphSearch<M: Morphism+Clone> {
#[derive(Debug)]
pub struct GraphSearch<M: Morphism+Clone+std::fmt::Debug> {
goal: MorphismType,
solution: Option< MorphismInstance<M> >,
explore_queue: Vec< Arc<RwLock<SearchNode<M>>> >
explore_queue: Vec< Arc<RwLock<SearchNode<M>>> >,
skip_preview: bool
}
#[derive(Clone, Debug, PartialEq)]
pub enum GraphSearchState<M: Morphism+Clone> {
pub enum GraphSearchState<M: Morphism+Clone+std::fmt::Debug> {
Solved( MorphismInstance<M> ),
Continue,
Err( GraphSearchError )
@ -34,19 +37,23 @@ pub enum GraphSearchError {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
/// represents a partial path during search in the morphism graph
pub struct SearchNode<M: Morphism+Clone> {
#[derive(Debug)]
pub struct SearchNode<M: Morphism+Clone+std::fmt::Debug> {
/// predecessor node
pred: Option< Arc<RwLock< SearchNode<M> >> >,
/// (measured) weight of the preceding path
weight: u64,
ty: MorphismType,
/// the advancement over pred
step: Step<M>,
ψ: TypeTerm,
}
pub enum Step<M: Morphism+Clone> {
#[derive(Debug)]
pub enum Step<M: Morphism+Clone+std::fmt::Debug> {
Id { τ: TypeTerm },
Inst{ m: MorphismInstance<M> },
Specialize { σ: HashMap<TypeID, TypeTerm> },
@ -55,29 +62,43 @@ pub enum Step<M: Morphism+Clone> {
MapEnum { variants: Vec< (String, GraphSearch<M>) > }
}
impl<M:Morphism+Clone> SearchNode<M> {
}
pub trait SearchNodeExt<M: Morphism+Clone> {
pub trait SearchNodeExt<M: Morphism+Clone+std::fmt::Debug> {
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> Arc<RwLock<SearchNode<M>>>;
fn chain(&self, m: &MorphismInstance<M>) -> Arc<RwLock<SearchNode<M>>>;
fn chain(&self, ψ: TypeTerm, σ: HashMap<TypeID, TypeTerm>, m: M) -> Arc<RwLock<SearchNode<M>>>;
fn set_sub(&self, ψ: TypeTerm) -> Arc<RwLock<SearchNode<M>>>;
fn map_seq(&self, goal: MorphismType) -> Arc<RwLock<SearchNode<M>>>;
fn map_struct(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>>;
fn map_enum(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>>;
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> >;
fn get_type(&self) -> MorphismType;
fn advance(&self, base: &MorphismBase<M>, dict: &mut impl TypeDict) -> Result<bool, GraphSearchError>;
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> >;
fn is_ready(&self) -> bool;
fn get_weight(&self) -> u64;
fn get_type(&self) -> MorphismType;
fn creates_loop(&self) -> bool;
}
impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
impl<M: Morphism+Clone+std::fmt::Debug> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
fn get_weight(&self) -> u64 {
self.read().unwrap().weight
+ match &self.read().unwrap().step {
Step::Id { τ } => 0,
Step::Inst { m } => m.get_weight(),
Step::Specialize { σ } => 0,
Step::MapSeq { item } => item.best_path_weight(),
Step::MapStruct { members } => todo!(),
Step::MapEnum { variants } => todo!(),
}
}
fn get_type(&self) -> MorphismType {
let s = self.read().unwrap();
MorphismType {
src_type: TypeTerm::Ladder(vec![ s.ψ.clone(), s.ty.src_type.clone() ]).normalize(),
dst_type: TypeTerm::Ladder(vec![ s.ψ.clone(), s.ty.dst_type.clone() ]).normalize(),
}
}
fn is_ready(&self) -> bool {
let n = self.read().unwrap();
@ -99,6 +120,21 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
}
}
fn creates_loop(&self) -> bool {
/*
let mut cur_node = self.read().unwrap().pred.clone();
while let Some(n) = cur_node {
if n.get_type().dst_type == self.get_type().dst_type {
return true;
}
cur_node = n.read().unwrap().pred.clone();
}
*/
false
}
fn advance(&self, base: &MorphismBase<M>, dict: &mut impl TypeDict) -> Result<bool, GraphSearchError> {
let mut n = self.write().unwrap();
match &mut n.step {
@ -106,20 +142,15 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
eprintln!("advance seq-map");
match item.advance(base, dict) {
GraphSearchState::Solved(item_morph) => {
let map_morph = MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(item_morph)
eprintln!("Sequence-Map Sub Graph Solved!!");
n.ty = MorphismType {
src_type: TypeTerm::Seq { seq_repr: None, items: vec![ item_morph.get_type().src_type ] },
dst_type: TypeTerm::Seq { seq_repr: None, items: vec![ item_morph.get_type().dst_type ] },
};
return Ok(false);
}
GraphSearchState::Err(err) => {
return Err(err)
},
GraphSearchState::Continue => {
//self.explore_queue.push(node.clone());
return Ok(true);
Ok(false)
}
GraphSearchState::Continue => Ok(true),
GraphSearchState::Err(err) => Err(err)
}
}
Step::MapStruct { members } => {
@ -128,52 +159,59 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
Step::MapEnum { variants } => {
todo!()
}
/*
Step::Sub { ψ } =>{
return n.pred.as_ref().unwrap().advance(base, dict);
}
*/
_ => {}
_ => Ok(false)
}
return Ok(false);
}
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
weight: self.get_weight(),
ty: MorphismType {
src_type: self.get_type().src_type.apply_subst(&σ).clone().normalize(),
dst_type: self.get_type().dst_type.apply_subst(&σ).clone().normalize()
},
step: Step::Specialize { σ },
ψ: self.read().unwrap().ψ.clone()
}))
}
fn chain(&self, m: &MorphismInstance<M>) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
fn chain(&self, ψ: TypeTerm, σ: HashMap<TypeID, TypeTerm>, m: M) -> Arc<RwLock<SearchNode<M>>> {
let m = MorphismInstance::Primitive { m: m.clone() };
let mut n = Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight + m.get_weight(),
step: Step::Inst{ m: m.clone() },
ψ: self.read().unwrap().ψ.clone()
}))
weight: self.get_weight(),
ty: MorphismType {
src_type: self.get_type().src_type,
dst_type: m.get_type().dst_type
},
step: Step::Inst{ m },
ψ: TypeTerm::unit(),//self.read().unwrap().ψ.clone()
}));
n.set_sub(ψ);
if !σ.is_empty() {
n = n.specialize(σ);
}
n
}
fn set_sub(&self, ψ: TypeTerm) -> Arc<RwLock<SearchNode<M>>> {
self.write().unwrap().ψ = ψ;
let oldψ = &mut self.write().unwrap().ψ;
*oldψ = TypeTerm::Ladder(vec![ ψ, oldψ.clone() ]).normalize();
self.clone()
/*
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
step: Step::Sub{ ψ }
}))
*/
}
fn map_seq(&self, goal: MorphismType) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
weight: self.get_weight(),
ty: MorphismType {
src_type: TypeTerm::Seq{ seq_repr: None, items: vec![goal.src_type.clone()] },
dst_type: TypeTerm::Seq{ seq_repr: None, items: vec![goal.src_type.clone()] }
},
step: Step::MapSeq { item: GraphSearch::new(goal) },
ψ: self.read().unwrap().ψ.clone()
}))
@ -182,7 +220,8 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
fn map_struct(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
weight: self.get_weight(),
ty: todo!(),
step: Step::MapStruct { members: goals.into_iter().map(|(name,goal)| (name, GraphSearch::new(goal))).collect() },
ψ: self.read().unwrap().ψ.clone()
}))
@ -191,7 +230,8 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
fn map_enum(&self, goals: Vec<(String, MorphismType)>) -> Arc<RwLock<SearchNode<M>>> {
Arc::new(RwLock::new(SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
weight: self.get_weight(),
ty: todo!(),
step: Step::MapEnum { variants: goals.into_iter().map(|(name,goal)| (name, GraphSearch::new(goal))).collect() },
ψ: self.read().unwrap().ψ.clone()
}))
@ -202,21 +242,25 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
let mut path = Vec::new();
let mut subst = HashMap::new();
// let mut halos = Vec::new();
let mut cur_node = Some(self.clone());
while let Some(n) = cur_node {
let n = n.read().unwrap();
match &n.step {
Step::Id { τ } => { begin = τ.clone(); },
Step::Inst{ m } => {
let mut m = m.clone();
let σ = subst.clone().filter_morphtype(&m.get_type());
/*
if !σ.is_empty() {
m = MorphismInstance::Specialize { σ, m: Box::new(m) }
}
*/
if ! n.ψ.is_empty() {
m = MorphismInstance::Sub { ψ: n.ψ.clone(), m: Box::new(m) };
}
path.push(m.clone());
},
/*
Step::Sub { ψ } => {
halos.push(ψ.clone());
}
*/
Step::Specialize { σ } => {
subst = subst.append(&σ);
}
@ -230,6 +274,13 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
m = MorphismInstance::Sub { ψ: n.ψ.clone(), m: Box::new(m) };
}
/*
let σ = subst.clone().filter_morphtype(&m.get_type());
if !σ.is_empty() {
m = MorphismInstance::Specialize { σ, m: Box::new(m) }
}
*/
path.push(m);
}
Step::MapStruct { members } => {
@ -246,6 +297,13 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
path.reverse();
for m in path.iter_mut() {
let σ = subst.clone().filter_morphtype(&m.get_type());
if !σ.is_empty() {
*m = MorphismInstance::Specialize { σ, m: Box::new(m.clone()) };
}
}
let mut m =
if path.len() == 0 {
MorphismInstance::Id { τ: begin }
@ -255,9 +313,6 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
MorphismInstance::Chain { path }
};
eprintln!("to_morph_instance() σ = {:?}", subst);
subst = subst.filter_morphtype(&m.get_type());
if !subst.is_empty() {
m = MorphismInstance::Specialize { σ: subst, m: Box::new(m) };
@ -265,64 +320,11 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
Some(m)
}
fn get_type(&self) -> MorphismType {
let s = self.read().unwrap();
let t = match &s.step {
Step::Id { τ } => MorphismType {
src_type: τ.clone(),
dst_type: τ.clone()
},
/*
Step::Sub { ψ } => {
MorphismType {
src_type: TypeTerm::Ladder(vec![
ψ.clone(),
s.pred.as_ref().unwrap().get_type().src_type
]),
dst_type: TypeTerm::Ladder(vec![
ψ.clone(),
s.pred.as_ref().unwrap().get_type().dst_type
])
}
}
*/
Step::Inst{ m } => {
MorphismType {
src_type: s.pred.as_ref().unwrap().get_type().src_type,
dst_type: m.get_type().dst_type
}
},
Step::Specialize { σ } => {
if let Some(p) = s.pred.as_ref() {
MorphismType {
src_type: p.get_type().src_type.apply_subst(σ).clone().normalize(),
dst_type: p.get_type().dst_type.apply_subst(σ).clone().normalize()
}
} else {
unreachable!()
}
},
Step::MapSeq { item } => {
MorphismType {
src_type: TypeTerm::Seq{ seq_repr: None, items: vec![item.goal.src_type.clone()] },
dst_type: TypeTerm::Seq{ seq_repr: None, items: vec![item.goal.dst_type.clone()] }
}
}
_ => todo!()
};
MorphismType {
src_type: TypeTerm::Ladder(vec![ s.ψ.clone(), t.src_type ]).normalize(),
dst_type: TypeTerm::Ladder(vec![ s.ψ.clone(), t.dst_type ]).normalize(),
}
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
impl<M: Morphism+Clone> MorphismGraph<M> {
impl<M: Morphism+Clone+std::fmt::Debug> MorphismGraph<M> {
pub fn new(base: MorphismBase<M>) -> Self {
MorphismGraph {
solved_paths: HashMap::new(),
@ -336,7 +338,6 @@ impl<M: Morphism+Clone> MorphismGraph<M> {
> {
let mut search = GraphSearch::<M>::new(goal);
loop {
eprintln!("try to advance search..");
match search.advance(&self.base, dict) {
GraphSearchState::Solved(m) => { return Ok(m); }
GraphSearchState::Continue => { continue; }
@ -346,9 +347,8 @@ impl<M: Morphism+Clone> MorphismGraph<M> {
}
}
impl<M: Morphism+Clone> GraphSearch<M> {
impl<M: Morphism+Clone+std::fmt::Debug> GraphSearch<M> {
pub fn new(goal: MorphismType) -> Self {
eprintln!("New GraphSearch Problem!");
GraphSearch {
goal: goal.clone(),
solution: None,
@ -356,10 +356,15 @@ impl<M: Morphism+Clone> GraphSearch<M> {
Arc::new(RwLock::new(SearchNode {
pred: None,
weight: 0,
ty: MorphismType {
src_type: goal.src_type.clone(),
dst_type: goal.src_type.clone()
},
step: Step::Id { τ: goal.src_type.clone() },
ψ: TypeTerm::unit()
}))
]
],
skip_preview: false
}
}
@ -367,6 +372,14 @@ impl<M: Morphism+Clone> GraphSearch<M> {
self.solution.clone()
}
pub fn best_path_weight(&self) -> u64 {
if let Some(best) = self.explore_queue.last() {
best.get_weight()
} else {
0
}
}
pub fn est_remain(goal: &MorphismType, search_node: &Arc<RwLock<SearchNode<M>>>) -> u64 {
MorphismType {
src_type: goal.src_type.clone(),
@ -389,20 +402,24 @@ impl<M: Morphism+Clone> GraphSearch<M> {
)
}
);
eprintln!("===== TOP 5 PATHS =====\nGoal:\n {} -> {}",
goal.src_type.pretty(dict, 0),
goal.dst_type.pretty(dict, 0)
);
for i in 1 ..= usize::min(self.explore_queue.len(), 5) {
let n = &self.explore_queue[self.explore_queue.len() - i];
eprintln!("[[ {} ]] (weight: {} + est remain: {}) --- {} --> {}", i,
n.get_weight(),
Self::est_remain(&goal, &n),
n.get_type().src_type.pretty(dict, 0),
n.get_type().dst_type.pretty(dict, 0));
/*
if !self.skip_preview {
eprintln!("===== TOP 5 PATHS =====\nGoal:\n {} -> {}",
goal.src_type.pretty(dict, 0),
goal.dst_type.pretty(dict, 0)
);
for i in 1 ..= usize::min(self.explore_queue.len(), 5) {
let n = &self.explore_queue[self.explore_queue.len() - i];
eprintln!("[[ {} ]] (weight: {} + est remain: {}) --- {} --> {}", i,
n.get_weight(),
Self::est_remain(&goal, &n),
n.get_type().src_type.pretty(dict, 0),
n.get_type().dst_type.pretty(dict, 0));
}
} else {
self.skip_preview = false;
}
*/
self.explore_queue.pop()
}
@ -411,7 +428,10 @@ impl<M: Morphism+Clone> GraphSearch<M> {
match node.advance(base, dict) {
Ok(_) => {
if ! node.is_ready() {
self.explore_queue.push(node);
if ! node.creates_loop() {
self.skip_preview = true;
self.explore_queue.push(node);
}
return GraphSearchState::Continue;
} else {
let w = node.to_morphism_instance().unwrap().get_weight();
@ -424,6 +444,10 @@ impl<M: Morphism+Clone> GraphSearch<M> {
}
}
if node.creates_loop() {
return GraphSearchState::Continue;
}
/* 1. Check if goal is already reached by the current path */
if let Ok((, σ)) = crate::constraint_system::subtype_unify( &node.get_type().dst_type, &self.goal.dst_type ) {
/* found path */
@ -431,39 +455,43 @@ impl<M: Morphism+Clone> GraphSearch<M> {
if σ.is_empty() {
node.to_morphism_instance().unwrap()
} else {
node.specialize( σ.filter_morphtype(&node.get_type()) ).to_morphism_instance().unwrap()
node
.specialize( σ.filter_morphtype(&node.get_type()) )
.to_morphism_instance()
.unwrap()
}
);
return GraphSearchState::Solved(self.get_solution().unwrap());
}
else if let Some((ψ, decomposition)) = base.morphism_decomposition(&node.get_type().dst_type, &self.goal.dst_type) {
self.explore_queue.push(
match decomposition {
DecomposedMorphismType::SeqMap { item } => { node.map_seq( item ) },
DecomposedMorphismType::StructMap { members } => { node.map_struct(members) },
DecomposedMorphismType::EnumMap { variants } => { node.map_enum(variants) },
}.set_sub(ψ.clone())
);
//return GraphSearchState::Continue;
let mut decompositions = base.enum_complex_morphisms(&node.get_type().dst_type);
if let Some(d) = base.morphism_decomposition(&node.get_type().dst_type, &self.goal.dst_type) {
decompositions.push(d);
}
//eprintln!("{} decompositions", decompositions.len());
let mut done = Vec::new();
for (ψ,decomposition) in decompositions {
if ! done.contains(&(ψ.clone(),decomposition.clone())) {
self.explore_queue.push(
match &decomposition {
DecomposedMorphismType::SeqMap { item } => { node.map_seq( item.clone() ) },
DecomposedMorphismType::StructMap { members } => { node.map_struct(members.clone()) },
DecomposedMorphismType::EnumMap { variants } => { node.map_enum(variants.clone()) },
}.set_sub(ψ.clone())
);
done.push((ψ, decomposition));
}else {
//eprintln!("avoid duplicate decomposition");
}
}
/* 2. Try to advance current path */
for next_morph_inst in base.enum_morphisms_from(&node.get_type().dst_type) {
eprintln!("add direct path");
self.explore_queue.push( node.chain(&next_morph_inst) );
}
eprintln!("check complex decompositions from {}", node.get_type().dst_type.pretty(dict,0));
for (ψ,decomposition) in base.enum_complex_morphisms(&node.get_type().dst_type) {
eprintln!("add decomposition!");
self.explore_queue.push(
match decomposition {
DecomposedMorphismType::SeqMap { item } => { node.map_seq( item ) },
DecomposedMorphismType::StructMap { members } => { node.map_struct(members) },
DecomposedMorphismType::EnumMap { variants } => { node.map_enum(variants) },
}.set_sub(ψ)
);
for (ψ,σ,m) in base.enum_morphisms_from(&node.get_type().dst_type) {
//eprintln!("add direct path");
self.explore_queue.push( node.chain(ψ,σ,m) );
}
GraphSearchState::Continue

View file

@ -5,17 +5,19 @@ use crate::{term::TypeTerm, constraint_system, EnumVariant, StructMember};
pub fn splice_ladders( mut upper: Vec< TypeTerm >, mut lower: Vec< TypeTerm > ) -> Vec< TypeTerm > {
//eprintln!("splice ladders {:?} <<<====>>> {:?} ", upper, lower);
// check for overlap
for i in 0 .. upper.len() {
if upper[i] == lower[0] {
let mut result_ladder = Vec::<TypeTerm>::new();
result_ladder.append(&mut upper[0..i].iter().cloned().collect());
result_ladder.append(&mut lower);
return result_ladder;
if lower.len() > 0 {
for i in 0 .. upper.len() {
if upper[i] == lower[0] {
let mut result_ladder = Vec::<TypeTerm>::new();
result_ladder.append(&mut upper[0..i].iter().cloned().collect());
result_ladder.append(&mut lower);
return result_ladder;
}
}
}
// no overlap found, just concatenate ladders
upper.append(&mut lower);
// no overlap found, just concatenate ladders
upper.append(&mut lower);
}
upper
}

View file

@ -8,34 +8,8 @@ use {
std::collections::HashMap
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
fn print_subst(m: &std::collections::HashMap<TypeID, TypeTerm>, dict: &mut impl TypeDict) {
eprintln!("{{");
for (k,v) in m.iter() {
eprintln!(" {} --> {}",
dict.get_typename(k).unwrap(),
v.pretty(dict, 0)
);
}
eprintln!("}}");
}
fn print_path(dict: &mut impl TypeDict, path: &Vec<MorphismInstance<DummyMorphism>>) {
for n in path.iter() {
eprintln!("
morph {}
--> {}
with
",
n.get_type().src_type.pretty(dict, 0),
n.get_type().dst_type.pretty(dict, 0),
);
print_subst(&n.get_subst(), dict)
}
}
#[cfg(test)]
use pretty_assertions::{assert_eq, assert_ne};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
@ -57,46 +31,47 @@ fn morphism_test_setup() -> ( BimapTypeDict, MorphismBase<DummyMorphism> ) {
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared("<Digit Radix> ~ Char").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap().sugar(&mut dict)
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap()
})
);
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared("<Digit Radix> ~ Char").unwrap().sugar(&mut dict)
src_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ Char").unwrap()
})
);
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared(" ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
src_type: dict.parse(" ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap(),
dst_type: dict.parse(" ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap()
})
);
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared(" ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
})
);
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
src_type: dict.parse(" ~ <PosInt Radix LittleEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap(),
dst_type: dict.parse(" ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap()
})
);
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared("_2^64 ~ ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared("_2^64 ~ machine.UInt64").unwrap().sugar(&mut dict)
src_type: dict.parse(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix>~_2^64~machine.UInt64>").unwrap(),
dst_type: dict.parse(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix>~_2^64~machine.UInt64>").unwrap()
})
);
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse("_2^64 ~ ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix>~_2^64~machine.UInt64>").unwrap(),
dst_type: dict.parse("_2^64 ~ machine.UInt64").unwrap()
})
);
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared("_2^64 ~ machine.UInt64").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared("_2^64 ~ ~ <PosInt 0 LittleEndian> ~ <Seq <Digit 0>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
src_type: dict.parse("_2^64 ~ machine.UInt64").unwrap(),
dst_type: dict.parse("_2^64 ~ ~ <PosInt 0 LittleEndian> ~ <Seq <Digit 0>~_2^64~machine.UInt64>").unwrap()
})
);
(dict, base)
@ -218,7 +193,42 @@ fn test_morphgraph_map_seq() {
}
#[test]
fn test_morphism_path3() {
fn test_morphism_path1() {
let (mut dict, mut base) = morphism_test_setup();
let morph_graph = MorphismGraph::new(base);
assert_eq!(
morph_graph.search(MorphismType {
src_type: dict.parse(" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
dst_type: dict.parse(" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ _2^64 ~ machine.UInt64>").unwrap(),
}, &mut dict),
Ok(
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt 10 LittleEndian>").expect(""),
m: Box::new(
MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
m: Box::new(MorphismInstance::Primitive {
m: DummyMorphism(MorphismType {
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap()
}),
})
}
)
}
)
}));
}
#[test]
fn test_morphism_path2() {
let (mut dict, mut base) = morphism_test_setup();
let morph_graph = MorphismGraph::new(base);
@ -229,11 +239,6 @@ fn test_morphism_path3() {
dst_type: dict.parse(" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16> ~ _2^64 ~ machine.UInt64>").unwrap(),
}, &mut dict),
Ok(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"DstRadix".into()).unwrap(), TypeTerm::Num(16)),
].into_iter().collect(),
m: Box::new(
MorphismInstance::Chain {
path: vec![
MorphismInstance::Sub {
@ -257,12 +262,12 @@ fn test_morphism_path3() {
}
)
},
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"SrcRadix".into()).unwrap(), TypeTerm::Num(10)),
(dict.get_typeid(&"DstRadix".into()).unwrap(), TypeTerm::Num(16)),
].into_iter().collect(),
m: Box::new(
m: Box::new(
MorphismInstance::Primitive{
m: DummyMorphism(MorphismType {
src_type: dict.parse_desugared(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
@ -273,92 +278,96 @@ fn test_morphism_path3() {
}
]
}
)
}));
));
}
#[test]
fn test_morphism_path4() {
fn test_morphism_path3() {
let (mut dict, mut base) = morphism_test_setup();
let mut morph_graph = MorphismGraph::new(base);
let result = morph_graph.search(MorphismType {
src_type: dict.parse(" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
dst_type: dict.parse(" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16> ~ Char>").unwrap()
}, &mut dict);
eprintln!("{:#?}", result);
return;
assert_eq!(
morph_graph.search(MorphismType {
src_type: dict.parse(" ~ <PosInt 10 LittleEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
dst_type: dict.parse(" ~ <PosInt 16 LittleEndian> ~ <Seq <Digit 16> ~ Char>").unwrap()
}, &mut dict),
result,
Ok(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"DstRadix".into()).unwrap(), TypeTerm::Num(16)),
].into_iter().collect(),
m: Box::new(
MorphismInstance::Chain {
path: vec![
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt 10 LittleEndian>").expect(""),
m: Box::new(
MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
m: Box::new(MorphismInstance::Primitive {
m: DummyMorphism(MorphismType {
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap()
}),
})
}
)
m: Box::new(
MorphismInstance::Chain {
path: vec![
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt 10 LittleEndian>").expect(""),
m: Box::new(
MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
m: Box::new(MorphismInstance::Primitive {
m: DummyMorphism(MorphismType {
src_type: dict.parse("<Digit Radix> ~ Char").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap()
}),
})
}
)
},
}
)
},
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"SrcRadix".into()).unwrap(), TypeTerm::Num(10)),
// (dict.get_typeid(&"DstRadix".into()).unwrap(), TypeTerm::Num(16)),
].into_iter().collect(),
m: Box::new(
MorphismInstance::Primitive{
m: DummyMorphism(MorphismType {
src_type: dict.parse_desugared(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict)
}),
}
)
},
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"SrcRadix".into()).unwrap(), TypeTerm::Num(10)),
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
m: Box::new(
MorphismInstance::Primitive{
m: DummyMorphism(MorphismType {
src_type: dict.parse_desugared(" ~ <PosInt SrcRadix LittleEndian> ~ <Seq <Digit SrcRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict)
}),
}
)
},
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt DstRadix LittleEndian>").expect(""),
m: Box::new(
MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt DstRadix LittleEndian>").expect(""),
m: Box::new(
MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(
MorphismInstance::Specialize {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), dict.parse("DstRadix").expect("")),
].into_iter().collect(),
m: Box::new(MorphismInstance::Primitive {
m: DummyMorphism(MorphismType {
src_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ Char").unwrap()
}),
})
}
)
}
)
},
]
}
)
}));
m: DummyMorphism(MorphismType {
src_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").unwrap(),
dst_type: dict.parse("<Digit Radix> ~ Char").unwrap()
}),
})
})
})
}
]
})
}
));
}