Exemple #1
0
def scp(p,bad_constr,sol):
    """
    Description: Sequential convex programming
    algorithm. Solve program p and try to 
    enforce equality on the bad constraints.
    Argument p: cvxpy_program is assumed to be in
    expanded and equivalent format.
    Argument bad_constr: List of nonconvex
    constraints, also in expanded and equivalent
    format.
    Argument sol: Solution of relaxation.
    """

    # Quit if program is linear
    if(len(bad_constr) == 0):
        if(not p.options['quiet']):
            print 'Tightening not needed'
        return True

    # Get parameters
    tight_tol = p.options['SCP_ALG']['tight tol']
    starting_lambda = p.options['SCP_ALG']['starting lambda'] 
    max_scp_iter = p.options['SCP_ALG']['max scp iter']
    lambda_multiplier = p.options['SCP_ALG']['lambda multiplier']
    max_lambda = p.options['SCP_ALG']['max lambda']
    top_residual = p.options['SCP_ALG']['top residual']

    # Construct slacks
    slacks = [abs(c.left-c.right) for c in bad_constr]

    # Print header
    if(not p.options['quiet']):
        print 'Iter\t:',
        print 'Max Slack\t:',
        print 'Objective\t:',
        print 'Solver Status\t:',
        print 'Pres\t\t:',
        print 'Dres\t\t:',
        print 'Lambda Max/Min'

    # SCP Loop
    lam = starting_lambda*np.ones(len(slacks))
    for i in range(0,max_scp_iter,1):

        # Calculate max slack
        max_slack = max(map(lambda x:x.get_value(), slacks))

        # Quit if status is primal infeasible
        if(sol['status'] == 'primal infeasible'):
            if(not p.options['quiet']):
                print 'Unable to tighten: Problem became infeasible'
            return False

        # Check if dual infeasible
        if(sol['status'] == 'dual infeasible'):
            sol['status'] = 'dual inf'
            sol['primal infeasibility'] = np.NaN
            sol['dual infeasibility'] = np.NaN

        # Print values
        if(not p.options['quiet']):
            print '%d\t:' %i,
            print '%.3e\t:' %max_slack,
            print '%.3e\t:' %p.obj.get_value(),
            print '   '+sol['status']+'\t:',
            if(sol['primal infeasibility'] is not np.NaN):
                print '%.3e\t:' %sol['primal infeasibility'],
            else:
                print '%.3e\t\t:' %sol['primal infeasibility'],
            if(sol['dual infeasibility'] is not np.NaN):
                print '%.3e\t:' %sol['dual infeasibility'],
            else:
                print '%.3e\t\t:' %sol['dual infeasibility'],
            print '(%.1e,%.1e)' %(np.max(lam),np.min(lam))

        # Quit if max slack is small
        if(max_slack < tight_tol and
           sol['status'] == 'optimal'):
            if(not p.options['quiet']):
                print 'Tightening successful'
            return True

        # Quit if residual is too large
        if(sol['primal infeasibility'] >= top_residual or
           sol['dual infeasibility'] >= top_residual):
            if(not p.options['quiet']):
                print 'Unable to tighten: Residuals are too large'
            return False

        # Linearize slacks
        linear_slacks = []
        for c in bad_constr:
            fn = c.left.item
            args = c.left.children
            right = c.right
            line = fn._linearize(args,right)
            linear_slacks += [line]

        # Add linearized slacks to objective
        sum_lin_slacks = 0.0
        for j in range(0,len(slacks),1):
            sum_lin_slacks += lam[j]*linear_slacks[j]
        if(p.action == MINIMIZE):
            new_obj = p.obj + sum_lin_slacks
        else:
            new_obj = p.obj - sum_lin_slacks
        new_t0, obj_constr = expand(new_obj)    
        new_p = prog((p.action,new_t0), obj_constr+p.constr,[],p.options)

        # Solve new problem
        sol = solve_convex(new_p,'scp')

        # Update lambdas
        for j in range(0,len(slacks),1):
            if(slacks[j].get_value() >= tight_tol):
                if(lam[j] < max_lambda):
                    lam[j] = lam[j]*lambda_multiplier

    # Maxiters reached
    if(not p.options['quiet']):
        print 'Unable to tighten: Maximum iterations reached'
    if(sol['status'] == 'optimal'):
        return True
    else:
        return False
