def test_dont_allow_partial_czs(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.CZ(q0, q1), cirq.CZPowGate(exponent=1, global_shift=-0.5).on(q0, q1), ) c_orig = cirq.Circuit(circuit) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit) assert circuit == c_orig circuit = cirq.Circuit(cirq.CZ(q0, q1)**0.5, ) c_orig = cirq.Circuit(circuit) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cirq.ConvertToCzAndSingleGates( ignore_failures=True).optimize_circuit(circuit) assert sum(1 for op in circuit.all_operations() if len(op.qubits) > 1) == 2 assert sum(1 for op in circuit.all_operations() if isinstance(op.gate, cirq.CZPowGate)) == 2 assert all(op.gate.exponent % 2 == 1 for op in circuit.all_operations() if isinstance(op.gate, cirq.CZPowGate)) cirq.testing.assert_allclose_up_to_global_phase(circuit.unitary(), c_orig.unitary(), atol=1e-7)
def test_allow_partial_czs(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.CZ(q0, q1)**0.5, cirq.CZPowGate(exponent=0.5, global_shift=-0.5).on(q0, q1), ) c_orig = cirq.Circuit(circuit) cirq.ConvertToCzAndSingleGates( allow_partial_czs=True).optimize_circuit(circuit) assert circuit == c_orig # yapf: disable circuit2 = cirq.Circuit( cirq.MatrixGate((np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1j]]))).on(q0, q1)) # yapf: enable cirq.ConvertToCzAndSingleGates( allow_partial_czs=True).optimize_circuit(circuit2) two_qubit_ops = list( circuit2.findall_operations(lambda e: len(e.qubits) == 2)) assert len(two_qubit_ops) == 1 gate = two_qubit_ops[0][1].gate assert isinstance(gate, cirq.ops.CZPowGate) and gate.exponent == 0.5
def test_avoids_decompose_when_matrix_available(): class OtherXX(cirq.testing.TwoQubitGate): # coverage: ignore def _unitary_(self) -> np.ndarray: m = np.array([[0, 1], [1, 0]]) return np.kron(m, m) def _decompose_(self, qubits): assert False class OtherOtherXX(cirq.testing.TwoQubitGate): # coverage: ignore def _unitary_(self) -> np.ndarray: m = np.array([[0, 1], [1, 0]]) return np.kron(m, m) def _decompose_(self, qubits): assert False a, b = cirq.LineQubit.range(2) c = cirq.Circuit(OtherXX()(a, b), OtherOtherXX()(a, b)) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cirq.ConvertToCzAndSingleGates().optimize_circuit(c) assert len(c) == 2
def main(): """Demonstrates Quantum Fourier transform. """ # Create circuit qft_circuit = generate_2x2_grid_qft_circuit() cirq.ConvertToCzAndSingleGates().optimize_circuit( qft_circuit) # cannot work with params cirq.ExpandComposite().optimize_circuit(qft_circuit) print('Circuit:') print(qft_circuit) qsim_circuit = qsimcirq.QSimCircuit(cirq_circuit=qft_circuit, allow_decomposition=True) # Simulate and collect final_state sv_simulator = cirq.Simulator() qs_simulator = qsimcirq.QSimSimulator(qsim_options={'t': 16, 'v': 2}) sv_result = sv_simulator.simulate(qft_circuit) qs_result = qs_simulator.simulate(qsim_circuit) assert sv_result.state_vector().shape == (16, ) assert qs_result.state_vector().shape == (16, ) assert cirq.linalg.allclose_up_to_global_phase(sv_result.state_vector(), qs_result.state_vector()) kc_simulator = cirq.KnowledgeCompilationSimulator(qft_circuit, intermediate=False) kc_result = kc_simulator.simulate(qft_circuit) print() print('FinalState') assert cirq.linalg.allclose_up_to_global_phase(sv_result.state_vector(), kc_result.state_vector()) print(kc_result.state_vector()) print(np.around(kc_result.final_state_vector, 3))
def test_composite_gates_without_matrix(): class CompositeDummy(cirq.SingleQubitGate): def _decompose_(self, qubits): yield cirq.X(qubits[0]) yield cirq.Y(qubits[0])**0.5 class CompositeDummy2(cirq.TwoQubitGate): def _decompose_(self, qubits): yield cirq.CZ(qubits[0], qubits[1]) yield CompositeDummy()(qubits[1]) q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( CompositeDummy()(q0), CompositeDummy2()(q0, q1), ) expected = cirq.Circuit( cirq.X(q0), cirq.Y(q0)**0.5, cirq.CZ(q0, q1), cirq.X(q1), cirq.Y(q1)**0.5, ) c_orig = cirq.Circuit(circuit) cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit) cirq.testing.assert_allclose_up_to_global_phase(circuit.unitary(), expected.unitary(), atol=1e-7) cirq.testing.assert_allclose_up_to_global_phase(circuit.unitary(), c_orig.unitary(), atol=1e-7)
def test_cirq_qsim_simulate_random_unitary(mode: str): q0, q1 = cirq.LineQubit.range(2) qsimSim = qsimcirq.QSimSimulator(qsim_options={"t": 16, "v": 0}) for iter in range(10): random_circuit = cirq.testing.random_circuit( 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) if mode == "noisy": random_circuit.append(NoiseTrigger().on(q0)) result = qsimSim.simulate(random_circuit, qubit_order=[q0, q1]) assert result.state_vector().shape == (4,) cirqSim = cirq.Simulator() cirq_result = cirqSim.simulate(random_circuit, qubit_order=[q0, q1]) # When using rotation gates such as S, qsim may add a global phase relative # to other simulators. This is fine, as the result is equivalent. assert cirq.linalg.allclose_up_to_global_phase( result.state_vector(), cirq_result.state_vector(), atol=1.0e-6 )
def test_allow_partial_czs(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit.from_ops(cirq.CZ(q0, q1)**0.5, ) c_orig = cirq.Circuit(circuit) cirq.ConvertToCzAndSingleGates( allow_partial_czs=True).optimize_circuit(circuit) assert circuit == c_orig
def test_fail_unsupported_gate(): class UnsupportedDummy(cirq.TwoQubitGate): pass q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(UnsupportedDummy()(q0, q1), ) with pytest.raises(TypeError): cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit)
def test_passes_through_measurements(): q0, q1, q2 = cirq.LineQubit.range(3) circuit = cirq.Circuit( cirq.measure(q0, key='m0'), cirq.measure(q1, q2, key='m1', invert_mask=(True, False)), ) c_orig = cirq.Circuit(circuit) cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit) assert circuit == c_orig
def test_fail_unsupported_gate(): class UnsupportedDummy(cirq.testing.TwoQubitGate): pass q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(UnsupportedDummy()(q0, q1), ) with pytest.raises(TypeError): with cirq.testing.assert_deprecated( "Use cirq.optimize_for_target_gateset", deadline='v1.0'): cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit)
def test_passes_through_measurements(): q0, q1, q2 = cirq.LineQubit.range(3) circuit = cirq.Circuit( cirq.measure(q0, key='m0'), cirq.measure(q1, q2, key='m1', invert_mask=(True, False))) c_orig = cirq.Circuit(circuit) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit) assert circuit == c_orig
def test_ignore_unsupported_gate(): class UnsupportedDummy(cirq.TwoQubitGate): pass q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(UnsupportedDummy()(q0, q1), ) c_orig = cirq.Circuit(circuit) cirq.ConvertToCzAndSingleGates( ignore_failures=True).optimize_circuit(circuit) assert circuit == c_orig
def test_kak_decomposes_unknown_two_qubit_gate(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit.from_ops(cirq.ISWAP(q0, q1)) c_orig = cirq.Circuit(circuit) cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit) assert sum(1 for op in circuit.all_operations() if len(op.qubits) > 1) == 2 assert sum(1 for op in circuit.all_operations() if cirq.op_gate_of_type(op, cirq.CZPowGate)) == 2 assert all(op.gate.exponent == 1 for op in circuit.all_operations() if cirq.op_gate_of_type(op, cirq.CZPowGate)) cirq.testing.assert_allclose_up_to_global_phase( circuit.to_unitary_matrix(), c_orig.to_unitary_matrix(), atol=1e-7)
def test_ignore_unsupported_gate(): class UnsupportedDummy(cirq.testing.TwoQubitGate): pass q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(UnsupportedDummy()(q0, q1), ) c_orig = cirq.Circuit(circuit) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cirq.ConvertToCzAndSingleGates( ignore_failures=True).optimize_circuit(circuit) assert circuit == c_orig
def optimize(c): cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit=c) cirq.MergeSingleQubitGates().optimize_circuit(circuit=c) cirq.EjectZ().optimize_circuit(circuit=c) cirq.EjectPhasedPaulis().optimize_circuit(circuit=c) cirq.MergeSingleQubitGates().optimize_circuit(circuit=c) cirq.DropNegligible().optimize_circuit(circuit=c) cirq.DropEmptyMoments().optimize_circuit(circuit=c) c2=cirq.Circuit() for g in c: for g2 in g: # print(g2) c2.append(g2,strategy=cirq.InsertStrategy.EARLIEST) return c2
def test_dont_allow_partial_czs(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit.from_ops(cirq.CZ(q0, q1)**0.5, ) c_orig = cirq.Circuit(circuit) cirq.ConvertToCzAndSingleGates( ignore_failures=True).optimize_circuit(circuit) assert sum(1 for op in circuit.all_operations() if len(op.qubits) > 1) == 2 assert sum(1 for op in circuit.all_operations() if cirq.op_gate_of_type(op, cirq.CZPowGate)) == 2 assert all(op.gate.exponent % 2 == 1 for op in circuit.all_operations() if cirq.op_gate_of_type(op, cirq.CZPowGate)) cirq.testing.assert_allclose_up_to_global_phase( circuit.to_unitary_matrix(), c_orig.to_unitary_matrix(), atol=1e-7)
def test_kak_decomposes_unknown_two_qubit_gate(): q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(cirq.ISWAP(q0, q1)) c_orig = cirq.Circuit(circuit) with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'): cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit) assert sum(1 for op in circuit.all_operations() if len(op.qubits) > 1) == 2 assert sum(1 for op in circuit.all_operations() if isinstance(op.gate, cirq.CZPowGate)) == 2 assert all(op.gate.exponent == 1 for op in circuit.all_operations() if isinstance(op.gate, cirq.CZPowGate)) cirq.testing.assert_allclose_up_to_global_phase(circuit.unitary(), c_orig.unitary(), atol=1e-7)
def test_avoids_infinite_cycle_when_matrix_available(): class OtherX(cirq.Gate, cirq.CompositeGate): def _unitary_(self) -> np.ndarray: return np.array([[0, 1], [1, 0]]) # coverage: ignore def default_decompose(self, qubits): raise NotImplementedError() class OtherOtherX(cirq.Gate, cirq.CompositeGate): def _unitary_(self) -> np.ndarray: return np.array([[0, 1], [1, 0]]) # coverage: ignore def default_decompose(self, qubits): raise NotImplementedError() q0 = cirq.LineQubit(0) c = cirq.Circuit.from_ops(OtherX()(q0), OtherOtherX()(q0)) c_orig = cirq.Circuit(c) cirq.ConvertToCzAndSingleGates().optimize_circuit(c) assert c == c_orig
def test_avoids_infinite_cycle_when_matrix_available(): class OtherX(cirq.SingleQubitGate): # coverage: ignore def _unitary_(self) -> np.ndarray: return np.array([[0, 1], [1, 0]]) def _decompose_(self, qubits): return OtherOtherX(*qubits) class OtherOtherX(cirq.SingleQubitGate): # coverage: ignore def _unitary_(self) -> np.ndarray: return np.array([[0, 1], [1, 0]]) def _decompose_(self, qubits): return OtherX(*qubits) q0 = cirq.LineQubit(0) c = cirq.Circuit.from_ops(OtherX()(q0), OtherOtherX()(q0)) c_orig = cirq.Circuit(c) cirq.ConvertToCzAndSingleGates().optimize_circuit(c) assert c == c_orig
def test_avoids_decompose_when_matrix_available(): class OtherXX(cirq.TwoQubitGate): # coverage: ignore def _unitary_(self) -> np.ndarray: m = np.array([[0, 1], [1, 0]]) return np.kron(m, m) def _decompose_(self, qubits): assert False class OtherOtherXX(cirq.TwoQubitGate): # coverage: ignore def _unitary_(self) -> np.ndarray: m = np.array([[0, 1], [1, 0]]) return np.kron(m, m) def _decompose_(self, qubits): assert False a, b = cirq.LineQubit.range(2) c = cirq.Circuit.from_ops(OtherXX()(a, b), OtherOtherXX()(a, b)) cirq.ConvertToCzAndSingleGates().optimize_circuit(c) assert len(c) == 2
def f(x): param_resolver = cirq.ParamResolver({ 'alpha':x[0], 'beta':x[1], 'gamma':x[2] }) # VALIDATE STATE VECTOR SIMULATION solved_circuit = cirq.resolve_parameters(meas_circuit, param_resolver) cirq.ConvertToCzAndSingleGates().optimize_circuit(solved_circuit) # cannot work with params cirq.ExpandComposite().optimize_circuit(solved_circuit) qsim_circuit = qsimcirq.QSimCircuit(solved_circuit) qs_sim_start = time.time() qs_sim_result = qs_sim_16.simulate(qsim_circuit) qs_sim_time = time.time() - qs_sim_start # kc_sim_start = time.time() # kc_sim_result = kc_sim.simulate(cirq_circuit, param_resolver=param_resolver) # kc_sim_time = time.time() - kc_sim_start # print("kc_sim_result.state_vector()=") # print(kc_sim_result.state_vector()) # print("qs_sim_result.state_vector()=") # print(qs_sim_result.state_vector()) # assert qs_sim_result.state_vector().shape == (1<<(length*length),) # assert cirq.linalg.allclose_up_to_global_phase( # qs_sim_result.state_vector(), # kc_sim_result.state_vector(), # rtol = 1.e-4, # atol = 1.e-6, # ) # VALIDATE SAMPLING HISTOGRAMS # Sample bitstrings from circuit qs_smp_16_start = time.time() qs_smp_16_result = qs_sim_16.run(qsim_circuit, repetitions=repetitions) qs_smp_16_time = time.time() - qs_smp_16_start qs_bitstrings = qs_smp_16_result.measurements['x'] # Process histogram qs_histogram = defaultdict(int) for bitstring in qs_bitstrings: integer = 0 for pos, bit in enumerate(bitstring): integer += bit<<pos qs_histogram[integer] += 1 # Process bitstrings qs_value = obj_func(qs_smp_16_result, h, jr, jc) print('Objective value is {}.'.format(qs_value)) # Sample bitstrings from circuit kc_smp_start = time.time() kc_smp_result = kc_smp.run(meas_circuit, param_resolver=param_resolver, repetitions=repetitions) kc_smp_time = time.time() - kc_smp_start # Process histogram kc_bitstrings = kc_smp_result.measurements['x'] kc_histogram = defaultdict(int) for bitstring in kc_bitstrings: integer = 0 for pos, bit in enumerate(reversed(bitstring)): integer += bit<<pos kc_histogram[integer] += 1 # Process bitstrings kc_value = obj_func(kc_smp_result, h, jr, jc) print('Objective value is {}.'.format(kc_value)) nonlocal iter # PRINT HISTOGRAMS kc_kl_div = 0 qs_kl_div = 0 print ('iter,index,bitstring,bitstring_bin,qs_probability,qs_samples,kc_samples') probabilities = np.zeros(1<<(length*length)) for bitstring, amplitude in enumerate(qs_sim_result.state_vector()): probability = abs(amplitude) * abs(amplitude) kc_samples = kc_histogram[bitstring]/repetitions qs_samples = qs_histogram[bitstring]/repetitions kc_kl_div += 0 if kc_samples==0 else kc_samples*math.log(kc_samples/probability) qs_kl_div += 0 if qs_samples==0 else qs_samples*math.log(qs_samples/probability) probabilities[bitstring]=probability kc_kl_divs[length].append(kc_kl_div) qs_kl_divs[length].append(qs_kl_div) sorted_bitstrings = np.argsort(probabilities) # for index, bitstring in enumerate(sorted_bitstrings): # print (str(iter)+','+str(index)+','+str(bitstring)+','+format(bitstring,'b').zfill(length*length)+','+str(probabilities[bitstring])+','+"{:.6e}".format(qs_histogram[bitstring]/repetitions)+','+"{:.6e}".format(kc_histogram[bitstring]/repetitions)) print ('qs_value='+str(qs_value)+' kc_value='+str(kc_value)) # print ( 'qs_sim_time='+str(qs_sim_time)+' kc_sim_time='+str(kc_sim_time) ) print ( 'qs_smp_16_time='+str(qs_smp_16_time)+' kc_smp_time='+str(kc_smp_time) ) print ('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') iter += 1 return qs_value
def main(): q0, q1, q2 = cirq.LineQubit.range(3) for iteration in range(1): random_circuit = cirq.testing.random_circuit(qubits=[q0, q1, q2], n_moments=32, op_density=0.99) cirq.ConvertToCzAndSingleGates().optimize_circuit( random_circuit) # cannot work with params cirq.ExpandComposite().optimize_circuit(random_circuit) qs_circuit = qsimcirq.QSimCircuit(random_circuit) random_circuit._to_quil_output().save_to_file('kc_qtorch.quil') qs_simulator = qsimcirq.QSimSimulator(qsim_options={'t': 16, 'v': 2}) qs_result = qs_simulator.simulate(qs_circuit) assert qs_result.state_vector().shape == (8, ) kc_simulator = cirq.KnowledgeCompilationSimulator(random_circuit) kc_result = kc_simulator.simulate(random_circuit) print("qs_result.state_vector()") print(qs_result.state_vector()) print("kc_result.state_vector()") print(kc_result.state_vector()) assert cirq.linalg.allclose_up_to_global_phase( qs_result.state_vector(), kc_result.state_vector(), rtol=1.e-4, atol=1.e-6, ) path_to_qtorch = '/common/home/yh804/research/qtorch/bin/qtorch' with open('kc_qtorch.inp', 'w') as inp_file: inp_file.write('''# Line graph decomposition method for contraction >string qasm kc_qtorch.quil # >string contractmethod simple-stoch >string contractmethod linegraph-qbb >int quickbbseconds 65536 # >string measurement kc_qtorch.meas # >string outputpath kc_qtorch.out >bool qbbonly true # >bool readqbbresonly true # >int threads 8 ''') stdout = os.system(path_to_qtorch + ' kc_qtorch.inp') probs = np.zeros(1 << 3) for bitstring in range(1 << 3): with open('kc_qtorch.inp', 'w') as inp_file: inp_file.write( '''# Line graph decomposition method for contraction >string qasm kc_qtorch.quil # >string contractmethod simple-stoch >string contractmethod linegraph-qbb # >int quickbbseconds 65536 >string measurement kc_qtorch.meas >string outputpath kc_qtorch.out # >bool qbbonly true >bool readqbbresonly true >int threads 8 ''') with open('kc_qtorch.meas', 'w') as meas_file: meas_file.write("{:03b}".format(bitstring)) stdout = os.system(path_to_qtorch + ' kc_qtorch.inp') with open('kc_qtorch.out', 'r') as out_file: for line in out_file.readlines(): words = re.split(r'\(|,', line) if words[0] == 'Result of Contraction: ': probs[bitstring] = float(words[1]) print( "np.diag(np.outer(qs_result.state_vector(),np.conj(qs_result.state_vector())))" ) print( np.diag( np.outer(qs_result.state_vector(), np.conj(qs_result.state_vector())))) print("probs") print(probs) assert cirq.linalg.allclose_up_to_global_phase( np.diag( np.outer(qs_result.state_vector(), np.conj(qs_result.state_vector()))), probs, rtol=1.e-4, atol=1.e-6, ) circuit_unitary = [] for x in range(8): result = kc_simulator.simulate(random_circuit, initial_state=x) circuit_unitary.append(result.final_state_vector) print("np.transpose(circuit_unitary) = ") print(np.transpose(circuit_unitary)) print("random_circuit.unitary() = ") print(random_circuit.unitary()) np.testing.assert_almost_equal(np.transpose(circuit_unitary), random_circuit.unitary(), decimal=4)
def kevin_optimize_circuit(self, circuit): cirq.DropNegligible().optimize_circuit(circuit) cirq.ConvertToCzAndSingleGates().optimize_circuit(circuit)