Repository: Qiskit/qiskit

Issue:
Should be able to initialize from an integer
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?

Should be able to do:

````
qc.initialize(int)
````
and have it add x gates where the bit values are one.


Discussion:
@nonhermitian, I've been playing around with this and came up with this so far,
```
from qiskit import BasicAer, execute, QuantumCircuit, QuantumRegister
qr = QuantumRegister(5)
qc = QuantumCircuit(qr)
qc.initialize(13)
qc.measure_all()

backend = BasicAer.get_backend('qasm_simulator')
print(execute(qc, backend).result().get_counts())
qc.draw('text')
```
```
{'01101': 1024}

        ┌─────────────────┐ ░ ┌─┐            
 q40_0: ┤0                ├─░─┤M├────────────
        │                 │ ░ └╥┘┌─┐         
 q40_1: ┤1                ├─░──╫─┤M├─────────
        │                 │ ░  ║ └╥┘┌─┐      
 q40_2: ┤2 initialize(13) ├─░──╫──╫─┤M├──────
        │                 │ ░  ║  ║ └╥┘┌─┐   
 q40_3: ┤3                ├─░──╫──╫──╫─┤M├───
        │                 │ ░  ║  ║  ║ └╥┘┌─┐
 q40_4: ┤4                ├─░──╫──╫──╫──╫─┤M├
        └─────────────────┘ ░  ║  ║  ║  ║ └╥┘
meas: 5/═══════════════════════╩══╩══╩══╩══╩═
                               0  1  2  3  4 
```
or
```
from qiskit import BasicAer, execute, QuantumCircuit, QuantumRegister
qr = QuantumRegister(5)
qc = QuantumCircuit(qr)
qc.initialize(13, [0, 1, 2, 4])
qc.measure_all()

backend = BasicAer.get_backend('qasm_simulator')
print(execute(qc, backend).result().get_counts())
qc.draw('text')
```

```
{'10101': 1024}

        ┌─────────────────┐ ░ ┌─┐            
 q35_0: ┤0                ├─░─┤M├────────────
        │                 │ ░ └╥┘┌─┐         
 q35_1: ┤1                ├─░──╫─┤M├─────────
        │                 │ ░  ║ └╥┘┌─┐      
 q35_2: ┤2 initialize(13) ├─░──╫──╫─┤M├──────
        │                 │ ░  ║  ║ └╥┘┌─┐   
 q35_3: ┤                 ├─░──╫──╫──╫─┤M├───
        │                 │ ░  ║  ║  ║ └╥┘┌─┐
 q35_4: ┤3                ├─░──╫──╫──╫──╫─┤M├
        └─────────────────┘ ░  ║  ║  ║  ║ └╥┘
meas: 5/═══════════════════════╩══╩══╩══╩══╩═
                               0  1  2  3  4 
```
One question is, if the number of bits in the integer exceeds the num_qubits, should we raise or just strip the leading bits off and use num_qubits bits?

Resolving patch:
diff --git a/qiskit/extensions/quantum_initializer/initializer.py b/qiskit/extensions/quantum_initializer/initializer.py
--- a/qiskit/extensions/quantum_initializer/initializer.py
+++ b/qiskit/extensions/quantum_initializer/initializer.py
@@ -42,22 +42,38 @@ class Initialize(Instruction):
     which is not unitary.
     """
 
-    def __init__(self, params):
+    def __init__(self, params, num_qubits=None):
         """Create new initialize composite.
 
-        params (str or list):
+        params (str, list, or int):
           * list: vector of complex amplitudes to initialize to.
           * string: labels of basis states of the Pauli eigenstates Z, X, Y. See
                :meth:`~qiskit.quantum_info.states.statevector.Statevector.from_label`.
                Notice the order of the labels is reversed with respect to the qubit index to
                be applied to. Example label '01' initializes the qubit zero to `|1>` and the