Exemple #2
0
def solve_prog(p):
    """
    Description
    -----------
    Solve optimization program.

    Arguments
    ---------
    p: cvxpy_program
    """

    # Reset variable counter
    var_reset()

    # Check parameters
    if (len(p.get_params()) != 0):
        if (not p.options['quiet']):
            print 'Error: Parameters present'
        return np.NaN, np.NaN

    # Original
    if (p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*         Original         *'
        print '****************************'
        p.show()

    # Expanded
    p_expanded = p._get_expanded()
    if (p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*         Expanded         *'
        print '****************************'
        p_expanded.show()

    # Equivalent
    p_equivalent = p_expanded._get_equivalent()
    if (p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*       Equivalent         *'
        print '****************************'
        p_equivalent.show()

    # Nonconvex constraints
    bad_constr = p_equivalent.constr._get_nonconvex()
    if (p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*  Nonconvex Constraints   *'
        print '****************************\n'
        print bad_constr

    # Convex Relaxation
    p_cvx_relaxation = p_equivalent._get_cvx_relaxation()
    if (p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*    Convex Relaxation     *'
        print '****************************'
        p_cvx_relaxation.show()

    # Solve convex relaxation
    if (not p.options['quiet']):
        print '\nSolving convex relaxation ...'
    sol = solve_convex(p_cvx_relaxation, 'rel')
    lagrange_mul_eq = matrix(sol['y'])
    if (not p.options['quiet']):
        print 'Relaxation status: ', sol['status']

    # Relaxation status: primal infeasible
    if (sol['status'] == 'primal infeasible'):
        if (not p.options['quiet']):
            print 'Original program is primal infeasible'
        if (p.action == MINIMIZE):
            return np.inf, lagrange_mul_eq
        else:
            return -np.inf, lagrange_mul_eq

    # Relaxation status: uknown
    elif (sol['status'] == 'unknown'):
        relaxation_obj = None

    # Relaxation status: dual infeasible
    elif (sol['status'] == 'dual infeasible'):
        if (p.action == MINIMIZE):
            relaxation_obj = -np.inf
        else:
            relaxation_obj = np.inf

    # Relaxacion status: optimal
    else:
        relaxation_obj = p_cvx_relaxation.obj.get_value()

    # Report max slack
    if (len(bad_constr) != 0 and not p.options['quiet']):
        print 'Max Slack: ',
        print max(
            map(lambda x: x.get_value(),
                [abs(c.left - c.right) for c in bad_constr]))

    # Tighten
    if (p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*    Tightening Stage      *'
        print '****************************'
    elif (not p.options['quiet']):
        print '\nAttempting tightening ...'
    valid_scp = scp(p_cvx_relaxation, bad_constr, sol)
    if (not valid_scp):
        return np.NaN, np.NaN

    # Prepare results
    if (len(bad_constr) == 0):
        obj = relaxation_obj
    else:
        obj = p.obj.get_value()
    if (p.action == MINIMIZE):
        bound_str = 'Lower Bound'
        if (relaxation_obj != None):
            bound = np.min([relaxation_obj, obj])
            gap = np.max([obj - relaxation_obj, 0.0])
    else:
        bound_str = 'Upper Bound'
        if (relaxation_obj != None):
            bound = np.max([relaxation_obj, obj])
            gap = np.max([relaxation_obj - obj, 0.0])

    # Show results
    if (p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*        Results           *'
        print '****************************'
    elif (not p.options['quiet']):
        print '\nResults'
    if (not p.options['quiet']):
        print 'Objective =\t%.5e' % obj
        if (relaxation_obj != None):
            print bound_str + ' =\t%.5e' % bound
            print 'Gap =\t\t%.5e' % gap
        else:
            print bound_str + ' =\tUnknown'
            print 'Gap =\t\tUnknown'
        if (len(bad_constr) != 0):
            ms = max(
                map(lambda x: x.get_value(),
                    [abs(c.left - c.right) for c in bad_constr]))
            print 'Max Slack =\t%.5e' % ms

    # Return objective and dual var
    return obj, lagrange_mul_eq
def solve_prog(p):
    """
    Description
    -----------
    Solve optimization program.

    Arguments
    ---------
    p: cvxpy_program
    """

    # Reset variable counter
    var_reset()

    # Check parameters
    if(len(p.get_params()) != 0):
        if(not p.options['quiet']):
            print 'Error: Parameters present'
        return np.NaN,np.NaN

    # Original
    if(p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*         Original         *'
        print '****************************'
        p.show()

    # Expanded
    p_expanded = p._get_expanded()
    if(p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*         Expanded         *'
        print '****************************'
        p_expanded.show()

    # Equivalent
    p_equivalent = p_expanded._get_equivalent()
    if(p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*       Equivalent         *'
        print '****************************'
        p_equivalent.show()

    # Nonconvex constraints
    bad_constr = p_equivalent.constr._get_nonconvex()
    if(p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*  Nonconvex Constraints   *'
        print '****************************\n'
        print bad_constr

    # Convex Relaxation
    p_cvx_relaxation = p_equivalent._get_cvx_relaxation()
    if(p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*    Convex Relaxation     *'
        print '****************************'
        p_cvx_relaxation.show()

    # Solve convex relaxation
    if(not p.options['quiet']):
        print '\nSolving convex relaxation ...'
    sol = solve_convex(p_cvx_relaxation,'rel')
    lagrange_mul_eq = matrix(sol['y'])
    if(not p.options['quiet']):
        print 'Relaxation status: ',sol['status']
    
    # Relaxation status: primal infeasible
    if(sol['status'] == 'primal infeasible'):
        if(not p.options['quiet']):
            print 'Original program is primal infeasible'
        if(p.action == MINIMIZE):
            return np.inf,lagrange_mul_eq
        else:
            return -np.inf,lagrange_mul_eq
        
    # Relaxation status: uknown
    elif(sol['status'] == 'unknown'):
        relaxation_obj = None

    # Relaxation status: dual infeasible
    elif(sol['status'] == 'dual infeasible'):
        if(p.action == MINIMIZE):
            relaxation_obj = -np.inf
        else:
            relaxation_obj = np.inf

    # Relaxacion status: optimal
    else:
        relaxation_obj = p_cvx_relaxation.obj.get_value()

    # Report max slack
    if(len(bad_constr) != 0 and not p.options['quiet']):
        print 'Max Slack: ',
        print max(map(lambda x:x.get_value(),
                      [abs(c.left-c.right) for c in bad_constr]))

    # Tighten
    if(p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*    Tightening Stage      *'
        print '****************************'
    elif(not p.options['quiet']):
        print '\nAttempting tightening ...'
    valid_scp = scp(p_cvx_relaxation,bad_constr,sol)
    if(not valid_scp):
        return np.NaN,np.NaN

    # Prepare results
    if(len(bad_constr) == 0):
        obj = relaxation_obj
    else:
        obj = p.obj.get_value()
    if(p.action == MINIMIZE):
        bound_str = 'Lower Bound'
        if(relaxation_obj != None):
            bound = np.min([relaxation_obj,obj])
            gap = np.max([obj-relaxation_obj,0.0])
    else:
        bound_str = 'Upper Bound'
        if(relaxation_obj != None):
            bound = np.max([relaxation_obj,obj])
            gap = np.max([relaxation_obj-obj,0.0])

    # Show results
    if(p.options['show steps'] and not p.options['quiet']):
        print '\n'
        print '****************************'
        print '*        Results           *'
        print '****************************'
    elif(not p.options['quiet']):
        print '\nResults'
    if(not p.options['quiet']):
        print 'Objective =\t%.5e' %obj
        if(relaxation_obj != None):
            print bound_str+' =\t%.5e' %bound
            print 'Gap =\t\t%.5e' %gap
        else:
            print bound_str+' =\tUnknown'
            print 'Gap =\t\tUnknown'
        if(len(bad_constr) != 0):
            ms = max(map(lambda x:x.get_value(),
                         [abs(c.left-c.right) for c in bad_constr]))
            print 'Max Slack =\t%.5e' %ms

    # Return objective and dual var
    return obj,lagrange_mul_eq