Skip to content

Commit ebe7fa9

Browse files
committed
frobenius decomposition: global sources/targets
Connect global sources directly to the sources of the left spider and global targets directly to the targets of the right spider. This changes each node’s spider pair from `0 → 1+m` and `1+n → 0` to `p → 1+m` and `1+n → q`, where `p` and `q` count global source and target occurrences respectively.
1 parent 568df59 commit ebe7fa9

2 files changed

Lines changed: 36 additions & 25 deletions

File tree

src/lax/spider.rs

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ impl<O: Clone + PartialEq, A: Clone> OpenHypergraph<O, A> {
2323
///
2424
/// For every original node, the construction inserts two spiders:
2525
///
26-
/// - `0 -> 1 + m`, where `m` is the number of occurrences as an operation
27-
/// source or global target;
28-
/// - `1 + n -> 0`, where `n` is the number of occurrences as an operation
29-
/// target or global source.
26+
/// - `p -> 1 + m` on the left, where `p` is the number of global source
27+
/// occurrences and `m` is the number of operation-source occurrences;
28+
/// - `1 + n -> q` on the right, where `n` is the number of
29+
/// operation-target occurrences and `q` is the number of global target
30+
/// occurrences.
3031
///
3132
/// The extra leg connects the two spiders. Every other occurrence gets a
3233
/// distinct node, making every node occur exactly once as a source and
@@ -62,18 +63,20 @@ impl<O: Clone + PartialEq, A: Clone> OpenHypergraph<O, A> {
6263
.map(|label| result.new_node(label))
6364
.collect();
6465

65-
let mut splitter_targets: Vec<Vec<NodeId>> =
66+
let mut left_sources = vec![Vec::new(); central.len()];
67+
let mut left_targets: Vec<Vec<NodeId>> =
6668
central.iter().copied().map(|node| vec![node]).collect();
67-
let mut merger_sources: Vec<Vec<NodeId>> =
69+
let mut right_sources: Vec<Vec<NodeId>> =
6870
central.iter().copied().map(|node| vec![node]).collect();
71+
let mut right_targets = vec![Vec::new(); central.len()];
6972

7073
for (operation, adjacency) in hypergraph.edges.into_iter().zip(hypergraph.adjacency) {
7174
let operation_sources = adjacency
7275
.sources
7376
.into_iter()
7477
.map(|node| {
7578
let occurrence = result.new_node(hypergraph.nodes[node.0].clone());
76-
splitter_targets[node.0].push(occurrence);
79+
left_targets[node.0].push(occurrence);
7780
occurrence
7881
})
7982
.collect();
@@ -83,7 +86,7 @@ impl<O: Clone + PartialEq, A: Clone> OpenHypergraph<O, A> {
8386
.into_iter()
8487
.map(|node| {
8588
let occurrence = result.new_node(hypergraph.nodes[node.0].clone());
86-
merger_sources[node.0].push(occurrence);
89+
right_sources[node.0].push(occurrence);
8790
occurrence
8891
})
8992
.collect();
@@ -101,7 +104,7 @@ impl<O: Clone + PartialEq, A: Clone> OpenHypergraph<O, A> {
101104
.into_iter()
102105
.map(|node| {
103106
let occurrence = result.new_node(hypergraph.nodes[node.0].clone());
104-
merger_sources[node.0].push(occurrence);
107+
left_sources[node.0].push(occurrence);
105108
occurrence
106109
})
107110
.collect();
@@ -110,33 +113,36 @@ impl<O: Clone + PartialEq, A: Clone> OpenHypergraph<O, A> {
110113
.into_iter()
111114
.map(|node| {
112115
let occurrence = result.new_node(hypergraph.nodes[node.0].clone());
113-
splitter_targets[node.0].push(occurrence);
116+
right_targets[node.0].push(occurrence);
114117
occurrence
115118
})
116119
.collect();
117120

118-
for (splitter, merger) in splitter_targets.into_iter().zip(merger_sources) {
119-
let splitter_outputs = splitter.len();
121+
for (((left_sources, left_targets), right_sources), right_targets) in left_sources
122+
.into_iter()
123+
.zip(left_targets)
124+
.zip(right_sources)
125+
.zip(right_targets)
126+
{
120127
result.new_edge(
121128
WithSpider::Spider {
122-
sources: 0,
123-
targets: splitter_outputs,
129+
sources: left_sources.len(),
130+
targets: left_targets.len(),
124131
},
125132
Hyperedge {
126-
sources: vec![],
127-
targets: splitter,
133+
sources: left_sources,
134+
targets: left_targets,
128135
},
129136
);
130137

131-
let merger_inputs = merger.len();
132138
result.new_edge(
133139
WithSpider::Spider {
134-
sources: merger_inputs,
135-
targets: 0,
140+
sources: right_sources.len(),
141+
targets: right_targets.len(),
136142
},
137143
Hyperedge {
138-
sources: merger,
139-
targets: vec![],
144+
sources: right_sources,
145+
targets: right_targets,
140146
},
141147
);
142148
}

tests/lax/spider.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,23 @@ fn spider_arities_count_all_occurrences() {
8282
vec![
8383
WithSpider::Operation("op"),
8484
WithSpider::Spider {
85-
sources: 0,
86-
targets: 4,
85+
sources: 2,
86+
targets: 3,
8787
},
8888
WithSpider::Spider {
89-
sources: 4,
90-
targets: 0,
89+
sources: 2,
90+
targets: 1,
9191
},
9292
]
9393
);
9494

9595
assert_eq!(spiderized.sources.len(), 2);
9696
assert_ne!(spiderized.sources[0], spiderized.sources[1]);
97+
98+
let left_spider = &spiderized.hypergraph.adjacency[1];
99+
let right_spider = &spiderized.hypergraph.adjacency[2];
100+
assert_eq!(left_spider.sources, spiderized.sources);
101+
assert_eq!(right_spider.targets, spiderized.targets);
97102
}
98103

99104
#[test]

0 commit comments

Comments
 (0)