Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions examples/QIR/Simulation/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Building a Simulator for QIR

**NOTE:** The text below is out-of-date and is to be rewritten. See more up-to-date information in the PR ["Replace C++ QIR Runtime with Rust QIR stdlib"](https://github.com/microsoft/qsharp-runtime/pull/1087).

This example discusses the structure of the QIR Runtime system and how to attach a simulator to it using two sample simulators implemented "from scratch":

- a state-less [trace simulator](TraceSimulator): prints each quantum instructions it receives, useful for debugging or simple hardware backend hookup
Expand Down Expand Up @@ -39,16 +41,16 @@ In order to communicate with the QIR Runtime, hardware backends or simulators ca
- the gate set `IQuantumGateSet` : only used by those backends that want to provide the Q# instruction set
- the diagnostics `IDiagnostics` : optional but helpful component to provide debug information of the backend state

The first component of the Runtime stack is the QIR Bridge at [public/QirRuntime.hpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/public/QirRuntime.hpp) which declares the functions for the runtime as `extern "C"`.
Different parts of the QIR spec are then implemented in C++ in the [lib/QIR](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime/lib/QIR) folder.
For example, the `__quantum__rt__string_create` function resides in [lib/QIR/strings.cpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/lib/QIR/strings.cpp).
For functions defined in [lib/QIR/delegated.cpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/lib/QIR/delegated.cpp) such as `__quantum__rt__qubit_allocate`, the Runtime eventually calls the implementation `IRuntimeDriver::Allocate` provided by the backend.
The first component of the Runtime stack is the QIR Bridge at "public/QirRuntime.hpp" which declares the functions for the runtime as `extern "C"`.
Different parts of the QIR spec are then implemented in C++ in the "lib/QIR" folder.
For example, the `__quantum__rt__string_create` function resides in "lib/QIR/strings.cpp".
For functions defined in "lib/QIR/delegated.cpp" such as `__quantum__rt__qubit_allocate`, the Runtime eventually calls the implementation `IRuntimeDriver::Allocate` provided by the backend.

Other components are provided for Q# programs compiled to QIR in [lib/QSharpCore](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime/lib/QSharpCore) and [lib/QSharpFoundation](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime/lib/QSharpFoundation).
Other components are provided for Q# programs compiled to QIR in "lib/QSharpCore" and "lib/QSharpFoundation".
In particular, the `QSharpCore` component provides the Q# instruction set.
As above, a bridge [lib/QSharpCore/qsharp__core__qis.hpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/lib/QSharpCore/qsharp__core__qis.hpp) first declares a function such as `__quantum__qis__h__body` as `extern "C"`, which is then implemented in [lib/QSharpCore/intrinsics.cpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/lib/QSharpCore/intrinsics.cpp), which then calls the specific implementation `IQuantumGateSet::H` provided by the backend.
As above, a bridge "lib/QSharpCore/qsharp__core__qis.hpp" first declares a function such as `__quantum__qis__h__body` as `extern "C"`, which is then implemented in "lib/QSharpCore/intrinsics.cpp", which then calls the specific implementation `IQuantumGateSet::H` provided by the backend.

A qubit manager (see next section) is also provided in [lib/QIR/QubitManager.cpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/lib/QIR/QubitManager.cpp).
A qubit manager (see next section) is also provided in "lib/QIR/QubitManager.cpp".

## Qubit Management

Expand All @@ -70,14 +72,14 @@ Similarly, it's possible to present a virtual qubit space to a program that is l
Further, the number of available logical qubits may change throughout the operation of a quantum computer (e.g. due to certain physical qubits becoming unusable), which needs to be handled.
Deciding which logical qubit to assign to which virtual qubit, and when and how to reuse logical qubits, is the task of the *qubit manager*.

Note: Instead of implementing your own qubit manager you should use the one provided by the Runtime at [public/QubitManager.hpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/public/QubitManager.hpp).
Note: Instead of implementing your own qubit manager you should use the one provided by the Runtime at "public/QubitManager.hpp".

## Structure of a Simulator

As mentioned further up, the QIR Runtime provides three interfaces to connect backends to the Runtime:

- `IRuntimeDriver` : Basic runtime functions such as qubit and measurement result management.
- `IQuantumGateSet` : The Q# instruction set. Implementation of this interface is not strictly required, as long as some instruction set is implemented, and the QIR code only calls instructions from that set (may necessitate the use of a bridge, see the [QIR Bridge](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime#qir-bridge-and-runtime) and [previous section](#understanding-the-qir-runtime-system)).
- `IQuantumGateSet` : The Q# instruction set. Implementation of this interface is not strictly required, as long as some instruction set is implemented, and the QIR code only calls instructions from that set (may necessitate the use of a bridge, see the "QIR Bridge" and [previous section](#understanding-the-qir-runtime-system)).
- `IDiagnostics` : Optional interface to provide insight into the state of a simulator or hardware backend (useful for debugging).

Let's have a look at the functionality each interface provides.
Expand Down
10 changes: 6 additions & 4 deletions examples/QIR/Simulation/StateSimulator/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# The State Simulator

**NOTE:** The text below is out-of-date and is to be rewritten. See more up-to-date information in the PR ["Replace C++ QIR Runtime with Rust QIR stdlib"](https://github.com/microsoft/qsharp-runtime/pull/1087).

A full state simulator mimics an ideal quantum computer with infinite compute register, although classical hardware limitations generally impose a simulation limit of at most a few dozen active qubits.
This sample provides a "from scratch" implementation of such a simulator, using the C++ linear algebra library [Eigen](http://eigen.tuxfamily.org/).
The simulator is designed to closely correspond to the mathematical operations which are typically used to describe quantum circuits.
Expand All @@ -10,7 +12,7 @@ Instead of using a custom qubit manager, the sample demonstrates how to hook up
The QIR Runtime provides three interfaces to connect backends to the Runtime, which will be implemented by the simulator:

- `IRuntimeDriver` : Provides basic runtime functions such as qubit and measurement result management.
- `IQuantumGateSet` : The Q# instruction set. Implementation of this interface is not strictly required, as long as *some* instruction set is implemented, and the QIR code only calls instructions from that set (may necessitate the use of a bridge, see the [QIR Bridge](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime#qir-bridge-and-runtime) and the [top-level guide](../#understanding-the-qir-runtime-system)).
- `IQuantumGateSet` : The Q# instruction set. Implementation of this interface is not strictly required, as long as *some* instruction set is implemented, and the QIR code only calls instructions from that set (may necessitate the use of a bridge, see the "QIR Bridge").
- `IDiagnostics` : Optional interface to provide insight into the state of a simulator or hardware backend (useful for debugging).

For a more detailed look at them, refer to the [top-level guide](../#structure-of-a-simulator) of the simulation example.
Expand Down Expand Up @@ -92,7 +94,7 @@ A new qubit manager instance can simply be attached to the simulator in the cons
}
```

The following functions will be used from the QIR qubit manager, but additional functionality is present to manage how qubits are reused (full interface at [public/QubitManager.hpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/public/QubitManager.hpp)):
The following functions will be used from the QIR qubit manager, but additional functionality is present to manage how qubits are reused (full interface at "public/QubitManager.hpp"):

```cpp
Qubit CQubitManager::Allocate()
Expand Down Expand Up @@ -126,7 +128,7 @@ void StateSimulator::ReleaseQubit(Qubit q)
}
```

Result management hands out either of two `Result` values, where the `Result` type is defined as a pointer to an undefined type in [CoreTypes.hpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/public/CoreTypes.hpp), allowing for backends to define custom result types.
Result management hands out either of two `Result` values, where the `Result` type is defined as a pointer to an undefined type in "CoreTypes.hpp", allowing for backends to define custom result types.
Here, we use the raw pointer type with different numeric values for each result:

```cpp
Expand Down Expand Up @@ -326,7 +328,7 @@ Refer to the [Optimization example](../../Optimization#installing-clang) for ins

Download the latest stable release of the [Eigen library](http://eigen.tuxfamily.org/) and copy over the relevant headers as described in [include/Eigen](include/Eigen/README.md).

Although the [QIR Runtime header files](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime/public) are sufficient to compile the simulator, actually running it will require the Runtime binaries.
Although the "QIR Runtime header files" are sufficient to compile the simulator, actually running it will require the Runtime binaries.
Use the NuGet CLI with the commands below to download the [QIR Runtime package](https://www.nuget.org/packages/Microsoft.Quantum.Qir.Runtime) and extract the appropriate headers and libraries (adjusting the package version as required):

- **Windows**:
Expand Down
12 changes: 7 additions & 5 deletions examples/QIR/Simulation/TraceSimulator/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# The Trace Simulator

**NOTE:** The text below is out-of-date and is to be rewritten. See more up-to-date information in the PR ["Replace C++ QIR Runtime with Rust QIR stdlib"](https://github.com/microsoft/qsharp-runtime/pull/1087).

A trace simulator is a quick way to provide a backend to the QIR Runtime system.
It's function is to print out all quantum instructions it receives.
While this can useful for debugging, it is also a simple way to connect QIR to hardware backends that do not support control flow.
Expand All @@ -12,7 +14,7 @@ This sample provides a "from scratch" implementation of a trace simulator, inclu
The QIR Runtime provides three interfaces to connect backends to the Runtime:

- `IRuntimeDriver` : Provides basic runtime functions such as qubit and measurement result management.
- `IQuantumGateSet` : The Q# instruction set. Implementation of this interface is not strictly required, as long as *some* instruction set is implemented, and the QIR code only calls instructions from that set (may necessitate the use of a bridge, see the [QIR Bridge](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime#qir-bridge-and-runtime) and the [top-level guide](../#understanding-the-qir-runtime-system)).
- `IQuantumGateSet` : The Q# instruction set. Implementation of this interface is not strictly required, as long as *some* instruction set is implemented, and the QIR code only calls instructions from that set (may necessitate the use of a bridge, see the "QIR Bridge" and the [top-level guide](../#understanding-the-qir-runtime-system)).
- `IDiagnostics` : Optional interface to provide insight into the state of a simulator or hardware backend (useful for debugging).

For a more detailed look at these interfaces, refer to the [top-level guide](../#structure-of-a-simulator) of the simulation example.
Expand Down Expand Up @@ -67,7 +69,7 @@ std::string GetQubitName(Qubit qubit)
```

The qubit ID is a simple perpetually increasing counter, so no IDs are ever reused (careful with overflow!).
The `Qubit` object itself is just a pointer (as defined in [CoreTypes.hpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/public/CoreTypes.hpp)) with the qubit ID as its value:
The `Qubit` object itself is just a pointer (as defined in "CoreTypes.hpp") with the qubit ID as its value:

```cpp
class QubitManager
Expand Down Expand Up @@ -101,7 +103,7 @@ The qubit manager provided by the Runtime for example provides configurable qubi

Implementation of the `IRuntimeDriver` interface is straightforward.
Qubit management is delegated to the respective `QubitManager` functions, while result management compares or hands out either of two `Result` values.
The `Result` type is defined as a pointer to an undefined type in [CoreTypes.hpp](https://github.com/microsoft/qsharp-runtime/blob/main/src/Qir/Runtime/public/CoreTypes.hpp), allowing for backends to define custom result types.
The `Result` type is defined as a pointer to an undefined type in "CoreTypes.hpp", allowing for backends to define custom result types.
Here, we use the raw pointer type with different numeric values for each result:

```cpp
Expand All @@ -120,7 +122,7 @@ bool TraceSimulator::AreEqualResults(Result r1, Result r2)
```

Such a straight-line code restriction is not a requirement for trace simulators, but it works well with the type of hardware currently available (when using the trace simulator in that context).
For a much more complete trace simulator that is also used for resource estimation, see the [QIR Runtime trace simulator](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime/lib/Tracer).
For a much more complete trace simulator that is also used for resource estimation, see the "QIR Runtime trace simulator".

---

Expand Down Expand Up @@ -180,7 +182,7 @@ Measuring qubits:
The simulator samples require a working [Clang](https://clang.llvm.org/) installation to compile.
Refer to the [Optimization example](../../Optimization#installing-clang) for instructions on setting up Clang and LLVM.

Although the [QIR Runtime header files](https://github.com/microsoft/qsharp-runtime/tree/main/src/Qir/Runtime/public) are sufficient to compile the simulator, actually running it will require the Runtime binaries.
Although the "QIR Runtime header files" are sufficient to compile the simulator, actually running it will require the Runtime binaries.
Use the NuGet CLI with the commands below to download the [QIR Runtime package](https://www.nuget.org/packages/Microsoft.Quantum.Qir.Runtime) and extract the appropriate headers and libraries (adjusting the package version as required):

- **Windows**:
Expand Down