Ejemplo n.º 1
0
def SimplexMethodI(A, b, c, max_it=500, rule=0, c_form=0):
    """ Error checking """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        raise Exception('Inputs must be a numpy arrays')

    # Construction in a standard form [A | I]
    if c_form == 0:
        (A, c) = stdForm(A, c)
    A = np.asmatrix(A)
    r_A, c_A = A.shape
    """ Check full rank matrix """

    # Remove ld rows:
    if not np.linalg.matrix_rank(A) == r_A:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    B = {0, 1, 2, 3, 4, 6, 7, 10, 12, 14, 16}
    D = list(B)
    x = np.zeros(c_A)
    x[D] = np.linalg.solve(A[:, D], b)

    info, x, B, z, itII, u = fun(A, c, x, B, 0, max_it, rule)

    # Print termination of phase II

    if info == 0:
        print_boxed(
            "Found optimal solution at x* =\n{}\n\n".format(x) +
            #                    "Basis indexes: {}\n".format(B) +
            #                    "Nonbasis indexes: {}\n".format(set(range(c_A)) - B) +
            "Optimal cost: {}\n".format(z.round(decimals=3)) +
            "Number of iterations: {}.".format(itII))
    elif info == 1:
        print("\nUnlimited problem.")
    elif info == 2:
        print('The problem is not solved after {} iterations.'.format(max_it))
    return x, u
Ejemplo n.º 2
0
def longpath2(A,
              b,
              c,
              gamma=0.001,
              c_form=0,
              w=10**(-8),
              max_it=500,
              info=0,
              ip=1):

    print('\n\tCOMPUTATION OF LPF ALGORITHM 2')

    # Algorithm in 4 steps:
    # 0..Input error checking
    # 1..Find the initial point with Mehrotra's method
    # 2..obtain the search direction
    # 3..find the largest step
    """ Input error checking & construction in a standard form """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        raise Exception('Inputs must be a numpy arrays')

    if c_form == 0:
        A, c = stdForm(A, c)
    r_A, c_A = A.shape
    if not np.linalg.matrix_rank(
            A) == r_A:  # Check full rank matrix:Remove ld rows:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    """ Initial points: Initial infeasible positive (x,y,s) and initial gap g """

    if ip == 0:
        (x, y, s) = sp(A, c, b)
    else:
        (x, y, s) = sp2(A, c, b)

    (x, y, s) = sp(A, c, b)
    g = np.dot(c, x) - np.dot(y, b)

    if info == 0:
        print('\nInitial primal-dual point:\nx = {} \nlambda = {} \ns = {}'.
              format(x, y, s))
        print('Dual initial g: {}.\n'.format("%10.3f" % g))

    # Check if (x, y, s) in neighborhood N_inf:
    mu = np.dot(x, s) / c_A
    if not (x * s > gamma * mu).all():
        print("Initial point is not in N")
    E = lambda a: (s + a * s1) * (x + a * x1) - (gamma * np.dot(
        (s + a * s1),
        (x + a * x1))) / c_A  # Function E: set of values in N_(gamma)

    #%%
    """ Search vector direction """
    '''Modified Newton's method with with normal equations: find the direction vector (y1, s1, x1)'''

    it = 0  # Num of iterations
    tm = term(it)  # Define tollerance tm = inf
    u = []  # Construct list of info elements
    u.append([it, g, x, s, b - np.dot(A, x), c - np.dot(A.T, y) - s])
    sig = []

    while tm > w:
        cp = min(0.1, 100 * np.dot(x, s) / c_A)  # sigma2

        if info == 0:
            print("\tIteration: {}\n".format(it), end='')
            print("Centering parameter sigma:{}.\n".format("%10.3f" % cp))

        X_inv = np.linalg.inv(np.diag(x))
        W1 = X_inv * np.diag(s)  # W1 = X^(-1)*S
        T = np.concatenate((np.zeros((r_A, r_A)), A), axis=1)
        U = np.concatenate((A.T, -W1), axis=1)
        V = np.concatenate((T, U), axis=0)

        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        rxs = -x * s + cp * (sum(x * s) / c_A) * np.ones(
            c_A)  # Newton step toward x*s = sigma*mi

        r = np.hstack((rb, rc - np.dot(X_inv, rxs)))
        o = np.linalg.solve(V, r)

        y1 = o[:r_A]
        x1 = o[r_A:c_A + r_A]
        s1 = np.dot(X_inv, rxs) - np.dot(W1, x1)

        if info == 0:
            print(
                'Search direction vectors: \n delta_x = {} \n delta_lambda = {} \n delta_s = {}.\n'
                .format(x1.round(decimals=3), y1.round(decimals=3),
                        s1.round(decimals=3)))
        """ Compute the largest step length & increment of the points and the iteration"""

        # We find the maximum alpha s. t the next iteration is in N_gamma
        v = np.arange(0, 1.000, 0.0001)
        i = len(v) - 1
        while i >= 0:
            if (E(v[i]) > 0).all():
                t = v[i]
                #                print('Largest step length:{}'.format("%10.3f"%t))
                break
            else:
                i -= 1

        # Update step
        x += t * x1  # Current x
        y += t * y1  # Current y
        s += t * s1  # Current s
        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s

        z = np.dot(c, x)  # Current opt. solution
        g = z - np.dot(y, b)  # Current gap
        it += 1
        u.append([it, g, x.copy(), s.copy(), rb.copy(), rc.copy()])
        sig.append([cp])

        # Termination elements
        m, n, q = term(it, b, c, rb, rc, z, g)
        tm = max(m, n, q)
        if it == max_it:
            raise TimeoutError("Iterations maxed out")
        if info == 0:
            print(
                '\nCurrent point:\n x = {} \n lambda = {} \n s = {}.\n'.format(
                    x.round(decimals=3), y.round(decimals=3),
                    s.round(decimals=3)))
            print('Dual next gap: {}.\n'.format("%10.3f" % g))

