some work

This commit is contained in:
Daniel Knüttel 2020-03-16 12:59:37 +01:00
parent ba500e334e
commit edaa8ac4a4

View File

@ -64,7 +64,7 @@ in Python.
The logic of gates is usually easy to implement using the integer basis. The The logic of gates is usually easy to implement using the integer basis. The
example below implements the Hadamard gate \ref{ref:singleqbitgates}: example below implements the Hadamard gate \ref{ref:singleqbitgates}:
\adjustbox{max width=\textwidth}{\lstinputlisting[language=C, firstline=153, lastline=178]{../pyqcs/src/pyqcs/gates/implementations/basic_gates.c}} \lstinputlisting[title={Implementation of the Hadamard Gate in C}, language=C, firstline=153, lastline=178, breaklines=true]{../pyqcs/src/pyqcs/gates/implementations/basic_gates.c}
A basic set of gates is implemented in PyQCS: A basic set of gates is implemented in PyQCS:
@ -103,8 +103,7 @@ circuits and can be constructing using the built-in generators. The generators
take the act-qbit as first argument, parameters such as the control qbit or an take the act-qbit as first argument, parameters such as the control qbit or an
angle as second argument: angle as second argument:
%\adjustbox{max width=\textwidth}{ \begin{lstlisting}[language=Python, breaklines=true, caption={Using Single Gate Circuits}]
\begin{lstlisting}[language=Python]
In [1]: from pyqcs import CX, CZ, H, R, Z, X In [1]: from pyqcs import CX, CZ, H, R, Z, X
...: from pyqcs import State ...: from pyqcs import State
...: ...:
@ -114,9 +113,9 @@ In [1]: from pyqcs import CX, CZ, H, R, Z, X
...: bell_state = CX(1, 0) * intermediate_state ...: bell_state = CX(1, 0) * intermediate_state
In [2]: bell_state In [2]: bell_state
Out[2]: (0.7071067811865476+0j)*|0b0> + (0.7071067811865476+0j)*|0b11> Out[2]: (0.7071067811865476+0j)*|0b0>
+ (0.7071067811865476+0j)*|0b11>
\end{lstlisting} \end{lstlisting}
%}
Large circuits can be constructed using the binary OR operator \lstinline{|} in Large circuits can be constructed using the binary OR operator \lstinline{|} in
an analogy to the pipeline operator on many *NIX systems. As usual circuits are an analogy to the pipeline operator on many *NIX systems. As usual circuits are
@ -124,7 +123,7 @@ read from left to right similar to pipelines on *NIX systems:
%\adjustbox{max width=\textwidth}{ %\adjustbox{max width=\textwidth}{
\begin{lstlisting}[language=Python] \begin{lstlisting}[language=Python, breaklines=true, caption={Constructing Circuits Using \lstinline{|}}]
In [1]: from pyqcs import CX, CZ, H, R, Z, X In [1]: from pyqcs import CX, CZ, H, R, Z, X
...: from pyqcs import State ...: from pyqcs import State
...: ...:
@ -137,7 +136,8 @@ In [1]: from pyqcs import CX, CZ, H, R, Z, X
...: bell_state = circuit * state ...: bell_state = circuit * state
In [2]: bell_state In [2]: bell_state
Out[2]: (0.7071067811865477+0j)*|0b0> + (0.7071067811865477+0j)*|0b11> Out[2]: (0.7071067811865477+0j)*|0b0>
+ (0.7071067811865477+0j)*|0b11>
\end{lstlisting} \end{lstlisting}
%} %}
@ -145,7 +145,7 @@ A quick way to generate circuits programatically is to use the \lstinline{list_t
function: function:
%\adjustbox{max width=\textwidth}{ %\adjustbox{max width=\textwidth}{
\begin{lstlisting}[language=Python] \begin{lstlisting}[language=Python, breaklines=true, caption={Constructing Circuits Using Python Lists}]
In [1]: from pyqcs import CX, CZ, H, R, Z, X In [1]: from pyqcs import CX, CZ, H, R, Z, X
...: from pyqcs import State, list_to_circuit ...: from pyqcs import State, list_to_circuit
...: ...:
@ -154,7 +154,8 @@ In [1]: from pyqcs import CX, CZ, H, R, Z, X
...: state = (H(0) | circuit_CX) * State.new_zero_state(5) ...: state = (H(0) | circuit_CX) * State.new_zero_state(5)
In [2]: state In [2]: state
Out[2]: (0.7071067811865476+0j)*|0b0> + (0.7071067811865476+0j)*|0b11111> Out[2]: (0.7071067811865476+0j)*|0b0>
+ (0.7071067811865476+0j)*|0b11111>
\end{lstlisting} \end{lstlisting}
%} %}
@ -232,26 +233,31 @@ implemented in \lstinline{C} and are exported to python3 in the class
\lstinline{RawGraphState}. This class has three main methods to implement the \lstinline{RawGraphState}. This class has three main methods to implement the
three classes of operations. three classes of operations.
%
%
%
\begin{description} \begin{description}
\item[\lstinline{RawGraphState.apply_C_L}]{This method \item[\hspace{-1em}]{\lstinline{RawGraphState.apply_C_L}\\
implements local clifford gates. It takes the qbit index and the index This method implements local clifford gates. It takes the qbit index
of the local Clifford operator (ranging form $0$ to $23$).} and the index of the local Clifford operator (ranging form $0$ to $23$).}
\item[\lstinline{RawGraphState.apply_CZ}]{Applies the $CZ$ gate to the \item[\hspace{-1em}]{\lstinline{RawGraphState.apply_CZ}\\
state. The first argument is the act-qbit, the second the control Applies the $CZ$ gate to the state. The first argument is the
qbit (note that this is just for consistency to the $CX$ gate).} act-qbit, the second the control qbit (note that this is just for
\item[\lstinline{RawGraphState.measure}]{Using this method one can consistency to the $CX$ gate).}
measure a qbit. It takes the qbit index as first argument and \item[\hspace{-1em}]{\lstinline{RawGraphState.measure}\\
a floating point (double precision) random number as second Using this method one can measure a qbit. It takes the qbit index
argument. This random number is used to decide the measurement outcome as first argument and a floating point (double precision) random
in non-deterministic measurements. This method returns either $1$ or $0$ as number as second argument. This random number is used to decide the
a measurement result.} measurement outcome in non-deterministic measurements. This method
returns either $1$ or $0$ as a measurement result.}
\end{description} \end{description}
Because this way of modifying the state is rather unconvenient and might lead to many 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 errors the \lstinline{RawGraphState} is wrapped by the pure python class\\
\lstinline{pyqcs.graph.state.GraphState}. It allows the use of circuits as described \lstinline{pyqcs.graph.state.GraphState}. It allows the use of circuits as
in \ref{ref:pyqcs_circuits} and provides the method \lstinline{GraphState.to_naive_state} described in \ref{ref:pyqcs_circuits} and provides the method
to convert the graphical state to a dense vector state. \lstinline{GraphState.to_naive_state} to convert the graphical state to a dense
vector state.
\subsubsection{Pure C Implementation} \subsubsection{Pure C Implementation}
@ -293,12 +299,12 @@ 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 states has yet to be implemented but can be done in polynomial time
\cite{dahlberg_ea2019}. \cite{dahlberg_ea2019}.
Writing circuits out by hand can be rather painful. The function Writing circuits out by hand can be rather painful. The function\\
\lstinline{pyqcs.list_to_circuit} Converts a list of circuits to a circuit. \lstinline{pyqcs.list_to_circuit} Converts a list of circuits to a circuit.
This is particularely helpful in combination with python's This is particularely helpful in combination with python's
\lstinline{listcomp}: \lstinline{listcomp}:
\begin{lstlisting} \begin{lstlisting}[caption={Generating a Large Circuit Efficiently}]
circuit_H = list_to_circuit([H(i) for i in range(nqbits)]) circuit_H = list_to_circuit([H(i) for i in range(nqbits)])
\end{lstlisting} \end{lstlisting}
@ -308,17 +314,30 @@ dense vector simulation. Using the module \lstinline{pyqcs.util.random_graphs}
one can generate random graphical states which is more performant than using one can generate random graphical states which is more performant than using
random circuits. random circuits.
\subsubsection{Exporting Circuits and Graphical States} The function \lstinline{pyqcs.util.to_circuit.graph_state_to_circuit} converts
graphical states into circuits (mapping the $\ket{0b0..0}$ to this state.
Using these circuits the graphical state can be copied or converted to a
dense vector state. Further it is a way to optimize circuits to run them on
other simulators. Also the circuits can be exported to \lstinline{qcircuit} code
(see below) which is a relatively readable way to represent graphical states.
\subsubsection{Exporting and Flattening Circuits}
Circuits can be drawn using the \LaTeX package \lstinline{qcircuit}; all Circuits can be drawn using the \LaTeX package \lstinline{qcircuit}; all
circuits in this documents use \lstinline{qcircuit}. To visualize the circuits circuits in this documents use \lstinline{qcircuit}. To visualize the circuits
built using \lstinline{pyqcs} the function built using \lstinline{pyqcs} the function\\
\lstinline{pyqcs.util.to_diagram.circuit_to_diagram} can be used to generate \lstinline{pyqcs.util.to_diagram.circuit_to_diagram} can be used to generate
\lstinline{qcircuit} code that can be used in \LaTeX documents or exported to \lstinline{qcircuit} code that can be used in \LaTeX documents or exported to
PDFs directly. The diagrams produced by this function is not optimized and the PDFs directly. The diagrams produced by this function is not optimized and the
diagrams can be unnecessary long. Usually this can be fixed easily by editing diagrams can be unnecessary long. Usually this can be fixed easily by editing
the produced code manually. the produced code manually.
The circuits constructed using the \lstinline{|} operator have a tree structure
which is rather unconvenient when optimizing circuits or exporting them.
The function \\
\lstinline{pyqcs.util.flatten.flatten} converts a circuit
to a list of single gate circuits that can be analyzed or exported easily.
\subsection{Performance} \subsection{Performance}
\label{ref:performance} \label{ref:performance}
@ -361,7 +380,7 @@ 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 Using this method circuits are generated and applied both to graphical and
dense vector states and the time required to execute the operations dense vector states and the time required to execute the operations
\cite{timeit} is measured. The resulting graph can be seen in \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 Figure \ref{fig:scaling_qbits_linear} and Figure \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 have been scaled linearely with the amount of qbits and the measured time was
divided by the number of qbits: divided by the number of qbits:
@ -399,7 +418,7 @@ One should be aware that the gate execution time (the time required to apply a g
to the state) highly depends on the state it is applied to. For the dense vector 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 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 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} gate execution time of the $CZ$ gate varies greatly. The plot Figure \ref{fig:scaling_circuits_linear}
shows the circuit execution time for two different numbers of qbits. One can observe three shows the circuit execution time for two different numbers of qbits. One can observe three
regimes: regimes:
@ -426,6 +445,13 @@ regimes:
\label{fig:graph_low_linear_regime} \label{fig:graph_low_linear_regime}
\end{figure} \end{figure}
\begin{figure}
\centering
\includegraphics[width=\linewidth]{../performance/regimes/graph_intermediate_regime.png}
\caption[Typical Graphical State in the Intermediate Regime]{Typical Graphical State in the Intermediate Regime}
\label{fig:graph_intermediate_regime}
\end{figure}
\begin{figure} \begin{figure}
\centering \centering
\includegraphics[width=\linewidth]{../performance/regimes/graph_high_linear_regime.png} \includegraphics[width=\linewidth]{../performance/regimes/graph_high_linear_regime.png}
@ -433,14 +459,17 @@ regimes:
\label{fig:graph_high_linear_regime} \label{fig:graph_high_linear_regime}
\end{figure} \end{figure}
These two regimes can be explained when considering the graphical states that typical live in these These two regimes can be explained when considering the graphical states that
regimes. With increased circuit length the amount of edges increases which makes toggling neighbourhoods typical live in these regimes. With increased circuit length the amount of
harder. Two graphs from the low-linear and high-linear regime can be seen in \ref{fig:graph_low_linear_regime} edges increases which makes toggling neighbourhoods harder. Graphs from the
and \ref{fig:graph_high_linear_regime}. The latter is hardly visible; this is due to the great amount of low-linear, intermediate and high-linear regime can be seen in
edges in this regime. Further these two regimes are only visibly for $n>30$ qbits so choosing smaller graphs is Figure \ref{fig:graph_low_linear_regime}, Figure \ref{fig:graph_intermediate_regime} and
not possible. Figure \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 Because states with more qbits reach the intermediate regime at higher circuit
account for this virtual performance boost when comparing with other simulation methods. This explains lengths it is important to account for this virtual performance boost when
why the circuit length in \ref{fig:scaling_qbits_linear} had to be scaled with the qbit number. comparing with other simulation methods. This explains why the circuit length
in Figure \ref{fig:scaling_qbits_linear} had to be scaled with the qbit number.