Skip to content

Commit

Permalink
Fix tolerance when checking if diagonal is unitary (Qiskit#707)
Browse files Browse the repository at this point in the history
  • Loading branch information
chriseclectic authored Apr 20, 2020
1 parent ddd640e commit 7de864c
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 103 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
Fix issue where the "diagonal" gate is checked to be unitary with too
high a tolerance. This was causing diagonals generated from Numpy functions
to often fail the test.
2 changes: 1 addition & 1 deletion src/framework/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ Op json_to_op_diagonal(const json_t &js) {
throw std::invalid_argument("\"diagonal\" matrix is wrong size.");
}
for (const auto val : op.params) {
if (!Linalg::almost_equal(std::abs(val), 1.0)) {
if (!Linalg::almost_equal(std::abs(val), 1.0, 1e-7)) {
throw std::invalid_argument("\"diagonal\" matrix is not unitary.");
}
}
Expand Down
14 changes: 0 additions & 14 deletions test/terra/backends/qasm_simulator/qasm_unitary_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,3 @@ def test_diagonal_gate(self):
result = execute(circuits, self.SIMULATOR, shots=shots).result()
self.assertTrue(getattr(result, 'success', False))
self.compare_counts(result, circuits, targets, delta=0)

def test_diagonal_gate_wrapper(self):
"""Test simulation with unitary gate circuit instructions."""
shots = 100
lsts = [
[1, -1],
[1, -1, -1, 1],
[1.0, -1.0, -1.0, 1.0]]
circuits = [ ref_diagonal_gate.diagonal_gate_circuits_deterministic_w(state)
for state in [ np.array(lst, dtype=t)
for t in (None, float, np.float32, complex, np.complex64)
for lst in lsts ] ]
result = execute(circuits, self.SIMULATOR, shots=shots).result()
self.assertTrue(getattr(result, 'success', False))
156 changes: 68 additions & 88 deletions test/terra/reference/ref_diagonal_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,6 @@
if not hasattr(QuantumCircuit, 'diagonal'):
QuantumCircuit.diagonal = QuantumCircuit.diag_gate

def diagonal_gate_circuits_deterministic_w(state, final_measure=True):
"""Diagonal gate test circuits with deterministic count output."""

qr = QuantumRegister(2, 'qr')
if final_measure:
cr = ClassicalRegister(2, 'cr')
regs = (qr, cr)
else:
regs = (qr, )

# Swap |00> <--> |11> states
circuit = QuantumCircuit(*regs)
circuit.h(qr)
circuit.diagonal([1, -1, -1, 1], qr)
circuit.h(qr)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
return circuit

def diagonal_gate_circuits_deterministic(final_measure=True):
"""Diagonal gate test circuits with deterministic count output."""
Expand All @@ -53,44 +34,42 @@ def diagonal_gate_circuits_deterministic(final_measure=True):
else:
regs = (qr, )

# Swap |00> <--> |01> states
circuit = QuantumCircuit(*regs)
circuit.h(0)
circuit.diagonal([1, -1], [0])
circuit.h(0)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# Swap |00> <--> |10> states
circuit = QuantumCircuit(*regs)
circuit.h(1)
circuit.diagonal([1, -1], [1])
circuit.h(1)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# Swap |00> <--> |11> states
circuit = QuantumCircuit(*regs)
circuit.h(qr)
circuit.diagonal([1, -1, -1, 1], qr)
circuit.h(qr)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# CS01.XX, 1j|11> state
circuit = QuantumCircuit(*regs)
circuit.x(qr)
circuit.diagonal([1, 1, 1, 1j], qr)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)
# 4 x Swap |00> <--> |01> states
# 4 x Swap |00> <--> |10> states
arg = [1, -1]
for qubit in [0, 1]:
for diag in [arg, np.array(arg), np.array(arg, dtype=float), np.array(arg, dtype=complex)]:
circuit = QuantumCircuit(*regs)
circuit.h(qubit)
circuit.diagonal(list(diag), [qubit])
circuit.h(qubit)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# 4 x Swap |00> <--> |11> states
arg = [1, -1, -1, 1]
for diag in [arg, np.array(arg), np.array(arg, dtype=float), np.array(arg, dtype=complex)]:
circuit = QuantumCircuit(*regs)
circuit.h(qr)
circuit.diagonal(list(diag), qr)
circuit.h(qr)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

# CS01.XX, exp(-1j * np.pi/k)|11> state
for diag in [np.array([1, 1, 1, np.exp(-1j * np.pi / k)])
for k in [10, 100, 1000, 10000]]:
circuit = QuantumCircuit(*regs)
circuit.x(qr)
circuit.diagonal(list(diag), qr)
if final_measure:
circuit.barrier(qr)
circuit.measure(qr, cr)
circuits.append(circuit)

return circuits

Expand All @@ -100,36 +79,36 @@ def diagonal_gate_counts_deterministic(shots, hex_counts=True):
targets = []
if hex_counts:
# Swap |00> <--> |01> states
targets.append({'0x1': shots})
targets += 4 * [{'0x1': shots}]
# Swap |00> <--> |10> states
targets.append({'0x2': shots})
targets += 4 * [{'0x2': shots}]
# Swap |00> <--> |11> states
targets.append({'0x3': shots})
# CS01.XX, 1j|11> state
targets.append({'0x3': shots})
targets += 4 * [{'0x3': shots}]
# CS01.XX, exp(-1j * np.pi/N)|11> state
targets += 4 * [{'0x3': shots}]
else:
# Swap |00> <--> |01> states
targets.append({'01': shots})
targets += 4 * [{'01': shots}]
# Swap |00> <--> |10> states
targets.append({'10': shots})
targets += 4 * [{'10': shots}]
# Swap |00> <--> |11> states
targets.append({'11': shots})
# CS01.XX, 1j|11> state
targets.append({'11': shots})
targets += 4 * [{'11': shots}]
# CS01.XX, exp(-1j * np.pi/k)|11> state
targets += 4 * [{'11': shots}]
return targets


def diagonal_gate_statevector_deterministic():
"""Diagonal gate test circuits with deterministic counts."""
targets = []
# Swap |00> <--> |01> states
targets.append(np.array([0, 1, 0, 0]))
targets += 4 * [np.array([0, 1, 0, 0])]
# Swap |00> <--> |10> states
targets.append(np.array([0, 0, 1, 0]))
targets += 4 * [np.array([0, 0, 1, 0])]
# Swap |00> <--> |11> states
targets.append(np.array([0, 0, 0, 1]))
# CS01.XX, 1j|11> state
targets.append(np.array([0, 0, 0, 1j]))
targets += 4 * [np.array([0, 0, 0, 1])]
# CS01.XX, exp(-1j * np.pi/k)|11> state
targets += [np.array([0, 0, 0, np.exp(-1j * np.pi / k)]) for k in [10, 100, 1000, 10000]]
return targets


Expand All @@ -138,23 +117,24 @@ def diagonal_gate_unitary_deterministic():
targets = []

# Swap |00> <--> |01> states
targets.append(np.array([[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]]))
targets += 4 * [np.array([[0, 1, 0, 0],
[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]])]
# Swap |00> <--> |10> states
targets.append(np.array([[0, 0, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 0],
[0, 1, 0, 0]]))
targets += 4 * [np.array([[0, 0, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 0],
[0, 1, 0, 0]])]
# Swap |00> <--> |11> states
targets.append(np.array([[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0]]))
targets += 4 * [np.array([[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0]])]
# CS01.XX, 1j|11> state
targets.append(np.array([[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1j, 0, 0, 0]]))
targets += [np.array([[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[np.exp(-1j * np.pi / k), 0, 0, 0]])
for k in [10, 100, 1000, 10000]]
return targets

0 comments on commit 7de864c

Please sign in to comment.