use crate::graph::Network;
use crate::op::Op;
use crate::{Tape, Tensor, conv2d};
use super::super::pattern::Pattern;
use super::super::view::View;
use super::match_at;
fn conv_network() -> Network<f64> {
let tape = Tape::new();
let input = tape.leaf(Tensor::new(
[1, 2, 4, 4],
(0..32).map(|v| v as f64 / 8.0 - 2.0).collect::<Vec<_>>(),
));
let weights = tape.leaf(Tensor::new(
[2, 2, 2, 2],
(0..16).map(|v| v as f64 / 4.0 - 2.0).collect::<Vec<_>>(),
));
let bias = tape.leaf(Tensor::new([2], [0.25, -0.5]));
let _output = conv2d(input, weights, bias, 2, 1);
tape.into_network()
}
fn matmul_index(network: &Network<f64>) -> usize {
let ops = &network.structure().ops;
(0..ops.len())
.find(|&index| matches!(ops.get(index), Some(Op::MatMul(_))))
.expect("the conv records one matmul")
}
#[test]
fn the_conv_chain_matches_with_its_geometry() {
let network = conv_network();
let structure = network.structure();
let length = structure.ops.len();
let wanted = vec![true; length];
let readable = vec![false; length];
let view = View::new(structure, &wanted, &readable);
let matmul = matmul_index(&network);
let candidate = match_at(matmul, &view).expect("the canonical chain matches");
let group = match candidate.pattern {
Pattern::WindowProduct(group) => group,
_ => panic!("the conv chain matches as a window product"),
};
assert_eq!(structure.shapes[group.source].axes(), [1, 2, 4, 4]);
assert_eq!(structure.shapes[group.kernel].axes(), [8, 2]);
assert_eq!(group.kernel_height, 2);
assert_eq!(group.kernel_width, 2);
assert_eq!(group.stride, 2);
assert_eq!(group.padding, 1);
assert_eq!(candidate.interiors.len(), 6);
assert!(candidate.named.is_empty());
}
#[test]
fn a_kept_interior_bars_the_match() {
let network = conv_network();
let structure = network.structure();
let length = structure.ops.len();
let matmul = matmul_index(&network);
let patches = structure
.operands
.get(matmul)
.expect("plan columns are fixed")
.as_slice()[0]
.index();
let wanted = vec![true; length];
let mut readable = vec![false; length];
readable[patches] = true;
let view = View::new(structure, &wanted, &readable);
assert!(match_at(matmul, &view).is_none());
}