Source code for mimiqcircuits.operations.rescaledgates
#
# Copyright © 2022-2024 University of Strasbourg. All Rights Reserved.
# Copyright © 2032-2024 QPerfect. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import symengine as se
from typing import TypeVar, Generic
from mimiqcircuits.operations.operator import AbstractOperator
from mimiqcircuits.operations.gates.gate import Gate
import sympy as sp
T = TypeVar("T", bound=Gate) # T is a type variable bound to Gate
[docs]
class RescaledGate(AbstractOperator, Generic[T]):
r"""RescaledGate operation.
The `RescaledGate` represents an operation where a quantum gate is rescaled by a factor `p`,
typically between 0 and 1. This rescaling modifies the action of the gate, multiplying its
matrix representation by `p`. The gate to be rescaled must be an instance of the `Gate` class,
and `p` must be a valid scalar (real or symbolic) in the range [0, 1].
Args:
- gate (Gate): The quantum gate to be rescaled.
- p (float or symbolic): The rescaling factor, must be between 0 and 1.
Raises:
- TypeError: If the provided gate is not an instance of `Gate`.
- ValueError: If the rescaling factor `p` is not between 0 and 1.
Methods:
- get_operation(): Returns the underlying gate.
- get_param(name): Retrieves the value of a parameter (such as `p`).
- _matrix(*args): Returns the matrix representation of the rescaled gate.
- get_scale(): Returns the scaling factor `p`.
- rescale(p): Returns a new `RescaledGate` with a different scaling factor.
- rescale_in_place(p): Rescales the gate in place by multiplying the current `p` with the new value.
- evaluate(d): Substitutes values in the parameters (useful when symbolic values are used).
Examples:
Creating and rescaling a gate:
>>> from mimiqcircuits import *
>>> g = GateH()
>>> rg = RescaledGate(g, 0.5)
>>> rg.get_scale()
0.5
>>> rg.rescale(0.8)
0.4*H
"""
_name = "RescaledGate"
def __init__(self, gate: T, p):
if not isinstance(gate, Gate):
raise TypeError(
f"Expected gate to be an instance of Gate, got {type(gate).__name__}"
)
super().__init__()
self._num_bits = gate.num_bits
self._num_qubits = gate.num_qubits
self._num_zvars = gate.num_zvars
self._num_cregs = gate._num_cregs
self._num_qregs = gate._num_qregs
self._num_zregs = gate._num_zregs
self._cregsizes = gate._cregsizes
self._qregsizes = gate._qregsizes
self._zregsizes = gate._zregsizes
if not isinstance(p, (se.Basic, sp.Basic)) and (float(p) < 0 or float(p) > 1):
raise ValueError("Value of p must be between 0 and 1.")
self.gate = gate
self.p = p
def __repr__(self):
return self.__str__()
[docs]
def get_operation(self):
return self.gate
[docs]
def get_param(self, name):
if name == "p":
return self.p
return self.gate.get_param(name)
def _matrix(self, *args):
return self.p * self.gate._matrix(*args)
[docs]
def get_scale(self):
return self.p
[docs]
def rescale(self, p):
return RescaledGate(self.gate, self.p * p)
[docs]
def rescale_in_place(self, p):
self.p *= p
return self
[docs]
def evaluate(self, d):
return RescaledGate(self.gate.evaluate(d), evaluate(self.p, d))
def __str__(self):
mult = "*" if getattr(self, "compact", True) else " * "
return f"{self.p}{mult}{self.gate}"
def evaluate(param, d):
# Replace symbols in param according to dictionary d, this is just a placeholder
return param.subs(d) if isinstance(param, (se.Basic, sp.Basic)) else param