entropicalabs / openqaoa

Multi-backend SDK for quantum optimisation
MIT License
119 stars 58 forks source link

Changing the way gates are applied by the `GateApplicator` objects. #203

Open shahidee44 opened 1 year ago

shahidee44 commented 1 year ago

I don't think we need 4 different methods (apply_1q_rotation_gate, apply_2q_rotation_gate, apply_1q_fixed_gate, apply_1q_fixed_gate) I think they all do exactly the same.

I believe we could change all of this:

    @staticmethod
    def apply_1q_rotation_gate(
        vectorized_gate: Callable,
        qubit_1: int,
        rotation_object: RotationAngle
    ):
        vectorized_gate(
            qubit_1,
            rotation_object.rotation_angle
        )

    @staticmethod
    def apply_2q_rotation_gate(
        vectorized_gate: Callable,
        qubit_1: int,
        qubit_2: int,
        rotation_object: RotationAngle
    ):
        vectorized_gate(
            qubit_1,
            qubit_2,
            rotation_object.rotation_angle
        )

    @staticmethod
    def apply_1q_fixed_gate(
        vectorized_gate: Callable,
        qubit_1: int
    ):
        vectorized_gate(
            qubit_1
        )

    @staticmethod
    def apply_2q_fixed_gate(
        vectorized_gate: Callable,
        qubit_1: int,
        qubit_2: int
    ):
        vectorized_gate(
            qubit_1,
            qubit_2
        )

    def apply_gate(self, gate: gates_core.Gate, *args):
        selected_vector_gate = self.gate_selector(gate, args[-1])
        # Remove argument from tuple
        args=args[:-1]
        if gate.n_qubits == 1:
            if hasattr(gate, 'rotation_object'):
                # *args must be of the following format -- (qubit_1,rotation_object)
                self.apply_1q_rotation_gate(selected_vector_gate, *args)
            else:
                # *args must be of the following format -- (qubit_1)
                self.apply_1q_fixed_gate(selected_vector_gate, *args)
        elif gate.n_qubits == 2:
            if hasattr(gate, 'rotation_object'):
                # *args must be of the following format -- (qubit_1,qubit_2,rotation_object)
                self.apply_2q_rotation_gate(selected_vector_gate, *args)
            else:
                # *args must be of the following format -- (qubit_1,qubit_2)
                self.apply_2q_fixed_gate(selected_vector_gate, *args)
        else:
            raise ValueError("Error applying the requested gate. Please check in the input")

for something much more compact like:

    def apply_gate(self, gate: gates_core.Gate, *args):

        if not gate.n_qubits in [1, 2]:
            raise ValueError("Error applying the requested gate. Please check in the input")

        selected_vector_gate = self.gate_selector(gate, args[-1])

        args_ = args[:-1]
        for i in range(len(args_)):
            if isinstance(args_[i], RotationAngle):
                args_[i] = args_[i].rotation_angle

        selected_vector_gate(*args_)

_Originally posted by @raulconchello in https://github.com/entropicalabs/openqaoa/pull/193#discussion_r1127306608_