def test_validate_scheduled_operation_XXPow_on_same_qubit(): d = ion_device(3) q0 = cirq.LineQubit(0) q1 = cirq.LineQubit(1) q2 = cirq.LineQubit(2) s = cirq.Schedule(d, [ cirq.ScheduledOperation.op_at_on(cirq.XX(q0, q1), cirq.Timestamp(), d), cirq.ScheduledOperation.op_at_on(cirq.XX(q1, q2), cirq.Timestamp(), d), ]) with pytest.raises(ValueError): d.validate_schedule(s)
def test_xx_diagrams(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') circuit = cirq.Circuit(cirq.XX(a, b), cirq.XX(a, b)**3, cirq.XX(a, b)**0.5) cirq.testing.assert_has_diagram( circuit, """ a: ───XX───XX───XX─────── │ │ │ b: ───XX───XX───XX^0.5─── """, )
def test_can_add_operation_into_moment(): d = ion_device(3) q0 = cirq.LineQubit(0) q1 = cirq.LineQubit(1) q2 = cirq.LineQubit(2) q3 = cirq.LineQubit(3) circuit = cirq.Circuit() circuit.append(cirq.XX(q0, q1)) for moment in circuit: assert not d.can_add_operation_into_moment(cirq.XX(q2, q0), moment) assert not d.can_add_operation_into_moment(cirq.XX(q1, q2), moment) assert d.can_add_operation_into_moment(cirq.XX(q2, q3), moment) assert d.can_add_operation_into_moment(cirq.Z(q3), moment)
def test_xx_diagrams(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') circuit = cirq.Circuit( cirq.XX(a, b), cirq.XX(a, b)**3, cirq.XX(a, b)**0.5, cirq.XXPowGate(global_shift=-0.5).on(a, b), ) cirq.testing.assert_has_diagram( circuit, """ a: ───XX───XX───XX───────MS(0.5π)─── │ │ │ │ b: ───XX───XX───XX^0.5───MS(0.5π)─── """)
def test_can_add_operation_into_moment_device_deprecated(): with cirq.testing.assert_deprecated('can_add_operation_into_moment', deadline='v0.15', count=5): d = ion_device(3) q0 = cirq.LineQubit(0) q1 = cirq.LineQubit(1) q2 = cirq.LineQubit(2) q3 = cirq.LineQubit(3) circuit = cirq.Circuit() circuit.append(cirq.XX(q0, q1)) for moment in circuit: assert not d.can_add_operation_into_moment(cirq.XX(q2, q0), moment) assert not d.can_add_operation_into_moment(cirq.XX(q1, q2), moment) assert d.can_add_operation_into_moment(cirq.XX(q2, q3), moment) assert d.can_add_operation_into_moment(cirq.Z(q3), moment) circuit = cirq.Circuit([cirq.X(q0)]) assert d.can_add_operation_into_moment(cirq.XX(q1, q2), circuit[0])
def test_time_evolution(self): # Given hamiltonian = PauliSum([ PauliTerm('X', 0) * PauliTerm('X', 1), PauliTerm('Y', 0, 0.5) * PauliTerm('Y', 1), PauliTerm('Z', 0, 0.3) * PauliTerm('Z', 1) ]) time = 0.4 order = 2 circuit = cirq.Circuit() q1 = cirq.LineQubit(0) q2 = cirq.LineQubit(1) for _ in range(0, order): circuit.append( cirq.XX(q1, q2)**(hamiltonian.terms[0].coefficient * 2 * time / order / pi)) circuit.append( cirq.YY(q1, q2)**(hamiltonian.terms[1].coefficient * 2 * time / order / pi)) circuit.append( cirq.ZZ(q1, q2)**(hamiltonian.terms[2].coefficient * 2 * time / order / pi)) u = circuit._unitary_() #When unitary_evolution = time_evolution(hamiltonian, time, trotter_order=order) u1 = unitary_evolution.to_unitary() # Then self.assertEqual(compare_unitary(u1, u, tol=1e-10), True)
def test_decompose_parameterized_gates(): theta = sympy.Symbol("theta") q = cirq.LineQubit.range(2) circuit = cirq.Circuit(cirq.H(q[0])**theta, cirq.XX(*q)**theta) d = ion_device(3) assert d.gateset.validate(d.decompose_circuit(circuit)) assert d.gateset._decompose_two_qubit_operation(cirq.CZ(*q)**theta, 0) is NotImplemented
def two_qubit_unitary(bits, symbols): """Make a Cirq circuit that creates an arbitrary two qubit unitary.""" circuit = cirq.Circuit() circuit += one_qubit_unitary(bits[0], symbols[0:3]) circuit += one_qubit_unitary(bits[1], symbols[3:6]) circuit += [cirq.ZZ(*bits)**symbols[6]] circuit += [cirq.YY(*bits)**symbols[7]] circuit += [cirq.XX(*bits)**symbols[8]] circuit += one_qubit_unitary(bits[0], symbols[9:12]) circuit += one_qubit_unitary(bits[1], symbols[12:]) return circuit
def _all_operations(q0, q1, q2, q3, q4, include_measurements=True): return ( cirq.Z(q0), cirq.Z(q0)**0.625, cirq.Y(q0), cirq.Y(q0)**0.375, cirq.X(q0), cirq.X(q0)**0.875, cirq.H(q1), cirq.CZ(q0, q1), cirq.CZ(q0, q1)**0.25, # Requires 2-qubit decomposition cirq.CNOT(q0, q1), cirq.CNOT(q0, q1)**0.5, # Requires 2-qubit decomposition cirq.SWAP(q0, q1), cirq.SWAP(q1, q0)**-1, cirq.SWAP(q0, q1)**0.75, # Requires 2-qubit decomposition cirq.CCZ(q0, q1, q2), cirq.CCX(q0, q1, q2), cirq.CCZ(q0, q1, q2)**0.5, cirq.CCX(q0, q1, q2)**0.5, cirq.CSWAP(q0, q1, q2), cirq.XX(q0, q1), cirq.XX(q0, q1)**0.75, cirq.YY(q0, q1), cirq.YY(q0, q1)**0.75, cirq.ZZ(q0, q1), cirq.ZZ(q0, q1)**0.75, cirq.IdentityGate(1).on(q0), cirq.IdentityGate(3).on(q0, q1, q2), cirq.ISWAP(q2, q0), # Requires 2-qubit decomposition cirq.PhasedXPowGate(phase_exponent=0.111, exponent=0.25).on(q1), cirq.PhasedXPowGate(phase_exponent=0.333, exponent=0.5).on(q1), cirq.PhasedXPowGate(phase_exponent=0.777, exponent=-0.5).on(q1), cirq.wait(q0, nanos=0), cirq.measure(q0, key='xX'), cirq.measure(q2, key='x_a'), cirq.measure(q3, key='X'), cirq.measure(q2, key='x_a'), cirq.measure(q1, q2, q3, key='multi', invert_mask=(False, True)), )
def test_validate_scheduled_operation_adjacent_XXPow_Z(): d = ion_device(3) q0 = cirq.LineQubit(0) q1 = cirq.LineQubit(1) q2 = cirq.LineQubit(2) s = cirq.Schedule(d, [ cirq.ScheduledOperation.op_at_on(cirq.Z(q0), cirq.Timestamp(), d), cirq.ScheduledOperation.op_at_on(cirq.XX(q1, q2), cirq.Timestamp(), d), cirq.ScheduledOperation.op_at_on(cirq.X(q1), cirq.Timestamp(), d), cirq.ScheduledOperation.op_at_on(cirq.measure(q2), cirq.Timestamp(), d), ]) d.validate_schedule(s)
def test_aqt_sampler_ms(): repetitions = 1000 num_qubits = 4 _, qubits = get_aqt_device(num_qubits) sampler = AQTSamplerLocalSimulator() circuit = cirq.Circuit(cirq.Z.on_each(*qubits), cirq.Z.on_each(*qubits)) for _dummy in range(9): circuit.append(cirq.XX(qubits[0], qubits[1])**0.5) circuit.append(cirq.Z(qubits[0])**0.5) results = sampler.run(circuit, repetitions=repetitions) hist = results.histogram(key='m') assert hist[12] > repetitions / 3 assert hist[0] > repetitions / 3
def test_operations_to_part_lens(): qubits = cirq.LineQubit.range(6) ops = [cirq.CZ(*qubits[1:3]), cirq.XX(*qubits[3:5])] part_lens = cca.gates.operations_to_part_lens(qubits, ops) assert part_lens == (1, 2, 2, 1) ops = cirq.CZ(qubits[1], qubits[3]) with pytest.raises(ValueError): cca.gates.operations_to_part_lens(qubits, ops) ops = [cirq.CZ(*qubits[1:3]), cirq.CZ(*qubits[2:4])] with pytest.raises(ValueError): cca.gates.operations_to_part_lens(qubits, ops)
def two_qubit_unitary(bits, symbols): """Make a Cirq circuit that creates an arbitrary two qubit unitary. Bits: 2 Symbols: 15 """ # Corollary 6 of https://arxiv.org/pdf/quant-ph/0507171.pdf circuit = cirq.Circuit() circuit += one_qubit_unitary(bits[0], symbols[0:3]) circuit += one_qubit_unitary(bits[1], symbols[3:6]) circuit += [cirq.ZZ(*bits)**symbols[6]] circuit += [cirq.YY(*bits)**symbols[7]] circuit += [cirq.XX(*bits)**symbols[8]] circuit += one_qubit_unitary(bits[0], symbols[9:12]) circuit += one_qubit_unitary(bits[1], symbols[12:]) return circuit
def test_ms_crosstalk_n_noise(): num_qubits = 4 noise_mod = AQTNoiseModel() device, qubits = get_aqt_device(num_qubits) circuit = cirq.Circuit(device=device) circuit.append(cirq.XX(qubits[1], qubits[2])**0.5) for moment in circuit.moments: noisy_moment = noise_mod.noisy_moment(moment, qubits) assert noisy_moment == [ (cirq.XX**0.5).on(cirq.LineQubit(1), cirq.LineQubit(2)), cirq.depolarize(p=0.01).on(cirq.LineQubit(1)), cirq.depolarize(p=0.01).on(cirq.LineQubit(2)), (cirq.XX**0.015).on(cirq.LineQubit(1), cirq.LineQubit(0)), (cirq.XX**0.015).on(cirq.LineQubit(1), cirq.LineQubit(3)), (cirq.XX**0.015).on(cirq.LineQubit(2), cirq.LineQubit(0)), (cirq.XX**0.015).on(cirq.LineQubit(2), cirq.LineQubit(3)), ]
def test_time_evolution_with_symbolic_parameter(self): # Given hamiltonian = PauliSum([ PauliTerm("X", 0) * PauliTerm("X", 1), PauliTerm("Y", 0, 0.5) * PauliTerm("Y", 1), PauliTerm("Z", 0, 0.3) * PauliTerm("Z", 1), ]) time_symbol = sympy.Symbol("t") time_value = 0.4 symbols_map = [(time_symbol, time_value)] order = 2 circuit = cirq.Circuit() q1 = cirq.LineQubit(0) q2 = cirq.LineQubit(1) for _ in range(0, order): circuit.append( cirq.XX(q1, q2)**(hamiltonian.terms[0].coefficient * 2 * time_value / order / pi)) circuit.append( cirq.YY(q1, q2)**(hamiltonian.terms[1].coefficient * 2 * time_value / order / pi)) circuit.append( cirq.ZZ(q1, q2)**(hamiltonian.terms[2].coefficient * 2 * time_value / order / pi)) target_unitary = circuit._unitary_() # When unitary_evolution_symbolic = time_evolution(hamiltonian, time_symbol, trotter_order=order) unitary_evolution = unitary_evolution_symbolic.evaluate(symbols_map) final_unitary = unitary_evolution.to_unitary() # Then self.assertEqual( compare_unitary(final_unitary, target_unitary, tol=1e-10), True)
(cirq.ControlledGate(cirq.ControlledGate(cirq.CCZ))(*cirq.LineQubit.range(5)), True), (GateUsingWorkspaceForApplyUnitary()(cirq.NamedQubit('q1')), True), (GateAllocatingNewSpaceForResult()(cirq.NamedQubit('q1')), True), ( cirq.MatrixGate(np.kron(*(cirq.unitary(cirq.H),) * 2), qid_shape=(4,)).on( cirq.NamedQid("q", 4) ), False, ), ( cirq.MatrixGate(cirq.testing.random_unitary(4, random_state=1234)).on( cirq.NamedQubit('q1'), cirq.NamedQubit('q2') ), False, ), (cirq.XX(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')) ** sympy.Symbol("s"), True), (cirq.DiagonalGate(sympy.symbols("s1, s2")).on(cirq.NamedQubit("q")), False), ], ) def test_controlled_operation_is_consistent( gate: cirq.GateOperation, should_decompose_to_target: bool ): cb = cirq.NamedQubit('ctr') cgate = cirq.ControlledOperation([cb], gate) cirq.testing.assert_implements_consistent_protocols(cgate) cirq.testing.assert_decompose_ends_at_default_gateset( cgate, ignore_known_gates=not should_decompose_to_target ) cgate = cirq.ControlledOperation([cb], gate, control_values=[0]) cirq.testing.assert_implements_consistent_protocols(cgate)
def test_complex_pad(self): """Test trickier padding.""" bit = cirq.GridQubit(0, 0) bit2 = cirq.GridQubit(0, 1) circuit = cirq.Circuit( cirq.X(bit)**sympy.Symbol('alpha'), cirq.Y(bit)**sympy.Symbol('alpha'), cirq.Z(bit)**sympy.Symbol('alpha'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) circuit2 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('beta'), cirq.Y(bit)**sympy.Symbol('beta'), cirq.Z(bit)**sympy.Symbol('beta'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) circuit3 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('alpha'), cirq.Y(bit)**sympy.Symbol('alpha'), cirq.Z(bit)**sympy.Symbol('alpha'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) inputs = util.convert_to_tensor([circuit, circuit2, circuit3]) symbols = tf.convert_to_tensor(['alpha', 'beta', 'gamma']) new = tf.convert_to_tensor(['new', 'old', 'nothing']) res = tfq_ps_util_ops.tfq_ps_symbol_replace(inputs, symbols, new) output = util.from_tensor(res) correct_000 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('new'), cirq.Y(bit)**sympy.Symbol('alpha'), cirq.Z(bit)**sympy.Symbol('alpha'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) correct_001 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('alpha'), cirq.Y(bit)**sympy.Symbol('new'), cirq.Z(bit)**sympy.Symbol('alpha'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) correct_002 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('alpha'), cirq.Y(bit)**sympy.Symbol('alpha'), cirq.Z(bit)**sympy.Symbol('new'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) correct_003 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('alpha'), cirq.Y(bit)**sympy.Symbol('alpha'), cirq.Z(bit)**sympy.Symbol('alpha'), cirq.XX(bit, bit2)**sympy.Symbol('new')) self.assertEqual(correct_000, output[0][0][0]) self.assertEqual(correct_001, output[0][0][1]) self.assertEqual(correct_002, output[0][0][2]) self.assertEqual(correct_003, output[0][0][3]) self.assertEqual(correct_000, output[2][0][0]) self.assertEqual(correct_001, output[2][0][1]) self.assertEqual(correct_002, output[2][0][2]) self.assertEqual(correct_003, output[2][0][3]) correct_110 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('old'), cirq.Y(bit)**sympy.Symbol('beta'), cirq.Z(bit)**sympy.Symbol('beta'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) correct_111 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('beta'), cirq.Y(bit)**sympy.Symbol('old'), cirq.Z(bit)**sympy.Symbol('beta'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) correct_112 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('beta'), cirq.Y(bit)**sympy.Symbol('beta'), cirq.Z(bit)**sympy.Symbol('old'), cirq.XX(bit, bit2)**sympy.Symbol('alpha')) correct_113 = cirq.Circuit() self.assertEqual(correct_110, output[1][1][0]) self.assertEqual(correct_111, output[1][1][1]) self.assertEqual(correct_112, output[1][1][2]) self.assertEqual(correct_113, output[1][1][3]) correct_100 = cirq.Circuit( cirq.X(bit)**sympy.Symbol('beta'), cirq.Y(bit)**sympy.Symbol('beta'), cirq.Z(bit)**sympy.Symbol('beta'), cirq.XX(bit, bit2)**sympy.Symbol('new')) correct_101 = cirq.Circuit() correct_102 = cirq.Circuit() correct_103 = cirq.Circuit() self.assertEqual(correct_100, output[1][0][0]) self.assertEqual(correct_101, output[1][0][1]) self.assertEqual(correct_102, output[1][0][2]) self.assertEqual(correct_103, output[1][0][3]) correct_220 = cirq.Circuit() correct_221 = cirq.Circuit() correct_222 = cirq.Circuit() correct_223 = cirq.Circuit() self.assertEqual(correct_220, output[2][2][0]) self.assertEqual(correct_221, output[2][2][1]) self.assertEqual(correct_222, output[2][2][2]) self.assertEqual(correct_223, output[2][2][3]) correct = cirq.Circuit() for i in range(3): for j in range(3): for k in range(3): if i != j and (not (i == 2 and j == 0)) \ and (not (i == 1 and j == 0)): self.assertEqual(correct, output[i][j][k])
def to_cirq(self, input_cirq_qubits=None): """Convert to a cirq gate. Args: input_cirq_qubits: list[cirq.LineQubit] (optional) a list of cirq Qubits that the gate can act on. If not provided the function will generate new cirq.LineQubit objects. Returns: A cirq Circuit object that corresponds to the specification of the quantum gate. In the special case the gate itself was natively generated from cirq, the function will faithfully reproduce the original GateOperation object, taking into account whether the gate acts on GridQubit objects or LineQubit objects. In the other cases the resulting cirq gate simply assumes that the qubits are LineQubit objects. """ if self.name not in ALL_GATES: sys.exit("Gate {} currently not supported.".format(self.name)) q_inds = [] q_inds.append(self.qubits[0].index) if len(self.qubits) >= 2: q_inds.append(self.qubits[1].index) if len(self.qubits) >= 3: q_inds.append(self.qubits[2].index) cirq_qubits = [] if input_cirq_qubits == None: for q in self.qubits: if q.info["label"] == "cirq": qkey = q.info["QubitKey"] if q.info["QubitType"] == "GridQubit": cirq_qubits.append(cirq.GridQubit(qkey[0], qkey[1])) if q.info["QubitType"] == "LineQubit": cirq_qubits.append(cirq.LineQubit(qkey)) else: cirq_qubits.append(cirq.LineQubit(q.index)) else: cirq_qubits = [ input_cirq_qubits[x] for x in [q.index for q in self.qubits] ] if len(self.params) > 0: params = self.params # single-qubit gates if self.name == "I": # Identity return cirq.I(cirq_qubits[0]) if self.name == "X": # Pauli X return cirq.X(cirq_qubits[0]) if self.name == "Y": # Pauli Y return cirq.Y(cirq_qubits[0]) if self.name == "Z": # Pauli Z return cirq.Z(cirq_qubits[0]) if self.name == "H": # Hadamard return cirq.H(cirq_qubits[0]) if self.name == "S": # S gate return cirq.S(cirq_qubits[0]) if self.name == "T": # T gate return cirq.T(cirq_qubits[0]) if self.name == "Rx": # Single-qubit X rotation return cirq.rx(params[0])(cirq_qubits[0]) if self.name == "Ry": # Single-qubit Y rotation return cirq.ry(params[0])(cirq_qubits[0]) if self.name == "Rz": # Single-qubit Z rotation return cirq.rz(params[0])(cirq_qubits[0]) if self.name == "PHASE": # Phase gate return cirq.Z(cirq_qubits[0])**(params[0] / pi) if self.name == "ZXZ": # PhasedXPowGate gate g = cirq.PhasedXPowGate(phase_exponent=params[0] / pi, exponent=params[1] / pi) return g(cirq_qubits[0]) if self.name == "RH": # HPowGate g = cirq.H**(params[0] / pi) return g(cirq_qubits[0]) if self.name == "Da": # Damping alpha gate g = DampingAlpha(params[0]) return g(cirq_qubits[0]) if self.name == "Db": # Damping beta gate g = DampingBeta(params[0]) return g(cirq_qubits[0]) # two-qubit gates if self.name == "CNOT": return cirq.CNOT(cirq_qubits[0], cirq_qubits[1]) if self.name == "CZ": return cirq.CZ(cirq_qubits[0], cirq_qubits[1]) if self.name == "CPHASE": return cirq.CZPowGate(exponent=params[0] / pi)(cirq_qubits[0], cirq_qubits[1]) if self.name == "SWAP": return cirq.SWAP(cirq_qubits[0], cirq_qubits[1]) if self.name == "XX": return cirq.XX(cirq_qubits[0], cirq_qubits[1])**(params[0] * 2 / pi) if self.name == "YY": return cirq.YY(cirq_qubits[0], cirq_qubits[1])**(params[0] * 2 / pi) if self.name == "ZZ": return cirq.ZZ(cirq_qubits[0], cirq_qubits[1])**(params[0] * 2 / pi)
def xxz_chain(qubits, boundary_condition="closed", data_dir=None): """1D XXZ model quantum data set. $$ H = \sum_{i} \sigma_i^x \sigma_{i+1}^x + \sigma_i^y \sigma_{i+1}^y + \Delta\sigma_i^z \sigma_{i+1}^z $$ Contains 76 circuit parameterizations corresponding to the ground states of the 1D XXZ chain for g in [0.3,1.8]. This dataset contains 76 datapoints. Each datapoint is represented by a circuit (`cirq.Circuit`), a label (Python `float`) a Hamiltonian (`cirq.PauliSum`) and some additional metadata. Each Hamiltonian in a datapoint is a 1D XXZ chain with boundary condition `boundary_condition` on `qubits` whos order parameter dictates the value of label. The circuit in a datapoint prepares (an approximation to) the ground state of the Hamiltonian in the datapoint. Example usage: >>> qbs = cirq.GridQubit.rect(4, 1) >>> circuits, labels, pauli_sums, addinfo = ... tfq.datasets.xxz_chain(qbs, "closed") You can print the available order parameters >>> [info.g for info in addinfo] [0.30, 0.32, 0.34, ... ,1.76, 1.78, 1.8] and the circuit corresponding to the ground state for a certain order parameter >>> print(circuits[10]) ┌──────────────────┐ ┌──────────────────┐ (0, 0): ───X───H───@─────────────ZZ─────────────────────YY────────── ... │ │ │ (1, 0): ───X───────X────ZZ───────┼─────────────YY───────┼─────────── ... │ │ │ │ (2, 0): ───X───H───@────ZZ^-0.922┼─────────────YY^-0.915┼─────────── ... │ │ │ (3, 0): ───X───────X─────────────ZZ^-0.922──────────────YY^-0.915─── ... └──────────────────┘ └──────────────────┘ The labels indicate the phase of the system >>> labels[10] 0 Additionally, you can obtain the `cirq.PauliSum` representation of the Hamiltonian >>> print(pauli_sums[10]) 0.400*Z((0, 0))*Z((1, 0))+0.400*Z((1, 0))*Z((2, 0))+ ... +1.000*Y((0, 0))*Y((3, 0))+1.000*X((0, 0))*X((3, 0)) The fourth output, `addinfo`, contains additional information about each instance of the system (see `tfq.datasets.spin_system.SpinSystem` ). For instance, you can print the ground state obtained from exact diagonalization >>> addinfo[10].gs [-8.69032854e-18-6.58023246e-20j 4.54546402e-17+3.08736567e-17j -9.51026525e-18+2.42638062e-17j 4.52284042e-02+3.18111120e-01j ... 4.52284042e-02+3.18111120e-01j -6.57974275e-18-3.84526414e-17j -1.60673943e-17+5.79767820e-17j 2.86193021e-17-5.06694574e-17j] with corresponding ground state energy >>> addinfo[10].gs_energy -6.744562646538039 You can also inspect the parameters >>> addinfo[10].params {'theta_0': 1.0780547, 'theta_1': 0.99271035, 'theta_2': 1.0854135, ... and change them to experiment with different parameter values by using the unresolved variational circuit returned by xxzchain >>> new_params = {} ... for symbol_name, value in addinfo[10].params.items(): ... new_params[symbol_name] = 0.5 * value >>> new_params {'theta_0': 0.5390273332595825, 'theta_1': 0.49635517597198486, ... >>> new_circuit = cirq.resolve_parameters(addinfo[10].var_circuit, ... new_params) >>> print(new_circuit) ┌──────────────────┐ ┌──────────────────┐ (0, 0): ───X───H───@─────────────ZZ─────────────────────YY────────── ... │ │ │ (1, 0): ───X───────X────ZZ───────┼─────────────YY───────┼─────────── ... │ │ │ │ (2, 0): ───X───H───@────ZZ^(7/13)┼─────────────YY^0.543 ┼─────────── ... │ │ │ (3, 0): ───X───────X─────────────ZZ^(7/13)──────────────YY^0.543 ─── ... └──────────────────┘ └──────────────────┘ Args: qubits: Python `lst` of `cirq.GridQubit`s. Supported number of spins are [4, 8, 12, 16]. boundary_condition: Python `str` indicating the boundary condition of the chain. Supported boundary conditions are ["closed"]. data_dir: Optional Python `str` location where to store the data on disk. Defaults to `/tmp/.keras`. Returns: A Python `lst` cirq.Circuit of depth len(qubits) / 2 with resolved parameters. A Python `lst` of labels, 0, for the critical metallic phase (`Delta<=1`) and 1 for the insulating phase (`Delta>1`). A Python `lst` of `cirq.PauliSum`s. A Python `lst` of `namedtuple` instances containing the following fields: - `g`: Numpy `float` order parameter. - `gs`: Complex `np.ndarray` ground state wave function from exact diagonalization. - `gs_energy`: Numpy `float` ground state energy from exact diagonalization. - `res_energy`: Python `float` residual between the circuit energy and the exact energy from exact diagonalization. - `fidelity`: Python `float` overlap between the circuit state and the exact ground state from exact diagonalization. - `params`: Dict with Python `str` keys and Numpy`float` values. Contains $M \times P $ parameters. Here $M$ is the number of parameters per circuit layer and $P$ the circuit depth. - `var_circuit`: Variational `cirq.Circuit` quantum circuit with unresolved Sympy parameters. """ supported_n = [4, 8, 12, 16] supported_bc = ["closed"] if any(isinstance(q, list) for q in qubits): raise TypeError("qubits must be a one-dimensional list") if not all(isinstance(q, cirq.GridQubit) for q in qubits): raise TypeError("qubits must be a list of cirq.GridQubit objects.") nspins = len(qubits) depth = nspins // 2 if nspins not in supported_n: raise ValueError("Supported number of spins are {}, received {}".format( supported_n, nspins)) if boundary_condition not in supported_bc: raise ValueError( "Supported boundary conditions are {}, received {}".format( supported_bc, boundary_condition)) data_path = _download_spin_data('XXZ_chain', boundary_condition, nspins, data_dir) name_generator = unique_name() # 4 * N/2 parameters. symbol_names = [next(name_generator) for _ in range(2 * nspins)] symbols = [sympy.Symbol(name) for name in symbol_names] # Define the circuit. circuit = cirq.Circuit(cirq.X.on_each(qubits)) even_qubits = qubits[::2] odd_qubits = qubits[1::2] circuit.append(cirq.H(qubits[i]) for i in range(0, nspins, 2)) circuit.append(cirq.CNOT(q1, q2) for q1, q2 in zip(even_qubits, odd_qubits)) for d in range(depth): for q1, q2 in zip(odd_qubits, even_qubits[1:]): circuit.append(cirq.ZZ(q1, q2)**(symbols[d])) circuit.append(cirq.YY(q1, q2)**(symbols[d + depth])) circuit.append(cirq.XX(q1, q2)**(symbols[d + depth])) if boundary_condition == "closed": circuit.append(cirq.ZZ(qubits[-1], qubits[0])**(symbols[d])) circuit.append(cirq.YY(qubits[-1], qubits[0])**(symbols[d + depth])) circuit.append(cirq.XX(qubits[-1], qubits[0])**(symbols[d + depth])) for q1, q2 in zip(even_qubits, odd_qubits): circuit.append(cirq.ZZ(q1, q2)**(symbols[d + 2 * depth])) circuit.append(cirq.YY(q1, q2)**(symbols[d + 3 * depth])) circuit.append(cirq.XX(q1, q2)**(symbols[d + 3 * depth])) # Initiate lists. resolved_circuits = [] hamiltonians = [] order_parameters = [] additional_info = [] labels = [] # Load the data and append to the lists. for i, directory in enumerate(x for x in os.listdir(data_path)): # The folders are named according to the order value data they contain. g = float(directory) with open(os.path.join(data_path, directory, "stats.txt"), "r") as file: lines = file.readlines() res_e = float(lines[0].split("=")[1].strip("\n")) fidelity = float(lines[2].split("=")[1].strip("\n")) order_parameters.append(g) params = np.load(os.path.join(data_path, directory, "params.npy")) \ / np.pi # Parameters are stored as np.float32, but cirq expects np.float64 # See https://github.com/quantumlib/Cirq/issues/3359 params = params.astype(np.float) additional_info.append( SpinSystemInfo(g=g, gs=np.load( os.path.join(data_path, directory, "groundstate.npy"))[:, 0], gs_energy=np.load( os.path.join(data_path, directory, "energy.npy"))[0], res_energy=res_e, fidelity=fidelity, params=dict(zip(symbol_names, params.flatten())), var_circuit=circuit)) # Resolve the circuit parameters. resolved_circuit = cirq.resolve_parameters(circuit, additional_info[i].params) resolved_circuits.append(resolved_circuit) # Make the PauliSum. paulisum = sum(order_parameters[i] * cirq.Z(q1) * cirq.Z(q2) + cirq.Y(q1) * cirq.Y(q2) + cirq.X(q1) * cirq.X(q2) for q1, q2 in zip(qubits, qubits[1:])) if boundary_condition == "closed": paulisum += order_parameters[i] * cirq.Z(qubits[0]) * cirq.Z( qubits[-1]) + cirq.Y(qubits[0]) * cirq.Y(qubits[-1]) + cirq.X( qubits[0]) * cirq.X(qubits[-1]) hamiltonians.append(paulisum) # Set labels for the different phases. if order_parameters[i] <= 1.0: labels.append(0) else: labels.append(1) # Make sure that the data is ordered from g=0.2 to g=1.8. _, resolved_circuits, labels, hamiltonians, additional_info = zip(*sorted( zip(order_parameters, resolved_circuits, labels, hamiltonians, additional_info))) return resolved_circuits, labels, hamiltonians, additional_info
def matrix_to_sycamore_operations( target_qubits: List[cirq.GridQubit], matrix: np.ndarray) -> Tuple[cirq.OP_TREE, List[cirq.GridQubit]]: """A method to convert a unitary matrix to a list of Sycamore operations. This method will return a list of `cirq.Operation`s using the qubits and (optionally) ancilla qubits to implement the unitary matrix `matrix` on the target qubits `qubits`. The operations are also supported by `cirq.google.gate_sets.SYC_GATESET`. Args: target_qubits: list of qubits the returned operations will act on. The qubit order defined by the list is assumed to be used by the operations to implement `matrix`. matrix: a matrix that is guaranteed to be unitary and of size (2**len(qs), 2**len(qs)). Returns: A tuple of operations and ancilla qubits allocated. Operations: In case the matrix is supported, a list of operations `ops` is returned. `ops` acts on `qs` qubits and for which `cirq.unitary(ops)` is equal to `matrix` up to certain tolerance. In case the matrix is not supported, it might return NotImplemented to reduce the noise in the judge output. Ancilla qubits: In case ancilla qubits are allocated a list of ancilla qubits. Otherwise an empty list. . """ def optimize_circuit(circ): ouut = [] converter = cirq.google.ConvertToSycamoreGates() for _ in circ.all_operations(): ouut.append(converter.convert(_)) return cirq.google.optimized_for_sycamore( cirq.Circuit(ouut), optimizer_type="sycamore"), [] if np.trace(matrix) == len(matrix): return [], [] if len(matrix) == 2: try: comparison = matrix == cirq.unitary(cirq.Z) if (comparison.all()): return cirq.Z(target_qubits[0]), [] comparison = matrix == cirq.unitary(cirq.X) if (comparison.all()): return cirq.X(target_qubits[0]), [] comparison = matrix == cirq.unitary(cirq.Y) if (comparison.all()): return cirq.Y(target_qubits[0]), [] comparison = matrix == cirq.unitary(cirq.H) if (comparison.all()): return cirq.H.on(target_qubits[0]), [] comparison = matrix == cirq.unitary(cirq.S) if (comparison.all()): return cirq.S(target_qubits[0]), [] comparison = matrix == cirq.unitary(cirq.T) if (comparison.all()): return cirq.T(target_qubits[0]), [] except [TypeError, ValueError]: return NotImplemented, [] if len(matrix) == 4: try: comparison = matrix == cirq.unitary(cirq.CNOT) if (comparison.all()): return optimize_circuit( cirq.Circuit(cirq.CNOT(target_qubits[0], target_qubits[1]))) comparison = matrix == cirq.unitary(cirq.XX) if (comparison.all()): return optimize_circuit( cirq.Circuit(cirq.XX(target_qubits[0], target_qubits[1]))) comparison = matrix == cirq.unitary(cirq.YY) if (comparison.all()): return optimize_circuit( cirq.Circuit(cirq.YY(target_qubits[0], target_qubits[1]))) comparison = matrix == cirq.unitary(cirq.ZZ) if (comparison.all()): return optimize_circuit( cirq.Circuit(cirq.ZZ(target_qubits[0], target_qubits[1]))) comparison = matrix == cirq.unitary(cirq.google.SYC) if (comparison.all()): return optimize_circuit( cirq.Circuit( cirq.google.SYC(target_qubits[0], target_qubits[1]))) except TypeError: return NotImplemented, [] if len(matrix) == 8: try: comparison = matrix == cirq.unitary(cirq.CCX) if (comparison.all()): return optimize_circuit( cirq.Circuit( cirq.CCX(target_qubits[0], target_qubits[1], target_qubits[2]))) comparison = matrix == cirq.unitary(cirq.CSWAP) if (comparison.all()): return optimize_circuit( cirq.Circuit( cirq.CSWAP(target_qubits[0], target_qubits[1], target_qubits[2]))) comparison = matrix == cirq.unitary(cirq.CCZ) if (comparison.all()): return optimize_circuit( cirq.Circuit( cirq.CCZ(target_qubits[0], target_qubits[1], target_qubits[2]))) comparison = matrix == cirq.unitary( cirq.ControlledGate(cirq.ISWAP**0.5, 1)) if (comparison.all()): return cirq.ControlledGate(cirq.ISWAP**0.5, 1) except TypeError: return NotImplemented, [] if len(matrix) == 16: try: comparison = matrix == cirq.unitary( cirq.ControlledGate(cirq.ISWAP**0.5, 2)) if (comparison.all()): return optimize_circuit( cirq.Circuit( cirq.ControlledGate(sub_gate=cirq.ISWAP**0.5).on( target_qubits[2], target_qubits[0], target_qubits[1]))) except TypeError: return NotImplemented, [] return NotImplemented, []
(cirq.ControlledGate(cirq.ControlledGate( cirq.CCZ))(*cirq.LineQubit.range(5)), True), (GateUsingWorkspaceForApplyUnitary()(cirq.NamedQubit('q1')), True), (GateAllocatingNewSpaceForResult()(cirq.NamedQubit('q1')), True), ( cirq.MatrixGate(np.kron(*(cirq.unitary(cirq.H), ) * 2), qid_shape=(4, )).on(cirq.NamedQid("q", 4)), False, ), ( cirq.MatrixGate(cirq.testing.random_unitary( 4, random_state=1234)).on(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')), False, ), (cirq.XX(cirq.NamedQubit('q1'), cirq.NamedQubit('q2'))** sympy.Symbol("s"), True), (cirq.DiagonalGate(sympy.symbols("s1, s2")).on( cirq.NamedQubit("q")), False), ], ) def test_controlled_operation_is_consistent(gate: cirq.GateOperation, should_decompose_to_target: bool): cb = cirq.NamedQubit('ctr') cgate = cirq.ControlledOperation([cb], gate) cirq.testing.assert_implements_consistent_protocols(cgate) cirq.testing.assert_decompose_ends_at_default_gateset( cgate, ignore_known_gates=not should_decompose_to_target) cgate = cirq.ControlledOperation([cb], gate, control_values=[0]) cirq.testing.assert_implements_consistent_protocols(cgate)
def test_known_two_qubit_op_decomposition(op, theta_range): for theta_val in theta_range: op_resolved = cirq.resolve_parameters(op, {'theta': theta_val}, recursive=False) known_2q_circuit = cirq.Circuit(cg.known_2q_op_to_sycamore_operations(op_resolved)) matrix_2q_circuit = cirq.Circuit( cg.two_qubit_matrix_to_sycamore_operations(q[0], q[1], cirq.unitary(op_resolved)) ) assert_implements(known_2q_circuit, op_resolved) assert_implements(matrix_2q_circuit, op_resolved) @pytest.mark.parametrize( 'op', [ cirq.CircuitOperation(cirq.FrozenCircuit(cirq.SWAP(*q), cirq.ZZ(*q), cirq.SWAP(*q))), cirq.X(q[0]), cirq.XX(*q) ** theta, cirq.FSimGate(0.25, 0.85).on(*q), cirq.XX(*q), cirq.YY(*q), *[cirq.testing.random_unitary(4, random_state=1234) for _ in range(10)], ], ) def test_unknown_two_qubit_op_decomposition(op): assert cg.known_2q_op_to_sycamore_operations(op) is None if cirq.has_unitary(op) and cirq.num_qubits(op) == 2: matrix_2q_circuit = cirq.Circuit( cg.two_qubit_matrix_to_sycamore_operations(q[0], q[1], cirq.unitary(op)) ) assert_implements(matrix_2q_circuit, op)
def _get_circuit_proto_pairs(): q0 = cirq.GridQubit(0, 0) q1 = cirq.GridQubit(0, 1) pairs = [ # HPOW and aliases. (cirq.Circuit(cirq.HPowGate(exponent=0.3)(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.HPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.HPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.H(q0)), _build_gate_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # XPOW and aliases. (cirq.Circuit(cirq.XPowGate(exponent=0.3)(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.XPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.XPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.X(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # YPOW and aliases (cirq.Circuit(cirq.YPowGate(exponent=0.3)(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.YPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.YPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.Y(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # ZPOW and aliases. (cirq.Circuit(cirq.ZPowGate(exponent=0.3)(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.ZPowGate(exponent=sympy.Symbol('alpha'))(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0'])), (cirq.Circuit(cirq.ZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0'])), (cirq.Circuit(cirq.Z(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0'])), # XXPow and aliases (cirq.Circuit(cirq.XXPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.XXPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.XXPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.XX(q0, q1)), _build_gate_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # YYPow and aliases (cirq.Circuit(cirq.YYPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.YYPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.YYPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.YY(q0, q1)), _build_gate_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # ZZPow and aliases (cirq.Circuit(cirq.ZZPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.ZZPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.ZZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.ZZ(q0, q1)), _build_gate_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # CZPow and aliases (cirq.Circuit(cirq.CZPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.CZPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.CZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.CZ(q0, q1)), _build_gate_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # CNOTPow and aliases (cirq.Circuit(cirq.CNotPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.CNotPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.CNotPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.CNOT(q0, q1)), _build_gate_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # SWAPPow and aliases (cirq.Circuit(cirq.SwapPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.SwapPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.SwapPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.SWAP(q0, q1)), _build_gate_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # ISWAPPow and aliases (cirq.Circuit(cirq.ISwapPowGate(exponent=0.3)(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], [0.3, 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.ISwapPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 1.0, 0.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.ISwapPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], ['alpha', 3.1, 0.0], ['0_0', '0_1'])), (cirq.Circuit(cirq.ISWAP(q0, q1)), _build_gate_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, 0.0], ['0_0', '0_1'])), # PhasedXPow and aliases (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=0.9, exponent=0.3, global_shift=0.2)(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], [0.9, 1.0, 0.3, 1.0, 0.2], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=sympy.Symbol('alpha'), exponent=0.3)(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], ['alpha', 1.0, 0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=3.1 * sympy.Symbol('alpha'), exponent=0.3)(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], ['alpha', 3.1, 0.3, 1.0, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=0.9, exponent=sympy.Symbol('beta'))(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], [0.9, 1.0, 'beta', 1.0, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=0.9, exponent=5.1 * sympy.Symbol('beta'))(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], [0.9, 1.0, 'beta', 5.1, 0.0], ['0_0'])), (cirq.Circuit( cirq.PhasedXPowGate(phase_exponent=3.1 * sympy.Symbol('alpha'), exponent=5.1 * sympy.Symbol('beta'))(q0)), _build_gate_proto("PXP", [ 'phase_exponent', 'phase_exponent_scalar', 'exponent', 'exponent_scalar', 'global_shift' ], ['alpha', 3.1, 'beta', 5.1, 0.0], ['0_0'])), # RX, RY, RZ with symbolization is tested in special cases as the # string comparison of the float converted sympy.pi does not happen # smoothly. See: test_serialize_deserialize_special_case_one_qubit (cirq.Circuit(cirq.rx(np.pi)(q0)), _build_gate_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, -0.5], ['0_0'])), (cirq.Circuit(cirq.ry(np.pi)(q0)), _build_gate_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, -0.5], ['0_0'])), (cirq.Circuit(cirq.rz(np.pi)(q0)), _build_gate_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'], [1.0, 1.0, -0.5], ['0_0'])), # Identity (cirq.Circuit(cirq.I(q0)), _build_gate_proto("I", ['unused'], [True], ['0_0'])), # FSimGate (cirq.Circuit(cirq.FSimGate(theta=0.1, phi=0.2)(q0, q1)), _build_gate_proto("FSIM", ['theta', 'theta_scalar', 'phi', 'phi_scalar'], [0.1, 1.0, 0.2, 1.0], ['0_0', '0_1'])), (cirq.Circuit( cirq.FSimGate(theta=2.1 * sympy.Symbol("alpha"), phi=1.3 * sympy.Symbol("beta"))(q0, q1)), _build_gate_proto("FSIM", ['theta', 'theta_scalar', 'phi', 'phi_scalar'], ['alpha', 2.1, 'beta', 1.3], ['0_0', '0_1'])), ] return pairs
print(qc) ndtotext_print(qc.unitary()) # exit() # class ISWAP(cirq.ISwapPowGate): # def __init__(self, target): # super(ISWAP, self).__init__() qubits = cirq.GridQubit.rect(2, 2) C1, C2, T1, T2 = qubits qc = cirq.Circuit() # qc = B2A_basis(qc, C1, C2) # Change output matrix to B-basis (easier to check for mistakes) # qc = B2A_basis(qc, T1, T2) # --- Very first one --- qc.append(cirq.XX(T1, T2)) qc.append(cirq.ZPowGate().on(T2).controlled_by(C1, C2, T1)**(t/π)) # NOTICE: Cancel out π qc.append(cirq.XX(T1, T2)) qc.append(cirq.XX(C1, C2)) qc.append(cirq.ZPowGate().on(C1).controlled_by(C2, T1, T2)**(-t/π)) qc.append(cirq.XX(C1, C2)) # --- Very first one end --- # --- Second two --- A2B_basis(qc, C1, C2) # This is to do the oper |11> <-> |+>, |00> <-> |-> A2B_basis(qc, T1, T2) X_on_all(qc, qubits) B2A_basis(qc, C1, C2) B2A_basis(qc, T1, T2) # CCiSWAP(t) then CCiSWAP(-t) qc.append(cirq.ISwapPowGate().on(T1, T2).controlled_by(C1, C2)**(-2*t/π)) # NOTICE: Swapped signs and cancel out π/2
# A simple Quantum circuit using cirq input_qubits = cirq.GridQubit.rect(1, 2) # 1x2 grid. model_circuit = cirq.Circuit() alpha1 = sympy.Symbol('a1') model_circuit.append(cirq.rx(alpha1)(input_qubits[0])) alpha2 = sympy.Symbol('a2') model_circuit.append(cirq.rx(alpha2)(input_qubits[1])) alpha3 = sympy.Symbol('a3') model_circuit.append(cirq.XX(input_qubits[1],input_qubits[0])**alpha3) alpha4 = sympy.Symbol('a4') model_circuit.append(cirq.H(input_qubits[0])**alpha4) alpha5 = sympy.Symbol('a5') model_circuit.append(cirq.H(input_qubits[1])**alpha5) model_readout = [cirq.X(input_qubits[0]),cirq.X(input_qubits[1])] print(model_circuit) DataList = ["HLine","VLine", "Triangle", "Circle"] methodList = ["Ground_Truth","Quantum", "Hybrid", "Single_Dense"]
def test_cirq_to_circuit() -> None: q0 = cq.LineQubit(0) q1 = cq.LineQubit(1) q2 = cq.LineQubit(2) gate = cirq_to_circuit(cq.Circuit(cq.X(q0)))[0] assert isinstance(gate, qf.X) assert gate.qubits == (0, ) gate = cirq_to_circuit(cq.Circuit(cq.X(q1)**0.4))[0] assert isinstance(gate, qf.XPow) assert gate.qubits == (1, ) gate = cirq_to_circuit(cq.Circuit(cq.CZ(q1, q0)))[0] assert isinstance(gate, qf.CZ) assert gate.qubits == (1, 0) gate = cirq_to_circuit(cq.Circuit(cq.CZ(q1, q0)**0.3))[0] assert isinstance(gate, qf.CZPow) assert gate.qubits == (1, 0) assert gate.param("t") == 0.3 gate = cirq_to_circuit(cq.Circuit(cq.CNOT(q0, q1)))[0] assert isinstance(gate, qf.CNot) assert gate.qubits == (0, 1) gate = cirq_to_circuit(cq.Circuit(cq.CNOT(q0, q1)**0.25))[0] assert isinstance(gate, qf.CNotPow) assert gate.qubits == (0, 1) assert gate.param("t") == 0.25 gate = cirq_to_circuit(cq.Circuit(cq.SWAP(q0, q1)))[0] assert isinstance(gate, qf.Swap) gate = cirq_to_circuit(cq.Circuit(cq.ISWAP(q0, q1)))[0] assert isinstance(gate, qf.ISwap) gate = cirq_to_circuit(cq.Circuit(cq.CSWAP(q0, q1, q2)))[0] assert isinstance(gate, qf.CSwap) gate = cirq_to_circuit(cq.Circuit(cq.CCX(q0, q1, q2)))[0] assert isinstance(gate, qf.CCNot) gate = cirq_to_circuit(cq.Circuit(cq.CCZ(q0, q1, q2)))[0] assert isinstance(gate, qf.CCZ) gate = cirq_to_circuit(cq.Circuit(cq.I(q0)))[0] assert isinstance(gate, qf.I) gate = cirq_to_circuit(cq.Circuit(cq.XX(q0, q2)))[0] assert isinstance(gate, qf.XX) assert gate.param("t") == 1.0 gate = cirq_to_circuit(cq.Circuit(cq.XX(q0, q2)**0.3))[0] assert isinstance(gate, qf.XX) assert gate.param("t") == 0.3 gate = cirq_to_circuit(cq.Circuit(cq.YY(q0, q2)))[0] assert isinstance(gate, qf.YY) assert gate.param("t") == 1.0 gate = cirq_to_circuit(cq.Circuit(cq.YY(q0, q2)**0.3))[0] assert isinstance(gate, qf.YY) assert gate.param("t") == 0.3 gate = cirq_to_circuit(cq.Circuit(cq.ZZ(q0, q2)))[0] assert isinstance(gate, qf.ZZ) assert gate.param("t") == 1.0 gate = cirq_to_circuit(cq.Circuit(cq.ZZ(q0, q2)**0.3))[0] assert isinstance(gate, qf.ZZ) assert gate.param("t") == 0.3 # Check that cirq's parity gates are the same as QF's XX, YY, ZZ # up to parity U = (cq.XX(q0, q2)**0.8)._unitary_() gate0 = qf.Unitary(U, [0, 1]) assert qf.gates_close(gate0, qf.XX(0.8, 0, 1)) U = (cq.YY(q0, q2)**0.3)._unitary_() gate0 = qf.Unitary(U, [0, 1]) assert qf.gates_close(gate0, qf.YY(0.3, 0, 1)) U = (cq.ZZ(q0, q2)**0.2)._unitary_() gate0 = qf.Unitary(U, [0, 1]) assert qf.gates_close(gate0, qf.ZZ(0.2, 0, 1))
for i, gate in enumerate(gates): a += gate b -= gate prefix = gates[:i + 1] expected_a = cirq.LinearCombinationOfGates(collections.Counter(prefix)) expected_b = -expected_a assert_linear_combinations_are_equal(a, expected_a) assert_linear_combinations_are_equal(b, expected_b) @pytest.mark.parametrize('op', ( cirq.X(q0), cirq.Y(q1), cirq.XX(q0, q1), cirq.CZ(q0, q1), cirq.FREDKIN(q0, q1, q2), cirq.ControlledOperation((q0, q1), cirq.H(q2)), cirq.ParallelGateOperation(cirq.X, (q0, q1, q2)), cirq.PauliString({ q0: cirq.X, q1: cirq.Y, q2: cirq.Z }), )) def test_empty_linear_combination_of_operations_accepts_all_operations(op): combination = cirq.LinearCombinationOfOperations({}) combination[op] = -0.5j assert len(combination) == 1
import os import string import qdata.parser as parser import qdata.ir as ir import math import sys sys.setrecursionlimit(2000) # Define mappings for operators from a .qasm name to a cirq operator. gate_operators = { 'h': lambda qubits: cirq.H(*qubits), 'x': lambda qubits: cirq.X(*qubits), 'cx': lambda qubits: cirq.CNOT(*qubits), 'zz': lambda qubits: cirq.ZZ(*qubits), 'yy': lambda qubits: cirq.YY(*qubits), 'xx': lambda qubits: cirq.XX(*qubits), } # Define mappings for operators from a .qasm name to a cirq operator. parsed_operators = { 'x': lambda qubits: cirq.X(*qubits), 'y': lambda qubits: cirq.Y(*qubits), 'z': lambda qubits: cirq.Z(*qubits), } def operator_parser_paulisum(operator): """ Return a function that implements the operator defined in the .qasm file. Args: operator:
def test_cirq_qsim_all_supported_gates(self): q0 = cirq.GridQubit(1, 1) q1 = cirq.GridQubit(1, 0) q2 = cirq.GridQubit(0, 1) q3 = cirq.GridQubit(0, 0) circuit = cirq.Circuit( cirq.Moment([ cirq.H(q0), cirq.H(q1), cirq.H(q2), cirq.H(q3), ]), cirq.Moment([ cirq.T(q0), cirq.T(q1), cirq.T(q2), cirq.T(q3), ]), cirq.Moment([ cirq.CZPowGate(exponent=0.7, global_shift=0.2)(q0, q1), cirq.CXPowGate(exponent=1.2, global_shift=0.4)(q2, q3), ]), cirq.Moment([ cirq.XPowGate(exponent=0.3, global_shift=1.1)(q0), cirq.YPowGate(exponent=0.4, global_shift=1)(q1), cirq.ZPowGate(exponent=0.5, global_shift=0.9)(q2), cirq.HPowGate(exponent=0.6, global_shift=0.8)(q3), ]), cirq.Moment([ cirq.CX(q0, q2), cirq.CZ(q1, q3), ]), cirq.Moment([ cirq.X(q0), cirq.Y(q1), cirq.Z(q2), cirq.S(q3), ]), cirq.Moment([ cirq.XXPowGate(exponent=0.4, global_shift=0.7)(q0, q1), cirq.YYPowGate(exponent=0.8, global_shift=0.5)(q2, q3), ]), cirq.Moment([cirq.I(q0), cirq.I(q1), cirq.IdentityGate(2)(q2, q3)]), cirq.Moment([ cirq.rx(0.7)(q0), cirq.ry(0.2)(q1), cirq.rz(0.4)(q2), cirq.PhasedXPowGate(phase_exponent=0.8, exponent=0.6, global_shift=0.3)(q3), ]), cirq.Moment([ cirq.ZZPowGate(exponent=0.3, global_shift=1.3)(q0, q2), cirq.ISwapPowGate(exponent=0.6, global_shift=1.2)(q1, q3), ]), cirq.Moment([ cirq.XPowGate(exponent=0.1, global_shift=0.9)(q0), cirq.YPowGate(exponent=0.2, global_shift=1)(q1), cirq.ZPowGate(exponent=0.3, global_shift=1.1)(q2), cirq.HPowGate(exponent=0.4, global_shift=1.2)(q3), ]), cirq.Moment([ cirq.SwapPowGate(exponent=0.2, global_shift=0.9)(q0, q1), cirq.PhasedISwapPowGate(phase_exponent=0.8, exponent=0.6)(q2, q3), ]), cirq.Moment([ cirq.PhasedXZGate(x_exponent=0.2, z_exponent=0.3, axis_phase_exponent=1.4)(q0), cirq.T(q1), cirq.H(q2), cirq.S(q3), ]), cirq.Moment([ cirq.SWAP(q0, q2), cirq.XX(q1, q3), ]), cirq.Moment([ cirq.rx(0.8)(q0), cirq.ry(0.9)(q1), cirq.rz(1.2)(q2), cirq.T(q3), ]), cirq.Moment([ cirq.YY(q0, q1), cirq.ISWAP(q2, q3), ]), cirq.Moment([ cirq.T(q0), cirq.Z(q1), cirq.Y(q2), cirq.X(q3), ]), cirq.Moment([ cirq.FSimGate(0.3, 1.7)(q0, q2), cirq.ZZ(q1, q3), ]), cirq.Moment([ cirq.ry(1.3)(q0), cirq.rz(0.4)(q1), cirq.rx(0.7)(q2), cirq.S(q3), ]), cirq.Moment([ cirq.MatrixGate( np.array([[0, -0.5 - 0.5j, -0.5 - 0.5j, 0], [0.5 - 0.5j, 0, 0, -0.5 + 0.5j], [0.5 - 0.5j, 0, 0, 0.5 - 0.5j], [0, -0.5 - 0.5j, 0.5 + 0.5j, 0]]))(q0, q1), cirq.MatrixGate( np.array([[0.5 - 0.5j, 0, 0, -0.5 + 0.5j], [0, 0.5 - 0.5j, -0.5 + 0.5j, 0], [0, -0.5 + 0.5j, -0.5 + 0.5j, 0], [0.5 - 0.5j, 0, 0, 0.5 - 0.5j]]))(q2, q3), ]), cirq.Moment([ cirq.MatrixGate(np.array([[1, 0], [0, 1j]]))(q0), cirq.MatrixGate(np.array([[0, -1j], [1j, 0]]))(q1), cirq.MatrixGate(np.array([[0, 1], [1, 0]]))(q2), cirq.MatrixGate(np.array([[1, 0], [0, -1]]))(q3), ]), cirq.Moment([ cirq.riswap(0.7)(q0, q1), cirq.givens(1.2)(q2, q3), ]), cirq.Moment([ cirq.H(q0), cirq.H(q1), cirq.H(q2), cirq.H(q3), ]), ) simulator = cirq.Simulator() cirq_result = simulator.simulate(circuit) qsim_simulator = qsimcirq.QSimSimulator() qsim_result = qsim_simulator.simulate(circuit) assert cirq.linalg.allclose_up_to_global_phase( qsim_result.state_vector(), cirq_result.state_vector())
def to_cirq(self, input_cirq_qubits=None): """Convert to a cirq gate. Args: input_cirq_qubits: list[cirq.LineQubit] (optional) a list of cirq Qubits that the gate can act on. If not provided the function will generate new cirq.LineQubit objects. Returns: A cirq Circuit object that corresponds to the specification of the quantum gate. In the special case the gate itself was natively generated from cirq, the function will faithfully reproduce the original GateOperation object, taking into account whether the gate acts on GridQubit objects or LineQubit objects. In the other cases the resulting cirq gate simply assumes that the qubits are LineQubit objects. """ if self.name not in ALL_GATES: sys.exit('Gate {} currently not supported.'.format(self.name)) q_inds = [] q_inds.append(self.qubits[0].index) if len(self.qubits) >= 2: q_inds.append(self.qubits[1].index) if len(self.qubits) >= 3: q_inds.append(self.qubits[2].index) cirq_qubits = [] if input_cirq_qubits == None: for q in self.qubits: if q.info['label'] == 'cirq': qkey = q.info['QubitKey'] if q.info['QubitType'] == 'GridQubit': cirq_qubits.append(cirq.GridQubit(qkey[0], qkey[1])) if q.info['QubitType'] == 'LineQubit': cirq_qubits.append(cirq.LineQubit(qkey)) else: cirq_qubits.append(cirq.LineQubit(q.index)) else: cirq_qubits = [ input_cirq_qubits[x] for x in [q.index for q in self.qubits] ] if len(self.params) > 0: params = self.params # single-qubit gates if self.name == 'X': # Pauli X return cirq.X(cirq_qubits[0]) if self.name == 'Y': # Pauli Y return cirq.Y(cirq_qubits[0]) if self.name == 'Z': # Pauli Z return cirq.Z(cirq_qubits[0]) if self.name == 'H': # Hadamard return cirq.H(cirq_qubits[0]) if self.name == 'S': # S gate return cirq.S(cirq_qubits[0]) if self.name == 'T': # T gate return cirq.T(cirq_qubits[0]) if self.name == 'Rx': # Single-qubit X rotation return cirq.Rx(params[0])(cirq_qubits[0]) if self.name == 'Ry': # Single-qubit Y rotation return cirq.Ry(params[0])(cirq_qubits[0]) if self.name == 'Rz': # Single-qubit Z rotation return cirq.Rz(params[0])(cirq_qubits[0]) if self.name == 'PHASE': # Phase gate return cirq.Z(cirq_qubits[0])**(params[0] / pi) if self.name == 'ZXZ': # PhasedXPowGate gate g = cirq.PhasedXPowGate(phase_exponent=params[0] / pi, exponent=params[1] / pi) return g(cirq_qubits[0]) if self.name == 'RH': # HPowGate g = cirq.H**(params[0] / pi) return g(cirq_qubits[0]) if self.name == 'Da': # Damping alpha gate g = DampingAlpha(params[0]) return g(cirq_qubits[0]) if self.name == 'Db': # Damping beta gate g = DampingBeta(params[0]) return g(cirq_qubits[0]) # two-qubit gates if self.name == 'CNOT': return cirq.CNOT(cirq_qubits[0], cirq_qubits[1]) if self.name == 'CZ': return cirq.CZ(cirq_qubits[0], cirq_qubits[1]) if self.name == 'CPHASE': return cirq.CZPowGate(exponent=params[0] / pi)(cirq_qubits[0], cirq_qubits[1]) if self.name == 'SWAP': return cirq.SWAP(cirq_qubits[0], cirq_qubits[1]) if self.name == 'XX': return cirq.XX(cirq_qubits[0], cirq_qubits[1])**(params[0] * 2 / pi) if self.name == 'YY': return cirq.YY(cirq_qubits[0], cirq_qubits[1])**(params[0] * 2 / pi) if self.name == 'ZZ': return cirq.ZZ(cirq_qubits[0], cirq_qubits[1])**(params[0] * 2 / pi)