---
title: "ClikaRT::graph::ModelGraph"
sidebar_label: "ModelGraph"
description: "An executable model graph. Move-only."
---

<!-- Generated by tools/doxygen2mdx from Doxygen XML. Do not edit. -->

<span class="api-kind api-kind--class">class</span>

**Header:** `ClikaRT/graph/model_graph.h`

An executable model graph. Move-only.

## Member functions

### ModelGraph(ModelGraph) {#ModelGraph}

<div class="api-signature">

**`ModelGraph`**(`ModelGraph&&`) `noexcept`

</div>

Move-only: transfers the graph. Inside one of the graph's transforms the move leaves both graphs as they were ([`optimize`](./ModelGraph.md#optimize)).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 141

</div>

### operator=(ModelGraph) {#operator-assign}

<div class="api-signature">

[`ModelGraph`](./ModelGraph.md)`&` **`operator=`**([`ModelGraph`](./ModelGraph.md)`&&`) `noexcept`

</div>

Move-assign: transfers the graph, with the same exception.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 143

</div>

### ModelGraph(ModelGraph) {#ModelGraph-2}

<div class="api-signature">

**`ModelGraph`**(`const ModelGraph&`) `=delete`

</div>

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 144

</div>

### operator=(ModelGraph) {#operator-assign-2}

<div class="api-signature">

[`ModelGraph`](./ModelGraph.md)`&` **`operator=`**(`const` [`ModelGraph`](./ModelGraph.md)`&`) `=delete`

</div>

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 145

</div>

### \~ModelGraph() {#ModelGraph-3}

<div class="api-signature">

**`~ModelGraph`**()

</div>

Releases the graph.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 147

</div>

### empty() {#empty}

<div class="api-signature">

`bool` **`empty`**() `const noexcept`

</div>