#%%

    print_boxed("Found optimal solution of the problem at\n x* = {}.\n\n".
                format(x.round(decimals=3)) +
                "Dual gap: {}\n".format("%2.2e" % g) +
                "Optimal cost: {}\n".format("%10.8E" % z) +
                "Number of iteration: {}".format(it))
    return x, s, u, sig
Ejemplo n.º 3
0
def SimplexMethod(A, b, c, max_it=500, rule=0, c_form=0):
    """ Error checking """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        raise Exception('Inputs must be a numpy arrays')

    # Construction in a standard form [A | I]
    if c_form == 0:
        (A, c) = stdForm(A, c)
    A = np.asmatrix(A)
    r_A, c_A = A.shape
    """ Check full rank matrix """

    # Remove ld rows:
    if not np.linalg.matrix_rank(A) == r_A:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows

    print('\n\tCOMPUTATION OF SIMPLEX ALGORITHM')
    if rule == 0:
        print('\twith the Bland\'s rule:\n')
    else:
        print('\t without the Bland\'s rule:\n')
    """ IIphases simplex method """

    # If b negative then I phase simplex fun with input data A_I, x_I, c_I
    # The solution x_I is the initial point for II phase.

    if sum(b < 0) > 0:  # Phase I variables:
        print('Vector b < 0:\n\tStart phase I\n')

        # Change sign of constraints
        A[[i for i in range(r_A) if b[i] < 0]] *= -1
        b = np.abs(b)
        A_I = np.matrix(np.concatenate((A, np.identity(r_A)), axis=1))
        c_I = np.concatenate((np.zeros(c_A), np.ones(r_A)))
        x_I = np.concatenate((np.zeros(c_A), b))
        B = set(range(c_A, c_A + r_A))

        # Compute the Algorithm of the extended LP

        infoI, xI, BI, zI, itI, uI = fun(A_I, c_I, x_I, B, 0, max_it, rule)
        assert infoI == 0

        #         Two cases of the phase I: zI > 0: STOP. zI = 0: Phase II

        if zI > 0:
            print('The problem is not feasible.\n{} iterations in phase I.'.
                  format(itI))
            print_boxed('Optimal cost in phase I: {}\n'.format(zI))
            return xI, uI

        else:  # Get initial BFS for original problem (without artificial vars.)
            xI = xI[:c_A]
            print("Found initial BFS at x: {}.\n\tStart phase II\n".format(xI))
            info, x, B, z, itII, u = fun(A, c, xI, BI, itI + 1, max_it, rule)
            u = uI + u
    # If b is positive phase II with B = [n+1,..., n+m]

    else:
        x = np.concatenate((np.zeros(c_A - r_A), b))
        B = set(range(c_A - r_A, c_A))
        info, x, B, z, itII, u = fun(A, c, x, B, 0, max_it, rule)

    # Print termination of phase II

    if info == 0:
        print_boxed(
            "Found optimal solution at x* =\n{}\n\n".format(x) +
            #                    "Basis indexes: {}\n".format(B) +
            #                    "Nonbasis indexes: {}\n".format(set(range(c_A)) - B) +
            "Optimal cost: {}\n".format(z.round(decimals=3)) +
            "Number of iterations: {}.".format(itII))
    elif info == 1:
        print("\nUnlimited problem.")
    elif info == 2:
        print('The problem is not solved after {} iterations.'.format(max_it))
    return x, u
