Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
set to None, the circuit's current device is used.
qubit_map: Transforms the qubits (e.g. so that they are GridQubits).
allow_partial_czs: If true, the optimized circuit may contain partial CZ
gates. Otherwise all partial CZ gates will be converted to full CZ
gates. At worst, two CZ gates will be put in place of each partial
CZ from the input.
Returns:
The optimized circuit.
"""
copy = circuit.copy()
opts = _OPTIMIZERS_PART_CZ if allow_partial_czs else _OPTIMIZERS
for optimizer in opts:
optimizer(copy)
return circuits.Circuit(
(op.transform_qubits(qubit_map) for op in copy.all_operations()),
strategy=circuits.InsertStrategy.EARLIEST,
device=new_device or copy.device)
qubits: Sequence['cirq.Qid'],
) -> Iterator['cirq.Operation']:
"""Adds single qubit operations to complete a desired interaction.
Args:
desired: The kak decomposition of the desired operation.
qubits: The pair of qubits that is being operated on.
operations: A list of operations that composes into the desired kak
interaction coefficients, but may not have the desired before/after
single qubit operations or the desired global phase.
Returns:
A list of operations whose kak decomposition approximately equals the
desired kak decomposition.
"""
actual = linalg.kak_decomposition(circuits.Circuit(operations))
def dag(a: np.ndarray) -> np.ndarray:
return np.transpose(np.conjugate(a))
for k in range(2):
g = ops.MatrixGate(
dag(actual.single_qubit_operations_before[k])
@ desired.single_qubit_operations_before[k])
yield g(qubits[k])
yield from operations
for k in range(2):
g = ops.MatrixGate(desired.single_qubit_operations_after[k] @ dag(
actual.single_qubit_operations_after[k]))
yield g(qubits[k])
yield ops.GlobalPhaseOperation(desired.global_phase / actual.global_phase)
def converted_gate_set(circuit: circuits.Circuit,
no_clifford_gates: bool = False,
atol: float = 1e-8,
) -> circuits.Circuit:
"""Returns a new, equivalent circuit using the gate set
{SingleQubitCliffordGate,
CZ/PauliInteractionGate, PauliStringPhasor}.
"""
conv_circuit = circuits.Circuit(circuit)
optimizers.ConvertToCzAndSingleGates().optimize_circuit(conv_circuit)
optimizers.MergeSingleQubitGates().optimize_circuit(conv_circuit)
ConvertToPauliStringPhasors(ignore_failures=True,
keep_clifford=not no_clifford_gates,
atol=atol,
).optimize_circuit(conv_circuit)
optimizers.DropEmptyMoments().optimize_circuit(conv_circuit)
return conv_circuit
def _compute_samples_display_value(display: ops.SamplesDisplay,
state: np.ndarray,
qubit_order: ops.QubitOrder,
qubit_map: Dict[ops.Qid, int]):
basis_change_circuit = circuits.Circuit(display.measurement_basis_change())
modified_state = basis_change_circuit.final_wavefunction(
state,
qubit_order=qubit_order,
qubits_that_should_be_present=qubit_map.keys())
indices = [qubit_map[qubit] for qubit in display.qubits]
samples = wave_function.sample_state_vector(modified_state,
indices,
repetitions=display.num_samples)
return display.value_derived_from_samples(samples)
qubits: qubit grid in which to generate the circuit.
cz_depth: number of layers with CZ gates.
seed: seed for the random instance.
Returns:
A circuit corresponding to instance
inst_{n_rows}x{n_cols}_{cz_depth+1}_{seed}
The mapping of qubits is cirq.GridQubit(j,k) -> q[j*n_cols+k]
(as in the QASM mapping)
"""
non_diagonal_gates = [ops.pauli_gates.X**(1/2), ops.pauli_gates.Y**(1/2)]
rand_gen = random.Random(seed).random
circuit = circuits.Circuit()
# Add an initial moment of Hadamards
circuit.append(ops.common_gates.H(qubit) for qubit in qubits)
layer_index = 0
if cz_depth:
layer_index = _add_cz_layer(layer_index, circuit)
# In the first moment, add T gates when possible
for qubit in qubits:
if not circuit.operation_at(qubit, 1):
circuit.append(ops.common_gates.T(qubit),
strategy=InsertStrategy.EARLIEST)
for moment_index in range(2, cz_depth+1):
layer_index = _add_cz_layer(layer_index, circuit)
# Add single qubit gates in the same moment
@property
@abc.abstractmethod
def initial_mapping(self) -> LogicalMapping:
"""The initial mapping of logical indices to qubits."""
@abc.abstractmethod
def get_operations(self, indices: Sequence[LogicalIndex],
qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
"""Gets the logical operations to apply to qubits."""
def __call__(self, *args, **kwargs):
return StrategyExecutor(self)(*args, **kwargs)
class StrategyExecutor(circuits.PointOptimizer):
"""Executes an acquaintance strategy."""
def __init__(self, execution_strategy: ExecutionStrategy) -> None:
super().__init__()
self.execution_strategy = execution_strategy
self.mapping = execution_strategy.initial_mapping.copy()
def __call__(self, strategy: 'cirq.Circuit'):
if not is_acquaintance_strategy(strategy):
raise TypeError('not is_acquaintance_strategy(strategy)')
expose_acquaintance_gates(strategy)
strategy.device = self.execution_strategy.device
super().optimize_circuit(strategy)
return self.mapping.copy()
def pauli_string_half(circuit: circuits.Circuit) -> circuits.Circuit:
"""Return only the non-Clifford part of a circuit. See
convert_and_separate_circuit().
Args:
circuit: A Circuit with the gate set {SingleQubitCliffordGate,
PauliInteractionGate, PauliStringPhasor}.
Returns:
A Circuit with only PauliStringPhasor operations.
"""
return circuits.Circuit.from_ops(
_pull_non_clifford_before(circuit),
strategy=circuits.InsertStrategy.EARLIEST)
def optimized_circuit(circuit: circuits.Circuit,
atol: float = 1e-8,
repeat: int = 10,
merge_interactions: bool = True
) -> circuits.Circuit:
circuit = circuits.Circuit(circuit) # Make a copy
for _ in range(repeat):
start_len = len(circuit)
start_cz_count = _cz_count(circuit)
if merge_interactions:
optimizers.MergeInteractions(allow_partial_czs=False,
post_clean_up=_optimized_ops,
).optimize_circuit(circuit)
circuit2 = pauli_string_optimized_circuit(
circuit,
move_cliffords=False,
atol=atol)
circuit3 = clifford_optimized_circuit(
circuit2,
atol=atol)
if (len(circuit3) == start_len
and _cz_count(circuit3) == start_cz_count):
def _render(diagram: circuits.TextDiagramDrawer) -> str:
w = diagram.width()
h = diagram.height()
qwx = {(x, y + 1)
for x, y1, y2, _ in diagram.vertical_lines
for y in range(int(y1), int(y2))}
qw = {(x, y)
for y, x1, x2, _ in diagram.horizontal_lines
for x in range(int(x1), int(x2))}
diagram2 = circuits.TextDiagramDrawer()
for y in range(h):
for x in range(max(0, w - 1)):
key = (x, y)
diagram_text = diagram.entries.get(key)
v = '&' + (diagram_text.text if diagram_text else '') + ' '
diagram2.write(2*x + 1, y, v)
post1 = r'\qw' if key in qw else ''
post2 = r'\qwx' if key in qwx else ''
diagram2.write(2*x + 2, y, post1 + post2)
diagram2.write(2*w - 1, y, r'&\qw\\')
grid = diagram2.render(horizontal_spacing=0, vertical_spacing=0)
output = '\\Qcircuit @R=1em @C=0.75em {\n \\\\\n' + grid + '\n \\\\\n}'
return output
def __init__(self):
circuits.PointOptimizer.__init__(self)
self.no_decomp = lambda op: (not get_acquaintance_size(
op) or ops.op_gate_of_type(op, AcquaintanceOpportunityGate))