Some work here
This commit is contained in:
parent
d03c076c8e
commit
f5c7fe824d
|
@ -232,20 +232,20 @@ implemented in \lstinline{C} and are exported to python3 in the class
|
|||
\lstinline{RawGraphState}. This class has three main methods to implement the
|
||||
three classes of operations.
|
||||
|
||||
%\begin{description}
|
||||
% \item[\lstinline{RawGraphState.apply_C_L}]{This method
|
||||
% implements local clifford gates. It takes the qbit index and the index
|
||||
% of the local Clifford operator (ranging form $0$ to $23$).}
|
||||
% \item[\lstinline{RawGraphState.apply_CZ}]{Applies the $CZ$ gate to the
|
||||
% state. The first argument is the act-qbit, the second the control
|
||||
% qbit (note that this is just for consistency to the $CX$ gate).}
|
||||
% \item[\lstinline{RawGraphState.measure}]{Using this method one can
|
||||
% measure a qbit. It takes the qbit index as first argument and
|
||||
% a floating point (double precision) random number as second
|
||||
% argument. This random number is used to decide the measurement outcome
|
||||
% in non-deterministic measurements. This method returns either $1$ or $0$ as
|
||||
% a measurement result.}
|
||||
%\end{description}
|
||||
\begin{description}
|
||||
\item[\lstinline{RawGraphState.apply_C_L}]{This method
|
||||
implements local clifford gates. It takes the qbit index and the index
|
||||
of the local Clifford operator (ranging form $0$ to $23$).}
|
||||
\item[\lstinline{RawGraphState.apply_CZ}]{Applies the $CZ$ gate to the
|
||||
state. The first argument is the act-qbit, the second the control
|
||||
qbit (note that this is just for consistency to the $CX$ gate).}
|
||||
\item[\lstinline{RawGraphState.measure}]{Using this method one can
|
||||
measure a qbit. It takes the qbit index as first argument and
|
||||
a floating point (double precision) random number as second
|
||||
argument. This random number is used to decide the measurement outcome
|
||||
in non-deterministic measurements. This method returns either $1$ or $0$ as
|
||||
a measurement result.}
|
||||
\end{description}
|
||||
|
||||
Because this way of modifying the state is rather unconvenient and might lead to many
|
||||
errors the \lstinline{RawGraphState} is wrapped by the pure python class
|
||||
|
@ -253,7 +253,7 @@ errors the \lstinline{RawGraphState} is wrapped by the pure python class
|
|||
in \ref{ref:pyqcs_circuits} and provides the method \lstinline{GraphState.to_naive_state}
|
||||
to convert the graphical state to a dense vector state.
|
||||
|
||||
\subsubsection{Pure \lstinline{C} Implementation}
|
||||
\subsubsection{Pure C Implementation}
|
||||
|
||||
Because python tends to be rather slow and might not run on any architecture
|
||||
a pure \lstinline{C} implementation of the graphical simulator is also provided.
|
||||
|
@ -273,8 +273,162 @@ always done in three steps:
|
|||
|
||||
\subsection{Utilities}
|
||||
|
||||
TODO
|
||||
To make both using the simulators more convenient and to help with using them in
|
||||
as scientific or educational context several utilities have been written. This chapter
|
||||
explains some of them.
|
||||
|
||||
\subsubsection{Sampling and Circuit Generation}
|
||||
|
||||
The function \lstinline{pyqcs.sample} provides a simple way to sample from a state.
|
||||
Copies of the state are made when necessary and the results are returned
|
||||
in a \lstinline{collections.Counter} object. Several qbits can be sampled at once; they can be passed
|
||||
to the function either as an integer which will be interpreted as a bit mask and the
|
||||
least significant bit will be sampled first. When passing the qbits to sample as a list
|
||||
of integers the integers are interpreted as qbit indices and are measured in the order
|
||||
they appear.
|
||||
|
||||
If the keyword argument \lstinline{keep_states} is \lstinline{True} the sampling
|
||||
function will include the resulting states in the result. At the moment this works
|
||||
for dense vectors only. Checking for equality on graphical states has yet to be implemented
|
||||
but can be done in polynomial time \cite{dahlberg_ea2019}.
|
||||
|
||||
Writing circuits out by hand can be rather painful. The function \lstinline{pyqcs.list_to_circuit}
|
||||
Converts a list of circuits to a circuit. This is particularely helpful in combination
|
||||
with python's \lstinline{listcomp}:
|
||||
|
||||
\begin{lstlisting}
|
||||
circuit_H = list_to_circuit([H(i) for i in range(nqbits)])
|
||||
\end{lstlisting}
|
||||
|
||||
The module \lstinline{pyqcs.util.random_circuits} provides the method described in \ref{ref:performance}
|
||||
to generate random circuits for both graphical and dense vector simulation. Using the module
|
||||
\lstinline{pyqcs.util.random_graphs} one can generate random graphical states which is more performant
|
||||
than using random circuits.
|
||||
|
||||
\subsubsection{Exporting Circuits, Graphical States}
|
||||
|
||||
|
||||
\subsection{Performance}
|
||||
\label{ref:performance}
|
||||
|
||||
To test the performance and compare it to the dense vector simulator the python
|
||||
module is used. Although the pure \lstinline{C} implementation has potential
|
||||
for better performance the python module is better comparable to the dense
|
||||
vector simulator which is a python module as well.
|
||||
|
||||
For performance tests (and for tests against the dense vector simulator) random
|
||||
circuits are used. Length $m$ circuits are generated from the probability space
|
||||
|
||||
|
||||
\begin{equation}
|
||||
\Omega = \left(\{1, ..., 4n\} \otimes \{1, ..., n-1\} \otimes [0, 2\pi)\right)^{\otimes m}
|
||||
\end{equation}
|
||||
|
||||
with the uniform distribution. The continous part $[0, 2\pi)$ is unused when
|
||||
generating random circuits for the graphical simulator; when generating random
|
||||
circuits for dense vector simulations this is the argument $\phi$ of the
|
||||
$R_\phi$ gate.
|
||||
|
||||
For $m=1$ an outcome is mapped to a gate using
|
||||
|
||||
\begin{equation}
|
||||
\begin{aligned}
|
||||
F(i, k, x) = \left\{\begin{array}{cc} X(i - 1) & \mbox{, if } i \le n \\
|
||||
H(i - n - 1) & \mbox{, if } i \le 2n\\
|
||||
S(i - 2n - 1) & \mbox{, if } i \le 3n\\
|
||||
CZ(i - 3n - 1, k - 1) & \mbox{, if } k \le i - 3n - 1 \\
|
||||
CZ(i - 3n - 1, k) & \mbox{, if } k > i - 3n - 1\\
|
||||
\end{array}\right.
|
||||
.
|
||||
\end{aligned}
|
||||
\end{equation}
|
||||
|
||||
This method provides equal probability for $X, H, S$ and $CZ$ gate. For the
|
||||
dense vector simulator $S$ can be replaced by $R_\phi$ with the parameter $x$.
|
||||
|
||||
Using this method circuits are generated and applied both to graphical and
|
||||
dense vector states and the time required to execute the operations
|
||||
\cite{timeit} is measured. The resulting graph can be seen in
|
||||
\ref{fig:scaling_qbits_linear} and \ref{fig:scaling_qbits_log}. Note in both cases the length of the circuits
|
||||
have been scaled linearely with the amount of qbits and the measured time was
|
||||
divided by the number of qbits:
|
||||
|
||||
\begin{equation}
|
||||
\begin{aligned}
|
||||
L_{\mbox{circuit}} &= \alpha n \\
|
||||
T_{\mbox{rescaled}} &= \frac{T_{\mbox{execution}}(L_{\mbox{circuit}})}{n}\\
|
||||
\end{aligned}
|
||||
\end{equation}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{../performance/scaling_qbits_linear.png}
|
||||
\caption[Runtime Behaviour for Scaling Qbit Number]{Runtime Behaviour for Scaling Qbit Number}
|
||||
\label{fig:scaling_qbits_linear}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{../performance/scaling_qbits_log.png}
|
||||
\caption[Runtime Behaviour for Scaling Qbit Number (Logarithmic Scale)]{Runtime Behaviour for Scaling Qbit Number (Logarithmic Scale)}
|
||||
\label{fig:scaling_qbits_log}
|
||||
\end{figure}
|
||||
|
||||
The reason for this scaling will be clear later; one can observe that the
|
||||
performance of the graphical simulator increases in some cases with growing
|
||||
number of qbits when the circuit length is constant.
|
||||
|
||||
As described by \cite{andersbriegel2005} the graphical simulator is exponentially
|
||||
faster than the dense vector simulator. According to \cite{andersbriegel2005} it
|
||||
is considerably faster than a simulator using the straight forward approach simulating
|
||||
the stabilizer tableaux like CHP \cite{CHP}.
|
||||
|
||||
One should be aware that the gate execution time (the time required to apply a gate
|
||||
to the state) highly depends on the state it is applied to. For the dense vector
|
||||
simulator and CHP this is not true: Gate execution time is constant for all gates
|
||||
and states. Because the graphical simulator has to toggle neighbourhoods the
|
||||
gate execution time of the $CZ$ gate varies greatly. The plot \ref{fig:scaling_circuits_linear}
|
||||
shows the circuit execution time for two different numbers of qbits. One can observe three
|
||||
regimes:
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{../performance/regimes/scaling_circuits_linear.png}
|
||||
\caption[Circuit Execution Time for Scaling Circuit Length]{Circuit Execution Time for Scaling Circuit Length}
|
||||
\label{fig:scaling_circuits_linear}
|
||||
\end{figure}
|
||||
|
||||
\begin{description}
|
||||
\item[Low-Linear Regime] {Here the circuit execution time scales approximately linearely
|
||||
with the number of gates in the circuit (i.e. the $CZ$ gate execution time is approximately constant).
|
||||
}
|
||||
\item[Intermediate Regime]{The circuit execution time has a nonlinear dependence on the circuit length.}
|
||||
\item[High-Linear Regime]{This regime shows a linear dependence on the circuit length; the slope is
|
||||
higher than in the low-linear regime.}
|
||||
\end{description}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{../performance/regimes/graph_low_linear_regime.png}
|
||||
\caption[Typical Graphical State in the Low-Linear Regime]{Typical Graphical State in the Low-Linear Regime}
|
||||
\label{fig:graph_low_linear_regime}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{../performance/regimes/graph_high_linear_regime.png}
|
||||
\caption[Typical Graphical State in the High-Linear Regime]{Typical Graphical State in the High-Linear Regime}
|
||||
\label{fig:graph_high_linear_regime}
|
||||
\end{figure}
|
||||
|
||||
These two regimes can be explained when considering the graphical states that typical live in these
|
||||
regimes. With increased circuit length the amount of edges increases which makes toggling neighbourhoods
|
||||
harder. Two graphs from the low-linear and high-linear regime can be seen in \ref{fig:graph_low_linear_regime}
|
||||
and \ref{fig:graph_high_linear_regime}. The latter is hardly visible; this is due to the great amount of
|
||||
edges in this regime. Further these two regimes are only visibly for $n>30$ qbits so choosing smaller graphs is
|
||||
not possible.
|
||||
|
||||
Because states with more qbits reach the intermediate regime at higher circuit lengths it is important to
|
||||
account for this virtual performance boost when comparing with other simulation methods. This explains
|
||||
why the circuit length in \ref{fig:scaling_qbits_linear} had to be scaled with the qbit number.
|
||||
|
||||
TODO
|
||||
|
|
|
@ -166,3 +166,11 @@
|
|||
note={Unpublished Work}
|
||||
}
|
||||
|
||||
@online{
|
||||
timeit,
|
||||
title={timeit — Measure execution time of small code snippets},
|
||||
url={https://docs.python.org/3.5/library/timeit.html},
|
||||
urldate={13.03.2020},
|
||||
year=2020,
|
||||
note={https://docs.python.org/3.5/library/timeit.html}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user