Ejemplo n.º 4
0
def longpathPC(A,
               b,
               c,
               gamma=0.001,
               c_form=0,
               w=10**(-8),
               max_it=500,
               info=0,
               ip=0):

    print('\n\tLPF predictor-corrector')

    # Algorithm in 4 steps:
    # 0..Input error checking
    # 1..Find the initial point with Mehrotra's method
    # 2..Predictor step
    # 3..Corrector step
    """ Input error checking & construction in a standard form """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        info = 1
        raise Exception('Inputs must be a numpy arrays: INFO {}'.format(info))

    if c_form == 0:  # Construction in a standard form [A | I]
        A, c = stdForm(A, c)
    r_A, c_A = A.shape
    if not np.linalg.matrix_rank(A) == r_A:  # Remove ld rows:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    """ Initial points: Initial infeasible positive (x,y,s) and initial gap g """

    if ip == 0:
        (x, y, s) = sp(A, c, b)
    else:
        (x, y, s) = sp2(A, c, b)
    g = np.dot(c, x) - np.dot(y, b)

    if info == 0:

        print('\nInitial primal-dual point:\nx = {} \nlambda = {} \ns = {}'.
              format(x, y, s))
        print('Dual initial gap: {}.\n'.format("%10.3f" % g))

    # Check if (x, y, s) in neighborhood N_inf and define E:
    if not (x * s > gamma * np.dot(x, s) / c_A).all():
        print("Initial point is not in N")
    E = lambda a: (s + a * s1) * (x + a * x1) - (gamma * np.dot(
        (s + a * s1),
        (x + a * x1))) / c_A  # Function E: set of values in N_(gamma)

    #%%
    """ Predictor step """
    '''Pure Newton's method with with normal equations: find the direction vector (y1, s1, x1)'''

    it = 0  # Num of iterations
    tm = term(it)  # Define tollerance tm = inf
    u = []  # Construct list of info elements
    u.append([it, g, x, s, b - np.dot(A, x), c - np.dot(A.T, y) - s])
    sig = []

    while tm > w:

        if info == 0:
            print("\tIteration: {}\n".format(it + 1))

        # Choose cp = 0 and compute the direction with augmented system
        (x1, y1, s1, rb, rc) = augm(A, b, c, x, y, s, 0)

        # Find the maximum alpha s.t the next iteration is in N_gamma
        v = np.arange(0, 1.0000, 0.0001)
        i = len(v) - 1
        while i >= 0:
            if (E(v[i]) > 0).all():
                t = v[i]
                #            print('Largest step length:{}'.format("%10.3f"%t))
                break
            else:
                i -= 1
        mi = np.dot(x, s) / c_A  # Duality measure
        mi_aff = np.dot(
            x + t * x1,
            s + t * s1) / c_A  # Average value of the incremented vectors
        Sigma = (mi_aff / mi)**3
        """ Corrector step: compute (x_k+1, lambda_k+1, s_k+1) """

        (x1, y1, s1, rb, rc) = augm(A, b, c, x, y, s, Sigma)

        if info == 0:
            print(
                'Search direction vectors: \n delta_x = {} \n delta_lambda = {} \n delta_s = {}.\n'
                .format(x1.round(decimals=3), x1.round(decimals=3),
                        s1.round(decimals=3)))

        # Update
        x += t * x1  # Current x
        y += t * y1  # Current y
        s += t * s1  # Current s
        z = np.dot(c, x)  # Current optimal solution
        g = z - np.dot(y, b)  # Current gap
        it += 1
        u.append([it, g, x.copy(), s.copy(), rb.copy(), rc.copy()])
        sig.append(Sigma)

        # Termination elements
        tm = term(it, b, c, rb, rc, z, g)

        if it == max_it:
            raise TimeoutError("Iterations maxed out")

        if info == 0:
            print(
                '\nCurrent primal-dual point:\n x = {} \n lambda = {} \n s = {}.\n'
                .format(x.round(decimals=3), y.round(decimals=3),
                        s.round(decimals=3)))
            print('Dual next gap: {}.\n'.format("%10.3f" % g))

#%%

    print_boxed("Found optimal solution of the problem at\n x* = {}.\n\n".
                format(x.round(decimals=3)) +
                "Dual gap: {}\n".format("%2.2e" % g) +
                "Optimal cost: {}\n".format("%10.3f" % z) +
                "Number of iteration: {}".format(it))

    return x, s, u, sig
Ejemplo n.º 5
0
def aff_an(A, b, c, c_form=0, w=10**(-8), max_iter=500):

    print('\n\tCOMPUTATION OF PRIMAL-DUAL AFFINE SCALING ALGORITHM')

    # Algorithm in 4 steps:
    # 0..Input error checking
    # 1..Find the initial point with Mehrotra's method
    # 2..obtain the search direction
    # 3..find the largest step
    """ Input error checking """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        raise Exception('Inputs must be a numpy arrays')

    # Construction in a standard form [A | I]
    if c_form == 0:
        A, c = stdForm(A, c)
    r_A, c_A = A.shape
    """ Check full rank matrix """

    if not np.linalg.matrix_rank(A) == r_A:  # Remove ld rows:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    """ Initial points """

    # Initial infeasible positive (x,y,s) and initial gap g
    (x, y, s) = sp(A, c, b)
    g = np.dot(c, x) - np.dot(y, b)

    print('\nInitial primal-dual point:\n x = {} \n lambda = {} \n s = {}.\n'.
          format(x, y, s))
    print('Dual initial gap: {}.\n'.format("%10.3f" % g))

    #%%
    """ Search vector direction """

    it = 0
    tm = term(it)
    u = []
    v = []
    while tm > w:
        u.append(sum(x.copy() * s.copy()) / c_A)
        print("\tIteration: {}\n".format(it))
        S_inv = np.linalg.inv(np.diag(s))
        W1 = S_inv * np.diag(x)  # W1 = D = S^(-1)*X
        W2 = np.dot(A, W1)  # W      A*S^(-1)*X
        W = np.dot(W2, A.T)
        L = np.linalg.cholesky(W)  # CHOLESKY for A* D^2 *A^T
        L_inv = np.linalg.inv(L)

        # RHS of the system
        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        rxs = -x * s  # Newton step toward x*s = 0

        B = rb + np.dot(W2, rc) - np.dot(np.dot(A, S_inv),
                                         rxs)  #RHS of normal equation form
        z = np.dot(L_inv, B)

        # SEARCH DIRECTION:
        y1 = np.dot(L_inv.T, z)
        s1 = rc - np.dot(A.T, y1)
        x1 = np.dot(S_inv, rxs) - np.dot(W1, s1)
        q1 = np.concatenate((x1, s1))
        v.append(np.linalg.norm(q1))
        print(
            'Search direction vectors: \n delta_x = {} \n delta_lambda = {} \n delta_s = {}.\n'
            .format(x1.round(decimals=3), y1.round(decimals=3),
                    s1.round(decimals=3)))

        #%%
        """ largest step length """

        # Largest step length T such that (x, s) + T (x1, s1) is positive
        m = min([(-x[i] / x1[i], i) for i in range(c_A) if x1[i] < 0],
                default=[1])[0]
        n = min([(-s[i] / s1[i], i) for i in range(c_A) if s1[i] < 0],
                default=[1])[0]
        T = (0.9) * min(m, n)

        # INCREMENT of the vectors and iterations
        x += min(T, 1) * x1
        y += min(T, 1) * y1
        s += min(T, 1) * s1

        z = np.dot(c, x)  # Current optimal solution
        g = z - np.dot(y, b)
        it += 1

        # Termination elements
        tm = term(it, b, c, rb, rc, z, g)

        if it == max_iter:
            raise TimeoutError("Iterations maxed out")

        print('Current point:\n x = {} \n lambda = {} \n s = {}.\n'.format(
            x, y, s))
        print('Dual next gap: {}.\n'.format("%10.3f" % g))

    print_boxed(
        "Found optimal solution of the problem at\n x* = {}.\n".format(x) +
        "Dual gap: {}\n".format("%10.6f" % g) +
        "Optimal cost: {}\n".format("%10.3f" % z) +
        "Number of iterations: {}".format(it))
    return x, s, u, v
