Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initialise simulator instruction to statevector_state #117

Merged
merged 22 commits into from
Apr 15, 2019

Conversation

ShellyGarion
Copy link
Member

@ShellyGarion ShellyGarion commented Apr 1, 2019

Summary

#82

Details and comments

Added some printouts for debugging - should be removed later

TODO

  • Update Changelog

@ShellyGarion
Copy link
Member Author

Added examples (in comments) to the functions index0 and indexes in QubitVector class, to explain what they are doing

@ShellyGarion
Copy link
Member Author

  • Now the code compiles and running - still need to verify that it does the right calculation
  • Removed printouts (for debugging)
  • Added some comments with explanation & examples

@chriseclectic
Copy link
Member

@ShellyGarion great! For verifying can you add some basic unit tests for initializing subsets of qubits. Some simple tests could be something like a 3-qubit state prepared in the |+++⟩ state:

  1. Initialize qubit [i] to |1⟩ state (for i =[0], [1], [2])
  2. Initialize qubits [i, j] to |01⟩ state for [i,j] = [0,1], [1, 0], [0, 2], [2, 0], [1, 2], [2, 1], where checking i->|1⟩, j->|0⟩.
  3. Initialize qubits [i, j, k] to |-01⟩ state for permutations of [i,j,j] = [0, 1, 2], [0, 2, 1], [1, 0, 2], etc.. the permutations are checking qubit i -> |1⟩, j->|0⟩, k->|-⟩.

You could also add tests that it works correctly for an entangled state: Eg 2-qubits prepared in |00⟩+|11⟩ / sqrt(2), and reset qubit [0] to |+⟩, the final state should be |0+⟩ or |1+⟩ with 50% probability each.

@chriseclectic chriseclectic added this to the 0.2 milestone Apr 3, 2019
@ShellyGarion
Copy link
Member Author

The initialize_component function is not producing the correct output (the norm of the vector is not 1) - I need to debug it

@ShellyGarion
Copy link
Member Author

@chriseclectic - In the function initialize_component - what should N be?
The number of qubits to be initialized ( N = qubits.size() ) or the total number of qubits in the state?
If it's the second option - how do I get this number? (I tried to use the function num_qubits() but got some error when running the code).

src/simulators/statevector/statevector_state.hpp Outdated Show resolved Hide resolved
src/simulators/statevector/statevector_state.hpp Outdated Show resolved Hide resolved
src/simulators/statevector/qubitvector.hpp Outdated Show resolved Hide resolved
@ShellyGarion
Copy link
Member Author

@chriseclectic - I updated the code following your comments and PR #126, and performed the checks that you suggested above, and it looks OK (see details below).
But I still need to update test_statevector_simulator.py accordingly.

In particular, we started from |+++> state:

[0.35355339+0.j 0.35355339+0.j 0.35355339+0.j 0.35355339+0.j
 0.35355339+0.j 0.35355339+0.j 0.35355339+0.j 0.35355339+0.j]
  • Initialized qubit i to |1> state for i=0,1,2 - and got that this was the "complement" of reset, e.g.
reset: qubit 0
statevector: [0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j] 
initialize: qubit 0
statevector: [0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j]

  • Initialized qubits i,j (for i,j=0,1,2) in two different ways and got the same results:
(name='initialize', qubits=[qubit_i], params=[[0, 0],[1, 0]]))
(name='initialize', qubits=[qubit_j], params=[[1, 0],[0, 0]]))

and:
(name='initialize', qubits=[qubit_i, qubit_j], params=[[0, 0], [1, 0], [0, 0], [0, 0]]))

  • Initialized qubits i,j,k (for i,j,k=0,1,2) in two different ways and got the same results:
(name='initialize', qubits=[qubit_i], params=[[0, 0], [1, 0]]))
(name='initialize', qubits=[qubit_j], params=[[1, 0], [0, 0]]))
(name='initialize', qubits=[qubit_k], params=[[0.70710678, 0], [-0.70710678, 0]]))

and:

(name='initialize', qubits=[qubit_i,qubit_j,qubit_k],
params=[[0, 0], [0.70710678, 0], [0, 0], [0, 0], [0, 0], [-0.70710678, 0], [0, 0], [0, 0]]))

