Skip to content

Commit

Permalink
Merge branch 'master' into qsim-pyopt
Browse files Browse the repository at this point in the history
  • Loading branch information
95-martin-orion authored Apr 18, 2022
2 parents 0406580 + 9e75230 commit 19e0594
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 31 deletions.
10 changes: 3 additions & 7 deletions qsimcirq/qsim_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,18 +332,17 @@ class QSimCircuit(cirq.Circuit):
def __init__(
self,
cirq_circuit: cirq.Circuit,
device: cirq.devices = cirq.devices.UNCONSTRAINED_DEVICE,
allow_decomposition: bool = False,
):

if allow_decomposition:
super().__init__([], device=device)
super().__init__()
for moment in cirq_circuit:
for op in moment:
# This should call decompose on the gates
self.append(op)
else:
super().__init__(cirq_circuit, device=device)
super().__init__(cirq_circuit)

def __eq__(self, other):
if not isinstance(other, QSimCircuit):
Expand All @@ -354,10 +353,7 @@ def __eq__(self, other):
def _resolve_parameters_(
self, param_resolver: cirq.study.ParamResolver, recursive: bool = True
):
return QSimCircuit(
cirq.resolve_parameters(super(), param_resolver, recursive),
device=self.device,
)
return QSimCircuit(cirq.resolve_parameters(super(), param_resolver, recursive))

def translate_cirq_to_qsim(
self, qubit_order: cirq.QubitOrderOrList = cirq.QubitOrder.DEFAULT
Expand Down
38 changes: 20 additions & 18 deletions qsimcirq/qsim_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ def _sample_measure_results(
self.noise.noisy_moments(program, sorted(all_qubits))
if self.noise is not cirq.NO_NOISE
else program,
device=program.device,
)

# Compute indices of measured qubits
Expand All @@ -324,14 +323,15 @@ def _sample_measure_results(
cirq.MeasurementGate
)
]
measured_qubits = [] # type: List[cirq.Qid]
bounds = {} # type: Dict[str, Tuple]
meas_ops = {} # type: Dict[str, cirq.GateOperation]
measured_qubits: List[cirq.Qid] = []
bounds: Dict[str, Tuple] = {}
meas_ops: Dict[str, List[cirq.GateOperation]] = {}
current_index = 0
for op in measurement_ops:
gate = op.gate
key = cirq.measurement_key_name(gate)
meas_ops[key] = op
meas_ops.setdefault(key, [])
meas_ops[key].append(op)
if key in bounds:
raise ValueError(f"Duplicate MeasurementGate with key {key}")
bounds[key] = (current_index, current_index + len(op.qubits))
Expand All @@ -345,7 +345,7 @@ def _sample_measure_results(
results = {}
for key, bound in bounds.items():
results[key] = np.ndarray(
shape=(repetitions, bound[1] - bound[0]), dtype=int
shape=(repetitions, len(meas_ops[key]), bound[1] - bound[0]), dtype=int
)

noisy = _needs_trajectories(program)
Expand Down Expand Up @@ -374,11 +374,12 @@ def _sample_measure_results(
]
)

for key, op in meas_ops.items():
meas_indices = [qubit_map[qubit] for qubit in op.qubits]
invert_mask = op.gate.full_invert_mask()
# Apply invert mask to re-ordered results
results[key] = full_results[:, meas_indices] ^ invert_mask
for key, oplist in meas_ops.items():
for i, op in enumerate(oplist):
meas_indices = [qubit_map[qubit] for qubit in op.qubits]
invert_mask = op.gate.full_invert_mask()
# Apply invert mask to re-ordered results
results[key][:, i, :] = full_results[:, meas_indices] ^ invert_mask

else:
if noisy:
Expand All @@ -396,7 +397,11 @@ def _sample_measure_results(
measurements = np.empty(
shape=(
repetitions,
sum(cirq.num_qubits(op) for op in meas_ops.values()),
sum(
cirq.num_qubits(op)
for oplist in meas_ops.values()
for op in oplist
),
),
dtype=int,
)
Expand All @@ -405,8 +410,9 @@ def _sample_measure_results(
measurements[i] = sampler_fn(options)

for key, (start, end) in bounds.items():
invert_mask = meas_ops[key].gate.full_invert_mask()
results[key] = measurements[:, start:end] ^ invert_mask
for i, op in enumerate(meas_ops[key]):
invert_mask = op.gate.full_invert_mask()
results[key][:, i, :] = measurements[:, start:end] ^ invert_mask

return results

Expand Down Expand Up @@ -442,7 +448,6 @@ def compute_amplitudes_sweep(
self.noise.noisy_moments(program, sorted(all_qubits))
if self.noise is not cirq.NO_NOISE
else program,
device=program.device,
)

# qsim numbers qubits in reverse order from cirq
Expand Down Expand Up @@ -525,7 +530,6 @@ def simulate_sweep(
self.noise.noisy_moments(program, sorted(all_qubits))
if self.noise is not cirq.NO_NOISE
else program,
device=program.device,
)

options = {}
Expand Down Expand Up @@ -661,7 +665,6 @@ def simulate_expectation_values_sweep(
self.noise.noisy_moments(program, sorted(all_qubits))
if self.noise is not cirq.NO_NOISE
else program,
device=program.device,
)

options = {}
Expand Down Expand Up @@ -796,7 +799,6 @@ def simulate_moment_expectation_values(
self.noise.noisy_moments(program, sorted(all_qubits))
if self.noise is not cirq.NO_NOISE
else program,
device=program.device,
)

options = {}
Expand Down
2 changes: 1 addition & 1 deletion qsimcirq/qsimh_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def compute_amplitudes_sweep(
) -> Sequence[Sequence[complex]]:

if not isinstance(program, qsimc.QSimCircuit):
program = qsimc.QSimCircuit(program, device=program.device)
program = qsimc.QSimCircuit(program)

n_qubits = len(program.all_qubits())
# qsim numbers qubits in reverse order from cirq
Expand Down
11 changes: 6 additions & 5 deletions qsimcirq_tests/qsimcirq_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,11 @@ def test_invalid_params():
x, y = sympy.Symbol("x"), sympy.Symbol("y")
circuit = cirq.Circuit(cirq.X(q0) ** x, cirq.H(q0) ** y)
prs = [{x: np.int64(0), y: np.int64(1)}, {x: np.int64(1), y: "z"}]
sweep = cirq.ListSweep(prs)

qsim_simulator = qsimcirq.QSimSimulator()
with pytest.raises(ValueError, match="Parameters must be numeric"):
_ = qsim_simulator.simulate_sweep(circuit, params=prs)
_ = qsim_simulator.simulate_sweep(circuit, params=sweep)


def test_iterable_qubit_order():
Expand Down Expand Up @@ -1154,10 +1155,10 @@ def test_cirq_qsim_simulate_random_unitary(mode: str):
qubits=[q0, q1], n_moments=8, op_density=0.99, random_state=iter
)

cirq.ConvertToCzAndSingleGates().optimize_circuit(
random_circuit
) # cannot work with params
cirq.ExpandComposite().optimize_circuit(random_circuit)
random_circuit = cirq.optimize_for_target_gateset(
random_circuit, gateset=cirq.CZTargetGateset()
)
random_circuit = cirq.expand_composite(random_circuit)
if mode == "noisy":
random_circuit.append(NoiseTrigger().on(q0))

Expand Down

0 comments on commit 19e0594

Please sign in to comment.