Ejemplo n.º 6
0
def longpathC(A,
              b,
              c,
              gamma=0.001,
              s_min=0.1,
              s_max=0.9,
              c_form=0,
              cp=0.6,
              w=0.005,
              max_iter=300):

    print('\n\tCOMPUTATION OF LPF ALGORITHM')
    """ Input error checking """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        info = 1
        raise Exception('Inputs must be a numpy arrays: INFO {}'.format(info))

    # Construction in a standard form [A | I]
    if c_form == 0:
        A, c = stdForm(A, c)
    r_A, c_A = A.shape
    E = lambda a: (s + a * s1) * (x + a * x1) - (gamma * np.dot(
        (s + a * s1),
        (x + a * x1))) / c_A  #Function E: set of values in N_(gamma)
    """ Check full rank matrix """

    if not np.linalg.matrix_rank(A) == r_A:  # Remove ld rows:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    """ Initial points """

    # Initial infeasible positive (x,y,s) and Initial gap g
    (x, y, s) = sp(A, c, b)
    g = np.dot(c, x) - np.dot(y, b)

    print('\nInitial primal-dual point:\nx = {} \nlambda = {} \ns = {}'.format(
        x, y, s))
    print('Dual initial gap: {}.\n'.format("%10.3f" % g))

    # Check if (x, y, s) in neighborhood N_inf:

    if (x * s > gamma * np.dot(x, s) / c_A).all():
        print("Initial point is in N_inf(gamma), gamma = {}\n".format(
            "%10.6f" % gamma))

    #%%
    """ search vector direction """

    # Compute the search direction solving the matricial system
    # Instead of solving the std system matrix it is uses AUGMENT SYSTEM with CHOL approach
    it = 0
    tm = term(it)
    u = []
    u.append([it, g, x, s, b - np.dot(A, x), c - np.dot(A.T, y) - s])
    #    sigma = random.uniform(s_min, s_max) Choose centering parameter SIGMA_k in [sigma_min , sigma_max]
    while tm > 10**(-8):
        print("\tIteration: {}\n".format(it + 1), end='')
        S_inv = np.linalg.inv(np.diag(s))
        W1 = S_inv * np.diag(x)  # W1 = D = S^(-1)*X
        W2 = np.dot(A, W1)  # W      A*S^(-1)*X
        W = np.dot(W2, A.T)
        L = np.linalg.cholesky(W)  # CHOLESKY for A* D^2 *A^T
        L_inv = np.linalg.inv(L)

        # RHS of the system

        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        rxs = -x * s + cp * (sum(x * s) / c_A) * np.ones(
            c_A)  # Newton step toward x*s = sigma*mi

        B = rb + np.dot(W2, rc) - np.dot(np.dot(A, S_inv),
                                         rxs)  #RHS of normal equation form
        z = np.dot(L_inv, B)

        # SEARCH DIRECTION:

        y1 = np.dot(L_inv.T, z)
        s1 = rc - np.dot(A.T, y1)
        x1 = np.dot(S_inv, rxs) - np.dot(W1, s1)
        print(
            'Search direction vectors: \n delta_x = {} \n delta_lambda = {} \n delta_s = {}.\n'
            .format(x1.round(decimals=3), x1.round(decimals=3),
                    s1.round(decimals=3)))

        #%%
        """ largest step length """

        # We find the maximum alpha s. t the next iteration is in N_gamma
        v = np.arange(0, 0.999, 0.0001)
        i = len(v) - 1
        while i >= 0:
            if (E(v[i]) > 0).all():
                t = v[i]
                print('Largest step length:{}'.format("%10.3f" % t))
                break
            else:
                i -= 1

        # Increment the points and iteration
        x += t * x1
        y += t * y1
        s += t * s1
        it += 1
        if it == max_iter:
            print("Iterations maxed out")
            return x, s, u
        print('\nCurrent point:\n x = {} \n lambda = {} \n s = {}.\n'.format(
            x.round(decimals=3), y.round(decimals=3), s.round(decimals=3)))
        z = np.dot(c, x)
        g = z - np.dot(y, b)

        # Termination elements
        tm = term(it, b, c, rb, rc, z, g)
        u.append([it, g, x.copy(), s.copy(), rb.copy(), rc.copy()])
        print('Dual next gap: {}.\n'.format("%10.3f" % g))

    print_boxed("Found optimal solution of the problem at\n x* = {}.\n\n".
                format(x.round(decimals=3)) +
                "Dual gap: {}\n".format("%10.6f" % g) +
                "Optimal cost: {}\n".format("%10.3f" % z) +
                "Number of iteration: {}".format(it))
    print("Centering parameter sigma:{}.\n".format("%10.3f" % cp))

    return x, s, u
