Ejemplo n.º 1
0
def Demo():

    #__SUPPLY_CHAIN_NETWORK__###################################################
    N = 10  # number of possible maps
    T = 1000  # number of time steps
    eta = .01  # learning rate

    # Define Domains and Compute Equilbria
    Domains = []
    X_Stars = []
    CurlBounds = []
    for n in range(N):
        # Create Domain
        Network = CreateRandomNetwork(I=3, Nm=2, Nd=2, Nr=1, seed=n)
        Domain = SupplyChain(Network=Network, alpha=2)

        # Record Domain
        Domains += [Domain]

        # Set Method
        Method = HeunEuler(Domain=Domain, P=BoxProjection(lo=0), Delta0=1e-3)

        # Initialize Starting Point
        Start = np.zeros(Domain.Dim)

        # Calculate Initial Gap
        gap_0 = Domain.gap_rplus(Start)

        # Calculate Curl Bound
        J = approx_jacobian(Domain.F, Start)
        _J = approx_jacobian(Domain.F, Start + 0.5)
        assert np.allclose(J, _J, atol=1e-5)
        CurlBounds += [
            np.sqrt(18) *
            svds(J, k=1, which='LM', return_singular_vectors=False).item()
        ]

        # Set Options
        Init = Initialization(Step=-1e-10)
        Term = Termination(MaxIter=25000,
                           Tols=[(Domain.gap_rplus, 1e-3 * gap_0)])
        Repo = Reporting(Requests=[Domain.gap_rplus])
        Misc = Miscellaneous()
        Options = DescentOptions(Init, Term, Repo, Misc)

        # Print Stats
        PrintSimStats(Domain, Method, Options)

        # Start Solver
        tic = time.time()
        SupplyChain_Results = Solve(Start, Method, Domain, Options)
        toc = time.time() - tic

        # Print Results
        PrintSimResults(Options, SupplyChain_Results, Method, toc)

        # Record X_Star
        X_Star = SupplyChain_Results.TempStorage['Data'][-1]
        X_Stars += [X_Star]
    X_Stars = np.asarray(X_Stars)

    # Compute Equilibrium of Average Domain
    Domain = AverageDomains(Domains)

    # Set Method
    Method = HeunEuler(Domain=Domain, P=BoxProjection(lo=0), Delta0=1e-3)

    # Initialize Starting Point
    Start = np.zeros(Domain.Dim)

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=25000, Tols=[(Domain.gap_rplus, 1e-3 * gap_0)])
    Repo = Reporting(Requests=[Domain.gap_rplus])
    Misc = Miscellaneous()
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Print Stats
    PrintSimStats(Domain, Method, Options)

    # Start Solver
    tic = time.time()
    SupplyChain_Results = Solve(Start, Method, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, SupplyChain_Results, Method, toc)

    # Record X_Opt
    # X_Opt = SupplyChain_Results.TempStorage['Data'][-1]
    X_Opt = np.mean(X_Stars, axis=0)

    print('Starting Online Learning')

    # Set First Prediction
    X = np.zeros(X_Stars.shape[1])

    # Select First Domain
    # idx = np.argmax(np.linalg.norm(X_Stars - X,axis=1))
    idx = 0

    distances = []
    loss_infs = []
    regret_standards = []
    regret_news = []
    stokes = []
    ts = range(T)
    for t in ts:
        print('t = ' + str(t))
        # retrieve domain
        Domain = Domains[idx]
        # retrieve equilibrium / reference vector
        equi = X_Stars[idx]
        # calculate distance
        distances += [np.linalg.norm(equi - X)]
        # calculate infinity loss
        loss_infs += [infinity_loss(Domain, X)]
        # calculate standard regret
        ci_predict = ContourIntegral(Domain, LineContour(equi, X))
        predict_loss = integral(ci_predict)
        ci_opt = ContourIntegral(Domain, LineContour(equi, X_Opt))
        predict_opt = integral(ci_opt)
        regret_standards += [predict_loss - predict_opt]
        # calculate new regret
        ci_new = ContourIntegral(Domain, LineContour(X_Opt, X))
        regret_news += [integral(ci_new)]
        # calculate bound
        # area = 0.5*np.prod(np.sort([np.linalg.norm(X_Opt-equi),np.linalg.norm(X-X_Opt),np.linalg.norm(equi-X)])[:2])  # area upper bound
        area = herons(X_Opt, X, equi)  # exact area
        stokes += [CurlBounds[idx] * area]
        # update prediction
        X = BoxProjection(lo=0).P(X, -eta, Domain.F(X))
        # update domain
        # idx = np.argmax(np.linalg.norm(X_Stars - X,axis=1))
        idx = (idx + 1) % X_Stars.shape[0]

    ts_p1 = range(1, T + 1)
    distances_avg = np.divide(distances, ts_p1)
    loss_infs_avg = np.divide(loss_infs, ts_p1)
    regret_standards_avg = np.divide(regret_standards, ts_p1)
    regret_news_avg = np.divide(regret_news, ts_p1)
    stokes = np.asarray(stokes)

    np.savez_compressed('NoRegret_SCN.npz',
                        d_avg=distances_avg,
                        linf_avg=loss_infs_avg,
                        rs_avg=regret_standards_avg,
                        rn_avg=regret_news_avg,
                        stokes=stokes)

    # plt.subplot(2, 1, 1)
    # plt.plot(ts, distances_avg, 'k',label='Average Distance')
    # plt.title('Demonstration of No-Regret on MLN')
    # plt.ylabel('Euclidean Distance')
    # plt.legend()

    plt.subplot(1, 1, 1)
    plt.plot(ts, loss_infs_avg, 'k--', label=r'loss$_{\infty}$')
    plt.plot(ts,
             regret_standards_avg,
             'r--o',
             markevery=T // 20,
             label=r'regret$_{s}$')
    plt.plot(ts, regret_news_avg, 'b-', label=r'regret$_{n}$')
    ax.fill_between(ts,
                    regret_news_avg - stokes,
                    regret_news_avg + stokes,
                    facecolor='c',
                    alpha=0.2,
                    zorder=0,
                    label='Stokes Bound')
    plt.plot(ts, np.zeros_like(ts), 'w-', lw=1)
    plt.xlabel('Time Step')
    plt.ylabel('Aggregate System-Wide Loss')
    plt.xlim([0, T])
    plt.ylim([-250, 1000])
    plt.legend()
    plt.title('Demonstration of No-Regret on Supply Chain Network')

    plt.savefig('NoRegret_SCN')
