Skip to content

Commit

Permalink
Updated to qoqo beta.2 and fixed reported bugs (#22)
Browse files Browse the repository at this point in the history
* Reading through documentation

* Resolved changes

* Updated dependencies

* Fixed typos in the documentation

* Last parst of docu fixed

* Updated requirements file

* Changed transparent background in images and fixed typos
  • Loading branch information
kbarkhqs authored Aug 17, 2022
1 parent 1112428 commit f0122a2
Show file tree
Hide file tree
Showing 39 changed files with 203 additions and 192 deletions.
30 changes: 16 additions & 14 deletions documentation/src/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ All evaluating backends provide the same methods: `run_circuit()`, `run_measurem

### Example

In this subsection, an example is provided. A [QuantumProgram](hight-level/program.md) is created to be executed on the [qoqo_quest](https://github.com/HQSquantumsimulations/qoqo-quest) simulator backend. Here, all three options supported by an `EvaluatingBackend` are presented:
A [QuantumProgram](hight-level/program.md) is created to be executed on the [qoqo_quest](https://github.com/HQSquantumsimulations/qoqo-quest) simulator backend. Here, all three options supported by an `EvaluatingBackend` are presented:

* to run a single circuit,
* to run a measurement, and
Expand All @@ -42,7 +42,7 @@ from qoqo import Circuit
from qoqo import operations as ops
from qoqo.measurements import PauliZProduct, PauliZProductInput
from qoqo import QuantumProgram
from qoqo_quest import SimulatorBackend
from qoqo_quest import Backend
# initialize |psi>
init_circuit = Circuit()
# Apply a RotateY gate with a symbolic angle
Expand Down Expand Up @@ -82,23 +82,23 @@ measurement = PauliZProduct(
# a single circuit, a measurement, and a quantum program.

# Create a backend simulating one qubit
backend = SimulatorBackend(1)
backend = Backend(1)

# a) Run a single circuit
(bit_registers, float_registers, complex_registers) = backend.run_circuit(z_circuit)

# b) To run a measurement we need to replace the free parameter by hand
executable_measurement = measurement.substitute_parameters({"angle": 0.2})
expecation_values = backend.run_measurement(executable_measurement)
print(expecation_values)
expectation_values = backend.run_measurement(executable_measurement)
print(expectation_values)

# c) Run a quantum program
# The QuantumProgram now has one free parameter that must be set when executing it.
# The symbolic value "angle" in the circuits will be replaced by that free parameter
# during execution.
program = QuantumProgram(measurement=measurement, input_parameter_names=["angle"])
# Run the program with 0.1 substituting `angle`
expecation_values = program.run(backend, [0.1])
expectation_values = program.run(backend, [0.1])
```

In Rust:
Expand Down Expand Up @@ -144,7 +144,7 @@ let x_basis_index = measurement_input.add_pauliz_product("ro_x".to_string(), vec
let mut linear: HashMap<usize, f64> = HashMap::new();
linear.insert(x_basis_index, 0.1);
linear.insert(z_basis_index, 0.2);
measurement_input.add_linear_exp_val("<H>".to_string(), linear);
measurement_input.add_linear_exp_val("<H>".to_string(), linear).unwrap();

let measurement = PauliZProduct{
constant_circuit: Some(init_circuit),
Expand All @@ -159,23 +159,25 @@ let measurement = PauliZProduct{
let backend = Backend::new(1);

// a) Run a single circuit
let (bit_registers, float_registers, complex_registers) = backend.run_circuit(&z_circuit).unwrap();
let (_bit_registers, _float_registers, _complex_registers) = backend.run_circuit(&z_circuit).unwrap();

// b) To run a measurement we need to replace the free parameter by hand
let executable_measurement = measurement.substitute_parameters(HashMap::from([("angle".to_string(), 0.2)])).unwrap();
let expecation_values = backend.run_measurement(&executable_measurement).unwrap();
println!("{:?}", expecation_values);
let expectation_values = backend.run_measurement(&executable_measurement).unwrap();
println!("{:?}", expectation_values);

// c) Run a quantum program
// The QuantumProgram now has one free parameter that must be set when executing it.
// The symbolic value "angle" in the circuits will be replaced by that free parameter
// during execution.
let program = QuantumProgram::PauliZProduct{ measurement, input_parameter_names: vec!["angle".to_string()]};
// Run the program with 0.1 substituting `angle`
let expecation_values = program.run(backend, &[0.1]).unwrap();
let expectation_values = program.run(backend, &[0.1]).unwrap();
println!("{:?}", expectation_values);
```

## Translating to other frameworks
## Translating to other quantum computing frameworks

Backends that translate qoqo/roqoqo objects (for example Circuits) to other frameworks or representations do not implement the `EvaluatingBackend`.
At the moment a backend to translate qoqo/roqoqo `Circuits` to qasm is implemented: [qoqo_qasm](https://github.com/HQSquantumsimulations/qoqo_qasm).
There are many open- and closed-source quantum frameworks. For some use cases, it may be advantageous to interface between qoqo and another quantum computing framework. Depending on the target framework, circuits containing an available subset of qoqo operations can be translated to other frameworks by backends. Backends that translate qoqo/roqoqo objects (for example Circuits) to other frameworks or representations do not implement the `EvaluatingBackend`.

At the moment, we have implemented one translating backend, from qoqo/roqoqo `Circuits` to qasm: [qoqo_qasm](https://github.com/HQSquantumsimulations/qoqo_qasm).
4 changes: 2 additions & 2 deletions documentation/src/circuits/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ from qoqo import operations as ops
# create a new circuit
circuit = Circuit()
# Define the readout for two qubits
circuit += ops.DefinitionBit(readout="ro", length=2, is_output=True)
circuit += ops.DefinitionBit(name="ro", length=2, is_output=True)
# Rotation around Z axis by pi/2 on qubit 0
circuit += ops.RotateZ(qubit=0, theta=1.57)
# Entangling qubits 0 and 1 with CNOT gate
Expand Down Expand Up @@ -50,4 +50,4 @@ circuit += MeasureQubit::new(0, "ro".to_string(), 0);
circuit += MeasureQubit::new(1, "ro".to_string(), 1);
```

For details on the **available methods** of a `Circuit` please refer to the **API documentation** of [roqoqo](https://docs.rs/roqoqo/latest/roqoqo/struct.Circuit.html) and [qoqo](https://qoqo.readthedocs.io/en/latest/generated/generated/qoqo.Circuit.html).
For details on the **available methods** of a `Circuit` please refer to the **API documentation** of [roqoqo](https://docs.rs/roqoqo/latest/roqoqo/struct.Circuit.html) and [qoqo](https://hqsquantumsimulations.github.io/qoqo/generated/qoqo.html#qoqo.Circuit).
18 changes: 9 additions & 9 deletions documentation/src/circuits/noise.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Noise Operations

qoqo/roqoqo enables the user to construct finely controlled noise models. Noise acting on the quantum computer is modeled as noise operations acting on individual qubits between unitary gates applied on the quantum computer.
qoqo/roqoqo enables the user to construct finely controlled noise models. Noise acting on the quantum computer is modeled as noise operations acting on individual qubits in between each unitary gate applied on the quantum computer.

The noise operations can be directly added to a quantum circuit and can be simulated by compatible backends. Since noise cannot be actively controlled on a quantum computer normally, the noise operations are defined as [Pragma](pragma.md) operations in qoqo/roqoqo. The strength of the noise is determined by defining a `gate_time` and a `rate`. The noise Pragma operation affects the system as a Lindblad type noise acting on the system with the rate `rate` for the time `gate_time`.

Expand Down Expand Up @@ -35,9 +35,9 @@ use roqoqo::operations;
let mut circuit = Circuit::new();
circuit += operations::CNOT::new(0,1);
// Adding dephasing noise acting on gate 0 with gate_time 1.0 and rate 1e-3
circuit += operations::PragmaDephasing::new(0, 1.0, 1e-3);
circuit += operations::PragmaDamping::new(1, 1.0, 2e-3);
circuit += operations::PragmaDepolarising::new(3, 1.0, 5e-3);
circuit += operations::PragmaDephasing::new(0, 1.0, 1e-3.into());
circuit += operations::PragmaDamping::new(1, 1.0, 2e-3.into());
circuit += operations::PragmaDepolarising::new(3, 1.0, 5e-3.into());
```

## Superoperator representation
Expand All @@ -46,7 +46,7 @@ All noise operations in qoqo/roqoqo provide a `superoperator()` method that retu
In the superoperator formalism, the density matrix of the system is rewritten as a vector in row-major form. Applying the noise to the quantum computer then corresponds to multiplying the vector with the superoperator matrix.
The superoperator matrix ignores the qubits the noise operation acts on to fit in the smallest possible matrix dimension.

For other methods available for noise operations see the API documentation of [roqoqo](https://docs.rs/roqoqo/latest/roqoqo/operations/index.html) and [qoqo](https://qoqo.readthedocs.io/en/latest/generated/generated/qoqo.operations.html#module-qoqo.operations).
For other methods available for noise operations see the API documentation of [roqoqo](https://docs.rs/roqoqo/latest/roqoqo/operations/index.html) and [qoqo](https://hqsquantumsimulations.github.io/qoqo/generated/generated/qoqo.operations.html).

## Noise operations

Expand All @@ -68,12 +68,12 @@ The most general noise can be modeled in qoqo by the PragmaGeneralNoise operatio
d & e & f \\\\
g & h & j \\\\
\end{pmatrix}
\\]
\\],

where the coefficients correspond to the following summands expanded from the first term of the non-coherent part of the Lindblad equation:
\\[
\frac{d}{dt}\rho = \sum_{i,j=0}^{2} M_{i,j} L_{i} \rho L_{j}^{\dagger} - \frac{1}{2} \{ L_{j}^{\dagger} L_i, \rho \}
\\]
\\],

with \\( L_0 = \sigma^{+} \\), \\( L_1 = \sigma^{-} \\) and \\( L_3 = \sigma_{z} \\).

Expand All @@ -86,11 +86,11 @@ qoqo/roqoqo also supports Pragma operations that lead to errors in the execution
### PragmaOverrotation

This operation applies a statistical overrotation to the next rotation gate in the circuit, which matches the name given in the `gate` parameter of `PragmaOverrotation` and the involved qubits provided in `qubits`. The applied overrotation corresponds to adding a random number to the rotation angle.
The random number is drawn from a normal distribution with mean `0` and standard deviation given by the input parameter `variance`, which is multiplied by the `amplitude` parameter.
The random number is drawn from a normal distribution with mean `0` and standard deviation whose variance is given by the input parameter `variance`, which is then multiplied by the `amplitude` parameter.

### PragmaBoostNoise

This operation boosts noise and overrotations in the circuit. The input parameter `noise_coefficient` defines the coefficient by which the noise is boosted, i.e. the number by which the `gate_time` is multiplied.
This operation boosts noise and overrotations in the circuit. The input parameter `noise_coefficient` defines the coefficient by which the noise is boosted, *i.e.* the number by which the `gate_time` is multiplied.

### PragmaSleep

Expand Down
4 changes: 2 additions & 2 deletions documentation/src/circuits/pragma.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ Pragma operations in qoqo/roqoqo are operations that are _not_ part of the set o

Pragma operations can be used to:

* Annotate a quantum circuit with additional information that is not necessary for execution (e.g `PragmaGlobalPhase`, `PragmaStartDecompositionBlock`)
* Annotate a quantum circuit with additional information that is not necessary for execution (e.g. `PragmaGlobalPhase`, `PragmaStartDecompositionBlock`)
* Apply operations that lead to a repeated execution of a circuit (`PragmaRepeatedMeasurement`, `PragmaSetNumberOfMeasurements`)
* Apply operations that are only available on specific hardware (e.g. `PragmaChangeDevice`, `PragmaSleep`)
* Apply operations that are only available on a simulator (e.g. `PragmaSetStateVector`, `PragmaGetStateVector`)
* Model noise ([see also](noise.md))
* Model error sources (`PragmaOverrotation`)

For a full list of available Pragma operations see the API documentation of [roqoqo](https://docs.rs/roqoqo/latest/roqoqo/operations/index.html)
and [qoqo](https://qoqo.readthedocs.io/en/latest/generated/generated/qoqo.operations.html#module-qoqo.operations).
and [qoqo](https://hqsquantumsimulations.github.io/qoqo/generated/generated/qoqo.operations.html).
2 changes: 1 addition & 1 deletion documentation/src/circuits/readout.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ circuit += ops.MeasureQubit(qubit=1, readout="bit_register", readout_index=1)
# Alternatively, define a Complex register to readout the state vector
circuit += ops.DefinitionComplex("complex_register", 3, is_output = False)
# Measure the state vector when running the circuit on a simulator
circuit += ops.PragmaGetStateVector("complex_register")
circuit += ops.PragmaGetStateVector("complex_register", None)
```

Setting up readouts in Rust:
Expand Down
24 changes: 15 additions & 9 deletions documentation/src/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,38 @@ This section gives a quick overview of some of the conventions used in qoqo/roqo
For the two basis states of a single qubit we define

\\[
\left\| 0 \right> = \left|\textrm{false} \right> = \left| \downarrow \right> = \begin{pmatrix}
\left\| 0 \right> = \left|\textrm{false} \right> = \left| \uparrow \right> = \begin{pmatrix}
1 \\\\
0
\end{pmatrix} \\\\
\\]
\\].

\\[
\left \|1 \right> = \left|\textrm{true} \right> = \left| \uparrow \right> = \begin{pmatrix}
\left \|1 \right> = \left|\textrm{true} \right> = \left| \downarrow \right> = \begin{pmatrix}
0 \\\\
1
\end{pmatrix} \\\\
\\]
\\].

Before any operations are applied in a circuit, a quantum computer is always assumed to be in the ground state (all qubits in state `|0>`).
Before any operations are applied in a circuit a quantum computer is always assumed to be in the zero state (all qubits in state `|0>`).

### Note

This convention implies that `|0>` is the **excited** state with respect to the `Z` Pauli operator and `|1>` is the **ground** state. This is in contract with the physical implementation of qubits, where `|0>` typically corresponds to the state with lower energy and damping will lead to the system relaxing from `|1>` to `|0>`.

This means that in this convention, when identifying the qubits with spins with respect to the `Z` operator, the system starts out in the highest energy case and damping leads to a heating effect where the system population shifts to higher energy spin states.

## Endianness

qoqo and roqoqo use little endian encoding, where the least significant qubit is at the smallest memory address (or at the lowest index in a vector and at the rightmost entry when writing the qubit state as a sequence of `0` and `1` like a binary number).
qoqo and roqoqo use little-endian encoding, where the least significant qubit is at the smallest memory address (or at the lowest index in a vector and at the rightmost entry when writing the qubit state as a sequence of `0` and `1` like a binary number).

For a two-qubit state space we write the states of the qubits in the following order:
\\[
\left|00 \right> = \textrm{state} 0 \\\\
\left|01 \right> = \textrm{state} 1 \\\\
\left|10 \right> = \textrm{state} 2 \\\\
\left|11 \right> = \textrm{state} 3 \\\\
\\]
\\].

## Operation order

Expand All @@ -55,7 +61,7 @@ For a two-qubit state space we write the states of the qubits in the following o
0 & 1 \\\\
1 & 0
\end{pmatrix}
\\]
\\].

## Qubit naming

Expand All @@ -72,5 +78,5 @@ When initializing two-qubit gates, the `control` is always the first argumemt an
Unitary operations in qoqo/roqoqo provide a `unitary_matrix()` method that returns the definition of the gate in matrix form. This definition ignores the qubits of the gate to fit in the smallest possible matrix dimension.

* For single-qubit gates, the created matrix always corresponds to `qubit=0` and has a 2x2-dimension.
* For two-qubit gates, the created matrix always corresponds to `control=1`, `target=0` and is a 4x4-dimensional matrix. This convention corresponds to the little endian encoding described above.
* For two-qubit gates, the created matrix always corresponds to `control=1`, `target=0` and is a 4x4-dimensional matrix. This convention corresponds to the little-endian encoding described above.
* For multi-qubit gates, the created matrix always corresponds to `qubits=[0..N]` where `N` is the number of qubits in the qubit vector of the multi-qubit gate.
6 changes: 3 additions & 3 deletions documentation/src/devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ Devices based on the roqoqo `Device` trait can be abstract devices or backend de

A typical example for abstract devices are linear chains of square lattices in which two-qubit gate operations are only available between neighboring qubits.

The noise model of the `Device` trait is based on the continuous time Lindblad equation:
The noise model of the `Device` trait is based on the continuous-time Lindblad equation:
\\[
\frac{d}{dt}\rho = \sum_{i,j=0}^{2} M_{i,j} L_{i} \rho L_{j}^{\dagger} - \frac{1}{2} \{ L_{j}^{\dagger} L_i \rho \},
\\]
\\],

