Skip to content

Commit

Permalink
Various tests, and various failures
Browse files Browse the repository at this point in the history
  • Loading branch information
acl-cqc committed Jun 27, 2023
1 parent 7f0df3b commit 04a824c
Showing 1 changed file with 127 additions and 1 deletion.
128 changes: 127 additions & 1 deletion src/hugr/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,15 @@ impl<'a> ValidationContext<'a> {

let postorder = DfsPostOrder::new(&region, entry_node);
let nodes_visited = postorder.iter(&region).filter(|n| *n != parent).count();
let _module_op_count = self
.hugr
.children(parent)
.filter(|n| OpTag::ModuleOp.contains(self.hugr.get_optype(*n).tag()))
.count();
// XXX TODO FIXME we should take _module_op_count off the child_count below,
// because e.g. Const nodes should not be reached by the DfsPostOrder in a forwards
// traversal. (Currently this would break tests because the traversal goes both forwards
// AND backwards).
if nodes_visited != self.hugr.hierarchy.child_count(parent.index) {
return Err(ValidationError::NotABoundedDag {
node: parent,
Expand Down Expand Up @@ -731,7 +740,7 @@ mod test {
use super::*;
use crate::builder::{BuildError, ModuleBuilder};
use crate::builder::{Container, Dataflow, DataflowSubContainer, HugrBuilder};
use crate::hugr::HugrMut;
use crate::hugr::{HugrError, HugrMut};
use crate::ops::dataflow::IOTrait;
use crate::ops::{self, ConstValue, LeafOp, OpType};
use crate::types::{ClassicType, LinearType, Signature};
Expand Down Expand Up @@ -1067,6 +1076,123 @@ mod test {
);
}

#[test]
fn test_ext_edge() -> Result<(), HugrError> {
let mut h = Hugr::new(ops::DFG {
signature: Signature::new_df(type_row![B, B], type_row![B]),
});
let input = h.add_op_with_parent(h.root(), ops::Input::new(type_row![B, B]))?;
let output = h.add_op_with_parent(h.root(), ops::Output::new(type_row![B]))?;
// Nested DFG B -> B
let sub_dfg = h.add_op_with_parent(
h.root(),
ops::DFG {
signature: Signature::new_linear(type_row![B]),
},
)?;
// this Xor has its 2nd input unconnected
let sub_op = {
let sub_input = h.add_op_with_parent(sub_dfg, ops::Input::new(type_row![B]))?;
let sub_output = h.add_op_with_parent(sub_dfg, ops::Output::new(type_row![B]))?;
let sub_op = h.add_op_with_parent(sub_dfg, LeafOp::Xor)?;
h.connect(sub_input, 0, sub_op, 0)?;
h.connect(sub_op, 0, sub_output, 0)?;
sub_op
};

h.connect(input, 0, sub_dfg, 0)?;
h.connect(sub_dfg, 0, output, 0)?;

assert_matches!(h.validate(), Err(ValidationError::UnconnectedPort { .. }));

h.connect(input, 1, sub_op, 1)?;
assert_matches!(
h.validate(),
Err(ValidationError::InterGraphEdgeError(
InterGraphEdgeError::MissingOrderEdge { .. }
))
);
//Order edge. There must be an easier way to do this?
h.connect(
input,
h.get_optype(input)
.other_port_index(Direction::Outgoing)
.unwrap()
.index(),
sub_dfg,
h.get_optype(sub_dfg)
.other_port_index(Direction::Incoming)
.unwrap()
.index(),
)?;
h.validate().unwrap();
Ok(())
}

#[test]
fn test_local_const() -> Result<(), HugrError> {
let mut h = Hugr::new(ops::DFG {
signature: Signature::new_df(type_row![B], type_row![B]),
});
let input = h.add_op_with_parent(h.root(), ops::Input::new(type_row![B]))?;
let output = h.add_op_with_parent(h.root(), ops::Output::new(type_row![B]))?;
let xor = h.add_op_with_parent(h.root(), LeafOp::Xor)?;
h.connect(input, 0, xor, 0)?;
h.connect(xor, 0, output, 0)?;
assert_eq!(
h.validate(),
Err(ValidationError::UnconnectedPort {
node: xor,
port: Port::new_incoming(1),
port_kind: EdgeKind::Value(B)
})
);
// Second input of Xor from a constant
let cst =
h.add_op_with_parent(h.root(), ops::Const(ConstValue::Int { width: 1, value: 1 }))?;
let lcst = h.add_op_with_parent(
h.root(),
ops::LoadConstant {
datatype: ClassicType::Int(1),
},
)?;
h.connect(cst, 0, lcst, 0)?;
h.connect(lcst, 0, xor, 1)?;
// XXX TODO FIXME This should fail, but succeeds:
h.validate().unwrap();
// Now include the LoadConstant node in the causal cone
h.connect(
input,
h.get_optype(input)
.other_port_index(Direction::Outgoing)
.unwrap()
.index(),
lcst,
h.get_optype(lcst)
.other_port_index(Direction::Incoming)
.unwrap()
.index(),
)?;
h.validate().unwrap();
Ok(())
}

#[test]
fn test_cyclic() -> Result<(), HugrError> {
let mut h = Hugr::new(ops::DFG {
signature: Signature::new_df(type_row![Q], type_row![Q]),
});
let input = h.add_op_with_parent(h.root(), ops::Input::new(type_row![Q]))?;
let output = h.add_op_with_parent(h.root(), ops::Output::new(type_row![Q]))?;
let cx = h.add_op_with_parent(h.root(), LeafOp::CX)?;
h.connect(input, 0, cx, 0)?;
h.connect(cx, 0, output, 0)?;
h.connect(cx, 1, cx, 1)?;
// TODO FIXME We should get an error here, but this passes ATM :-(
h.validate().unwrap();
Ok(())
}

#[test]
/// A wire with no resource requirements is wired into a node which has
/// [A,B] resources required on its inputs and outputs. This could be fixed
Expand Down

0 comments on commit 04a824c

Please sign in to comment.