def Demo():

    #__SPHERE__##################################################

    # Define Dimension and Domain
    Domain = MonotoneCycle()

    # Set Method
    MethodEuler = Euler(Domain=Domain, P=IdentityProjection(), FixStep=True)
    MethodEG = EG(Domain=Domain, P=IdentityProjection(), FixStep=True)

    # Set Options
    Init = Initialization(Step=-1e-1)
    Term = Termination(MaxIter=100)
    Repo = Reporting(Requests=['Data'])
    Misc = Miscellaneous()
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Initialize Starting Point
    Start = np.ones(Domain.Dim)

    # Print Stats
    PrintSimStats(Domain, MethodEuler, Options)

    # Start Solver
    tic = time.time()
    Euler_Results = Solve(Start, MethodEuler, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, Euler_Results, MethodEuler, toc)

    # Print Stats
    PrintSimStats(Domain, MethodEG, Options)

    # Start Solver
    tic = time.time()
    EG_Results = Solve(Start, MethodEG, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, EG_Results, MethodEG, toc)

    data_Euler = ListONP2NP(Euler_Results.PermStorage['Data'])
    data_EG = ListONP2NP(EG_Results.PermStorage['Data'])

    X, Y = np.meshgrid(np.arange(-2.5, 2.5, .2), np.arange(-2.5, 2.5, .2))
    U = np.zeros_like(X)
    V = np.zeros_like(Y)
    for i in range(X.shape[0]):
        for j in range(X.shape[1]):
            vec = -Domain.F([X[i, j], Y[i, j]])
            U[i, j] = vec[0]
            V[i, j] = vec[1]

    # plt.figure()
    # plt.title('Arrows scale with plot width, not view')
    # Q = plt.quiver(X, Y, U, V, units='width')
    # qk = plt.quiverkey(Q, 0.9, 0.9, 2, r'$2 \frac{m}{s}$', labelpos='E',
    #                    coordinates='figure')

    fig = plt.figure()
    # ax = fig.add_axes([0.1, 0.1, 0.6, 0.75])
    # plt.title("Extragradient vs Simultaneous Gradient Descent")
    s = 2
    Q = plt.quiver(X[::s, ::s],
                   Y[::s, ::s],
                   U[::s, ::s],
                   V[::s, ::s],
                   pivot='mid',
                   units='inches',
                   color='r')
    # vec_Euler = -Domain.F(data_Euler[-1,:])
    vec_EG = -Domain.F(data_EG[-1, :])
    # print(data_Euler[-1])
    # print(vec_Euler)
    # plt.quiver(data_Euler[-1][0], data_Euler[-1][1], vec_Euler[0], vec_Euler[1], pivot='mid', units='inches', color='b',
    #         headwidth=5)
    plt.quiver(data_EG[-1][0],
               data_EG[-1][1],
               vec_EG[0],
               vec_EG[1],
               pivot='mid',
               units='inches',
               color='r',
               headwidth=5)
    plt.scatter(X[::s, ::s], Y[::s, ::s], color='r', s=5)
    # plt.plot(data_Euler[:,0],data_Euler[:,1],'b',linewidth=5,label='Simultaneous\nGradient Descent')
    # plt.plot(data_EG[:,0],data_EG[:,1],'r',linewidth=5,label='Extragradient')
    # plt.plot([0],[0],linestyle="None",marker=(5,1,0),markersize=20,color='gold',label='Equilibrium')
    plt.axis([-2.5, 2.5, -2.5, 2.5])
    # plt.legend(loc='center left', bbox_to_anchor=(1, 0.5), borderaxespad=0.5)
    # plt.ion()
    # plt.show()
    plt.axis('off')
    plt.axis('square')
    plt.savefig('StrawberryFields.png')
