Skip to content

Commit

Permalink
Read through the user documentation (#21)
Browse files Browse the repository at this point in the history
* Reading through documentation

* Resolved changes

* Updated dependencies
  • Loading branch information
kbarkhqs authored Aug 12, 2022
1 parent 3627a1f commit 1112428
Show file tree
Hide file tree
Showing 28 changed files with 136 additions and 139 deletions.
10 changes: 5 additions & 5 deletions documentation/src/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ Backends in qoqo/roqoqo are used for two things:

To obtain results based on a quantum program (or quantum circuit) defined in qoqo/roqoqo, the program must run on a simulator or real quantum computing hardware.

For an individual simulator or hardware a backend can be created that implements roqoqo's `EvaluatingBackend` trait and executes quantum circuits.
For an individual simulator or hardware, a backend can be created that implements roqoqo's `EvaluatingBackend` trait and executes quantum circuits.
The implementation of individual backends is provided not in qoqo itself, but in other packages.

At the moment the following evaluating backends are implemented for qoqo/roqoqo:
At the moment the following EvaluatingBackends are implemented for qoqo/roqoqo:

* [qoqo_aqt](https://github.com/HQSquantumsimulations/qoqo_aqt)
* [qoqo_mock](https://github.com/HQSquantumsimulations/qoqo_aqt)
Expand All @@ -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:
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:

* to run a single circuit,
* to run a measurement, and
Expand Down Expand Up @@ -97,7 +97,7 @@ print(expecation_values)
# 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`
# Run the program with 0.1 substituting `angle`
expecation_values = program.run(backend, [0.1])
```

Expand Down Expand Up @@ -171,7 +171,7 @@ println!("{:?}", expecation_values);
// 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`
// Run the program with 0.1 substituting `angle`
let expecation_values = program.run(backend, &[0.1]).unwrap();
```

Expand Down
12 changes: 6 additions & 6 deletions documentation/src/circuits/intro.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Quantum circuit

A quantum circuit refers to a linear sequence of operations that can be executed on a quantum computer. Like most quantum computing toolkits qoqo/roqoqo provides a `Circuit` object and a set of `Operations` that can be added to a `Circuit`.
A quantum circuit refers to a linear sequence of operations that can be executed on a quantum computer. Like most quantum computing toolkits, qoqo/roqoqo provides a `Circuit` object and a set of `Operations` that can be added to a `Circuit`.

qoqo/roqoqo distinguishes between:

* Definitions: Operations that declare (and initialize) classical register values ([see also here](readout.md) )
* Definitions: Operations that declare (and initialize) classical register values ([see also here](readout.md))
* Gate Operations: Unitary operations that can be executed on every unitary quantum computer (but might need to be decomposed into a sequence of native operations) ([see also here](unitary.md))
* Pargma operations that are not generally available on all universal quantum computers (see [pragma operations](pragma.md) and [noise operations](noise.md) )
* Pragma operations that are not generally available on all universal quantum computers (see [pragma operations](pragma.md) and [noise operations](noise.md) )

In order to create a useful result a Circuit in qoqo/roqoqo must contain:
In order to create a useful result, a Circuit in qoqo/roqoqo must contain:

* A definition of a classical register for readout
* Operations to change the state of the quantum computer, for example `RotateZ` or `CNOT` gate operations.
* A measurement to return classical information based on the state of the quantum computer.

With qoqo a `Circuit` can be constructed like this:
With qoqo, a `Circuit` can be constructed like this:

```python
from qoqo import Circuit
Expand All @@ -32,7 +32,7 @@ circuit += ops.MeasureQubit(qubit=0, readout="ro", readout_index=0)
circuit += ops.MeasureQubit(qubit=1, readout="ro", readout_index=1)
```

And with roqoqo like this:
And with roqoqo, like this:

```rust
use roqoqo::{Circuit, operations::*};
Expand Down
21 changes: 10 additions & 11 deletions documentation/src/circuits/noise.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ _Note_: as long as gate times and rates are scaled inversely any kind of units c

## Example

For example we can add dephasing noise to qubit 0, damping noise to qubit 1 and depolarising noise to qubit 2 after a `CNOT` gate has been applied.
For example we can add dephasing noise to qubit 0, damping noise to qubit 1, and depolarising noise to qubit 2 after a `CNOT` gate has been applied.

In Python:

Expand All @@ -19,7 +19,7 @@ from qoqo import operations

circuit = Circuit()
circuit += operations.CNOT(0,1)
#Adding dephasing noise acting on gate 0 with gate_time 1.0 and rate 1e-3
# Adding dephasing noise acting on gate 0 with gate_time 1.0 and rate 1e-3
circuit += operations.PragmaDephasing(qubit=0, gate_time=1.0, rate=1e-3)
circuit += operations.PragmaDamping(1, 1.0, 2e-3)
circuit += operations.PragmaDepolarising(3, 1.0, 5e-3)
Expand All @@ -43,25 +43,24 @@ circuit += operations::PragmaDepolarising::new(3, 1.0, 5e-3);
## Superoperator representation

All noise operations in qoqo/roqoqo provide a `superoperator()` method that returns the definition of the noise operation in superoperator matrix form.
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.
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://qoqo.readthedocs.io/en/latest/generated/generated/qoqo.operations.html#module-qoqo.operations).

## Noise operations

The single noise operations shown in the example above are:

* `PragmaDamping` that applies a pure damping error corresponding to _zero_ temperature environments.
* `PragmaDepolarising` which applies a depolarising noise.
* `PragmaDephasing` representing a pure dephasing noise.
* `PragmaDamping`, which applies a pure damping error corresponding to _zero_ temperature environments.
* `PragmaDepolarising`, which applies a depolarising noise.
* `PragmaDephasing`, which applies a pure dephasing noise.

For a stochastically unravelled combination of dephasing and depolarising the user can choose to use the `PragmaRandomNoise`. The error rate of the depolaristion (`depolarising_rate`) and the error rate of the dephasing (`dephasing_rate`) are provided as input parameters for this random noise operation.
For a stochastically unravelled combination of dephasing and depolarising, the user can choose to use the `PragmaRandomNoise`. The error rate of the depolaristion (`depolarising_rate`) and the error rate of the dephasing (`dephasing_rate`) are provided as input parameters for this random noise operation.

### PragmaGeneralNoise

The most general noise can be modelled in qoqo by the PragmaGeneralNoise operation. This Pragma operation applies a noise term according to the given rates. The rates are represented by a 3x3 matrix:
The most general noise can be modeled in qoqo by the PragmaGeneralNoise operation. This Pragma operation applies a noise term according to the given rates. The rates are represented by a 3x3 matrix:

\\[
M = \begin{pmatrix}
Expand All @@ -87,7 +86,7 @@ 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` that is multiplied by the `amplitude` parameter.
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.

### PragmaBoostNoise

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 @@ -6,8 +6,8 @@ Pragma operations can be used to:

* 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`)
* Appy operations that are only available on specific hardware (e.g. `PragmaChangeDevice`, `PragmaSleep`)
* Apply operations that are only available on simulator (e.g. `PragmaSetStateVector`, `PragmaGetStateVector`)
* 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`)

Expand Down
16 changes: 8 additions & 8 deletions documentation/src/circuits/readout.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Readout

To obtain results from running a quantum circuit the quantum computer needs to return classical information.
qoqo/roqoqo uses register based readouts where all classical information is returned from the quantum circuit using classical registers declared at the start of the circuit.
To obtain results from running a quantum circuit, the quantum computer needs to return classical information.
qoqo/roqoqo uses register-based readouts where all classical information is returned from the quantum circuit using classical registers declared at the start of the circuit.
Classical registers can contain three types of classical data:

* Bit (or bool)
* Float (f64/double)
* Complex.

Each register is declared in a `Circuit` with a Pragma operation setting the register name and a length. The Pragma operation also declares whether the register is an output or not.
Each register is declared in a `Circuit` by a Pragma operation setting the register name and a length. The Pragma operation also declares whether the register is an output or not.
After being declared at the start of the circuit, information is written to the registers in the `Circuit` by `Measurement` or `Pragma` operations.
If the register is declared as an output register it is returned after the execution of the circuit.
If the register is declared as an output register, it is returned after the execution of the circuit.

A python example:

Expand Down Expand Up @@ -51,12 +51,12 @@ Information is written to registers by the `MeasureQubit` operation or Pragma op
* On quantum computing _hardware_ only _projective_ measurements into a bit register are available, that is a measurement in the `Z`-basis yielding `0` or `1`.
* On _simulators_ one can also read out the full state vector or density matrix into a complex register.

`MeasureQubit` corresponds directly to a _projectivce_ measurement. By definition projective measurements are available on universal quantum computers.
`PragmaRepeatedMeasurement` is shorthand for repeatedly running the circuit and apply a projective measurement each time. While it is not necessarily available on every [backend](backends.md) it is compatible with hardware quantum computers.
`MeasureQubit` corresponds directly to a _projectivce_ measurement. By definition, projective measurements are available on universal quantum computers.
`PragmaRepeatedMeasurement` is shorthand for repeatedly running the circuit and applying a projective measurement each time. While it is not necessarily available on every [backend](backends.md) it is compatible with hardware quantum computers.

As shown in the example below, the operation `MeasureQubit` can be used to provide measurement instructions for each individual qubit. The input parameter `qubit` specifies the qubit to be measured, whereas the parameter `readout_index` defines the position in the classical register `readout` where the measurement value of the `qubit` is stored. The explicit assignment of a qubit measurement to a readout register index can be used to handle qubit remapping in a quantum circuit.
As shown in the example below, the operation `MeasureQubit` can be used to provide measurement instructions for each individual qubit. The input parameter `qubit` specifies the qubit to be measured, whereas the parameter `readout_index` defines the position in the classical register `readout` where the measurement value of the `qubit` is stored. The explicit assignment of a qubit measurement to a readout register index can be used to handle qubit remapping in a quantum circuit.

When supported by the backend, `PragmaRepeatedMeasurement` can be used instead of `MeasureQubit` command to provide the measurement instruction for all qubits in `qubit_mapping` that needs to be repeated N times (`number_measurements`). For further available Pragma measurement instructions please refer to the section [Pragma operations](pragma.md).
When supported by the backend, `PragmaRepeatedMeasurement` can be used instead of `MeasureQubit` command to provide the measurement instruction for all qubits in `qubit_mapping` that needs to be repeated N times (`number_measurements`). For further available Pragma measurement instructions, please refer to the section [Pragma operations](pragma.md).

Setting up readouts in Python:

Expand Down
6 changes: 3 additions & 3 deletions documentation/src/circuits/unitary.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Unitary operations or gate operations are operations that can be executed on all

Gate operations in qoqo/roqoqo provide a `unitary_matrix()` method that returns the definition of the gate in matrix form. This definition ignores the qubits the gates acts on to fit in the smallest possible matrix dimension.

* For single-qubit gates the created matrix always corresponds to `qubit=0` and has dimension 2x2.
* For two-qubit gates the created matrix always corresponds to `control=1`, `target=0` and has dimension a 4x4. See also the state ordering [conventions](../conventions.md).
* 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.
* For single-qubit gates, the created matrix always corresponds to `qubit=0` and has dimension 2x2.
* For two-qubit gates, the created matrix always corresponds to `control=1`, `target=0` and has dimension a 4x4. See also the state ordering [conventions](../conventions.md).
* 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.

For a list of unitary operations see [gate operations](../gate_operations/intro.md).
22 changes: 11 additions & 11 deletions documentation/src/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This section gives a quick overview of some of the conventions used in qoqo/roqo

## Definitions

* `operation`: An atomic instruction applied to a quantum computer (or simulated quantum computer)
* `operation`: An atomic instruction applied to a quantum computer (or simulated quantum computer).
* `gate`: An `operation` that corresponds to a unitary transformation of the state of the quantum computer and can be implemented on all universal quantum computers.
* `qubit`: A quantum bit. Can be in a superposition of two basis states.
* `Circuit`: A linear sequence of `operations`.
Expand All @@ -27,11 +27,11 @@ For the two basis states of a single qubit we define
\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 ground state (all qubits in state `|0>`).

## Endianness

qoqo and roqoqo use little endian encoding, 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:
\\[
Expand All @@ -43,7 +43,7 @@ For a two-qubit state space we write the states of the qubits in the following o

## Operation order

When adding qoqo/roqoqo operations to circuits, the first operation added will be executed first. When writing qoqo/roqoqo operations, they are read left to right. This leads to an inversion of the order when transcribing to matrix form where the matrix to the right acts first.
When adding qoqo/roqoqo operations to circuits, the first operation added will be executed first. When writing qoqo/roqoqo operations, they are read left to right. This leads to an inversion of the order when transcribing to matrix form, where the matrix to the right acts first.

\\[
\textrm{PauliX}(0) \cdot \textrm{PauliZ}(0) \\\\ =
Expand All @@ -61,16 +61,16 @@ For a two-qubit state space we write the states of the qubits in the following o

qoqo uses a unified naming scheme for qubits in operations

* In single-qubit operations the qubit is always referred to as `qubit`,
* In two-qubit gates the two qubits are referred to as `control` and `target`,
* In multi-qubit gates the ordered list/ vector of qubits the gates acts on is reffered to as `qubits`.
* In single-qubit operations, the qubit is always referred to as `qubit`,
* In two-qubit gates, the two qubits are referred to as `control` and `target`,
* In multi-qubit gates, the ordered list/vector of qubits the gates acts on is referred to as `qubits`.

When initializing two-qubit gates, the `control` is always the first and `target` the second argument.
When initializing two-qubit gates, the `control` is always the first argumemt and `target` the second argument.

## Unitary Matrix

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 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.
* 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 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.
Loading

0 comments on commit 1112428

Please sign in to comment.