<jupyter_start><jupyter_text>Trusted Notebook" width="500 px" align="left">  Quantum CircuitsThe `QuantumCircuit`, `QuantumRegister`, and `ClassicalRegister` are the main objects for Qiskit Terra. Most users will be able to do all they want with these objects. **NOTE THIS ONLY WORKS ON QISKIT 0.7**<jupyter_code>import numpy as np
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import Aer, execute
from qiskit.quantum_info import Pauli, state_fidelity, basis_state, process_fidelity<jupyter_output><empty_output><jupyter_text>Quantum and Classical RegistersQuantum and Classical Registers are declared using the following:<jupyter_code>q0 = QuantumRegister(2, 'q0')
c0 = ClassicalRegister(2, 'c0')
q1 = QuantumRegister(2, 'q1')
c1 = ClassicalRegister(2, 'c1')
q_test = QuantumRegister(2, 'q0')<jupyter_output><empty_output><jupyter_text>The name is optional. If not given Qiskit will name it $qi$ where $i$ is an interger which will count from 0. The name and size can be returned using the following:<jupyter_code>print(q0.name)
print(q0.size)<jupyter_output>q0
2<jupyter_text>You can test if the register are the same or different.<jupyter_code>q0==q0
q0==q_test
q0==q1<jupyter_output><empty_output><jupyter_text>Quantum CircuitsQuantum Circuits are made using registers. Either when initiated or by using the `add_register` command.<jupyter_code>circ = QuantumCircuit(q0, q1)
circ.x(q0[1])
circ.x(q1[0])
circ.draw()<jupyter_output><empty_output><jupyter_text>is the same as<jupyter_code>circ2 = QuantumCircuit()
circ2.add_register(q0)
circ2.add_register(q1)
circ2.x(q0[1])
circ2.x(q1[0])
circ2.draw()<jupyter_output><empty_output><jupyter_text>Note: The order of registers in the list is the order they are initiated or added (**not** the tensor product for quantum registers).<jupyter_code>from copy import deepcopy

q3 = QuantumRegister(2, 'q3')
circ3 = deepcopy(circ)
circ3.add_register(q3)
circ3.draw()<jupyter_output><empty_output><jupyter_text>Note: The circuit drawer has the last register added at the top and if we add a new register it will add it to the top of the circuit. **TODO: CHECK AFTER UPDATE THAT THIS IS CORRECT**  Extending a circuitIn many situations you may have two circuits that you want to concatenate together to form a new circuit. This is very useful when one circuit has no measurements and the final circuit represents a measurement.<jupyter_code>meas = QuantumCircuit(q0, q1, c0, c1)
meas.measure(q0, c0)
meas.measure(q1, c1)

qc = circ + meas

qc.draw()
meas2 = QuantumCircuit()
meas2.add_register(q0)
meas2.add_register(q1)
meas2.add_register(c0)
meas2.add_register(c1)
meas2.measure(q0, c0)
meas2.measure(q1, c1)

qc2 = circ2 + meas2