Ejemplo n.º 7
0
def affine2(A, b, c, c_form=0, w=10**(-8), max_iter=500):

    print('\n\tCOMPUTATION OF PRIMAL-DUAL AFFINE SCALING ALGORITHM')

    # Algorithm in 4 steps:
    # 0..Input error checking
    # 1..Find the initial point with Mehrotra's method
    # 2..obtain the search direction,
    # 3..find the largest step
    """ Input error checking """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        raise Exception('Inputs must be a numpy arrays')

    # Construction in a standard form [A | I]
    if c_form == 0:
        A, c = stdForm(A, c)
    r_A, c_A = A.shape
    """ Check full rank matrix """

    if not np.linalg.matrix_rank(A) == r_A:  # Remove ld rows:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    """ Initial points """

    # Initial infeasible positive (x,y,s) and Initial gap g
    (x, y, s) = sp(A, c, b)
    g = np.dot(c, x) - np.dot(y, b)

    print('\nInitial primal-dual point:\n x = {} \n lambda = {} \n s = {}.\n'.
          format(x, y, s))
    print('Dual initial gap: {}.\n'.format("%10.3f" % g))

    #%%
    """ search vector direction """

    it = 0
    tm = term(it)
    u = []
    u.append([it, g, x, s, b - np.dot(A, x), c - np.dot(A.T, y) - s])
    while tm > w:

        print("\tIteration: {}\n".format(it))
        # solve search direction with AUGMENTED SYSTEM
        X_inv = np.linalg.inv(np.diag(x))
        W1 = X_inv * np.diag(s)  # W1 = D = X^(-1)*S
        T = np.concatenate((np.zeros((r_A, r_A)), A), axis=1)
        U = np.concatenate((A.T, -W1), axis=1)
        V = np.concatenate((T, U), axis=0)

        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        rxs = -x * s  # Newton step toward x*s

        r = np.hstack((rb, -np.dot(X_inv, rxs)))
        o = np.linalg.solve(V, r)

        y1 = o[:r_A]
        x1 = o[r_A:c_A + r_A]
        s1 = np.dot(X_inv, rxs) - np.dot(W1, x1)
        print(
            'Search direction vectors: \n delta_x = {} \n delta_lambda = {} \n delta_s = {}.\n'
            .format(x1.round(decimals=3), y1.round(decimals=3),
                    s1.round(decimals=3)))

        #%%
        """ largest step length """

        # Largest step length T such that (x, s) + T (x1, s1) is positive
        m = min([(-x[i] / x1[i], i) for i in range(c_A) if x1[i] < 0],
                default=[1])[0]
        n = min([(-s[i] / s1[i], i) for i in range(c_A) if s1[i] < 0],
                default=[1])[0]
        T = (0.9) * min(m, n)

        # INCREMENT of the vectors and iterations
        x += min(T, 1) * x1
        y += min(T, 1) * y1
        s += min(T, 1) * s1

        z = np.dot(c, x)  # Current optimal solution
        g = z - np.dot(y, b)
        u.append([it, g, x.copy(), s.copy(), rb.copy(), rc.copy()])

        # Termination elements
        tm = term(it, b, c, rb, rc, z, g)

        it += 1
        if it == max_iter:
            raise TimeoutError("Iterations maxed out")

        print('Current point:\n x = {} \n lambda = {} \n s = {}.\n'.format(
            x, y, s))
        print('Dual next gap: {}.\n'.format("%10.3f" % g))

    print_boxed(
        "Found optimal solution of the problem at\n x* = {}.\n".format(x) +
        "Dual gap: {}\n".format("%10.6f" % g) +
        "Optimal cost: {}\n".format("%10.3f" % z) +
        "Number of iterations: {}".format(it))
    return x, s, u
