def operator_matrix(self, operator): """Converts an operator representation to Kraus matrix representation Args: operator (operator): operator representation. Can be a noise circuit or a matrix or a list of matrices. Returns: Kraus: the operator, converted to Kraus representation. """ if isinstance(operator, list) and isinstance(operator[0], dict): operator_error = QuantumError([(operator, 1)]) kraus_rep = Kraus(operator_error.to_quantumchannel()).data return kraus_rep return operator
def test_auto_method_clifford_circuits_and_reset_noise(self): """Test statevector method is used for Clifford circuit""" # Test noise model noise_circs = [[{ "name": "reset", "qubits": [0] }], [{ "name": "id", "qubits": [0] }]] noise_probs = [0.5, 0.5] error = QuantumError(zip(noise_circs, noise_probs)) noise_model = NoiseModel() noise_model.add_all_qubit_quantum_error( error, ['id', 'x', 'y', 'z', 'h', 's', 'sdg']) backend = self.backend(noise_model=noise_model) # Test circuits shots = 100 circuits = ref_2q_clifford.cz_gate_circuits_deterministic( final_measure=True) result = backend.run(circuits, shots=shots).result() success = getattr(result, 'success', False) self.assertTrue(success) self.compare_result_metadata(result, circuits, 'method', 'stabilizer')
def test_backend_method_clifford_circuits_and_reset_noise(self): """Test statevector method is used for Clifford circuit""" # Test noise model noise_circs = [[{ "name": "reset", "qubits": [0] }], [{ "name": "id", "qubits": [0] }]] noise_probs = [0.5, 0.5] error = QuantumError(zip(noise_circs, noise_probs)) noise_model = NoiseModel() noise_model.add_all_qubit_quantum_error( error, ['id', 'x', 'y', 'z', 'h', 's', 'sdg']) # Test circuits shots = 100 circuits = ref_2q_clifford.cz_gate_circuits_deterministic( final_measure=True) qobj = assemble(circuits, self.SIMULATOR, shots=shots) result = self.SIMULATOR.run(qobj, backend_options=self.BACKEND_OPTS, noise_model=noise_model).result() success = getattr(result, 'success', False) self.assertTrue(success) # Check simulation method method = self.BACKEND_OPTS.get('method', 'automatic') if method != 'automatic': self.compare_result_metadata(result, circuits, 'method', method) else: self.compare_result_metadata(result, circuits, 'method', 'stabilizer')
def test_from_dict(self): noise_ops_1q = [((IGate(), [0]), 0.9), ((XGate(), [0]), 0.1)] noise_ops_2q = [((PauliGate('II'), [0, 1]), 0.9), ((PauliGate('IX'), [0, 1]), 0.045), ((PauliGate('XI'), [0, 1]), 0.045), ((PauliGate('XX'), [0, 1]), 0.01)] noise_model = NoiseModel() with self.assertWarns(DeprecationWarning): noise_model.add_quantum_error(QuantumError(noise_ops_1q, 1), 'h', [0]) noise_model.add_quantum_error(QuantumError(noise_ops_1q, 1), 'h', [1]) noise_model.add_quantum_error(QuantumError(noise_ops_2q, 2), 'cx', [0, 1]) noise_model.add_quantum_error(QuantumError(noise_ops_2q, 2), 'cx', [1, 0]) deserialized = NoiseModel.from_dict(noise_model.to_dict()) self.assertEqual(noise_model, deserialized)
def test_auto_method_nonclifford_circuit_and_reset_noise(self): """Test statevector method is used for Clifford circuit""" # Test noise model noise_circs = [Reset(), IGate()] noise_probs = [0.5, 0.5] error = QuantumError(zip(noise_circs, noise_probs)) noise_model = NoiseModel() noise_model.add_all_qubit_quantum_error( error, ['id', 'x', 'y', 'z', 'h', 's', 'sdg']) backend = self.backend(noise_model=noise_model) # Test circuits shots = 100 circuits = ref_non_clifford.ccx_gate_circuits_deterministic( final_measure=True) result = backend.run(circuits, shots=shots).result() success = getattr(result, 'success', False) self.compare_result_metadata(result, circuits, 'method', "density_matrix")
def get_error_channel(dag_cir, noisy_position, p): """to get the error channel of the noisy circuit """ t_start = time.time() num_qubit = get_real_qubit_num(dag_cir) noise_ops = [([{ "name": 'unitary', "qubits": [num_qubit - 1], 'params': [np.eye(2)] }], 1)] error = QuantumError(noise_ops, number_of_qubits=num_qubit).to_quantumchannel() for k in dag_cir.nodes: operation = dag_cir.nodes[k]['operation'] nam = operation.name q = operation.involve_qubits_list if nam != 'CX': U = operation.u_matrix else: if q[0] < q[1]: U = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]]) else: U = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) noise_ops = [([{"name": 'unitary', "qubits": q, 'params': [U]}], 1)] temp_error = QuantumError( noise_ops, number_of_qubits=num_qubit).to_quantumchannel() error = error.compose(temp_error) if k in noisy_position: q = [q[0]] for q0 in q: noise_ops = [([{ "name": 'id', "qubits": [q0] }], 1 - p), ([{ "name": 'x', "qubits": [q0] }], p / 3), ([{ "name": 'y', "qubits": [q0] }], p / 3), ([{ "name": 'z', "qubits": [q0] }], p / 3)] temp_error = QuantumError( noise_ops, number_of_qubits=num_qubit).to_quantumchannel() error = error.compose(temp_error) return error
def test_backend_method_nonclifford_circuit_and_reset_noise(self): """Test statevector method is used for Clifford circuit""" # Test noise model noise_circs = [[{ "name": "reset", "qubits": [0] }], [{ "name": "id", "qubits": [0] }]] noise_probs = [0.5, 0.5] error = QuantumError(zip(noise_circs, noise_probs)) noise_model = NoiseModel() noise_model.add_all_qubit_quantum_error( error, ['id', 'x', 'y', 'z', 'h', 's', 'sdg']) # Test circuits shots = 100 circuits = ref_non_clifford.ccx_gate_circuits_deterministic( final_measure=True) qobj = assemble(circuits, self.SIMULATOR, shots=shots) def get_result(): return self.SIMULATOR.run(qobj, backend_options=self.BACKEND_OPTS, noise_model=noise_model).result() # Check simulation method method = self.BACKEND_OPTS.get('method', 'automatic') if method == 'stabilizer': self.assertRaises(AerError, get_result) else: result = get_result() self.is_completed(result) if method == 'automatic': target_method = 'density_matrix' else: target_method = method self.compare_result_metadata(result, circuits, 'method', target_method)
def approximate_quantum_error(error, *, operator_string=None, operator_dict=None, operator_list=None): """Return an approximate QuantumError bases on the Hilbert-Schmidt metric. Currently this is only implemented for 1-qubit QuantumErrors. Args: error (QuantumError): the error to be approximated. operator_string (string or None): a name for a premade set of building blocks for the output channel (Default: None). operator_dict (dict or None): a dictionary whose values are the building blocks for the output channel (Default: None). operator_list (dict or None): list of building blocks for the output channel (Default: None). Returns: QuantumError: the approximate quantum error. Raises: NoiseError: if number of qubits is not supported or approximation failsed. RuntimeError: If there's no information about the noise type Additional Information ---------------------- The operator input precedence is as follows: list < dict < string if a string is given, dict is overwritten; if a dict is given, list is overwritten possible values for string are 'pauli', 'reset', 'clifford' For further information see `NoiseTransformer.named_operators`. """ if not isinstance(error, QuantumError): error = QuantumError(error) if error.number_of_qubits > 1: raise NoiseError("Only 1-qubit noises can be converted, {}-qubit " "noise found in model".format(error.number_of_qubits)) error_kraus_operators = Kraus(error.to_quantumchannel()).data transformer = NoiseTransformer() if operator_string is not None: operator_string = operator_string.lower() if operator_string not in transformer.named_operators.keys(): raise RuntimeError( "No information about noise type {}".format(operator_string)) operator_dict = transformer.named_operators[operator_string] if operator_dict is not None: names, operator_list = zip(*operator_dict.items()) if operator_list is not None: op_matrix_list = [ transformer.operator_matrix(operator) for operator in operator_list ] probabilities = transformer.transform_by_operator_list( op_matrix_list, error_kraus_operators) identity_prob = 1 - sum(probabilities) if identity_prob < 0 or identity_prob > 1: raise RuntimeError( "Approximated channel operators probabilities sum to {}". format(1 - identity_prob)) quantum_error_spec = [([{'name': 'id', 'qubits': [0]}], identity_prob)] op_circuit_list = [ transformer.operator_circuit(operator) for operator in operator_list ] for (operator, probability) in zip(op_circuit_list, probabilities): quantum_error_spec.append((operator, probability)) return QuantumError(quantum_error_spec) raise NoiseError( "Quantum error approximation failed - no approximating operators detected" )
# In[5]: # Convert to Kraus operator bit_flip_kraus = Kraus(bit_flip) print(bit_flip_kraus) # In[6]: # Convert to Superoperator phase_flip_sop = SuperOp(phase_flip) print(phase_flip_sop) # In[7]: # Convert back to a quantum error print(QuantumError(bit_flip_kraus)) # Check conversion is equivalent to original error QuantumError(bit_flip_kraus) == bit_flip # ### Readout Error # # Classical readout errors are specified by a list of assignment probabilities vectors $P(A|B)$: # # * $A$ is the *recorded* classical bit value # * $B$ is the *true* bit value returned from the measurement # # E.g. for 1 qubits: $ P(A|B) = [P(A|0), P(A|1)]$. # In[8]: