pub struct Graph {
pub nodes: Arena<NodeId, Node>,
pub values: Arena<ValueId, Value>,
pub inputs: Vec<ValueId>,
pub outputs: Vec<ValueId>,
pub initializers: HashMap<ValueId, WeightRef>,
pub symbol_constraints: HashMap<SymbolId, SymbolConstraints>,
pub opset_imports: HashMap<String, u64>,
pub subgraphs: HashMap<(NodeId, String), Graph>,
/* private fields */
}Expand description
A computation graph in SSA form.
Nodes and values live in Arenas keyed by NodeId / ValueId. The
mutation API keeps producer/consumer edges consistent, so optimization
passes can rewrite the graph and then Graph::validate it.
Fields§
§nodes: Arena<NodeId, Node>§values: Arena<ValueId, Value>§inputs: Vec<ValueId>Graph inputs, in order. These have no producer.
outputs: Vec<ValueId>Graph outputs, in order.
initializers: HashMap<ValueId, WeightRef>Constant initializer weights, keyed by the value they populate.
symbol_constraints: HashMap<SymbolId, SymbolConstraints>Constraints on symbolic dimensions.
opset_imports: HashMap<String, u64>Imported opsets: domain → version.
subgraphs: HashMap<(NodeId, String), Graph>Subgraph bodies for control-flow ops, keyed by (node, attr_name).
Implementations§
Source§impl Graph
impl Graph
Sourcepub fn new() -> Self
pub fn new() -> Self
An empty graph.
Examples found in repository?
6fn hub_graph(node_count: usize) -> (Graph, Vec<NodeId>) {
7 let mut graph = Graph::new();
8 let hub = graph.create_value(DataType::Float32, static_shape([1]));
9 graph.add_input(hub);
10 let mut nodes = Vec::with_capacity(node_count);
11 for _ in 0..node_count {
12 let output = graph.create_value(DataType::Float32, static_shape([1]));
13 nodes.push(graph.insert_node(Node::new(
14 NodeId(0),
15 "Identity",
16 vec![Some(hub)],
17 vec![output],
18 )));
19 }
20 (graph, nodes)
21}Sourcepub fn node(&self, id: NodeId) -> &Node
pub fn node(&self, id: NodeId) -> &Node
Borrow a node. Panics if id is not live; use
Graph::try_node for a checked lookup.
Sourcepub fn node_mut(&mut self, id: NodeId) -> &mut Node
pub fn node_mut(&mut self, id: NodeId) -> &mut Node
Mutably borrow a node. Panics if id is not live.
Sourcepub fn value(&self, id: ValueId) -> &Value
pub fn value(&self, id: ValueId) -> &Value
Borrow a value. Panics if id is not live; use
Graph::try_value for a checked lookup.
Sourcepub fn value_mut(&mut self, id: ValueId) -> &mut Value
pub fn value_mut(&mut self, id: ValueId) -> &mut Value
Mutably borrow a value. Panics if id is not live.
Sourcepub fn uses(&self, value: ValueId) -> Vec<(NodeId, u32)>
pub fn uses(&self, value: ValueId) -> Vec<(NodeId, u32)>
Consuming input slots sorted by (NodeId, input_index).
Sourcepub fn consumers(&self, value: ValueId) -> Vec<NodeId>
pub fn consumers(&self, value: ValueId) -> Vec<NodeId>
Distinct consumer nodes sorted by ascending NodeId.
Sourcepub fn has_uses(&self, value: ValueId) -> bool
pub fn has_uses(&self, value: ValueId) -> bool
Whether at least one node input slot consumes value.
Sourcepub fn num_values(&self) -> usize
pub fn num_values(&self) -> usize
Number of live values.
Sourcepub fn value_type_is_known(&self, id: ValueId) -> bool
pub fn value_type_is_known(&self, id: ValueId) -> bool
Whether a value’s element type came from explicit source type information.
Sourcepub fn value_shape_is_known(&self, id: ValueId) -> bool
pub fn value_shape_is_known(&self, id: ValueId) -> bool
Whether a value’s rank and dimensions came from explicit source shape information.
Sourcepub fn mark_value_type_unknown(&mut self, id: ValueId)
pub fn mark_value_type_unknown(&mut self, id: ValueId)
Mark a value’s placeholder element type as unknown.
Sourcepub fn mark_value_shape_unknown(&mut self, id: ValueId)
pub fn mark_value_shape_unknown(&mut self, id: ValueId)
Mark a value’s placeholder shape as unknown.
Sourcepub fn create_symbol(&mut self, name: Option<String>) -> SymbolId
pub fn create_symbol(&mut self, name: Option<String>) -> SymbolId
Allocate a fresh symbolic dimension with an optional name (no dedup).
Sourcepub fn intern_symbol(&mut self, name: &str) -> SymbolId
pub fn intern_symbol(&mut self, name: &str) -> SymbolId
Intern a symbolic dimension by protobuf dim-param name: repeated names
resolve to the same SymbolId (graph-construction invariant §3.5.4).
Sourcepub fn create_value(&mut self, dtype: DataType, shape: Shape) -> ValueId
pub fn create_value(&mut self, dtype: DataType, shape: Shape) -> ValueId
Create a new anonymous value with a contiguous default layout.
Examples found in repository?
6fn hub_graph(node_count: usize) -> (Graph, Vec<NodeId>) {
7 let mut graph = Graph::new();
8 let hub = graph.create_value(DataType::Float32, static_shape([1]));
9 graph.add_input(hub);
10 let mut nodes = Vec::with_capacity(node_count);
11 for _ in 0..node_count {
12 let output = graph.create_value(DataType::Float32, static_shape([1]));
13 nodes.push(graph.insert_node(Node::new(
14 NodeId(0),
15 "Identity",
16 vec![Some(hub)],
17 vec![output],
18 )));
19 }
20 (graph, nodes)
21}Sourcepub fn create_named_value(
&mut self,
name: impl Into<String>,
dtype: DataType,
shape: Shape,
) -> ValueId
pub fn create_named_value( &mut self, name: impl Into<String>, dtype: DataType, shape: Shape, ) -> ValueId
Create a new named value.
Sourcepub fn add_input(&mut self, value: ValueId)
pub fn add_input(&mut self, value: ValueId)
Register value as a graph input.
Examples found in repository?
6fn hub_graph(node_count: usize) -> (Graph, Vec<NodeId>) {
7 let mut graph = Graph::new();
8 let hub = graph.create_value(DataType::Float32, static_shape([1]));
9 graph.add_input(hub);
10 let mut nodes = Vec::with_capacity(node_count);
11 for _ in 0..node_count {
12 let output = graph.create_value(DataType::Float32, static_shape([1]));
13 nodes.push(graph.insert_node(Node::new(
14 NodeId(0),
15 "Identity",
16 vec![Some(hub)],
17 vec![output],
18 )));
19 }
20 (graph, nodes)
21}Sourcepub fn add_output(&mut self, value: ValueId)
pub fn add_output(&mut self, value: ValueId)
Register value as a graph output.
Sourcepub fn insert_output(&mut self, index: usize, value: ValueId)
pub fn insert_output(&mut self, index: usize, value: ValueId)
Insert value into the ordered graph outputs.
Sourcepub fn remove_input(&mut self, index: usize) -> ValueId
pub fn remove_input(&mut self, index: usize) -> ValueId
Remove one ordered graph input.
Sourcepub fn remove_output(&mut self, index: usize) -> ValueId
pub fn remove_output(&mut self, index: usize) -> ValueId
Remove one ordered graph output.
Sourcepub fn set_inputs(&mut self, inputs: Vec<ValueId>)
pub fn set_inputs(&mut self, inputs: Vec<ValueId>)
Replace the complete ordered graph-input list.
Sourcepub fn set_outputs(&mut self, outputs: Vec<ValueId>)
pub fn set_outputs(&mut self, outputs: Vec<ValueId>)
Replace the complete ordered graph-output list.
Sourcepub fn set_initializer(&mut self, value: ValueId, weight: WeightRef)
pub fn set_initializer(&mut self, value: ValueId, weight: WeightRef)
Attach initializer weights to value.
Sourcepub fn predecessors(&self, node: NodeId) -> Vec<NodeId>
pub fn predecessors(&self, node: NodeId) -> Vec<NodeId>
Direct predecessors: nodes that produce this node’s inputs.
Sourcepub fn successors(&self, node: NodeId) -> Vec<NodeId>
pub fn successors(&self, node: NodeId) -> Vec<NodeId>
Direct successors: nodes that consume this node’s outputs.
Sourcepub fn nodes_between(
&self,
inputs: &[ValueId],
outputs: &[ValueId],
) -> Vec<NodeId>
pub fn nodes_between( &self, inputs: &[ValueId], outputs: &[ValueId], ) -> Vec<NodeId>
All nodes that lie on a path between inputs and outputs.
Walks backwards from outputs via producer edges, stopping at any value
in inputs. Used to extract subgraphs for EP capability claims (§3.4).
Sourcepub fn topological_order(&self) -> Result<Vec<NodeId>, GraphError>
pub fn topological_order(&self) -> Result<Vec<NodeId>, GraphError>
Topological order of nodes via Kahn’s algorithm.
Ties are broken by ascending NodeId for deterministic output.
Returns GraphError::CycleDetected if the graph has a cycle.
Sourcepub fn insert_node(&mut self, node: Node) -> NodeId
pub fn insert_node(&mut self, node: Node) -> NodeId
Insert a node, wiring its producer/consumer edges. The node’s id
field is overwritten with the freshly allocated NodeId.
Examples found in repository?
6fn hub_graph(node_count: usize) -> (Graph, Vec<NodeId>) {
7 let mut graph = Graph::new();
8 let hub = graph.create_value(DataType::Float32, static_shape([1]));
9 graph.add_input(hub);
10 let mut nodes = Vec::with_capacity(node_count);
11 for _ in 0..node_count {
12 let output = graph.create_value(DataType::Float32, static_shape([1]));
13 nodes.push(graph.insert_node(Node::new(
14 NodeId(0),
15 "Identity",
16 vec![Some(hub)],
17 vec![output],
18 )));
19 }
20 (graph, nodes)
21}Sourcepub fn remove_node(&mut self, id: NodeId)
pub fn remove_node(&mut self, id: NodeId)
Remove a node, disconnecting its edges. Output values left with no consumers (and not graph I/O or initializers) are deleted.
Examples found in repository?
23fn sequential_remove(node_count: usize) -> Duration {
24 let (mut graph, nodes) = hub_graph(node_count);
25 let start = Instant::now();
26 for node in nodes {
27 graph.remove_node(node);
28 }
29 let elapsed = start.elapsed();
30 black_box(graph);
31 elapsed
32}
33
34fn single_hub_disconnect(node_count: usize, repeats: usize) -> Duration {
35 let (base, nodes) = hub_graph(node_count);
36 let target = nodes[0];
37 let mut elapsed = Duration::ZERO;
38 for _ in 0..repeats {
39 let mut graph = base.clone();
40 let start = Instant::now();
41 graph.remove_node(target);
42 elapsed += start.elapsed();
43 black_box(graph);
44 }
45 elapsed / repeats as u32
46}Sourcepub fn remove_nodes(&mut self, ids: &[NodeId])
pub fn remove_nodes(&mut self, ids: &[NodeId])
Remove nodes in slice order.
Each input edge is removed directly by (NodeId, input_index), so this
remains linear in the number of removed edges even for a high-fanout
shared value.
Sourcepub fn replace_node_groups(
&mut self,
groups: Vec<(Vec<NodeId>, Node)>,
graph_outputs: &HashSet<ValueId>,
) -> Vec<NodeId>
pub fn replace_node_groups( &mut self, groups: Vec<(Vec<NodeId>, Node)>, graph_outputs: &HashSet<ValueId>, ) -> Vec<NodeId>
Replace disjoint node groups with one node each while updating shared producer/consumer metadata in a batch.
Each group is semantically equivalent to calling Graph::remove_node
for its IDs in slice order and then Graph::insert_node for the
replacement. In particular, replacement IDs and orphan-value collection
match that sequential operation. graph_outputs is retained for API
compatibility and checked against the per-value membership invariant in
debug builds.
Sourcepub fn replace_node(&mut self, old: NodeId, new: Node) -> NodeId
pub fn replace_node(&mut self, old: NodeId, new: Node) -> NodeId
Replace node old in place with new, preserving the NodeId.
The old node’s edges are disconnected and the new node’s edges are
connected. Values that were outputs of old but not of new are left
in place (producer cleared); the caller may prune them.
Sourcepub fn insert_on_edge(&mut self, value: ValueId, new_node: Node) -> NodeId
pub fn insert_on_edge(&mut self, value: ValueId, new_node: Node) -> NodeId
Splice new_node onto the edge feeding out of value:
producer(value) → [new_node] → consumers(value).
new_node’s single input becomes value, and it produces a fresh value
that replaces value in all of value’s original consumers.
Sourcepub fn replace_input(
&mut self,
node: NodeId,
input_index: usize,
new_value: Option<ValueId>,
) -> Option<ValueId>
pub fn replace_input( &mut self, node: NodeId, input_index: usize, new_value: Option<ValueId>, ) -> Option<ValueId>
Replace one node input and update both values’ consumer sets.
This is constant-time on average for edge metadata. None disconnects
the slot and is used by node removal.
Sourcepub fn replace_all_uses(&mut self, old_value: ValueId, new_value: ValueId)
pub fn replace_all_uses(&mut self, old_value: ValueId, new_value: ValueId)
Replace every use of old_value with new_value in consumer nodes and
in the graph output list, moving consumer edges accordingly.