Ejemplo n.º 8
0
def mehrotra(A, b, c, c_form=0, w=10**(-8), max_it=500, info=0, ip=1):

    print('\n\tCOMPUTATION OF MEHROTRA ALGORITHM\n')

    # Algorithm in 4 steps:
    # 0..Input error checking
    # 1..Find the initial point with Mehrotra's method
    # 2..Predictor step
    # 3..Centering step
    # 4..Corrector step
    """ Input error checking & construction in a standard form """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        raise Exception('Inputs must be a numpy arrays')

    if c_form == 0:
        A, c = stdForm(A, c)
    r_A, c_A = A.shape
    if not np.linalg.matrix_rank(
            A) == r_A:  # Check full rank matrix:Remove ld rows:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    """ Initial points: Initial infeasible positive (x,y,s) and initial gap g """

    if ip == 0:
        (x, y, s) = sp(A, c, b)  # MIP
    else:
        (x, y, s) = sp2(A, c, b)  # STP1

    g = np.dot(c, x) - np.dot(y, b)

    if info == 0:

        print('\nInitial primal-dual point:\nx = {} \nlambda = {} \ns = {}'.
              format(x, y, s))
        print('Dual initial g: {}.\n'.format("%10.3f" % g))

    #%%
    """ Predictor step: compute affine direction """
    '''
    Compute affine scaling direction solving Qs = R with system D^2 = S^{-1}*X 
    with Q a large sparse matrix 
    and R = [rb, rc, - x_0*s_0]
    '''

    it = 0  # Num of iterations
    tm = term(it)  # Tollerance in the cycle

    u = []  # Construct list of info elements
    sig = []
    u.append([it, g, x, s, b - np.dot(A, x), c - np.dot(A.T, y) - s])

    while tm > w:
        """ Pure Newton's method with with normal equations: find the direction vector (y1, s1, x1)"""

        S_inv = np.linalg.inv(np.diag(s))  # S^{-1}
        W1 = np.dot(S_inv, np.diag(x))  # W1 = D = S^(-1)*X
        W2 = np.dot(A, W1)  # W2      A*S^(-1)*X
        W = np.dot(W2, A.T)
        L = np.linalg.cholesky(W)
        L_inv = np.linalg.inv(L)

        # RHS of the system, including the minus
        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        rxs = -x * s

        B = rb + np.dot(W2, rc) - np.dot(np.dot(A, S_inv),
                                         rxs)  #RHS of normal equation form
        z = np.dot(L_inv, B)

        # SEARCH DIRECTION affine:
        y1 = np.dot(L_inv.T, z)
        s1 = rc - np.dot(A.T, y1)
        x1 = np.dot(S_inv, rxs) - np.dot(W1, s1)

        if info == 0:

            print("\n\tIteration: {}\n".format(it), end='')
            print(
                "\nPREDICTOR STEP:\nAffine direction:\n({}, {}, {})\n".format(
                    x1, y1, s1))

        #%%
        """ Centering step: compute search direction """
        '''
        Find alfa1_affine and alfa2_affine : maximum steplength along affine-scaling direction
        Find the minimum( x_{i}/x1_{i} , 1) and the minimum( s_{i}/s1_{i} , 1)
        '''

        h = min([(-x[i] / x1[i], i) for i in range(c_A) if x1[i] < 0],
                default=[0])[0]
        k = min([(-s[i] / s1[i], i) for i in range(c_A) if s1[i] < 0],
                default=[0])[0]

        alfa1 = min(h, 1)
        alfa2 = min(k, 1)

        # Set the centering parameter to Sigma = (mi_aff/mi)^{3}
        mi = np.dot(x, s) / c_A  # Duality measure
        mi_af = np.dot(
            x + alfa1 * x1,
            s + alfa2 * s1) / c_A  # Average value of the incremented vectors
        Sigma = (mi_af / mi)**(3)

        # SECOND SEARCH DIRECTION
        Rxs = -x1 * s1 + Sigma * mi * np.ones(
            (c_A))  # RHS of the New system, including minus

        Rb = -np.dot(np.dot(A, S_inv), Rxs)  # RHS of New normal equation form
        z = np.dot(L_inv, Rb)

        # SEARCH DIRECTION centering-orrector:
        y2 = np.dot(L_inv.T, z)
        s2 = -np.dot(A.T, y2)
        x2 = np.dot(S_inv, Rxs) - np.dot(W1, s2)

        if info == 0:

            print("Cc direction:\n({}, {}, {})\n".format(x2, y2, s2))

        #%%
        """ Corrector step: compute (x_k+1, lambda_k+1, s_k+1) """

        # The steplength without eta_k
        x2 += x1
        s2 += s1
        y2 += y1
        H = min([(-x[i] / x2[i], i) for i in range(c_A) if x2[i] < 0],
                default=[0])[0]
        K = min([(-s[i] / s2[i], i) for i in range(c_A) if s2[i] < 0],
                default=[0])[0]
        Alfa1 = min(0.99 * H, 1)
        Alfa2 = min(0.99 * K, 1)

        # Update
        x += Alfa1 * x2  # Current x
        y += Alfa2 * y2  # Current y
        s += Alfa2 * s2  # Current s
        z = np.dot(c, x)  # Current optimal solution
        g = z - np.dot(y, b)  # Current gap
        it += 1
        u.append([it, g, x.copy(), s.copy(), rb.copy(), rc.copy()])
        sig.append([Sigma])

        # Termination elements
        tm = term(it, b, c, rb, rc, z, g)

        if it == max_it:
            raise TimeoutError("Iterations maxed out")

        if info == 0:
            print('CORRECTOR STEP:\nCurrent primal-dual point: \n x = ', x,
                  '\nlambda = ', y, '\n s = ', s)
            print('Current g: {}\n'.format("%.3f" % g))

#%%

    print_boxed(
        "Found optimal solution of the standard problem at\n x* = {}.\n\n".
        format(x) + "Dual gap: {}\n".format("%2.2e" % g) +
        "Optimal cost: {}\n".format("%10.3f" % z) +
        "Number of iteration: {}".format(it))

    return x, s, u, sig
