further work on new graph search
now passes simple tests for id, specialization and chains
This commit is contained in:
parent
081004ffab
commit
0126a62e76
7 changed files with 372 additions and 224 deletions
|
@ -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;
|
||||
|
|
134
src/morphism.rs
134
src/morphism.rs
|
@ -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(γ);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue