Skip to content

Commit

Permalink
Merge pull request #126 from BoxiLi/Add-code-example
Browse files Browse the repository at this point in the history
Add more code examples in the docstring
  • Loading branch information
BoxiLi committed Feb 20, 2022
2 parents e7f1e01 + a5788a0 commit 3f29972
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 11 deletions.
29 changes: 28 additions & 1 deletion src/qutip_qip/compiler/cavityqedcompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class CavityQEDCompiler(GateCompiler):
params: dict
A Python dictionary contains the name and the value of the parameters.
See :meth:`.DispersiveCavityQED.set_up_params` for the definition.
See :obj:`.CavityQEDModel` for the definition.
global_phase: float, optional
Record of the global phase change and will be returned.
Expand All @@ -46,6 +46,33 @@ class CavityQEDCompiler(GateCompiler):
gate_compiler: dict
The Python dictionary in the form of {gate_name: decompose_function}.
It saves the decomposition scheme for each gate.
Examples
--------
>>> import numpy as np
>>> from qutip_qip.circuit import QubitCircuit
>>> from qutip_qip.device import ModelProcessor, CavityQEDModel
>>> from qutip_qip.compiler import CavityQEDCompiler
>>>
>>> qc = QubitCircuit(2)
>>> qc.add_gate("ISWAP", targets=[0, 1])
>>>
>>> model = CavityQEDModel(2)
>>> processor = ModelProcessor(model=model)
>>> compiler = CavityQEDCompiler(2, params=model.params)
>>> processor.load_circuit(
... qc, compiler=compiler) # doctest: +NORMALIZE_WHITESPACE
({'sz0': array([ 0. , 2500. , 2500.01315789]),
'sz1': array([ 0. , 2500. , 2500.01315789]),
'g0': array([ 0., 2500.]),
'g1': array([ 0., 2500.])},
{'sz0': array([-0.5, -9.5]),
'sz1': array([-0.5, -9.5]),
'g0': array([0.01]),
'g1': array([0.01])})
Notice that the above example is equivalent to using directly
the :obj:`.DispersiveCavityQED`.
"""

def __init__(
Expand Down
40 changes: 40 additions & 0 deletions src/qutip_qip/compiler/circuitqedcompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,46 @@ class SCQubitsCompiler(GateCompiler):
+-----------------+-----------------------+
|``params`` | Hardware Parameters |
+-----------------+-----------------------+
Parameters
----------
num_qubits: int
The number of qubits in the system.
params: dict
A Python dictionary contains the name and the value of the parameters.
See :meth:`.SCQubitsModel` for the definition.
Attributes
----------
num_qubits: int
The number of the component systems.
params: dict
A Python dictionary contains the name and the value of the parameters,
such as laser frequency, detuning etc.
gate_compiler: dict
The Python dictionary in the form of {gate_name: decompose_function}.
It saves the decomposition scheme for each gate.
Examples
--------
>>> import numpy as np
>>> from qutip_qip.circuit import QubitCircuit
>>> from qutip_qip.device import ModelProcessor, SCQubitsModel
>>> from qutip_qip.compiler import SCQubitsCompiler
>>>
>>> qc = QubitCircuit(2)
>>> qc.add_gate("CNOT", targets=0, controls=1)
>>>
>>> model = SCQubitsModel(2)
>>> processor = ModelProcessor(model=model)
>>> compiler = SCQubitsCompiler(2, params=model.params)
>>> processor.load_circuit(qc, compiler=compiler); # doctest: +SKIP
Notice that the above example is equivalent to using directly
the :obj:`.SCQubits`.
"""

