Skip to content

Commit f6dcb14

Browse files
committed
docs
1 parent e87b172 commit f6dcb14

21 files changed

+570
-169
lines changed

docs/Project.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
33
DocumenterVitepress = "4710194d-e776-4893-9690-8d956a29c365"
44
LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
55
MonitoredQuantumCircuits = "d8bf802c-9929-44b5-8e59-9c739daaeb6f"
6-
OhMyREPL = "5fb14364-9ced-5910-84b2-373655c76a03"

docs/make.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ makedocs(;
2020
"Home" => "index.md",
2121
"Getting started" => "getting_started.md",
2222
"Library" => [
23-
"Geometries" => "library/lattices.md",
23+
"Geometries" => "library/geometries.md",
2424
"Operations" => "library/operations.md",
2525
"Circuits" => "library/circuits.md",
2626
"Backends" => [
@@ -30,9 +30,8 @@ makedocs(;
3030
]
3131
],
3232
"Interfaces" => [
33-
"Geometry" => "interfaces/add_lattice.md",
33+
"Geometry" => "interfaces/add_geometry.md",
3434
"Operation" => "interfaces/add_operation.md",
35-
"Circuit" => "interfaces/add_circuit.md",
3635
"Backend" => "interfaces/add_backend.md"
3736
],
3837
"Modules" => [

docs/src/getting_started.md

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,69 @@
11
# Getting Started
22

3-
The framework consists of three main parts. First is the qubit geometry, which represents the underlying qubits structure. Second is the circuit, which holds information about the operations applied to the qubits in a given geometry. The last part is the execution of the circuit, which can happen on various backends.
4-
As always, load MonitoredQuantumCircuits.jl (after [installing](/index.md) it) using the `using` keyword for the following code snippets to work
3+
MonitoredQuantumCircuits.jl is structured around three core components: **qubit geometry**, **circuit construction**, and **circuit execution**. This guide provides a concise overview to help you begin using the framework effectively.
4+
5+
Before proceeding, ensure that MonitoredQuantumCircuits.jl is [installed](/index.md) and loaded:
6+
57
```julia
68
using MonitoredQuantumCircuits
79
```
810

9-
## Choose a Geometry
10-
A `Geometry` is a representation of qubits and connections between them (i.e., a graph). In general, it is only possible to apply operations to multiple qubits if they are connected in the geometry. For more information see [Geometries](/library/lattices.md).
11-
To construct a geometry object, call a constructor, e.g.,
11+
## 1. Select a Geometry
12+
13+
A `Geometry` defines the arrangement and connectivity of qubits, typically represented as a graph. Operations can only be applied to qubits that are connected within the chosen geometry. For further details, refer to the [Geometries](/library/geometries.md) documentation.
14+
15+
To construct a geometry object, use one of the provided constructors. For example:
16+
1217
```julia
1318
geometry = HoneycombGeometry(Periodic, 12, 12)
1419
```
1520

16-
## Compose a Circuit
17-
A circuit stores the [Operations](/library/operations.md) being applied to the qubits in a lattice. For more information see [Circuits](/library/circuits.md).
18-
To construct a circuit object, call a constructor, e.g.,
21+
## 2. Construct a Circuit
22+
23+
A circuit encapsulates the [operations](/library/operations.md) applied to the qubits within a given geometry. For more information, see [Circuits](/library/circuits.md).
24+
25+
To create a circuit, you may use a predefined constructor:
26+
1927
```julia
2028
circuit = MeasurementOnlyKitaev(geometry, px, py, pz; depth=100)
2129
```
22-
Or start an iterative construction by initializing an empty circuit
30+
31+
Alternatively, you can build a circuit iteratively by initializing an empty circuit:
32+
2333
```julia
2434
circuit = Circuit(geometry)
2535
```
26-
Now you could continue with the CLI and call `apply!` for different operations, or launch a [GUI](/modules/gui.md) (WIP) using
36+
37+
You may then use the command-line interface to apply operations, or launch the [Graphical User Interface](/modules/gui.md) (GUI, work in progress):
38+
2739
```julia
2840
GUI.CircuitComposer!(circuit)
2941
```
30-
Once you are done creating the circuit, compile it for faster iteration
42+
43+
Once your circuit is complete, compile it for improved performance:
44+
3145
```julia
3246
compiled_circuit = compile(circuit)
3347
```
3448

35-
## Execute
36-
To execute a quantum circuit, you first have to think about which [Backend](/library/backends.md) to use.
37-
For example a Clifford simulation using QuantumClifford.jl
49+
## 3. Execute the Circuit
50+
51+
To execute a quantum circuit, first select an appropriate [backend](/library/backends.md). For example, to use a Clifford simulator via QuantumClifford.jl:
52+
3853
```julia
3954
simulator = QuantumClifford.TableauSimulator(nQubits(geometry))
4055
```
41-
or a state vector simulation using cuQuantum via Qiskit-Aer
56+
57+
Or, for state vector simulation using cuQuantum through Qiskit-Aer:
58+
4259
```julia
4360
simulator = Qiskit.GPUStateVectorSimulator()
4461
```
45-
Then, you can execute the circuit using
62+
63+
Execute the compiled circuit on the chosen backend:
64+
4665
```julia
47-
execute!(circuit::CompiledCircuit, backend::Backend)
66+
execute!(compiled_circuit, simulator)
4867
```
49-
For more information see [Backends](/library/backends.md).
5068

69+
For additional details, consult the [Backends](/library/backends.md) documentation.

docs/src/interfaces/add_circuit.md

Whitespace-only changes.

docs/src/interfaces/add_geometry.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Geometry Interface
2+
3+
A **qubit geometry** represents the physical connectivity of qubits. Geometries are primarily intended to simplify the construction of circuits on various lattice structures, making it easier for users to implement and reason about their circuits. While geometries do not play a major role in the execution of circuits, they provide a convenient abstraction for circuit design.
4+
5+
Several [pre-implemented geometries](/library/geometries.md) are available. However, if you wish to define a custom geometry, this guide outlines the recommended approach.
6+
7+
## Defining a Geometry Type
8+
9+
To implement your own geometry, define a new `struct`:
10+
11+
```julia
12+
struct MyGeometry <: Geometry
13+
graph::Graph
14+
end
15+
```
16+
17+
along with any necessary constructors.
18+
19+
## Recommended Methods
20+
21+
While not strictly required, the following methods are considered best practice and will help you construct and interact with circuits on your custom geometry.
22+
23+
### Indexing
24+
25+
It is often useful to support multiple indexing schemes, such as a one-dimensional linear index and a two-dimensional grid index. To facilitate conversions between these schemes, consider implementing:
26+
27+
```julia
28+
function to_linear(geometry::MyGeometry, (i, j)::NTuple{2,Int64})
29+
# Convert a grid index to a linear index (integer)
30+
end
31+
32+
function to_grid(geometry::MyGeometry, i::Int64)
33+
# Convert a linear index to a grid index (tuple)
34+
end
35+
```
36+
37+
### Neighbor Access
38+
39+
In many cases, it is important to identify the nearest neighbors of a qubit, for example, to apply two-qubit gates. Ideally, connections can be distinguished by their type, ensuring that each qubit has at most one neighbor of a given type. To support this, implement a neighbor-access method:
40+
41+
```julia
42+
function neighbor(geometry::MyGeometry, i::Int64; direction::Symbol)
43+
# Return the neighbor of qubit `i` in the specified `direction`
44+
# Should return a linear index (integer)
45+
end
46+
```
47+
48+
### Visualization (Optional)
49+
50+
For improved usability in the REPL, you may wish to provide a visualization method:
51+
52+
```julia
53+
function visualize(io::IO, geometry::MyGeometry)
54+
# Print a basic visualization of the geometry
55+
end
56+
```
57+
58+
## Example: All-to-All Connectivity
59+
60+
Below is an example implementation of a geometry with all-to-all connectivity:
61+
62+
```julia
63+
using Graphs
64+
65+
struct CompleteGeometry <: Geometry
66+
graph::Graph
67+
size::Int64
68+
function CompleteGeometry(nQubits::Integer)
69+
graph = complete_graph(nQubits)
70+
new(graph, nQubits)
71+
end
72+
end
73+
```
74+
75+
By following these guidelines, you can create custom geometries that integrate seamlessly with the MonitoredQuantumCircuits.jl framework.

docs/src/interfaces/add_lattice.md

Lines changed: 0 additions & 38 deletions
This file was deleted.

docs/src/interfaces/add_operation.md

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,47 @@
11
# Operation Interface
2-
Adding custom operation to the MonitoredQuantumCircuits.jl framework is also possible. I can however be a bit tricky since you have to be familiar with every backend that should support your new operation.
32

4-
## The basics
5-
Independent of which backend you would like to support the operation, you need to implement a few functions. Firstly, you need to implement a type `MyOperation<:Operation` or `MyOperation<:MeasurementOperation` if your operation includes measurements. Next, there are some basic interfaces that the circuit construction logic relies on. Thus, please implement the following methods for your operation:
3+
It is possible to add custom operations to the MonitoredQuantumCircuits.jl framework. However, this process may require familiarity with each backend that should support your new operation.
64

7-
- `nQubits(::MyOperation)`
8-
- `isClifford(::MyOperation)`
9-
- `connectionGraph(::MyOperation)`
10-
- `plotPositions(::MyOperation)`
11-
- `color(::MyOperation)`
12-
- `isAncilla(::MyOperation, qubit::Integer)`
5+
## Basic Requirements
136

14-
## For each backend
15-
For each backend that should support this operation, implement the `apply!` method.
7+
Regardless of the backend, you must implement a few essential methods. Begin by defining a new type, either as a subtype of `Operation` or `MeasurementOperation` (if your operation involves measurements). The circuit construction logic relies on the following interface methods, which must be implemented for your operation:
8+
9+
- `nQubits(::MyOperation)`
10+
Specifies the number of qubits the operation acts upon.
11+
- `isClifford(::MyOperation)`
12+
Indicates whether the operation is a Clifford operation.
13+
14+
## Backend Integration
15+
16+
For each backend that should support your operation, you must implement the corresponding `apply!` method.
1617

1718
## Example
18-
Here is an example how one could implement the `Id` (identity) gate:
19+
20+
Below is an example implementation of the `Id` (identity) gate:
21+
1922
```julia
20-
import MonitoredQuantumCircuits: Operation, nQubits, isClifford, connectionGraph, plotPositions, color, isAncilla
21-
import MonitoredQuantumCircuits: Graphs
22-
import MonitoredQuantumCircuits: Qiskit
23-
import MonitoredQuantumCircuits: QuantumClifford
24-
import MonitoredQuantumCircuits: apply!
23+
import MonitoredQuantumCircuits: Operation, nQubits, isClifford
24+
import MonitoredQuantumCircuits: Qiskit, QuantumClifford, apply!
25+
2526
struct Id <: Operation end
2627

2728
nQubits(::Id) = 1
2829
isClifford(::Id) = true
29-
connectionGraph(::Id) = Graphs.path_graph(1)
30-
plotPositions(::Id) = [(0.0,0.0)]
31-
color(::Id) = "#FFFFFF"
32-
isAncilla(::Id, ::Integer) = false
3330

34-
function apply!(qc::Qiskit.QuantumCircuit, ::Id, pos::Integer)
35-
qc.id(pos - 1)
31+
# Qiskit backend implementation
32+
function apply!(qc::Qiskit.Circuit, ::Id, p, ::Integer)
33+
qc.id(p[1] - 1)
3634
end
37-
function apply!(qc::QuantumClifford.QC.Register, ::Id, pos::Integer)
38-
QuantumClifford.QC.apply!(qc, QuantumClifford.QC.sId1(p))
35+
36+
# QuantumClifford backend implementation
37+
function apply!(
38+
register::QuantumClifford.QC.Register,
39+
::QuantumClifford.TableauSimulator,
40+
::Id,
41+
p
42+
)
43+
QuantumClifford.QC.apply!(register, QuantumClifford.QC.sId1(p[1]))
3944
end
45+
```
4046

41-
```
47+
By following this approach, you can ensure that your custom operation integrates seamlessly with the MonitoredQuantumCircuits.jl framework and is supported across the desired backends.

docs/src/library/backends.md

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,35 @@
1-
Currently, there are the following backends:
2-
3-
- Quantum computer
4-
- `IBMBackend(name::String)`
5-
- Simulator
6-
- Qiskit Aer
7-
- `StateVectorSimulator()`
8-
- `GPUStateVectorSimulator()`
9-
- `CliffordSimulator()`
10-
- `GPUTensorNetworkSimulator()`
11-
- QuantumClifford
12-
- `TableauSimulator()`
13-
- `PauliFrameSimulator()`
14-
- `GPUPauliFrameSimulator()`
1+
## Backends
2+
3+
```@meta
4+
CurrentModule = MonitoredQuantumCircuits
5+
```
6+
7+
A **backend** is a computational engine responsible for executing quantum circuits. Backends may represent either actual quantum hardware or classical simulators. The backend executes the compiled circuit and returns the results for further analysis.
8+
9+
MonitoredQuantumCircuits.jl provides a range of built-in backends, encompassing both quantum computers and simulators. If you wish to integrate a custom backend, please refer to the [backend interface](/interfaces/add_backend.md) documentation.
10+
11+
### Available Backends
12+
13+
- **Quantum Computer**
14+
- `IBMBackend`
15+
16+
- **Simulators**
17+
- **Qiskit Aer**
18+
- `StateVectorSimulator`
19+
- `GPUStateVectorSimulator`
20+
- `CliffordSimulator`
21+
- `GPUTensorNetworkSimulator`
22+
- **QuantumClifford**
23+
- `TableauSimulator`
24+
- `PauliFrameSimulator`
25+
- `GPUPauliFrameSimulator`
26+
27+
### Selecting a Backend
28+
29+
Backends are organized into modules according to their origin. For example, backends provided by [Qiskit](/library/qiskit.md) reside in the `Qiskit` module, while those from [QuantumClifford](/library/quantum_clifford.md) are found in the `QuantumClifford` module. To instantiate a backend, prefix the constructor with the appropriate module name. For example, to create a state vector simulator using Qiskit:
30+
31+
```julia
32+
backend = Qiskit.StateVectorSimulator()
33+
```
34+
35+
For further details on backend capabilities and usage, consult the respective module documentation.

0 commit comments

Comments
 (0)