def plot_bloch_multivector(rho, title='', figsize=None): """Plot the Bloch sphere. Plot a sphere, axes, the Bloch vector, and its projections onto each axis. Args: rho (ndarray): Numpy array for state vector or density matrix. title (str): a string that represents the plot title figsize (tuple): Has no effect, here for compatibility only. Returns: matplotlib.Figure: A matplotlib figure instance. Raises: ImportError: Requires matplotlib. Example: .. jupyter-execute:: from qiskit import QuantumCircuit, BasicAer, execute from qiskit.visualization import plot_bloch_multivector %matplotlib inline qc = QuantumCircuit(2, 2) qc.h(0) qc.cx(0, 1) qc.measure([0, 1], [0, 1]) backend = BasicAer.get_backend('statevector_simulator') job = execute(qc, backend).result() plot_bloch_multivector(job.get_statevector(qc), title="New Bloch Multivector") """ if not HAS_MATPLOTLIB: raise ImportError( 'Must have Matplotlib installed. To install, run "pip install ' 'matplotlib".') rho = _validate_input_state(rho) num = int(np.log2(len(rho))) width, height = plt.figaspect(1 / num) fig = plt.figure(figsize=(width, height)) for i in range(num): ax = fig.add_subplot(1, num, i + 1, projection='3d') pauli_singles = [ Pauli.pauli_single(num, i, 'X'), Pauli.pauli_single(num, i, 'Y'), Pauli.pauli_single(num, i, 'Z') ] bloch_state = list( map(lambda x: np.real(np.trace(np.dot(x.to_matrix(), rho))), pauli_singles)) plot_bloch_vector(bloch_state, "qubit " + str(i), ax=ax, figsize=figsize) fig.suptitle(title, fontsize=16) if get_backend() in ['module://ipykernel.pylab.backend_inline', 'nbAgg']: plt.close(fig) return fig
def test_pauli_error_2q_gate_from_pauli(self): """Test two-qubit pauli error as gate qobj from Pauli obj""" paulis = [Pauli.from_label(s) for s in ['XZ', 'YX', 'ZY']] probs = [0.5, 0.3, 0.2] error = pauli_error(zip(paulis, probs), standard_gates=True) target_circs = [[{ "name": "z", "qubits": [0] }, { "name": "x", "qubits": [1] }], [{ "name": "x", "qubits": [0] }, { "name": "y", "qubits": [1] }], [{ "name": "y", "qubits": [0] }, { "name": "z", "qubits": [1] }]] target_probs = probs.copy() for j in range(len(paulis)): circ, p = error.error_term(j) self.remove_if_found(p, target_probs) self.remove_if_found(circ, target_circs) self.assertEqual(target_probs, [], msg="Incorrect probabilities") self.assertEqual(target_circs, [], msg="Incorrect circuits")
def test_pauli_error_1q_unitary_from_pauli(self): """Test single-qubit pauli error as unitary qobj from Pauli obj""" paulis = [Pauli.from_label(s) for s in ['I', 'X', 'Y', 'Z']] probs = [0.4, 0.3, 0.2, 0.1] error = pauli_error(zip(paulis, probs), standard_gates=False) target_unitaries = [ standard_gate_unitary('x'), standard_gate_unitary('y'), standard_gate_unitary('z') ] target_probs = probs.copy() target_identity_count = 0 for j in range(len(paulis)): circ, p = error.error_term(j) name = circ[0]['name'] self.assertIn(name, ('unitary', 'id')) self.assertEqual(circ[0]['qubits'], [0]) self.remove_if_found(p, target_probs) if name == "unitary": self.remove_if_found(circ[0]['params'][0], target_unitaries) else: target_identity_count += 1 self.assertEqual(target_probs, [], msg="Incorrect probabilities") self.assertEqual(target_unitaries, [], msg="Incorrect unitaries") self.assertEqual(target_identity_count, 1, msg="Incorrect identities")
def heisenberg1D(num_qubits): '''construct the 1D Heisenberg model with open boundary conditions: 1/4 * \sum_i (X_i X_{i+1} + Y_i Y_{i+1} + Z_i Z_{i+1}) Inputs: num_qubits the number of qubits (spins) in the chain Returns: Operator (SummedOp of PauliOps) representing the Hamiltonian ''' ind_op = 0 coeff = 0.25 for i in range(num_qubits - 1): for pauli_label in ['X', 'Y', 'Z']: labels = ['I'] * (i) + [pauli_label, pauli_label ] + ['I'] * (num_qubits - (i + 2)) pauli = Pauli(label=labels) pauli_op = PauliOp(pauli, coeff) if ind_op == 0: hamiltonian = pauli_op else: hamiltonian += pauli_op ind_op += 1 return hamiltonian
def magnetic_fields(potentials): '''construct magnetic fields of the form 1/2 * \sum_i h_i Z_i Inputs: potentials a list or ndarray representing the potential h_i Returns: Operator (SummedOp of PauliOps) representing the magnetic fields ''' num_qubits = len(potentials) for i in range(num_qubits): coeff = 0.5 * potentials[i] labels = ['I'] * (i) + ['Z'] + ['I'] * (num_qubits - (i + 1)) pauli = Pauli(label=labels) pauli_op = PauliOp(pauli, coeff) if i == 0: op = pauli_op else: op += pauli_op return op
def to_pauli(op): if isinstance(op, Pauli): return op elif isinstance(op, str): try: return Pauli(op) except QiskitError: pass raise NoiseError("Invalid Pauli input operator: {}".format(op))
def get_bloch_vectors(qc): rho = what_is_the_density_matrix(qc) bit_size = int(log2(rho.shape[0])) bloch_array = [] for current_bit in range(bit_size): x_component = np.real( np.trace( Pauli.pauli_single(bit_size, current_bit, 'X').to_matrix() @ rho)) y_component = np.real( np.trace( Pauli.pauli_single(bit_size, current_bit, 'Y').to_matrix() @ rho)) z_component = np.real( np.trace( Pauli.pauli_single(bit_size, current_bit, 'Z').to_matrix() @ rho)) bloch_array.append([x_component, y_component, z_component]) return bloch_array
def test_init_from_pauli(self): """Test initialization from Pauli""" samples = 10 nseed = 999 for qubit_num in range(1, 5): for i in range(samples): pauli = Pauli.random(qubit_num, seed=nseed + i) elem = CNOTDihedral(pauli) value = Operator(pauli) target = Operator(elem) self.assertTrue(value.equiv(target), 'Error: Pauli operator is not the same.')
def plot_bloch_multivector(rho, title='', figsize=None): """Plot the Bloch sphere. Plot a sphere, axes, the Bloch vector, and its projections onto each axis. Args: rho (ndarray): Numpy array for state vector or density matrix. title (str): a string that represents the plot title figsize (tuple): Has no effect, here for compatibility only. Returns: Figure: A matplotlib figure instance. Raises: ImportError: Requires matplotlib. """ if not HAS_MATPLOTLIB: raise ImportError('Must have Matplotlib installed.') rho = _validate_input_state(rho) num = int(np.log2(len(rho))) width, height = plt.figaspect(1 / num) fig = plt.figure(figsize=(width, height)) for i in range(num): ax = fig.add_subplot(1, num, i + 1, projection='3d') pauli_singles = [ Pauli.pauli_single(num, i, 'X'), Pauli.pauli_single(num, i, 'Y'), Pauli.pauli_single(num, i, 'Z') ] bloch_state = list( map(lambda x: np.real(np.trace(np.dot(x.to_matrix(), rho))), pauli_singles)) plot_bloch_vector(bloch_state, "qubit " + str(i), ax=ax, figsize=figsize) fig.suptitle(title, fontsize=16) if get_backend() in ['module://ipykernel.pylab.backend_inline', 'nbAgg']: plt.close(fig) return fig
def test_pauli_error_2q_unitary_from_pauli(self): """Test two-qubit pauli error as unitary qobj from Pauli obj""" paulis = [Pauli.from_label(s) for s in ['XY', 'YZ', 'ZX']] probs = [0.5, 0.3, 0.2] error = pauli_error(zip(paulis, probs), standard_gates=False) X = standard_gate_unitary('x') Y = standard_gate_unitary('y') Z = standard_gate_unitary('z') target_unitaries = [np.kron(X, Y), np.kron(Y, Z), np.kron(Z, X)] target_probs = probs.copy() for j in range(len(paulis)): circ, p = error.error_term(j) name = circ[0]['name'] self.assertIn(name, 'unitary') self.assertEqual(circ[0]['qubits'], [0, 1]) self.remove_if_found(p, target_probs) self.remove_if_found(circ[0]['params'], target_unitaries) self.assertEqual(target_probs, [], msg="Incorrect probabilities") self.assertEqual(target_unitaries, [], msg="Incorrect unitaries")
def iplot_bloch_multivector(rho, figsize=None): """ Create a bloch sphere representation. Graphical representation of the input array, using as much bloch spheres as qubit are required. Args: rho (array): State vector or density matrix figsize (tuple): Figure size in pixels. Example: .. code-block:: from qiskit import QuantumCircuit, BasicAer, execute from qiskit.visualization import iplot_bloch_multivector %matplotlib inline qc = QuantumCircuit(2, 2) qc.h(0) qc.cx(0, 1) qc.measure([0, 1], [0, 1]) backend = BasicAer.get_backend('statevector_simulator') job = execute(qc, backend).result() iplot_bloch_multivector(job.get_statevector(qc)) """ # HTML html_template = Template(""" <p> <div id="content_$divNumber" style="position: absolute; z-index: 1;"> <div id="bloch_$divNumber"></div> </div> </p> """) # JavaScript javascript_template = Template(""" <script> requirejs.config({ paths: { qVisualization: "https://qvisualization.mybluemix.net/q-visualizations" } }); data = $data; dataValues = []; for (var i = 0; i < data.length; i++) { // Coordinates var x = data[i][0]; var y = data[i][1]; var z = data[i][2]; var point = {'x': x, 'y': y, 'z': z}; dataValues.push(point); } require(["qVisualization"], function(qVisualizations) { // Plot figure qVisualizations.plotState("bloch_$divNumber", "bloch", dataValues, $options); }); </script> """) rho = _validate_input_state(rho) if figsize is None: options = {} else: options = {'width': figsize[0], 'height': figsize[1]} # Process data and execute num = int(np.log2(len(rho))) bloch_data = [] for i in range(num): pauli_singles = [Pauli.pauli_single(num, i, 'X'), Pauli.pauli_single(num, i, 'Y'), Pauli.pauli_single(num, i, 'Z')] bloch_state = list(map(lambda x: np.real(np.trace(np.dot(x.to_matrix(), rho))), pauli_singles)) bloch_data.append(bloch_state) div_number = str(time.time()) div_number = re.sub('[.]', '', div_number) html = html_template.substitute({ 'divNumber': div_number }) javascript = javascript_template.substitute({ 'data': bloch_data, 'divNumber': div_number, 'options': options }) display(HTML(html + javascript))
def run_exp(num_reps=1): # choice of Hi basis H_basis = [Pauli.from_label(p) for p in ['II', 'ZI', 'IZ', 'ZZ', 'YY', 'XX']] num_qubits = 2 evo_time = 1 epsilon = 0.1 L = 32 ## number of local hamiltonian terms ############################################################ # Generate a random Hamiltonian H as the sum of m basis Hi operators ############################################################ hs = np.random.random(L) indexes = np.random.randint(low=0, high=6, size=L) ## H in matrix form H_matrix = np.zeros((2 ** num_qubits, 2 ** num_qubits)) ## H as a list of pauli operators (unweighted) H_list = [] for i in range(L): H_matrix = H_matrix + hs[i] * H_basis[indexes[i]].to_matrix() H_list.append(H_basis[indexes[i]]) print('matrix H: \n', H_matrix) # H as a pauli operator H_qubitOp = op_converter.to_weighted_pauli_operator(MatrixOperator(matrix=H_matrix)) # Generate an initial state state_in = Custom(num_qubits, state='random') ############################################################ # Ground truth and benchmarks ############################################################ # Ground truth state_in_vec = state_in.construct_circuit('vector') groundtruth = expm(-1.j * H_matrix * evo_time) @ state_in_vec print('The directly computed groundtruth evolution result state is') print('{}\n.'.format(groundtruth)) # Build circuit using Qiskit's evolve algorithm, which based on Trotter-Suzuki. quantum_registers = QuantumRegister(num_qubits) circuit = state_in.construct_circuit('circuit', quantum_registers) circuit += H_qubitOp.evolve( None, evo_time, num_time_slices=10, quantum_registers=quantum_registers, expansion_mode='suzuki', expansion_order=1 ) # Simulate Trotter-Suzuki circuit and print it backend = BasicAer.get_backend('statevector_simulator') job = q_execute(circuit, backend) circuit_execution_result = np.asarray(job.result().get_statevector(circuit)) print('The simulated (suzuki) evolution result state is') print('{}\n'.format(circuit_execution_result)) # The difference between the ground truth and the simulated state # measured by "Fidelity" fidelity_suzuki = state_fidelity(groundtruth, circuit_execution_result) print('Fidelity between the groundtruth and the circuit result states is {}.'.format(fidelity_suzuki)) print('\n') ############################################################ # Our qdrift implementation ############################################################ quantum_registers = QuantumRegister(num_qubits) circuit = state_in.construct_circuit('circuit', quantum_registers) # Contruct the circuit which implements qdrift circuit = time_evolve_qubits(quantum_registers, circuit, num_qubits, H_list, hs, evo_time, epsilon, num_reps) # Simulate circuit and print it backend = BasicAer.get_backend('statevector_simulator') job = q_execute(circuit, backend) circuit_execution_result = np.asarray(job.result().get_statevector(circuit)) print('The simulated (qdrift) evolution result state is\n{}.'.format(circuit_execution_result)) print('\n') # Measure the fidelity fidelity_qdrift = state_fidelity(groundtruth, circuit_execution_result) print('Fidelity between the groundtruth and the circuit result states is {}.'.format(fidelity_qdrift)) print('\n') print('benchmark, suzuki:', fidelity_suzuki) print('qdrift:', fidelity_qdrift) return fidelity_qdrift, fidelity_suzuki
def depolarizing_error(param, num_qubits, standard_gates=None): r""" Return a depolarizing quantum error channel. The depolarizing channel is defined as: .. math:: E(ρ) = (1 - λ) ρ + λ \text{Tr}[ρ] \frac{I}{2^n} with :math:`0 \le λ \le 4^n / (4^n - 1)` where :math:`λ` is the depolarizing error param and :math`n` is the number of qubits. * If :math:`λ = 0` this is the identity channel :math:`E(ρ) = ρ` * If :math:`λ = 1` this is a completely depolarizing channel :math:`E(ρ) = I / 2^n` * If :math:`λ = 4^n / (4^n - 1)` this is a uniform Pauli error channel: :math:`E(ρ) = \sum_j P_j ρ P_j / (4^n - 1)` for all :math:`P_j != I`. Args: param (double): depolarizing error parameter. num_qubits (int): the number of qubits for the error channel. standard_gates (bool): DEPRECATED, if True return the operators as Pauli gates. If false return as unitary gates. (Default: None) Returns: QuantumError: The quantum error object. Raises: NoiseError: If noise parameters are invalid. """ if not isinstance(num_qubits, int) or num_qubits < 1: raise NoiseError("num_qubits must be a positive integer.") # Check that the depolarizing parameter gives a valid CPTP num_terms = 4**num_qubits max_param = num_terms / (num_terms - 1) if param < 0 or param > max_param: raise NoiseError("Depolarizing parameter must be in between 0 " "and {}.".format(max_param)) # Rescale completely depolarizing channel error probs # with the identity component removed prob_iden = 1 - param / max_param prob_pauli = param / num_terms probs = [prob_iden] + (num_terms - 1) * [prob_pauli] if standard_gates is not None: warnings.warn( '"standard_gates" option has been deprecated as of qiskit-aer 0.10.0' ' and will be removed no earlier than 3 months from that release date.', DeprecationWarning, stacklevel=2) circs = [] for pauli_list in it.product( [IGate(), XGate(), YGate(), ZGate()], repeat=num_qubits): qc = QuantumCircuit(num_qubits) for q, pauli in enumerate(pauli_list): if not standard_gates: pauli = UnitaryGate(pauli.to_matrix()) qc.append(pauli, qargs=[q]) circs.append(qc) return QuantumError(zip(circs, probs)) # Generate pauli strings. The order doesn't matter as long # as the all identity string is first. paulis = [ Pauli("".join(tup)) for tup in it.product(['I', 'X', 'Y', 'Z'], repeat=num_qubits) ] return QuantumError(zip(paulis, probs))