def __init__(self, num_qubits, params):
Expand Down
46 changes: 46 additions & 0 deletions src/qutip_qip/compiler/gatecompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,52 @@ def generate_pulse_shape(cls, shape, num_samples, maximum=1.0, area=1.0):
``Processor.pulse_mode`` to ``"continuous"``.
Notice that finite number of sampling points will also make
the total integral of the coefficients slightly deviate from ``area``.
Examples
--------
.. plot::
:context: reset
from qutip_qip.compiler import GateCompiler
import numpy as np
compiler = GateCompiler()
coeff, tlist= compiler.generate_pulse_shape(
"hann", # Scipy Hann window
1000, # 100 sampling point
maximum=3.,
# Notice that 2 pi is added to H by qutip solvers.
area= 1.,
)
We can plot the generated pulse shape:
.. plot::
:context: close-figs
import matplotlib.pyplot as plt
plt.plot(tlist, coeff)
plt.show()
The pulse is normalized to fit the area. Notice that due to
the finite number of sampling points, it is not exactly 1.
.. testsetup::
from qutip_qip.compiler import GateCompiler
import numpy as np
compiler = GateCompiler()
coeff, tlist= compiler.generate_pulse_shape(
"hann", # Scipy Hann window
1000, # 100 sampling point
maximum=3.,
# Notice that 2 pi is added to H by qutip solvers.
area= 1.,
)
.. doctest::
>>> round(np.trapz(coeff, tlist), 2)
1.0
"""
coeff, tlist = _normalized_window(shape, num_samples)
sign = np.sign(area)
Expand Down
24 changes: 23 additions & 1 deletion src/qutip_qip/compiler/spinchaincompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SpinChainCompiler(GateCompiler):
params: dict
A Python dictionary contains the name and the value of the parameters.
See :meth:`.SpinChain.set_up_params` for the definition.
See :obj:`.SpinChainModel` for the definition.
setup: string
"linear" or "circular" for two sub-classes.
Expand Down Expand Up @@ -70,6 +70,28 @@ class SpinChainCompiler(GateCompiler):
global_phase: bool
Record of the global phase change and will be returned.
Examples
--------
>>> import numpy as np
>>> from qutip_qip.circuit import QubitCircuit
>>> from qutip_qip.device import ModelProcessor, SpinChainModel
>>> from qutip_qip.compiler import SpinChainCompiler
>>>
>>> qc = QubitCircuit(2)
>>> qc.add_gate("RX", 0, arg_value=np.pi)
>>> qc.add_gate("RZ", 1, arg_value=np.pi)
>>>
>>> model = SpinChainModel(2, "linear", g=0.1)
>>> processor = ModelProcessor(model=model)
>>> compiler = SpinChainCompiler(2, params=model.params, setup="linear")
>>> processor.load_circuit(
... qc, compiler=compiler) # doctest: +NORMALIZE_WHITESPACE
({'sx0': array([0., 1.]), 'sz1': array([0. , 0.25])},
{'sx0': array([0.25]), 'sz1': array([1.])})
Notice that the above example is equivalent to using directly
the :obj:`.LinearSpinChain`.
"""

