Repository: Qiskit/qiskit

Issue:
Pass to remove reset in the beginning of circuit
<!-- ⚠️ 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?
We need a pass that removes `reset` operations if they are immediately after "in" nodes. 

A more advanced version of this would involve analyzing whether the qubit is in the 0 state, potentially even in the middle of the circuit.


Discussion:

Resolving patch:
diff --git a/qiskit/transpiler/passes/__init__.py b/qiskit/transpiler/passes/__init__.py
--- a/qiskit/transpiler/passes/__init__.py
+++ b/qiskit/transpiler/passes/__init__.py
@@ -24,6 +24,7 @@
 from .commutation_analysis import CommutationAnalysis
 from .optimize_swap_before_measure import OptimizeSwapBeforeMeasure
 from .commutative_cancellation import CommutativeCancellation
+from .remove_reset_in_zero_state import RemoveResetInZeroState
 from .mapping.barrier_before_final_measurements import BarrierBeforeFinalMeasurements
 from .mapping.check_map import CheckMap
 from .mapping.check_cnot_direction import CheckCnotDirection
diff --git a/qiskit/transpiler/passes/remove_reset_in_zero_state.py b/qiskit/transpiler/passes/remove_reset_in_zero_state.py
new file mode 100644
--- /dev/null
+++ b/qiskit/transpiler/passes/remove_reset_in_zero_state.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2019, IBM.
+#
+# This source code is licensed under the Apache License, Version 2.0 found in
+# the LICENSE.txt file in the root directory of this source tree.
+
+
+"""
+Transpiler pass to remove reset gate when the qubit is in zero state
+"""
+
+from qiskit.circuit import Reset
+from qiskit.transpiler.basepasses import TransformationPass
+
+
+class RemoveResetInZeroState(TransformationPass):
+    """Remove reset gate when the qubit is in zero state"""
+
+    def run(self, dag):
+        """Return a new circuit that has been optimized."""
+        resets = dag.op_nodes(Reset)
+        for reset in resets:
+            predecessor = next(dag.predecessors(reset))
+            if predecessor.type == 'in':
+                dag.remove_op_node(reset)
+        return dag


Test patch:
diff --git a/test/python/transpiler/test_remove_reset_in_zero_state.py b/test/python/transpiler/test_remove_reset_in_zero_state.py
new file mode 100644
--- /dev/null
+++ b/test/python/transpiler/test_remove_reset_in_zero_state.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2019, IBM.
+#
+# This source code is licensed under the Apache License, Version 2.0 found in
+# the LICENSE.txt file in the root directory of this source tree.
+
+"""Test RemoveResetInZeroState pass"""
+
+import unittest
+
+from qiskit import QuantumRegister, QuantumCircuit
+from qiskit.transpiler import PassManager, transpile_dag
+from qiskit.transpiler.passes import RemoveResetInZeroState, DAGFixedPoint
+from qiskit.converters import circuit_to_dag
+from qiskit.test import QiskitTestCase
+
+
+class TestRemoveResetInZeroState(QiskitTestCase):
+    """ Test swap-followed-by-measure optimizations. """
+
+    def test_optimize_single_reset(self):
+        """ Remove a single reset
+            qr0:--|0>--   ==>    qr0:----
+        """
+        qr = QuantumRegister(1, 'qr')
+        circuit = QuantumCircuit(qr)
+        circuit.reset(qr)
+        dag = circuit_to_dag(circuit)
+
+        expected = QuantumCircuit(qr)
+
+        pass_ = RemoveResetInZeroState()
+        after = pass_.run(dag)
+
+        self.assertEqual(circuit_to_dag(expected), after)
+
+    def test_dont_optimize_non_zero_state(self):
+        """ Do not remove reset if not in a zero state
+            qr0:--[H]--|0>--   ==>    qr0:--[H]--|0>--
+        """
+        qr = QuantumRegister(1, 'qr')
+        circuit = QuantumCircuit(qr)
+        circuit.h(qr)
+        circuit.reset(qr)
+        dag = circuit_to_dag(circuit)
+
+        expected = QuantumCircuit(qr)
+        expected.h(qr)
+        expected.reset(qr)
+
+        pass_ = RemoveResetInZeroState()
+        after = pass_.run(dag)
+
+        self.assertEqual(circuit_to_dag(expected), after)
+
+    def test_optimize_single_reset_in_diff_qubits(self):
+        """ Remove a single reset in different qubits
+            qr0:--|0>--          qr0:----
+                          ==>
+            qr1:--|0>--          qr1:----
+        """
+        qr = QuantumRegister(2, 'qr')
+        circuit = QuantumCircuit(qr)
+        circuit.reset(qr)
+        dag = circuit_to_dag(circuit)
+
+        expected = QuantumCircuit(qr)
+
+        pass_ = RemoveResetInZeroState()
+        after = pass_.run(dag)
+
+        self.assertEqual(circuit_to_dag(expected), after)
+
+
+class TestRemoveResetInZeroStateFixedPoint(QiskitTestCase):
+    """ Test RemoveResetInZeroState in a transpiler, using fixed point. """
+
+    def test_two_resets(self):
+        """ Remove two initial resets
+            qr0:--|0>-|0>--   ==>    qr0:----
+        """
+        qr = QuantumRegister(1, 'qr')
+        circuit = QuantumCircuit(qr)
+        circuit.reset(qr[0])
+        circuit.reset(qr[0])
+        dag = circuit_to_dag(circuit)
+
+        expected = QuantumCircuit(qr)
+
+        pass_manager = PassManager()
+        pass_manager.append(
+            [RemoveResetInZeroState(), DAGFixedPoint()],
+            do_while=lambda property_set: not property_set['dag_fixed_point'])
+        after = transpile_dag(dag, pass_manager=pass_manager)
+
+        self.assertEqual(circuit_to_dag(expected), after)
+
+
+if __name__ == '__main__':
+    unittest.main()