<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <img src="../../images/qiskit-heading.gif" alt="Note
Step1:  Quantum and Classical Registers
Quantum and Classical Registers are declared using the following
Step2:  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
Step3:  You can test if the register are the same or different.
Step4:  Quantum Circuits
Quantum Circuits are made using registers. Either when initiated or by using the add_register command.
Step5:  is the same as
Step6:  <div class="alert alert-block alert-info">
<b>Note
Step7:  <div class="alert alert-block alert-info">
<b>Note
Step8:  It even works when the circuits have different registers. Let's start by making two new circuits
Step9:  The new register is added to the circuit
Step10:  We have also overloaded += to the QuantumCircuit object
Step11:  Outcomes of Quantum Circuits
In 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
Step12:  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$). 
<div class="alert alert-block alert-info">
<b>Note
Step13:  To check the fidelity of this state with the basis_state in Qiskit Terra you can use
Step14:  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.
Step15:  To map the information of the quantum state to the classial world we have to use the example with measurements qc
Step16:  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.
Step17:  To show that it does not matter how you add the registers we run the same as above on the second example circuit
Step18:  Counting circuit resources
A QuantumCircuit object provides methods for inquiring its resource use. This includes the number of qubits, operations, and a few other things.
<ASSISTANT_TASK:>
Python 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 
Explanation: <img src="../../images/qiskit-heading.gif" alt="Note: In order for images to show up in this jupyter notebook you need to select File => Trusted Notebook" width="500 px" align="left">
Quantum Circuits
The 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
End of explanation
q0 = QuantumRegister(2, 'q0')
c0 = ClassicalRegister(2, 'c0')
q1 = QuantumRegister(2, 'q1')
c1 = ClassicalRegister(2, 'c1')
q_test = QuantumRegister(2, 'q0')
Explanation: Quantum and Classical Registers
Quantum and Classical Registers are declared using the following:
End of explanation
print(q0.name)
print(q0.size)
Explanation: 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:
End of explanation
q0==q0
q0==q_test
q0==q1
Explanation: You can test if the register are the same or different.
End of explanation
circ = QuantumCircuit(q0, q1)
circ.x(q0[1])
circ.x(q1[0])
circ.draw()
Explanation: Quantum Circuits
Quantum Circuits are made using registers. Either when initiated or by using the add_register command.
End of explanation
circ2 = QuantumCircuit()
circ2.add_register(q0)
circ2.add_register(q1)
circ2.x(q0[1])
circ2.x(q1[0])
circ2.draw()
Explanation: is the same as
End of explanation
from copy import deepcopy
q3 = QuantumRegister(2, 'q3')
circ3 = deepcopy(circ)
circ3.add_register(q3)
circ3.draw()
Explanation: <div class="alert alert-block alert-info">
<b>Note:</b> The order of registers in the list is the order they are initiated or added (**not** the tensor product for quantum registers).
</div>
End of explanation
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()
Explanation: <div class="alert alert-block alert-info">
<b>Note:</b> 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. 
</div>
TODO: CHECK AFTER UPDATE THAT THIS IS CORRECT
Extending a circuit
In 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.
End of explanation
circ4 = QuantumCircuit(q1)
circ4.x(q1)
circ4.draw()
circ5 = QuantumCircuit(q3)
circ5.h(q3)
circ5.draw()
Explanation: It even works when the circuits have different registers. Let's start by making two new circuits:
End of explanation
(circ4+circ5).draw()
Explanation: The new register is added to the circuit:
End of explanation
circ4 += circ5
circ4.draw()
Explanation: We have also overloaded += to the QuantumCircuit object:
End of explanation
circ.draw()
Explanation: Outcomes of Quantum Circuits
In 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:
End of explanation
backend_sim = Aer.get_backend('statevector_simulator')
result = execute(circ, backend_sim).result()
state = result.get_statevector(circ)
print(state)
Explanation: 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$). 
<div class="alert alert-block alert-info">
<b>Note:</b> The tensor order in Qiskit goes as $Q_n \otimes .. Q_1 \otimes Q_0$
</div>
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.
End of explanation
state_fidelity(basis_state('0110', 4), state)
Explanation: To check the fidelity of this state with the basis_state in Qiskit Terra you can use:
End of explanation
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)
Explanation: 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.
End of explanation
qc.draw()
Explanation: To map the information of the quantum state to the classial world we have to use the example with measurements qc:
End of explanation
backend_sim = Aer.get_backend('qasm_simulator')
result = execute(qc, backend_sim).result()
counts = result.get_counts(qc)
print(counts)
Explanation: 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.
End of explanation
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)
Explanation: To show that it does not matter how you add the registers we run the same as above on the second example circuit:
End of explanation
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()
Explanation: Counting circuit resources
A QuantumCircuit object provides methods for inquiring its resource use. This includes the number of qubits, operations, and a few other things.
End of explanation
<END_TASK>