def __init__(
Expand Down
31 changes: 31 additions & 0 deletions src/qutip_qip/device/cavityqed.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,37 @@ class DispersiveCavityQED(ModelProcessor):
**params:
Hardware parameters. See :obj:`CavityQEDModel`.
Examples
--------
.. testcode::
import numpy as np
import qutip
from qutip_qip.circuit import QubitCircuit
from qutip_qip.device import DispersiveCavityQED
qc = QubitCircuit(2)
qc.add_gate("RX", 0, arg_value=np.pi)
qc.add_gate("RY", 1, arg_value=np.pi)
qc.add_gate("ISWAP", [1, 0])
processor = DispersiveCavityQED(2, g=0.1)
processor.load_circuit(qc)
result = processor.run_state(
qutip.basis([10, 2, 2], [0, 0, 0]),
options=qutip.Options(nsteps=5000))
final_qubit_state = result.states[-1].ptrace([1, 2])
print(round(qutip.fidelity(
final_qubit_state,
qc.run(qutip.basis([2, 2], [0, 0]))
), 4))
.. testoutput::
0.9994
"""

def __init__(
Expand Down
22 changes: 21 additions & 1 deletion src/qutip_qip/device/circuitqed.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ class SCQubits(ModelProcessor):
If ZZ cross-talk is included.
**params:
Hardware parameters. See :obj:`SCQubitsModel`.
Examples
--------
.. testcode::
import numpy as np
import qutip
from qutip_qip.circuit import QubitCircuit
from qutip_qip.device import SCQubits
qc = QubitCircuit(2)
qc.add_gate("RZ", 0, arg_value=np.pi)
qc.add_gate("RY", 1, arg_value=np.pi)
qc.add_gate("CNOT", targets=0, controls=1)
processor = SCQubits(2)
processor.load_circuit(qc)
init_state = qutip.basis([3, 3], [0, 0])
result = processor.run_state(init_state)
"""

def __init__(self, num_qubits, dims=None, zz_crosstalk=False, **params):
Expand Down Expand Up @@ -140,7 +160,7 @@ class SCQubitsModel(Model):

def __init__(self, num_qubits, dims=None, zz_crosstalk=False, **params):
self.num_qubits = num_qubits
self.dims = dims
self.dims = dims if dims is not None else [3] * num_qubits
self.params = {
"wq": np.array(
((5.15, 5.09) * int(np.ceil(self.num_qubits / 2)))[
Expand Down
44 changes: 41 additions & 3 deletions src/qutip_qip/device/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ class Processor(object):
It compiles quantum circuit into a Hamiltonian model and then
simulate the time-evolution described by the master equation.
.. note::
This is an abstract class that includes the general API but
has no concrete physical model implemented.
In particular, it provides a series of low-level APIs that allow
direct modification of the Hamiltonian model and control pulses,
which can usually be achieved automatically using :obj:`.Model`
and build-in workflows.
They provides more flexibility but are not always the most
elegant approaches.
Parameters
----------
num_qubits : int, optional
Expand Down Expand Up @@ -221,7 +232,8 @@ def add_control(
self, qobj, targets=None, cyclic_permutation=False, label=None
):
"""
Add a control Hamiltonian to the model.
Add a control Hamiltonian to the model. The new control Hamiltonian
is saved in the :obj:`.Processor.model` attributes.
Parameters
----------
Expand All @@ -243,6 +255,21 @@ def add_control(
If ``None``,
it will be set to the current number of
control Hamiltonians in the system.
Examples
--------
>>> import qutip
>>> from qutip_qip.device import Processor
>>> processor = Processor(1)
>>> processor.add_control(qutip.sigmax(), 0, label="sx")
>>> processor.get_control_labels()
['sx']
>>> processor.get_control("sx") # doctest: +NORMALIZE_WHITESPACE
(Quantum object: dims = [[2], [2]], shape = (2, 2),
type = oper, isherm = True
Qobj data =
[[0. 1.]
[1. 0.]], [0])
"""
targets = self._unify_targets(qobj, targets)
if label is None:
Expand All @@ -268,6 +295,19 @@ def get_control(self, label):
-------
control_hamiltonian : tuple
The control Hamiltonian in the form of ``(qobj, targets)``.
Examples
--------
>>> from qutip_qip.device import LinearSpinChain
>>> processor = LinearSpinChain(1)
>>> processor.get_control_labels()
['sx0', 'sz0']
>>> processor.get_control('sz0') # doctest: +NORMALIZE_WHITESPACE
(Quantum object: dims = [[2], [2]], shape = (2, 2),
type = oper, isherm = True
Qobj data =
[[ 6.28318531 0. ]
[ 0. -6.28318531]], 0)
"""
return self.model.get_control(label)

Expand Down Expand Up @@ -403,7 +443,6 @@ def set_coeffs(self, coeffs):
)

set_all_coeffs = set_coeffs
set_all_coeffs.__doc__ = "Equivalent to :obj:`Processor.set_coeffs`."

def set_tlist(self, tlist):
"""
Expand All @@ -430,7 +469,6 @@ def set_tlist(self, tlist):
self.pulses[pulse_dict[pulse_label]].tlist = value

set_all_tlist = set_tlist
set_all_coeffs.__doc__ = "Equivalent to :obj:`Processor.set_tlist`."

def get_full_tlist(self, tol=1.0e-10):
"""
Expand Down

0 comments on commit 3f29972

Please sign in to comment.