Ejemplo n.º 3
0
def Demo():

    #__ONLINE_MONOTONE_EQUILIBRATION_DEMO_OF_A_SERVICE_ORIENTED_INTERNET__######

    # Define Number of Different VIs
    N = 10
    np.random.seed(0)

    # Define Initial Network and Domain
    World = np.random.randint(N)
    Worlds = [World]
    Network = CreateRandomNetwork(m=3,n=2,o=2,seed=World)
    Domain = SOI(Network=Network,alpha=2)

    # Define Initial Strategy
    Strategies = [np.zeros(Domain.Dim)]
    eta = 0.1

    for t in xrange(1000):

        #__PERFORM_SINGLE_UPDATE

        print('Time '+str(t))

        # Set Method
        Method = Euler(Domain=Domain,P=BoxProjection(lo=0))

        # Set Options
        Init = Initialization(Step=-eta)
        Term = Termination(MaxIter=1)
        Repo = Reporting(Requests=['Data'])
        Misc = Miscellaneous()
        Options = DescentOptions(Init,Term,Repo,Misc)

        # Run Update
        Result = Solve(Strategies[-1],Method,Domain,Options)

        # Get New Strategy
        Strategy = Result.PermStorage['Data'][-1]
        Strategies += [Strategy]

        #__DEFINE_NEXT_VI

        # Define Initial Network and Domain
        World = np.random.randint(N)
        Worlds += [World]
        Network = CreateRandomNetwork(m=3,n=2,o=2,seed=World)
        Domain = SOI(Network=Network,alpha=2)

    # Scrap Last Strategy / World
    Strategies = np.asarray(Strategies[:-1])
    Worlds = Worlds[:-1]

    # Store Equilibrium Strategies
    Equilibria = dict()

    for w in np.unique(Worlds):

        print('World '+str(w))

        #__FIND_EQUILIBRIUM_SOLUTION_OF_VI

        # Define Initial Network and Domain
        Network = CreateRandomNetwork(m=3,n=2,o=2,seed=w)
        Domain = SOI(Network=Network,alpha=2)

        # Set Method
        Method = HeunEuler(Domain=Domain,P=BoxProjection(lo=0),Delta0=1e-5)

        # Initialize Starting Point
        Start = np.zeros(Domain.Dim)

        # Calculate Initial Gap
        gap_0 = Domain.gap_rplus(Start)

        # Set Options
        Init = Initialization(Step=-1e-10)
        Term = Termination(MaxIter=25000,Tols=[(Domain.gap_rplus,1e-6*gap_0)])
        Repo = Reporting(Requests=[Domain.gap_rplus,'Step','Data'])
        Misc = Miscellaneous()
        Options = DescentOptions(Init,Term,Repo,Misc)

        # Print Stats
        PrintSimStats(Domain,Method,Options)

        # Start Solver
        tic = time.time()
        Results = Solve(Start,Method,Domain,Options)
        toc = time.time() - tic

        # Print Results
        PrintSimResults(Options,Results,Method,toc)

        # Get Equilibrium Strategy
        Equilibrium = Results.PermStorage['Data'][-1]
        Equilibria[w] = Equilibrium

    # Matched Equilibria & Costs
    Equilibria_Matched = np.asarray([Equilibria[w] for w in Worlds])

    # Compute Mean of Equilibria
    Mean_Equilibrium = np.mean(Equilibria_Matched,axis=0)

    # Compute Strategies Distance From Mean Equilibrium
    Distance_From_Mean = np.linalg.norm(Strategies-Mean_Equilibrium,axis=1)

    # Plot Results
    fig = plt.figure()
    ax1 = fig.add_subplot(1,1,1)
    ax1.plot(Distance_From_Mean,label='Distance from Mean')
    ax1.set_title('Online Monotone Equilibration of Dynamic SOI Network')
    ax1.legend()
    ax1.set_xlabel('Time')

    plt.savefig('OMEfast.png')

    embed()