qc2.draw()<jupyter_output><empty_output><jupyter_text>It even works when the circuits have different registers. Let's start by making two new circuits:<jupyter_code>circ4 = QuantumCircuit(q1)
circ4.x(q1)
circ4.draw()
circ5 = QuantumCircuit(q3)
circ5.h(q3)
circ5.draw()<jupyter_output><empty_output><jupyter_text>The new register is added to the circuit:<jupyter_code>(circ4+circ5).draw()<jupyter_output><empty_output><jupyter_text>We have also overloaded `+=` to the `QuantumCircuit` object:<jupyter_code>circ4 += circ5
circ4.draw()<jupyter_output><empty_output><jupyter_text>Outcomes of Quantum CircuitsIn the circuit output, the most significant bit (MSB) is to the left and the least significant bit (LSB) is to the right (i.e. we follow the regular computer science little endian ordering). In this example:<jupyter_code>circ.draw()<jupyter_output><empty_output><jupyter_text>qubit register $Q_0$ is prepared in the state $|10\rangle$ and $Q_1$ is in the state $|01\rangle$ giving a total state $|0110\rangle$ ($Q1\otimes Q0$). Note: The tensor order in Qiskit goes as $Q_n \otimes .. Q_1 \otimes Q_0$That is the four qubit statevector of length 16 with the 6th element (`int('0110',2)=6`) being one. Note the element count starts from zero.<jupyter_code>backend_sim = Aer.get_backend('statevector_simulator')
result = execute(circ, backend_sim).result()
state = result.get_statevector(circ)
print(state)<jupyter_output>[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j
 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]<jupyter_text>To check the fidelity of this state with the `basis_state` in Qiskit Terra you can use:<jupyter_code>state_fidelity(basis_state('0110', 4), state)<jupyter_output><empty_output><jupyter_text>We can also use Qiskit Terra to make the unitary operator representing the circuit (provided there are no measurements). This will be a $16\otimes16$ matrix equal to $I\otimes X\otimes X\otimes I$. To check this is correct we can use the `Pauli` class and the `process_fidelity` function.<jupyter_code>backend_sim = Aer.get_backend('unitary_simulator')
result = execute(circ, backend_sim).result()
unitary = result.get_unitary(circ)
process_fidelity(Pauli(label='IXXI').to_matrix(), unitary)<jupyter_output><empty_output><jupyter_text>To map the information of the quantum state to the classial world we have to use the example with measurements `qc`:<jupyter_code>qc.draw()<jupyter_output><empty_output><jupyter_text>This will map the quantum state to the classical world and since the state has no superpositions it will be deterministic and equal to `'01 10'`.  Here a space is used to separate the registers.<jupyter_code>backend_sim = Aer.get_backend('qasm_simulator')
result = execute(qc, backend_sim).result()
counts = result.get_counts(qc)
print(counts)<jupyter_output>{'01 10': 1024}<jupyter_text>To show that it does not matter how you add the registers we run the same as above on the second example circuit:<jupyter_code>backend_sim = Aer.get_backend('statevector_simulator')
result = execute(circ2, backend_sim).result()
states = result.get_statevector(circ2)

backend_sim = Aer.get_backend('qasm_simulator')
result = execute(qc2, backend_sim).result()
counts = result.get_counts(qc2)

backend_sim = Aer.get_backend('unitary_simulator')
result = execute(circ2, backend_sim).result()
unitary = result.get_unitary(circ2)
print(counts)
state_fidelity(basis_state('0110', 4), state)
process_fidelity(Pauli(label='IXXI').to_matrix(), unitary)<jupyter_output><empty_output><jupyter_text>Counting circuit resourcesA `QuantumCircuit` object provides methods for inquiring its resource use. This includes the number of qubits, operations, and a few other things.<jupyter_code>q = QuantumRegister(6)
circuit = QuantumCircuit(q)
circuit.h(q[0])
circuit.ccx(q[0], q[1], q[2])
circuit.cx(q[1], q[3])
circuit.x(q)
circuit.h(q[2])
circuit.h(q[3])
circuit.draw()
# total number of operations in the circuit. no unrolling is done.
circuit.size()
# depth of circuit (number of ops on the critical path)
circuit.depth()
# number of qubits in the circuit
circuit.width()
# a breakdown of operations by type
circuit.count_ops()
# number of unentangled subcircuits in this circuit.
# each subcircuit can in principle be executed on a different quantum processor!
circuit.num_tensor_factors()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1074462061155153, 'fraction_numerical': 0.027180067950169876, 'mean_word_length': 6.746710526315789, 'pattern_counts': {'":': 0, '<': 74, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '76952', 'license': 'Apache-2.0', 'n_tokens_mistral': 2570, 'n_tokens_neox': 2374, 'n_words': 719, 'path': 'qiskit/terra/QuantumCircuits.ipynb', 'repo_name': 'antoniomezzacapo/qiskit-tutorial', 'size': '7064'}