Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Experimental tree RSI products

tensor4all-treersi approximates simultaneous Hadamard products of existing tree tensor networks. All inputs must have the same labeled tree and matching physical indices at each node. Input bond dimensions may differ. The implementation supports four real/complex scalar types and CPU execution.

Use hadamard_many_in with the same execution context that owns the inputs. The convenience hadamard_many uses the default CPU context and requires the global-defaults feature. Set max_bond_dim or sketch_dim; start with a rank budget appropriate to the application and validate actual product error. rel_tol controls local sketch pivots and is not a global error tolerance.

The example below takes a nonconstant bond-two chain, uses sketched columns, and checks the full squared tensor against a dense oracle. Dense validation is appropriate for this small example. Materialize each tensor once.

use tensor4all_core::{DynIndex, IdxTensor};
use tensor4all_treersi::{hadamard_many, TreeRsiOptions};
use tensor4all_treetn::TreeTN;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let sites: Vec<_> = (0..7).map(|_| DynIndex::new_dyn(2)).collect();
    let bonds: Vec<_> = (0..6).map(|_| DynIndex::new_dyn(2)).collect();
    let mut cores = Vec::new();
    for v in 0..7 {
        let mut indices = vec![sites[v].clone()];
        if v > 0 {
            indices.push(bonds[v - 1].clone());
        }
        if v < 6 {
            indices.push(bonds[v].clone());
        }
        // Column-major core entries; nonconstant bond-two input.
        let data = (0..(1 << indices.len()))
            .map(|j| 0.3 + ((j * 13 + v * 7) % 17) as f64 / 20.0)
            .collect();
        cores.push(IdxTensor::from_dense(indices, data)?);
    }
    let input = TreeTN::from_tensors(cores, (0usize..7).collect())?;
    let dense = input.to_dense()?.permute_indices(&sites)?.to_vec::<f64>()?;
    let expected = IdxTensor::from_dense(sites, dense.iter().map(|x| x * x).collect())?;
    let options = TreeRsiOptions {
        max_bond_dim: Some(4),
        sketch_dim: Some(3),
        seed: 7,
        ..Default::default()
    };
    let result = hadamard_many::<f64, _>(&[input.clone(), input], &options)?;
    assert!(result
        .diagnostics
        .edges
        .iter()
        .any(|edge| !edge.exact_columns));
    let error = result.tree.to_dense()?.sub(&expected)?.maxabs()? / expected.maxabs()?;
    assert!(error < 1e-10, "actual product relative max error: {error}");
    Ok(())
}

For larger problems, choose held-out points independently of the sketch RNG, compute each input there using TreeTNCachedEvaluator::evaluate_batched, and compare their pointwise product to the returned tensor at those same points. Keep the reference values outside any timing loop. A sampled relative L2 error is useful evidence, but does not bound error over all physical entries. Use a fixed acceptance threshold; reject failed calls and nonfinite values.

The edge diagnostics describe local row selection. Small relative_pivot, a low output rank, or successful return does not certify accuracy. The method can miss even a rank-one true product for legal explicit probes. See the derivation and counterexample.

Binary scales accompany contractions to handle long chains and extreme overall magnitudes. Detected loss of representable numerical range is an error. max_local_elements limits individual dense blocks; total cache and backend scratch memory are additional. Only products are supported: there is no arbitrary nonlinear map or reciprocal API and no automatic differentiation.