Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare the qutip-qip-0.1.2 release #110

Merged
merged 7 commits into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.1
0.1.2
76 changes: 38 additions & 38 deletions doc/source/qip-simulator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ method.

.. testcode::

from qutip import tensor
from qutip import tensor, basis
zero_state = tensor(basis(2, 0), basis(2, 0), basis(2, 0))
result = qc.run(state=zero_state)
wstate = result
Expand Down Expand Up @@ -93,42 +93,42 @@ outputs, we can use the :meth:`.QubitCircuit.run_statistics` function:
.. testoutput::
:options: +NORMALIZE_WHITESPACE

State:
Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = (8, 1), type = ket
Qobj data =
[[0.]
[1.]
[0.]
[0.]
[0.]
[0.]
[0.]
[0.]]
with probability 0.33333257054168813
State:
Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = (8, 1), type = ket
Qobj data =
[[0.]
[0.]
[1.]
[0.]
[0.]
[0.]
[0.]
[0.]]
with probability 0.33333257054168813
State:
Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = (8, 1), type = ket
Qobj data =
[[0.]
[0.]
[0.]
[0.]
[1.]
[0.]
[0.]
[0.]]
with probability 0.33333485891662384
State:
Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = (8, 1), type = ket
Qobj data =
[[0.]
[1.]
[0.]
[0.]
[0.]
[0.]
[0.]
[0.]]
with probability 0.3333325705416881
State:
Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = (8, 1), type = ket
Qobj data =
[[0.]
[0.]
[1.]
[0.]
[0.]
[0.]
[0.]
[0.]]
with probability 0.3333325705416881
State:
Quantum object: dims = [[2, 2, 2], [1, 1, 1]], shape = (8, 1), type = ket
Qobj data =
[[0.]
[0.]
[0.]
[0.]
[1.]
[0.]
[0.]
[0.]]
with probability 0.33333485891662384

The function returns a :class:`~.Result` object which contains
the output states.
Expand Down Expand Up @@ -186,7 +186,7 @@ The :class:`.CircuitSimulator` class also enables stepping through the circuit:
[0. ]
[0. ]]

This only excutes one gate in the circuit and
This only executes one gate in the circuit and
allows for a better understanding of how the state evolution takes place.
The method steps through both the gates and the measurements.

Expand Down
15 changes: 14 additions & 1 deletion src/qutip_qip/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ class QubitCircuit:
A list of integer for the dimension of each composite system.
e.g [2,2,2,2,2] for 5 qubits system. If None, qubits system
will be the default option.
num_cbits : int
Number of classical bits in the system.

Examples
--------
Expand Down Expand Up @@ -1805,7 +1807,7 @@ def latex_code(self):
code += r" & %s" % rows[m][n]
code += r" & \qw \\ " + "\n"

return code
return _latex_template % code

# This slightly convoluted dance with the conversion formats is because
# image conversion has optional dependencies. We always want the `png` and
Expand Down Expand Up @@ -1866,6 +1868,17 @@ def _to_qasm(self, qasm_out):
op._to_qasm(qasm_out)


_latex_template = r"""
\documentclass{standalone}
\usepackage[braket]{qcircuit}
\renewcommand{\qswap}{*=<0em>{\times}}
\begin{document}
\Qcircuit @C=1cm @R=1cm {
%s}
\end{document}
"""


class CircuitResult:

def __init__(self, final_states, probabilities, cbits=None):
Expand Down
17 changes: 6 additions & 11 deletions src/qutip_qip/circuit_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,6 @@
import tempfile
import warnings

_latex_template = r"""
\documentclass{standalone}
\usepackage[braket]{qcircuit}
\renewcommand{\qswap}{*=<0em>{\times}}
\begin{document}
\Qcircuit @C=1cm @R=1cm {
%s}
\end{document}
"""


def _run_command(command, *args, **kwargs):
"""
Expand Down Expand Up @@ -228,7 +218,7 @@ def image_from_latex(code, file_type="png"):
try:
os.chdir(temporary_dir)
with open(filename + ".tex", "w") as file:
file.write(_latex_template % code)
file.write(code)
try:
_run_command((_pdflatex, '-interaction', 'batchmode',
filename))
Expand All @@ -238,6 +228,11 @@ def image_from_latex(code, file_type="png"):
" Perhaps you do not have it installed, or you are"
" missing the LaTeX package 'qcircuit'."
)
message += (
"The latex code is printed below. "
"Please try to compile locally using pdflatex:\n"
+ code
)
raise RuntimeError(message) from e
_crop_pdf(filename + ".pdf")
if file_type in _MISSING_CONVERTERS:
Expand Down
3 changes: 1 addition & 2 deletions src/qutip_qip/device/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,10 +669,9 @@ def get_qobjevo(self, args=None, noisy=False):
final_qu.args.update(args)

# bring all c_ops to the same tlist, won't need it in QuTiP 5
full_tlist = self.get_full_tlist()
temp = []
for c_op in c_ops:
temp.append(_merge_qobjevo([c_op], full_tlist))
temp.append(_merge_qobjevo([c_op], final_qu.tlist))
c_ops = temp

if noisy:
Expand Down
1 change: 1 addition & 0 deletions src/qutip_qip/noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def process_noise(pulses, noise_list, dims, t1=None, t2=None,
noisy_pulses: list of :class:`.Pulse`
The noisy pulses, including the system noise.
"""
noise_list = noise_list.copy()
noisy_pulses = deepcopy(pulses)
systematic_noise = Pulse(None, None, label="systematic_noise")

