def main(argv): t, y = read_data(argv[0]) degree = int(argv[1]) A = +matrix([[t**k] for k in xrange(degree + 1)]) c = +y gels(A, c) print c[:degree + 1] plot_poly(t, y, c, degree)
def main(argv): t, y = read_data(argv[0]) degree = int(argv[1]) A = +matrix( [[t ** k] for k in xrange(degree + 1)] ) c = +y gels(A, c) print c[:degree + 1] plot_poly(t, y, c, degree)
def setUp(self): """ Use cvxopt to get ground truth values """ from cvxopt import lapack, solvers, matrix, spdiag, log, div, normal, setseed from cvxopt.modeling import variable, op, max, sum solvers.options['show_progress'] = 0 setseed() m, n = 100, 30 A = normal(m, n) b = normal(m, 1) b /= (1.1 * max(abs(b))) self.m, self.n, self.A, self.b = m, n, A, b # l1 approximation # minimize || A*x + b ||_1 x = variable(n) op(sum(abs(A * x + b))).solve() self.x1 = x.value # l2 approximation # minimize || A*x + b ||_2 bprime = -matrix(b) Aprime = matrix(A) lapack.gels(Aprime, bprime) self.x2 = bprime[:n] # Deadzone approximation # minimize sum(max(abs(A*x+b)-0.5, 0.0)) x = variable(n) dzop = op(sum(max(abs(A * x + b) - 0.5, 0.0))) dzop.solve() self.obj_dz = sum( np.max([np.abs(A * x.value + b) - 0.5, np.zeros((m, 1))], axis=0)) # Log barrier # minimize -sum (log ( 1.0 - (A*x+b)**2)) def F(x=None, z=None): if x is None: return 0, matrix(0.0, (n, 1)) y = A * x + b if max(abs(y)) >= 1.0: return None f = -sum(log(1.0 - y**2)) gradf = 2.0 * A.T * div(y, 1 - y**2) if z is None: return f, gradf.T H = A.T * spdiag(2.0 * z[0] * div(1.0 + y**2, (1.0 - y**2)**2)) * A return f, gradf.T, H self.cxlb = solvers.cp(F)['x']
def l1(P, q): m, n = P.size c = matrix(n*[0.0] + m*[1.0]) h = matrix([q, -q]) def Fi(x, y, alpha = 1.0, beta = 0.0, trans = 'N'): if trans == 'N': u = P*x[:n] y[:m] = alpha * ( u - x[n:]) + beta*y[:m] y[m:] = alpha * (-u - x[n:]) + beta*y[m:] else: y[:n] = alpha * P.T * (x[:m] - x[m:]) + beta*y[:n] y[n:] = -alpha * (x[:m] + x[m:]) + beta*y[n:] def Fkkt(W): d1, d2 = W['d'][:m], W['d'][m:] D = 4*(d1**2 + d2**2)**-1 A = P.T * spdiag(D) * P lapack.potrf(A) def f(x, y, z): x[:n] += P.T * ( mul( div(d2**2 - d1**2, d1**2 + d2**2), x[n:]) + mul( .5*D, z[:m]-z[m:] ) ) lapack.potrs(A, x) u = P*x[:n] x[n:] = div( x[n:] - div(z[:m], d1**2) - div(z[m:], d2**2) + mul(d1**-2 - d2**-2, u), d1**-2 + d2**-2 ) z[:m] = div(u-x[n:]-z[:m], d1) z[m:] = div(-u-x[n:]-z[m:], d2) return f uls = +q lapack.gels(+P, uls) rls = P*uls[:n] - q x0 = matrix( [uls[:n], 1.1*abs(rls)] ) s0 = +h Fi(x0, s0, alpha=-1, beta=1) if max(abs(rls)) > 1e-10: w = .9/max(abs(rls)) * rls else: w = matrix(0.0, (m,1)) z0 = matrix([.5*(1+w), .5*(1-w)]) dims = {'l': 2*m, 'q': [], 's': []} sol = solvers.conelp(c, Fi, h, dims, kktsolver = Fkkt, primalstart={'x': x0, 's': s0}, dualstart={'z': z0}) return sol['x'][:n]
def fit_polynomial(X, Y, d): m = len(X) assert(len(Y) == m) A = matrix( [[X**k] for k in xrange(d)]) # make a deep copy of Y xls = +Y # general least-squares: minimize ||A*x - y||_2 lapack.gels(+A,xls) xls = xls[:d] return xls
def fit_polynomial(X, Y, d): m = len(X) assert (len(Y) == m) A = matrix([[X**k] for k in xrange(d)]) # make a deep copy of Y xls = +Y # general least-squares: minimize ||A*x - y||_2 lapack.gels(+A, xls) xls = xls[:d] return xls
def setUp(self): """ Use cvxopt to get ground truth values """ from cvxopt import lapack,solvers,matrix,spdiag,log,div,normal,setseed from cvxopt.modeling import variable,op,max,sum solvers.options['show_progress'] = 0 setseed() m,n = 100,30 A = normal(m,n) b = normal(m,1) b /= (1.1*max(abs(b))) self.m,self.n,self.A,self.b = m,n,A,b # l1 approximation # minimize || A*x + b ||_1 x = variable(n) op(sum(abs(A*x+b))).solve() self.x1 = x.value # l2 approximation # minimize || A*x + b ||_2 bprime = -matrix(b) Aprime = matrix(A) lapack.gels(Aprime,bprime) self.x2 = bprime[:n] # Deadzone approximation # minimize sum(max(abs(A*x+b)-0.5, 0.0)) x = variable(n) dzop = op(sum(max(abs(A*x+b)-0.5, 0.0))) dzop.solve() self.obj_dz = sum(np.max([np.abs(A*x.value+b)-0.5,np.zeros((m,1))],axis=0)) # Log barrier # minimize -sum (log ( 1.0 - (A*x+b)**2)) def F(x=None, z=None): if x is None: return 0, matrix(0.0,(n,1)) y = A*x+b if max(abs(y)) >= 1.0: return None f = -sum(log(1.0 - y**2)) gradf = 2.0 * A.T * div(y, 1-y**2) if z is None: return f, gradf.T H = A.T * spdiag(2.0*z[0]*div(1.0+y**2,(1.0-y**2)**2))*A return f,gradf.T,H self.cxlb = solvers.cp(F)['x']
def leastsquares(A, B): """Finds the least-squares approximate solution X, which minimizes ||AX - B||_fro. A must be full rank.""" if not (isinstance(A, (matrix, spmatrix)) and isinstance(B, (matrix, spmatrix))): raise TypeError('both arguments must be matrices') if rows(A) < cols(A): raise DimError('A must be skinny') if rows(B) != rows(A): raise DimError('rows(B) must equal rows(A)') X = matrix(B) lapack.gels(matrix(A), X) return X
def leastnorm(A, B): """Finds the least-norm X which minimizes ||X||_fro while satisfying AX == B. A must be full rank.""" if not (isinstance(A, (matrix, spmatrix)) and isinstance(B, (matrix, spmatrix))): raise TypeError('both arguments must be matrices') if rows(A) > cols(A): raise DimError('A must be fat') if rows(B) != rows(A): raise DimError('rows(B) must equal rows(A)') # Pad X to make room for the solution. X = concatvert(B, zeros(cols(A) - rows(B), cols(B), full=True)) lapack.gels(matrix(A), X) return X
nbins = 100 bins = [-1.5 + 3.0 / (nbins - 1) * k for k in xrange(nbins)] pylab.hist(A * x1 + b, numpy.array(bins)) nopts = 200 xs = -1.5 + 3.0 / (nopts - 1) * matrix(range(nopts)) pylab.plot(xs, (35.0 / 1.5) * abs(xs), 'g-') pylab.axis([-1.5, 1.5, 0, 40]) pylab.ylabel('l1') pylab.title('Penalty function approximation (fig. 6.2)') # l2 approximation # # minimize || A*x + b ||_2 x = matrix(0.0, (m, 1)) lapack.gels(+A, x) x2 = x[:n] pylab.subplot(412) pylab.hist(A * x2 + b, numpy.array(bins)) pylab.plot(xs, (8.0 / 1.5**2) * xs**2, 'g-') pylab.ylabel('l2') pylab.axis([-1.5, 1.5, 0, 10]) # Deadzone approximation # # minimize sum(max(abs(A*x+b)-0.5, 0.0)) x = variable(n) op(sum(max(abs(A * x + b) - 0.5, 0.0))).solve() xdz = x.value
x[n:] = div( x[n:] - mul(d1, z[:n]) - mul(d2, z[n:]), d1+d2 )\ - mul( d3, x[:n] ) # z[:n] = D1^1/2 * ( x[:n] - x[n:] - bz[:n] ) # z[n:] = D2^1/2 * ( -x[:n] - x[n:] - bz[n:] ). z[:n] = mul(W['di'][:n], x[:n] - x[n:] - z[:n]) z[n:] = mul(W['di'][n:], -x[:n] - x[n:] - z[n:]) return g x = solvers.coneqp(P, q, G, h, kktsolver=Fkkt)['x'][:n] I = [k for k in range(n) if abs(x[k]) > 1e-2] xls = +y lapack.gels(A[:, I], xls) ybp = A[:, I] * xls[:len(I)] print("Sparse basis contains %d basis functions." % len(I)) print("Relative RMS error = %.1e." % (blas.nrm2(ybp - y) / blas.nrm2(y))) if pylab_installed: pylab.figure(2, facecolor='w') pylab.subplot(211) pylab.plot(ts, y, '-', ts, ybp, 'r--') pylab.xlabel('t') pylab.ylabel('y(t), yhat(t)') pylab.axis([0, 1, -1.5, 1.5]) pylab.title('Signal and basis pursuit approximation (fig. 6.22)') pylab.subplot(212) pylab.plot(ts, y - ybp, '-')
# constant h[k][2, :2] = B[k, :] h[k][:2, 2] = B[k, :].T sol = solvers.sdp(c, Gs=G, hs=h) X1 = matrix(sol['x'][L:], (N, 2)) # Quadratic placement: h(u) = u^2. # # minimize sum (A*X[:,0] + B[:,0])**2 + (A*X[:,1] + B[:,1])**2 # # with variable X (Nx2). Bc = -B lapack.gels(+A1, Bc) X2 = Bc[:N, :] # Fourth order placement: h(u) = u^4 # # minimize g(AA*x + BB) # # where AA = [A1, 0; 0, A1] # BB = [B[:,0]; B[:,1]] # x = [X[:,0]; X[:,1]] # g(u,v) = sum((uk.^2 + vk.^2).^2) # # with variables x (2*N). AA = matrix(0.0, (2 * L, 2 * N)) AA[:L, :N], AA[L:, N:] = A1, A1
def l1(P, q): """ Returns the solution u of the ell-1 approximation problem (primal) minimize ||P*u - q||_1 (dual) maximize q'*w subject to P'*w = 0 ||w||_infty <= 1. """ m, n = P.size # Solve equivalent LP # # minimize [0; 1]' * [u; v] # subject to [P, -I; -P, -I] * [u; v] <= [q; -q] # # maximize -[q; -q]' * z # subject to [P', -P']*z = 0 # [-I, -I]*z + 1 = 0 # z >= 0 c = matrix(n * [0.0] + m * [1.0]) h = matrix([q, -q]) def Fi(x, y, alpha=1.0, beta=0.0, trans='N'): if trans == 'N': # y := alpha * [P, -I; -P, -I] * x + beta*y u = P * x[:n] y[:m] = alpha * (u - x[n:]) + beta * y[:m] y[m:] = alpha * (-u - x[n:]) + beta * y[m:] else: # y := alpha * [P', -P'; -I, -I] * x + beta*y y[:n] = alpha * P.T * (x[:m] - x[m:]) + beta * y[:n] y[n:] = -alpha * (x[:m] + x[m:]) + beta * y[n:] def Fkkt(W): # Returns a function f(x, y, z) that solves # # [ 0 0 P' -P' ] [ x[:n] ] [ bx[:n] ] # [ 0 0 -I -I ] [ x[n:] ] [ bx[n:] ] # [ P -I -W1^2 0 ] [ z[:m] ] = [ bz[:m] ] # [-P -I 0 -W2 ] [ z[m:] ] [ bz[m:] ] # # On entry bx, bz are stored in x, z. # On exit x, z contain the solution, with z scaled (W['di'] .* z is # returned instead of z). d1, d2 = W['d'][:m], W['d'][m:] D = 4 * (d1**2 + d2**2)**-1 A = P.T * spdiag(D) * P lapack.potrf(A) def f(x, y, z): x[:n] += P.T * (mul(div(d2**2 - d1**2, d1**2 + d2**2), x[n:]) + mul(.5 * D, z[:m] - z[m:])) lapack.potrs(A, x) u = P * x[:n] x[n:] = div( x[n:] - div(z[:m], d1**2) - div(z[m:], d2**2) + mul(d1**-2 - d2**-2, u), d1**-2 + d2**-2) z[:m] = div(u - x[n:] - z[:m], d1) z[m:] = div(-u - x[n:] - z[m:], d2) return f # Initial primal and dual points from least-squares solution. # uls minimizes ||P*u-q||_2; rls is the LS residual. uls = +q lapack.gels(+P, uls) rls = P * uls[:n] - q # x0 = [ uls; 1.1*abs(rls) ]; s0 = [q;-q] - [P,-I; -P,-I] * x0 x0 = matrix([uls[:n], 1.1 * abs(rls)]) s0 = +h Fi(x0, s0, alpha=-1, beta=1) # z0 = [ (1+w)/2; (1-w)/2 ] where w = (.9/||rls||_inf) * rls # if rls is nonzero and w = 0 otherwise. if max(abs(rls)) > 1e-10: w = .9 / max(abs(rls)) * rls else: w = matrix(0.0, (m, 1)) z0 = matrix([.5 * (1 + w), .5 * (1 - w)]) dims = {'l': 2 * m, 'q': [], 's': []} sol = solvers.conelp(c, Fi, h, dims, kktsolver=Fkkt, primalstart={ 'x': x0, 's': s0 }, dualstart={'z': z0}) return sol['x'][:n]
def sysid(y, u, vsig, svth = None): """ System identification using the subspace method and nuclear norm optimization. Estimate a linear time-invariant state-space model given inputs and outputs. The algorithm is described in [1]. INPUT y 'd' matrix of size (p, N). y are the measured outputs, p is the number of outputs, and N is the number of data points measured. u 'd' matrix of size (m, N). u are the inputs, m is the number of inputs, and N is the number of data points. vsig a weighting parameter in the nuclear norm optimization, its value is approximately the 1-sigma output noise level svth an optional parameter, if specified, the model order is determined as the number of singular values greater than svth times the maximum singular value. The default value is 1E-3 OUTPUT sol a dictionary with the following words -- 'A', 'B', 'C', 'D' are the state-space matrices -- 'svN', the original singular values of the Hankel matrix -- 'sv', the optimized singular values of the Hankel matrix -- 'x0', the initial state x(0) -- 'n', the model order [1] Zhang Liu and Lieven Vandenberghe. "Interior-point method for nuclear norm approximation with application to system identification." """ m, N, p = u.size[0], u.size[1], y.size[0] if y.size[1] != N: raise ValueError, "y and u must have the same length" # Y = G*X + H*U + V, Y has size a x b, U has size c x b, Un has b x d r = min(int(30/p),int((N+1.0)/(p+m+1)+1.0)) a = r*p c = r*m b = N-r+1 d = b-c # construct Hankel matrix Y Y = Hankel(y,r,b,p=p,q=1) # construct Hankel matrix U U = Hankel(u,r,b,p=m,q=1) # compute Un = null(U) and YUn = Y*Un Vt = matrix(0.0,(b,b)) Stemp = matrix(0.0,(c,1)) Un = matrix(0.0,(b,d)) YUn = matrix(0.0,(a,d)) lapack.gesvd(U,Stemp,jobvt='A',Vt=Vt) Un[:,:] = Vt.T[:,c:] blas.gemm(Y,Un,YUn) # compute original singular values svN = matrix(0.0,(min(a,d),1)) lapack.gesvd(YUn,svN) # variable, [y(1);...;y(N)] # form the coefficient matrices for the nuclear norm optimization # minimize | Yh * Un |_* + alpha * | y - yh |_F AA = Hankel_basis(r,b,p=p,q=1) A = matrix(0.0,(a*d,p*N)) temp = spmatrix([],[],[],(a,b),'d') temp2 = matrix(0.0,(a,d)) for ii in xrange(p*N): temp[:] = AA[:,ii] base.gemm(temp,Un,temp2) A[:,ii] = temp2[:] B = matrix(0.0,(a,d)) # flip the matrix if columns is more than rows if a < d: Itrans = [i+j*a for i in xrange(a) for j in xrange(d)] B[:] = B[Itrans] B.size = (d,a) for ii in xrange(p*N): A[:,ii] = A[Itrans,ii] # regularized term x0 = y[:] Qd = matrix(2.0*svN[0]/p/N/(vsig**2),(p*N,1)) # solve the nuclear norm optimization sol = nrmapp(A, B, C = base.spdiag(Qd), d = -base.mul(x0, Qd)) status = sol['status'] x = sol['x'] # construct YhUn and take the svd YhUn = matrix(B) blas.gemv(A,x,YhUn,beta=1.0) if a < d: YhUn = YhUn.T Uh = matrix(0.0,(a,d)) sv = matrix(0.0,(d,1)) lapack.gesvd(YhUn,sv,jobu='S',U=Uh) # determine model order if svth is None: svth = 1E-3 svthn = sv[0]*svth n=1 while sv[n] >= svthn and n < 10: n=n+1 # estimate A, C Uhn = Uh[:,:n] for ii in xrange(n): blas.scal(sv[ii],Uhn,n=a,offset=ii*a) syseC = Uhn[:p,:] Als = Uhn[:-p,:] Bls = Uhn[p:,:] lapack.gels(Als,Bls) syseA = Bls[:n,:] Als[:,:] = Uhn[:-p,:] Bls[:,:] = Uhn[p:,:] blas.gemm(Als,syseA,Bls,beta=-1.0) Aerr = blas.nrm2(Bls) # stabilize A Sc = matrix(0.0,(n,n),'z') w = matrix(0.0, (n,1), 'z') Vs = matrix(0.0, (n,n), 'z') def F(w): return (abs(w) < 1.0) Sc[:,:] = syseA ns = lapack.gees(Sc, w, Vs, select = F) while ns < n: #print "stabilize matrix A" w[ns:] = w[ns:]**-1 Sc[::n+1] = w Sc = Vs*Sc*Vs.H syseA[:,:] = Sc.real() Sc[:,:] = syseA ns = lapack.gees(Sc, w, Vs, select = F) # estimate B,D,x0 stored in vector [x0; vec(D); vec(B)] F1 = matrix(0.0,(p*N,n)) F1[:p,:] = syseC for ii in xrange(1,N): F1[ii*p:(ii+1)*p,:] = F1[(ii-1)*p:ii*p,:]*syseA F2 = matrix(0.0,(p*N,p*m)) ut = u.T for ii in xrange(p): F2[ii::p,ii::p] = ut F3 = matrix(0.0,(p*N,n*m)) F3t = matrix(0.0,(p*(N-1),n*m)) for ii in xrange(1,N): for jj in xrange(p): for kk in xrange(n): F3t[jj:jj+(N-ii)*p:p,kk::n] = ut[:N-ii,:]*F1[(ii-1)*p+jj,kk] F3[ii*p:,:] = F3[ii*p:,:] + F3t[:(N-ii)*p,:] F = matrix([[F1],[F2],[F3]]) yls = y[:] Sls = matrix(0.0,(F.size[1],1)) Uls = matrix(0.0,(F.size[0],F.size[1])) Vtls = matrix(0.0,(F.size[1],F.size[1])) lapack.gesvd(F, Sls, jobu='S', jobvt='S', U=Uls, Vt=Vtls) Frank=len([ii for ii in xrange(Sls.size[0]) if Sls[ii] >= 1E-6]) #print 'Rank deficiency = ', F.size[1] - Frank xx = matrix(0.0,(F.size[1],1)) xx[:Frank] = Uls.T[:Frank,:] * yls xx[:Frank] = base.mul(xx[:Frank],Sls[:Frank]**-1) xx[:] = Vtls.T[:,:Frank]*xx[:Frank] blas.gemv(F,xx,yls,beta=-1.0) xxerr = blas.nrm2(yls) x0 = xx[:n] syseD = xx[n:n+p*m] syseD.size = (p,m) syseB = xx[n+p*m:] syseB.size = (n,m) return {'A': syseA, 'B': syseB, 'C': syseC, 'D': syseD, 'svN': svN, 'sv': \ sv, 'x0': x0, 'n': n, 'Aerr': Aerr, 'xxerr': xxerr}
def feasibleStartingValue(G, h, allowQuasiBoundary=False, isMin=True): ''' Find a feasible starting value given a set of inequalities Gx<=h Parameters ---------- G: array like matrix G in Gx<=h h: array like vector h in Gx<=h allowQuasiBoundary: bool, optional whether we allow points to sit on the hyperplanes. This also acts as a mechanism to accommodate machine precision problem isMin: bool, optional whether we want to solve the problem min x s.t. Gx<=h or max x s.t. Gx>=h Returns ------- x: a feasible point ''' # equal weight for each dimension p = len(G[0, :]) if isMin: x0 = matrix(numpy.ones(p)) else: x0 = matrix(-numpy.ones(p)) # change the type to make it suitable for cvxopt if type(G) is numpy.ndarray: G = matrix(G) if type(h) is numpy.ndarray: h = matrix(h) # aka do we allow for some numerical error if allowQuasiBoundary == False: h = h - numpy.sqrt(numpy.finfo(numpy.float).eps) # find our feasible point h1 = copy.deepcopy(h) # Note that lapack.gels expects A to be full rank lapack.gels(+G, h1) x = h1[:p] # test feasibility if feasiblePoint(numpy.array(x), numpy.array(G), numpy.array(h), allowQuasiBoundary): # print "YES!, our shape is convex" return numpy.array(x) else: # print "Solving lp to get starting value" sol = solvers.conelp(x0, G, h) # check if see if the solution exist if sol['status'] == "optimal": pass elif sol['status'] == "primal infeasible": raise Exception( "The interior defined by the set of inequalities is empty") elif sol['status'] == "dual infeasible": raise Exception("The interior is unbounded") else: if feasiblePoint(numpy.array(sol['x']), numpy.array(G), numpy.array(h), allowQuasiBoundary): pass else: raise Exception("Something went wrong, I have no idea") return numpy.array(sol['x'])
pylab.hist( A*x1+b , numpy.array(bins)) nopts = 200 xs = -1.5 + 3.0/(nopts-1) * matrix(list(range(nopts))) pylab.plot(xs, (35.0/1.5) * abs(xs), 'g-') pylab.axis([-1.5, 1.5, 0, 40]) pylab.ylabel('l1') pylab.title('Penalty function approximation (fig. 6.2)') # l2 approximation # # minimize || A*x + b ||_2 x = matrix(0.0, (m,1)) lapack.gels(+A, x) x2 = x[:n] if pylab_installed: pylab.subplot(412) pylab.hist(A*x2+b, numpy.array(bins)) pylab.plot(xs, (8.0/1.5**2) * xs**2 , 'g-') pylab.ylabel('l2') pylab.axis([-1.5, 1.5, 0, 10]) # Deadzone approximation # # minimize sum(max(abs(A*x+b)-0.5, 0.0)) x = variable(n)
def findAnalyticCenter(G, h, full_output=False): ''' Find the analytic center of a polygon given a set of inequalities Gx<=h. Solves the problem min_{x} \sum_{i}^{n} -log(h - Gx)_{i} subject to the satisfaction of the inequalities Parameters ---------- G: array like matrix A in Gx<=h, shape (p,d) h: array like vector h in Gx<=h shape (p,) full_output: bool, optional whether the full output is required. Only the center *x* is return if False, which is the default. Returns ------- x: array like analytic center of the polygon sol: dict solution dictionary from cvxopt G: array like binding matrix G in Gx<=h h: array like binding vector h in G<=h See Also -------- :func:`findAnalyticCenter` ''' # we use the cvxopt convention here in that # Gx \preceq h is our general linear inequality constraints # where Ax \le b is our linear inequality # and box is our box constraints ## note that the new set of G and h are the binding constraints bindingIndex, dualHull, G, h, x0 = bindingConstraint(G, h, None, True) # define our objective function along with the # gradient and the Hessian def F(x=None, z=None): if x is None: return 0, matrix(x0) y = h - G * x # we are assuming here that the center can sit on an edge if min(y) <= 0: return None # pretty standard log barrier f = -sum(log(y)) Df = (y**-1).T * G if z is None: return matrix(f), Df H = G.T * spdiag(y**-2) * G return matrix(f), Df, z[0] * H # then we solve the non-linear program try: # print "Find the analytic center" sol = solvers.cp(F) except: print feasiblePoint(numpy.array(x0), numpy.array(G), numpy.array(h)) print "G" print G print "h" print h print "Distance to face" print h - G * x0 print "starting location" print x0 h1 = h lapack.gels(G, h1) print "LS version" print h1[:len(G[0, :])] print "Re-solve the problem" sol = solvers.conelp(matrix(numpy.ones(len(G[0, :]))), G, h) print sol print h - G * sol['x'] sol = solvers.conelp(matrix(-numpy.ones(len(G[0, :]))), G, h) print sol print h - G * sol['x'] raise Exception("Problem! Unidentified yet") # this is rather confusing because part of the outputs are # in cvxopt matrix format while the first is in numpy.ndarray # also note that G and h are the binding constraints # rather than the full set of inequalities if full_output: return numpy.array(sol['x']).flatten(), sol, G, h else: return numpy.array(sol['x']).flatten()
# - (D2-D1)*(D1+D2)^-1 * x[:n] x[n:] = div( x[n:] - mul(d1, z[:n]) - mul(d2, z[n:]), d1+d2 )\ - mul( d3, x[:n] ) # z[:n] = D1^1/2 * ( x[:n] - x[n:] - bz[:n] ) # z[n:] = D2^1/2 * ( -x[:n] - x[n:] - bz[n:] ). z[:n] = mul( W['di'][:n], x[:n] - x[n:] - z[:n] ) z[n:] = mul( W['di'][n:], -x[:n] - x[n:] - z[n:] ) return g x = solvers.coneqp(P, q, G, h, kktsolver = Fkkt)['x'][:n] I = [ k for k in range(n) if abs(x[k]) > 1e-2 ] xls = +y lapack.gels(A[:,I], xls) ybp = A[:,I]*xls[:len(I)] print("Sparse basis contains %d basis functions." %len(I)) print("Relative RMS error = %.1e." %(blas.nrm2(ybp-y) / blas.nrm2(y))) if pylab_installed: pylab.figure(2, facecolor='w') pylab.subplot(211) pylab.plot(ts, y, '-', ts, ybp, 'r--') pylab.xlabel('t') pylab.ylabel('y(t), yhat(t)') pylab.axis([0, 1, -1.5, 1.5]) pylab.title('Signal and basis pursuit approximation (fig. 6.22)') pylab.subplot(212) pylab.plot(ts, y-ybp, '-')
def sysid(y, u, vsig, svth=None): """ System identification using the subspace method and nuclear norm optimization. Estimate a linear time-invariant state-space model given inputs and outputs. The algorithm is described in [1]. INPUT y 'd' matrix of size (p, N). y are the measured outputs, p is the number of outputs, and N is the number of data points measured. u 'd' matrix of size (m, N). u are the inputs, m is the number of inputs, and N is the number of data points. vsig a weighting parameter in the nuclear norm optimization, its value is approximately the 1-sigma output noise level svth an optional parameter, if specified, the model order is determined as the number of singular values greater than svth times the maximum singular value. The default value is 1E-3 OUTPUT sol a dictionary with the following words -- 'A', 'B', 'C', 'D' are the state-space matrices -- 'svN', the original singular values of the Hankel matrix -- 'sv', the optimized singular values of the Hankel matrix -- 'x0', the initial state x(0) -- 'n', the model order [1] Zhang Liu and Lieven Vandenberghe. "Interior-point method for nuclear norm approximation with application to system identification." """ m, N, p = u.size[0], u.size[1], y.size[0] if y.size[1] != N: raise ValueError, "y and u must have the same length" # Y = G*X + H*U + V, Y has size a x b, U has size c x b, Un has b x d r = min(int(30 / p), int((N + 1.0) / (p + m + 1) + 1.0)) a = r * p c = r * m b = N - r + 1 d = b - c # construct Hankel matrix Y Y = Hankel(y, r, b, p=p, q=1) # construct Hankel matrix U U = Hankel(u, r, b, p=m, q=1) # compute Un = null(U) and YUn = Y*Un Vt = matrix(0.0, (b, b)) Stemp = matrix(0.0, (c, 1)) Un = matrix(0.0, (b, d)) YUn = matrix(0.0, (a, d)) lapack.gesvd(U, Stemp, jobvt='A', Vt=Vt) Un[:, :] = Vt.T[:, c:] blas.gemm(Y, Un, YUn) # compute original singular values svN = matrix(0.0, (min(a, d), 1)) lapack.gesvd(YUn, svN) # variable, [y(1);...;y(N)] # form the coefficient matrices for the nuclear norm optimization # minimize | Yh * Un |_* + alpha * | y - yh |_F AA = Hankel_basis(r, b, p=p, q=1) A = matrix(0.0, (a * d, p * N)) temp = spmatrix([], [], [], (a, b), 'd') temp2 = matrix(0.0, (a, d)) for ii in xrange(p * N): temp[:] = AA[:, ii] base.gemm(temp, Un, temp2) A[:, ii] = temp2[:] B = matrix(0.0, (a, d)) # flip the matrix if columns is more than rows if a < d: Itrans = [i + j * a for i in xrange(a) for j in xrange(d)] B[:] = B[Itrans] B.size = (d, a) for ii in xrange(p * N): A[:, ii] = A[Itrans, ii] # regularized term x0 = y[:] Qd = matrix(2.0 * svN[0] / p / N / (vsig**2), (p * N, 1)) # solve the nuclear norm optimization sol = nrmapp(A, B, C=base.spdiag(Qd), d=-base.mul(x0, Qd)) status = sol['status'] x = sol['x'] # construct YhUn and take the svd YhUn = matrix(B) blas.gemv(A, x, YhUn, beta=1.0) if a < d: YhUn = YhUn.T Uh = matrix(0.0, (a, d)) sv = matrix(0.0, (d, 1)) lapack.gesvd(YhUn, sv, jobu='S', U=Uh) # determine model order if svth is None: svth = 1E-3 svthn = sv[0] * svth n = 1 while sv[n] >= svthn and n < 10: n = n + 1 # estimate A, C Uhn = Uh[:, :n] for ii in xrange(n): blas.scal(sv[ii], Uhn, n=a, offset=ii * a) syseC = Uhn[:p, :] Als = Uhn[:-p, :] Bls = Uhn[p:, :] lapack.gels(Als, Bls) syseA = Bls[:n, :] Als[:, :] = Uhn[:-p, :] Bls[:, :] = Uhn[p:, :] blas.gemm(Als, syseA, Bls, beta=-1.0) Aerr = blas.nrm2(Bls) # stabilize A Sc = matrix(0.0, (n, n), 'z') w = matrix(0.0, (n, 1), 'z') Vs = matrix(0.0, (n, n), 'z') def F(w): return (abs(w) < 1.0) Sc[:, :] = syseA ns = lapack.gees(Sc, w, Vs, select=F) while ns < n: #print "stabilize matrix A" w[ns:] = w[ns:]**-1 Sc[::n + 1] = w Sc = Vs * Sc * Vs.H syseA[:, :] = Sc.real() Sc[:, :] = syseA ns = lapack.gees(Sc, w, Vs, select=F) # estimate B,D,x0 stored in vector [x0; vec(D); vec(B)] F1 = matrix(0.0, (p * N, n)) F1[:p, :] = syseC for ii in xrange(1, N): F1[ii * p:(ii + 1) * p, :] = F1[(ii - 1) * p:ii * p, :] * syseA F2 = matrix(0.0, (p * N, p * m)) ut = u.T for ii in xrange(p): F2[ii::p, ii::p] = ut F3 = matrix(0.0, (p * N, n * m)) F3t = matrix(0.0, (p * (N - 1), n * m)) for ii in xrange(1, N): for jj in xrange(p): for kk in xrange(n): F3t[jj:jj + (N - ii) * p:p, kk::n] = ut[:N - ii, :] * F1[(ii - 1) * p + jj, kk] F3[ii * p:, :] = F3[ii * p:, :] + F3t[:(N - ii) * p, :] F = matrix([[F1], [F2], [F3]]) yls = y[:] Sls = matrix(0.0, (F.size[1], 1)) Uls = matrix(0.0, (F.size[0], F.size[1])) Vtls = matrix(0.0, (F.size[1], F.size[1])) lapack.gesvd(F, Sls, jobu='S', jobvt='S', U=Uls, Vt=Vtls) Frank = len([ii for ii in xrange(Sls.size[0]) if Sls[ii] >= 1E-6]) #print 'Rank deficiency = ', F.size[1] - Frank xx = matrix(0.0, (F.size[1], 1)) xx[:Frank] = Uls.T[:Frank, :] * yls xx[:Frank] = base.mul(xx[:Frank], Sls[:Frank]**-1) xx[:] = Vtls.T[:, :Frank] * xx[:Frank] blas.gemv(F, xx, yls, beta=-1.0) xxerr = blas.nrm2(yls) x0 = xx[:n] syseD = xx[n:n + p * m] syseD.size = (p, m) syseB = xx[n + p * m:] syseB.size = (n, m) return {'A': syseA, 'B': syseB, 'C': syseC, 'D': syseD, 'svN': svN, 'sv': \ sv, 'x0': x0, 'n': n, 'Aerr': Aerr, 'xxerr': xxerr}
# Robust regression. from cvxopt import solvers, lapack, matrix, spmatrix from pickle import load #solvers.options['show_progress'] = 0 data = load(open('huber.bin', 'rb')) u, v = data['u'], data['v'] m, n = len(u), 2 A = matrix([m * [1.0], [u]]) b = +v # Least squares solution. xls = +b lapack.gels(+A, xls) xls = xls[:2] # Robust least squares. # # minimize sum( h( A*x-b )) # # where h(u) = u^2 if |u| <= 1.0 # = 2*(|u| - 1.0) if |u| > 1.0. # # Solve as a QP (see exercise 4.5): # # minimize (1/2) * u'*u + 1'*v # subject to -u - v <= A*x-b <= u + v # 0 <= u <= 1 # v >= 0
# Figure 4.11, page 185. # Regularized least-squares. from pickle import load from cvxopt import blas, lapack, matrix from cvxopt import solvers #solvers.options['show_progress'] = 0 data = load(open("rls.bin",'rb')) A, b = data['A'], data['b'] m, n = A.size # LS solution xls = +b lapack.gels(+A, xls) xls = xls[:n] # We compute the optimal values of # # minimize/maximize || A*x - b ||_2^2 # subject to x'*x = alpha # # via the duals. # # Lower bound: # # maximize -t - u*alpha # subject to [u*I, 0; 0, t] + [A, b]'*[A, b] >= 0 # # Upper bound: #
def l1(P, q): """ Returns the solution u of the ell-1 approximation problem (primal) minimize ||P*u - q||_1 (dual) maximize q'*w subject to P'*w = 0 ||w||_infty <= 1. """ m, n = P.size # Solve equivalent LP # # minimize [0; 1]' * [u; v] # subject to [P, -I; -P, -I] * [u; v] <= [q; -q] # # maximize -[q; -q]' * z # subject to [P', -P']*z = 0 # [-I, -I]*z + 1 = 0 # z >= 0 c = matrix(n*[0.0] + m*[1.0]) h = matrix([q, -q]) def Fi(x, y, alpha = 1.0, beta = 0.0, trans = 'N'): if trans == 'N': # y := alpha * [P, -I; -P, -I] * x + beta*y u = P*x[:n] y[:m] = alpha * ( u - x[n:]) + beta*y[:m] y[m:] = alpha * (-u - x[n:]) + beta*y[m:] else: # y := alpha * [P', -P'; -I, -I] * x + beta*y y[:n] = alpha * P.T * (x[:m] - x[m:]) + beta*y[:n] y[n:] = -alpha * (x[:m] + x[m:]) + beta*y[n:] def Fkkt(W): # Returns a function f(x, y, z) that solves # # [ 0 0 P' -P' ] [ x[:n] ] [ bx[:n] ] # [ 0 0 -I -I ] [ x[n:] ] [ bx[n:] ] # [ P -I -W1^2 0 ] [ z[:m] ] = [ bz[:m] ] # [-P -I 0 -W2 ] [ z[m:] ] [ bz[m:] ] # # On entry bx, bz are stored in x, z. # On exit x, z contain the solution, with z scaled (W['di'] .* z is # returned instead of z). d1, d2 = W['d'][:m], W['d'][m:] D = 4*(d1**2 + d2**2)**-1 A = P.T * spdiag(D) * P lapack.potrf(A) def f(x, y, z): x[:n] += P.T * ( mul( div(d2**2 - d1**2, d1**2 + d2**2), x[n:]) + mul( .5*D, z[:m]-z[m:] ) ) lapack.potrs(A, x) u = P*x[:n] x[n:] = div( x[n:] - div(z[:m], d1**2) - div(z[m:], d2**2) + mul(d1**-2 - d2**-2, u), d1**-2 + d2**-2 ) z[:m] = div(u-x[n:]-z[:m], d1) z[m:] = div(-u-x[n:]-z[m:], d2) return f # Initial primal and dual points from least-squares solution. # uls minimizes ||P*u-q||_2; rls is the LS residual. uls = +q lapack.gels(+P, uls) rls = P*uls[:n] - q # x0 = [ uls; 1.1*abs(rls) ]; s0 = [q;-q] - [P,-I; -P,-I] * x0 x0 = matrix( [uls[:n], 1.1*abs(rls)] ) s0 = +h Fi(x0, s0, alpha=-1, beta=1) # z0 = [ (1+w)/2; (1-w)/2 ] where w = (.9/||rls||_inf) * rls # if rls is nonzero and w = 0 otherwise. if max(abs(rls)) > 1e-10: w = .9/max(abs(rls)) * rls else: w = matrix(0.0, (m,1)) z0 = matrix([.5*(1+w), .5*(1-w)]) dims = {'l': 2*m, 'q': [], 's': []} sol = solvers.conelp(c, Fi, h, dims, kktsolver = Fkkt, primalstart={'x': x0, 's': s0}, dualstart={'z': z0}) return sol['x'][:n]
hs = [matrix(0.0, (M, M))] hs[0][:(M + 1) * m:M + 1] = 1.0 hs[0][-1, :m] = -b.T return solvers.sdp(c, None, None, Fs, hs)['x'][:n] # Figure 6.15 data = load(open('robls.bin', 'rb'))['6.15'] A, b, B = data['A'], data['b'], data['B'] m, n = A.size # Nominal problem: minimize || A*x - b ||_2 xnom = +b lapack.gels(+A, xnom) xnom = xnom[:n] # Stochastic problem. # # minimize E || (A+u*B) * x - b ||_2^2 # = || A*x - b||_2^2 + x'*P*x # # with P = E(u^2) * B'*B = (1/3) * B'*B S = A.T * A + (1.0 / 3.0) * B.T * B xstoch = A.T * b lapack.posv(S, xstoch) # Worst case approximation. #
# constant h[k][2,:2] = B[k,:] h[k][:2,2] = B[k,:].T sol = solvers.sdp(c, Gs=G, hs=h) X1 = matrix(sol['x'][L:], (N,2)) # Quadratic placement: h(u) = u^2. # # minimize sum (A*X[:,0] + B[:,0])**2 + (A*X[:,1] + B[:,1])**2 # # with variable X (Nx2). Bc = -B lapack.gels(+A1, Bc) X2 = Bc[:N,:] # Fourth order placement: h(u) = u^4 # # minimize g(AA*x + BB) # # where AA = [A1, 0; 0, A1] # BB = [B[:,0]; B[:,1]] # x = [X[:,0]; X[:,1]] # g(u,v) = sum((uk.^2 + vk.^2).^2) # # with variables x (2*N). AA = matrix(0.0, (2*L, 2*N))
# subject to -y <= x <= y # sum(y) <= alpha P = matrix(0.0, (2*n,2*n)) P[:n,:n] = A.T*A q = matrix(0.0, (2*n,1)) q[:n] = -A.T*b I = matrix(0.0, (n,n)) I[::n+1] = 1.0 G = matrix([[I, -I, matrix(0.0, (1,n))], [-I, -I, matrix(1.0, (1,n))]]) h = matrix(0.0, (2*n+1,1)) # Least-norm solution xln = matrix(0.0, (n,1)) xln[:m] = b lapack.gels(+A, xln) nopts = 100 res = [ blas.nrm2(b) ] card = [ 0 ] alphas = blas.asum(xln)/(nopts-1) * matrix(range(1,nopts), tc='d') for alpha in alphas: # minimize ||A*x-b||_2 # subject to ||x||_1 <= alpha h[-1] = alpha x = solvers.qp(P, q, G, h)['x'][:n] xmax = max(abs(x)) I = [ k for k in range(n) if abs(x[k]) > tol*xmax ] if len(I) <= m:
def solve_SAT2(self,cnf,number_of_variables,number_of_clauses): #Solves CNFSAT by a Polynomial Time Approximation scheme: # - Encode each clause as a linear equation in n variables: missing variables and negated variables are 0, others are 1 # - Solve previous system of equations by least squares algorithm to fit a line # - Variable value above 0.5 is set to 1 and less than 0.5 is set to 0 # - Rounded of assignment array satisfies the CNFSAT with high probability #Returns: a tuple with set of satisfying assignments satass=[] x=[] self.solve_SAT(cnf,number_of_variables,number_of_clauses) for clause in self.cnfparsed: equation=[] for n in xrange(number_of_variables): equation.append(0) #print "clause:",clause for literal in clause: if literal[0] != "!": equation[int(literal[1:])-1]=1 else: equation[int(literal[2:])-1]=0 self.equationsA.append(equation) for n in xrange(number_of_clauses): self.equationsB.append(1) a = np.array(self.equationsA) b = np.array(self.equationsB) init_guess = [] for n in xrange(number_of_variables): init_guess.append(0.00000000001) initial_guess = np.array(init_guess) self.A=a self.B=b #print "a:",a #print "b:",b #print "a.shape:",a.shape #print "b.shape:",b.shape matrixa=matrix(a,tc='d') matrixb=matrix(b,tc='d') x=None if number_of_variables == number_of_clauses: if self.Algorithm=="lsqr()": #x = np.dot(np.linalg.inv(a),b) #x = gmres(a,b) #x = lgmres(a,b) #x = minres(a,b) #x = bicg(a,b) #x = cg(a,b) #x = cgs(a,b) #x = bicgstab(a,b) x = lsqr(a,b,atol=0,btol=0,conlim=0,show=True) if self.Algorithm=="lapack()": try: x = gesv(matrixa,matrixb) #x = gels(matrixa,matrixb) #x = sysv(matrixa,matrixb) #x = getrs(matrixa,matrixb) x = [matrixb] except: print "Exception:",sys.exc_info() return None if self.Algorithm=="l1regls()": l1x = l1regls(matrixa,matrixb) ass=[] x=[] for n in l1x: ass.append(n) x.append(ass) if self.Algorithm=="lsmr()": x = lsmr(a,b,atol=0,btol=0,conlim=0,show=True,x0=initial_guess) else: if self.Algorithm=="solve()": x = solve(a,b) if self.Algorithm=="lstsq()": x = lstsq(a,b,lapack_driver='gelsy') if self.Algorithm=="lsqr()": x = lsqr(a,b,atol=0,btol=0,conlim=0,show=True) if self.Algorithm=="lsmr()": #x = lsmr(a,b,atol=0.1,btol=0.1,maxiter=5,conlim=10,show=True) x = lsmr(a,b,atol=0,btol=0,conlim=0,show=True,x0=initial_guess) if self.Algorithm=="spsolve()": x = dsolve.spsolve(csc_matrix(a),b) if self.Algorithm=="pinv2()": x=[] #pseudoinverse_a=pinv(a) pseudoinverse_a=pinv2(a,check_finite=False) x.append(matmul(pseudoinverse_a,b)) if self.Algorithm=="lsq_linear()": x = lsq_linear(a,b,lsq_solver='exact') if self.Algorithm=="lapack()": try: #x = gesv(matrixa,matrixb) x = gels(matrixa,matrixb) #x = sysv(matrixa,matrixb) #x = getrs(matrixa,matrixb) x = [matrixb] except: print "Exception:",sys.exc_info() return None if self.Algorithm=="l1regls()": l1x = l1regls(matrixa,matrixb) ass=[] x=[] for n in l1x: ass.append(n) x.append(ass) print "solve_SAT2(): ",self.Algorithm,": x:",x if x is None: return None cnt=0 binary_parity=0 real_parity=0.0 if rounding_threshold == "Randomized": randomized_rounding_threshold=float(random.randint(1,100000))/100000.0 else: min_assignment=min(x[0]) max_assignment=max(x[0]) randomized_rounding_threshold=(min_assignment + max_assignment)/2 print "randomized_rounding_threshold = ", randomized_rounding_threshold print "approximate assignment :",x[0] for e in x[0]: if e > randomized_rounding_threshold: satass.append(1) binary_parity += 1 else: satass.append(0) binary_parity += 0 real_parity += e cnt+=1 print "solve_SAT2(): real_parity = ",real_parity print "solve_SAT2(): binary_parity = ",binary_parity return (satass,real_parity,binary_parity,x[0])
def l1blas (P, q): """ Returns the solution u of the ell-1 approximation problem (primal) minimize ||P*u - q||_1 (dual) maximize q'*w subject to P'*w = 0 ||w||_infty <= 1. """ m, n = P.size # Solve equivalent LP # # minimize [0; 1]' * [u; v] # subject to [P, -I; -P, -I] * [u; v] <= [q; -q] # # maximize -[q; -q]' * z # subject to [P', -P']*z = 0 # [-I, -I]*z + 1 = 0 # z >= 0 c = matrix(n*[0.0] + m*[1.0]) h = matrix([q, -q]) u = matrix(0.0, (m,1)) Ps = matrix(0.0, (m,n)) A = matrix(0.0, (n,n)) def Fi(x, y, alpha = 1.0, beta = 0.0, trans = 'N'): if trans == 'N': # y := alpha * [P, -I; -P, -I] * x + beta*y blas.gemv(P, x, u) y[:m] = alpha * ( u - x[n:]) + beta*y[:m] y[m:] = alpha * (-u - x[n:]) + beta*y[m:] else: # y := alpha * [P', -P'; -I, -I] * x + beta*y blas.copy(x[:m] - x[m:], u) blas.gemv(P, u, y, alpha = alpha, beta = beta, trans = 'T') y[n:] = -alpha * (x[:m] + x[m:]) + beta*y[n:] def Fkkt(W): # Returns a function f(x, y, z) that solves # # [ 0 0 P' -P' ] [ x[:n] ] [ bx[:n] ] # [ 0 0 -I -I ] [ x[n:] ] [ bx[n:] ] # [ P -I -D1^{-1} 0 ] [ z[:m] ] = [ bz[:m] ] # [-P -I 0 -D2^{-1} ] [ z[m:] ] [ bz[m:] ] # # where D1 = diag(di[:m])^2, D2 = diag(di[m:])^2 and di = W['di']. # # On entry bx, bz are stored in x, z. # On exit x, z contain the solution, with z scaled (di .* z is # returned instead of z). # Factor A = 4*P'*D*P where D = d1.*d2 ./(d1+d2) and # d1 = d[:m].^2, d2 = d[m:].^2. di = W['di'] d1, d2 = di[:m]**2, di[m:]**2 D = div( mul(d1,d2), d1+d2 ) Ds = spdiag(2 * sqrt(D)) base.gemm(Ds, P, Ps) blas.syrk(Ps, A, trans = 'T') lapack.potrf(A) def f(x, y, z): # Solve for x[:n]: # # A*x[:n] = bx[:n] + P' * ( ((D1-D2)*(D1+D2)^{-1})*bx[n:] # + (2*D1*D2*(D1+D2)^{-1}) * (bz[:m] - bz[m:]) ). blas.copy(( mul( div(d1-d2, d1+d2), x[n:]) + mul( 2*D, z[:m]-z[m:] ) ), u) blas.gemv(P, u, x, beta = 1.0, trans = 'T') lapack.potrs(A, x) # x[n:] := (D1+D2)^{-1} * (bx[n:] - D1*bz[:m] - D2*bz[m:] # + (D1-D2)*P*x[:n]) base.gemv(P, x, u) x[n:] = div( x[n:] - mul(d1, z[:m]) - mul(d2, z[m:]) + mul(d1-d2, u), d1+d2 ) # z[:m] := d1[:m] .* ( P*x[:n] - x[n:] - bz[:m]) # z[m:] := d2[m:] .* (-P*x[:n] - x[n:] - bz[m:]) z[:m] = mul(di[:m], u-x[n:]-z[:m]) z[m:] = mul(di[m:], -u-x[n:]-z[m:]) return f # Initial primal and dual points from least-squares solution. # uls minimizes ||P*u-q||_2; rls is the LS residual. uls = +q lapack.gels(+P, uls) rls = P*uls[:n] - q # x0 = [ uls; 1.1*abs(rls) ]; s0 = [q;-q] - [P,-I; -P,-I] * x0 x0 = matrix( [uls[:n], 1.1*abs(rls)] ) s0 = +h Fi(x0, s0, alpha=-1, beta=1) # z0 = [ (1+w)/2; (1-w)/2 ] where w = (.9/||rls||_inf) * rls # if rls is nonzero and w = 0 otherwise. if max(abs(rls)) > 1e-10: w = .9/max(abs(rls)) * rls else: w = matrix(0.0, (m,1)) z0 = matrix([.5*(1+w), .5*(1-w)]) dims = {'l': 2*m, 'q': [], 's': []} sol = solvers.conelp(c, Fi, h, dims, kktsolver = Fkkt, primalstart={'x': x0, 's': s0}, dualstart={'z': z0}) return sol['x'][:n]
hs = [matrix(0.0, (M, M))] hs[0][:(M+1)*m:M+1] = 1.0 hs[0][-1, :m] = -b.T return solvers.sdp(c, None, None, Fs, hs)['x'][:n] # Figure 6.15 data = load(open('robls.bin','rb'))['6.15'] A, b, B = data['A'], data['b'], data['B'] m, n = A.size # Nominal problem: minimize || A*x - b ||_2 xnom = +b lapack.gels(+A, xnom) xnom = xnom[:n] # Stochastic problem. # # minimize E || (A+u*B) * x - b ||_2^2 # = || A*x - b||_2^2 + x'*P*x # # with P = E(u^2) * B'*B = (1/3) * B'*B S = A.T * A + (1.0/3.0) * B.T * B xstoch = A.T * b lapack.posv(S, xstoch)
def l1(P, q): """ Returns the solution u, w of the ell-1 approximation problem (primal) minimize ||P*u - q||_1 (dual) maximize q'*w subject to P'*w = 0 ||w||_infty <= 1. """ m, n = P.size # Solve equivalent LP # # minimize [0; 1]' * [u; v] # subject to [P, -I; -P, -I] * [u; v] <= [q; -q] # # maximize -[q; -q]' * z # subject to [P', -P']*z = 0 # [-I, -I]*z + 1 = 0 # z >= 0 c = matrix(n * [0.0] + m * [1.0]) h = matrix([q, -q]) def Fi(x, y, alpha=1.0, beta=0.0, trans='N'): if trans == 'N': # y := alpha * [P, -I; -P, -I] * x + beta*y u = P * x[:n] y[:m] = alpha * (u - x[n:]) + beta * y[:m] y[m:] = alpha * (-u - x[n:]) + beta * y[m:] else: # y := alpha * [P', -P'; -I, -I] * x + beta*y y[:n] = alpha * P.T * (x[:m] - x[m:]) + beta * y[:n] y[n:] = -alpha * (x[:m] + x[m:]) + beta * y[n:] def Fkkt(W): # Returns a function f(x, y, z) that solves # # [ 0 0 P' -P' ] [ x[:n] ] [ bx[:n] ] # [ 0 0 -I -I ] [ x[n:] ] [ bx[n:] ] # [ P -I -D1^{-1} 0 ] [ z[:m] ] = [ bz[:m] ] # [-P -I 0 -D2^{-1} ] [ z[m:] ] [ bz[m:] ] # # where D1 = diag(di[:m])^2, D2 = diag(di[m:])^2 and di = W['di']. # # On entry bx, bz are stored in x, z. # On exit x, z contain the solution, with z scaled (di .* z is # returned instead of z). # Factor A = 4*P'*D*P where D = d1.*d2 ./(d1+d2) and # d1 = d[:m].^2, d2 = d[m:].^2. di = W['di'] d1, d2 = di[:m]**2, di[m:]**2 D = div(mul(d1, d2), d1 + d2) A = P.T * spdiag(4 * D) * P lapack.potrf(A) def f(x, y, z): # Solve for x[:n]: # # A*x[:n] = bx[:n] + P' * ( ((D1-D2)*(D1+D2)^{-1})*bx[n:] # + (2*D1*D2*(D1+D2)^{-1}) * (bz[:m] - bz[m:]) ). x[:n] += P.T * (mul(div(d1 - d2, d1 + d2), x[n:]) + mul(2 * D, z[:m] - z[m:])) lapack.potrs(A, x) # x[n:] := (D1+D2)^{-1} * (bx[n:] - D1*bz[:m] - D2*bz[m:] # + (D1-D2)*P*x[:n]) u = P * x[:n] x[n:] = div( x[n:] - mul(d1, z[:m]) - mul(d2, z[m:]) + mul(d1 - d2, u), d1 + d2) # z[:m] := d1[:m] .* ( P*x[:n] - x[n:] - bz[:m]) # z[m:] := d2[m:] .* (-P*x[:n] - x[n:] - bz[m:]) z[:m] = mul(di[:m], u - x[n:] - z[:m]) z[m:] = mul(di[m:], -u - x[n:] - z[m:]) return f # Initial primal and dual points from least-squares solution. # uls minimizes ||P*u-q||_2; rls is the LS residual. uls = +q lapack.gels(+P, uls) rls = P * uls[:n] - q # x0 = [ uls; 1.1*abs(rls) ]; s0 = [q;-q] - [P,-I; -P,-I] * x0 x0 = matrix([uls[:n], 1.1 * abs(rls)]) s0 = +h Fi(x0, s0, alpha=-1, beta=1) # z0 = [ (1+w)/2; (1-w)/2 ] where w = (.9/||rls||_inf) * rls # if rls is nonzero and w = 0 otherwise. if max(abs(rls)) > 1e-10: w = .9 / max(abs(rls)) * rls else: w = matrix(0.0, (m, 1)) z0 = matrix([.5 * (1 + w), .5 * (1 - w)]) dims = {'l': 2 * m, 'q': [], 's': []} sol = solvers.conelp(c, Fi, h, dims, kktsolver=Fkkt, primalstart={ 'x': x0, 's': s0 }, dualstart={'z': z0}) return sol['x'][:n], sol['z'][m:] - sol['z'][:m]
def solve_SAT2(self, cnf, number_of_variables, number_of_clauses): #Solves CNFSAT by a Polynomial Time Approximation scheme: # - Encode each clause as a linear equation in n variables: missing variables and negated variables are 0, others are 1 # - Solve previous system of equations by least squares algorithm to fit a line # - Variable value above 0.5 is set to 1 and less than 0.5 is set to 0 # - Rounded of assignment array satisfies the CNFSAT with high probability #Returns: a tuple with set of satisfying assignments satass = [] x = [] self.solve_SAT(cnf, number_of_variables, number_of_clauses) for clause in self.cnfparsed: equation = [] for n in xrange(number_of_variables): equation.append(0) #print "clause:",clause for literal in clause: if literal[0] != "!": equation[int(literal[1:]) - 1] = 1 else: equation[int(literal[2:]) - 1] = 0 self.equationsA.append(equation) for n in xrange(number_of_clauses): self.equationsB.append(1) a = np.array(self.equationsA) b = np.array(self.equationsB) init_guess = [] for n in xrange(number_of_variables): init_guess.append(0.00000000001) initial_guess = np.array(init_guess) self.A = a self.B = b #print "a:",a #print "b:",b #print "a.shape:",a.shape #print "b.shape:",b.shape matrixa = matrix(a, tc='d') matrixb = matrix(b, tc='d') x = None if number_of_variables == number_of_clauses: if self.Algorithm == "lsqr()": #x = np.dot(np.linalg.inv(a),b) #x = gmres(a,b) #x = lgmres(a,b) #x = minres(a,b) #x = bicg(a,b) #x = cg(a,b) #x = cgs(a,b) #x = bicgstab(a,b) x = lsqr(a, b, atol=0, btol=0, conlim=0, show=True) if self.Algorithm == "lapack()": try: x = gesv(matrixa, matrixb) #x = gels(matrixa,matrixb) #x = sysv(matrixa,matrixb) #x = getrs(matrixa,matrixb) x = [matrixb] except: print "Exception:", sys.exc_info() return None if self.Algorithm == "l1regls()": l1x = l1regls(matrixa, matrixb) ass = [] x = [] for n in l1x: ass.append(n) x.append(ass) if self.Algorithm == "lsmr()": x = lsmr(a, b, atol=0, btol=0, conlim=0, show=True, x0=initial_guess) else: if self.Algorithm == "solve()": x = solve(a, b) if self.Algorithm == "lstsq()": x = lstsq(a, b, lapack_driver='gelsy') if self.Algorithm == "lsqr()": x = lsqr(a, b, atol=0, btol=0, conlim=0, show=True) if self.Algorithm == "lsmr()": #x = lsmr(a,b,atol=0.1,btol=0.1,maxiter=5,conlim=10,show=True) x = lsmr(a, b, atol=0, btol=0, conlim=0, show=True, x0=initial_guess) if self.Algorithm == "spsolve()": x = dsolve.spsolve(csc_matrix(a), b) if self.Algorithm == "pinv2()": x = [] #pseudoinverse_a=pinv(a) pseudoinverse_a = pinv2(a, check_finite=False) x.append(matmul(pseudoinverse_a, b)) if self.Algorithm == "lsq_linear()": x = lsq_linear(a, b, lsq_solver='exact') if self.Algorithm == "lapack()": try: #x = gesv(matrixa,matrixb) x = gels(matrixa, matrixb) #x = sysv(matrixa,matrixb) #x = getrs(matrixa,matrixb) x = [matrixb] except: print "Exception:", sys.exc_info() return None if self.Algorithm == "l1regls()": l1x = l1regls(matrixa, matrixb) ass = [] x = [] for n in l1x: ass.append(n) x.append(ass) print "solve_SAT2(): ", self.Algorithm, ": x:", x if x is None: return None cnt = 0 binary_parity = 0 real_parity = 0.0 if rounding_threshold == "Randomized": randomized_rounding_threshold = float(random.randint( 1, 100000)) / 100000.0 else: min_assignment = min(x[0]) max_assignment = max(x[0]) randomized_rounding_threshold = (min_assignment + max_assignment) / 2 print "randomized_rounding_threshold = ", randomized_rounding_threshold print "approximate assignment :", x[0] for e in x[0]: if e > randomized_rounding_threshold: satass.append(1) binary_parity += 1 else: satass.append(0) binary_parity += 0 real_parity += e cnt += 1 print "solve_SAT2(): real_parity = ", real_parity print "solve_SAT2(): binary_parity = ", binary_parity return (satass, real_parity, binary_parity, x[0])