I also started with the Bell state:
[0.70710678+0.j 0. +0.j 0. +0.j 0.70710678+0.j]
and reset qubit [0] to |+⟩, then I got either:
[ 0. +0.j 0. +0.j 0.70710678+0.j -0.70710678+0.j] or:
[ 0.70710678+0.j -0.70710678+0.j 0. +0.j 0. +0.j]

@chriseclectic
Copy link
Member

@ShellyGarion can you add a proper unit file for the above tests (and the failing test from your issue comments) and we can look to debugging them.

@ShellyGarion
Copy link
Member Author

ShellyGarion commented Apr 10, 2019

@chriseclectic - please see the updated test/terra/test_statevector_simulator.py in the recent commit to this PR.
It calls the following two temporary files:

  • test/terra/utils/ref_initialize_temp_1.py:
    in which I Initialized the Qobj directly by adding QasmQobjInstruction, and the calculation of the statevector after the initialize looks correct.
    In particular after initializing qubit 0 directly using
    qobj.experiments[0].instructions.append(QasmQobjInstruction(name='initialize', qubits=[0], params=[[0,0],[1,0]]))
    we get:
    initialize: qubit 0 statevector: [0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j]
  • test/terra/utils/ref_initialize_temp_2.py:
    in which I used the API of: circ6.initialize(np.array([0.+0.j, 1.+0.j]), [qr[0]]), and the output statevector is wrong...
    statevector of circ6: [-0.35355339+0.j 0.35355339+0.j -0.35355339+0.j 0.35355339+0.j -0.35355339+0.j 0.35355339+0.j -0.35355339+0.j 0.35355339+0.j]

@ShellyGarion
Copy link
Member Author

I think that the problem may be with the type of the params given -
see in the code and output of ref_initialize_temp_2.py the difference between circ4 and circ6.

When I update the Qobj in circ4 directly using:
qobj = assemble_circuits(circ4, run_config=RunConfig(shots=1000)) qobj.experiments[0].instructions.append(QasmQobjInstruction(name='initialize', qubits=[0], params= [[0,0],[1,0]]))
I get the following Qobj:
QasmQobj(config=QasmQobjConfig(memory_slots=0, n_qubits=3, shots=1000), experiments=[QasmQobjExperiment(config=QasmQobjExperimentConfig(memory_slots=0, n_qubits=3), header=QobjExperimentHeader(clbit_labels=[], creg_sizes=[], memory_slots=0, n_qubits=3, name='circuit248', qreg_sizes=[['q65', 3]], qubit_labels=[['q65', 0], ['q65', 1], ['q65', 2]]), instructions=[QasmQobjInstruction(name='h', qubits=[0]), QasmQobjInstruction(name='h', qubits=[1]), QasmQobjInstruction(name='h', qubits=[2]), QasmQobjInstruction(name='initialize', params=[[0, 0], [1, 0]], qubits=[0])])], header=QobjHeader(), qobj_id='2279534b-04fd-4ee4-8802-404d5664558b', schema_version='1.1.0', type='QASM')
and the correct output:
statevector of updated circ4 (after initialize): [0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j 0. +0.j 0.5+0.j]

When I update circ6 using circ6.initialize(np.array([0.+0.j, 1.+0.j]), [qr[0]])
then I get the following Qobj:
QasmQobj(config=QasmQobjConfig(memory_slots=0, n_qubits=3), experiments=[QasmQobjExperiment(config=QasmQobjExperimentConfig(memory_slots=0, n_qubits=3), header=QobjExperimentHeader(clbit_labels=[], creg_sizes=[], memory_slots=0, n_qubits=3, name='circuit252', qreg_sizes=[['q65', 3]], qubit_labels=[['q65', 0], ['q65', 1], ['q65', 2]]), instructions=[QasmQobjInstruction(name='h', qubits=[0]), QasmQobjInstruction(name='h', qubits=[1]), QasmQobjInstruction(name='h', qubits=[2]), QasmQobjInstruction(name='initialize', params=[0, 1.00000000000000], qubits=[0])])], header=QobjHeader(), qobj_id='e0f15fcb-9e66-402c-8a25-564100caf24f', schema_version='1.1.0', type='QASM')
and the output is not correct:
statevector of circ6: [-0.35355339+0.j 0.35355339+0.j -0.35355339+0.j 0.35355339+0.j -0.35355339+0.j 0.35355339+0.j -0.35355339+0.j 0.35355339+0.j]

