1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::internal::*;
use crate::model::{Fact, Graph, OutletId};
use std::collections::HashMap;
use std::convert::*;
use std::fmt;
pub trait Translate<TI1, O1, TI2, O2>: fmt::Debug
where
TI1: Fact + Hash + Clone + 'static,
TI2: Fact + Hash + Clone + 'static,
O1: fmt::Display + fmt::Debug + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static + Hash,
O2: fmt::Display + fmt::Debug + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static + Hash,
{
fn translate_node(
&self,
source: &Graph<TI1, O1>,
node: &Node<TI1, O1>,
target: &mut Graph<TI2, O2>,
mapping: &HashMap<OutletId, OutletId>,
) -> TractResult<TVec<OutletId>>;
fn translate_model(&self, source: &Graph<TI1, O1>) -> TractResult<Graph<TI2, O2>> {
Ok(self.translate_model_with_mappings(source)?.0)
}
fn translate_model_with_mappings(
&self,
source: &Graph<TI1, O1>,
) -> TractResult<(Graph<TI2, O2>, HashMap<OutletId, OutletId>)> {
let mut target = Graph::default();
let mut mapping = HashMap::new();
for old_id in source.eval_order()? {
let node = source.node(old_id);
trace!("Translating {} {:?}", node, self);
let outlets = self
.translate_node(&source, node, &mut target, &mapping)
.with_context(|| format!("Translating node {} {:?}", node, self))?;
for (ix, outlet) in outlets.into_iter().enumerate() {
mapping.insert(OutletId::new(node.id, ix), outlet);
if let Some(label) = source.outlet_label(OutletId::new(node.id, ix)) {
target.set_outlet_label(outlet, label.to_string())?;
}
}
}
for i in source.input_outlets()? {
if !mapping.contains_key(i) {
let node = source.node(i.node);
trace!("Translate useless source {}", node);
let outlets = self
.translate_node(&source, node, &mut target, &mapping)
.with_context(|| format!("Translating input {} {:?}", node, self))?;
mapping.insert(*i, outlets[0]);
}
}
target.inputs = source.input_outlets()?.iter().map(|i| mapping[&i]).collect();
target.outputs = source.output_outlets()?.iter().map(|o| mapping[&o]).collect();
target.properties = source.properties.clone();
Ok((target, mapping))
}
}
#[derive(Debug)]
pub struct IntoTranslator;
impl<TI1, O1, TI2, O2, EO, ETI> Translate<TI1, O1, TI2, O2> for IntoTranslator
where
TractError: From<EO> + From<ETI>,
TI1: Fact + Hash + Clone + 'static,
TI2: Fact + Hash + for<'a> TryFrom<&'a TI1, Error = EO> + Clone + 'static,
O1: fmt::Display + fmt::Debug + Clone + AsRef<dyn Op> + AsMut<dyn Op> + Clone + 'static + Hash,
O2: fmt::Display
+ for<'a> TryFrom<&'a O1, Error = ETI>
+ fmt::Debug
+ AsRef<dyn Op>
+ AsMut<dyn Op>
+ Clone
+ Hash
+ 'static,
Graph<TI2, O2>: SpecialOps<TI2, O2>,
{
fn translate_node(
&self,
source: &Graph<TI1, O1>,
node: &Node<TI1, O1>,
target: &mut Graph<TI2, O2>,
mapping: &HashMap<OutletId, OutletId>,
) -> TractResult<TVec<OutletId>> {
let node_is_input =
(0..node.outputs.len()).all(|o| source.inputs.contains(&(node.id, o).into()));
if node_is_input {
(0..node.outputs.len())
.map(|i| {
target.add_source(
if node.outputs.len() > 1 {
format!("{}-{}", node.name, i)
} else {
node.name.to_string()
},
TI2::try_from(&node.outputs[i].fact)?,
)
})
.collect()
} else {
let new_op = O2::try_from(&node.op)?;
let facts = node
.outputs
.iter()
.map(|of| Ok(TI2::try_from(&of.fact)?))
.collect::<TractResult<TVec<_>>>()?;
let new_id = target.add_node(node.name.clone(), new_op, facts)?;
for (ix, o) in node.inputs.iter().enumerate() {
target.add_edge(mapping[o], InletId::new(new_id, ix))?
}
Ok(node.outputs.iter().enumerate().map(|(ix, _)| OutletId::new(new_id, ix)).collect())
}
}
}