Yao.jl
repository·master·Indexed 21 days ago
https://github.com/quantumbfs/yao.jlAn extensible and efficient Julia framework for quantum algorithm design, quantum software 2.0, and quantum computation education. It utilizes the Quantum Block Intermediate Representation (QBIR) to define programs that can be interpreted across various simulation backends and matrix representations. The ecosystem includes components like YaoBlocks for circuit building blocks, YaoPlots for visualization, YaoSym for symbolic computation, and YaoToEinsum for tensor network conversion, as well as a specialized reverse-mode automatic differentiation engine.
What's inside Yao.jl
- YaoSym is the symbolic computation backend for Yao.jl. It provides the symbolic capabilities required for high-level quantum circuit manipulation and expression within the Yao ecosystem.
What are YaoBlocks?
masterYaoBlocks is a component package for Yao.jl that provides standard basic quantum circuit simulator building blocks. It contains the abstract definitions and basic implementations of the fundamental building blocks used to construct quantum circuits within the Yao ecosystem.Convert Yao circuits to tensor networks (einsum)
masterYaoToEinsumis a Julia package designed to convert Yao.jl quantum circuits into tensor network representations usingeinsumnotation.How QBIR works in the Yao framework
masterThe core functionality of the framework is built on the Quantum Block Intermediate Representation (QBIR).
In the Yao workflow:
- A quantum program is defined using QBIR.
- The QBIR program is then interpreted into specific targets.
- Supported targets include various simulation backends and different matrix representations.
Perform symbolic computation in Yao
masterYao's symbolic engine, powered by
SymEngine.jl, allows you to define quantum circuits containing symbolic parameters. This is useful for analyzing circuits that depend on variables (like rotation angles) before assigning concrete values.Key operations include:
- Defining symbolic variables using the
@varsmacro. - Substituting symbolic variables with concrete values using the
subsfunction.
To use these features, ensure you have
YaoSymavailable (typically viausing Yao).using Yao @vars θ # Define a circuit with a symbolic parameter θ circuit = chain(2, put(1=>H), put(2=>Ry(θ))) # Get the symbolic matrix representation mat(circuit) # Substitute θ with a concrete value (e.g., π/2) new_circuit = subs(circuit, θ=>π/2) # Get the concrete matrix representation mat(new_circuit)- Defining symbolic variables using the
How quantum registers work in Yao
masterA quantum register represents a quantum state or a batch of quantum states. Yao uses two primary types of registers:
ArrayRegandBatchedArrayReg, both of which use matrices for storage.A key concept is the distinction between active and inactive qubits:
- Active qubits: Only these qubits are visible to quantum operators. Applying an operator to a register only affects the active subset.
- Inactive (remaining) qubits: These are part of the register but are ignored by quantum operators.
This allows for efficient computation by focusing on a subset of qubits using
focus!and then returning to the full configuration usingrelax!.using Yao using YaoArrayRegister reg = rand_state(3) focus!(reg, 1:2) # Set first two qubits as active nactive(reg) # Returns number of active qubits relax!(reg) # Set all qubits back to active nactive(reg)Overload exist methods for a custom block
masterIn Yao, every block has two primary methods that can be overloaded to define custom behavior:
matandapply!.- Overload
mat(block)to define how the block's matrix form is gathered. - Overload
apply!(reg, block)to define how the block is applied to a quantum register.
This allows you to create custom block types with specialized matrix representations or application logic.
# Prototypes for overloading apply!(reg, block) mat(block)- Overload
Simulate noisy circuits using `DensityMatrixMode` or `PauliBasisMode`
masterYaoToEinsum supports noisy circuit simulation by specifying a simulation mode:
DensityMatrixMode(): Simulates using the density matrix representation. Useful for general decoherence and noise channels.network = Yao.yao2einsum(noisy_circuit; mode=DensityMatrixMode(), ...)result = Yao.contract(network)[](returns the density matrix)
PauliBasisMode(): Simulates using the Pauli basis representation.network = Yao.yao2einsum(noisy_circuit; mode=PauliBasisMode(), ...)result = Yao.contract(network)(returns Pauli coefficients)
# Density Matrix Mode Example network_dm = Yao.yao2einsum(noisy_circuit; mode=DensityMatrixMode(), initial_state=Dict([i=>0 for i=1:n_small]), observable=put(n_small, 1=>Z) ) res_network = contract(network_dm)[] # Pauli Basis Mode Example network_pauli = Yao.yao2einsum(noisy_circuit; mode=PauliBasisMode(), initial_state=Dict([i=>0 for i=1:n_small]), observable=put(n_small, 1=>Z) ) res_pauli = Yao.contract(network_pauli)Integrate Yao with general-purpose AD engines like Zygote
masterWhile Yao's builtin AD engine is specialized for quantum circuits, you can use Yao within general-purpose Julia AD frameworks (such as Zygote.jl). This is possible because Yao's differentiation rules have been ported to ChainRules.jl, allowing seamless integration with the broader Julia machine learning ecosystem.Understand the Yao and CuYao architecture
masterThe Yao ecosystem is organized into two primary meta-packages: Yao and CuYao. The architecture is designed to allow quantum programs to be defined once and then interpreted for various targets, such as different simulation backends or matrix representations.Choose between `put` and `subroutine` blocks
masterWhen mapping a subblock to a subset of qudits, choose the block type based on the complexity of the operation:
put: Applies a gate in-place using a static matrix representation. It is most efficient when the subblock is small.subroutine: Designed for running sub-programs on a subset of qubits. It usesfocus!to set target qubits as active andrelax!to unset them. This is generally faster for complex circuits applied to a subset of qubits.
Use
subroutineinstead ofputfor larger circuits to improve performance.using Yao reg = rand_state(20); # Use put for small subblocks @time apply(reg, put(20, 1:6=>EasyBuild.qft_circuit(6))); # Use subroutine for sub-programs/circuits on subsets @time apply(reg, subroutine(20, EasyBuild.qft_circuit(6), 1:6));Use BitBasis for bit-represented linear algebra bases
masterTheBitBasismodule provides types and operations for representing bases in linear algebra using bits. This is useful for quantum computing simulations where basis states are indexed by bitstrings. For comprehensive details on the underlying implementation and advanced usage, refer to the standalone BitBasis.jl documentation.