Expand Down
7 changes: 3 additions & 4 deletions src/qutip_qip/operations/gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -924,11 +924,10 @@ def hadamard_transform(N=1):
Quantum object representation of the N-qubit Hadamard gate.

"""
data = 2 ** (-N / 2) * np.array([[(-1) ** _hamming_distance(i & j)
for i in range(2 ** N)]
for j in range(2 ** N)])
data = [[1, 1], [1, -1]]
H = Qobj(data) / np.sqrt(2)

return Qobj(data, dims=[[2] * N, [2] * N])
return tensor([H] * N)


def _flatten(lst):
Expand Down
12 changes: 11 additions & 1 deletion tests/test_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,10 +655,20 @@ def test_wstate(self):
np.testing.assert_allclose(probs_initial, probs_final)
assert sum(result_cbits[i]) == 1

_latex_template = r"""
\documentclass{standalone}
\usepackage[braket]{qcircuit}
\renewcommand{\qswap}{*=<0em>{\times}}
\begin{document}
\Qcircuit @C=1cm @R=1cm {
%s}
\end{document}
"""

def test_latex_code_teleportation_circuit(self):
qc = _teleportation_circuit()
latex = qc.latex_code()
assert latex == "\n".join([
assert latex == self._latex_template % "\n".join([
r" & \lstick{c1} & \qw & \qw & \qw & \qw"
r" & \qw \cwx[4] & \qw & \qw & \ctrl{2} & \qw \\ ",
r" & \lstick{c0} & \qw & \qw & \qw & \qw"
Expand Down
17 changes: 17 additions & 0 deletions tests/test_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,23 @@ def test_cnot_explicit(self):
[0, 0, 0, 1, 0, 0, 0, 0]])
np.testing.assert_allclose(test, expected, atol=1e-15)

def test_hadamard_explicit(self):
test = gates.hadamard_transform(3).full()
expected = np.array(
[
[1, 1, 1, 1, 1, 1, 1, 1],
[1, -1, 1, -1, 1, -1, 1, -1],
[1, 1, -1, -1, 1, 1, -1, -1],
[1, -1, -1, 1, 1, -1, -1, 1],
[1, 1, 1, 1, -1, -1, -1, -1],
[1, -1, 1, -1, -1, 1, -1, 1],
[1, 1, -1, -1, -1, -1, 1, 1],
[1, -1, -1, 1, -1, 1, 1, -1],
]
)
expected = expected / np.sqrt(8)
np.testing.assert_allclose(test, expected)

def test_cyclic_permutation(self):
operators = [qutip.sigmax(), qutip.sigmaz()]
test = gates.expand_operator(qutip.tensor(*operators), N=3,
Expand Down
20 changes: 18 additions & 2 deletions tests/test_noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

from qutip import (
tensor, qeye, sigmaz, sigmax, sigmay, destroy, identity, QobjEvo,
fidelity, basis
fidelity, basis, sigmam
)
from qutip_qip.device import Processor, SCQubits
from qutip_qip.device import Processor, SCQubits, LinearSpinChain
from qutip_qip.noise import (
RelaxationNoise, DecoherenceNoise, ControlAmpNoise, RandomNoise,
ZZCrossTalk, Noise)
Expand Down Expand Up @@ -50,6 +50,22 @@ def test_decoherence_noise(self):
assert_allclose(c_ops[0].tlist, tlist)
assert_allclose(c_ops[1].ops[0].qobj, tensor(qeye(2), sigmax()))

def test_collapse_with_different_tlist(self):
"""
Test if there are errors raised because of wrong tlist handling.
"""
qc = QubitCircuit(1)
qc.add_gate("X", 0)
proc = LinearSpinChain(1)
proc.load_circuit(qc)
tlist = np.linspace(0, 30., 100)
coeff = tlist * 0.1
noise = DecoherenceNoise(
sigmam(), targets=0,
coeff=coeff, tlist=tlist)
proc.add_noise(noise)
proc.run_state(basis(2, 0))

def test_relaxation_noise(self):
"""
Test for the relaxation noise
Expand Down
19 changes: 16 additions & 3 deletions tests/test_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,10 @@ def testPlot(self):
processor.add_control(sigmaz())
processor.pulses[0].tlist = tlist
processor.pulses[0].coeff = np.array([np.sin(t) for t in tlist])
processor.plot_pulses()
plt.clf()
fig, _ = processor.plot_pulses()
# testing under Xvfb with pytest-xvfb complains if figure windows are
# left open, so we politely close it:
plt.close(fig)

# cubic spline
tlist = np.linspace(0., 2*np.pi, 20)
Expand All @@ -184,7 +186,10 @@ def testPlot(self):
processor.pulses[0].tlist = tlist
processor.pulses[0].coeff = np.array([np.sin(t) for t in tlist])
processor.plot_pulses()
plt.clf()
fig, _ = processor.plot_pulses()
# testing under Xvfb with pytest-xvfb complains if figure windows are
# left open, so we politely close it:
plt.close(fig)

def testSpline(self):
"""
Expand Down Expand Up @@ -365,3 +370,11 @@ def test_pulse_dict(self):
processor = Processor(1)
processor.add_control(sigmax(), 0, label="test")
assert("test" in processor.get_pulse_dict())

def test_repeated_use_of_processor(self):
processor = Processor(1, t1=1.)
processor.add_pulse(
Pulse(sigmax(), targets=0, coeff=True))
result1 = processor.run_state(basis(2, 0), tlist=np.linspace(0, 1, 10))
result2 = processor.run_state(basis(2, 0), tlist=np.linspace(0, 1, 10))
assert_allclose(result1.states[-1].full(), result2.states[-1].full())