Source code for SimulaQron.virtNode.quantum

#
# 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.

from SimulaQron.virtNode.crudeSimulator import simpleEngine
from twisted.spread import pb
from twisted.internet.defer import *

import logging

[docs]class simulatedQubit(pb.Referenceable): """ Simulated qubit object in the specified local simulation engine. - **Arguments** :node: network node that this qubit lives at :register: register on that node that the qubit is in .. note:: Qubit objects are local to each node that is simulating a particular quantum register. A qubit object provides the backing for a virtual qubit, which may be at another node. """ def __init__(self, node, register, simNum, num = 0): # Node where this qubit is located self.node = node # Register where this qubit is simulated self.register = register # Number in the register, if known self.num = num # Number of the simulated qubit, unique at each virtual node self.simNum = simNum # Lock marshalling access to this qubit self._lock = DeferredLock() # Mark this qubit as active (still connected to a register) self.active = True
[docs] def lock(self): self._lock.acquire()
[docs] def remote_lock(self): self._lock.acquire()
[docs] def unlock(self): self._lock.release()
[docs] def remote_unlock(self): self._lock.release()
[docs] def isLocked(self): return self._lock.locked
[docs] def remote_isActive(self): return self.active
[docs] def make_fresh(self): """ Make this a fresh qubit. """ # Create a fresh qubit in the |0> state num = self.register.add_fresh_qubit() self.num = num logging.debug("QUANTUM %s: Adding qubit number %d to register %d",self.node.name, num,self.register.num)
[docs] def remote_apply_X(self): """ Apply X gate to itself by passing it onto the underlying register. """ logging.debug("VIRTUAL NODE %s: applying X to number %d",self.node.name, self.num) self.register.apply_X(self.num)
[docs] def remote_apply_K(self): """ Apply K gate to itself by passing it onto the underlying register. Maps computational to Y eigenbasis. """ logging.debug("VIRTUAL NODE %s: applying K to number %d",self.node.name, self.num) self.register.apply_K(self.num)
[docs] def remote_apply_Y(self): """ Apply Y gate. """ logging.debug("VIRTUAL NODE %s: applying Y to number %d",self.node.name, self.num) self.register.apply_Y(self.num)
[docs] def remote_apply_Z(self): """ Apply Z gate. """ logging.debug("VIRTUAL NODE %s: applying Z to number %d",self.node.name, self.num) self.register.apply_Z(self.num)
[docs] def remote_apply_H(self): """ Apply H gate. """ logging.debug("VIRTUAL NODE %s: applying H to number %d",self.node.name, self.num) self.register.apply_H(self.num)
[docs] def remote_apply_T(self): """ Apply T gate. """ logging.debug("VIRTUAL NODE %s: applying T to number %d",self.node.name, self.num) self.register.apply_T(self.num)
[docs] def remote_apply_rotation(self,*args): """ Apply rotation around axis n with angle a. Arguments: n A tuple of three numbers specifying the rotation axis, e.g n=(1,0,0) a The rotation angle in radians. """ n=args[0] a=args[1] logging.debug("VIRTUAL NODE %s: applying rotation to number %d. Axis=%s,angle=%s",self.node.name, self.num,str(tuple(n)),str(a)) self.register.apply_rotation(self.num,n,a)
[docs] def remote_measure_inplace(self): """ Measure the qubit in the standard basis. This does NOT delete the qubit, but replace the relevant qubit with the measurement outcome. Returns the measurement outcome. """ outcome = self.register.measure_qubit_inplace(self.num) return outcome
[docs] def remote_measure(self): """ Measure the qubit in the standard basis. This does delete the qubit. Returns the measurement outcome. """ # Measure the qubit outcome = self.register.measure_qubit(self.num) return outcome
[docs] def remote_cnot_onto(self, targetNum): """ Performs a CNOT operation with this qubit as control, and the other qubit as target. Arguments targetNum the qubit to use as the target of the CNOT """ logging.debug("VIRTUAL NODE %s: CNOT from %d to %d", self.node.name, self.num, targetNum) self.register.apply_CNOT(self.num, targetNum)
[docs] def remote_cphase_onto(self, targetNum): """ Performs a CPHASE operation with this qubit as control, and the other qubit as target. Arguments targetNum the qubit to use as the target of the CPHASE """ self.register.apply_CPHASE(self.num, targetNum)
[docs] def remote_get_sim_number(self): """ Returns the simulation number of this qubit. """ return self.simNum
[docs] def remote_get_number(self): """ Returns the local number of this qubit. """ return self.num
[docs] def remote_get_register(self): """ Returns the register where this qubit is simulated. """ return self.register
[docs] def remote_get_numbers(self): """ Returns the number of the simulating register. """ return (self.num, self.register.num)
[docs] def remote_get_qubit(self): """ Returns the state of the qubits in the list qList by tracing out the rest. """ logging.debug("VIRTUAL NODE %s: Returning qubit %d", self.node.name, self.num) return self.register.get_qubits_RI([self.num])
[docs] def remote_get_details(self): """ Returns out simulation number as well as the details of this simulating node. """ return (self.simNum, self.node.name)