-               qubit one to `|0>`
+               qubit one to `|0>`.
+          * int: an integer that is used as a bitmap indicating which qubits to initialize
+               to `|1>`. Example: setting params to 5 would initialize qubit 0 and qubit 2
+               to `|1>` and qubit 1 to `|0>`.
+        num_qubits (int): This parameter is only used if params is an int. Indicates the total
+            number of qubits in the `initialize` call. Example: `initialize` covers 5 qubits
+            and params is 3. This allows qubits 0 and 1 to be initialized to `|1>` and the
+            remaining 3 qubits to be initialized to `|0>`.
         """
+        if not isinstance(params, int) and num_qubits is not None:
+            raise QiskitError("The num_qubits parameter to Initialize should only be"
+                              " used when params is an integer")
+        self._from_label = False
+        self._from_int = False
         if isinstance(params, str):
-            self._fromlabel = True
+            self._from_label = True
             num_qubits = len(params)
+        elif isinstance(params, int):
+            self._from_int = True
+            if num_qubits is None:
+                num_qubits = int(math.log2(params)) + 1
+            params = [params]
         else:
-            self._fromlabel = False
             num_qubits = math.log2(len(params))
 
             # Check if param is a power of 2
@@ -74,9 +90,14 @@ def __init__(self, params):
         super().__init__("initialize", num_qubits, 0, params)
 
     def _define(self):
-        self.definition = self._define_fromlabel() if self._fromlabel else self._define_synthesis()
+        if self._from_label:
+            self.definition = self._define_from_label()
+        elif self._from_int:
+            self.definition = self._define_from_int()
+        else:
+            self.definition = self._define_synthesis()
 
-    def _define_fromlabel(self):
+    def _define_from_label(self):
         q = QuantumRegister(self.num_qubits, 'q')
         initialize_circuit = QuantumCircuit(q, name='init_def')
 
@@ -99,6 +120,27 @@ def _define_fromlabel(self):
 
         return initialize_circuit
 
+    def _define_from_int(self):
+        q = QuantumRegister(self.num_qubits, 'q')
+        initialize_circuit = QuantumCircuit(q, name='init_def')
+
+        # Convert to int since QuantumCircuit converted to complex
+        # and make a bit string and reverse it
+        intstr = f'{int(np.real(self.params[0])):0{self.num_qubits}b}'[::-1]
+
+        # Raise if number of bits is greater than num_qubits
+        if len(intstr) > self.num_qubits:
+            raise QiskitError("Initialize integer has %s bits, but this exceeds the"
+                              " number of qubits in the circuit, %s." %
+                              (len(intstr), self.num_qubits))
+
+        for qubit, bit in enumerate(intstr):
+            initialize_circuit.append(Reset(), [q[qubit]])
+            if bit == '1':
+                initialize_circuit.append(XGate(), [q[qubit]])
+
+        return initialize_circuit
+
     def _define_synthesis(self):
         """Calculate a subcircuit that implements this initialization
 
@@ -299,7 +341,7 @@ def validate_parameter(self, parameter):
         """Initialize instruction parameter can be str, int, float, and complex."""
 
         # Initialize instruction parameter can be str
-        if self._fromlabel:
+        if self._from_label:
             if parameter in ['0', '1', '+', '-', 'l', 'r']:
                 return parameter
             raise CircuitError("invalid param label {0} for instruction {1}. Label should be "
@@ -315,11 +357,17 @@ def validate_parameter(self, parameter):
                                "{1}".format(type(parameter), self.name))
 
 
-def initialize(self, params, qubits):
+def initialize(self, params, qubits=None):
     """Apply initialize to circuit."""
-    if not isinstance(qubits, list):
-        qubits = [qubits]
-    return self.append(Initialize(params), qubits)
+    if qubits is None:
+        qubits = self.qubits
+    else:
+        if isinstance(qubits, int):
+            qubits = [qubits]
+        qubits = self._bit_argument_conversion(qubits, self.qubits)
+
+    num_qubits = None if not isinstance(params, int) else len(qubits)
+    return self.append(Initialize(params, num_qubits), qubits)
 
 
 QuantumCircuit.initialize = initialize


Test patch:
diff --git a/test/python/circuit/test_initializer.py b/test/python/circuit/test_initializer.py
--- a/test/python/circuit/test_initializer.py
+++ b/test/python/circuit/test_initializer.py
@@ -346,16 +346,18 @@ def test_max_number_cnots(self):
     def test_from_labels(self):
         """Initialize from labels."""
         desired_sv = Statevector.from_label('01+-lr')
-
         qc = QuantumCircuit(6)
         qc.initialize('01+-lr', range(6))
-        job = execute(qc, BasicAer.get_backend('statevector_simulator'))
-        result = job.result()
-        statevector = result.get_statevector()
-        fidelity = state_fidelity(statevector, desired_sv)
-        self.assertGreater(
-            fidelity, self._desired_fidelity,
-            "Initializer has low fidelity {:.2g}.".format(fidelity))
+        actual_sv = Statevector.from_instruction(qc)
+        self.assertTrue(desired_sv == actual_sv)
+
+    def test_from_int(self):
+        """Initialize from int."""
+        desired_sv = Statevector.from_label('110101')
+        qc = QuantumCircuit(6)
+        qc.initialize(53, range(6))
+        actual_sv = Statevector.from_instruction(qc)
+        self.assertTrue(desired_sv == actual_sv)
 
 
 class TestInstructionParam(QiskitTestCase):