A miniature implementation of Qiskit's quantum circuit framework using tensor networks. This project demonstrates how quantum circuits can be represented and simulated efficiently using tensor network methods, providing both educational insight and practical quantum circuit simulation capabilities.
This project implements a Qiskit-like quantum circuit interface from scratch using only tensor networks. It leverages the TensorNetwork library for efficient tensor contractions and provides support for both full statevector and Matrix Product State (MPS) representations.
- Tensor Network Backend: All quantum operations are represented and contracted using tensor networks
- Qiskit-Compatible API: Familiar interface for users of Qiskit
- Multiple Representations: Support for both statevector and MPS representations
- Two Dense Contraction Schemes: Statevector contraction can run through time or through space
- MPS Compression: Optional compression with configurable error tolerance for efficient simulation of larger circuits
- Quantum Registers: Support for named quantum registers similar to Qiskit
- Visualization: Circuit visualization using matplotlib
- Quantum Algorithms: Includes implementation of Deutsch-Jozsa algorithm
(See requirements.txt for complete dependency list)
from qiskit_from_scratch import QuantumCircuit
# Create a 3-qubit circuit
qc = QuantumCircuit(3, name='MyCircuit')
# Add gates
qc.h(0) # Hadamard on qubit 0
qc.cx(0, 1) # CNOT with control=0, target=1
qc.rz(np.pi/4, 2) # Z-rotation on qubit 2
# Get the statevector
statevector = qc.state_vector()from qiskit_from_scratch import QuantumCircuit, QuantumRegister
# Create quantum registers
qx = QuantumRegister(2, name='qx')
qy = QuantumRegister(1, name='qy')
# Create circuit with registers
qc = QuantumCircuit(qx, qy, name='RegisterCircuit')
# Apply gates using register notation
qc.h(qx['all']) # Hadamard on all qubits in qx
qc.cx(qx[0], qy[0]) # CNOT between registers# Create and run circuit with MPS representation
qc = QuantumCircuit(10, name='LargeCircuit')
qc.h(list(range(10)))
# Contract using MPS with compression (eps = error tolerance)
mps = qc.contract(scheme='time', representation='MPS', eps=0.01)# Dense contraction, folding the network from top to bottom
space_state = qc.contract(scheme='space', representation='statevector')# Create state preparation circuit
qc = QuantumCircuit(3, name='State')
qc.h(0)
qc.cx(0, 1)
# Create operator circuit
operator = QuantumCircuit(3, name='Observable')
operator.z(1) # Z operator on qubit 1
# Convert operator to gate and compute expectation value
operator_gate = operator.to_gate()
expectation = qc.expected(operator_gate, representation='MPS', eps=0.1)- Pauli Gates:
x(),y(),z() - Hadamard:
h() - Rotation Gates:
rx(angle),ry(angle),rz(angle)
- Controlled-X (CNOT):
cx(control, target) - Controlled-Z:
cz(control, target)
- Toffoli (CCX):
ccx(control1, control2, target)
append_gate_single(): Add custom single-qubit gatesappend_gate_control(): Add custom controlled gatesappend_gate_multi_control(): Add custom multi-controlled gatesappend_operator(): Add arbitrary tensor network operators
Parent class that manages the tensor network representation of quantum circuits.
Key Methods:
append_operator(operator, qudits): Add operators to the circuitcontract(scheme, representation, eps): Contract the tensor networkscheme: 'time' or 'space' ('space'only for dense statevector contractions)representation: 'statevector' or 'MPS'eps: MPS compression error tolerance
Attributes:
tensors: 2D list of tensor nodes organized by [time][qudit]n_qudits: Number of quditsdimension_qudits: Dimension of each qudit (2 for qubits)depth: Circuit depth
Inherits from TNCircuit and provides a Qiskit-like interface.
Additional Methods:
- Single and multi-qubit gate methods (h, x, y, z, rx, ry, rz, cx, cz, ccx)
state_vector(): Get the full statevectorexpected(operator): Compute expectation valuecheck_state(state): Get amplitude of a specific basis stateto_gate(): Convert circuit to a gate for use in other circuitsdraw(): Visualize the circuit
Magic Methods:
len(qc): Returns circuit depthqc[i]: Get all tensors at qudit iprint(qc): Display circuit diagram
Manages named collections of qudits.
Features:
- Named qudit access:
reg[0],reg['all'],reg[(0,3)] - Integration with
QuantumCircuit
Complete implementation of the Deutsch-Jozsa algorithm for determining whether a function is constant or balanced.
# Create a balanced oracle
oracle = QuantumCircuit(3, name='Oracle')
oracle.cx(1, 2)
oracle_gate = oracle.to_gate()
# Run Deutsch-Jozsa algorithm
Deutsch_Jozsa_Algorithm(2, oracle_gate, repr='MPS', eps=0.5)
# Output: Balanced functionMini-Qiskit_with_Tensor_Networks/
│
├── qiskit_from_scratch.ipynb # Main implementation and examples
├── auxiliary_functions.py # Helper functions for tensor operations
├── requirements.txt # Python dependencies
└── README.md # This file
Each qubit is represented as a tensor with multiple indices:
- out: Physical qubit dimension (connects forward in time)
- in: Connects to previous time step
- up/down: Connects to adjacent qubits (for multi-qubit gates)
Gates are represented as tensors that contract with the state tensors. The circuit evolves by systematically contracting these tensors according to the chosen scheme (time-based) and representation (statevector or MPS).
Time-based Contraction:
- Contracts tensors layer by layer through time
- Maintains quantum state at each time step
- Supports both exact (statevector) and approximate (compressed MPS) representations
Space-based Contraction:
- Contracts each qudit row across time first
- Folds the resulting row tensors from top to bottom
- Implemented only for the dense statevector representation
For large circuits, MPS representation with compression provides significant memory savings:
- Uses Tensor Train (TT) decomposition via tntorch
- Configurable error tolerance (eps parameter)
- Enables simulation of circuits with more qubits than full statevector methods
- Spatial contraction is not implemented for MPS
- Density operator representation not implemented
- PEPS (Projected Entangled Pair States) representation not implemented
- No measurement operations (classical registers)
- No noise models
- Limited gate set compared to full Qiskit
Potential areas for extension:
- Additional quantum gates (SWAP, phase gates, etc.)
- Measurement operations
- More quantum algorithms (Grover's, QFT, VQE)
- Density matrix representation
- Spatial contraction schemes
- Noise models and error mitigation
- Performance optimizations
This project is for educational purposes, demonstrating the connection between quantum circuits and tensor networks.
This implementation is inspired by Qiskit and uses the following libraries:
- TensorNetwork library for tensor operations
- tntorch for MPS compression
- PyTorch for tensor backend
- NumPy for numerical operations
- Matplotlib for visualization
Developed as an educational project to understand quantum circuit simulation using tensor network methods.