some work
This commit is contained in:
parent
ba500e334e
commit
edaa8ac4a4
|
@ -64,7 +64,7 @@ in Python.
|
|||
The logic of gates is usually easy to implement using the integer basis. The
|
||||
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:
|
||||
|
||||
|
@ -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
|
||||
angle as second argument:
|
||||
|
||||
%\adjustbox{max width=\textwidth}{
|
||||
\begin{lstlisting}[language=Python]
|
||||
\begin{lstlisting}[language=Python, breaklines=true, caption={Using Single Gate Circuits}]
|
||||
In [1]: from pyqcs import CX, CZ, H, R, Z, X
|
||||
...: 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
|
||||
|
||||
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}
|
||||
%}
|
||||
|
||||
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
|
||||
|
@ -124,7 +123,7 @@ read from left to right similar to pipelines on *NIX systems:
|
|||
|
||||
|
||||
%\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
|
||||
...: from pyqcs import State
|
||||
...:
|
||||
|
@ -137,7 +136,8 @@ In [1]: from pyqcs import CX, CZ, H, R, Z, X
|
|||
...: bell_state = circuit * 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}
|
||||
%}
|
||||
|
||||
|
@ -145,7 +145,7 @@ A quick way to generate circuits programatically is to use the \lstinline{list_t
|
|||
function:
|
||||
|
||||
%\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
|
||||
...: 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)
|
||||
|
||||
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}
|
||||
%}
|
||||
|
@ -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
|
||||
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.}
|
||||
\item[\hspace{-1em}]{\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[\hspace{-1em}]{\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[\hspace{-1em}]{\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
|
||||
\lstinline{pyqcs.graph.state.GraphState}. It allows the use of circuits as described
|
||||
in \ref{ref:pyqcs_circuits} and provides the method \lstinline{GraphState.to_naive_state}
|
||||
to convert the graphical state to a dense vector state.
|
||||
errors the \lstinline{RawGraphState} is wrapped by the pure python class\\
|
||||
\lstinline{pyqcs.graph.state.GraphState}. It allows the use of circuits as
|
||||
described 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 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
|
||||
\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.
|
||||
This is particularely helpful in combination with python's
|
||||
\lstinline{listcomp}:
|
||||
|
||||
\begin{lstlisting}
|
||||
\begin{lstlisting}[caption={Generating a Large Circuit Efficiently}]
|
||||
circuit_H = list_to_circuit([H(i) for i in range(nqbits)])
|
||||
\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
|
||||
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 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{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
|
||||
diagrams can be unnecessary long. Usually this can be fixed easily by editing
|
||||
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}
|
||||
\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
|
||||
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
|
||||
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
|
||||
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
|
||||
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}
|
||||
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
|
||||
regimes:
|
||||
|
||||
|
@ -426,6 +445,13 @@ regimes:
|
|||
\label{fig:graph_low_linear_regime}
|
||||
\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}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{../performance/regimes/graph_high_linear_regime.png}
|
||||
|
@ -433,14 +459,17 @@ regimes:
|
|||
\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.
|
||||
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. Graphs from the
|
||||
low-linear, intermediate and high-linear regime can be seen in
|
||||
Figure \ref{fig:graph_low_linear_regime}, Figure \ref{fig:graph_intermediate_regime} and
|
||||
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
|
||||
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.
|
||||
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 Figure \ref{fig:scaling_qbits_linear} had to be scaled with the qbit number.
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user