Ejemplo n.º 4
0
def Demo():

    #__SERVICE_ORIENTED_INTERNET__##############################################
    N = 10  # number of possible maps
    T = 1000  # number of time steps
    eta = 1e-3  # learning rate

    print('Creating Domains')

    # Define Domains and Compute Equilbria
    Domains = []
    X_Stars = []
    CurlBounds = []
    n = 0
    while len(Domains) < N:
        # Create Domain
        Network = CreateRandomNetwork(m=3, n=2, o=2, seed=None)
        Domain = SOI(Network=Network, alpha=2)

        # Initialize Starting Point
        Start = np.zeros(Domain.Dim)

        # Assert PD
        J = approx_jacobian(Domain.F, Start)
        eigs = np.linalg.eigvals(J + J.T)
        eigs_i = np.abs(np.linalg.eigvals(J - J.T))
        if not np.all(eigs > 0):
            continue
        print(eigs.min(), eigs.max())
        print(eigs_i.min(), eigs_i.max())
        _J = approx_jacobian(Domain.F, Start + 0.5)
        assert np.allclose(J, _J,
                           atol=1e-5)  # assert J is constant (unique for SOI)

        # Record Domain
        Domains += [Domain]

        # Calculate Initial Gap
        gap_0 = Domain.gap_rplus(Start)

        # Calculate Curl Bound
        CurlBounds += [
            np.sqrt(18) *
            svds(J, k=1, which='LM', return_singular_vectors=False).item()
        ]

        # Set Method
        Method = HeunEuler(Domain=Domain, P=BoxProjection(lo=0), Delta0=1e-3)

        # Set Options
        Init = Initialization(Step=-1e-10)
        Term = Termination(MaxIter=25000,
                           Tols=[(Domain.gap_rplus, 1e-6 * gap_0)])
        Repo = Reporting(Requests=[Domain.gap_rplus])
        Misc = Miscellaneous()
        Options = DescentOptions(Init, Term, Repo, Misc)

        # Print Stats
        PrintSimStats(Domain, Method, Options)

        # Start Solver
        tic = time.time()
        SOI_Results = Solve(Start, Method, Domain, Options)
        toc = time.time() - tic

        # Print Results
        PrintSimResults(Options, SOI_Results, Method, toc)

        # Record X_Star
        X_Star = SOI_Results.TempStorage['Data'][-1]
        X_Stars += [X_Star]
        n += 1
    X_Stars = np.asarray(X_Stars)

    print('Starting Online Learning')

    # Set First Prediction
    X = np.zeros(X_Stars.shape[1])
    # X = np.mean(X_Stars,axis=0)
    # X += np.random.rand(*X.shape)*np.linalg.norm(X)

    # Select First Domain
    # idx = np.argmax(np.linalg.norm(X_Stars - X,axis=1))
    idx = np.random.choice(len(Domains))

    # Domain Sequence
    idx_seq = []
    X_seq = []
    F_seq = []

    ts = range(T)
    for t in ts:
        print('t = ' + str(t), end='\r')
        # record prediction
        X_seq += [X]
        # record domain
        idx_seq += [idx]
        # retrieve domain
        Domain = Domains[idx]
        # record F
        FX = Domain.F(X)
        F_seq += [FX]
        # update prediction
        X = BoxProjection(lo=0).P(X, -eta, FX)
        # update domain
        # idx = np.argmax(np.linalg.norm(X_Stars - X,axis=1))
        idx = np.random.choice(len(Domains))

    L = np.sqrt(np.mean(np.linalg.norm(F_seq, axis=1)**2.))

    print('Computing Optimal Strategy')

    weights = np.bincount(idx_seq, minlength=len(Domains)) / len(idx_seq)
    print(weights)

    # Compute Equilibrium of Average Domain
    Domain = AverageDomains(Domains, weights=weights)

    # Set Method
    Method = HeunEuler_PhaseSpace(Domain=Domain,
                                  P=BoxProjection(lo=0),
                                  Delta0=1e-5)

    # Initialize Starting Point
    Start = np.zeros(Domain.Dim)

    # Assert PSD - sum of PSD is PSD doesn't hurt to check
    J = approx_jacobian(Domain.F, Start)
    eigs = np.linalg.eigvals(J + J.T)
    eigs_i = np.abs(np.linalg.eigvals(J - J.T))
    assert np.all(eigs > 0)
    print(eigs.min(), eigs.max())
    print(eigs_i.min(), eigs_i.max())

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=25000, Tols=[(Domain.gap_rplus, 1e-10 * gap_0)])
    Repo = Reporting(Requests=[Domain.gap_rplus])
    Misc = Miscellaneous()
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Print Stats
    PrintSimStats(Domain, Method, Options)

    # Start Solver
    tic = time.time()
    SOI_Results = Solve(Start, Method, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, SOI_Results, Method, toc)

    print('Computing Regrets')

    # Record X_Opt
    X_Opt = SOI_Results.TempStorage['Data'][-1]
    # X_Opt = X_Stars[0]
    B = np.linalg.norm(X_Opt)

    eta_opt = B / (L * np.sqrt(2 * T))
    bound_opt = B * L * np.sqrt(2 * T)
    reg_bound = (B**2) / (2 * eta) + eta * T * L**2

    distances = []
    loss_infs = []
    regret_standards = []
    regret_news = []
    stokes = []
    ts = range(T)
    for t in ts:
        print('t = ' + str(t), end='\r')
        idx = idx_seq[t]
        X = X_seq[t]
        # retrieve domain
        Domain = Domains[idx]
        # retrieve equilibrium / reference vector
        equi = X_Stars[idx]
        # equi = np.zeros_like(X_Stars[idx])
        # calculate distance
        distances += [np.linalg.norm(X_Opt - X)]
        # calculate infinity loss
        # loss_infs += [infinity_loss(Domain,X)]
        # calculate standard regret
        ci_predict = ContourIntegral(Domain, LineContour(equi, X))
        predict_loss = integral(ci_predict)
        ci_opt = ContourIntegral(Domain, LineContour(equi, X_Opt))
        predict_opt = integral(ci_opt)
        regret_standards += [predict_loss - predict_opt]
        # calculate new regret
        ci_new = ContourIntegral(Domain, LineContour(X_Opt, X))
        regret_news += [integral(ci_new)]
        # calculate bound
        # area = 0.5*np.prod(np.sort([np.linalg.norm(X_Opt-equi),np.linalg.norm(X-X_Opt),np.linalg.norm(equi-X)])[:2])  # area upper bound
        area = herons(X_Opt, X, equi)  # exact area
        stokes += [CurlBounds[idx] * area]
        # # update prediction
        # X = BoxProjection(lo=0).P(X,-eta,Domain.F(X))
        # # update domain
        # idx = np.argmax(np.linalg.norm(X_Stars - X,axis=1))
    # embed()
    ts_p1 = range(1, T + 1)
    distances_avg = np.divide(np.cumsum(distances), ts_p1)
    # loss_infs_avg = np.divide(np.cumsum(loss_infs),ts_p1)
    regret_standards_avg = np.divide(np.cumsum(regret_standards), ts_p1)
    regret_news_avg = np.divide(np.cumsum(regret_news), ts_p1)
    stokes = np.divide(np.cumsum(stokes), ts_p1)

    # np.savez_compressed('NoRegret_MLN2c.npz',d_avg=distances_avg,
    #                     linf_avg=loss_infs_avg,rs_avg=regret_standards_avg,
    #                     rn_avg=regret_news_avg,stokes=stokes)

    plt.subplot(2, 1, 2)
    plt.plot(ts, distances_avg, 'k', label='Average Distance')
    # plt.title('Demonstration of No-Regret on MLN')
    plt.xlabel('Time Step')
    plt.ylabel('Euclidean Distance')
    plt.legend()

    plt.subplot(2, 1, 1)
    # plt.plot(ts, loss_infs_avg, 'k--', label=r'loss$_{\infty}$')
    plt.plot(ts,
             regret_standards_avg,
             'r--o',
             markevery=T // 20,
             label=r'regret$_{s}$')
    plt.plot(ts, regret_news_avg, 'b-', label=r'regret$_{n}$')
    # plt.fill_between(ts, regret_news_avg-stokes, regret_news_avg+stokes,
    #                  facecolor='c', alpha=0.2, zorder=0, label='Stokes Bound')
    plt.plot(ts, np.zeros_like(ts), 'w-', lw=1)
    # plt.xlabel('Time Step')
    plt.ylabel('Aggregate System-Wide Loss')
    plt.xlim([0, T])
    # plt.ylim([-200,200])
    plt.legend(loc='lower right')
    plt.title('Demonstration of No-Regret on MLN')

    plt.savefig('NoRegret_MLN2c')

    # data = np.load('NoRegret2.npz')
    # distances_avg = data['d_avg']
    # loss_infs_avg = data['linf_avg']
    # regret_standards_avg = data['rs_avg']
    # regret_news_avg = data['rn_avg']
    # stokes = data['stokes']
    # ts = range(len(distances_avg))

    embed()
Ejemplo n.º 5
0
def Demo():

    #__BLOOD_BANK__##################################################

    #############################################################
    # Phase 1 - Left hospital has relatively low demand for blood
    #############################################################

    # Define Network and Domain
    Network = CreateNetworkExample(ex=1)
    Domain = BloodBank(Network=Network, alpha=2)

    # Set Method
    Method = ABEuler(Domain=Domain, P=BoxProjection(lo=0), Delta0=1e-5)

    # Initialize Starting Point
    Start = np.zeros(Domain.Dim)

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=10000, Tols=[(Domain.gap_rplus, 1e-3 * gap_0)])
    Repo = Reporting(Requests=[
        Domain.gap_rplus, 'Step', 'F Evaluations', 'Projections', 'Data'
    ])
    Misc = Miscellaneous()
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Print Stats
    PrintSimStats(Domain, Method, Options)

    # Start Solver
    tic = time.time()
    BloodBank_Results_Phase1 = Solve(Start, Method, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, BloodBank_Results_Phase1, Method, toc)

    #########################################################
    # Phase 2 - Left hospital has comparable demand for blood
    #########################################################

    # Define Network and Domain
    Network = CreateNetworkExample(ex=2)
    Domain = BloodBank(Network=Network, alpha=2)

    # Set Method
    Method = ABEuler(Domain=Domain, P=BoxProjection(lo=0), Delta0=1e-5)

    # Initialize Starting Point
    Start = BloodBank_Results_Phase1.PermStorage['Data'][-1]

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=10000, Tols=[(Domain.gap_rplus, 1e-3 * gap_0)])
    Repo = Reporting(Requests=[
        Domain.gap_rplus, 'Step', 'F Evaluations', 'Projections', 'Data'
    ])
    Misc = Miscellaneous()
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Print Stats
    PrintSimStats(Domain, Method, Options)

    # Start Solver
    tic = time.time()
    BloodBank_Results_Phase2 = Solve(Start, Method, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, BloodBank_Results_Phase2, Method, toc)

    ########################################################
    # Phase 3 - Left hospital has excessive demand for blood
    ########################################################

    # Define Network and Domain
    Network = CreateNetworkExample(ex=3)
    Domain = BloodBank(Network=Network, alpha=2)

    # Set Method
    Method = ABEuler(Domain=Domain, P=BoxProjection(lo=0), Delta0=1e-5)

    # Initialize Starting Point
    Start = BloodBank_Results_Phase2.PermStorage['Data'][-1]

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=10000, Tols=[(Domain.gap_rplus, 1e-3 * gap_0)])
    Repo = Reporting(Requests=[
        Domain.gap_rplus, 'Step', 'F Evaluations', 'Projections', 'Data'
    ])
    Misc = Miscellaneous()
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Print Stats
    PrintSimStats(Domain, Method, Options)

    # Start Solver
    tic = time.time()
    BloodBank_Results_Phase3 = Solve(Start, Method, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, BloodBank_Results_Phase3, Method, toc)

    ########################################################
    # Animate Network
    ########################################################

    # Construct MP4 Writer
    fps = 15
    FFMpegWriter = animation.writers['ffmpeg']
    metadata = dict(title='BloodBank', artist='Matplotlib')
    writer = FFMpegWriter(fps=fps, metadata=metadata)

    # Collect Frames
    frame_skip = 5
    freeze = 5
    Dyn_1 = BloodBank_Results_Phase1.PermStorage['Data']
    Frz_1 = [Dyn_1[-1]] * fps * frame_skip * freeze
    Dyn_2 = BloodBank_Results_Phase2.PermStorage['Data']
    Frz_2 = [Dyn_2[-1]] * fps * frame_skip * freeze
    Dyn_3 = BloodBank_Results_Phase3.PermStorage['Data']
    Frz_3 = [Dyn_3[-1]] * fps * frame_skip * freeze
    Frames = np.concatenate((Dyn_1, Frz_1, Dyn_2, Frz_2, Dyn_3, Frz_3),
                            axis=0)[::frame_skip]

    # Normalize Colormap by Flow at each Network Level
    Domain.FlowNormalizeColormap(Frames, cm.Reds)

    # Mark Annotations
    t1 = 0
    t2 = t1 + len(BloodBank_Results_Phase1.PermStorage['Data']) // frame_skip
    t3 = t2 + fps * freeze
    t4 = t3 + len(BloodBank_Results_Phase2.PermStorage['Data']) // frame_skip
    t5 = t4 + fps * freeze
    t6 = t5 + len(BloodBank_Results_Phase3.PermStorage['Data']) // frame_skip
    Dyn_1_ann = '$Demand_{1}$ $<$ $Demand_{2}$ & $Demand_{3}$\n(Equilibrating)'
    Frz_1_ann = '$Demand_{1}$ $<$ $Demand_{2}$ & $Demand_{3}$\n(Converged)'
    Dyn_2_ann = '$Demand_{1}$ ~= $Demand_{2}$ & $Demand_{3}$\n(Equilibrating)'
    Frz_2_ann = '$Demand_{1}$ ~= $Demand_{2}$ & $Demand_{3}$\n(Converged)'
    Dyn_3_ann = '$Demand_{1}$ $>$ $Demand_{2}$ & $Demand_{3}$\n(Equilibrating)'
    Frz_3_ann = '$Demand_{1}$ $>$ $Demand_{2}$ & $Demand_{3}$\n(Converged)'
    anns = sorted([(t1, plt.title, Dyn_1_ann), (t2, plt.title, Frz_1_ann),
                   (t3, plt.title, Dyn_2_ann), (t4, plt.title, Frz_2_ann),
                   (t5, plt.title, Dyn_3_ann), (t6, plt.title, Frz_3_ann)],
                  key=lambda x: x[0],
                  reverse=True)

    # Save Animation to File
    fig, ax = plt.subplots()
    BloodBank_ani = animation.FuncAnimation(fig,
                                            Domain.UpdateVisual,
                                            init_func=Domain.InitVisual,
                                            frames=len(Frames),
                                            fargs=(ax, Frames, anns),
                                            blit=True)
    BloodBank_ani.save('BloodBank.mp4', writer=writer)