Ejemplo n.º 9
0
def affine(A, b, c, c_form = 0, w = 10**(-8), max_it = 500, info = 0, ip = 0):
        
    print('\n\tCOMPUTATION OF PRIMAL-DUAL AFFINE SCALING ALGORITHM')
    
    # Algorithm in 4 steps:  
    # 0..Input error checking
    # 1..Find the initial point with Mehrotra's method 
    # 2..obtain the search direction
    # 3..find the largest step   
        
    """ Input error checking & construction in a standard form """
        
    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray) or isinstance(c, np.ndarray)):
       raise Exception('Inputs must be a numpy arrays')
        
    if c_form == 0:
        A, c = stdForm(A, c)    
    r_A, c_A = A.shape
    if not np.linalg.matrix_rank(A) == r_A: # Check full rank matrix: Remove ld rows
        A = A[[i for i in range(r_A) if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))], :]
        r_A = A.shape[0]  # Update no. of rows
    
    """ Initial points: Initial infeasible positive (x,y,s) and initial gap g """
    
    if ip == 0:
        (x, y, s) = sp(A, c, b)
    else:
        (x, y, s) = sp2(A, c, b)        
    g = np.dot(c,x) - np.dot(y,b)    
    
    if info == 0:
        print('\nInitial primal-dual point:\n x = {} \n lambda = {} \n s = {}.\n'.format(x, y, s))    
        print('Dual initial gap: {}.\n'.format("%10.3f"%g))      
    
   #%%
        
    """ Search vector direction """
    
    it = 0        # Num of iterations
    tm = term(it) # Tollerance in the cycle
    
    u = [] # Construct list of info elements 
    u.append([it, g, x, s, b - np.dot(A,x), c - np.dot(A.T, y) - s])
    
    while tm > w:               
        
        """ Pure Newton's method with with normal equations: find the direction vector (y1, s1, x1)"""
        
        S_inv = np.linalg.inv(np.diag(s))           
        W1 = S_inv*np.diag(x)                       # W1 = D = S^(-1)*X    
        W2 = np.dot(A, W1)                          # W      A*S^(-1)*X
        W  = np.dot(W2, A.T)
        L = np.linalg.cholesky(W)                   # CHOLESKY for A* D^2 *A^T
        L_inv = np.linalg.inv(L) 
        
        # RHS of the system        
        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        rxs = - x*s  # Newton step toward x*s = 0
        
        B = rb + np.dot(W2, rc) - np.dot(np.dot(A, S_inv), rxs) #RHS of normal equation form
        z = np.dot(L_inv, B)
        
        # SEARCH DIRECTION:        
        y1 = np.dot(L_inv.T, z)
        s1 = rc - np.dot(A.T, y1)
        x1 = np.dot(S_inv, rxs) - np.dot(W1,s1)
        
        if info == 0:
            print("\tIteration: {}\n".format(it))
            print('Search direction vectors: \n delta_x = {} \n delta_lambda = {} \n delta_s = {}.\n'.format(x1.round(decimals = 3),y1.round(decimals = 3),s1.round(decimals = 3)))
        
        """ Compute the largest step length & increment of the points and the iteration"""
        
        # Largest step length T such that (x, s) + T (x1, s1) is positive
        m = min([(-x[i] / x1[i], i) for i in range(c_A) if x1[i] < 0], default = [1])[0] 
        n = min([(-s[i] / s1[i], i) for i in range(c_A) if s1[i] < 0], default = [1])[0] 
        T = (0.9)*min(m, n) 

        # Update step
        x += min(T,1)*x1            # Current x
        y += min(T,1)*y1            # Current y
        s += min(T,1)*s1            # Current s  
        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        z = np.dot(c, x)            # Current optimal solution
        g = np.abs(z - np.dot(y, b))# Current gap 
        it += 1
        u.append([it, g.copy(), x.copy(), s.copy(), rb.copy(), rc.copy()])       
                
        # Termination elements
        m, n, q = term(it, b, c, rb, rc, z, g)
        tm = max(m, n, q)
        if it == max_it:
            raise TimeoutError("Iterations maxed out") 
        
        if info == 0:
            print('Current point:\n x = {} \n lambda = {} \n s = {}.\n'.format(x, y, s))
            print('Dual next gap: {}.\n'.format("%10.3f"%g))
        
#%%
        
    print_boxed("Found optimal solution of the problem at\n x* = {}.\n".format(x) +
                "Dual gap: {}\n".format("%10.6f"%g) +
                "Optimal cost: {}\n".format("%.8E" %z) +
                "Number of iterations: {}".format(it))
    return x, s, u
