Source code for simulaqron.virtNode.basics

#
# Copyright (c) 2017, Stephanie Wehner and Axel Dahlberg
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#    This product includes software developed by Stephanie Wehner, QuTech.
# 4. Neither the name of the QuTech organization nor the
#    names of its contributors may be used to endorse or promote products
#    derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import abc
from twisted.spread import pb


[docs]class quantumError(pb.Error): def __init__(self, value): self.value = value def __str__(self): return repr(self.value)
[docs]class noQubitError(quantumError): pass
[docs]class virtNetError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value)
[docs]class quantumEngine(pb.Referenceable): """ Basic quantum engine. Abstract class meant to be subclassed to implement different simulation backends. Attributes: Arguments node node this register is started from num number of this register maxQubits maximum number of qubits this register supports """ def __init__(self, node, num, maxQubits=10): """ Initialize the simple engine. If no number is given for maxQubits, the assumption will be 10. """ self.maxQubits = maxQubits # Each register has a number, this may be used be the ``outside`` application # using this simulator self.num = num # Node that actually simulates this register self.simNode = node
[docs] @abc.abstractmethod def add_fresh_qubit(self): """ Add a new qubit initialized in the \|0\> state. :return: The qubit number :rtype: int """ pass
[docs] @abc.abstractmethod def add_qubit(self, newQubit): """ Add new qubit in the state described by the density matrix newQubit :return: The qubit number :rtype: int """ pass
[docs] @abc.abstractmethod def remove_qubit(self, qubitNum): """ Removes the qubit with the desired number qubitNum :rtype: None """ pass
[docs] @abc.abstractmethod def get_register_RI(self): """ Retrieves the entire register in real and imaginary parts and returns the result as a list. Twisted only likes to send real valued lists, not complex ones. :return: The real and imaginary parts of a qubit state :rtype: tuple """ pass
[docs] @abc.abstractmethod def apply_H(self, qubitNum): """ Applies a Hadamard gate to the qubits with number qubitNum. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_K(self, qubitNum): """ Applies a K gate to the qubits with number qubitNum. Maps computational basis to Y eigenbasis. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_X(self, qubitNum): """ Applies a X gate to the qubits with number qubitNum. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_Z(self, qubitNum): """ Applies a Z gate to the qubits with number qubitNum. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_Y(self, qubitNum): """ Applies a Y gate to the qubits with number qubitNum. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_T(self, qubitNum): """ Applies a T gate to the qubits with number qubitNum. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_rotation(self, qubitNum, n, a): """ Applies a rotation around the axis n with the angle a to qubit with number qubitNum. If n is zero a ValueError is raised. :param qubitNum: int Qubit number :param n: tuple A tuple of three numbers specifying the rotation axis, e.g n=(1,0,0) :param a: float The rotation angle in radians. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_CNOT(self, qubitNum1, qubitNum2): """ Applies the CNOT to the qubit with the numbers qubitNum1 and qubitNum2. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_CPHASE(self, qubitNum1, qubitNum2): """ Applies the CPHASE to the qubit with the numbers qubitNum1 and qubitNum2. :rtype: None """ pass
[docs] @abc.abstractmethod def apply_onequbit_gate(self, gateU, qubitNum): """ Applies a unitary gate to the specified qubit. Arguments: gateU unitary to apply as Qobj qubitNum the number of the qubit this gate is applied to :rtype: None """ pass
[docs] @abc.abstractmethod def apply_twoqubit_gate(self, gateU, qubit1, qubit2): """ Applies a unitary gate to the two specified qubits. Arguments: gateU unitary to apply as Qobj qubit1 the first qubit qubit2 the second qubit :rtype: None """ pass
[docs] @abc.abstractmethod def measure_qubit_inplace(self, qubitNum): """ Measures the desired qubit in the standard basis. This returns the classical outcome. The quantum register is in the post-measurment state corresponding to the obtained outcome. Arguments: qubitNum qubit to be measured :return: The meaurement outcome :rtype: int """ pass
[docs] @abc.abstractmethod def measure_qubit(self, qubitNum): """ Measures the desired qubit in the standard basis. This returns the classical outcome and deletes the qubit. Arguments: qubitNum qubit to be measured :return: The meaurement outcome :rtype: int """ pass
[docs] @abc.abstractmethod def replace_qubit(self, qubitNum, state): """ Replaces the qubit at position qubitNum with the one given by state. :rtype: None """ pass
[docs] @abc.abstractmethod def absorb(self, other): """ Absorb the qubits from the other engine into this one. This is done by tensoring the state at the end. :rtype: None """ pass
[docs] @abc.abstractmethod def absorb_parts(self, R, I, activeQ): """ Absorb the qubits, given in pieces Arguments: R real part of the qubit state as a list I imaginary part as a list activeQ active number of qubits :rtype: None """ pass