Ejemplo n.º 6
0
def Demo():

    #__SERVICE_ORIENTED_INTERNET__##############################################
    N = 10  # number of possible maps
    T = 1000  # number of time steps
    eta = 1e-3  # learning rate

    print('Creating Domains')

    # Define Domains and Compute Equilbria
    Domains = []
    X_Stars = []
    CurlBounds = []
    n = 0
    while len(Domains) < N:
        # Create Domain
        Network = CreateRandomNetwork(m=3, n=2, o=2, seed=None)
        Domain = SOI(Network=Network, alpha=2)

        # Initialize Starting Point
        Start = np.zeros(Domain.Dim)

        # Assert PD
        J = approx_jacobian(Domain.F, Start)
        eigs = np.linalg.eigvals(J + J.T)
        if not np.all(eigs > 0):
            continue
        _J = approx_jacobian(Domain.F, Start + 0.5)
        assert np.allclose(J, _J,
                           atol=1e-5)  # assert J is constant (unique for SOI)

        # Record Domain
        Domains += [Domain]

        # Calculate Initial Gap
        gap_0 = Domain.gap_rplus(Start)

        # Calculate Curl Bound
        CurlBounds += [
            np.sqrt(18) *
            svds(J, k=1, which='LM', return_singular_vectors=False).item()
        ]

        # Set Method
        Method = HeunEuler(Domain=Domain, P=BoxProjection(lo=0), Delta0=1e-3)

        # Set Options
        Init = Initialization(Step=-1e-10)
        Term = Termination(MaxIter=25000,
                           Tols=[(Domain.gap_rplus, 1e-6 * gap_0)])
        Repo = Reporting(Requests=[Domain.gap_rplus])
        Misc = Miscellaneous()
        Options = DescentOptions(Init, Term, Repo, Misc)

        # Print Stats
        PrintSimStats(Domain, Method, Options)

        # Start Solver
        tic = time.time()
        SOI_Results = Solve(Start, Method, Domain, Options)
        toc = time.time() - tic

        # Print Results
        PrintSimResults(Options, SOI_Results, Method, toc)

        # Record X_Star
        X_Star = SOI_Results.TempStorage['Data'][-1]
        X_Stars += [X_Star]
        n += 1
    X_Stars = np.asarray(X_Stars)

    print('Starting Online Learning')

    # Set First Prediction
    X = np.zeros(X_Stars.shape[1])

    # Select First Domain
    idx = np.random.choice(len(Domains))

    # Domain Sequence
    idx_seq = []
    X_seq = []
    F_seq = []

    ts = range(T)
    for t in ts:
        print('t = ' + str(t), end='\r')
        # record prediction
        X_seq += [X]
        # record domain
        idx_seq += [idx]
        # retrieve domain
        Domain = Domains[idx]
        # record F
        FX = Domain.F(X)
        F_seq += [FX]
        # update prediction
        X = BoxProjection(lo=0).P(X, -eta, FX)
        # update domain
        idx = np.random.choice(len(Domains))

    print('Computing Optimal Strategy')

    weights = np.bincount(idx_seq, minlength=len(Domains)) / len(idx_seq)
    print('Weights: ', weights)

    # Compute Equilibrium of Average Domain
    Domain = AverageDomains(Domains, weights=weights)

    # Set Method
    Method = HeunEuler_PhaseSpace(Domain=Domain,
                                  P=BoxProjection(lo=0),
                                  Delta0=1e-5)

    # Initialize Starting Point
    Start = np.zeros(Domain.Dim)

    # Assert PSD - sum of PSD is PSD doesn't hurt to check
    J = approx_jacobian(Domain.F, Start)
    eigs = np.linalg.eigvals(J + J.T)
    assert np.all(eigs > 0)
    sigma = min(eigs)

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=25000, Tols=[(Domain.gap_rplus, 1e-10 * gap_0)])
    Repo = Reporting(Requests=[Domain.gap_rplus])
    Misc = Miscellaneous()
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Print Stats
    PrintSimStats(Domain, Method, Options)

    # Start Solver
    tic = time.time()
    SOI_Results = Solve(Start, Method, Domain, Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, SOI_Results, Method, toc)

    print('Computing Regrets')

    # Record X_Opt
    X_Opt = SOI_Results.TempStorage['Data'][-1]

    # Record constants for bounds
    L = np.sqrt(np.mean(np.linalg.norm(F_seq, axis=1)**2.))
    B = np.linalg.norm(X_Opt)
    eta_opt = B / (L * np.sqrt(2 * T))
    bound_opt = B * L * np.sqrt(2 * T)
    reg_bound = (B**2) / (2 * eta) + eta * T * L**2

    opt_distances = []
    equi_distances = []
    regret_standards = []
    regret_news = []
    Fnorms = []
    stokes = []
    areas = []
    ts = range(T)
    for t in ts:
        print('t = ' + str(t), end='\r')
        idx = idx_seq[t]
        X = X_seq[t]
        # retrieve domain
        Domain = Domains[idx]
        # retrieve equilibrium / reference vector
        if t > 0:
            equi = X_seq[t - 1]
        else:
            equi = np.zeros_like(X)
        # calculate distance
        opt_distances += [np.linalg.norm(X_Opt - X)]
        equi_distances += [np.linalg.norm(equi - X)]
        # calculate standard regret
        ci_predict = ContourIntegral(Domain, LineContour(equi, X))
        predict_loss = integral(ci_predict)
        ci_opt = ContourIntegral(Domain, LineContour(equi, X_Opt))
        predict_opt = integral(ci_opt)
        regret_standards += [predict_loss - predict_opt]
        # calculate new regret
        ci_new = ContourIntegral(Domain, LineContour(X_Opt, X))
        regret_news += [integral(ci_new)]
        # calculate bound
        area = herons(X_Opt, X, equi)  # exact area
        areas += [area]
        stokes += [CurlBounds[idx] * area]
        # stokes += [np.max(CurlBounds[idx]*regret_news[-1]/sigma,0)]
        # calculate Fnorm
        Fnorms += [np.linalg.norm(F_seq[t])]

    ts_p1 = range(1, T + 1)
    opt_distances_avg = np.divide(np.cumsum(opt_distances), ts_p1)
    equi_distances_avg = np.divide(np.cumsum(equi_distances), ts_p1)
    regret_standards_avg = np.divide(np.cumsum(regret_standards), ts_p1)
    regret_news_avg = np.divide(np.cumsum(regret_news), ts_p1)
    areas_avg = np.divide(np.cumsum(areas), ts_p1)
    stokes_avg = np.divide(np.cumsum(stokes), ts_p1)
    Fnorms_avg = np.divide(np.cumsum(Fnorms), ts_p1)

    np.savez_compressed('NoRegret_MLN2d.npz',
                        opt_d_avg=opt_distances_avg,
                        equi_d_avg=equi_distances_avg,
                        rs_avg=regret_standards_avg,
                        rn_avg=regret_news_avg,
                        stokes=stokes_avg)

    plt.subplot(2, 1, 2)
    plt.semilogy(ts,
                 opt_distances_avg,
                 'k',
                 label='Average Distance to Optimal')
    plt.semilogy(ts,
                 equi_distances_avg,
                 'r',
                 label='Average Distance to Reference')
    plt.semilogy(ts, areas_avg, 'g-', label='Area')
    plt.semilogy(ts, Fnorms_avg, 'b-', label='Fnorms')
    # plt.title('Demonstration of No-Regret on MLN')
    plt.xlabel('Time Step')
    plt.ylabel('Euclidean Distance')
    # plt.legend()
    lgd1 = plt.legend(bbox_to_anchor=(1.05, 1), loc=2)

    plt.subplot(2, 1, 1)
    plt.plot(ts,
             regret_standards_avg,
             'r--o',
             markevery=T // 20,
             label=r'regret$_{s}$')
    plt.plot(ts, regret_news_avg, 'b-', label=r'regret$_{n}$')
    plt.fill_between(ts,
                     regret_news_avg - stokes,
                     regret_news_avg + stokes,
                     facecolor='c',
                     alpha=0.2,
                     zorder=5,
                     label='Stokes Bound')

    # plt.plot(ts, np.zeros_like(ts), 'w-', lw=1)
    # plt.xlabel('Time Step')
    plt.ylabel('Aggregate System-Wide Loss')
    plt.xlim([0, T])
    plt.ylim([-5000, 5000])
    # plt.legend(loc='lower right')
    lgd2 = plt.legend(bbox_to_anchor=(1.05, 1), loc=2)
    plt.title('Demonstration of No-Regret on MLN')

    plt.savefig('NoRegret_MLN.pdf',
                format='pdf',
                additional_artists=[lgd1, lgd2],
                bbox_inches='tight')

    sat = np.logical_or(regret_standards_avg >= regret_news_avg - stokes,
                        regret_standards_avg <= regret_news_avg + stokes)

    embed()