Ejemplo n.º 10
0
def mehrotra2(A, b, c, c_form=0, w=10**(-8), max_it=500, info=0, ip=0):

    print('\n\tCOMPUTATION OF MEHROTRA ALGORITHMwith Augmented system\n')

    # Algorithm in 4 steps:
    # 0..Input error checking
    # 1..Find the initial point with Mehrotra's method
    # 2..Predictor step
    # 3..Centering step
    # 4..Corrector step
    """ Input error checking & construction in a standard form """

    if not (isinstance(A, np.ndarray) or isinstance(b, np.ndarray)
            or isinstance(c, np.ndarray)):
        raise Exception('Inputs must be a numpy arrays')

    if c_form == 0:
        A, c = stdForm(A, c)
    r_A, c_A = A.shape
    if not np.linalg.matrix_rank(
            A) == r_A:  # Check full rank matrix:Remove ld rows:
        A = A[[
            i for i in range(r_A)
            if not np.array_equal(np.linalg.qr(A)[1][i, :], np.zeros(c_A))
        ], :]
        r_A = A.shape[0]  # Update no. of rows
    """ Initial points: Initial infeasible positive (x,y,s) and initial gap g """

    if ip == 0:
        (x, y, s) = sp(A, c, b)
    else:
        (x, y, s) = sp2(A, c, b)
    g = np.dot(c, x) - np.dot(y, b)
    if info == 0:

        print('\nInitial primal-dual point:\nx = {} \nlambda = {} \ns = {}'.
              format(x, y, s))
        print('Dual initial g: {}.\n'.format("%10.3f" % g))

    #%%
    """ Predictor step: compute affine direction """
    '''
    Compute affine scaling direction solving Qs = R with an augmented system D^2 = S^{-1}*X 
    with Q a large sparse matrix 
    and R = [rb, rc, - x_0*s_0]
    '''

    it = 0  # Num of iterations
    tm = term(it)  # Tollerance in the cycle

    u = []  # Construct list of info elements
    sig = []
    u.append([it, g, x, s, b - np.dot(A, x), c - np.dot(A.T, y) - s])

    while tm > w:
        if info == 0:
            print("\n\tIteration: {}\n".format(it), end='')

        X_inv = np.linalg.inv(np.diag(x))
        W1 = X_inv * np.diag(s)  # W1 = X^(-1)*S
        T = np.concatenate((np.zeros((r_A, r_A)), A), axis=1)
        U = np.concatenate((A.T, -W1), axis=1)
        V = np.concatenate((T, U), axis=0)

        # RHS of the system, including the minus

        rb = b - np.dot(A, x)
        rc = c - np.dot(A.T, y) - s
        rxs = -x * s

        r = np.hstack((rb, rc - np.dot(X_inv, rxs)))
        o = np.linalg.solve(V, r)

        # SEARCH DIRECTION affine:
        y1 = o[:r_A]
        x1 = o[r_A:c_A + r_A]
        s1 = np.dot(X_inv, rxs) - np.dot(W1, x1)
        if info == 0:

            print(
                "\nPREDICTOR STEP:\nAffine direction:\n({}, {}, {})\n".format(
                    x1, y1, s1))

        #%%
        """ Centering step: compute search direction """

        # Find alfa1_affine and alfa2_affine : maximum steplength along affine-scaling direction
        # Find the minimum( x_{i}/x1_{i} , 1) and the minimum( s_{i}/s1_{i} , 1)

        h = min([(-x[i] / x1[i], i) for i in range(c_A) if x1[i] < 0],
                default=[0])[0]
        k = min([(-s[i] / s1[i], i) for i in range(c_A) if s1[i] < 0],
                default=[0])[0]

        alfa1 = min(h, 1)
        alfa2 = min(k, 1)

        # Set the centering parameter to Sigma = (mi_aff/mi)^{3}
        mi = np.dot(x, s) / c_A  # Duality measure
        mi_af = np.dot(
            x + alfa1 * x1,
            s + alfa2 * s1) / c_A  # Average value of the incremented vectors
        Sigma = (mi_af / mi)**(3)

        # SECOND SEARCH DIRECTION
        Rxs = -x1 * s1 + Sigma * mi * np.ones(
            (c_A))  # RHS of the New system, including minus

        r = np.hstack((np.zeros(r_A), -np.dot(X_inv, Rxs)))
        o = np.linalg.solve(V, r)

        # SEARCH DIRECTION centering-corrector:
        y2 = o[:r_A]
        x2 = o[r_A:c_A + r_A]
        s2 = np.dot(X_inv, Rxs) - np.dot(W1, x2)
        if info == 0:

            print("\nPREDICTOR STEP:\nCC direction:\n({}, {}, {})\n".format(
                x2, y2, s2))

        #%%
        """ Corrector step: compute (x_k+1, lambda_k+1, s_k+1) """

        # The steplength without eta_k
        x2 += x1
        s2 += s1
        y2 += y1
        H = min([(-x[i] / x2[i], i) for i in range(c_A) if x2[i] < 0],
                default=[0])[0]
        K = min([(-s[i] / s2[i], i) for i in range(c_A) if s2[i] < 0],
                default=[0])[0]
        Alfa1 = min(0.99 * H, 1)
        Alfa2 = min(0.99 * K, 1)

        # Compute the final update , using sol2 and Alfa_i

        x += Alfa1 * x2
        y += Alfa2 * y2
        s += Alfa2 * s2
        it += 1
        if it == max_it:
            return x, s, u, sig
            raise TimeoutError("Iterations maxed out")

        # Dual gap c^{T}*x - b^{T}*y = x*s
        z = np.dot(c, x)
        g = np.dot(x, s)
        g1 = z - np.dot(y, b)

        u.append([it, g, x.copy(), s.copy(), rb.copy(), rc.copy()])
        sig.append([Sigma])
        # Termination elements
        m, n, q = term(it, b, c, rb, rc, z, g)
        tm = max(m, n, q)
        if info == 0:

            print('Tollerance: {}.\n'.format("%10.3f" % tm))

            print('CORRECTOR STEP:\nCurrent primal-dual point: \n x = ', x,
                  '\nlambda = ', y, '\n s = ', s)
            print('Current g: {}\nCurrent g1: {}\n'.format(
                "%.3f" % g, "%.3f" % g1))

    print_boxed(
        "Found optimal solution of the standard problem at\n x* = {}.\n\n".
        format(x) + "Dual gap: {}\n".format("%2.2e" % g) +
        "Optimal cost: {}\n".format("%2.8E" % z) +
        "Number of iteration: {}".format(it))

    return x, s, u, sig