True for a graph that holds none: default-constructed, moved from, or consumed by a merge, a split or an extract (every part of [`graph::merge`](./index.md#merge), the `second` of [`merge`](./ModelGraph.md#merge), and the graph [`graph::split`](./index.md#split) or [`graph::extract`](./index.md#extract) is given).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 153

</div>

### input\_names() {#input_names}

<div class="api-signature">

`std::vector<std::string>` **`input_names`**() `const`

</div>

Runtime input names, in the model's declaration order, the order the positional [`run`](./ModelGraph.md#run) binds. Weights are not inputs; they ride the graph.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 158

</div>

### output\_names() {#output_names}

<div class="api-signature">

`std::vector<std::string>` **`output_names`**() `const`

</div>

Output names, declaration order, the order every [`run`](./ModelGraph.md#run) returns.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 160

</div>

### inputs() {#inputs}

<div class="api-signature">

`std::vector<`[`spec::TensorSpec`](../spec/TensorSpec.md)`>` **`inputs`**() `const`

</div>

Input / output slots as (name, dtype, dims) specs, same order as [`input_names()`](./ModelGraph.md#input_names) / [`output_names()`](./ModelGraph.md#output_names). A dimension the graph left dynamic reads as [`spec::TensorSpec::kDynamicDim`](../spec/TensorSpec.md#kDynamicDim) (-1).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 165

</div>

### outputs() {#outputs}

<div class="api-signature">

`std::vector<`[`spec::TensorSpec`](../spec/TensorSpec.md)`>` **`outputs`**() `const`

</div>

The produced edges as specs, the output twin of [`inputs()`](./ModelGraph.md#inputs).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 167

</div>

### run(vector\<Tensor\>) {#run}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`run`**(`std::vector<`[`Tensor`](../Tensor.md)`>` `inputs`) `const`

</div>

Run with positional inputs (one per [`input_names()`](./ModelGraph.md#input_names) entry, that order). Returns the outputs in [`output_names()`](./ModelGraph.md#output_names) order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 185

</div>

### run(NamedTensors) {#run-2}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`run`**(`const` [`NamedTensors`](../NamedTensors.md)`&` `inputs`) `const`

</div>

Run with positional inputs (one per [`input_names()`](./ModelGraph.md#input_names) entry, that order). Returns the outputs in [`output_names()`](./ModelGraph.md#output_names) order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 192

</div>

### run(vector\<Tensor\>, vector\<Tensor\>) {#run-3}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`run`**(`std::vector<`[`Tensor`](../Tensor.md)`>` `inputs`, `std::vector<`[`Tensor`](../Tensor.md)`>` `bound_outputs`) `const`

</div>

Run with positional inputs (one per [`input_names()`](./ModelGraph.md#input_names) entry, that order). Returns the outputs in [`output_names()`](./ModelGraph.md#output_names) order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 202

</div>

### run(NamedTensors, NamedTensors) {#run-4}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`run`**(`const` [`NamedTensors`](../NamedTensors.md)`&` `inputs`, `const` [`NamedTensors`](../NamedTensors.md)`&` `bound_outputs`) `const`

</div>

Run with positional inputs (one per [`input_names()`](./ModelGraph.md#input_names) entry, that order). Returns the outputs in [`output_names()`](./ModelGraph.md#output_names) order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 213

</div>

### attach\_kv\_cache(nn::KVCacheConfig) {#attach_kv_cache}

<div class="api-signature">

`void` **`attach_kv_cache`**(`const` [`nn::KVCacheConfig`](../nn/KVCacheConfig.md)`&` `config`)

</div>

Build ONE [`nn::KVCache`](../nn/KVCache.md) on the graph's device from [`kv_cache_info()`](./ModelGraph.md#kv_cache_info) and bind it to every self-attention layer. Fields of `config` left at 0 are taken from the graph: `num_layers` (the self-attention layer count), `num_kv_heads` and `head_dim` (each layer's own values fill its row, so a stack with mixed geometry binds per layer); a layer's sliding window becomes its row's `window`; `kv_dtype` is taken from the graph's KV planes (the config's value is not consulted). `mode`, `paged`, `max_seqs`, `max_tokens_per_seq` and the quantization fields come from `config` as given. The attentions write the cache planes in place, so each continuous row without a window is preallocated at `max_tokens_per_seq` and its planes never move; a windowed row is a fixed ring of its window, and a paged row takes blocks from the pool. After this call the past inputs leave [`input_names()`](./ModelGraph.md#input_names); the present outputs stay in [`output_names()`](./ModelGraph.md#output_names) and `run(inputs, step)` returns each layer's cache plane at its present position, no copy. Every self-attention layer reports [`KVCacheLayerInfo::bound_to_cache`](./KVCacheLayerInfo.md#bound_to_cache), and the graph runs through [`run`](./ModelGraph.md#run)`(`[`inputs`](./ModelGraph.md#inputs)`, const `[`nn::KVCache::StepIndices`](../nn/KVCache.StepIndices.md)`&)`.

The present K/V of a bound layer ARE the cache planes: read them through [`kv_cache()`](./ModelGraph.md#kv_cache)`->keys(l)` / `values(l)` (a continuous cache's `[max_seqs, kv_heads, max_tokens_per_seq, head_dim]` plane; a paged cache's block pool, addressed through `paged_block_table()`). A graph with an interior consumer of a present output (a graph node reading it) refuses to attach (`Unsupported`): the in-place append needs the plane bound at the output port.

Refuses `InvalidArgument` on a graph with no KV layers, one already attached, or a config the cache cannot build (the cache's own message); `Unsupported` on a graph with a cross-attention layer; `FAILED_PRECONDITION` on a graph that is not finalized, while a run is in flight, while [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize) or an edit runs on it, and inside one of its transforms ("Transforms you write"). One cache, one graph run at a time: the caller serializes [`run`](./ModelGraph.md#run) calls on the graph (the cache's `prepare_step` already requires one driving thread).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 255

</div>

### attach\_kv\_cache(shared\_ptr\<nn::KVCache\>) {#attach_kv_cache-2}

<div class="api-signature">

`void` **`attach_kv_cache`**(`std::shared_ptr<`[`nn::KVCache`](../nn/KVCache.md)`>` `cache`)

</div>

Build ONE [`nn::KVCache`](../nn/KVCache.md) on the graph's device from [`kv_cache_info()`](./ModelGraph.md#kv_cache_info) and bind it to every self-attention layer. Fields of `config` left at 0 are taken from the graph: `num_layers` (the self-attention layer count), `num_kv_heads` and `head_dim` (each layer's own values fill its row, so a stack with mixed geometry binds per layer); a layer's sliding window becomes its row's `window`; `kv_dtype` is taken from the graph's KV planes (the config's value is not consulted). `mode`, `paged`, `max_seqs`, `max_tokens_per_seq` and the quantization fields come from `config` as given. The attentions write the cache planes in place, so each continuous row without a window is preallocated at `max_tokens_per_seq` and its planes never move; a windowed row is a fixed ring of its window, and a paged row takes blocks from the pool. After this call the past inputs leave [`input_names()`](./ModelGraph.md#input_names); the present outputs stay in [`output_names()`](./ModelGraph.md#output_names) and `run(inputs, step)` returns each layer's cache plane at its present position, no copy. Every self-attention layer reports [`KVCacheLayerInfo::bound_to_cache`](./KVCacheLayerInfo.md#bound_to_cache), and the graph runs through [`run`](./ModelGraph.md#run)`(`[`inputs`](./ModelGraph.md#inputs)`, const `[`nn::KVCache::StepIndices`](../nn/KVCache.StepIndices.md)`&)`.

The present K/V of a bound layer ARE the cache planes: read them through [`kv_cache()`](./ModelGraph.md#kv_cache)`->keys(l)` / `values(l)` (a continuous cache's `[max_seqs, kv_heads, max_tokens_per_seq, head_dim]` plane; a paged cache's block pool, addressed through `paged_block_table()`). A graph with an interior consumer of a present output (a graph node reading it) refuses to attach (`Unsupported`): the in-place append needs the plane bound at the output port.

Refuses `InvalidArgument` on a graph with no KV layers, one already attached, or a config the cache cannot build (the cache's own message); `Unsupported` on a graph with a cross-attention layer; `FAILED_PRECONDITION` on a graph that is not finalized, while a run is in flight, while [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize) or an edit runs on it, and inside one of its transforms ("Transforms you write"). One cache, one graph run at a time: the caller serializes [`run`](./ModelGraph.md#run) calls on the graph (the cache's `prepare_step` already requires one driving thread).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 274

</div>

### kv\_cache() {#kv_cache}

<div class="api-signature">

`std::shared_ptr<`[`nn::KVCache`](../nn/KVCache.md)`>` **`kv_cache`**() `const`

</div>

The attached cache; null when none is attached. Owned or injected, it is the one [`nn::KVCache`](../nn/KVCache.md) the serving loop drives.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 280

</div>

### run(vector\<Tensor\>, nn::KVCache::StepIndices) {#run-5}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`run`**(`std::vector<`[`Tensor`](../Tensor.md)`>` `inputs`, `const` [`nn::KVCache::StepIndices`](../nn/KVCache.StepIndices.md)`&` `step`) `const`

</div>

Run with positional inputs (one per [`input_names()`](./ModelGraph.md#input_names) entry, that order). Returns the outputs in [`output_names()`](./ModelGraph.md#output_names) order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 294

</div>

### run(NamedTensors, nn::KVCache::StepIndices) {#run-6}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`run`**(`const` [`NamedTensors`](../NamedTensors.md)`&` `inputs`, `const` [`nn::KVCache::StepIndices`](../nn/KVCache.StepIndices.md)`&` `step`) `const`

</div>

Run with positional inputs (one per [`input_names()`](./ModelGraph.md#input_names) entry, that order). Returns the outputs in [`output_names()`](./ModelGraph.md#output_names) order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 301

</div>

### kv\_cache\_info() {#kv_cache_info}

<div class="api-signature">

`std::vector<`[`KVCacheLayerInfo`](./KVCacheLayerInfo.md)`>` **`kv_cache_info`**() `const`

</div>

Per-attention-layer KV-cache descriptors, layer order. Empty = the graph carries no KV cache. After [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache), every self-attention layer reports `bound_to_cache` with empty `past_*_input` (they left the input list; the present names stay), and [`generate_kv_input_specs`](./index.md#generate_kv_input_specs) contributes nothing for those layers.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 312

</div>

### nodes() {#nodes}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`nodes`**() `const`

</div>

Every node in topological order: each node after the producers of its inputs, the `Input` nodes first. Fails when the graph holds a cycle (the error's `code_name()` is `INVALID_GRAPH`).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 328

</div>

### node() {#node}

<div class="api-signature">

`std::optional<`[`Node`](./Node.md)`>` **`node`**(`std::string_view` `name`) `const`

</div>

The node named `name`, or `std::nullopt`.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 331

</div>

### find\_nodes(OpCode) {#find_nodes}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`find_nodes`**([`OpCode`](./index.md#OpCode) `code`) `const`

</div>

Every node whose `op_code()` is `code`, in name order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 334

</div>

### find\_pattern() {#find_pattern}

<div class="api-signature">

`std::vector<`[`Match`](./Match.md)`>` **`find_pattern`**(`const` [`Pattern`](./Pattern.md)`&` `pattern`) `const`

</div>

Every occurrence of `pattern` ([pattern.h](./index.md#pattern-h)): one [`Match`](./Match.md) per occurrence, the matched node per pattern node in the pattern's [`add_node`](./ModelGraph.md#add_node) order, occurrences never overlapping. Fails when a pattern edge names a node that was never added or a node was added with an empty predicate ([`Status::InvalidArgument`](../../index.md#Status)), and with a predicate's own failure when one throws.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 343

</div>

### constants() {#constants}

<div class="api-signature">

`std::vector<`[`Value`](./Value.md)`>` **`constants`**() `const`

</div>

The graph's edge constants: every tensor bound onto an edge with bytes fixed for the graph's lifetime (an ONNX initializer, a constant a trace captured), one [`Value`](./Value.md) each, in the graph's own order; [`Value::constant()`](./Value.md#constant) reads the bytes. A compiled ONNX initializer is also its operator's bound tensor ([`Node::bound_tensors()`](./Node.md#bound_tensors), the same bytes); a traced module's weights are bound into the operators alone and are not edge constants. A constant [`add_constant`](./ModelGraph.md#add_constant) made is listed before anything reads it.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 355

</div>

### is\_finalized() {#is_finalized}

<div class="api-signature">

`bool` **`is_finalized`**() `const`

</div>

True once [`finalize()`](./ModelGraph.md#finalize) ran: the operators are finalized for serving, weights packed into their kernel layouts and constants absorbed. [`compile`](./index.md#compile) and [`trace`](./index.md#trace) return a graph that is not finalized. Only a finalized graph runs; the edits below, [`optimize()`](./ModelGraph.md#optimize) and other graph rewrites belong before this point.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 362

</div>

### replace\_all\_uses\_with() {#replace_all_uses_with}

<div class="api-signature">

`void` **`replace_all_uses_with`**(`const` [`Value`](./Value.md)`&` `old_value`, `const` [`Value`](./Value.md)`&` `replacement`)

</div>

Every read of `old_value` reads `replacement` instead: each operator input it feeds, and each graph output it returns (the output keeps its name). Nothing reads `old_value` afterwards, so its view is gone, unless it is a graph input's value. Refuses `replacement` being `old_value`, a type mismatch, a replacement computed from one of `old_value`'s readers (it would form a cycle), a state buffer's reads, a read an operator serves from a weight it holds itself, and a constant taking a graph output.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 402

</div>

### remove\_node() {#remove_node}

<div class="api-signature">

`void` **`remove_node`**(`const` [`Node`](./Node.md)`&` `node`)

</div>

Remove [`node`](./ModelGraph.md#node), an operator nothing reads, with its reads of other values (a constant only it read goes with it). Refuses an Input node, a node that reads a state buffer, and a node whose outputs are still read (`FAILED_PRECONDITION`, naming the first reader: rewire or remove that reader first).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 412

</div>

### bypass\_node() {#bypass_node}

<div class="api-signature">

`void` **`bypass_node`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `node`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`int` `input_port` `=` `0`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`int` `output_port` `=` `0`<br />
)

</div>

Every read of [`node`](./ModelGraph.md#node)'s output `output_port` reads the value on its input `input_port` instead, and [`node`](./ModelGraph.md#node) is removed once nothing reads any of its outputs. Refuses an Input node, an input port nothing feeds, an output port nothing reads, a type mismatch between the two values, a node that reads a state buffer, and a constant taking a graph output.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 420

</div>

### set\_input() {#set_input}

<div class="api-signature">

`void` **`set_input`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `node`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`int` `port`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Value`](./Value.md)`&` `value`<br />
)

</div>

[`node`](./ModelGraph.md#node)'s input `port` reads `value`. The edit replaces the value the port reads, so the port already reads one: an input the operator was built without stays empty. Refuses an Input node (its one input is the tensor [`run`](./ModelGraph.md#run) binds), a port nothing feeds, a state buffer's read, a port the operator serves from a weight it holds itself, a type mismatch with the value the port reads, and a value computed from [`node`](./ModelGraph.md#node)'s own outputs (it would form a cycle).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 432

</div>

### set\_constant\_input() {#set_constant_input}

<div class="api-signature">

`void` **`set_constant_input`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `node`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`int` `port`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Tensor`](../Tensor.md)`&` `value`<br />
)

</div>

[`node`](./ModelGraph.md#node)'s input `port` reads a new constant holding `value`'s bytes: the graph keeps a handle to them, no copy, and [`finalize()`](./ModelGraph.md#finalize) places them with the graph. The constant replaces the value the port reads, so the port already reads one, of the same type. Refuses an Input node, a port nothing feeds, a state buffer's read, a port the operator serves from a weight it holds itself, a tensor with no data (a traced or a meta tensor), and a type mismatch with the value the port reads.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 444

</div>

### add\_constant() {#add_constant}

<div class="api-signature">

[`Value`](./Value.md) **`add_constant`**(`const` [`Tensor`](../Tensor.md)`&` `value`)

</div>

A new constant holding `value`'s bytes (a handle, no copy) that nothing reads yet; [`set_input`](./ModelGraph.md#set_input) and [`replace_all_uses_with`](./ModelGraph.md#replace_all_uses_with) take the value it returns. [`constants()`](./ModelGraph.md#constants) lists it. Once an operator reads it, it lives while something reads it, like every constant; [`finalize()`](./ModelGraph.md#finalize) drops it if nothing reads it by then. Refuses a tensor with no data (a traced or a meta tensor).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 455

</div>

### add\_node() {#add_node}

<div class="api-signature">

[`Node`](./Node.md) **`add_node`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OpCode`](./index.md#OpCode) `code`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ClikaRT::Span`](../Span.md)`<const std::optional<`[`Value`](./Value.md)`>>` `inputs`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ClikaRT::Span`](../Span.md)`<const` [`Attr`](./Attr.md)`>` `attributes` `=` `{}`<br />
)

</div>

A new operator of `code`, built the way its public op builds it (the op's own checks apply). [`inputs`](./ModelGraph.md#inputs) holds its values, one entry per input port in the op's order: `std::nullopt` omits an optional operand, and trailing entries may be left off; a constant enters as a value ([`add_constant`](./ModelGraph.md#add_constant)). `attributes` holds its settings under the names [`Node::attributes()`](./Node.md#attributes) reports: an integer also serves a number, an enumerated setting takes its enumerator's name, and a setting left out takes the op's default. A setting the op derives from its inputs instead of taking it (MaskedFill's `fill_is_exact_zero`, true only for a literal zero) takes the value the op builds when left out, and when given must be that value; where it asks for one, a constant scalar input goes in as the scalar it holds. A template setting (a list that [`Node::attributes()`](./Node.md#attributes) reports with `std::nullopt` in each slot fed at run time, such as a shape, Pad's `pad` or Slice's bounds) keeps its literal slots, and each run-time slot reads the next input past the op call's own inputs, in the order the op's parameters list them; a lone bound with no value (Select's `index`) reads the next input the same way. A setting the op takes as a plain list (Unflatten's `sizes`) takes a template only when every slot is literal. A scalar operand the op records as a setting when it is a literal (Clamp's `min`, SoftcapLogits' `cap`) reads its input when one is given and the setting of its name otherwise; given both, the setting must be what the op builds for that input. Full's `fill_value` is its setting alone and takes no input. Nothing reads its outputs yet, so wire them with [`set_input`](./ModelGraph.md#set_input), [`replace_all_uses_with`](./ModelGraph.md#replace_all_uses_with) or [`add_output`](./ModelGraph.md#add_output); [`finalize()`](./ModelGraph.md#finalize) drops a node nothing reads by then, with what only it read. The node is named `<`[`OpCode`](./index.md#OpCode)`>_<N>`, as a trace names it ([`rename_node`](./ModelGraph.md#rename_node) renames it). Refuses a value of another graph or one no longer held, a state buffer, a missing required input or setting, an input or a setting the op does not take, a setting of another kind, a slot fed at run time with no input for it, a derived setting or one beside its input that the op builds otherwise, the op's own refusal of the arguments, and a code no single public op call builds (an operator with several outputs, one whose public op call takes a setting the operator does not record, one whose op call takes a quantized tensor object). Build those from the public ops that compute them.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 496

</div>

### insert() {#insert}

<div class="api-signature">

`std::vector<`[`Value`](./Value.md)`>` **`insert`**([`TraceFunction`](./index.md#TraceFunction) `fn`, [`ClikaRT::Span`](../Span.md)`<const` [`Value`](./Value.md)`>` `inputs`)

</div>

New operators computed from [`inputs`](./ModelGraph.md#inputs): the ones `fn` records when it is traced over one tensor per input, each with that value's dtype, device and shape (a dynamic dim keeps the graph's own symbol). A constant scalar input goes into `fn` as the literal it holds, so a value `fn` reads from it (a range's end, a count) keeps the extent it gives. Returns the values `fn` returns, in its order, which nothing reads yet: wire them as [`add_node`](./ModelGraph.md#add_node)'s outputs are wired. A tensor holding data that `fn` makes or reads becomes a constant of the graph, a value `fn` returns unchanged comes back as the input it is, and the new nodes take fresh names. `fn` computes values: it does not write one of its inputs, or a tensor that holds data, in place, and it does not edit this graph or call [`optimize()`](./ModelGraph.md#optimize). Refuses a value of another graph or one no longer held, a state buffer, a value with no recorded type, an empty `fn`, `fn`'s own failure or throw (with its status and code), such an in-place write, an output of `fn` that is undefined or holds data, and a read of a tensor without data that is none of its inputs.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 518

</div>

### replace() {#replace}

<div class="api-signature">

`std::vector<`[`Value`](./Value.md)`>` **`replace`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ClikaRT::Span`](../Span.md)`<const` [`Value`](./Value.md)`>` `old_outputs`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`TraceFunction`](./index.md#TraceFunction) `fn`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ClikaRT::Span`](../Span.md)`<const` [`Value`](./Value.md)`>` `inputs`<br />
)

</div>

`insert(fn, inputs)`, then every read of `old_outputs[i]` reads new value `i`, the graph's returns included (they keep their names), and the operators that computed `old_outputs` from [`inputs`](./ModelGraph.md#inputs) go, with every producer only they read. An operator an input is computed from stays, since the new values read that input; when it makes an old output (an input read from another of its outputs), that output's reads move all the same. Returns the new values. As in [`insert`](./ModelGraph.md#insert), a constant scalar input goes into `fn` as the literal it holds, so a value `fn` reads from it keeps its extent. Refuses what [`insert`](./ModelGraph.md#insert) refuses, and: no old outputs, one listed twice, or one that is a constant, a state buffer or a graph input's value; an old output that is also one of [`inputs`](./ModelGraph.md#inputs); an old output not computed from [`inputs`](./ModelGraph.md#inputs); a value those operators make that another node reads or the graph returns (naming it and its reader); a KV cache layer's attention among them ([`kv_cache_info()`](./ModelGraph.md#kv_cache_info)); an input computed from a reader of an old output (a cyclic graph); a count of new values other than the old outputs'; a new value whose type differs from its old output's; and a constant a graph output would return.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 543

</div>

### rename\_node() {#rename_node}

<div class="api-signature">

`void` **`rename_node`**(`const` [`Node`](./Node.md)`&` `node`, `std::string` `name`)

</div>

Name [`node`](./ModelGraph.md#node) `name`; its outputs keep their names. Views of the old name are gone afterwards: find the node again with `node(name)`. Refuses an Input node (rename it with [`rename_input`](./ModelGraph.md#rename_input)), an empty name, and a name another node carries.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 552

</div>

### add\_input() {#add_input}

<div class="api-signature">

[`Node`](./Node.md) **`add_input`**(`const` [`spec::TensorSpec`](../spec/TensorSpec.md)`&` `spec`)

</div>

A new graph input named `spec.name`, last in [`input_names()`](./ModelGraph.md#input_names), with the dtype and dims of [`spec`](../spec/index.md): a dynamic dim takes its size at [`run`](./ModelGraph.md#run), and dims that share a `dim_names` entry share that size. Returns its Input node, whose value (`output(0)`) the other edits take. Refuses an empty name, a name a node carries already, and a dim that is neither positive nor [`spec::TensorSpec::kDynamicDim`](../spec/TensorSpec.md#kDynamicDim).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 563

</div>

### add\_output() {#add_output}

<div class="api-signature">

`void` **`add_output`**(`const` [`Value`](./Value.md)`&` `value`, `std::string` `name`)

</div>

Return `value` as a new graph output named `name`, last in [`output_names()`](./ModelGraph.md#output_names); a value the graph returns already may be returned under a second name. Refuses an empty name, a name another output carries, and a constant or a state buffer (a graph output never returns one directly).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 571

</div>

### remove\_output() {#remove_output}

<div class="api-signature">

`void` **`remove_output`**(`std::string_view` `name`)

</div>

Stop returning the graph output `name`; the node that computes it stays. Refuses a name no output carries, and an output a KV cache layer returns its cache as (`FAILED_PRECONDITION`, naming the layer).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 579

</div>

### rename\_input() {#rename_input}

<div class="api-signature">

`void` **`rename_input`**(`std::string_view` `name`, `std::string` `new_name`)

</div>

[Rename](./Rename.md) the graph input `name`, and its Input node, `new_name`. Views of the old name are gone afterwards. Refuses a name no input carries, an input a KV cache layer reads its cache from (`FAILED_PRECONDITION`, naming the layer), an empty name, and a name a node carries already.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 586

</div>

### rename\_output() {#rename_output}

<div class="api-signature">

`void` **`rename_output`**(`std::string_view` `name`, `std::string` `new_name`)

</div>

[Rename](./Rename.md) the graph output `name` `new_name`. Refuses a name no output carries, an output a KV cache layer returns its cache as (`FAILED_PRECONDITION`, naming the layer), an empty name, and a name another output carries.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 595

</div>

### optimize() {#optimize}

<div class="api-signature">

[`OptimizeReport`](./OptimizeReport.md) **`optimize`**(`const` [`OptimizeOptions`](./OptimizeOptions.md)`&` `options` `=` [`OptimizeOptions`](./OptimizeOptions.md)`()`)

</div>

Run the graph optimizer: `options.transforms`, or this graph's default list when it is `std::nullopt` ([`default_transforms`](./ModelGraph.md#default_transforms)`(options.defaults)`), iterated until an iteration changes nothing or `options.max_num_iterations` have run. The defaults resolve as the build that produced the graph resolves them ([optimize.h](./transforms/index.md#optimize-h)). Returns what the run did, a row per list entry included. One of the runtime's transforms that fails is undone and skipped, and its row says so; the run goes on. A transform you wrote that fails ends the run: [`optimize`](./ModelGraph.md#optimize) returns its failure and leaves the graph as it found it ("Transforms you write"). Refuses `FAILED_PRECONDITION` on a finalized graph, while a run is in flight, while another [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize) or an edit runs on this graph, inside one of its transforms, and while a trace is being recorded on this thread (inside a function [`graph::trace`](./index.md#trace), [`insert`](./ModelGraph.md#insert) or [`replace`](./ModelGraph.md#replace) traces); `InvalidArgument` when `max_num_iterations` is outside 1 to 2147483647, when the list places a transform ahead of one it must follow (naming both), when the list holds a transform that `options.defaults` switch off for this graph (naming the choice to set), and when it holds two different transforms of one name (naming both).

Transforms you write ([`Transform::from_function`](./Transform.md#from_function)) run beside the runtime's, at their places in the list, each on the thread that called [`optimize`](./ModelGraph.md#optimize). One counts as changing the graph when one of its edits did; a refused edit, and one that changes nothing, change nothing. Inside one:

- the edits above run as part of this [`optimize`](./ModelGraph.md#optimize); an edit of this graph from another thread is refused;
- the graph's inputs and outputs (their names in order, and each one's dtype, rank and dims) change only through the I/O edits; a change made any other way fails the transform;
- [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize), [`to`](./ModelGraph.md#to) and [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache) on this graph are refused (`FAILED_PRECONDITION`, naming the transform);
- moving from this graph, or assigning over it, leaves both graphs as they were and logs the reason at [Error](../Error.md): a move cannot fail, and [`optimize`](./ModelGraph.md#optimize) is still working on the graph;
- calls on other graphs, [`graph::trace`](./index.md#trace) included, run as usual. A transform that fails, or throws, ends the run: [`optimize`](./ModelGraph.md#optimize) returns its status and code as it gave them, with the message "optimize: transforms\[i\] (name) failed: " and its own, and the graph is as [`optimize`](./ModelGraph.md#optimize) found it, the changes of every transform in the run undone.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 644

</div>

### default\_transforms() {#default_transforms}

<div class="api-signature">

`std::vector<`[`Transform`](./Transform.md)`>` **`default_transforms`**(`const` [`DefaultsOptions`](./DefaultsOptions.md)`&` `defaults` `=` [`DefaultsOptions`](./DefaultsOptions.md)`()`) `const`

</div>

The transform list [`optimize()`](./ModelGraph.md#optimize) runs on this graph under `defaults` when [`OptimizeOptions::transforms`](./OptimizeOptions.md#transforms) is `std::nullopt`, in the order it runs them: a starting point to edit and hand back as [`OptimizeOptions::transforms`](./OptimizeOptions.md#transforms). It follows how the graph was built, so it can differ from the graph-free `transforms::defaults(defaults)`. Empty on a moved-from graph.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 654

</div>

### finalize() {#finalize}

<div class="api-signature">

`void` **`finalize`**()

</div>

Finalize the graph for serving: place it on its device ([`CompileOptions::weights`](./CompileOptions.md#weights), or the one [`to()`](./ModelGraph.md#to) named; a graph with neither keeps its operators where they are), pack the weights into their kernel layouts, absorb the constants the operators hold, and plan the execution order. A finalized graph runs and refuses [`optimize`](./ModelGraph.md#optimize); calling [`finalize`](./ModelGraph.md#finalize) again succeeds and changes nothing. Refuses `FAILED_PRECONDITION` while another [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize) or an edit runs on this graph, and inside one of its transforms ([`optimize`](./ModelGraph.md#optimize)). Refuses `DEVICE_MISMATCH` when a graph input sits on a device that an operator reading it cannot take it from. A traced graph builds its inputs on the host, so a traced graph whose operators run on an accelerator needs [`to()`](./ModelGraph.md#to) first. The refusal names the input and the operator and leaves the graph unfinalized: `to(stream)`, then [`finalize()`](./ModelGraph.md#finalize), serves it.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 671

</div>

### to() {#to}

<div class="api-signature">

`void` **`to`**([`StreamOrDevice`](../StreamOrDevice.md) `where`)

</div>

Move the graph to a placement: a [`Device`](../Device.md), or a [`Stream`](../Stream.md) so the graph computes on that stream (build once, `to(lane)` once, run every step). A [`Device`](../Device.md) means the stream `StreamOrDevice(device).resolve()` names: the calling thread's current stream on that device. Before [`finalize()`](./ModelGraph.md#finalize) it records where finalizing places the graph and moves nothing; [`device()`](../device-namespace/index.md) reports the new device at once. After [`finalize()`](./ModelGraph.md#finalize) it moves the finalized graph, which then computes on the new stream: an operator that changes device re-packs its weights there once, one already on that device keeps its packed weights, the execution order stays the one finalizing chose, and no copy of a moved weight stays behind. A graph traced from a module computes through the module's own operators, so moving the graph moves the module's weights too, an operator the optimizer rebuilt included; a module that already serves on another device stays there. Refuses `FAILED_PRECONDITION` while a KV cache is attached (call [`to`](./ModelGraph.md#to) before [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache)), while a run is in flight, while [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize), [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache) or an edit runs on the graph, and inside one of its transforms ([`optimize`](./ModelGraph.md#optimize)); a device that cannot lease a stream refuses before anything moves. A move that fails part-way leaves the graph finalized and serving where it was.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 695

</div>

### device() {#device}

<div class="api-signature">

[`Device`](../Device.md) **`device`**() `const`

</div>

The device the graph serves on: the one [`CompileOptions::weights`](./CompileOptions.md#weights) or [`to`](./ModelGraph.md#to) named. A graph with neither serves where its operators sit; when they sit on several devices, this is the device of the first one in [`nodes()`](./ModelGraph.md#nodes) order. A graph with no operators reports the CPU.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 701

</div>

### merge() {#merge}

<div class="api-signature">

`std::vector<`[`Rename`](./Rename.md)`>` **`merge`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ModelGraph`](./ModelGraph.md)`&` `second`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const std::vector<std::pair<std::string, std::string>>&` `io_map` `=` `{}`<br />
)

</div>

Merge `second` into this graph, as [`io::OnnxModel::merge`](../io/OnnxModel.md#merge) merges two models. Each `io_map` entry `(this_output, second_input)` feeds one of this graph's outputs into one of `second`'s inputs; the connected outputs and inputs leave the graph's lists, and everything else stays. The inputs are this graph's, then `second`'s unconnected ones, and the outputs are `second`'s, then this graph's unconnected ones. This graph keeps every name; a node, input or output name of `second` that this graph already uses takes the first free `<name>_<n>`. Returns every name that changed, each under the part `second` ([`Rename`](./Rename.md)).

The rest is [`graph::merge`](./index.md#merge)'s ([compose.h](./index.md#compose-h)), the two graphs being the parts `this` and `second`: the shapes, the devices (a connection between two devices moves its value, as under [`CrossDevice::Move`](./index.md#CrossDevice)), the KV caches, the weights and every refusal. On success `second` is consumed (left empty) and this graph is the merged one: a view of `second` then refuses as a view whose graph is gone ([node.h](./index.md#node-h)), and a view of this graph finds its node again by key. On a refusal, or on a failure inside the merge, both are left as they were. Also refuses `InvalidArgument` for a merge of a graph with itself, and `FailedPrecondition` inside one of this graph's transforms ([`optimize`](./ModelGraph.md#optimize)).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 725

</div>

### find\_nodes\_by\_name() {#find_nodes_by_name}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`find_nodes_by_name`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`regex::Regex`](../regex/Regex.md)`&` `pattern`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`NameMatch`](./index.md#NameMatch) `match` `=` [`NameMatch::Whole`](./index.md#NameMatch)<br />
) `const`

</div>

Every node whose name `pattern` matches, in name order: the whole name ([`NameMatch::Whole`](./index.md#NameMatch)) or some part of it ([`NameMatch::Anywhere`](./index.md#NameMatch)).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 743

</div>

### find\_nodes(NodePredicate) {#find_nodes-2}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`find_nodes`**([`NodePredicate`](./index.md#NodePredicate) `predicate`) `const`

</div>

Every node `predicate` accepts, in name order. The predicate runs throw-contained: a throw ends the search, which fails with it. Refuses an empty predicate ([`Status::InvalidArgument`](../../index.md#Status)).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 749

</div>

### edges() {#edges}

<div class="api-signature">

`std::vector<`[`Edge`](./Edge.md)`>` **`edges`**() `const`

</div>

Every edge, in (source name, source port, destination name, destination port) order.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 755

</div>

### edges\_between() {#edges_between}

<div class="api-signature">

`std::vector<`[`Edge`](./Edge.md)`>` **`edges_between`**(`const` [`Node`](./Node.md)`&` `src`, `const` [`Node`](./Node.md)`&` `dst`) `const`

</div>

The edges from `src` to `dst`, in (source port, destination port) order. Empty when no edge runs from one to the other, a node of another graph included.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 760

</div>

### walk() {#walk}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`walk`**(`const` [`Node`](./Node.md)`&` `start`, [`WalkOptions`](./WalkOptions.md) `options` `=` [`WalkOptions`](./WalkOptions.md)`()`) `const`

</div>

The nodes a walk from `start` reaches, in walk order: breadth-first, the start first, each node once at its fewest edges from the start, and a node's neighbors in `out_edges()` order (`in_edges()` walking backward). Fails on `options.max_nodes` and with a callable's own failure.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 767

</div>

### visit() {#visit}

<div class="api-signature">

`void` **`visit`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `start`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`NodeVisitor`](./index.md#NodeVisitor) `visitor`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`WalkOptions`](./WalkOptions.md) `options` `=` [`WalkOptions`](./WalkOptions.md)`()`<br />
) `const`

</div>

The same walk, showing `visitor` each node it reaches, the start included: [`VisitAction::Prune`](./index.md#VisitAction) does not go past that node, `Stop` ends the walk, which then succeeds. A throw from the visitor ends the walk, which fails with it. Refuses an empty visitor ([`Status::InvalidArgument`](../../index.md#Status)).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 777

</div>

### layers() {#layers}

<div class="api-signature">

`std::vector<std::vector<`[`Node`](./Node.md)`>>` **`layers`**() `const`

</div>

The topological generations: the nodes with no in-edge first ([`Node::in_degree()`](./Node.md#in_degree) 0), then each node one layer after its latest producer; every layer in [`nodes()`](./ModelGraph.md#nodes) order. Fails like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 787

</div>

### ancestors() {#ancestors}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`ancestors`**(`const` [`Node`](./Node.md)`&` `node`, [`WalkOptions`](./WalkOptions.md) `options` `=` [`WalkOptions`](./WalkOptions.md)`()`) `const`

</div>

Every node with a path to [`node`](./ModelGraph.md#node), [`node`](./ModelGraph.md#node) left out, nearest first: a backward walk, so `options.direction` is not read.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 792

</div>

### descendants() {#descendants}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`descendants`**(`const` [`Node`](./Node.md)`&` `node`, [`WalkOptions`](./WalkOptions.md) `options` `=` [`WalkOptions`](./WalkOptions.md)`()`) `const`

</div>

Every node with a path from [`node`](./ModelGraph.md#node), [`node`](./ModelGraph.md#node) left out, nearest first: a forward walk, so `options.direction` is not read.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 799

</div>

### find\_paths\_to() {#find_paths_to}

<div class="api-signature">

`std::vector<std::vector<`[`Node`](./Node.md)`>>` **`find_paths_to`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `start`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`NodePredicate`](./index.md#NodePredicate) `target`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`PathOptions`](./PathOptions.md) `options` `=` [`PathOptions`](./PathOptions.md)`()`<br />
) `const`

</div>

Every simple path from `start` that ends at the first node `target` accepts: a path never passes an accepted node, and an accepted `start` is the one-node path. Depth-first, each node's next nodes in `out_edges()` order; parallel edges give one path. The target and the edge filter each run once per node or edge. Fails past [`kMaxPathsWithoutLimit`](./index.md#kMaxPathsWithoutLimit) paths when `options.limit` is empty, and with a callable's own failure. Refuses an empty `target` ([`Status::InvalidArgument`](../../index.md#Status)).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 814

</div>

### has\_path() {#has_path}

<div class="api-signature">

`bool` **`has_path`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `src`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `dst`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`PathOptions`](./PathOptions.md) `options` `=` [`PathOptions`](./PathOptions.md)`()`<br />
) `const`

</div>

True when a path runs from `src` to `dst` within `options`; a node reaches itself.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 822

</div>

### shortest\_path(Node, Node, PathOptions) {#shortest_path}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`shortest_path`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `src`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `dst`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`PathOptions`](./PathOptions.md) `options` `=` [`PathOptions`](./PathOptions.md)`()`<br />
) `const`

</div>

A path from `src` to `dst` with the fewest edges within `options`, as nodes: `{src}` when the two are one node, empty when no path runs. One answer among equally short paths, the same on every call.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 832

</div>

### weighted\_shortest\_path\_impl() {#weighted_shortest_path_impl}

<div class="api-signature">

[`Result`](../Result.md)`<`[`WeightedPath`](./WeightedPath.md)`>` **`weighted_shortest_path_impl`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `src`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `dst`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`detail::ContainedEdgeCost` `edge_cost`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`ContainedPathOptions`](./ContainedPathOptions.md)`&` `options`<br />
) `const`

</div>

The cheapest path from `src` to `dst` within `options`, `edge_cost` summed over the edges it takes (among parallel edges, the cheapest). Every edge cost must be finite and at least 0; an empty `edge_cost` counts 0. Ties go to fewer edges; under a cutoff, the cheapest path of at most that many edges. Empty when no path runs, `{src}` at cost 0 when the two are one node. `edge_cost` runs at most once per edge. A negative, NaN or infinite cost fails naming the edge ([`Status::InvalidArgument`](../../index.md#Status)); a throw fails with it.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 844

</div>

### shortest\_path(Node, Node, EdgeCost, PathOptions) {#shortest_path-2}

<div class="api-signature">

[`WeightedPath`](./WeightedPath.md) **`shortest_path`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `src`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `dst`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`EdgeCost`](./index.md#EdgeCost) `edge_cost`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`PathOptions`](./PathOptions.md) `options` `=` [`PathOptions`](./PathOptions.md)`()`<br />
) `const`

</div>

A path from `src` to `dst` with the fewest edges within `options`, as nodes: `{src}` when the two are one node, empty when no path runs. One answer among equally short paths, the same on every call.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 847

</div>

### all\_simple\_paths() {#all_simple_paths}

<div class="api-signature">

`std::vector<std::vector<`[`Node`](./Node.md)`>>` **`all_simple_paths`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `src`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `dst`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`PathOptions`](./PathOptions.md) `options` `=` [`PathOptions`](./PathOptions.md)`()`<br />
) `const`

</div>

Every simple path from `src` to `dst`, as nodes; parallel edges give one path (networkx's [`all_simple_paths`](./ModelGraph.md#all_simple_paths) over the graph with parallel edges merged). `src == dst` gives the one-node path. The order, callables and cap of [`find_paths_to`](./ModelGraph.md#find_paths_to).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 859

</div>

### all\_simple\_edge\_paths() {#all_simple_edge_paths}

<div class="api-signature">

`std::vector<std::vector<`[`Edge`](./Edge.md)`>>` **`all_simple_edge_paths`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `src`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `dst`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`PathOptions`](./PathOptions.md) `options` `=` [`PathOptions`](./PathOptions.md)`()`<br />
) `const`

</div>

Every simple path from `src` to `dst`, as edges; each parallel edge gives its own path (networkx's [`all_simple_edge_paths`](./ModelGraph.md#all_simple_edge_paths)). `src == dst` gives one empty path. Depth-first in `out_edges()` order, with the callables and cap of [`find_paths_to`](./ModelGraph.md#find_paths_to).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 870

</div>

### count\_paths() {#count_paths}

<div class="api-signature">

`std::uint64_t` **`count_paths`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `src`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`Node`](./Node.md)`&` `dst`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`PathOptions`](./PathOptions.md) `options` `=` [`PathOptions`](./PathOptions.md)`()`<br />
) `const`

</div>

How many paths [`all_simple_paths`](./ModelGraph.md#all_simple_paths) lists, counted without listing them, so no cap applies and `options.limit` is not read. Fails when the count passes the range of `std::uint64_t`, and like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 879

</div>

### critical\_path() {#critical_path}

<div class="api-signature">

[`WeightedPath`](./WeightedPath.md) **`critical_path`**([`NodeCost`](./index.md#NodeCost) `node_cost`, [`EdgeCost`](./index.md#EdgeCost) `edge_cost` `=` [`EdgeCost`](./index.md#EdgeCost)`()`) `const`

</div>

The critical path: the path of greatest cost, `node_cost` summed over its nodes and `edge_cost` over its edges, each finite and of any sign; an empty cost counts 0, so two empty costs give the path with the most edges. A path may start and end at any node: a prefix whose sum falls below 0 is dropped and the path starts again at the next node, as networkx's `dag_longest_path` does. Ties go to more edges, then to the path found first. Empty on a graph with no nodes. Each cost runs once per node or edge. A NaN or infinite cost fails naming the node or edge ([`Status::InvalidArgument`](../../index.md#Status)), a throw fails with it, and a cyclic graph fails like [`nodes()`](./ModelGraph.md#nodes).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 894

</div>

### topological\_order() {#topological_order}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`topological_order`**([`TopologicalOrder`](./index.md#TopologicalOrder) `order` `=` [`TopologicalOrder::Deterministic`](./index.md#TopologicalOrder)) `const`

</div>

Every node in the topological order `order` names ([query.h](./index.md#query-h)): each node once, after every node whose output it reads. Fails like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 903

</div>

### random\_topological\_order() {#random_topological_order}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`random_topological_order`**(`std::uint64_t` `seed`) `const`

</div>

A topological order drawn at random from the valid ones: each node once, after every node whose output it reads. One `seed` draws one order of a given graph, on every platform. Fails like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 912

</div>

### topological\_generations() {#topological_generations}

<div class="api-signature">

`std::vector<std::vector<`[`Node`](./Node.md)`>>` **`topological_generations`**() `const`

</div>

[`layers()`](./ModelGraph.md#layers) under networkx's name: the same generations from the same call.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 918

</div>

### depths() {#depths}

<div class="api-signature">

[`NodeMap`](./NodeMap.md)`<std::size_t>` **`depths`**() `const`

</div>

Each node's generation: the most edges on a path that ends at it, so [`depths()`](./ModelGraph.md#depths)`[n]` is the index of `n`'s layer in [`layers()`](./ModelGraph.md#layers). One entry per node, in [`nodes()`](./ModelGraph.md#nodes) order. Fails like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 926

</div>

### is\_topological\_order() {#is_topological_order}

<div class="api-signature">

`bool` **`is_topological_order`**([`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `order`) `const`

</div>

True when `order` is a topological order of this graph: every node exactly once, and every edge running forward. A node of another graph, a repeated or a missing node, or an edge running backward makes it false.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 932

</div>

### find\_cycle() {#find_cycle}

<div class="api-signature">

`std::vector<`[`Edge`](./Edge.md)`>` **`find_cycle`**() `const`

</div>

One cycle as its edges, in order: each edge enters the node the next one leaves, and the last enters the node the first one leaves. Empty when the graph has none, as every traced or compiled graph.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 937

</div>

### would\_create\_cycle() {#would_create_cycle}

<div class="api-signature">

`bool` **`would_create_cycle`**(`const` [`Node`](./Node.md)`&` `src`, `const` [`Node`](./Node.md)`&` `dst`) `const`

</div>

True when an edge from `src` to `dst` would close a cycle: `dst` reaches `src`, or the two are one node.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 942

</div>

### weakly\_connected\_components() {#weakly_connected_components}

<div class="api-signature">

`std::vector<std::vector<`[`Node`](./Node.md)`>>` **`weakly_connected_components`**() `const`

</div>

The weakly connected components: the groups of nodes joined by edges taken either way, each in name order, the groups ordered by their first node's name.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 949

</div>

### dominators() {#dominators}

<div class="api-signature">

[`NodeMap`](./NodeMap.md)`<`[`Node`](./Node.md)`>` **`dominators`**() `const`

</div>

Each node's immediate dominator: the last node before it that every path from the graph inputs to it crosses. Paths start at the graph inputs, so a constant or weight operand opens none. A node no other node dominates (an input, or a node where two inputs' paths meet) maps to itself, and a node on no path from an input has no entry. Entries in [`nodes()`](./ModelGraph.md#nodes) order. Fails like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 958

</div>

### post\_dominators() {#post_dominators}

<div class="api-signature">

[`NodeMap`](./NodeMap.md)`<`[`Node`](./Node.md)`>` **`post_dominators`**() `const`

</div>

Each node's immediate post-dominator: the first node after it that every path from it to the graph outputs crosses. A node no other node post-dominates maps to itself, and a node on no path to an output has no entry. Entries in [`nodes()`](./ModelGraph.md#nodes) order. Fails like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 965

</div>

### split\_points() {#split_points}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`split_points`**() `const`

</div>

The nodes every path from the graph inputs to the graph outputs crosses, from the inputs to the outputs: where the graph splits into two stages at one node. Empty when no node is on every such path. Fails like [`nodes()`](./ModelGraph.md#nodes) on a cycle.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 972

</div>

### lowest\_common\_ancestors() {#lowest_common_ancestors}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`lowest_common_ancestors`**([`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `nodes`) `const`

</div>

The lowest common ancestors of [`nodes`](./ModelGraph.md#nodes): the nodes every one of them descends from (each counting as its own ancestor) that no other such node descends from, in [`nodes()`](./ModelGraph.md#nodes) order. networkx's `lowest_common_ancestor` returns one of them. At least one node.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 979

</div>

### merge\_point() {#merge_point}

<div class="api-signature">

`std::optional<`[`Node`](./Node.md)`>` **`merge_point`**([`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `nodes`) `const`

</div>

Where the paths from [`nodes`](./ModelGraph.md#nodes) merge: the nearest node every path from them to the graph outputs crosses, each counting for itself. Empty when their paths meet only at the outputs. A node on no path to an output is not counted. At least one node.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 988

</div>

### region() {#region}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`region`**(`const` [`Node`](./Node.md)`&` `entry`, `const` [`Node`](./Node.md)`&` `exit`) `const`

</div>

The single-entry, single-exit region from `entry` to `exit`: the nodes `entry` dominates and `exit` post-dominates, both ends included, in [`nodes()`](./ModelGraph.md#nodes) order; a node alone is a region. Fails ([`Status::InvalidArgument`](../../index.md#Status)) unless `entry` dominates `exit` and `exit` post-dominates `entry`, naming the condition that fails.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 998

</div>

### between() {#between}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`between`**(`const` [`Node`](./Node.md)`&` `src`, `const` [`Node`](./Node.md)`&` `dst`) `const`

</div>

Every node on a path from `src` to `dst`, both ends included, in [`nodes()`](./ModelGraph.md#nodes) order; empty when no path runs.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1005

</div>

### producer\_cone() {#producer_cone}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`producer_cone`**([`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `nodes`) `const`

</div>

The producer cone of [`nodes`](./ModelGraph.md#nodes): every node whose output they read, directly or through others, in [`nodes()`](./ModelGraph.md#nodes) order. A node of [`nodes`](./ModelGraph.md#nodes) counts only when another one reads it, so the cone of an input is empty.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1014

</div>

### consumer\_cone() {#consumer_cone}

<div class="api-signature">

`std::vector<`[`Node`](./Node.md)`>` **`consumer_cone`**([`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `nodes`) `const`

</div>

The consumer cone of [`nodes`](./ModelGraph.md#nodes): every node that reads their outputs, directly or through others, in [`nodes()`](./ModelGraph.md#nodes) order; the cone of a node no other node reads is empty.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1022

</div>

### is\_convex() {#is_convex}

<div class="api-signature">

`bool` **`is_convex`**([`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `nodes`) `const`

</div>

True when [`nodes`](./ModelGraph.md#nodes) is convex: no path leaves the set and comes back into it, so the set can be cut out and replaced as one piece.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1029

</div>

### min\_value\_cut() {#min_value_cut}

<div class="api-signature">

[`ValueCut`](./ValueCut.md) **`min_value_cut`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `before` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ClikaRT::Span`](../Span.md)`<const` [`Node`](./Node.md)`>` `after` `=` `{}`<br />
) `const`

</div>

The cheapest cut through the graph's values: a split of the nodes in two, every node before the cut with its producers before it, that hands the fewest bytes from the part before to the part after ([`ValueCut`](./ValueCut.md)). The graph inputs and the nodes of `before` run before the cut and the nodes of `after` after it; a graph output made before the cut is one of the values. A value weighs its tensor's bytes: a view adds nothing to the tensor it re-describes, and a constant or a state buffer is never one of the values. Of the cheapest cuts this is the one nearest the inputs: the least set of nodes before the cut. Fails ([`Status::InvalidArgument`](../../index.md#Status)) when no cut exists, naming the node of `after` that is a graph input, is in `before` or feeds a node of `before`, and ([`Status::Unsupported`](../../index.md#Status)) when a value has no fixed size in bytes (a dynamic dim), since the cut weighs every value.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1047

</div>

### visualize() {#visualize}

<div class="api-signature">

`void` **`visualize`**(`std::string_view` `path`) `const`

</div>

Write the compiled graph to `path` as an ONNX model for viewing in Netron or any ONNX graph viewer. The file holds the executable topology as [`compile`](./index.md#compile) left it: the runtime's fused and absorbed operators under their own op types, every edge as a tensor wire carrying its shape and dtype, and the graph's inputs and outputs under their names. Structure only. No weights are written, so the file is a picture of the graph, not a runnable model. `path` is created or overwritten.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1062

</div>

### export\_onnx() {#export_onnx}

<div class="api-signature">

`void` **`export_onnx`**(`std::string_view` `path`, `const` [`OnnxExportOptions`](./OnnxExportOptions.md)`&` `options` `=` `{}`) `const`

</div>

Write the graph to `path` as a runnable ONNX model. The inputs and outputs keep their names, dtypes and dims, and a dynamic dimension is written under its name, so two inputs that share a dimension still share it when the model is read back. The weights become the model's initializers, in the file or beside it as `options` says. They are read as the file is written, one at a time, so the export holds no second copy of them. [`io::OnnxModel::from_graph`](../io/OnnxModel.md#from_graph) builds the same model in memory without writing it; [`io::OnnxModel::open`](../io/OnnxModel.md#open) and [`compile`](./index.md#compile) read the file back.

Refused, with nothing written:

- a graph that rewrites a cache buffer in place: one given a cache by [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache), or one traced over a function that writes its cache in place. Export before [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache), or trace the step with the cache as an input and its update as an output;
- a graph holding an operator that has no ONNX form at the chosen opset, naming the node and the operator;
- a call while [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize), [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache), [`to`](./ModelGraph.md#to) or an edit runs on the graph (`FAILED_PRECONDITION`, naming the call).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1087

</div>

### shape\_domains() {#shape_domains}

<div class="api-signature">

`std::vector<`[`ShapeDomain`](./ShapeDomain.md)`>` **`shape_domains`**() `const`

</div>

The shapes each input admits, [`input_names()`](./ModelGraph.md#input_names) order. A dimension with a fixed size is `Fixed`; a dynamic dimension compiled with a recorded profile (an ONNX compile given `InputSpec` ranges or named-dim bindings) is `Range`; a dynamic dimension without one is `Free`. See [`ShapeDomain`](./ShapeDomain.md) ([bench.h](./index.md#bench-h)).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1098

</div>

### input\_shape\_domain() {#input_shape_domain}

<div class="api-signature">

[`ShapeDomain`](./ShapeDomain.md) **`input_shape_domain`**(`std::string_view` `name`) `const`

</div>

The domain of the input named `name`. Raises [`ClikaRT::Error`](../Error.md) (NotFound) when no input carries the name.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1105

</div>

### validate\_shapes(vector\<InputShape\>) {#validate_shapes}

<div class="api-signature">

`void` **`validate_shapes`**(`const std::vector<`[`InputShape`](./InputShape.md)`>&` `shapes`) `const`

</div>

Check named shapes against the domains: every runtime input present once, every name an input, every rank equal to the input's, and every extent admitted ([`DimDomain::admits`](./DimDomain.md#admits)). Raises [`ClikaRT::Error`](../Error.md) (InvalidArgument) naming the input and the dimension that failed.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1114

</div>

### validate\_shapes(vector\<vector\<int64\_t\>\>) {#validate_shapes-2}

<div class="api-signature">

`void` **`validate_shapes`**(`const std::vector<std::vector<std::int64_t>>&` `shapes`) `const`

</div>

Check named shapes against the domains: every runtime input present once, every name an input, every rank equal to the input's, and every extent admitted ([`DimDomain::admits`](./DimDomain.md#admits)). Raises [`ClikaRT::Error`](../Error.md) (InvalidArgument) naming the input and the dimension that failed.

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1121

</div>

### bench(vector\<InputShape\>, BenchOptions) {#bench}

<div class="api-signature">

[`BenchReport`](./BenchReport.md) **`bench`**(`const std::vector<`[`InputShape`](./InputShape.md)`>&` `shapes`, [`BenchOptions`](./BenchOptions.md) `options` `=` `{}`) `const`

</div>

Time the graph on synthesized inputs of the given shapes. The shapes are validated as [`validate_shapes`](./ModelGraph.md#validate_shapes) does, one tensor per input is filled per `options.fill` on the benchmark device, `options.warmup` untimed runs precede `options.iterations` timed ones, and the report carries every timed run's wall-clock milliseconds (each output synchronized before the clock stops), the summary statistics, the process's peak resident set and the device's memory counters. Raises [`ClikaRT::Error`](../Error.md) on a shape the domains reject, a run that fails, a graph that is not finalized, or one that [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize) or [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache) is changing (`FAILED_PRECONDITION`).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1137

</div>

### bench(vector\<vector\<int64\_t\>\>, BenchOptions) {#bench-2}

<div class="api-signature">

[`BenchReport`](./BenchReport.md) **`bench`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const std::vector<std::vector<std::int64_t>>&` `shapes`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`BenchOptions`](./BenchOptions.md) `options` `=` `{}`<br />
) `const`

</div>

Time the graph on synthesized inputs of the given shapes. The shapes are validated as [`validate_shapes`](./ModelGraph.md#validate_shapes) does, one tensor per input is filled per `options.fill` on the benchmark device, `options.warmup` untimed runs precede `options.iterations` timed ones, and the report carries every timed run's wall-clock milliseconds (each output synchronized before the clock stops), the summary statistics, the process's peak resident set and the device's memory counters. Raises [`ClikaRT::Error`](../Error.md) on a shape the domains reject, a run that fails, a graph that is not finalized, or one that [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize) or [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache) is changing (`FAILED_PRECONDITION`).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1146

</div>

### bench(NamedTensors, BenchOptions) {#bench-3}

<div class="api-signature">

[`BenchReport`](./BenchReport.md) **`bench`**(`const` [`NamedTensors`](../NamedTensors.md)`&` `inputs`, [`BenchOptions`](./BenchOptions.md) `options` `=` `{}`) `const`

</div>

Time the graph on synthesized inputs of the given shapes. The shapes are validated as [`validate_shapes`](./ModelGraph.md#validate_shapes) does, one tensor per input is filled per `options.fill` on the benchmark device, `options.warmup` untimed runs precede `options.iterations` timed ones, and the report carries every timed run's wall-clock milliseconds (each output synchronized before the clock stops), the summary statistics, the process's peak resident set and the device's memory counters. Raises [`ClikaRT::Error`](../Error.md) on a shape the domains reject, a run that fails, a graph that is not finalized, or one that [`optimize`](./ModelGraph.md#optimize), [`finalize`](./ModelGraph.md#finalize) or [`attach_kv_cache`](./ModelGraph.md#attach_kv_cache) is changing (`FAILED_PRECONDITION`).

<div class="api-declared">

Declared in `ClikaRT/graph/model_graph.h`, line 1156

</div>