As you can see, in the Qobj of circ4 we have: (name='initialize', params=[[0, 0], [1, 0]], qubits=[0])])
whereas in the Qobj of circ6 we have: (name='initialize', params=[0, 1.00000000000000], qubits=[0])

@chriseclectic
Copy link
Member

@ShellyGarion the code looks good to me. I think the failing tests are when you use execute instead of assemble_circuits. Since 'initialize' is not in the simulators basis gates the terra compiler is unrolling the initialize instruction to gates and there is a bug with this unrolling in terra in that it does not insert the required reset operations so it will fail if initialize isn't the first instruction in a circuit.

Can you edit the StatevectorSimulator and QasmSimulator python classes to include 'initalize' in their basis gates and then i think it should work

Note that you can check the correct qobj is being produced by using old compile instead of new assemble_circuits since it will unroll to the simulators basis gates.

From local testing I didn't find any problems with different format of the input state, the following all produced the same result for me:

qr = QuantumRegister(3)

circ0 = QuantumCircuit(qr)
circ0.h(qr)
circ0.reset(qr[0])
circ0.x(qr[0])

circ1 = QuantumCircuit(qr)
circ1.h(qr)
circ1.initialize([0, 1], [qr[0]])

circ2 = QuantumCircuit(qr)
circ2.h(qr)
circ2.initialize([0.0, 1.0], [qr[0]])

circ3 = QuantumCircuit(qr)
circ3.h(qr)
circ3.initialize([0j, 1.0 + 0j], [qr[0]])

circ4 = QuantumCircuit(qr)
circ4.h(qr)
circ4.initialize(np.array([0, 1], dtype=float), [qr[0]])

circ5 = QuantumCircuit(qr)
circ5.h(qr)
circ5.initialize(np.array([0, 1], dtype=complex), [qr[0]])

@ShellyGarion
Copy link
Member Author

@chriseclectic - Indeed, I am now using the new API of assemble_circuits and the deterministic tests are running OK.

However, I am not sure how to combine a nondeterministic test as you suggested above:
"Start with an entangled state: Eg 2-qubits prepared in |00⟩+|11⟩ / sqrt(2), and reset qubit [0] to |+⟩, the final state should be |0+⟩ or |1+⟩ with 50% probability each."

I also added initialize and reset to the StatevectorSimulator and QasmSimulator python classes.

@ShellyGarion ShellyGarion changed the title [WIP] Add initialise simulator instruction to statevector_state Add initialise simulator instruction to statevector_state Apr 14, 2019
@ShellyGarion
Copy link
Member Author

@chriseclectic - I think that most of the test_statevector_simulator.py (namely, testing reset and other gates) is written with the old API of "execute" that will be deprecated soon.

@yaelbh yaelbh mentioned this pull request Apr 15, 2019
@chriseclectic chriseclectic merged commit 2f82397 into Qiskit:master Apr 15, 2019
@chriseclectic
Copy link
Member

This is passing so I will merge here, and @yaelbh will continue working on tests in follow up PR #137

gadial pushed a commit to gadial/qiskit-aer that referenced this pull request Apr 16, 2019
* added initialize_component function to qubitvector class

* added examples to index0 and indexes functions (in comments)

* added comments with explanations to qubitvector class

* added an optimization where the qubits are sorted

* added a test: initialize_statevector_deterministic

* updated test_statevector simulator

* added basic gates initialize and reset to statvector_simulator and qasm_simulator classes
dcmckayibm pushed a commit to dcmckayibm/qiskit-aer that referenced this pull request Nov 3, 2019
* added initialize_component function to qubitvector class

* added examples to index0 and indexes functions (in comments)

* added comments with explanations to qubitvector class

* added an optimization where the qubits are sorted

* added a test: initialize_statevector_deterministic

* updated test_statevector simulator

* added basic gates initialize and reset to statvector_simulator and qasm_simulator classes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants