def test_fidelity_invalid_dim(): """Tests for invalid dim.""" rho = np.array([[1 / 2, 0, 0, 1 / 2], [0, 0, 0, 0], [0, 0, 0, 0], [1 / 2, 0, 0, 1 / 2]]) sigma = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) with np.testing.assert_raises(ValueError): fidelity(rho, sigma)
def test_fidelity_non_identical_states_2(): """Test the fidelity between two non-identical states.""" e_0, e_1 = basis(2, 0), basis(2, 1) rho = 3 / 4 * e_0 * e_0.conj().T + 1 / 4 * e_1 * e_1.conj().T sigma = 1 / 8 * e_0 * e_0.conj().T + 7 / 8 * e_1 * e_1.conj().T np.testing.assert_equal( np.isclose(fidelity(rho, sigma), 0.774, rtol=1e-03), True)
def test_sub_fidelity_lower_bound_2(): """Test sub_fidelity is lower bound on fidelity for rho and pi.""" e_0, e_1 = basis(2, 0), basis(2, 1) rho = 3 / 4 * e_0 * e_0.conj().T + 1 / 4 * e_1 * e_1.conj().T sigma = 1 / 8 * e_0 * e_0.conj().T + 7 / 8 * e_1 * e_1.conj().T res = sub_fidelity(rho, sigma) np.testing.assert_array_less(res, fidelity(rho, sigma))
def test_fidelity_default(): """Test fidelity default arguments.""" rho = np.array([[1 / 2, 0, 0, 1 / 2], [0, 0, 0, 0], [0, 0, 0, 0], [1 / 2, 0, 0, 1 / 2]]) sigma = rho res = fidelity(rho, sigma) np.testing.assert_equal(np.isclose(res, 1), True)
def test_fidelity_cvx(): """Test fidelity for cvx objects.""" rho = cvxpy.bmat([[1 / 2, 0, 0, 1 / 2], [0, 0, 0, 0], [0, 0, 0, 0], [1 / 2, 0, 0, 1 / 2]]) sigma = rho res = fidelity(rho, sigma) np.testing.assert_equal(np.isclose(res, 1), True)
def bures_distance(rho_1: np.ndarray, rho_2: np.ndarray, decimals: int = 10) -> float: r""" Compute the Bures distance of two density matrices [WikBures]_. Calculate the Bures distance between two density matrices :code:`rho_1` and :code:`rho_2` defined by: .. math:: \sqrt{2 (1 - F(\rho_1, \rho_2))}, where :math:`F(\cdot)` denotes the fidelity between :math:`\rho_1` and :math:`\rho_2`. The return is a value between :math:`0` and :math:`\sqrt{2}`,with :math:`0` corresponding to matrices: :code:`rho_1 = rho_2` and :math:`\sqrt{2}` corresponding to the case: :code:`rho_1` and :code:`rho_2` with orthogonal support. Examples ========== Consider the following Bell state .. math:: u = \frac{1}{\sqrt{2}} \left( |00 \rangle + |11 \rangle \right) \in \mathcal{X}. The corresponding density matrix of :math:`u` may be calculated by: .. math:: \rho = u u^* = \frac{1}{2} \begin{pmatrix} 1 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 \end{pmatrix} \in \text{D}(\mathcal{X}). In the event where we calculate the Bures distance between states that are identical, we should obtain the value of :math:`0`. This can be observed in :code:`toqito` as follows. >>> from toqito.state_metrics import bures_distance >>> import numpy as np >>> rho = 1 / 2 * np.array( >>> [[1, 0, 0, 1], >>> [0, 0, 0, 0], >>> [0, 0, 0, 0], >>> [1, 0, 0, 1]] >>> ) >>> sigma = rho >>> bures_distance(rho, sigma) 0 References ========== .. [WikBures] Wikipedia: Bures metric https://en.wikipedia.org/wiki/Bures_metric :param rho_1: Density operator. :param rho_2: Density operator. :param decimals: Number of decimal places to round to (default 10). :return: The Bures distance between :code:`rho_1` and :code:`rho_2`. """ # Perform some error checking. if not np.all(rho_1.shape == rho_2.shape): raise ValueError("InvalidDim: `rho_1` and `rho_2` must be matrices of the same size.") # Round fidelity to only 10 decimals to avoid error when :code:`rho_1 = rho_2`. return np.sqrt(2.0 * (1.0 - np.round(fidelity(rho_1, rho_2), decimals)))
def graph(nbPlayers, sym, delta=0.01, start=0, end=2, seeSawRepeatLow=10, seeSawRepeatHigh=3, treshold=0.4, dimension=2): operatorsP1 = [0, 1, 2] operatorsP2 = [0, 3, 4] operatorsP3 = [0, 5, 6] operatorsP4 = [0, 7, 8] operatorsP5 = [0, 9, 10] P3 = [operatorsP1, operatorsP2, operatorsP3] P5 = [operatorsP1, operatorsP2, operatorsP3, operatorsP4, operatorsP5] if nbPlayers == 5: P = P5 else: P = P3 points = int(np.round((end - start) / delta)) + 1 x = np.linspace(start, end, points) paramV0 = cp.Parameter() v1 = 2 - paramV0 game = Game(nbPlayers, paramV0, v1, sym) prob = Hierarchie(game, P) print("GraphState & deviated strat & classical strat") QSW_GraphState = [] SW_classical = [] # QSW_dev = [] xGraphState = [] xClassical = [] # xDev = [] for idx, v0 in enumerate(x): print("iteration {}".format(idx)) game.v0.value = v0 SWGraph = quantumStrategies.graphStateStrategy(game) if SWGraph is not None: QSW_GraphState.append(SWGraph) xGraphState.append(game.v0.value) SW_classical.append(bestClassicalStrategy(game)) print(bestClassicalStrategy(game)) xClassical.append(game.v0.value) # # QSW for deviated strat # if quantumStrategies.devStratIsNashEq(game): # dev = quantumStrategies.QSW(game, quantumStrategies.optimalTheta(game)) # xDev.append(v0) # QSW_dev.append(dev) # try: # QSW_NotNash = readFile('data/{}Players_{}Points_Sym{}_HierarchieNoNash.txt'.format(nbPlayers, points, sym)) # print("Chargement hierarchie sans contrainte de Nash") # except: # print("Hierarchie Sans contrainte de Nash") # QSW_NotNash = [] # for idx, v0 in enumerate(x): # print("iteration {}".format(idx)) # paramV0.value = v0 # qsw = prob.optimize(verbose=False, warmStart=True, solver="MOSEK") # QSW_NotNash.append(qsw) # with open('data/{}Players_{}Points_Sym{}_HierarchieNoNash.txt'.format(nbPlayers, points, sym), 'w') as f: # for item in QSW_NotNash: # f.write("%s\n" % item) try: QSW_Nash = readFile( 'data/{}Players_{}Points_Sym{}_HierarchieNash.txt'.format( nbPlayers, points, sym)) print("Chargement hierarchie avec contrainte de Nash") except: print("Hierarchie avec contrainte de Nash") QSW_Nash = [] prob.setNashEqConstraints() for idx, v0 in enumerate(x): print("iteration {}".format(idx)) paramV0.value = v0 qsw = prob.optimize(verbose=False, warmStart=True, solver="MOSEK") QSW_Nash.append(qsw) with open( 'data/{}Players_{}Points_Sym{}_HierarchieNash.txt'.format( nbPlayers, points, sym), 'w') as f: for item in QSW_Nash: f.write("%s\n" % item) try: QSW_SeeSaw = readFile( 'data/{}Players_{}Points_Sym{}_SeeSaw.txt'.format( nbPlayers, points, sym)) Winrate_SeeSaw = readFile( 'data/{}Players_{}Points_Sym{}_SeeSaw_Winrate.txt'.format( nbPlayers, points, sym)) print("Chargement SeeSaw") except: print("SeeSaw") graphStateMatrix = graphState(nbPlayers) game = Game(nbPlayers, 0, 0, sym) lastGraphStateInit = (graphStatePOVMS(nbPlayers), graphStateMatrix) lastInit = (graphStatePOVMS(nbPlayers), graphStateMatrix) QSW_SeeSaw = [] Winrate_SeeSaw = [] #If one of them exist, we remove the file. if os.path.exists('data/{}Players_{}Points_Sym{}_SeeSaw.txt'.format( nbPlayers, points, sym)): os.remove('data/{}Players_{}Points_Sym{}_SeeSaw.txt'.format( nbPlayers, points, sym)) if os.path.exists( 'data/{}Players_{}Points_Sym{}_SeeSaw_Winrate.txt'.format( nbPlayers, points, sym)): os.remove( 'data/{}Players_{}Points_Sym{}_SeeSaw_Winrate.txt'.format( nbPlayers, points, sym)) prevMax = 1 for it, v0 in enumerate(reversed(x)): game.v0 = v0 game.v1 = 2 - v0 print("\nGlobal Iteration {} v0 {}".format(it, v0)) maxQsw = 0 nbRepeat = seeSawRepeatLow * (v0 < treshold) + seeSawRepeatHigh * ( v0 >= treshold) #On pourrait couper si on est proche de la borne de la hierarchie for r in range(nbRepeat): print("nbRepeat {}".format(r)) if r == 0: # Following strat with POVMs near graphstate ones qsw, seeSaw = fullSeeSaw(game, dimension=dimension, init=lastGraphStateInit) lastGraphStateInit = (seeSaw.POVM_Dict, seeSaw.genRho()) if r == 1: #Takes best init for last value of v0 qsw, seeSaw = fullSeeSaw(game, dimension=dimension, init=lastInit) if r == 2: initClassical = (classicalStratPOVM(game), genRhoClassic(game.nbPlayers)) qsw, seeSaw = fullSeeSaw(game, dimension=dimension, init=initClassical) else: #Random init init = (seeSaw.genPOVMs(), seeSaw.genRho()) qsw, seeSaw = fullSeeSaw(game, dimension=dimension, init=init) maxQsw = max(maxQsw, qsw) ###UNCOMMENT TO HAVE RANDOM INIT. #First repetition take best POVMs for last V0 value. After it takes random POVMs. # If it's the best result we encoutered yet for this v0's value, we save the strategy. if maxQsw == qsw: bestSeeSaw = seeSaw maxDiff = abs(prevMax - maxQsw) # If huge diff, we do another cyle on a strategy which as already been optimized. # Otherwise we have "holes" where the qsw collapse when we shift of strategy class # (i.e when we go from quantum strat to classicals) iter = 0 while maxDiff >= 0.05 and v0 != 0 and iter <= 1: print("another cycle") # #Best of last iteration if iter == 0: init = (bestSeeSaw.genPOVMs(), seeSaw.genRho()) qsw, seeSaw = fullSeeSaw(game, dimension=dimension, init=init) # # #GraphState povms if iter == 1: qsw, seeSaw = fullSeeSaw(game, dimension=dimension, init=lastGraphStateInit) # # else: # init = (seeSaw.genPOVMs(), seeSaw.genRho()) # qsw, seeSaw = fullSeeSaw(nbPlayers, v0, v1, init=init, sym=sym) # init = (seeSaw.POVM_Dict, seeSaw.genRho()) # qsw, seeSaw = fullSeeSaw(nbPlayers, v0, v1, init=init, sym=sym) # # maxQsw = max(maxQsw, qsw) if maxQsw == qsw: bestSeeSaw = seeSaw maxDiff = abs(prevMax - maxQsw) # iter += 1 # prevMax = maxQsw QSW_SeeSaw.append(maxQsw) Winrate_SeeSaw.append(bestSeeSaw.winrate) lastInit = ( bestSeeSaw.POVM_Dict, seeSaw.genRho() ) #If we keep old rho, we often (always ?) stay on the same equilibrium. printPOVMS(bestSeeSaw) print("Rho:") print(bestSeeSaw.rho) print("Trace of rho squared:", np.trace(np.dot(bestSeeSaw.rho, bestSeeSaw.rho))) print("Fidelity with graphState", fidelity(bestSeeSaw.rho, graphStateMatrix)) with open( 'data/{}Players_{}Points_Sym{}_SeeSaw.txt'.format( nbPlayers, points, sym), 'w') as f: for item in QSW_SeeSaw: f.write("%s\n" % item) with open( 'data/{}Players_{}Points_Sym{}_SeeSaw_Winrate.txt'.format( nbPlayers, points, sym), 'w') as f: for item in Winrate_SeeSaw: f.write("%s\n" % item) fig, axs = plt.subplots(1, constrained_layout=True, figsize=(10, 10)) fig.suptitle("Graph for {} players with {} points, sym: {}".format( nbPlayers, points, sym)) axs.plot([v / 2 for v in xGraphState], QSW_GraphState, label="GraphState") axs.plot(x / 2, QSW_Nash, label="HierarchieNash") # axs.plot(x/2, QSW_NotNash, label="HierarchieNotNash") axs.plot(x / 2, list(reversed(QSW_SeeSaw)), label="SeeSaw") # axs.plot(x, list(reversed(Winrate_SeeSaw)), label="Winrate Seesaw") axs.plot([v / 2 for v in xClassical], SW_classical, label="SW best classical strat") # axs.plot([v/2 for v in xDev], QSW_dev, label="SW of deviated strat") axs.set_title("Quantum social welfare") axs.set_xlabel("v0/(v0+v1)") axs.set_ylabel("QSW") axs.set_ylim([0, 2]) axs.legend(loc="upper right") plt.show()