At the moment a network is built by eagerly composing concrete SLH triples with ▷, ⊞, and feedback. That's great for small setups, but the network only ever exists as its final evaluated triple. You can't build a layout out of components you haven't specified yet, you can't ask whether two layouts are the same, and once the triples are composed the structural information (which channels actually talk to each other) is gone.
I'd like an abstract circuit layer that sits on top of the current machinery. The idea is a symbolic circuit expression: component placeholders combined with ▷/⊞/feedback as lazy nodes instead of eagerly-evaluated ones. Concrete SLH composition stays exactly as it is and becomes the thing the expression lowers to, so nothing about the current API changes.
Concretely this buys us a few things. You can do topological reasoning with black-box components: build and manipulate a network before any component's SLH is pinned down, substitute concrete triples in later, and derive the reduced SLH of a feedback network as a function of abstract blocks (or just check that two layouts are equivalent). It gives us block decomposition, factoring a large network into independent sub-blocks and detecting channels that don't interact so the effective channel count shrinks, which the eager path throws away. It's the natural home for a real component library, since beam splitter, phase shifter, cavity, and coherent drive currently live only as prose in the docs rather than exported constructors. And it lets permutation routing be an algebraic object rather than manual index bookkeeping.
Rough API sketch (names are placeholders):
# Named black-box components with a fixed channel dimension
bs = CircuitSymbol(:BS, 2) # 2 in / 2 out
cav = CircuitSymbol(:cav, 1)
perm = CPermutation([2, 1]) # channel routing as a first-class object
# The composition operators stay eager on concrete SLHs (unchanged), but build
# a lazy Circuit expression as soon as any operand is symbolic:
net = feedback((bs ⊞ cav) ▷ perm, 2, 1) # a Circuit, not yet an SLH
# Fill in the black boxes
net = substitute(net, Dict(bs => beamsplitter(θ), cav => cavity(Δ, γ)))
# Symbolic reduction: feedback elimination + series/concat laws, parameters kept symbolic
net = simplify(net)
# Structural analysis
blocks = decompose(net) # independent Circuit sub-expressions
isequiv(net_a, net_b) # equal after reduction?
# Lower to the concrete triple (runs today's composition path)
G = SLH(net)
Two things worth settling before building the full thing: the payoff is mostly for large or modular networks, so it's worth deciding whether that's in scope, and whether block decomposition needs its own graph representation or can be read straight off the expression tree.
At the moment a network is built by eagerly composing concrete
SLHtriples with▷,⊞, andfeedback. That's great for small setups, but the network only ever exists as its final evaluated triple. You can't build a layout out of components you haven't specified yet, you can't ask whether two layouts are the same, and once the triples are composed the structural information (which channels actually talk to each other) is gone.I'd like an abstract circuit layer that sits on top of the current machinery. The idea is a symbolic circuit expression: component placeholders combined with
▷/⊞/feedbackas lazy nodes instead of eagerly-evaluated ones. ConcreteSLHcomposition stays exactly as it is and becomes the thing the expression lowers to, so nothing about the current API changes.Concretely this buys us a few things. You can do topological reasoning with black-box components: build and manipulate a network before any component's
SLHis pinned down, substitute concrete triples in later, and derive the reducedSLHof a feedback network as a function of abstract blocks (or just check that two layouts are equivalent). It gives us block decomposition, factoring a large network into independent sub-blocks and detecting channels that don't interact so the effective channel count shrinks, which the eager path throws away. It's the natural home for a real component library, since beam splitter, phase shifter, cavity, and coherent drive currently live only as prose in the docs rather than exported constructors. And it lets permutation routing be an algebraic object rather than manual index bookkeeping.Rough API sketch (names are placeholders):
Two things worth settling before building the full thing: the payoff is mostly for large or modular networks, so it's worth deciding whether that's in scope, and whether block decomposition needs its own graph representation or can be read straight off the expression tree.