further work on new graph search

now passes simple tests for id, specialization and chains
This commit is contained in:
Michael Sippel 2025-05-30 00:20:13 +02:00
parent 081004ffab
commit 0126a62e76
Signed by: senvas
GPG key ID: F96CF119C34B64A6
7 changed files with 372 additions and 224 deletions

View file

@ -1,10 +1,11 @@
use crate::{MorphismType, TypeTerm};
use crate::{MorphismType, TypeTerm, TypeID};
impl MorphismType {
pub fn estimated_cost(&self) -> u64 {
if let Ok((ψ,σ)) = crate::subtype_unify(&self.src_type, &self.dst_type) {
1
0
} else {
match (self.src_type.clone().normalize(),
self.dst_type.clone().normalize())
@ -28,7 +29,7 @@ impl MorphismType {
(TypeTerm::Seq{ seq_repr: sr1, items: items1 },
TypeTerm::Seq{ seq_repr: sr2, items: items2 }) => {
let mut cost = 10;
/*
/* // todo : add cost seq-repr conversion?
estimated_morphism_cost(
&MorphismType { src_type: sr1, dst_type: sr2 }
);
@ -40,6 +41,11 @@ impl MorphismType {
cost
}
(TypeTerm::TypeID(TypeID::Var(_)), x)
| (x, TypeTerm::TypeID(TypeID::Var(_)))
=> {
return 1;
}
(a, b) => {
if a == b {
return 0;

View file

@ -186,28 +186,27 @@ pub trait Morphism : Sized {
#[derive(Clone, PartialEq, Debug)]
pub enum MorphismInstance<M: Morphism + Clone> {
Id { ψ: TypeTerm },
Primitive{
Id { τ: TypeTerm },
Primitive{ m: M },
Sub {
ψ: TypeTerm,
m: Box<MorphismInstance<M>>
},
Specialize{
σ: HashMap<TypeID, TypeTerm>,
morph: M,
},
Chain{
path: Vec<MorphismInstance<M>>
m: Box<MorphismInstance<M>>
},
Chain{ path: Vec<MorphismInstance<M>> },
MapSeq{
ψ: TypeTerm,
seq_repr: Option<Box<TypeTerm>>,
item_morph: Box<MorphismInstance<M>>,
},
MapStruct{
ψ: TypeTerm,
src_struct_repr: Option<Box<TypeTerm>>,
dst_struct_repr: Option<Box<TypeTerm>>,
member_morph: Vec< (String, MorphismInstance<M>) >
},
MapEnum{
ψ: TypeTerm,
enum_repr: Option<Box<TypeTerm>>,
variant_morph: Vec< (String, MorphismInstance<M>) >
}
@ -221,39 +220,44 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
pub fn get_weight(&self) -> u64 {
match self {
MorphismInstance::Id { ψ } => 0,
MorphismInstance::Primitive { ψ, σ, morph } => 1,
MorphismInstance::Id { τ } => 0,
MorphismInstance::Sub { ψ, m } => 0,
MorphismInstance::Specialize { σ, m } => 0,
MorphismInstance::Primitive { m } => 10,
MorphismInstance::Chain { path } => path.iter().map(|m| m.get_weight()).sum(),
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => item_morph.get_weight() + 1,
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => member_morph.iter().map(|m| m.1.get_weight()).sum(),
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => variant_morph.iter().map(|m| m.1.get_weight()).sum()
MorphismInstance::MapSeq { seq_repr, item_morph } => item_morph.get_weight() + 15,
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => member_morph.iter().map(|m| m.1.get_weight()).sum(),
MorphismInstance::MapEnum { enum_repr, variant_morph } => variant_morph.iter().map(|m| m.1.get_weight()).sum()
}
}
pub fn get_type(&self) -> MorphismType {
match self {
MorphismInstance::Id { ψ } => {
MorphismInstance::Id { τ } => {
MorphismType {
src_type: ψ.clone(),
dst_type: ψ.clone()
src_type: τ.clone(),
dst_type: τ.clone()
}
}
MorphismInstance::Primitive { ψ, σ, morph } => {
MorphismInstance::Primitive { m } => { m.get_type() },
MorphismInstance::Sub { ψ, m } =>
MorphismType {
src_type:
TypeTerm::Ladder(vec![
ψ.clone(),
morph.get_type().src_type
.apply_subst(σ).clone()
]).strip(),
m.get_type().src_type
]).normalize(),
dst_type: TypeTerm::Ladder(vec![
ψ.clone(),
morph.get_type().dst_type
.apply_subst(σ).clone()
]).strip(),
}
}
m.get_type().dst_type
]).normalize(),
},
MorphismInstance::Specialize { σ, m } =>
MorphismType {
src_type: m.get_type().src_type.apply_subst(σ).clone(),
dst_type: m.get_type().dst_type.apply_subst(σ).clone(),
},
MorphismInstance::Chain { path } => {
if path.len() > 0 {
let s = self.get_subst();
@ -268,60 +272,49 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
}
}
}
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => {
MorphismInstance::MapSeq { seq_repr, item_morph } => {
MorphismType {
src_type: TypeTerm::Ladder(vec![
ψ.clone(),
TypeTerm::Seq{ seq_repr: seq_repr.clone(),
items: vec![ item_morph.get_type().src_type ]}
]),
dst_type: TypeTerm::Ladder(vec![
ψ.clone(),
TypeTerm::Seq{ seq_repr: seq_repr.clone(),
items: vec![ item_morph.get_type().dst_type ]}
])
src_type: TypeTerm::Seq{ seq_repr: seq_repr.clone(),
items: vec![ item_morph.get_type().src_type ]
},
dst_type: TypeTerm::Seq{ seq_repr: seq_repr.clone(),
items: vec![ item_morph.get_type().dst_type ]
}
}
}
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => {
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => {
MorphismType {
src_type: TypeTerm::Ladder(vec![ ψ.clone(),
TypeTerm::Struct{
src_type: TypeTerm::Struct {
struct_repr: src_struct_repr.clone(),
members:
member_morph.iter().map(|(symbol, morph)| {
StructMember{ symbol:symbol.clone(), ty: morph.get_type().src_type }
}).collect()
}
]),
dst_type: TypeTerm::Ladder(vec![ ψ.clone(),
TypeTerm::Struct{
},
dst_type: TypeTerm::Struct {
struct_repr: dst_struct_repr.clone(),
members: member_morph.iter().map(|(symbol, morph)| {
StructMember { symbol: symbol.clone(), ty: morph.get_type().dst_type}
}).collect()
}
])
}
}
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => {
MorphismInstance::MapEnum { enum_repr, variant_morph } => {
MorphismType {
src_type: TypeTerm::Ladder(vec![ ψ.clone(),
TypeTerm::Struct{
src_type: TypeTerm::Struct{
struct_repr: enum_repr.clone(),
members:
variant_morph.iter().map(|(symbol, morph)| {
StructMember{ symbol:symbol.clone(), ty: morph.get_type().src_type }
}).collect()
}
]),
dst_type: TypeTerm::Ladder(vec![ ψ.clone(),
TypeTerm::Struct{
},
dst_type: TypeTerm::Struct{
struct_repr: enum_repr.clone(),
members: variant_morph.iter().map(|(symbol, morph)| {
StructMember { symbol: symbol.clone(), ty: morph.get_type().dst_type}
}).collect()
}
])
}
}
}.normalize()
@ -329,10 +322,12 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
pub fn get_subst(&self) -> std::collections::HashMap< TypeID, TypeTerm > {
match self {
MorphismInstance::Id { ψ } => {
std::collections::HashMap::new()
MorphismInstance::Id { τ } => HashMap::new(),
MorphismInstance::Primitive { m } => HashMap::new(),
MorphismInstance::Sub { ψ, m } => m.get_subst(),
MorphismInstance::Specialize { σ, m } => {
m.get_subst().append(σ)
}
MorphismInstance::Primitive { ψ, σ, morph } => σ.clone(),
MorphismInstance::Chain { path } => {
path.iter().fold(
std::collections::HashMap::new(),
@ -342,17 +337,17 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
}
)
},
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => {
MorphismInstance::MapSeq { seq_repr, item_morph } => {
item_morph.get_subst()
},
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => {
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => {
let mut σ = HashMap::new();
for (symbol, m) in member_morph.iter() {
σ = σ.append(&mut m.get_subst());
}
σ
},
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => {
MorphismInstance::MapEnum { enum_repr, variant_morph } => {
todo!();
HashMap::new()
},
@ -362,18 +357,22 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
pub fn apply_subst(&mut self, γ: &std::collections::HashMap< TypeID, TypeTerm >) {
let ty = self.get_type();
match self {
MorphismInstance::Id { ψ } => {
ψ.apply_subst( γ );
MorphismInstance::Id { τ } => {
τ.apply_subst( γ );
}
MorphismInstance::Primitive { ψ, σ, morph } => {
MorphismInstance::Primitive { m } => { },
MorphismInstance::Sub { ψ, m } => {
ψ.apply_subst(γ);
m.apply_subst(γ);
}
MorphismInstance::Specialize { σ, m } => {
for (n,t) in σ.iter_mut() {
t.apply_subst(γ);
}
for (n,t) in γ.iter() {
if let TypeID::Var(varid) = n {
if morph.get_type().src_type.apply_subst(σ).contains_var(*varid)
|| morph.get_type().dst_type.apply_subst(σ).contains_var(*varid) {
if m.get_type().src_type.apply_subst(σ).contains_var(*varid)
|| m.get_type().dst_type.apply_subst(σ).contains_var(*varid) {
σ.insert(n.clone(), t.clone());
}
}
@ -384,16 +383,15 @@ impl<M: Morphism + Clone> MorphismInstance<M> {
n.apply_subst(γ);
}
}
MorphismInstance::MapSeq { ψ, seq_repr, item_morph } => {
ψ.apply_subst(γ);
MorphismInstance::MapSeq { seq_repr, item_morph } => {
item_morph.apply_subst(γ);
}
MorphismInstance::MapStruct { ψ, src_struct_repr, dst_struct_repr, member_morph } => {
MorphismInstance::MapStruct { src_struct_repr, dst_struct_repr, member_morph } => {
for (_,ty) in member_morph {
ty.apply_subst(γ);
}
},
MorphismInstance::MapEnum { ψ, enum_repr, variant_morph } => {
MorphismInstance::MapEnum { enum_repr, variant_morph } => {
for (_,ty) in variant_morph {
ty.apply_subst(γ);
}

View file

@ -19,6 +19,12 @@ pub trait MorphBase<
}
}
pub enum DecomposedMorphismType {
SeqMap { item: MorphismType },
StructMap { members: Vec<(String, MorphismType)> },
EnumMap { variants: Vec<(String, MorphismType)> }
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
#[derive(Clone)]
@ -38,29 +44,16 @@ impl<M: Morphism + Clone> MorphismBase<M> {
pub fn add_morphism(&mut self, m: M) {
self.morphisms.push( m );
}
/*
pub fn get_morphism_instance(&self, ty: &MorphismType, dict: &mut impl TypeDict) -> Option<MorphismInstance<M>> {
if let Some(path) = ShortestPathProblem::new(self, ty.clone()).solve(dict) {
if path.len() == 0 {
Some(MorphismInstance::Id{ ψ: ty.src_type.clone() })
} else if path.len() == 1 {
Some(path[0].clone())
} else {
Some(MorphismInstance::Chain { path })
}
} else {
None
}
}
*/
/*
given a morphism type (src/dst types),
try to match their outer structure (Struct/Seq/Map)
and spawn a GraphSearch for each component
*/
/*
pub fn complex_morphism_decomposition(&self, src_type: &TypeTerm, dst_type: &TypeTerm, dict: &mut impl TypeDict) -> Option< MorphismInstance<M> > {
pub fn complex_morphism_decomposition(&self, src_type: &TypeTerm, dst_type: &TypeTerm, dict: &mut impl TypeDict) ->
Option< DecomposedMorphismType >
{
let (src_ψ, src_floor) = src_type.get_floor_type();
let (dst_ψ, dst_floor) = dst_type.get_floor_type();
@ -138,8 +131,8 @@ impl<M: Morphism + Clone> MorphismBase<M> {
}
}
}
pub fn enum_morphisms_from(&self, src_type: &TypeTerm, dict: &mut impl TypeDict) -> Vec< MorphismInstance<M> > {
*/
pub fn enum_morphisms_from(&self, src_type: &TypeTerm) -> Vec< MorphismInstance<M> > {
let mut morphs = Vec::new();
for m in self.morphisms.iter() {
@ -152,22 +145,32 @@ 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 morph_inst = MorphismInstance::Primitive { ψ, σ, morph: m.clone() };
eprintln!("..found direct morph to {:?}", morph_inst.get_type().dst_type);
morphs.push(morph_inst);
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);
}
/* 2. check complex types */
/*
else if let Some(complex_morph) = self.complex_morphism_decomposition(src_type, &m_src_type, dict) {
eprintln!("found complex morph to {:?}", complex_morph.get_type().dst_type);
morphs.push(complex_morph);
}
*/
}
morphs
}
/*
pub fn to_dot(&self, dict: &mut impl TypeDict) -> String {
let mut dot_source = String::new();

View file

@ -1,31 +1,31 @@
use {
crate::{
Morphism, MorphismType, MorphismInstance, Substitution,
TypeTerm, TypeID
Morphism, MorphismBase, MorphismInstance, MorphismType, Substitution, TypeID, TypeTerm, TypeDict
},
std::collections::HashMap,
std::sync::{Arc,RwLock}
std::{collections::HashMap, sync::{Arc,RwLock}}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
pub struct MorphismGraph<M: Morphism+Clone> {
solved_paths: HashMap< MorphismType, MorphismInstance<M> >,
base: MorphismBase<M>
}
pub struct GraphSearch<M: Morphism+Clone> {
goal: MorphismType,
solution: Option< MorphismInstance<M> >,
explore_queue: Vec< Arc<RwLock<SearchNode<M>>> >
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub enum GraphSearchState<M: Morphism+Clone> {
Solved( MorphismInstance<M> ),
Continue,
Err( GraphSearchError )
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub enum GraphSearchError {
NoMorphismFound
}
@ -46,67 +46,100 @@ pub struct SearchNode<M: Morphism+Clone> {
pub enum Step<M: Morphism+Clone> {
Id { τ: TypeTerm },
Sub{ ψ: TypeTerm },
Inst( MorphismInstance<M> ),
Spec{ σ: HashMap<TypeID, TypeTerm> },
Inst{ m: MorphismInstance<M> },
Specialize { σ: HashMap<TypeID, TypeTerm> },
MapSeq { item: GraphSearch<M> },
MapStruct { members: Vec< (String, GraphSearch<M>) > },
MapEnum { variants: Vec< (String, GraphSearch<M>) > }
}
impl<M:Morphism+Clone> SearchNode<M> {
pub fn advance(&mut self) -> GraphSearchState<M> {
match &mut self.step {
Step::MapSeq { item } => {
match item.advance() {
GraphSearchState::Solved(item_morph) => GraphSearchState::Solved(
MorphismInstance::MapSeq { ψ: todo!(), seq_repr: todo!(), item_morph: Box::new(item_morph) }
),
x => x
}
}
Step::MapStruct { members } => {
todo!()
}
Step::MapEnum { variants } => {
todo!()
}
_ => {
GraphSearchState::Solved(self.to_morphism_instance())
}
}
}
fn to_morphism_instance(&self) -> MorphismInstance<M> {
// let pred_instance = self.read().unwrap().pred.unwrap().to_morphism_instance();
match &self.step {
Step::Id { τ } => MorphismInstance::Id { ψ: τ.clone() },
_ => todo!()
}
}
}
pub trait SearchNodeExt<M: Morphism+Clone> {
fn advance_dst(&self, m: &MorphismInstance<M>) -> SearchNode<M>;
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> SearchNode<M>;
fn chain(&self, m: &MorphismInstance<M>) -> SearchNode<M>;
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> >;
fn get_type(&self) -> MorphismType;
}
impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
fn advance_dst(&self, m: &MorphismInstance<M>) -> SearchNode<M> {
fn specialize(&self, σ: HashMap<TypeID, TypeTerm>) -> SearchNode<M> {
SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight,
step: Step::Specialize { σ }
}
}
fn chain(&self, m: &MorphismInstance<M>) -> SearchNode<M> {
SearchNode {
pred: Some(self.clone()),
weight: self.read().unwrap().weight + m.get_weight(),
step: Step::Inst(m.clone())
step: Step::Inst{ m: m.clone() }
}
}
fn to_morphism_instance(&self) -> Option< MorphismInstance<M> > {
let mut begin = TypeTerm::unit();
let mut path = Vec::new();
let mut subst = HashMap::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 } => {
path.push(m.clone());
},
Step::Specialize { σ } => {
subst = subst.append(&σ);
}
Step::MapSeq { item } => {
path.push(MorphismInstance::MapSeq {
seq_repr: None,
item_morph: Box::new(item.get_solution().expect(""))
})
}
Step::MapStruct { members } => {
todo!();
//path.push(MorphismInstance::MapStruct { src_struct_repr: (), dst_struct_repr: (), member_morph: () })
}
Step::MapEnum { variants } => {
todo!();
}
}
cur_node = n.pred.clone();
}
path.reverse();
let mut m =
if path.len() == 0 {
MorphismInstance::Id { τ: begin }
} else if path.len() == 1 {
path[0].clone()
} else {
MorphismInstance::Chain { path }
};
if !subst.is_empty() {
m = MorphismInstance::Specialize { σ: subst, m: Box::new(m) };
}
Some(m)
}
fn get_type(&self) -> MorphismType {
match &self.read().unwrap().step {
Step::Id { τ } => MorphismType {
src_type: τ.clone(),
dst_type: τ.clone()
},
/*
Step::Sub { ψ } => {
if let Some(p) = self.read().unwrap().pred.as_ref() {
MorphismType {
@ -117,8 +150,9 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
unreachable!()
}
}
Step::Inst( m ) => m.get_type(),
Step::Spec { σ } => {
*/
Step::Inst{ m } => m.get_type(),
Step::Specialize { σ } => {
if let Some(p) = self.read().unwrap().pred.as_ref() {
MorphismType {
src_type: p.get_type().src_type.apply_subst(σ).clone().normalize(),
@ -148,14 +182,26 @@ impl<M: Morphism+Clone> SearchNodeExt<M> for Arc<RwLock<SearchNode<M>>> {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
impl<M: Morphism+Clone> MorphismGraph<M> {
pub fn new() -> Self {
pub fn new(base: MorphismBase<M>) -> Self {
MorphismGraph {
solved_paths: HashMap::new()
solved_paths: HashMap::new(),
base
}
}
pub fn search(&self, goal: MorphismType) -> GraphSearch<M> {
GraphSearch::<M>::new(goal)
pub fn search(&self, goal: MorphismType, dict: &mut impl TypeDict) -> Result<
MorphismInstance<M>,
GraphSearchError
> {
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; }
GraphSearchState::Err(err) => { return Err(err); }
}
}
}
}
@ -163,6 +209,7 @@ impl<M: Morphism+Clone> GraphSearch<M> {
pub fn new(goal: MorphismType) -> Self {
GraphSearch {
goal: goal.clone(),
solution: None,
explore_queue: vec![
Arc::new(RwLock::new(SearchNode {
pred: None,
@ -173,6 +220,10 @@ impl<M: Morphism+Clone> GraphSearch<M> {
}
}
pub fn get_solution(&self) -> Option< MorphismInstance<M> > {
self.solution.clone()
}
pub fn est_remain(goal: &MorphismType, search_node: &Arc<RwLock<SearchNode<M>>>) -> u64 {
MorphismType {
src_type: goal.src_type.clone(),
@ -185,7 +236,7 @@ impl<M: Morphism+Clone> GraphSearch<M> {
}.estimated_cost()
}
pub fn choose_next_node(&mut self) -> Option<Arc<RwLock<SearchNode<M>>>> {
pub fn choose_next_node(&mut self, dict: &mut impl TypeDict) -> Option<Arc<RwLock<SearchNode<M>>>> {
let goal= self.goal.clone();
self.explore_queue.sort_by(
|a,b| {
@ -195,49 +246,74 @@ 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!("[[ {} ]] (est remain: {}) --- {} --> {}", i,
Self::est_remain(&goal, &n),
n.get_type().src_type.pretty(dict, 0),
n.get_type().dst_type.pretty(dict, 0));
}
self.explore_queue.pop()
}
pub fn advance(&mut self) -> GraphSearchState<M> {
if let Some(node) = self.choose_next_node() {
pub fn advance(&mut self, base: &MorphismBase<M>, dict: &mut impl TypeDict) -> GraphSearchState<M> {
if let Some(node) = self.choose_next_node(dict) {
{
let mut n = node.write().unwrap();
match &mut n.step {
Step::MapSeq { item } => {
match item.advance(base, dict) {
GraphSearchState::Solved(item_morph) => {
let map_morph = MorphismInstance::MapSeq {
seq_repr: todo!(),
item_morph: Box::new(item_morph)
};
}
GraphSearchState::Err(err) => {
return GraphSearchState::Err(err);
},
GraphSearchState::Continue => {
self.explore_queue.push(node.clone());
return GraphSearchState::Continue;
}
}
}
Step::MapStruct { members } => {
todo!()
}
Step::MapEnum { variants } => {
todo!()
}
_ => {}
}
}
/* 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,
* now apply substitution and trim to variables in terms of each step
*/
//node.apply_subst(&σ);
//node.specialize(&σ);
return GraphSearchState::Solved(node.read().unwrap().to_morphism_instance());
/* found path */
self.solution = Some(
if σ.is_empty() {
node.to_morphism_instance().unwrap()
} else {
Arc::new(RwLock::new(node.specialize(σ))).to_morphism_instance().unwrap()
}
);
return GraphSearchState::Solved(self.get_solution().unwrap())
}
/* 2. Try to advance current path */
/*
else if let Some(complex_morph) =
self.morphism_base.complex_morphism_decomposition( &cur_path.cur_type, &self.goal, dict )
{
self.advance(&cur_path, complex_morph);
for next_morph_inst in base.enum_morphisms_from(&node.get_type().dst_type) {
self.explore_queue.push( Arc::new(RwLock::new( node.chain(&next_morph_inst) )) );
}
for next_morph_inst in self.morphism_base.enum_morphisms_from(&cur_path.cur_type, dict) {
self.advance(&cur_path, next_morph_inst);
}
*/
}
GraphSearchState::Continue
}
pub fn solve(&mut self) -> Result<
MorphismInstance<M>,
GraphSearchError
> {
loop {
match self.advance() {
GraphSearchState::Solved(m) => { return Ok(m); }
GraphSearchState::Continue => { continue; }
GraphSearchState::Err(err) => { return Err(err); }
}
}
}
}

View file

@ -19,7 +19,6 @@ pub struct MorphismPath<M: Morphism + Clone> {
pub morphisms: Vec< MorphismInstance<M> >,
}
impl<M: Morphism+Clone> MorphismPath<M> {
fn apply_subst(&mut self, σ: &std::collections::HashMap<TypeID, TypeTerm>) {
for m in self.morphisms.iter_mut() {

View file

@ -9,7 +9,7 @@ fn test_heuristic() {
src_type: dict.parse("A").expect("parse"),
dst_type: dict.parse("A").expect("parse")
}.estimated_cost(),
1
0
);
assert_eq!(
@ -17,6 +17,6 @@ fn test_heuristic() {
src_type: dict.parse("<Digit 10> ~ Char ~ Ascii ~ native.UInt8").expect("parse"),
dst_type: dict.parse("<Digit 16> ~ native.UInt8").expect("parse")
}.estimated_cost(),
41
40
);
}

View file

@ -67,6 +67,8 @@ fn morphism_test_setup() -> ( BimapTypeDict, MorphismBase<DummyMorphism> ) {
dst_type: dict.parse_desugared("<Digit Radix> ~ Char").unwrap().sugar(&mut dict)
})
);
/*
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared(" ~ <PosInt Radix BigEndian> ~ <Seq <Digit Radix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict),
@ -85,7 +87,9 @@ fn morphism_test_setup() -> ( BimapTypeDict, MorphismBase<DummyMorphism> ) {
dst_type: dict.parse_desugared(" ~ <PosInt DstRadix LittleEndian> ~ <Seq <Digit DstRadix>~_2^64~machine.UInt64>").unwrap().sugar(&mut dict)
})
);
*/
/*
base.add_morphism(
DummyMorphism(MorphismType{
@ -93,6 +97,7 @@ fn morphism_test_setup() -> ( BimapTypeDict, MorphismBase<DummyMorphism> ) {
dst_type: dict.parse_desugared("_2^64 ~ machine.UInt64").unwrap().sugar(&mut dict)
})
);
*/
base.add_morphism(
DummyMorphism(MorphismType{
src_type: dict.parse_desugared("_2^64 ~ machine.UInt64").unwrap().sugar(&mut dict),
@ -101,66 +106,127 @@ fn morphism_test_setup() -> ( BimapTypeDict, MorphismBase<DummyMorphism> ) {
);
(dict, base)
}
/*
#[test]
fn test_morphism_path1() {
let (mut dict, mut base) = morphism_test_setup();
let path = ShortestPathProblem::new(&base, MorphismType {
src_type: dict.parse_desugared("<Digit 10> ~ Char").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared("<Digit 10> ~ _2^64 ~ machine.UInt64").unwrap().sugar(&mut dict),
}).solve();
#[test]
fn test_morphgraph_id() {
let (mut dict, mut base) = morphism_test_setup();
let morph_graph = MorphismGraph::new(base);
assert_eq!(
path,
Some(
vec![
MorphismInstance::Primitive {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
ψ: TypeTerm::unit(),
morph: 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)
}),
}
]
));
morph_graph.search(MorphismType {
src_type: dict.parse("_2^64 ~ machine.UInt64").expect("parse"),
dst_type: dict.parse("_2^64 ~ machine.UInt64").expect("parse"),
}, &mut dict),
Ok(MorphismInstance::Id {
τ: dict.parse("_2^64 ~ machine.UInt64").expect("parse")
})
);
}
#[test]
fn test_morphism_path2() {
fn test_morphgraph_prim() {
let (mut dict, mut base) = morphism_test_setup();
let path = ShortestPathProblem::new(&base, MorphismType {
src_type: dict.parse_desugared(" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ Char>").unwrap().sugar(&mut dict),
dst_type: dict.parse_desugared(" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ _2^64 ~ machine.UInt64>").unwrap().sugar(&mut dict),
}).solve();
let morph_graph = MorphismGraph::new(base);
assert_eq!(
path,
Some(
vec![
MorphismInstance::MapSeq {
ψ: dict.parse_desugared(" ~ <PosInt 10 BigEndian>").expect("").sugar(&mut dict),
seq_repr: None,
item_morph: Box::new(MorphismInstance::Primitive {
σ: vec![
(dict.get_typeid(&"Radix".into()).unwrap(), TypeTerm::Num(10)),
].into_iter().collect(),
ψ: TypeTerm::unit(),
morph: 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)
}),
morph_graph.search(MorphismType {
src_type: dict.parse("<Digit 10> ~ Char").expect("parse"),
dst_type: dict.parse("<Digit 10> ~ _2^64 ~ machine.UInt64").expect("parse"),
}, &mut dict),
Ok(
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").expect("parse"),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").expect("parse"),
})
}
]
));
})
}
)
);
}
#[test]
fn test_morphgraph_chain() {
let (mut dict, mut base) = morphism_test_setup();
let morph_graph = MorphismGraph::new(base);
assert_eq!(
morph_graph.search(MorphismType {
src_type: dict.parse("<Digit 10> ~ Char").expect("parse"),
dst_type: dict.parse("<Digit 10> ~ _2^64 ~ ~ <PosInt 0 LittleEndian> ~ <Seq <Digit 0>~_2^64~machine.UInt64>").expect("parse"),
}, &mut dict),
Ok(
MorphismInstance::Chain {
path: vec![
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").expect("parse"),
dst_type: dict.parse("<Digit Radix> ~ _2^64 ~ machine.UInt64").expect("parse"),
})
})
},
MorphismInstance::Sub {
ψ: dict.parse("<Digit 10>").expect("parse"),
m: Box::new(
MorphismInstance::Primitive { m: DummyMorphism(MorphismType{
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()
}) }
)
}
]
}
)
);
}
#[test]
fn test_morphgraph_map_seq() {
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 BigEndian> ~ <Seq <Digit 10> ~ Char>").unwrap(),
dst_type: dict.parse(" ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ _2^64 ~ machine.UInt64>").unwrap(),
}, &mut dict),
Ok(
MorphismInstance::Sub {
ψ: dict.parse(" ~ <PosInt 10 BigEndian>").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_path3() {
let (mut dict, mut base) = morphism_test_setup();