with \\( L_0 = \sigma^{+}\\), \\( L_1 = \sigma^{-}\\) and \\(L_3 = \sigma^{z}\\).

It is defined by the decoherence rates `M` and the (pseudo) time needed to execute a quantum operation.
It is defined by the decoherence rates `M` and the (pseudo-)time needed to execute a quantum operation.

The matrix representation of the decoherence rates of the Lindblad equation can be obtained by calling the method `qubit_decoherence_rates()` of a device.

Expand Down
12 changes: 6 additions & 6 deletions documentation/src/gate_operations/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ A list of the gate operations available in qoqo and roqoqo with their mathematic
* \\( \sigma_x \\), \\( \sigma_y \\), \\( \sigma_z \\) are the Pauli matrices X, Y, Z
\\[
\sigma_x = \begin{pmatrix} 0 & 1 \\\\ 1 & 0 \end{pmatrix} := X, \quad \sigma_y = \begin{pmatrix} 0 & -i \\\\ i & 0 \end{pmatrix} := Y, \quad \sigma_z = \begin{pmatrix} 1 & 0 \\\\ 0 & -1 \end{pmatrix} := Z
\\]
\\].

## [Single-qubit gates](single_qubit_gates.md)

Expand All @@ -39,30 +39,30 @@ A list of the gate operations available in qoqo and roqoqo with their mathematic
| Gate | Short Description |
|---------|---------|
| Bogoliubov | The Bogoliubov DeGennes interaction gate. |
| CNOT | The controlled not gate, e.g. to entangle two qubits. |
| CNOT | The controlled not gate, *e.g.* to entangle two qubits. |
| ComplexPMInteraction | The complex hopping gate. |
| ControlledPauliY | The controlled PauliY gate. |
| ControlledPauliZ | The controlled PauliZ gate. |
| ControlledPhaseShift | The controlled phase shift gate. |
| Fsim | The fermionic qubit simulation gate. |
| FSwap | The fermionic SWAP gate. |
| GivensRotation | The Givens rotation interaction gate in big endian notation: \\(e^{-\mathrm{i} \theta (X_c Y_t - Y_c X_t)}\cdot e^{-i \phi Z_t/2} \\). |
| GivensRotationLittleEndian | The Givens rotation interaction gate in little endian notation: \\(e^{-\mathrm{i} \theta (X_c Y_t - Y_c X_t)}\cdot e^{-i \phi Z_c/2} \\). |
| GivensRotationLittleEndian | The Givens rotation interaction gate in little-endian notation: \\(e^{-\mathrm{i} \theta (X_c Y_t - Y_c X_t)}\cdot e^{-i \phi Z_c/2} \\). |
| InvSqrtISwap | The inverse square root of the ISwap gate. |
| ISwap | The complex swap gate. |
| MolmerSorensenXX | The fixed-phase MolmerSorensen XX gate. |
| MolmerSorensenXX | The fixed-phase Mølmer–Sørensen XX gate. |
| PhaseShiftedControlledZ | The phased-shifted controlled-Z gate. |
| PMInteraction | The transversal interaction gate. |
| Qsim | The qubit simulation gate. |
| SpinInteraction | The generalized, anisotropic XYZ Heisenberg interaction between spins. |
| SqrtISwap | The square root of the ISwap gate. |
| SWAP | The swap gate, to switch the positions of two qubits. |
| VariablesMSXX | The variable-angle MolmerSorensen XX gate. |
| VariablesMSXX | The variable-angle Mølmer–Sørensen XX gate. |
| XY | The XY gate. |

## [Multi-qubit gates](multi_qubit_gates.md)

| Gate | Short Description |
|---------|---------|
| MultiQubitMS | The Molmer-Sorensen gate between multiple qubits. |
| MultiQubitMS | The Mølmer–Sørensen gate between multiple qubits. |
| MultiQubitZZ | The multi-qubit PauliZ-product gate. |
Loading

0 comments on commit f0122a2

Please sign in to comment.