def nextMatrix(matrix, step, a, b, nRows): module = QuantumMath.vectorModule([a, b]) if step[0] == step[1]: #diagonal matrix[step[0], step[0]] = 1 matrix[nRows - 1, nRows - 1] *= -QuantumMath.conjugate(a) return matrix else: #! mejorar para no hacer la multiplicacion newMatrix = np.eye(nRows, dtype=complex) newMatrix[step[0], step[0]] = a / module newMatrix[step[1], step[1]] = -QuantumMath.conjugate(a) / module newMatrix[step[0], step[1]] = b / module newMatrix[step[1], step[0]] = QuantumMath.conjugate(b) / module #print (newMatrix) return np.dot(newMatrix, matrix)
def generateRowReversePath(target1, target2, dic): nQubits = dic.getNQubits() if target1 == target2: #identity matrix basicId = AQP.generateBasic(standarGate=StandarGate.I, targets=[0], dic=dic) return [basicId] #convert targets to binary targetList1 = QuantumMath.toBinary(2**nQubits - target1 - 1, nQubits) targetList2 = QuantumMath.toBinary(2**nQubits - target2 - 1, nQubits) allsources = [] for i in range(nQubits): allsources.append(i) idList = [] for i in range(nQubits): if targetList1[i] == targetList2[i]: continue # create X gate to set all to 1 targets = [] sources = [] for j in range(nQubits): if i == j: continue if targetList1[j] == 1: targets.append(j) sources.append(j) setTrueId = AQP.generateBasic(standarGate=StandarGate.X, targets=targets, dic=dic) # create toffoli toffoliId = AQP.generateToffoli(sources=sources, target=i, dic=dic) idList.append([setTrueId, toffoliId, setTrueId]) targetList1[i] = targetList2[i] # generate the last path concatenating all path = [] for i in idList: path += i for i in reversed(idList[:-1]): path += i return path
def __init__(self, id, matrix, nQubits, path, targets): Special.__init__(self, id=id, matrix=matrix, nQubits=nQubits, path=path, name="Oracle" + str(nQubits) + "_" + str(QuantumMath.codingQubits(targets))) self.targets = QuantumMath.codingQubits(targets)
def generateGate(index, nQubits, dic): Debug.debug(str(index) + " ; " + str(nQubits), DebugLevel.Function) array = [] for i in range(nQubits): array.append(i) if index == 0: return AQP.generateBasic(standarGate=StandarGate.X, targets=array, dic=dic) elif index == 1: return AQP.generateXnot(source=0, target=nQubits - 1, dic=dic) elif index == 2: return AQP.generateBasicTurn(target=nQubits - 1, angle=math.pi / 2, turnType=TurnType.X, dic=dic) elif index == 3: return AQP.generateCondTurn(turnType=TurnType.X, target=nQubits - 1, source=nQubits - 2, angle=math.pi / 2, dic=dic) elif index == 4: return AQP.generateMultipleTurn(turnType=TurnType.X, target=nQubits - 1, sources=array[:-1], angle=math.pi / 2, dic=dic) elif index == 5: return AQP.generateToffoli(target=nQubits - 1, sources=array[:-1], dic=dic) elif index == 6: return AQP.generateSpecialTurn(a=1j, b=-1, dic=dic) elif index == 7: return AQP.generateRowReverse(target1=1, target2=2**nQubits - 2, dic=dic) elif index == 8: matrix = QuantumMath.getOracleMatrix( nQubits=nQubits, targets=[0, nQubits, 2**nQubits - 1]) return (AQP.generateSpecial(name="oracle", matrix=matrix, dic=dic), matrix) elif index == 9: matrix = QuantumMath.getAmplitudAmplifier(nQubits=nQubits) return (AQP.generateSpecial(name="aa", matrix=matrix, dic=dic), matrix)
def generateSpecialTurnPath(a, b, dic): module = QuantumMath.vectorModule([a, b]) # normalizing parameters a /= module b /= module # calculating theta x and y theta = math.asin(QuantumMath.complexModule(b)) y = cmath.phase(b) x = cmath.phase(a) lastQubit = dic.getNQubits() - 1 sourceQubits = [] for i in range(lastQubit): sourceQubits.append(i) firstGateId = AQP.generateMultipleTurn(turnType=TurnType.Z, target=lastQubit, sources=sourceQubits, angle=(-y + x + math.pi), dic=dic) secondGateId = AQP.generateMultipleTurn(turnType=TurnType.X, target=lastQubit, sources=sourceQubits, angle=theta * 2, dic=dic) thirdGateId = AQP.generateMultipleTurn(turnType=TurnType.Z, target=lastQubit, sources=sourceQubits, angle=(y + x), dic=dic) lastCondId = AQP.generateMultipleTurn( turnType=TurnType.Z, target=lastQubit, sources=sourceQubits, angle=QuantumMath.inverseAngle(x), dic=dic) # is the same with Toffoli or last qubit X #allToffoliId = AQP.generateToffoli(target=lastQubit, sources=sourceQubits, dic=dic) allToffoliId = AQP.generateBasic(standarGate=StandarGate.X, targets=[lastQubit], dic=dic) return [ firstGateId, secondGateId, thirdGateId, lastCondId, allToffoliId, lastCondId, allToffoliId ]
def generateBasicMatrix(standarGate, targets, nQubits): matrixIdentity = QuantumMath.getStdMatrix("I") matrixGate = QuantumMath.getStdMatrix(standarGate.name) matrixList = [] for i in range(nQubits): if i in targets: matrixList.append(matrixGate) else: matrixList.append(matrixIdentity) return QuantumMath.tensorDot(matrixList)
def generateBasicTurnMatrix(target, angle, turnType, nQubits): matrixIdentity = QuantumMath.getStdMatrix("I") matrixGate = QuantumMath.getStdTurnMatrix(turnType, angle) matrixList = [] for i in range(nQubits): if i == target: matrixList.append(matrixGate) else: matrixList.append(matrixIdentity) return QuantumMath.tensorDot(matrixList)
def generateCondTurnPath(turnType, target, source, angle, dic): # xnot xnotId = AQP.generateXnot(source=source, target=target, dic=dic) # turn inverseTurnId = AQP.generateBasicTurn(target=target, angle=QuantumMath.inverseAngle( angle / 2), turnType=turnType, dic=dic) turnId = AQP.generateBasicTurn(target=target, angle=angle / 2, turnType=turnType, dic=dic) # with Z turn it need a recalculation if turnType == TurnType.Z: turnIdSource = AQP.generateBasicTurn(target=source, angle=angle / 2, turnType=turnType, dic=dic) return [xnotId, inverseTurnId, xnotId, turnId, turnIdSource] else: #return [xnotId, inverseTurnId, xnotId, turnId] return [turnId, xnotId, inverseTurnId, xnotId]
def __init__(self, id, matrix, nQubits, path, target, sources): Conditional.__init__(self, id=id, matrix=matrix, path=path, target=target, nQubits=nQubits) self.sourcesCode = QuantumMath.codingQubits(sources)
def generateMatrixFromPath(path, dic): matrixList = [] for i in path: matrixList.append(dic.getGate(i).getMatrix()) matrixList.reverse() return QuantumMath.matrixDot(matrixList)
def getStringTypedPerQubit(self): l = [] targets = QuantumMath.decodingQubits(self.targetsCode) for i in range(self.nQubits): if i in targets: l.append((QubitStringType.Target, self.standarGate.name)) else: l.append((QubitStringType.Empty, "")) return (len(self.standarGate.name), l)
def getStringTypedPerQubit(self): l = [] sources = QuantumMath.decodingQubits(self.sourcesCode) for i in range(self.nQubits): if i in sources: l.append((QubitStringType.Source, "")) else: l.append((QubitStringType.Empty, "")) l[self.target] = (QubitStringType.Target, "(X)") return (3, l)
def getStringTypedPerQubit(self): l = [] st = printTurn(self.turnType, self.angle) sources = QuantumMath.decodingQubits(self.sourcesCode) for i in range(self.nQubits): if i in sources: l.append((QubitStringType.Source, "")) else: l.append((QubitStringType.Empty, "")) l[self.target] = (QubitStringType.Target, st) return (len(st), l)
def getAsm(self, compress=False): stCom = Assembler.comment("Std Gate - " + self.standarGate.name + " targets: " + str(self.targetsCode)) st = "" for i in QuantumMath.decodingQubits(self.targetsCode): st += Assembler.writeStdGate(standarGate=self.standarGate, target=i, nQubits=self.nQubits) if compress: return st else: return stCom + st + stCom + "\n"
def generateGate(index, rowReverse, nQubits, dic): Debug.debug(str(index) + " ; " + str(nQubits), DebugLevel.Function) if rowReverse: return AQP.generateRowReverse(target1=0, target2=index, dic=dic) else: matrix = QuantumMath.getOracleMatrix(nQubits=nQubits, targets=[]) #generate a diagonal matrix matrix[0,0] = 1/math.sqrt(2) matrix[0,index] = 1/math.sqrt(2) matrix[index,0] = 1/math.sqrt(2) matrix[index,index] = -1/math.sqrt(2) return AQP.generateSpecial(name="2superpoitionGate", matrix=matrix, dic=dic)
def generateXnotMatrix(source, target, nQubits): array = [] o2 = 2**(nQubits - source - 1) t2 = 2**(nQubits - target - 1) q2 = 2**nQubits for i in range(q2): #buscamos los bits que nos conciernen en este caso bo = (i // o2) % 2 if bo == 1: to = (i // t2) % 2 if to == 0: n = i + t2 else: n = i - t2 else: n = i newArray = np.zeros(q2, dtype=complex) newArray[n] = 1 array.append(newArray) return QuantumMath.generateMatrixFromBasicEquations(nQubits, array)
def generateMultipleTurnPath(turnType, target, sources, angle, dic): # if there is just one source, is like a condTurn if len(sources) == 1: return [ AQP.generateCondTurn(turnType=turnType, target=target, source=sources[0], angle=angle, dic=dic) ] # if there is two sources the implementation in automatic elif len(sources) == 2: nAngle = angle / 2 # conditional turn condTurnId = AQP.generateCondTurn(turnType=turnType, target=target, source=sources[1], angle=nAngle, dic=dic) # xnot xnotId = AQP.generateXnot(source=sources[0], target=sources[1], dic=dic) # conditional turn inverse condTurnInvId = AQP.generateCondTurn( turnType=turnType, target=target, source=sources[1], angle=QuantumMath.inverseAngle(nAngle), dic=dic) # conditional turn from above condTurnAboveId = AQP.generateCondTurn(turnType=turnType, target=target, source=sources[0], angle=nAngle, dic=dic) #added to path return [condTurnId, xnotId, condTurnInvId, xnotId, condTurnAboveId] else: nAngle = angle / 2 path = [] # multiple n-1 sources multipleId = AQP.generateMultipleTurn(turnType=turnType, target=target, sources=sources[1:], angle=nAngle, dic=dic) path.append(multipleId) # create xnot to every qubit source from first source pathXnot = [] for qubitAux in sources[1:]: # xnot xnotId = AQP.generateXnot(source=sources[0], target=qubitAux, dic=dic) #added to path pathXnot.append(xnotId) path += pathXnot # multiple n-1 sources multipleInvId = AQP.generateMultipleTurn( turnType=turnType, target=target, sources=sources[1:], angle=QuantumMath.inverseAngle(nAngle), dic=dic) path.append(multipleInvId) # redo xnots path += pathXnot # negate last qubit negateId = AQP.generateBasic(standarGate=StandarGate.X, targets=[sources[-1]], dic=dic) path.append(negateId) # x not from last qubit pathInverseXnot = [] for qubitAux in sources[1:-1]: # xnot xnotId = AQP.generateXnot(source=sources[-1], target=qubitAux, dic=dic) #added to path pathInverseXnot.append(xnotId) path += pathInverseXnot # create the new multi conditional multiLowId = AQP.generateMultipleTurn(turnType=turnType, target=target, sources=sources[:-1], angle=nAngle, dic=dic) path.append(multiLowId) # redo the negation path += pathInverseXnot path.append(negateId) return path
def getIdBasic(self, standarGate, targets): return self.getId( GateType.Basic, [standarGate, QuantumMath.codingQubits(targets)])
def addIdToffoli(self, gate, target, sources): return self.addGate(gate, GateType.Toffoli, [target, QuantumMath.codingQubits(sources)])
def addIdMultipleTurn(self, gate, turnType, target, sources, angle): return self.addGate( gate, GateType.MultipleTurn, [turnType, target, QuantumMath.codingQubits(sources), angle])
def addIdBasic(self, gate, standarGate, targets): return self.addGate( gate, GateType.Basic, [standarGate, QuantumMath.codingQubits(targets)])
def getIdMultipleTurn(self, turnType, target, sources, angle): return self.getId( GateType.MultipleTurn, [turnType, target, QuantumMath.codingQubits(sources), angle])
def generateSpecialPath(name, matrix, dic): nRows = 2**dic.getNQubits() step = AQP.getNextStep(matrix=matrix, step=[-1, -1], nRows=nRows) lastRow = nRows - 1 penLastRow = nRows - 2 idPath = [] while (step): #print(matrix) #print(step) a = 0 b = 0 if step[0] == step[1]: #diagonal if step[0] == penLastRow: #last special turn # create the special turn matrix with the conjugate values a = QuantumMath.conjugate(matrix[step[0], step[0]]) specialTurnId = AQP.generateSpecialTurn(a=a, b=0, dic=dic) #added to path idPath = [specialTurnId] + idPath else: rowRevertPenLastId = AQP.generateRowReverse( target1=step[0], target2=penLastRow, dic=dic) # create the special turn matrix with the conjugate values a = QuantumMath.conjugate(matrix[step[0], step[0]]) specialTurnId = AQP.generateSpecialTurn(a=a, b=0, dic=dic) #added to path idPath = [ rowRevertPenLastId, specialTurnId, rowRevertPenLastId ] + idPath else: # create the row reversion rowRevertPenLastId = AQP.generateRowReverse(target1=step[0], target2=penLastRow, dic=dic) rowRevertLastId = AQP.generateRowReverse(target1=step[1], target2=lastRow, dic=dic) # create the special turn matrix with the conjugate values a = QuantumMath.conjugate(matrix[step[0], step[0]]) b = QuantumMath.conjugate(matrix[step[1], step[0]]) specialTurnId = AQP.generateSpecialTurn(a=a, b=b, dic=dic) #! IS IMPORTANT THE ORDEN OF THE REVERSER #added to path idPath = [ rowRevertLastId, rowRevertPenLastId, specialTurnId, rowRevertPenLastId, rowRevertLastId ] + idPath matrix = AQP.nextMatrix(matrix=matrix, step=step, a=a, b=b, nRows=nRows) #print(matrix) #print("\n\n") step = AQP.getNextStep(matrix=matrix, step=step, nRows=nRows) # Last binary matrix should be a Z #get phase for last value phase = QuantumMath.getPhase(matrix[nRows - 1, nRows - 1]) if phase != 0: sources = [] for i in range(dic.getNQubits() - 1): sources.append(i) # added last turn Z turnId = AQP.generateMultipleTurn(turnType=TurnType.Z, target=dic.getNQubits() - 1, sources=sources, angle=phase, dic=dic) idPath = [turnId] + idPath return idPath
def printTurn(turnType, angle, decimals=2): return turnType.name + str(QuantumMath.round(angle, decimals))
def getIdToffoli(self, target, sources): return self.getId(GateType.Toffoli, [target, QuantumMath.codingQubits(sources)])
def __init__(self, id, matrix, nQubits, standarGate, targets): Standar.__init__(self, id=id, matrix=matrix, nQubits=nQubits) self.standarGate = standarGate self.targetsCode = QuantumMath.codingQubits(targets)
def addIdOracle(self, gate, targets): return self.addGate(gate, GateType.Oracle, QuantumMath.codingQubits(targets))
def getIdOracle(self, targets): return self.getId(GateType.Oracle, QuantumMath.codingQubits(targets))