Ejemplo n.º 7
0
def Demo():

    #__BLOOD_BANK__##################################################

    #############################################################
    # Example 1 from Nagurney's Paper
    #############################################################

    # Define Network and Domain
    Network = CreateNetworkExample(ex=1)
    Domain = SOI(Network=Network,alpha=2)

    # Set Method
    Method = ABEuler(Domain=Domain,P=BoxProjection(lo=0),Delta0=1e-2)

    # Initialize Starting Point
    Start = np.zeros(Domain.Dim)

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=10000,Tols=[(Domain.gap_rplus,1e-6*gap_0)])
    Repo = Reporting(Requests=[Domain.gap_rplus, 'Step', 'F Evaluations',
                               'Projections','Data'])
    Misc = Miscellaneous()
    Options = DescentOptions(Init,Term,Repo,Misc)

    # Print Stats
    PrintSimStats(Domain,Method,Options)

    # Start Solver
    tic = time.time()
    SOI_Results_Phase1 = Solve(Start,Method,Domain,Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options,SOI_Results_Phase1,Method,toc)

    #########################################################
    # Example 2 from Nagurney's Paper
    #########################################################

    # Define Network and Domain
    Network = CreateNetworkExample(ex=2)
    Domain = SOI(Network=Network,alpha=2)

    # Set Method
    Method = ABEuler(Domain=Domain,P=BoxProjection(lo=0),Delta0=1e-5)

    # Initialize Starting Point
    Start = SOI_Results_Phase1.PermStorage['Data'][-1]

    # Calculate Initial Gap
    gap_0 = Domain.gap_rplus(Start)

    # Set Options
    Init = Initialization(Step=-1e-10)
    Term = Termination(MaxIter=10000,Tols=[(Domain.gap_rplus,1e-3*gap_0)])
    Repo = Reporting(Requests=[Domain.gap_rplus, 'Step', 'F Evaluations',
                               'Projections','Data'])
    Misc = Miscellaneous()
    Options = DescentOptions(Init,Term,Repo,Misc)

    # Print Stats
    PrintSimStats(Domain,Method,Options)

    # Start Solver
    tic = time.time()
    SOI_Results_Phase2 = Solve(Start,Method,Domain,Options)
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options,SOI_Results_Phase2,Method,toc)

    ########################################################
    # Animate Network
    ########################################################

    # Construct MP4 Writer
    fps = 15
    FFMpegWriter = animation.writers['ffmpeg']
    metadata = dict(title='SOI', artist='Matplotlib')
    writer = FFMpegWriter(fps=fps, metadata=metadata)

    # Collect Frames
    frame_skip = 5
    freeze = 5
    Dyn_1 = SOI_Results_Phase1.PermStorage['Data']
    Frz_1 = [Dyn_1[-1]]*fps*frame_skip*freeze
    Dyn_2 = SOI_Results_Phase2.PermStorage['Data']
    Frz_2 = [Dyn_2[-1]]*fps*frame_skip*freeze
    Frames = np.concatenate((Dyn_1,Frz_1,Dyn_2,Frz_2),axis=0)[::frame_skip]

    # Normalize Colormap by Flow at each Network Level
    Domain.FlowNormalizeColormap(Frames,cm.rainbow)

    # Mark Annotations
    t1 = 0
    t2 = t1 + len(SOI_Results_Phase1.PermStorage['Data']) // frame_skip
    t3 = t2 + fps*freeze
    t4 = t3 + len(SOI_Results_Phase2.PermStorage['Data']) // frame_skip
    Dyn_1_ann = 'Control Network\n(Equilibrating)'
    Frz_1_ann = 'Control Network\n(Converged)'
    Dyn_2_ann = 'Market 1 Increases Demand for Service 1 by Provider 1' + \
                '\n(Equilibrating)'
    Frz_2_ann = 'Market 1 Increases Demand for Service 1 by Provider 1' + \
                '\n(Converged)'
    anns = sorted([(t1, plt.title, Dyn_1_ann),
                   (t2, plt.title, Frz_1_ann),
                   (t3, plt.title, Dyn_2_ann),
                   (t4, plt.title, Frz_2_ann)],
                  key=lambda x:x[0], reverse=True)

    # Save Animation to File
    fig, ax = plt.subplots()
    SOI_ani = animation.FuncAnimation(fig, Domain.UpdateVisual,
                                      init_func=Domain.InitVisual,
                                      frames=len(Frames),
                                      fargs=(ax, Frames, anns), blit=True)
    SOI_ani.save('Videos/SOI.mp4', writer=writer)
