from qiskit import QuantumCircuit
qc=QuantumCircuit()

from qiskit import QuantumRegister
qr = QuantumRegister(2,'a')

qc.add_register(qr)

qc.qregs   ## qc.qregs is for displaying

qc.draw()

qc.h(qr[0])   ## applying Hadamard gate on the first qubit


qc.draw()

#qc.x(qr[0]) ## applying Hadamard gate on the first qubit
#qc.draw()

qc.cx(qr[1], qr[0])
qc.draw()

from qiskit import Aer
sv_sim = Aer.get_backend('aer_simulator')    ##it is simulator for showing output

for backend in Aer.backends():     
    print(backend)

from qiskit import assemble
qc.save_statevector()         ## this converts output in to state vector
qobj = assemble(qc)           ## this assembles quantum circuit
job = sv_sim.run(qobj)         ## this is for running the job

ket = job.result().get_statevector()
for amplitude in ket:
    print(amplitude)

new_qc = QuantumCircuit(qr)

new_qc.initialize(ket, qr)

new_qc.x(qr[0]) 

from qiskit import assemble
new_qc.save_statevector()         ## this converts output in to state vector
qobj = assemble(new_qc)           ## this assembles quantum circuit
job = sv_sim.run(qobj) 
ket = job.result().get_statevector()
for amplitude in ket:
    print(amplitude)

from qiskit import ClassicalRegister
cr = ClassicalRegister(2,'creg')

qc.add_register(cr)

qc.measure(qr[0],cr[0])     ##measuring first quibit on first classical register
qc.measure(qr[1],cr[1])    ##measuring second quibit on second classical register

qc.draw()

aer_sim = Aer.get_backend('aer_simulator')
qobj = assemble(qc, shots=100)      ##shots is the number of experiments
job = aer_sim.run(qobj, memory=True)                ##.run is for running the experiments

hist = job.result().get_counts()
print(hist)

from qiskit.visualization import plot_histogram

plot_histogram(hist)

samples = job.result().get_memory()    #to get result of each experiment as a result
print(samples)

qubit = QuantumRegister(8)
bit = ClassicalRegister(8)
qc_2 = QuantumCircuit(qubit,bit)

qc_2.x(qubit[7])
qc_2.measure(qubit,bit) # this is a way to do all the qc.measure(qr8[j],cr8[j]) at once

qobj = assemble(qc_2, shots=8192)
aer_sim.run(qobj).result().get_counts()

qc = QuantumCircuit(2,1)     ## where first arguments is corresponding to number of quantum regsiter and second
                             ##argument is corresponding to the number of classical register.

qc.h(0)
qc.cx(0,1)
qc.measure(1,0)

qc.draw()

sub_circuit = QuantumCircuit(3, name='toggle_cx')
sub_circuit.cx(0,1)
sub_circuit.cx(1,2)
sub_circuit.cx(0,1)
sub_circuit.cx(1,2)

sub_circuit.draw()

toggle_cx = sub_circuit.to_instruction()   ##we convert this circuit to the custom gate

qr = QuantumRegister(4)
new_qc = QuantumCircuit(qr)

new_qc.append(toggle_cx, [qr[1],qr[2],qr[3] ])

new_qc.draw()

