Ejemplo n.º 1
0
def maximize_fapx_cvxopt( node, problem, scoop=False):
    '''
    Finds the value of y solving maximize sum(fapx(x)) subject to:
                       constr
                       l <= x <= u
    fapx is calculated by approximating the functions given in fs
    as the concave envelope of the function that is tight, 
    for each coordinate i, at the points in tight[i]
    fs should be a list of tuples containing the function and its derivative
    corresponding to each coordinate of the vector x.
  
    Returns a dict containing the optimal variable y as a list, 
    the optimal value of the approximate objective,
    and the value of sum(f(x)) at x.
    
    scoop = True optionally dumps all problem parameters into a file
    which can be parsed and solved using the scoop second order cone 
    modeling language
    '''
    n = len(node.l);
    l = matrix(node.l); u = matrix(node.u)

    x = problem.variable
    constr = problem.constr
        
    # add box constraints
    box = [x[i]<=u[i] for i in xrange(n)] + [x[i]>=l[i] for i in xrange(n)]

    # find approximation to concave envelope of each function
    (fapx,slopes,offsets,fapxs) = utilities.get_fapx(node.tight,problem.fs,l,u,y=x)
    
    if problem.check_z:
        utilities.check_z(problem,node,fapx,x)
        
    if scoop:
        utilities.scoop(p,node,slopes,offsets)
    
    obj = sum( fapx )
    o = op(obj,constr + box)
    try:
        o.solve(solver = 'glpk')
    except:
        o.solve()
    if not o.status == 'optimal':
        if o.status == 'unknown':
            raise ImportError('Unable to solve subproblem. Please try again after installing cvxopt with glpk binding.')
        else:
            # This node is dead, since the problem is infeasible
            return False
    else:
        # find the difference between the fapx and f for each coordinate i
        fi = numpy.array([problem.fs[i][0](x.value[i]) for i in range(n)])
        fapxi = numpy.array([list(-fun.value())[0] for fun in fapx])
        #if verbose: print 'fi',fi,'fapxi',fapxi
        maxdiff_index = numpy.argmax( fapxi - fi )
        results = {'x': list(x.value), 'fapx': -list(obj.value())[0], 'f': float(sum(fi)), 'maxdiff_index': maxdiff_index}
        return results
Ejemplo n.º 2
0
def maximize_fapx_glpk( node, problem, verbose = False ):
    '''
    Finds the value of y solving maximize sum(fapx(x)) subject to:
                       constr
                       l <= x <= u
    fapx is calculated by approximating the functions given in fs
    as the concave envelope of the function that is tight, 
    for each coordinate i, at the points in tight[i]
    fs should be a list of tuples containing the function and its derivative
    corresponding to each coordinate of the vector x.
  
    Returns a dict containing the optimal variable y as a list, 
    the optimal value of the approximate objective,
    and the value of sum(f(x)) at x.
    '''
    n = len(node.l);
    l = node.l; u = node.u
    
    # find approximation to concave envelope of each function
    (slopes,offsets,fapxs) = utilities.get_fapx(node.tight,problem.fs,l,u)
    
    # verify correctness of concave envelope
    if problem.check_z:
        utilities.check_z(problem,node,fapxs,x)
    
    # formulate concave problem as lp and solve    
    lp = sigopt2pyglpk(slopes = slopes,offsets=offsets,l=l,u=u,**problem.constr)
    lp.simplex()

    # find the difference between the fapx and f for each coordinate i
    xstar = [c.primal for c in lp.cols[:n]]
    fi = numpy.array([problem.fs[i][0](xstar[i]) for i in range(n)])
    fapxi = numpy.array([c.primal for c in lp.cols[n:]])
    maxdiff_index = numpy.argmax( fapxi - fi )
    results = {'x': xstar, 'fapx': lp.obj.value, 'f': float(sum(fi)), 'maxdiff_index': maxdiff_index}
    if verbose: print 'fi',fi,'fapxi',fapxi,results
    return results
Ejemplo n.º 3
0
Archivo: plot.py Proyecto: sl7rf/sigopt
def plot_node(p,n,fn='',ncol=None,annotation=None,coords_to_plot=None,plot_opt = 1,verbose=True):
    '''
    Plots node n and its concave envelope for sigmoidal programming problem p
    
    Each graph represents one variable and its associated objective function (solid line) 
    and concave approximation (dashed line) on the rectangle that the node represents.
    The solution $x^\star_i$ for each variable is given by 
    the x coordinate of the red X.
    The node's rectangle is bounded by the solid grey lines
    and the endpoints of the interval.
    The red line gives the error between the value of the concave approximation $\hat{f}$
    and the sigmoidal function $f$ at the solution $x\star$.
    '''
    if annotation is None: annotation = {}
    if n is None:
        raise ValueError('Node is empty --- cannot plot. \
                          Perhaps the problem is infeasible?')
                          
    if hasattr(n,'x') and n.x:
        plot_opt = plot_opt
    else:
        if plot_opt:
            plot_opt = 0
            if verbose: print 'No solution found for node. Not plotting optimal point.'
            
    tight = [utilities.find_concave_hull(li,ui,fi,[],p.sub_tol) for li,ui,fi in zip(n.l,n.u,p.fs)]
    fapx = utilities.get_fapx(tight, p.fs, n.l, n.u, tol = p.sub_tol)[-1]
    
    if not ncol:
        ncol = math.floor(math.sqrt(len(p.l)))
        nrow = math.ceil(len(p.l)/float(ncol))
    fig = plt.figure()
    if 'subtitle' in annotation.keys():
    	fig.subplots_adjust(hspace = .8)
    if coords_to_plot is None:
        coords_to_plot = range(len(p.l))
    for i in coords_to_plot:
        ax = fig.add_subplot(nrow,ncol,i+1)
        if 'subtitle' in annotation:
            if annotation['subtitle'] == 'numbered':    
                ax.title('%d'%i)
            else:
                ax.set_title(annotation['subtitle'][i])
                
        # plot f
        x = list(numpy.linspace(p.l[i],p.u[i],300))
        ax.plot(x,[p.fs[i][0](xi) for xi in x],'b-')

        # plot fapx, only over the node n
        nx = list(numpy.linspace(n.l[i],n.u[i],300))
        fapxi=[]
        for xi in nx:
            fapxi.append(fapx[i](xi))
        ax.plot(nx,fapxi,'c--')

        # plot node boundary
        if n.l[i]>p.l[i]: 
            ax.axvline(x=n.l[i], linewidth=.5, color = 'grey')
        if n.u[i]<p.u[i]: 
            ax.axvline(x=n.u[i], linewidth=.5, color = 'grey')

        # plot optimal point
        if plot_opt:
            ax.plot([n.x[i]],[p.fs[i][0](n.x[i])],'rx')            
            ax.plot([n.x[i]],[fapx[i](n.x[i])],'rx')   
            # plot error
            ax.vlines(n.x[i],fapx[i](n.x[i]),p.fs[i][0](n.x[i]),'r')
        
        ax.margins(.05)
        ax.axis('off')
        #ax.axis('equal')

    if not fn:
        fn = p.name+'_best_node.eps'
    if verbose:
        print 'Saving figure in',fn
    fig.savefig(fn)
    return fig