Ejemplo n.º 8
0
def Demo():

    # __ROSENBROCK__############################################################
    # __STEEPEST_DESCENT__######################################################

    # Define Domain
    Domain = Rosenbrock(Dim=2)

    # Set Method
    Method = Euler(Domain=Domain, FixStep=True)
    # Method = HeunEuler_PhaseSpace(Domain=Domain,Delta0=1e-1)
    # Method = HeunEuler_AdaGrad_PhaseSpace(Domain=Domain,Delta0=1e-1)

    # Set Options
    Term = Termination(MaxIter=20000, Tols=[(Domain.f_Error, 1e-6)])
    Repo = Reporting(Requests=[
        Domain.f_Error, 'Step', 'F Evaluations', 'Projections', 'Data'
    ])
    Misc = Miscellaneous()

    # Set starting point and step size ranges
    r = 2
    rads = np.linspace(0, 2 * np.pi, num=4, endpoint=False)
    steps = -np.logspace(-5, -3, num=3, endpoint=True)
    # steps = -np.logspace(-8,-6,num=3,endpoint=True)

    # Construct figure
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.view_init(azim=-160.)
    X = np.arange(-1.5, 3.5, 0.25)
    Y = np.arange(-1.5, 3.5, 0.25)
    X, Y = np.meshgrid(X, Y)
    Z = np.zeros_like(X)
    for i in xrange(Z.shape[0]):
        for j in xrange(Z.shape[1]):
            Z[i, j] = Domain.f(np.array([X[i, j], Y[i, j]]))
    ax.plot_surface(X,
                    Y,
                    Z,
                    rstride=1,
                    cstride=1,
                    cmap=cm.coolwarm,
                    linewidth=0,
                    antialiased=False)
    ax.set_xlim3d(np.min(X), np.max(X))
    ax.set_ylim3d(np.min(Y), np.max(Y))
    ax.set_zlim3d(np.min(Z), np.max(Z))
    ax.set_xlabel('X axis')
    ax.set_ylabel('Y axis')
    ax.zaxis.set_rotate_label(False)  # disable automatic rotation
    ax.set_zlabel('f(X,Y)', rotation=90)
    ax.text2D(0.05,
              0.95,
              'Steepest Descent on the\nRosenbrock Function',
              transform=ax.transAxes)
    lw = cycle(range(2 * len(steps), 0, -2))
    plt.ion()
    plt.show()

    # Compute trajectories
    for rad, step in itertools.product(rads, steps):

        # Initialize Starting Point
        assert Domain.Dim == 2
        Start = Domain.ArgMin + r * np.asarray([np.cos(rad), np.sin(rad)])

        # Set Options
        Init = Initialization(Step=step)
        Options = DescentOptions(Init, Term, Repo, Misc)

        # Print Stats
        PrintSimStats(Domain, Method, Options)

        # Start Solver
        tic = time.time()
        Rosenbrock_Results = Solve(Start, Method, Domain, Options)
        toc = time.time() - tic

        # Print Results
        PrintSimResults(Options, Rosenbrock_Results, Method, toc)

        # Plot Results
        data_SD = Rosenbrock_Results.PermStorage['Data']
        res_SD = np.asarray(Rosenbrock_Results.PermStorage[Domain.f_Error])
        res_SD[np.isnan(res_SD)] = np.inf
        trajX = []
        trajY = []
        trajZ = []
        for i in xrange(len(data_SD)):
            trajX.append(data_SD[i][0])
            trajY.append(data_SD[i][1])
            trajZ.append(res_SD[i])
        ax.plot(trajX, trajY, trajZ, lw=next(lw))
        plt.draw()
    plt.ioff()
    plt.show()

    # __NEWTONS_METHOD____######################################################

    # Define Domain
    Domain = Rosenbrock(Dim=2, Newton=True)

    # Set Method
    Method = Euler(Domain=Domain, FixStep=True)

    # Set Options
    Term = Termination(MaxIter=20000, Tols=[(Domain.f_Error, 1e-6)])
    Repo = Reporting(Requests=[
        Domain.f_Error, 'Step', 'F Evaluations', 'Projections', 'Data'
    ])
    Misc = Miscellaneous()
    Init = Initialization(Step=-1e-3)
    Options = DescentOptions(Init, Term, Repo, Misc)

    # Print Stats
    PrintSimStats(Domain, Method, Options)

    # Start Solver
    tic = time.time()
    Rosenbrock_Results = Solve(Start, Method, Domain,
                               Options)  # Use same Start
    toc = time.time() - tic

    # Print Results
    PrintSimResults(Options, Rosenbrock_Results, Method, toc)

    # Plot Results
    data_N = Rosenbrock_Results.PermStorage['Data']
    res_N = np.asarray(Rosenbrock_Results.PermStorage[Domain.f_Error])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(res_N, label='Newton' 's Method')
    ax.plot(res_SD, label='Steepest Descent')
    ax.set_yscale('log')
    ax.set_xlabel('Iterations (k)')
    ax.set_ylabel('f(X,Y) [log-scale]')
    ax.set_title('Rosenbrock Test: Newton' 's Method vs Steepest Descent')
    ax.legend()
    plt.show()

    fig = plt.figure()
    ax = fig.add_subplot(111)
    diff_N = [np.linalg.norm(d - Domain.ArgMin) for d in data_N]
    diff_SD = [np.linalg.norm(d - Domain.ArgMin) for d in data_SD]
    ax.plot(diff_N, label='Newton' 's Method')
    ax.plot(diff_SD, label='Steepest Descent')
    ax.set_yscale('log')
    ax.set_xlabel('Iterations (k)')
    ax.set_ylabel(r'$||x-x^*||$ [log-scale]')
    ax.set_title('Rosenbrock Test: Newton' 's Method vs Steepest Descent')
    ax.legend()
    plt.show()