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
|
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.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user