def check_out_symplectic(c, pspec, s, p, n): s0, p0 = symplectic.prep_stabilizer_state(n) sc, pc = symplectic.symplectic_rep_of_clifford_circuit(c,pspec=pspec) scout, pcout = symplectic.apply_clifford_to_stabilizer_state(sc,pc,s0,p0) stargetout, ptargetout = symplectic.apply_clifford_to_stabilizer_state(s,p,s0,p0) for i in range(n): mtout = symplectic.pauli_z_measurement(stargetout,ptargetout,i) mcout = symplectic.pauli_z_measurement(scout,pcout,i) self.assertArraysAlmostEqual(mtout[0],mcout[0])
def test_compile_stabilizer_state(self): compiled = compilers.compile_stabilizer_state( self.fixture.clifford_sym, self.fixture.clifford_phase, **self.options) sym_0, phase_0 = symplectic.prep_stabilizer_state(self.fixture.n) sym_compiled, phase_compiled = symplectic.symplectic_rep_of_clifford_circuit( compiled, pspec=self.options.get('pspec', None)) sym_out, phase_out = symplectic.apply_clifford_to_stabilizer_state( sym_compiled, phase_compiled, sym_0, phase_0) sym_target, phase_target = symplectic.apply_clifford_to_stabilizer_state( self.fixture.clifford_sym, self.fixture.clifford_phase, sym_0, phase_0) for i in range(self.fixture.n): self.assertArraysAlmostEqual( symplectic.pauli_z_measurement(sym_target, phase_target, i)[0], symplectic.pauli_z_measurement(sym_out, phase_out, i)[0])
def test_compile_stabilizer_measurement(self): compiled = compilers.compile_stabilizer_measurement( self.fixture.clifford_sym, self.fixture.clifford_phase, **self.options) sym_compiled, phase_compiled = symplectic.symplectic_rep_of_clifford_circuit( compiled, pspec=self.options.get('pspec', None)) sym_state, phase_state = symplectic.prep_stabilizer_state( self.fixture.n) sym_state, phase_state = symplectic.apply_clifford_to_stabilizer_state( self.fixture.clifford_sym, self.fixture.clifford_phase, sym_state, phase_state) sym_out, phase_out = symplectic.apply_clifford_to_stabilizer_state( sym_compiled, phase_compiled, sym_state, phase_state) # This asserts that a particular stabilizer propagation yields the expected result - # the all-0 state. This test preparation, acting-on, and measurment of stabilizer states. for i in range(self.fixture.n): self.assertAlmostEqual( symplectic.pauli_z_measurement(sym_out, phase_out, i)[1], 0.)
def test_compilers(self): n = 10 # Pick a random Clifford to compile s, p = symplectic.random_clifford(n) # Directly test the core algorithm c = compilers.compile_symplectic_using_GGE_core(s) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c) self.assertArraysEqual(s, sout) # Test accessing all the allowed algorithms, without a pspec or a subsetQs c = compilers.compile_symplectic(s, iterations=3, algorithms=['BGGE', 'ROGGE']) # Tests init a pspec with limited availability, and user-specified labels. n = 5 qubit_labels = ['Q' + str(i) for i in range(n)] availability = { 'Gcnot': [('Q' + str(i), 'Q' + str(i + 1)) for i in range(0, n - 1)] } gate_names = ['Gh', 'Gp', 'Gxpi', 'Gpdag', 'Gcnot'] # 'Gi', pspec = ProcessorSpec(n, gate_names=gate_names, availability=availability, qubit_labels=qubit_labels) s, p = symplectic.random_clifford(n) # Test accessing all the allowed algorithms, with a pspec but no subsetQs c = compilers.compile_symplectic(s, pspec=pspec, iterations=3, algorithms=['BGGE', 'ROGGE']) # Test accessing all the allowed algorithms, with a pspec and a subsetQs n = 2 s, p = symplectic.random_clifford(n) c = compilers.compile_symplectic( s, pspec=pspec, subsetQs=['Q2', 'Q3'], iterations=2, algorithms=['BGGE', 'ROGGE', 'iAGvGE']) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) self.assertArraysEqual(s, sout) # Test the main function that we'll access -- compile_clifford n = 5 s, p = symplectic.random_clifford(n) c = compilers.compile_clifford(s, p, pspec=pspec, subsetQs=None, iterations=2, algorithm='ROGGE', prefixpaulis=True, paulirandomize=True) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) self.assertArraysEqual(s, sout) c = compilers.compile_clifford(s, p, pspec=None, subsetQs=None, iterations=2, algorithm='ROGGE') sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) self.assertArraysEqual(s, sout) n = 2 s, p = symplectic.random_clifford(n) c = compilers.compile_clifford(s, p, pspec=pspec, subsetQs=['Q2', 'Q3'], iterations=2, algorithm='ROGGE', prefixpaulis=True, paulirandomize=True) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) self.assertArraysEqual(s, sout) c = compilers.compile_clifford(s, p, pspec=pspec, subsetQs=['Q2', 'Q3'], iterations=2, algorithm='BGGE', prefixpaulis=True, paulirandomize=True) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) self.assertArraysEqual(s, sout) c = compilers.compile_clifford(s, p, pspec=pspec, subsetQs=['Q2', 'Q3'], iterations=2, algorithm='iAGvGE', prefixpaulis=True, paulirandomize=False) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) self.assertArraysEqual(s, sout) # Check it works for the 1-qubit case. n = 1 # Pick a random Clifford to compile s, p = symplectic.random_clifford(1) c = compilers.compile_clifford(s, p) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c) c = compilers.compile_clifford(s, p, pspec=pspec, subsetQs=['Q3'], iterations=2, algorithm='ROGGE', prefixpaulis=False, paulirandomize=True) sout, pout = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) self.assertArraysEqual(s, sout) # Tests all CNOT compiler algorithms n = 8 qubit_labels = ['Q' + str(i) for i in range(n)] availability = { 'Gcnot': [('Q' + str(i), 'Q' + str(i + 1)) for i in range(0, n - 1)] + [ ('Q0', 'Q2'), ] } gate_names = ['Gh', 'Gp', 'Gxpi', 'Gpdag', 'Gcnot'] # 'Gi', pspec8 = ProcessorSpec(n, gate_names=gate_names, availability=availability, qubit_labels=qubit_labels) n = 6 qubit_labels = ['Q' + str(i) for i in range(n)] availability = { 'Gcphase': [('Q' + str(i), 'Q' + str(i + 1)) for i in range(0, n - 1)] + [('Q' + str(n - 1), 'Q' + str(0))] } gate_names = ['Gh', 'Gxpi2', 'Gp', 'Gcphase'] # 'Gi', pspec6 = ProcessorSpec(n, gate_names=gate_names, availability=availability, qubit_labels=qubit_labels) nsubset = 6 circuit = [] for i in range(100): a = np.random.randint(nsubset) b = np.random.randint(nsubset) if a != b: circuit.append(Label('CNOT', ('Q' + str(a), 'Q' + str(b)))) subsetQs = ['Q' + str(i) for i in range(nsubset)] circuit = Circuit(layer_labels=circuit, line_labels=subsetQs) s, p = pygsti.tools.symplectic.symplectic_rep_of_clifford_circuit( circuit) aargs = {} aargs['COCAGE'] = [] aargs['COiCAGE'] = [] aargs['OCAGE'] = [ ['Q1', 'Q0', 'Q2', 'Q5', 'Q3', 'Q4'], ] # This ordering must be a 'contraction' of the graph, with the remaining graph always connected. aargs['OiCAGE'] = [ ['Q0', 'Q1', 'Q2', 'Q5', 'Q3', 'Q4'], ] aargs['ROCAGE'] = [] for algorithm in ['COiCAGE', 'OiCAGE', 'COCAGE', 'ROCAGE']: c = compilers.compile_cnot_circuit(s, pspec6, algorithm=algorithm, subsetQs=None, aargs=aargs[algorithm]) c = compilers.compile_cnot_circuit(s, pspec8, algorithm=algorithm, subsetQs=subsetQs, aargs=aargs[algorithm]) # Tests stabilizer state and measurement functions. # Tests the stabilizer compilers for n = 1 n = 1 pspec1 = ProcessorSpec( nQubits=n, gate_names=['Gcnot', 'Gh', 'Gp', 'Gxpi', 'Gypi', 'Gzpi']) # 'Gi', s, p = symplectic.random_clifford(n) c = compilers.compile_stabilizer_state(s, p, pspec1, algorithm='COCAGE', paulirandomize=False) c = compilers.compile_stabilizer_measurement(s, p, pspec1, algorithm='ROCAGE', paulirandomize=True) c = compilers.compile_stabilizer_measurement(s, p, pspec6, subsetQs=[ 'Q3', ], algorithm='COiCAGE', paulirandomize=False) def check_out_symplectic(c, pspec, s, p, n): s0, p0 = symplectic.prep_stabilizer_state(n) sc, pc = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec) scout, pcout = symplectic.apply_clifford_to_stabilizer_state( sc, pc, s0, p0) stargetout, ptargetout = symplectic.apply_clifford_to_stabilizer_state( s, p, s0, p0) for i in range(n): mtout = symplectic.pauli_z_measurement(stargetout, ptargetout, i) mcout = symplectic.pauli_z_measurement(scout, pcout, i) self.assertArraysAlmostEqual(mtout[0], mcout[0]) n = 6 s, p = symplectic.random_clifford(n) c = compilers.compile_stabilizer_state(s, p, pspec6, algorithm='ROCAGE', paulirandomize=False) check_out_symplectic(c, pspec6, s, p, n) s, p = symplectic.random_clifford(n) c = compilers.compile_stabilizer_state(s, p, pspec6, algorithm='COiCAGE', paulirandomize=True) check_out_symplectic(c, pspec6, s, p, n) s, p = symplectic.random_clifford(3) c = compilers.compile_stabilizer_measurement( s, p, pspec6, subsetQs=['Q3', 'Q4', 'Q5'], algorithm='COiCAGE', paulirandomize=False) sc, pc = symplectic.symplectic_rep_of_clifford_circuit(c, pspec=pspec6) # The state the c should map to |0,0,0,....>. sstate, pstate = symplectic.prep_stabilizer_state(3) sstate, pstate = symplectic.apply_clifford_to_stabilizer_state( s, p, sstate, pstate) sout, pout = symplectic.apply_clifford_to_stabilizer_state( sc, pc, sstate, pstate) for i in range(3): mtout = symplectic.pauli_z_measurement(sout, pout, i) self.assertArraysAlmostEqual(mtout[1], 0.) s, p = symplectic.random_clifford(n) c1 = compilers.compile_stabilizer_state(s, p, pspec6, algorithm='COiCAGE', paulirandomize=False) c2 = compilers.compile_stabilizer_measurement(s, p, pspec6, algorithm='COiCAGE', paulirandomize=True) c2 = c2.copy(editable=True) c2.prefix_circuit(c1) zerosstate_s, zerosstate_p = symplectic.prep_stabilizer_state(n) sc, pc = symplectic.symplectic_rep_of_clifford_circuit(c2, pspec=pspec6) scout, pcout = symplectic.apply_clifford_to_stabilizer_state( sc, pc, zerosstate_s, zerosstate_p) for i in range(n): mtout = symplectic.pauli_z_measurement(scout, pcout, i) self.assertArraysAlmostEqual(mtout[1], 0.)
def oneshot_circuit_simulator_for_tensored_independent_pauli_errors(circuit, pspec, errormodel, idle1q_placeholder='I'): """ Generates a single measurement result for the `circuit_simulator_for_tensored_independent_pauli_errors()` simulator Parameters ---------- circuit : Circuit The circuit to simulate. It should only contain gates that are also contained within the provided QubitProcessorSpec `pspec` and are Clifford gates. pspec : QubitProcessorSpec The QubitProcessorSpec that defines the device. The Clifford model in QubitProcessorSpec should contain all of the gates that are in the circuit. errormodel : dict A dictionary defining the error model. This errormodel should have keys that are Label objects (the elements of the circuit). The values for a particular Label is an (n,4) numpy array of floats, that encodes the errors caused by the gate specified by that Label. The (i,j) value in the array is the probability that this gate is followed by Pauli i where Pauli 0 = identity, Pauli 1 = X, Pauli 2 = Y and Pauli 3 = Z. So, if the arrray is [1.,0.,0.,0.] in every row then there is no errors, if it is [1-p,p/3,p/3,p/3] in row j then there is equal probability of each Pauli error on qubit j with an error probability of p. TODO: docstring: idle1q_placeholder Returns ------- tuple A tuple of values that are 0 or 1, corresponding to the results of a z-measurement on all the qubits. The ordering of this tuple corresponds to the ordering of the wires in the circuit. """ n = circuit.number_of_lines depth = circuit.depth sout, pout = _symp.prep_stabilizer_state(n, zvals=None) srep = pspec.models['clifford'].compute_clifford_symplectic_reps() I = _np.identity(2 * n, int) for l in range(depth): layer = circuit.layer_with_idles(l, idle_gate_name=idle1q_placeholder) s, p = _symp.symplectic_rep_of_clifford_layer(layer, n, q_labels=circuit.line_labels, srep_dict=srep) # Apply the perfect layer to the current state. sout, pout = _symp.apply_clifford_to_stabilizer_state(s, p, sout, pout) # Consider each gate in the layer, and apply Pauli errors with the relevant probs. for gate in layer: # Sample a pauli vector for the gate gerror_p = _np.zeros(2 * n, int) sampledvec = _np.array([list(_np.random.multinomial(1, pp)) for pp in errormodel[gate]]) # Z and Y both map X - > -X under conjugation, which is encoded with the upper half of # the p vector being set to 2. gerror_p[:n] = 2 * (sampledvec[:, 3] ^ sampledvec[:, 2]) # X and Y both map Z - > -Z under conjugation, which is encoded with the lower half of # the p vector being set to 2. gerror_p[n:] = 2 * (sampledvec[:, 1] ^ sampledvec[:, 2]) sout, pout = _symp.apply_clifford_to_stabilizer_state(I, gerror_p, sout, pout) output = [] for q in range(n): measurement_out = _symp.pauli_z_measurement(sout, pout, q) # The probability of the '1' outcome oneprob = measurement_out[1] # Sample a bit with that probability to be 1. bit = _np.random.binomial(1, oneprob) output.append(bit) # Add measurement errors, by bit-flipping with some probability try: measurement_errors = errormodel['measure'] except: measurement_errors = [0 for i in range(n)] add_to_outcome = _np.array([_np.random.binomial(1, p) for p in measurement_errors]) output = tuple(_np.array(output) ^ add_to_outcome) outputasstring = '' for s in output: outputasstring += str(s) return outputasstring