Giter Club home page Giter Club logo

Comments (5)

thomashaener avatar thomashaener commented on August 17, 2024

I agree that there are benefits, but there is no pi in the definition of Rz (I'd expect its argument to be theta in exp(+/- i*theta/2)).
Not providing Rz at all (and going with ZPow instead) is not a good solution either, since Rx,y,z can be found in most textbooks.
As for the resource count / circuit drawing: We could also just run a continued fraction expansion on both the angle itself and angle/pi (if the first cfe didn't converge) to have a nicer output.

from projectq.

Strilanc avatar Strilanc commented on August 17, 2024

You definitely wouldn't want to remove Rz (since people will indeed want to use it). But the internal constructions can prefer ZPow over Rz and thereby gain free precision.

There'd be other things to do, like ensure they interop when merging etc.

from projectq.

Strilanc avatar Strilanc commented on August 17, 2024

Having rotation gates support __pow__, with the gate as either the base or the exponent, would subsume this idea.

from projectq.

Strilanc avatar Strilanc commented on August 17, 2024

Some followup on what this would look like:

def _exp_i_pi(exponent):
    exponent %= 2
    exponent = float(exponent)

    # At half-steps, give results without floating point error.
    if exponent % 0.5 == 0:
        return 1j**int(exponent * 2)

    return cmath.exp(np.pi * 1j * exponent)


class VectorPhaseGate(BasicGate):
    def __init__(self, vector_name, vector, phase_exponent=1):
        """
        :param vector_name: The root name used when describing the gate.
        :param vector: The eigenvector to phase. All vectors perpendicular
            to this one are not affected by the operation.

            Doesn't need to be normalized.
        :param phase_exponent: The eigenvector is phased by -1 raised to this
            power, defined as (-1)^x = exp(i π x).
        """
        super(VectorPhaseGate, self).__init__()
        self.vector = vector
        self.vector_name = vector_name
        # Wrap into (-1, +1].
        self.phase_exponent = -((1-phase_exponent) % 2 - 1)

    def __str__(self):
        g = self.vector_name
        e = self.phase_exponent
        if e == 1:
            return g
        return g + '^' + str(e)

    def tex_str(self):
        g = self.vector_name
        e = self.phase_exponent
        if e == 1:
            return g
        return g + '^{' + str(e) + '}'

    @property
    def matrix(self):
        d = len(self.vector)
        m = np.dot(self.vector, self.vector.T)
        p = _exp_i_pi(self.phase_exponent)
        return np.identity(d) + (p - 1) * m / m.trace()

    def __and__(self, other):
        return OperationWithControl(self, other)

    def __eq__(self, other):
        return (isinstance(other, VectorPhaseGate) and
                np.array_equal(self.vector, other.vector) and
                self.vector_name == other.vector_name and
                self.phase_exponent % 2 == other.phase_exponent % 2)

    def same_axis_as(self, other):
        return (isinstance(other, VectorPhaseGate) and
                np.array_equal(self.vector, other.vector) and
                self.vector_name == other.vector_name)

    def __pow__(self, power):
        return VectorPhaseGate(self.vector_name,
                               self.vector,
                               self.phase_exponent * power)

    def get_inverse(self):
        return VectorPhaseGate(self.vector_name,
                               self.vector,
                               -self.phase_exponent)

    def get_merged(self, other):
        if not self.same_axis_as(other):
            raise NotMergeable('Different axis.')
        return VectorPhaseGate(self.vector_name,
                               self.vector,
                               self.phase_exponent + other.phase_exponent)


X = VectorPhaseGate('X', np.mat([[1], [-1]]))
Y = VectorPhaseGate('Y', np.mat([[1], [1j]]))
Z = VectorPhaseGate('Z', np.mat([[0], [1]]))
H = VectorPhaseGate('H', np.mat([[1 - np.sqrt(2)], [1]]))

S = Z**0.5
Sdag = Z**-0.5

T = Z**0.25
Tdag = Z**-0.25

from projectq.

thomashaener avatar thomashaener commented on August 17, 2024

I think adding __pow__ to BasicRotationGate would be nice. I would not do the above for X, Y, Z, H, ..., as it makes the compilation harder (one always has to run rotation synthesis although it was just, e.g., H which got merged with S).

from projectq.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.