Skip to content

Commit

Permalink
v1.15.1
Browse files Browse the repository at this point in the history
  • Loading branch information
WrathfulSpatula committed Jun 18, 2023
1 parent 8ddeaf2 commit 0507512
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 1 deletion.
102 changes: 102 additions & 0 deletions pyqrack/qrack_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@
try:
from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.qobj.qasm_qobj import QasmQobjExperiment
from qiskit.quantum_info.operators.symplectic.clifford import Clifford
from .util import convert_qiskit_circuit_to_qasm_experiment
except ImportError:
_IS_QISKIT_AVAILABLE = False

_IS_NUMPY_AVAILABLE = True
try:
import numpy as np
except:
_IS_NUMPY_AVAILABLE = False


class QrackSimulator:
"""Interface for all the QRack functionality.
Expand Down Expand Up @@ -2417,6 +2424,101 @@ def in_from_file(filename, is_binary_decision_tree = False, is_paged = True, is_

return out

def file_to_qiskit_circuit(filename):
"""Convert an output state file to a Qiskit circuit
Reads in an (optimized) circuit from a file named
according to the "filename" parameter and outputs
a Qiskit circuit.
Args:
filename: Name of file
Raises:
RuntimeErorr: Before trying to file_to_qiskit_circuit() with
QrackCircuit, you must install Qiskit, numpy, and math!
"""
if not (_IS_QISKIT_AVAILABLE and _IS_NUMPY_AVAILABLE):
raise RuntimeError(
"Before trying to file_to_qiskit_circuit() with QrackCircuit, you must install Qiskit, numpy, and math!"
)

lines = []
with open(filename, 'r') as file:
lines = file.readlines()

logical_qubits = int(lines[0])
stabilizer_qubits = int(lines[1])
rows = stabilizer_qubits << 1

tableau = []
for line in lines[2:(rows + 2)]:
bits = line.split()
row = []
for bit in bits:
row.append(bool(int(bit)))
row[-1] = (int(bits[-1]) >> 1) & 1
tableau.append(row)

non_clifford_gates = []
g = 0
for line in lines[(rows + 2):]:
i = 0
tokens = line.split()
op = np.zeros((2,2), dtype=complex)
row = []
for _ in range(2):
amp = tokens[i].replace("(","").replace(")","").split(',')
row.append(float(amp[0]) + float(amp[1])*1j)
i = i + 1
l = math.sqrt(np.real(row[0] * np.conj(row[0]) + row[1] * np.conj(row[1])))
op[0][0] = row[0] / l
op[0][1] = row[1] / l

if np.abs(op[0][0] - row[0]) > 1e-5:
print("Warning: gate ", str(g), " might not be unitary!")
if np.abs(op[0][1] - row[1]) > 1e-5:
print("Warning: gate ", str(g), " might not be unitary!")

row = []
for _ in range(2):
amp = tokens[i].replace("(","").replace(")","").split(',')
row.append(float(amp[0]) + float(amp[1])*1j)
i = i + 1
l = math.sqrt(np.real(row[0] * np.conj(row[0]) + row[1] * np.conj(row[1])))
op[1][0] = row[0] / l
op[1][1] = row[1] / l

ph = np.real(np.log(np.linalg.det(op)) / 1j)

op[1][0] = -np.exp(1j * ph) * np.conj(op[0][1])
op[1][1] = np.exp(1j * ph) * np.conj(op[0][0])

if np.abs(op[1][0] - row[0]) > 1e-5:
print("Warning: gate ", str(g), " might not be unitary!")
if np.abs(op[1][1] - row[1]) > 1e-5:
print("Warning: gate ", str(g), " might not be unitary!")

non_clifford_gates.append(op)
g = g + 1

clifford = Clifford(tableau)

circ = clifford.to_circuit()
for i in range(len(non_clifford_gates)):
circ.unitary(non_clifford_gates[i], [i])

ident = np.eye(2)
second_ancilla = non_clifford_gates[logical_qubits + 1]
if np.all(np.equal(ident, second_ancilla)):
# We're "hardware-encoded"
for i in range(logical_qubits, stabilizer_qubits, 2):
circ.h(i + 1)
circ.cz(i, i + 1)
circ.h(i + 1)

return circ

def _apply_pyzx_op(self, gate):
if gate.name == "XPhase":
self.r(Pauli.PauliX, math.pi * gate.phase, gate.target)
Expand Down
2 changes: 1 addition & 1 deletion source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Output Unitary Clifford+RZ Simulation For Quantum Hardware
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is theoretically possible to use the Clifford+RZ improvements of v8.12 to compile for hardware. (`QUnit` "Schmidt decomposition cannot be used over `QStabilizerHybrid`, for this.)

Since v8.13, it is now possible to output `QStabilizerHybrid` state to file, (not while using `QUnit`). This is done with `QrackSimulator.out_to_file(filename)`, on a simulator instance. The files have the following format, by line:
Since v8.13, it is now possible to output `QStabilizerHybrid` state to file, (not while using `QUnit`). This is done with `QrackSimulator.out_to_file(filename)`, on a simulator instance. With `QrackSimulator.file_to_qiskit_circuit(filename)`, we perform the algorithm that follows, to produce a Qiskit circuit. The files have the following format, by line:

[Logical qubit count]

Expand Down

0 comments on commit 0507512

Please sign in to comment.