def get_scores(self, sol, idx, y=[]): y = np.array(y) if (y.size==0): y=np.array(self.y[idx]) (foo, T) = y.shape N = self.states F = self.dims scores = matrix(0.0, (1, T)) # this is the score of the complete example anom_score = sol.trans()*self.get_joint_feature_map(idx) # transition matrix A = self.get_transition_matrix(sol) # emission matrix without loss em = self.calc_emission_matrix(sol, idx, augment_loss=False); # store scores for each position of the sequence scores[0] = 0.0 + em[int(y[0,0]),0] for t in range(1,T): scores[t] = A[int(y[0,t-1]),int(y[0,t])] + em[int(y[0,t]),t] # transform for better interpretability # transform for better interpretability if max(abs(scores))>10.0**(-15): scores = exp(-abs(4.0*scores/max(abs(scores)))) else: scores = matrix(0.0, (1,T)) return (anom_score, scores)
def testgp(opts): Aflr = 1000.0 Awall = 100.0 alpha = 0.5 beta = 2.0 gamma = 0.5 delta = 2.0 F = matrix( [[-1., 1., 1., 0., -1., 1., 0., 0.], [-1., 1., 0., 1., 1., -1., 1., -1.], [-1., 0., 1., 1., 0., 0., -1., 1.]]) g = log( matrix( [1.0, 2/Awall, 2/Awall, 1/Aflr, alpha, 1/beta, gamma, 1/delta]) ) K = [1, 2, 1, 1, 1, 1, 1] solvers.options.update(opts) sol = solvers.gp(K, F, g) #localcvx.options.update(opts) #sol = localcvx.gp(K, F, g, kktsolver='chol') if sol['status'] == 'optimal': x = sol['x'] print "x=\n", helpers.strSpe(x, "%.17f") h, w, d = exp(x) print("\n h = %f, w = %f, d = %f.\n" %(h,w,d)) print "\n *** running GO test ***" helpers.run_go_test("../testgp", {'x': x})
def F(x=None, z=None): if x is None: return 0, matrix(0.0, (2,1)) w = exp(A*x) f = c.T*x + sum(log(1+w)) grad = c + A.T * div(w, 1+w) if z is None: return f, grad.T H = A.T * spdiag(div(w,(1+w)**2)) * A return f, grad.T, z[0]*H
def F(x=None, z=None): if x is None: return 0, matrix(0.0, (n+1,1)) w = exp(A*x) f = dot(c,x) + sum(log(1+w)) grad = c + A.T * div(w, 1+w) if z is None: return matrix(f), grad.T H = A.T * spdiag(div(w,(1+w)**2)) * A return matrix(f), grad.T, z[0]*H
def test_cvxopt_sparse(self): m = 100 n = 20 mu = cvxopt.exp(cvxopt.normal(m)) F = cvxopt.normal(m, n) D = cvxopt.spdiag(cvxopt.uniform(m)) x = Variable(m) exp = square(norm2(D * x))
def test_cvxopt_sparse(self): m = 100 n = 20 mu = cvxopt.exp( cvxopt.normal(m) ) F = cvxopt.normal(m, n) D = cvxopt.spdiag( cvxopt.uniform(m) ) x = Variable(m) exp = square(norm2(D*x))
def init1(self, dae): retval = True # electrical torque in pu # te = mul(xmu, mul(dae.x[self.irq], dae.y[self.isd]) - mul(dae.x[self.ird], dae.y[self.isq])) for i in range(self.n): if self.te0[i] < 0: self.message( 'Electric power is negative at bus <{}>. Wind speed initialize failed.' .format(self.bus[i]), ERROR) retval = False # wind power in pu omega = dae.x[self.omega_m] theta = dae.x[self.theta_p] pw = mul(self.te0, dae.x[self.omega_m]) dae.y[self.pw] = pw # wind speed initialization loop R = 4 * pi * self.system.Settings.freq * mul(self.R, self.ngb, div(1, self.npole[i])) AA = pi * self.R**2 vw = 0.9 * self.Vwn for i in range(self.n): mis = 1 iter = 0 while abs(mis) > self.system.TDS.tol: if iter > 50: self.message( 'Initialization of wind <{}> failed. Try increasing the nominal wind speed.' .format(self.wind[i])) retval = False break pw_iter, jac = self.windpower(self.ngen[i], self.rho[i], vw[i], AA[i], R[i], omega[i], theta[i]) mis = pw_iter - pw[i] inc = -mis / jac[1] vw[i] += inc iter += 1 # set wind speed dae.x[self.vw] = div(vw, self.Vwn) lamb = div(omega, vw, div(1, R)) ilamb = div(1, (div(1, lamb + 0.08 * theta) - div(0.035, theta**3 + 1))) cp = 0.22 * mul( div(116, ilamb) - 0.4 * theta - 5, exp(div(-12.5, ilamb))) dae.y[self.lamb] = lamb dae.y[self.ilamb] = ilamb dae.y[self.cp] = cp
def init1(self, dae): # electrical torque in pu # te = mul( # xmu, # mul(dae.x[self.irq], dae.y[self.isd]) - mul( # dae.x[self.ird], dae.y[self.isq])) for i in range(self.n): if self.te0[i] < 0: logger.error( 'Pe < 0 on bus <{}>. Wind speed initialize failed.'.format( self.bus[i])) # wind power in pu omega = dae.x[self.omega_m] theta = dae.x[self.theta_p] pw = mul(self.te0, dae.x[self.omega_m]) dae.y[self.pw] = pw # wind speed initialization loop R = 4 * pi * self.system.config.freq * mul(self.R, self.ngb, div(1, self.npole)) AA = pi * self.R**2 vw = 0.9 * self.Vwn for i in range(self.n): mis = 1 niter = 0 while abs(mis) > self.system.tds.config.tol: if niter > 50: self.message( 'Wind <{}> init failed. ' 'Try increasing the nominal wind speed.'.format( self.wind[i])) break pw_iter, jac = self.windpower(self.ngen[i], self.rho[i], vw[i], AA[i], R[i], omega[i], theta[i]) mis = pw_iter - pw[i] inc = -mis / jac[1] vw[i] += inc niter += 1 # set wind speed dae.x[self.vw] = div(vw, self.Vwn) lamb = div(omega, vw, div(1, R)) ilamb = div(1, lamb + 0.08 * theta) - div(0.035, theta**3 + 1) cp = 0.22 * mul( mul(116, ilamb) - 0.4 * theta - 5, exp(mul(-12.5, ilamb))) dae.y[self.lamb] = lamb dae.y[self.ilamb] = ilamb dae.y[self.cp] = cp
def gycall(self, dae): dae.add_jac(Gy, mul(self.xmu, 1 - dae.x[self.omega_m]), self.vrd, self.isq) dae.add_jac(Gy, -mul(self.xmu, 1 - dae.x[self.omega_m]), self.vrq, self.isd) dae.add_jac(Gy, -sin(dae.y[self.a]), self.vsd, self.v) dae.add_jac(Gy, -mul(dae.y[self.v], cos(dae.y[self.a])), self.vsd, self.a) dae.add_jac(Gy, cos(dae.y[self.a]), self.vsq, self.v) dae.add_jac(Gy, -mul(dae.y[self.v], sin(dae.y[self.a])), self.vsq, self.a) dae.add_jac( Gy, mul(0.5, self.ngen, pi, self.rho, (self.R)**2, (self.Vwn)**3, div(1, self.mva_mega), (dae.x[self.vw])**3), self.pw, self.cp) dae.add_jac( Gy, mul(-25.52, (dae.y[self.ilamb])**-2, exp(mul(-12.5, div(1, dae.y[self.ilamb])))) + mul( 12.5, (dae.y[self.ilamb])**-2, -1.1 + mul(25.52, div(1, dae.y[self.ilamb])) + mul(-0.088, dae.x[self.theta_p]), exp(mul(-12.5, div(1, dae.y[self.ilamb])))), self.cp, self.ilamb) dae.add_jac( Gy, mul((dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p]))**-2, (div(1, dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p])) + mul(-0.035, div(1, 1 + (dae.x[self.theta_p])**3)))**-2), self.ilamb, self.lamb) dae.add_jac(Gy, -mul(dae.y[self.isd], self.u0), self.a, self.vsd) dae.add_jac(Gy, -mul(dae.x[self.irq], self.u0), self.a, self.vrq) dae.add_jac(Gy, -mul(self.u0, dae.y[self.vsq]), self.a, self.isq) dae.add_jac(Gy, -mul(dae.x[self.ird], self.u0), self.a, self.vrd) dae.add_jac(Gy, -mul(dae.y[self.isq], self.u0), self.a, self.vsq) dae.add_jac(Gy, -mul(self.u0, dae.y[self.vsd]), self.a, self.isd) dae.add_jac( Gy, mul( self.u0, mul(2, dae.y[self.v], div(1, self.x0)) + mul(dae.x[self.ird], self.xmu, div(1, self.x0))), self.v, self.v)
def gcall(self, dae): toSb = div(self.Sn, self.system.Settings.mva) dae.g[self.isd] = -dae.y[self.vsd] + mul( dae.x[self.irq], self.xmu) + mul(dae.y[self.isq], self.x0) - mul( dae.y[self.isd], self.rs) dae.g[self.isq] = -dae.y[self.vsq] - mul( dae.x[self.ird], self.xmu) - mul(dae.y[self.isd], self.x0) - mul( dae.y[self.isq], self.rs) dae.g[self.vrd] = -dae.y[self.vrd] + mul( 1 - dae.x[self.omega_m], mul(dae.x[self.irq], self.x1) + mul(dae.y[self.isq], self.xmu)) - mul(dae.x[self.ird], self.rr) dae.g[self.vrq] = -dae.y[self.vrq] - mul( dae.x[self.irq], self.rr) - mul( 1 - dae.x[self.omega_m], mul(dae.x[self.ird], self.x1) + mul(dae.y[self.isd], self.xmu)) dae.g[self.vsd] = -dae.y[self.vsd] - mul(dae.y[self.v], sin(dae.y[self.a])) dae.g[self.vsq] = -dae.y[self.vsq] + mul(dae.y[self.v], cos(dae.y[self.a])) dae.g[self.vref] = self.vref0 - dae.y[self.vref] # dae.g[self.pwa] = mul(2*dae.x[self.omega_m] - 1, toSb) - dae.y[self.pwa] dae.g[self.pwa] = mmax(mmin(2 * dae.x[self.omega_m] - 1, 1), 0) - dae.y[self.pwa] dae.hard_limit(self.pwa, 0, 1) dae.g[self.pw] = -dae.y[self.pw] + mul( 0.5, dae.y[self.cp], self.ngen, pi, self.rho, (self.R)**2, (self.Vwn)**3, div(1, self.mva_mega), (dae.x[self.vw])**3) dae.g[self.cp] = -dae.y[self.cp] + mul( -1.1 + mul(25.52, div(1, dae.y[self.ilamb])) + mul(-0.08800000000000001, dae.x[self.theta_p]), exp(mul(-12.5, div(1, dae.y[self.ilamb])))) dae.g[self.lamb] = -dae.y[self.lamb] + mul( 4, self.R, self.fn, self.ngb, dae.x[self.omega_m], pi, div(1, self.Vwn), div(1, self.npole), div(1, dae.x[self.vw])) dae.g[self.ilamb] = div( 1, div(1, dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p])) + mul(-0.035, div(1, 1 + (dae.x[self.theta_p])**3))) - dae.y[self.ilamb] dae.g += spmatrix( mul( self.u0, -mul(dae.x[self.ird], dae.y[self.vrd]) - mul(dae.x[self.irq], dae.y[self.vrq]) - mul(dae.y[self.isd], dae.y[self.vsd]) - mul(dae.y[self.isq], dae.y[self.vsq])), self.a, [0] * self.n, (dae.m, 1), 'd') dae.g += spmatrix( mul( self.u0, mul((dae.y[self.v])**2, div(1, self.x0)) + mul(dae.x[self.ird], dae.y[self.v], self.xmu, div( 1, self.x0))), self.v, [0] * self.n, (dae.m, 1), 'd')
def gycall(self, dae): dae.add_jac( Gy, mul(0.5, self.ngen, pi, self.rho, (self.R)**2, (self.Vwn)**3, div(1, self.mva_mega), (dae.x[self.vw])**3), self.pw, self.cp) dae.add_jac( Gy, mul(-25.52, (dae.y[self.ilamb])**-2, exp(mul(-12.5, div(1, dae.y[self.ilamb])))) + mul( 12.5, (dae.y[self.ilamb])**-2, -1.1 + mul(25.52, div(1, dae.y[self.ilamb])) + mul(-0.08800000000000001, dae.x[self.theta_p]), exp(mul(-12.5, div(1, dae.y[self.ilamb])))), self.cp, self.ilamb) dae.add_jac( Gy, mul((dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p]))**-2, (div(1, dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p])) + mul(-0.035, div(1, 1 + (dae.x[self.theta_p])**3)))**-2), self.ilamb, self.lamb)
def F(x=None, z=None): # beta without constant x[:d], constant x[d], t = x[d+1:] if x is None: return 2 * d, matrix(0.0,(2*d+1,1)) # m = 2 *d is the number of constraints absE = absA*x[:d+1] # 0 - d contains the constant absW = exp(absE) cmpE = cmpA*x[:d+1] cmpW = exp(cmpE) f = matrix(0.0,(2*d+1,1)) f[0] = absWeight*(-sum(absE) + sum(log(1+absW))) + cmpWeight*(-sum(cmpE) + sum(log(1+cmpW))) + lamda * sum(x[d+1:])# from d+1 withou the constant f[1:d+1] = x[:d] - x[d+1:] # beta - t < 0 f[d+1:] = -x[:d] - x[d+1:] # -beta - t <0 Df = matrix(0.0,(2*d+1,2*d+1)) Df[0,:d+1] = absWeight*(matrix(absA.T * (div(absW,1+absW)-1.0))).T + cmpWeight*(matrix(cmpA.T * (div(cmpW,1+cmpW)-1.0))).T Df[0,d+1:] = lamda Df[1:d+1,0:d] = spdiag(matrix(1.0,(d,1))) Df[d+1:, 0:d] = spdiag(matrix(-1.0,(d,1))) Df[1:d+1,d+1:] = spdiag(matrix(-1.0,(d,1))) Df[d+1:,d+1:] = spdiag(matrix(-1.0,(d,1))) if z is None: return f ,Df H = matrix(0.0,(2*d+1,2*d+1)) H[0:d+1,0:d+1] = absWeight*(absA.T *spdiag(div(absW, (1 + absW) ** 2)) * absA) + cmpWeight*(cmpA.T *spdiag(div(cmpW, (1 +cmpW) ** 2)) * cmpA) return f, Df, z[0]*H
def gcall(self, dae): dae.g[self.pw] = -dae.y[self.pw] + mul( 0.5, dae.y[self.cp], self.ngen, pi, self.rho, (self.R)**2, (self.Vwn)**3, div(1, self.mva_mega), (dae.x[self.vw])**3) dae.g[self.lamb] = -dae.y[self.lamb] + mul( 4, self.R, self.fn, self.ngb, dae.x[self.omega_m], pi, div(1, self.Vwn), div(1, self.npole), div(1, dae.x[self.vw])) dae.g[self.cp] = -dae.y[self.cp] + mul( -1.1 + mul(25.52, dae.y[self.ilamb]) + mul(-0.08800000000000001, dae.x[self.theta_p]), exp(mul(-12.5, dae.y[self.ilamb]))) dae.g[self.ilamb] = div( 1, dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p])) - dae.y[self.ilamb] + mul( -0.035, div(1, 1 + (dae.x[self.theta_p])**3))
def windpower(self, ngen, rho, vw, Ar, R, omega, theta, derivative=False): mva_mega = self.system.mva * 1e6 lamb = omega * R / vw ilamb = 1 / (1 / (lamb + 0.08 * theta) - 0.035 / (theta**3 + 1)) cp = 0.22 * (116 / ilamb - 0.4 * theta - 5) * exp(-12.5 / ilamb) pw = 0.5 * ngen * rho * cp * Ar * vw**3 / mva_mega a1 = exp(-12.5 / ilamb) a2 = (lamb + 0.08 * theta)**2 a3 = 116. / ilamb - 0.4 * theta - 5 a4 = -9.28 / (lamb + 0.08 * theta) ** 2 + \ 12.180 * theta * theta / (theta ** 3 + 1) ** 2 - 0.4 a5 = 1.000 / (lamb + 0.08 * theta) ** 2 - \ 1.3125 * theta * theta / (theta ** 3 + 1) ** 2 jac = ones(1, 3) jac[0] = ngen * R * a1 * rho * vw * vw * Ar * ( -12.760 + 1.3750 * a3) / a2 / mva_mega jac[1] = ngen * (omega * R * (12.760 - 1.3750 * a3) / a2 + 0.330 * a3 * vw) * vw * Ar * rho * a1 / mva_mega jac[2] = ngen * 0.110 * rho * (a4 + a3 * a5) * a1 * Ar * vw**3 / mva_mega return pw, jac
def get_kernel(X, Y, type='linear', param=1.0): """Calculates a kernel given the data X and Y (dims x exms)""" (Xdims,Xn) = X.size (Ydims,Yn) = Y.size kernel = matrix(1.0) if type=='linear': print('Calculating linear kernel with size {0}x{1}.'.format(Xn,Yn)) kernel = matrix([ dotu(X[:,i],Y[:,j]) for j in range(Yn) for i in range(Xn)], (Xn,Yn), 'd') if type=='rbf': print('Calculating Gaussian kernel with size {0}x{1}.'.format(Xn,Yn)) kernel = matrix([dotu(X[:,i]-Y[:,j],X[:,i]-Y[:,j]) for j in range(Yn) for i in range(Xn)], (Xn,Yn)) kernel = exp(-param*kernel) return kernel
def computeLoss(Z,Y,D,lam_t,lam_s,T,n_rows,n_cols,lh_trend): ''' This function evaluates the objective function at a given solution Z. ''' n_t=n_rows*n_cols*(T-2);#no. of temporal constraints n_lh=0 if lh_trend: n_year=T/52 n_lh=(n_year-2)*n_rows*n_cols n_s=D.size[0]-n_lh-n_t#no. of spatial constraints lam_vec=np.array(n_t*[lam_t]+n_s*[lam_s]+n_lh*[lam_t]).reshape((1,-1)) f1=np.sum(np.array(Z+mul(Y**2,exp(-Z)))) f2=float(lam_vec.dot( np.abs(np.array(D*Z)) )) return f1+f2
def solving_for_cloud_x(m, M): N, T = m.shape K = [1] for i in range(T): K.append(N) g = [1] for i in range(N * T): g.append(1 / M) F = np.zeros((N * T + 1, N * T)) F[0, :] = -1 * m.reshape(1, N * T) for i in range(T): for j in range(N): F[N * i + j + 1, j * T + i] = 1 solvers.options['show_progress'] = False sol_cloud = solvers.gp(K, matrix(F), log(matrix(g, tc='d'))) x_cloud = array(exp(sol_cloud['x'])).reshape((N, T)) return x_cloud
def F(x=None, z=None): # beta without constant x[:d], constant x[d], t = x[d+1:] if x is None: return 2 * d, matrix(0.0,(2*d+1,1)) # m = 2 *d is the number of constraints e = A*x[:d+1] # 0 - d contains the constant w = exp(e) f = matrix(0.0,(2*d+1,1)) f[0] = alpha*(-sum(e) + sum(log(1+w))) + lamda * sum(x[d+1::])# from d+1 withou the constant f[1:d+1] = x[:d] - x[d+1:] # beta - t < 0 f[d+1:] = -x[:d] - x[d+1:] # -beta - t <0 Df = matrix(0.0,(2*d+1,2*d+1)) # Df[0,:d+1] = (matrix(A.T * (div(w,1+w)-1.0))).T Df[0, :d + 1] = alpha*(matrix(A.T * (div(w, 1 + w) - 1.0))).T Df[0,d+1:] = lamda Df[1:d+1,0:d] = spdiag(matrix(1.0,(d,1))) Df[d+1:, 0:d] = spdiag(matrix(-1.0,(d,1))) Df[1:d+1,d+1:] = spdiag(matrix(-1.0,(d,1))) Df[d+1:,d+1:] = spdiag(matrix(-1.0,(d,1))) if z is None: return f ,Df H = matrix(0.0,(2*d+1,2*d+1)) H[0:d+1,0:d+1] = alpha*(A.T *spdiag(div(w, (1 + w) ** 2)) * A) return f, Df, z[0]*H
def get_kernel(X, Y, type='linear', param=1.0): """Calculates a kernel given the data X and Y (dims x exms)""" (Xdims, Xn) = X.size (Ydims, Yn) = Y.size kernel = matrix(1.0) if type == 'linear': print('Calculating linear kernel with size {0}x{1}.'.format( Xn, Yn)) kernel = matrix( [dotu(X[:, i], Y[:, j]) for j in range(Yn) for i in range(Xn)], (Xn, Yn), 'd') if type == 'rbf': print('Calculating Gaussian kernel with size {0}x{1}.'.format( Xn, Yn)) kernel = matrix([ dotu(X[:, i] - Y[:, j], X[:, i] - Y[:, j]) for j in range(Yn) for i in range(Xn) ], (Xn, Yn)) kernel = exp(-param * kernel) return kernel
def test_cvxopt_sparse(self): m = 100 n = 20 mu = cvxopt.exp( cvxopt.normal(m) ) F = cvxopt.normal(m, n) D = cvxopt.spdiag( cvxopt.uniform(m) ) x = Variable(m) exp = square(norm2(D*x)) # # TODO # # Test scipy sparse matrices. # def test_scipy_sparse(self): # m = 100 # n = 20 # mu = cvxopt.exp( cvxopt.normal(m) ) # F = cvxopt.normal(m, n) # x = Variable(m) # D = scipy.sparse.spdiags(1.5, 0, m, m ) # exp = square(norm2(D*x))
def fxcall(self, dae): dae.add_jac( Gx, mul(1.5, dae.y[self.cp], self.ngen, pi, self.rho, (self.R)**2, (self.Vwn)**3, div(1, self.mva_mega), (dae.x[self.vw])**2), self.pw, self.vw) dae.add_jac(Gx, mul(-0.088, exp(mul(-12.5, dae.y[self.ilamb]))), self.cp, self.theta_p) dae.add_jac( Gx, mul(-4, self.R, self.fn, self.ngb, dae.x[self.omega_m], pi, div(1, self.Vwn), div(1, self.npole), (dae.x[self.vw])**-2), self.lamb, self.vw) dae.add_jac( Gx, mul(4, self.R, self.fn, self.ngb, pi, div(1, self.Vwn), div(1, self.npole), div(1, dae.x[self.vw])), self.lamb, self.omega_m) dae.add_jac( Gx, mul(-0.08, (dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p]))**-2) + mul(0.10500000000000001, (dae.x[self.theta_p])**2, (1 + (dae.x[self.theta_p])**3)**-2), self.ilamb, self.theta_p)
def __init__(self, casefile, **kwargs): """ Optional keyword arguments: branch_rmin (default: -inf ) shunt_gmin (default: -inf ) gen_elim (default: 0.0 ) truncate_gen_bounds (default: None ) line_constraints (default: True ) scale (default: False ) """ self.to_real = kwargs.get('to_real', True) self.conversion = kwargs.get('conversion', False) self.scale = kwargs.get('scale', False) self.shunt_gmin = kwargs.get('shunt_gmin', -float('inf')) self.branch_rmin = kwargs.get('branch_rmin', -float('inf')) self.gen_elim = kwargs.get('gen_elim', 0.0) self.truncate_gen_bounds = kwargs.get('truncate_gen_bounds',None) self.line_constraints = kwargs.get('line_constraints', True) self.pad_constraints = kwargs.get('pad_constraints', True) self.__verbose = kwargs.get('verbose',0) self.eigtol = kwargs.get('eigtol',1e5) ### load data data = _load_case(casefile, verbose = kwargs.get('verbose',0)) assert data['version'] == '2' if kwargs.get('verbose',0): print("Extracting data from case file.") ### add data to object self.baseMVA = data['baseMVA'] self.cost_scale = self.baseMVA self.nbus = data['bus'].shape[0] # branches in service active_branches = [i for i in range(data['branch'].shape[0]) if data['branch'][i,10] > 0] self.nbranch = len(active_branches) # generators in service active_generators = [i for i in range(data['gen'].shape[0]) if data['gen'][i,7] > 0] self.ngen = len(active_generators) # bus data self.busses = [] for k in range(self.nbus): bus = {'id': int(data['bus'][k,0]), 'type': int(data['bus'][k,1]), 'Pd': data['bus'][k,2] / self.baseMVA, 'Qd': data['bus'][k,3] / self.baseMVA, 'Gs': data['bus'][k,4], 'Bs': data['bus'][k,5], 'area': data['bus'][k,6], 'Vm': data['bus'][k,7], 'Va': data['bus'][k,8], 'baseKV': data['bus'][k,9], 'maxVm': data['bus'][k,11], 'minVm': data['bus'][k,12]} if bus['Gs'] < self.shunt_gmin: bus['Gs'] = self.shunt_gmin self.busses.append(bus) self.bus_id_to_index = {} for k, bus in enumerate(self.busses): self.bus_id_to_index[bus['id']] = k # generator data self.generators = [] ii_p = 0 ii_q = 0 for k in active_generators: gen = {'bus_id': int(data['gen'][k,0]), 'Pg': data['gen'][k,1] / self.baseMVA, 'Pmax': data['gen'][k,8] / self.baseMVA, 'Pmin': data['gen'][k,9] / self.baseMVA, 'Qg': data['gen'][k,2] / self.baseMVA, 'Qmax': data['gen'][k,3] / self.baseMVA, 'Qmin': data['gen'][k,4] / self.baseMVA, 'Vg': data['gen'][k,5], 'mBase': data['gen'][k,6] } if gen['Pmax'] > gen['Pmin'] + self.gen_elim: gen['pslack'] = ii_p ii_p += 1 else: # eliminate slack variable and set Pmin and Pmax to their average gen['pslack'] = None gen['Pmin'] = (gen['Pmax'] + gen['Pmin'])/2.0 gen['Pmax'] = gen['Pmin'] if gen['Qmax'] > gen['Qmin'] + self.gen_elim: gen['qslack'] = ii_q ii_q += 1 else: # eliminate slack variable and set Qmin and Qmax to their average gen['qslack'] = None gen['Qmin'] = (gen['Qmax'] + gen['Qmin'])/2.0 gen['Qmax'] = gen['Qmin'] if self.truncate_gen_bounds: if gen['Pmin'] < -self.truncate_gen_bounds or gen['Pmax'] > self.truncate_gen_bounds: if kwargs.get('verbose',0): print("Warning: generator at bus %i with large active bound(s); decreasing bound(s)"%(gen['bus_id'])) gen['Pmin'] = max(-self.truncate_gen_bounds, gen['Pmin']) gen['Pmax'] = min( self.truncate_gen_bounds, gen['Pmax']) if gen['Qmin'] < -self.truncate_gen_bounds or gen['Qmax'] > self.truncate_gen_bounds: if kwargs.get('verbose',0): print("Warning: generator at bus %i with large reactive bound(s); decreasing bound(s)"%(gen['bus_id'])) gen['Qmin'] = max(-self.truncate_gen_bounds, gen['Qmin']) gen['Qmax'] = min( self.truncate_gen_bounds, gen['Qmax']) self.generators.append(gen) self.bus_id_to_genlist = {} for k, gen in enumerate(self.generators): if gen['bus_id'] in self.bus_id_to_genlist: self.bus_id_to_genlist[gen['bus_id']].append(k) else: self.bus_id_to_genlist[gen['bus_id']] = [k] # branch data self.branches = [] for k in active_branches: branch = {'from': int(data['branch'][k,0]), 'to': int(data['branch'][k,1]), 'r': data['branch'][k,2], 'x': data['branch'][k,3], 'b': data['branch'][k,4], 'rateA': data['branch'][k,5], 'rateB': data['branch'][k,6], 'rateC': data['branch'][k,7], 'ratio': data['branch'][k,8], 'angle': data['branch'][k,9], 'angle_min': data['branch'][k,11], 'angle_max': data['branch'][k,12] } if branch['r'] < self.branch_rmin: if kwargs.get('verbose',0): print("Warning: branch (%i:%i->%i) with small resistance; enforcing min. resistance"%(k,branch['from'],branch['to'])) branch['r'] = self.branch_rmin if not self.line_constraints: branch['rateA'] = 0.0 if not self.pad_constraints: branch['angle_min'] = -360.0 branch['angle_max'] = 360.0 elif (branch['angle_min'] > -360.0 and branch['angle_min'] <= -180.0) or (branch['angle_max'] < 360.0 and branch['angle_max'] >= 180.0) or (branch['angle_min']==0.0 and branch['angle_max']==0.0): if kwargs.get('verbose',0): print("Warning: branch (%i:%i->%i) with unsupported phase angle diff. constraint; dropping constraint"%(k,branch['from'],branch['to'])) branch['angle_min'] = -360.0 branch['angle_max'] = 360.0 self.branches.append(branch) # gen cost for i, k in enumerate(active_generators): gencost = {'model': int(data['gencost'][k,0]), 'startup': data['gencost'][k,1], 'shutdown': data['gencost'][k,2], 'ncoef': int(data['gencost'][k,3]), 'coef': data['gencost'][k,4:].T } if gencost['model'] == 1: raise TypeError("Piecewise linear cost functions are not supported.") self.generators[i]['Pcost'] = gencost if data['gencost'].shape[0] == 2*data['gen'].shape[0]: offset = data['gen'].shape[0] for i, k in enumerate(active_generators): gencost = {'model': int(data['gencost'][offset + k,0]), 'startup': data['gencost'][offset + k,1], 'shutdown': data['gencost'][offset + k,2], 'ncoef': int(data['gencost'][offset + k,3]), 'coef': data['gencost'][offset + k,4:].T } self.generators[i]['Qcost'] = gencost ### Compute bus admittance matrix and connection matrices j = complex(0.0,1.0) r = matrix([branch['r'] for branch in self.branches]) b = matrix([branch['b'] for branch in self.branches]) x = matrix([branch['x'] for branch in self.branches]) Gs = matrix([bus['Gs'] for bus in self.busses]) Bs = matrix([bus['Bs'] for bus in self.busses]) tap = matrix([1.0 if branch['ratio'] == 0.0 else branch['ratio'] for branch in self.branches]) angle = matrix([branch['angle'] for branch in self.branches]) tap = mul(tap, exp(j*pi/180.*angle)) self.tap = tap Ys = div(1.0, r + j*x) Ytt = Ys + j*b/2.0 Yff = div(Ytt, mul(tap, tap.H.T)) Yft = -div(Ys, tap.H.T) Ytf = -div(Ys, tap) Ysh = (Gs+j*Bs)/self.baseMVA self.Ybr = [] for k in range(self.nbranch): self.Ybr.append([[Yff[k],Yft[k]],[Ytf[k],Ytt[k]]]) f = matrix([self.bus_id_to_index[branch['from']] for branch in self.branches]) t = matrix([self.bus_id_to_index[branch['to']] for branch in self.branches]) Cf = spmatrix(1.0, range(self.nbranch), f, (self.nbranch,self.nbus)) Ct = spmatrix(1.0, range(self.nbranch), t, (self.nbranch,self.nbus)) Yf = spmatrix(matrix([Yff,Yft]), 2*list(range(self.nbranch)), matrix([f,t]), (self.nbranch,self.nbus)) Yt = spmatrix(matrix([Ytf,Ytt]), 2*list(range(self.nbranch)), matrix([f,t]), (self.nbranch,self.nbus)) Ybus = Cf.T*Yf + Ct.T*Yt + spmatrix(Ysh, range(self.nbus), range(self.nbus), (self.nbus,self.nbus)) self.Cf = Cf self.Ct = Ct self.Yf = Yf self.Yt = Yt self.Ybus = Ybus if kwargs.get('verbose',0): print("Building cone LP.") self._build_conelp() if self.conversion: if kwargs.get('verbose',0): if kwargs.get('coupling','full') == 'full': print("Applying chordal conversion to cone LP.") else: print("Applying partial chordal conversion to cone LP.") _conelp_convert(self, **kwargs) if self.scale: if kwargs.get('verbose',0): print("Scaling cone LP.") _conelp_scale(self, **kwargs) if self.to_real: if kwargs.get('verbose',0): print("Converting to real-valued cone LP.") _conelp_to_real(self, **kwargs) return
def Se(self): dae = self.system.DAE vfout = dae.x[self.vfout] return mul(self.Ae, exp(mul(self.Be, abs(vfout))))
def fxcall(self, dae): omega = not0(dae.x[self.omega_m]) toSb = div(self.Sn, self.system.mva) dae.add_jac(Gx, mul(self.x1, 1 - dae.x[self.omega_m]), self.vrd, self.irq) dae.add_jac( Gx, -mul(dae.x[self.irq], self.x1) - mul(dae.y[self.isq], self.xmu), self.vrd, self.omega_m) dae.add_jac( Gx, mul(dae.x[self.ird], self.x1) + mul(dae.y[self.isd], self.xmu), self.vrq, self.omega_m) dae.add_jac(Gx, -mul(self.x1, 1 - dae.x[self.omega_m]), self.vrq, self.ird) dae.add_jac( Gx, mul(1.5, dae.y[self.cp], self.ngen, pi, self.rho, (self.R)**2, (self.Vwn)**3, div(1, self.mva_mega), (dae.x[self.vw])**2), self.pw, self.vw) dae.add_jac(Gx, mul(-0.088, exp(mul(-12.5, div(1, dae.y[self.ilamb])))), self.cp, self.theta_p) dae.add_jac( Gx, mul(-4, self.R, self.fn, self.ngb, dae.x[self.omega_m], pi, div(1, self.Vwn), div(1, self.npole), (dae.x[self.vw])**-2), self.lamb, self.vw) dae.add_jac( Gx, mul(4, self.R, self.fn, self.ngb, pi, div(1, self.Vwn), div(1, self.npole), div(1, dae.x[self.vw])), self.lamb, self.omega_m) dae.add_jac( Gx, mul((div(1, dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p])) + mul(-0.035, div(1, 1 + (dae.x[self.theta_p])**3)))**-2, mul(0.08, (dae.y[self.lamb] + mul(0.08, dae.x[self.theta_p]))**-2) + mul(-0.105, (dae.x[self.theta_p])**2, (1 + (dae.x[self.theta_p])**3)**-2)), self.ilamb, self.theta_p) dae.add_jac(Gx, -mul(self.u0, dae.y[self.vrq]), self.a, self.irq) dae.add_jac(Gx, -mul(self.u0, dae.y[self.vrd]), self.a, self.ird) dae.add_jac(Gx, mul(self.u0, dae.y[self.v], self.xmu, div(1, self.x0)), self.v, self.ird) dae.add_jac( Fx, mul(dae.y[self.pwa], self.x0, toSb, div(1, self.Te), (dae.x[self.omega_m])**-2, div(1, dae.y[self.v]), div(1, self.xmu)), self.irq, self.omega_m) dae.add_jac( Fy, mul(dae.y[self.pwa], self.x0, toSb, div(1, self.Te), div(1, omega), (dae.y[self.v])**-2, div(1, self.xmu)), self.irq, self.v) dae.add_jac( Fy, -mul(self.x0, toSb, div(1, self.Te), div(1, omega), div(1, dae.y[self.v]), div(1, self.xmu)), self.irq, self.pwa) dae.add_jac(Fx, mul(0.5, dae.y[self.isq], self.xmu, div(1, self.H)), self.omega_m, self.ird) dae.add_jac( Fx, mul(-0.5, dae.y[self.pw], div(1, self.H), (dae.x[self.omega_m])**-2), self.omega_m, self.omega_m) dae.add_jac(Fx, mul(-0.5, dae.y[self.isd], self.xmu, div(1, self.H)), self.omega_m, self.irq) dae.add_jac(Fy, mul(0.5, div(1, self.H), div(1, dae.x[self.omega_m])), self.omega_m, self.pw) dae.add_jac(Fy, mul(-0.5, dae.x[self.irq], self.xmu, div(1, self.H)), self.omega_m, self.isd) dae.add_jac(Fy, mul(0.5, dae.x[self.ird], self.xmu, div(1, self.H)), self.omega_m, self.isq)
# The small GP of section 9.3 (Geometric programming). from cvxopt import matrix, log, exp, solvers Aflr = 1000.0 Awall = 100.0 alpha = 0.5 beta = 2.0 gamma = 0.5 delta = 2.0 F = matrix([[-1., 1., 1., 0., -1., 1., 0., 0.], [-1., 1., 0., 1., 1., -1., 1., -1.], [-1., 0., 1., 1., 0., 0., -1., 1.]]) g = log( matrix([ 1.0, 2 / Awall, 2 / Awall, 1 / Aflr, alpha, 1 / beta, gamma, 1 / delta ])) K = [1, 2, 1, 1, 1, 1, 1] h, w, d = exp(solvers.gp(K, F, g)['x']) print("\n h = %f, w = %f, d = %f.\n" % (h, w, d))
b[6][2] = 0.5 * A[6][2, :] * (C[5] + C[6]) # For regions k=1, ..., 6, let pk be the optimal value of # # minimize x'*x # subject to A*x <= b. # # The Chernoff upper bound is 1.0 - sum exp( - pk / (2 sigma^2)). P = matrix([1.0, 0.0, 0.0, 1.0], (2, 2)) q = matrix(0.0, (2, 1)) optvals = matrix( [blas.nrm2(solvers.qp(P, q, A[k], b[k])['x'])**2 for k in range(1, 7)]) nopts = 200 sigmas = 0.2 + (0.5 - 0.2) / nopts * matrix(list(range(nopts)), tc='d') bnds = [1.0 - sum(exp(-optvals / (2 * sigma**2))) for sigma in sigmas] try: import pylab except ImportError: pass else: pylab.figure(facecolor='w') pylab.plot(sigmas, bnds, '-') pylab.axis([0.2, 0.5, 0.9, 1.0]) pylab.title('Chernoff lower bound (fig. 7.8)') pylab.xlabel('sigma') pylab.ylabel('Probability of correct detection') pylab.show() if 0: # uncomment out for the Monte Carlo estimation.
def F(x=None, z=None): """ Evaluates the objective and nonlinear constraint functions. """ if x is None: # Include power mismatch constraint twice to force equality. nln_N = self.om.nln_N + neqnln return nln_N, x0 # Evaluate objective function ------------------------------------- Pgen = x[Pg.i1:Pg.iN + 1] # Active generation in p.u. Qgen = x[Qg.i1:Qg.iN + 1] # Reactive generation in p.u. xx = matrix([Pgen, Qgen]) * base_mva # Evaluate the objective function value. if len(ipol) > 0: # FIXME: Implement reactive power costs. f0 = sum([g.total_cost(xx[i]) for i, g in enumerate(gn)]) else: f0 = 0 # Piecewise linear cost of P and Q. if ny: y = self.om.get_var("y") ccost = spmatrix(matrix(1.0, (ny, 1)), range(y.i1, y.iN + 1), matrix(0.0, (ny, 1)), size=(nxyz, 1)).T f0 = f0 + ccost * x else: ccost = matrix(0.0, (1, nxyz)) # TODO: Generalised cost term. # Evaluate cost gradient ------------------------------------------ iPg = range(Pg.i1, Pg.iN + 1) iQg = range(Qg.i1, Qg.iN + 1) # Polynomial cost of P and Q. df_dPgQg = matrix(0.0, (2 * ng, 1)) # w.r.t p.u. Pg and Qg for i in ipol: df_dPgQg[i] = \ base_mva * polyval(polyder(list(gn[i].p_cost)), xx[i]) df0 = matrix(0.0, (nxyz, 1)) df0[iPg] = df_dPgQg[:ng] df0[iQg] = df_dPgQg[ng:ng + ng] # Piecewise linear cost of P and Q. df0 = df0 + ccost.T # TODO: Generalised cost term. # Evaluate cost Hessian ------------------------------------------- # d2f = None # Evaluate nonlinear equality constraints ------------------------- for i, g in enumerate(gn): g.p = Pgen[i] * base_mva # active generation in MW g.q = Qgen[i] * base_mva # reactive generation in MVAr # Rebuild the net complex bus power injection vector in p.u. Sbus = matrix(case.getSbus(bs)) Vang = x[Va.i1:Va.iN + 1] Vmag = x[Vm.i1:Vm.iN + 1] V = mul(Vmag, exp(1j * Vang)) # Evaluate the power flow equations. mis = mul(V, conj(Ybus * V)) - Sbus # Equality constraints (power flow). g = matrix([ mis.real(), # active power mismatch for all buses mis.imag() ]) # reactive power mismatch for all buses # Evaluate nonlinear inequality constraints ----------------------- # Inequality constraints (branch flow limits). # (line constraint is actually on square of limit) flow_max = matrix([(l.rate_a / base_mva)**2 for l in ln]) # FIXME: There must be a more elegant way to do this. for i, rate in enumerate(flow_max): if rate == 0.0: flow_max[i] = 1e5 if self.flow_lim == IFLOW: If = Yf * V It = Yt * V # Branch current limits. h = matrix([(If * conj(If)) - flow_max, (If * conj(It)) - flow_max]) else: i_fbus = [e.from_bus._i for e in ln] i_tbus = [e.to_bus._i for e in ln] # Complex power injected at "from" bus (p.u.). Sf = mul(V[i_fbus], conj(Yf * V)) # Complex power injected at "to" bus (p.u.). St = mul(V[i_tbus], conj(Yt * V)) if self.flow_lim == PFLOW: # active power limit, P (Pan Wei) # Branch real power limits. h = matrix( [Sf.real()**2 - flow_max, St.real()**2 - flow_max]) elif self.flow_lim == SFLOW: # apparent power limit, |S| # Branch apparent power limits. h = matrix([ mul(Sf, conj(Sf)) - flow_max, mul(St, conj(St)) - flow_max ]).real() else: raise ValueError # Evaluate partial derivatives of constraints --------------------- iVa = matrix(range(Va.i1, Va.iN + 1)) iVm = matrix(range(Vm.i1, Vm.iN + 1)) iPg = matrix(range(Pg.i1, Pg.iN + 1)) iQg = matrix(range(Qg.i1, Qg.iN + 1)) iVaVmPgQg = matrix([iVa, iVm, iPg, iQg]).T # Compute partials of injected bus powers. dSbus_dVm, dSbus_dVa = dSbus_dV(Ybus, V) i_gbus = [gen.bus._i for gen in gn] neg_Cg = spmatrix(matrix(-1.0, (ng, 1)), i_gbus, range(ng), (nb, ng)) # Transposed Jacobian of the power balance equality constraints. dg = spmatrix([], [], [], (nxyz, 2 * nb)) blank = spmatrix([], [], [], (nb, ng)) dg[iVaVmPgQg, :] = sparse([[dSbus_dVa.real(), dSbus_dVa.imag()], [dSbus_dVm.real(), dSbus_dVm.imag()], [neg_Cg, blank], [blank, neg_Cg]]).T # Compute partials of flows w.r.t V. if self.flow_lim == IFLOW: dFf_dVa, dFf_dVm, dFt_dVa, dFt_dVm, Ff, Ft = \ dIbr_dV(Yf, Yt, V) else: dFf_dVa, dFf_dVm, dFt_dVa, dFt_dVm, Ff, Ft = \ dSbr_dV(Yf, Yt, V, bs, ln) if self.flow_lim == PFLOW: dFf_dVa = dFf_dVa.real dFf_dVm = dFf_dVm.real dFt_dVa = dFt_dVa.real dFt_dVm = dFt_dVm.real Ff = Ff.real Ft = Ft.real # Squared magnitude of flow (complex power, current or real power). df_dVa, df_dVm, dt_dVa, dt_dVm = \ dAbr_dV(dFf_dVa, dFf_dVm, dFt_dVa, dFt_dVm, Ff, Ft) # Construct Jacobian of inequality constraints (branch limits) and # transpose it. dh = spmatrix([], [], [], (nxyz, 2 * nl)) dh[matrix([iVa, iVm]).T, :] = sparse([[df_dVa, dt_dVa], [df_dVm, dt_dVm]]).T f = matrix([f0, g, h, -g]) df = matrix([[df0], [dg], [dh], [-dg]]).T if z is None: return f, df # Evaluate cost Hessian ------------------------------------------- nxtra = nxyz - (2 * nb) # Evaluate d2f ---------------------------------------------------- d2f_dPg2 = matrix(0.0, (ng, 1)) # w.r.t p.u. Pg d2f_dQg2 = matrix(0.0, (ng, 1)) # w.r.t p.u. Qg for i in ipol: d2f_dPg2[i, 0] = polyval(polyder(list(gn[i].p_cost), 2), Pg.v0[i] * base_mva) * base_mva**2 # TODO: Reactive power costs. # for i in ipol: # d2f_dQg2[i] = polyval(polyder(list(gn[i].q_cost), 2), # Qg.v0[i] * base_mva) * base_mva**2 i = matrix([range(Pg.i1, Pg.iN + 1), range(Qg.i1, Qg.iN + 1)]) d2f = spmatrix(matrix([d2f_dPg2, d2f_dQg2]), i, i, (nxyz, nxyz)) # TODO: Generalised cost model. d2f = d2f * self.opt["cost_mult"] # Evaluate Hessian of power balance constraints ------------------- eqnonlin = z[1:neqnln + 1] nlam = len(eqnonlin) / 2 lamP = eqnonlin[:nlam] lamQ = eqnonlin[nlam:nlam + nlam] Gpaa, Gpav, Gpva, Gpvv = d2Sbus_dV2(Ybus, V, lamP) Gqaa, Gqav, Gqva, Gqvv = d2Sbus_dV2(Ybus, V, lamQ) d2G_1 = sparse([[ sparse([[Gpaa, Gpva], [Gpav, Gpvv]]).real() + sparse([[Gqaa, Gqva], [Gqav, Gqvv]]).imag() ], [spmatrix([], [], [], (2 * nb, nxtra))]]) d2G_2 = spmatrix([], [], [], (nxtra, 2 * nb + nxtra)) d2G = sparse([d2G_1, d2G_2]) # Evaluate Hessian of flow constraints --------------------------- ineqnonlin = z[1 + neqnln:1 + neqnln + niqnln] nmu = len(ineqnonlin) / 2 muF = ineqnonlin[:nmu] muT = ineqnonlin[nmu:nmu + nmu] if self.flow_lim == IFLOW: dIf_dVa, dIf_dVm, dIt_dVa, dIt_dVm, If, It = \ dIbr_dV(Yf, Yt, V) Hfaa, Hfav, Hfva, Hfvv = \ d2AIbr_dV2(dIf_dVa, dIf_dVm, If, Yf, V, muF) Htaa, Htav, Htva, Htvv = \ d2AIbr_dV2(dIt_dVa, dIt_dVm, It, Yt, V, muT) else: fr = [e.from_bus._i for e in ln] to = [e.to_bus._i for e in ln] # Line-bus connection matrices. Cf = spmatrix(1.0, range(nl), fr, (nl, nb)) Ct = spmatrix(1.0, range(nl), to, (nl, nb)) dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St = \ dSbr_dV(Yf, Yt, V, bs, ln) if self.flow_lim == PFLOW: Hfaa, Hfav, Hfva, Hfvv = \ d2ASbr_dV2(dSf_dVa.real(), dSf_dVm.real(), Sf.real(), Cf, Yf, V, muF) Htaa, Htav, Htva, Htvv = \ d2ASbr_dV2(dSt_dVa.real(), dSt_dVm.real(), St.real(), Ct, Yt, V, muT) elif self.flow_lim == SFLOW: Hfaa, Hfav, Hfva, Hfvv = \ d2ASbr_dV2(dSf_dVa, dSf_dVm, Sf, Cf, Yf, V, muF) Htaa, Htav, Htva, Htvv = \ d2ASbr_dV2(dSt_dVa, dSt_dVm, St, Ct, Yt, V, muT) else: raise ValueError d2H_1 = sparse([[ sparse([[Hfaa, Hfva], [Hfav, Hfvv]]) + sparse([[Htaa, Htva], [Htav, Htvv]]) ], [spmatrix([], [], [], (2 * nb, nxtra))]]) d2H_2 = spmatrix([], [], [], (nxtra, 2 * nb + nxtra)) d2H = sparse([d2H_1, d2H_2]) Lxx = d2f + d2G + d2H return f, df, Lxx
def polar(m, a): """Return complex number from polar form m*exp(1j*a)""" return mul(m, exp(1j * a))
def sigmoid(X): return (1.0 + co.exp(-X))**(-1)
def dSe(self): dae = self.system.dae vfout = dae.x[self.vfout] return mul(self.Ae, exp(mul(self.Be, abs(vfout)))) \ + mul(self.Ae, self.Be, abs(vfout), exp(mul(self.Be, abs(vfout))))
import cvxopt import numpy from cvxpy import * from multiprocessing import Pool from pylab import figure, show import math num_assets = 100 num_factors = 20 mu = cvxopt.exp(cvxopt.normal(num_assets)) F = cvxopt.normal(num_assets, num_factors) D = cvxopt.spdiag(cvxopt.uniform(num_assets)) x = Variable(num_assets) gamma = Parameter(sign="positive") expected_return = mu.T * x variance = square(norm2(F.T * x)) + square(norm2(D * x)) # construct portfolio optimization problem *once* p = Problem(Maximize(expected_return - gamma * variance), [sum(x) == 1, x >= 0]) # encapsulate the allocation function def allocate(gamma_value): gamma.value = gamma_value p.solve() w = x.value expected_return, risk = mu.T * w, w.T * (F * F.T + D * D) * w return (expected_return[0], math.sqrt(risk[0]))
import cvxopt import numpy from cvxpy import * from multiprocessing import Pool from pylab import figure, show import math num_assets = 100 num_factors = 20 mu = cvxopt.exp( cvxopt.normal(num_assets) ) F = cvxopt.normal(num_assets, num_factors) D = cvxopt.spdiag( cvxopt.uniform(num_assets) ) x = Variable(num_assets) gamma = Parameter(sign="positive") expected_return = mu.T * x variance = square(norm2(F.T*x)) + square(norm2(D*x)) # construct portfolio optimization problem *once* p = Problem( Maximize(expected_return - gamma * variance), [sum(x) == 1, x >= 0] ) # encapsulate the allocation function def allocate(gamma_value): gamma.value = gamma_value p.solve() w = x.value expected_return, risk = mu.T*w, w.T*(F*F.T + D*D)*w
def init1(self, dae): """New initialization function""" self.servcall(dae) retval = True mva = self.system.mva self.p0 = mul(self.p0, self.gammap) self.q0 = mul(self.q0, self.gammaq) dae.y[self.vsd] = mul(dae.y[self.v], -sin(dae.y[self.a])) dae.y[self.vsq] = mul(dae.y[self.v], cos(dae.y[self.a])) rs = matrix(self.rs) rr = matrix(self.rr) xmu = matrix(self.xmu) x1 = matrix(self.xs) + xmu x2 = matrix(self.xr) + xmu Pg = matrix(self.p0) Qg = matrix(self.q0) Vc = dae.y[self.v] vsq = dae.y[self.vsq] vsd = dae.y[self.vsd] toSn = div(mva, self.Sn) # to machine base toSb = self.Sn / mva # to system base # rotor speed omega = 1 * (ageb(mva * Pg, self.Sn)) + \ mul(0.5 + 0.5 * mul(Pg, toSn), aandb(agtb(Pg, 0), altb(mva * Pg, self.Sn))) + \ 0.5 * (aleb(mva * Pg, 0)) slip = 1 - omega theta = mul(self.Kp, mround(1000 * (omega - 1)) / 1000) theta = mmax(theta, 0) # prepare for the iterations irq = mul(-x1, toSb, (2 * omega - 1), div(1, Vc), div(1, xmu), div(1, omega)) isd = zeros(*irq.size) isq = zeros(*irq.size) # obtain ird isd isq for i in range(self.n): A = sparse([[-rs[i], vsq[i]], [x1[i], -vsd[i]]]) B = matrix([vsd[i] - xmu[i] * irq[i], Qg[i]]) linsolve(A, B) isd[i] = B[0] isq[i] = B[1] ird = -div(vsq + mul(rs, isq) + mul(x1, isd), xmu) vrd = -mul(rr, ird) + mul( slip, mul(x2, irq) + mul(xmu, isq)) # todo: check x1 or x2 vrq = -mul(rr, irq) - mul(slip, mul(x2, ird) + mul(xmu, isd)) # main iterations for i in range(self.n): mis = ones(6, 1) rows = [0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5] cols = [0, 1, 3, 0, 1, 2, 2, 4, 3, 5, 0, 1, 2] x = matrix([isd[i], isq[i], ird[i], irq[i], vrd[i], vrq[i]]) # vals = [-rs, x1, xmu, -x1, -rs, -xmu, -rr, # -1, -rr, -1, vsd, vsq, -xmu * Vc / x1] vals = [ -rs[i], x1[i], xmu[i], -x1[i], -rs[i], -xmu[i], -rr[i], -1, -rr[i], -1, vsd[i], vsq[i], -xmu[i] * Vc[i] / x1[i] ] jac0 = spmatrix(vals, rows, cols, (6, 6), 'd') niter = 0 while max(abs(mis)) > self.system.tds.config.tol: if niter > 20: logger.error('Initialization of DFIG <{}> failed.'.format( self.name[i])) retval = False break mis[0] = -rs[i] * x[0] + x1[i] * x[1] + xmu[i] * x[3] - vsd[i] mis[1] = -rs[i] * x[1] - x1[i] * x[0] - xmu[i] * x[2] - vsq[i] mis[2] = -rr[i] * x[2] + slip[i] * (x2[i] * x[3] + xmu[i] * x[1]) - x[4] mis[3] = -rr[i] * x[3] - slip[i] * (x2[i] * x[2] + xmu[i] * x[0]) - x[5] mis[4] = vsd[i] * x[0] + vsq[i] * x[1] + x[4] * x[2] + \ x[5] * x[3] - Pg[i] mis[5] = -xmu[i] * Vc[i] * x[2] / x1[i] - \ Vc[i] * Vc[i] / x1[i] - Qg[i] rows = [2, 2, 3, 3, 4, 4, 4, 4] cols = [1, 3, 0, 2, 2, 3, 4, 5] vals = [ slip[i] * xmu[i], slip[i] * x2[i], -slip[i] * xmu[i], -slip[i] * x2[i], x[4], x[5], x[2], x[3] ] jac = jac0 + spmatrix(vals, rows, cols, (6, 6), 'd') linsolve(jac, mis) x -= mis niter += 1 isd[i] = x[0] isq[i] = x[1] ird[i] = x[2] irq[i] = x[3] vrd[i] = x[4] vrq[i] = x[5] dae.x[self.ird] = mul(self.u0, ird) dae.x[self.irq] = mul(self.u0, irq) dae.y[self.isd] = isd dae.y[self.isq] = isq dae.y[self.vrd] = vrd dae.y[self.vrq] = vrq dae.x[self.omega_m] = mul(self.u0, omega) dae.x[self.theta_p] = mul(self.u0, theta) dae.y[self.pwa] = mmax(mmin(2 * dae.x[self.omega_m] - 1, 1), 0) self.vref0 = mul(aneb(self.KV, 0), Vc - div(ird + div(Vc, xmu), self.KV)) dae.y[self.vref] = self.vref0 k = mul(div(x1, Vc, xmu, omega), toSb) self.irq_off = -mul(k, mmax(mmin(2 * omega - 1, 1), 0)) - irq # electrical torque in pu te = mul( xmu, mul(dae.x[self.irq], dae.y[self.isd]) - mul(dae.x[self.ird], dae.y[self.isq])) for i in range(self.n): if te[i] < 0: logger.error( 'Pe < 0 on bus <{}>. Wind speed initialize failed.'.format( self.bus[i])) retval = False # wind power in pu pw = mul(te, omega) dae.y[self.pw] = pw # wind speed initialization loop R = 4 * pi * self.system.freq * mul(self.R, self.ngb, div( 1, self.npole)) AA = pi * self.R**2 vw = 0.9 * self.Vwn for i in range(self.n): mis = 1 niter = 0 while abs(mis) > self.system.tds.config.tol: if niter > 50: logger.error( 'Wind <{}> init failed. ' 'Try increasing the nominal wind speed.'.format( self.wind[i])) retval = False break pw_iter, jac = self.windpower(self.ngen[i], self.rho[i], vw[i], AA[i], R[i], omega[i], theta[i]) mis = pw_iter - pw[i] inc = -mis / jac[1] vw[i] += inc niter += 1 # set wind speed dae.x[self.vw] = div(vw, self.Vwn) lamb = div(omega, vw, div(1, R)) ilamb = div(1, (div(1, lamb + 0.08 * theta) - div(0.035, theta**3 + 1))) cp = 0.22 * mul( div(116, ilamb) - 0.4 * theta - 5, exp(div(-12.5, ilamb))) dae.y[self.lamb] = lamb dae.y[self.ilamb] = ilamb dae.y[self.cp] = cp self.system.rmgen(self.gen) if not retval: logger.error('DFIG initialization failed') return retval
c = -matrix([sum( uk for uk, yk in zip(u,y) if yk ), sum(y) ]) # minimize c'*x + sum log (1 + exp(A*x)) # # variable x (2). def F(x=None, z=None): if x is None: return 0, matrix(0.0, (2,1)) w = exp(A*x) f = c.T*x + sum(log(1+w)) grad = c + A.T * div(w, 1+w) if z is None: return f, grad.T H = A.T * spdiag(div(w,(1+w)**2)) * A return f, grad.T, z[0]*H sol = solvers.cp(F) a, b = sol['x'][0], sol['x'][1] try: import pylab except ImportError: pass else: pylab.figure(facecolor='w') nopts = 200 pts = -1.0 + 12.0/nopts * matrix(list(range(nopts))) w = exp(a*pts + b) pylab.plot(u, y, 'o', pts, div(w, 1+w), '-') pylab.title('Logistic regression (fig. 7.1)') pylab.axis([-1, 11, -0.1, 1.1]) pylab.xlabel('u') pylab.ylabel('Prob(y=1)') pylab.show()
# Basis functions are Gabor pulses: for k = 0,...,K-1, # # exp(-(t - k * tau)^2/sigma^2 ) * cos (l*omega0*t), l = 0,...,L # exp(-(t - k * tau)^2/sigma^2 ) * sin (l*omega0*t), l = 1,...,L sigma = 0.05 tau = 0.002 omega0 = 5.0 K = 501 L = 30 N = 501 # number of samples of each signal in [0,1] # Build dictionary matrix ts = (1.0/N) * matrix(range(N), tc='d') B = ts[:, K*[0]] - tau * matrix(range(K), (1,K), 'd')[N*[0],:] B = exp(-(B/sigma)**2) A = matrix(0.0, (N, K*(2*L+1))) # First K columns are DC pulses for k = 0,...,K-1 A[:,:K] = B for l in range(L): # Cosine pulses for omega = (l+1)*omega0 and k = 0,...,K-1. A[:, K+l*(2*K) : K+l*(2*K)+K] = mul(B, cos((l+1)*omega0*ts)[:, K*[0]]) # Sine pulses for omega = (l+1)*omega0 and k = 0,...,K-1. A[:, K+l*(2*K)+K : K+(l+1)*(2*K)] = \ mul(B, sin((l+1)*omega0*ts)[:,K*[0]]) if pylab_installed:
# For regions k=1, ..., 6, let pk be the optimal value of # # minimize x'*x # subject to A*x <= b. # # The Chernoff upper bound is 1.0 - sum exp( - pk / (2 sigma^2)). P = matrix([1.0, 0.0, 0.0, 1.0], (2,2)) q = matrix(0.0, (2,1)) optvals = matrix([ blas.nrm2( solvers.qp(P, q, A[k], b[k] )['x'] )**2 for k in range(1,7) ]) nopts = 200 sigmas = 0.2 + (0.5 - 0.2)/nopts * matrix(list(range(nopts)), tc='d') bnds = [ 1.0 - sum( exp( - optvals / (2*sigma**2) )) for sigma in sigmas] try: import pylab except ImportError: pass else: pylab.figure(facecolor='w') pylab.plot(sigmas, bnds, '-') pylab.axis([0.2, 0.5, 0.9, 1.0]) pylab.title('Chernoff lower bound (fig. 7.8)') pylab.xlabel('sigma') pylab.ylabel('Probability of correct detection') pylab.show() if 0: # uncomment out for the Monte Carlo estimation. N = 100000
# Basis functions are Gabor pulses: for k = 0,...,K-1, # # exp(-(t - k * tau)^2/sigma^2 ) * cos (l*omega0*t), l = 0,...,L # exp(-(t - k * tau)^2/sigma^2 ) * sin (l*omega0*t), l = 1,...,L sigma = 0.05 tau = 0.002 omega0 = 5.0 K = 501 L = 30 N = 501 # number of samples of each signal in [0,1] # Build dictionary matrix ts = (1.0 / N) * matrix(range(N), tc='d') B = ts[:, K * [0]] - tau * matrix(range(K), (1, K), 'd')[N * [0], :] B = exp(-(B / sigma)**2) A = matrix(0.0, (N, K * (2 * L + 1))) # First K columns are DC pulses for k = 0,...,K-1 A[:, :K] = B for l in range(L): # Cosine pulses for omega = (l+1)*omega0 and k = 0,...,K-1. A[:, K + l * (2 * K):K + l * (2 * K) + K] = mul( B, cos((l + 1) * omega0 * ts)[:, K * [0]]) # Sine pulses for omega = (l+1)*omega0 and k = 0,...,K-1. A[:, K+l*(2*K)+K : K+(l+1)*(2*K)] = \ mul(B, sin((l+1)*omega0*ts)[:,K*[0]])
def PA_GP_MCS_minRate(channel_alloc, channel_gain, B, noise_vec, priority, SU_power, minRate, SNR_gap, QAM_cap, objective_list): n_su = channel_alloc.shape[0] n_channel = channel_alloc.shape[1] channel_gain = copy.deepcopy(channel_gain) Noise = copy.deepcopy(noise_vec) channel_gain = channel_gain * (10**8) Noise = Noise * (10**8) # non-zero power list channel_alloc_total = np.sum(channel_alloc, dtype=np.int32) def A(m, n, j, t): if (t == n): return -1 else: if (t == j): return 1 else: return 0 def C(m, n, j): if (j == n): return (Noise[n]) / (channel_gain[n, n] / SNR_gap[n]) else: return channel_gain[n, j] / (channel_gain[n, n] / SNR_gap[n]) # Objective function F_obj = np.zeros(channel_alloc_total * 2) i = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): F_obj[channel_alloc_total + i] = priority[n] * B / (10**6) i = i + 1 g_obj = np.zeros(1) # Constraints of slack variables (m => n => j) n_F_slack = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): for j in range(n_su): if (channel_alloc[j, m] == 1): n_F_slack = n_F_slack + 1 F_slack = np.zeros((n_F_slack, channel_alloc_total * 2)) index0 = 0 index1 = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): for j in range(n_su): if (channel_alloc[j, m] == 1): F_slack[index0, channel_alloc_total + index1] = -1 index3 = 0 for t in range(n_su): if (channel_alloc[t, m] == 1): F_slack[index0, int(np.sum(channel_alloc[:, 0:m])) + index3] = A(m, n, j, t) index3 = index3 + 1 index0 = index0 + 1 index1 = index1 + 1 g_slack = np.zeros(n_F_slack) index0 = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): for j in range(n_su): if (channel_alloc[j, m] == 1): g_slack[index0] = np.log(C(m, n, j)) index0 = index0 + 1 # Constraints of maximum power F_power = np.zeros((channel_alloc_total, channel_alloc_total * 2)) index0 = 0 for n in range(n_su): for m in range(n_channel): if (channel_alloc[n, m] == 1): F_power[index0, int(np.sum(channel_alloc[:, 0:m])) + int(np.sum(channel_alloc[:(n + 1), m])) - 1] = 1 index0 = index0 + 1 g_power = np.zeros(channel_alloc_total) index0 = 0 for n in range(n_su): for m in range(n_channel): if (channel_alloc[n, m] == 1): g_power[index0] = np.log(1 / SU_power[n]) index0 = index0 + 1 # Constraints of minimum data rate constraint F_minRate = np.zeros((n_su, channel_alloc_total * 2)) index0 = 0 for n in range(n_su): for m in range(n_channel): if (channel_alloc[n, m] == 1): F_minRate[n, channel_alloc_total + index0] = B / (10**6) index0 = index0 + 1 g_minRate = np.zeros(n_su) for n in range(n_su): g_minRate[n] = np.log(2**(minRate[n] / (10**6))) # Constraints of QAM capability F_QAM = np.zeros((channel_alloc_total, channel_alloc_total * 2)) index0 = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): F_QAM[index0, channel_alloc_total + index0] = 1 index0 = index0 + 1 g_QAM = np.zeros(channel_alloc_total) index0 = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): g_QAM[index0] = np.log(2**-(QAM_cap[n] + 1)) index0 = index0 + 1 K_obj = np.ones(1) K_slack = n_su * np.ones(channel_alloc_total) index0 = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): K_slack[index0] = np.sum(channel_alloc[:, m]) index0 = index0 + 1 K_power = n_channel * np.ones(n_su) for n in range(n_su): K_power[n] = np.sum(channel_alloc[n, :]) K_minRate = np.ones(n_su) K_QAM = np.ones(channel_alloc_total) K_arr = np.concatenate((K_obj, K_slack, K_power, K_minRate, K_QAM)) K_arr = K_arr.astype(int) F_arr = np.vstack((F_obj, F_slack, F_power, F_minRate, F_QAM)) g_arr = np.concatenate((g_obj, g_slack, g_power, g_minRate, g_QAM)) K = K_arr.tolist() F_arr = F_arr.T F = cvx.matrix(F_arr.tolist()) g_arr = g_arr.T g = cvx.matrix(g_arr.tolist()) cvx.solvers.options['show_progress'] = False sol = cvx.exp(cvx.solvers.gp(K, F, g, quiet=True)['x']) power_alloc = np.zeros((n_su, n_channel)) index0 = 0 for m in range(n_channel): for n in range(n_su): if (channel_alloc[n, m] == 1): power_alloc[n, m] = sol[index0] index0 = index0 + 1 objective_list['total'].append( objective_value(channel_alloc, power_alloc, priority, channel_gain / (10**8), B, noise_vec, SNR_gap)) return power_alloc
# The small GP of section 9.3 (Geometric programming). from cvxopt import matrix, log, exp, solvers Aflr = 1000.0 Awall = 100.0 alpha = 0.5 beta = 2.0 gamma = 0.5 delta = 2.0 F = matrix( [[-1., 1., 1., 0., -1., 1., 0., 0.], [-1., 1., 0., 1., 1., -1., 1., -1.], [-1., 0., 1., 1., 0., 0., -1., 1.]]) g = log( matrix( [1.0, 2/Awall, 2/Awall, 1/Aflr, alpha, 1/beta, gamma, 1/delta]) ) K = [1, 2, 1, 1, 1, 1, 1] h, w, d = exp( solvers.gp(K, F, g)['x'] ) print("\n h = %f, w = %f, d = %f.\n" %(h,w,d))
def F(x=None, z=None): if x is None: return 0, matrix(0.0, (2, 1)) w = exp(A * x) f = c.T * x + sum(log(1 + w)) grad = c + A.T * div(w, 1 + w) if z is None: return f, grad.T H = A.T * spdiag(div(w, (1 + w)**2)) * A return f, grad.T, z[0] * H sol = solvers.cp(F) a, b = sol['x'][0], sol['x'][1] try: import pylab except ImportError: pass else: pylab.figure(facecolor='w') nopts = 200 pts = -1.0 + 12.0 / nopts * matrix(list(range(nopts))) w = exp(a * pts + b) pylab.plot(u, y, 'o', pts, div(w, 1 + w), '-') pylab.title('Logistic regression (fig. 7.1)') pylab.axis([-1, 11, -0.1, 1.1]) pylab.xlabel('u') pylab.ylabel('Prob(y=1)') pylab.show()
def _solve(self): # An alias to the internal problem instance. p = self.int # This class doubles as an implementation for the SMCP solver. solver = self.ext.options['solver'].lower() assert solver in ("cvxopt", "smcp") isGP = self._is_geometric_program() # Check if the problem type is supported. # TODO: Check if general-obj problems are properly handled. if solver == 'smcp': # SMCP is a standalone solver made available through the SMCPSolver # class. However, since SMCP both depends on CVXOPT and has a # similar interface, its logic is implemented inside CVXOPTSolver, # and SMCPSolver subclasses it. Ensure that self is indeed a # SMCPSolver instance. assert self.__class__.__name__ == "SMCPSolver", \ "SMCP needs to be used through the SMCPSolver class." import smcp # Clear all options set previously. This is necessary because CVXOPT # options are global, and might be changed even by another problem. cvx.solvers.options.clear() # Handle "verbose" option. cvx.solvers.options['show_progress'] = (self.verbosity() >= 1) # Handle "tol", "feastol", "abstol" and "reltol" options. feastol = self.ext.options['feastol'] if feastol is None: feastol = self.ext.options['tol'] abstol = self.ext.options['abstol'] if abstol is None: abstol = self.ext.options['tol'] reltol = self.ext.options['reltol'] if reltol is None: reltol = 10 * self.ext.options['tol'] cvx.solvers.options['feastol'] = feastol cvx.solvers.options['abstol'] = abstol cvx.solvers.options['reltol'] = reltol # Handle "maxit" option. maxit = self.ext.options['maxit'] if maxit is None: maxit = int(1e6) cvx.solvers.options['maxiters'] = maxit # Allow solving GPs that are not strictly feasible. # TODO: Turn this into a proper option? cvx.solvers.options['kktreg'] = 1e-6 # Handle unsupported options. self._handle_unsupported_options('lp_root_method', 'lp_node_method', 'timelimit', 'treememory', 'nbsol', 'hotstart') # TODO: Add CVXOPT-sepcific options. Candidates are: # - refinement # Set options for SMCP. if solver == 'smcp': # Restore default options. smcp.solvers.options = self._smcp_default_options.copy() # Copy options also used by CVXOPT. smcp.solvers.options.update(cvx.solvers.options) # Further handle "verbose" option. smcp.solvers.options['debug'] = (self.verbosity() >= 2) # TODO: Add SMCP-sepcific options. if self._debug(): from pprint import pformat if solver == 'smcp': options = smcp.solvers.options else: options = cvx.solvers.options self._debug("Setting options:\n{}\n".format(pformat(options))) # Print a header. if solver == 'smcp': subsolverText = None else: if isGP: subsolverText = 'internal GP solver' else: subsolverText = 'internal CONELP solver' # Further prepare the problem for the CVXOPT/SMCP CONELP solvers. # TODO: This should be done during import. if not isGP: # Retrieve the structure of the cone, which is a cartesian product # of the non-negative orthant of dimension l, a number of second # order cones with dimensions in q and a number of positive # semidefinite cones with dimensions in s. dims = { 'l': p['Gl'].size[0], 'q': [Gqi.size[0] for Gqi in p['Gq']], 's': [int(numpy.sqrt(Gsi.size[0])) for Gsi in p['Gs']] } # Construct G and h to contain all conic inequalities, starting with # those with respect to the non-negative orthant. G = p['Gl'] h = p['hl'] # SMCP's ConeLP solver does not handle (linear) equalities, so cast # them as inequalities. if solver == 'smcp': if p['A'].size[0] > 0: G = cvx.sparse([G, p['A']]) G = cvx.sparse([G, -p['A']]) h = cvx.matrix([h, p['b']]) h = cvx.matrix([h, -p['b']]) dims['l'] += (2 * p['A'].size[0]) # Add second-order cone inequalities. for i in range(len(dims['q'])): G = cvx.sparse([G, p['Gq'][i]]) h = cvx.matrix([h, p['hq'][i]]) # Add semidefinite cone inequalities. for i in range(len(dims['s'])): G = cvx.sparse([G, p['Gs'][i]]) h = cvx.matrix([h, p['hs'][i]]) # Remove zero lines from linear equality constraint matrix, as # CVXOPT expects this matrix to have full row rank. JP = list(set(p['A'].I)) IP = range(len(JP)) VP = [1] * len(JP) if any([b for (i, b) in enumerate(p['b']) if i not in JP]): raise SolverError( 'Infeasible constraint of the form 0 = a with a != 0.') P = spmatrix(VP, IP, JP, (len(IP), p['A'].size[0])) A = P * p['A'] b = P * p['b'] # Attempt to solve the problem. with self._header(subsolverText), self._stopwatch(): if solver == 'smcp': if self._debug(): self._debug( "Calling smcp.solvers.conelp(c, G, h, dims) " "with\nc:\n{}\nG:\n{}\nh:\n{}\ndims:\n{}\n".format( p['c'], G, h, dims)) try: result = smcp.solvers.conelp(p['c'], G, h, dims) except TypeError: # HACK: Work around "'NoneType' object is not subscriptable" # exception with infeasible/unbounded problems. result = None else: if isGP: result = cvx.solvers.gp(p['K'], p['F'], p['g'], p['Gl'], p['hl'], p['A'], p['b'], kktsolver='ldl') else: result = cvx.solvers.conelp(p['c'], G, h, dims, A, b) # Retrieve primals. if self.ext.options["noprimals"]: primals = None elif result is None or result["x"] is None: primals = None else: primals = {} # Retrieve values for all but LSE auxiliary variables. for var in self.ext.variables.values(): # Auxiliary variables for LSE metaconstraints have no # meaningful value at this point. if isinstance(var.origin, LSEConstraint): continue # HACK: Cast from numpy array to list so that _retrieve_matrix # will respect the target matrix size. # TODO: Refactor _retrieve_matrix to handle different input # types consistently. value = list(result["x"][var.startIndex:var.endIndex]) primals[var.name] = value # Give auxiliary variables added for an LSE metaconstraint a # solution value. for var in self.ext.variables.values(): if isinstance(var.origin, LSEConstraint): value = [] for i, exponent in enumerate(var.origin.le0Exponents): value.append( cvx.matrix(exponent.constant if exponent. constant else 0.0)) for v, factor in exponent.factors.items(): value[i] += factor * cvx.matrix(primals[v.name]) value[i] = cvx.exp(value[i])[0, 0] primals[var.name] = cvx.matrix(value, var.size) # Retrieve duals. if self.ext.options["noduals"]: duals = None elif result is None: duals = None else: duals = [] (indy, indzl, indzq, indznl, indzs) = (0, 0, 0, 0, 0) if isGP: zkey = 'zl' zqkey = 'zq' zskey = 'zs' else: zkey = 'z' zqkey = 'z' zskey = 'z' indzq = dims['l'] indzs = dims['l'] + _bsum(dims['q']) if solver == 'smcp': # Equality constraints were cast as two inequalities. ieq = p['Gl'].size[0] neq = (dims['l'] - ieq) // 2 soleq = result['z'][ieq:ieq + neq] soleq -= result['z'][ieq + neq:ieq + 2 * neq] else: soleq = result['y'] seenLSEConstraints = [] for constraint in self.ext.constraints: dual = None consSz = len(constraint) if isinstance(constraint.origin, LSEConstraint): # We are looking at an auxiliary constraint for a # metaconstraint that was imported directly. # We don't get any duals: # - The affine constraint was imported for technical reasons # and all variables used in it are irrelevant to the # objective function. Hence the dual will always be 0. # We don't store it since that could produce a bad result # when querying the LSE metaconstraint for its dual. # - The exponential cone constraints were never imported. # Instead, a single LSE constraint was imported. if isinstance(constraint, AffineConstraint): assert constraint.is_inequality() indzl += len(constraint) # = 1 else: assert isinstance(constraint, ExpConeConstraint) if constraint.origin not in seenLSEConstraints: indznl += len(constraint.origin) # = 1 seenLSEConstraints.append(constraint.origin) elif isinstance(constraint, AffineConstraint): if constraint.is_equality(): if soleq is not None: dual = (P.T * soleq)[indy:indy + consSz] indy += consSz else: if result[zkey] is not None: dual = result[zkey][indzl:indzl + consSz] indzl += consSz elif isinstance(constraint, SOCConstraint) \ or isinstance(constraint, RSOCConstraint): if result[zqkey] is not None: if isGP: dual = result[zqkey][indzq] dual[1:] = -dual[1:] indzq += 1 else: dual = result[zqkey][indzq:indzq + consSz] # Swap the sign of the SOcone's Lagrange multiplier, # as PICOS wants it the other way round. # Note that this also affects RScone constraints # which were cast as SOcone constraints on import. dual[1:] = -dual[1:] if isinstance(constraint, RSOCConstraint): # RScone were cast as a SOcone on import, so # transform the dual to a proper RScone dual. alpha = dual[0] - dual[-1] beta = dual[0] + dual[-1] z = 2.0 * dual[1:-1] dual = cvx.matrix([alpha, beta, z]) indzq += consSz elif isinstance(constraint, LMIConstraint): if result[zskey] is not None: matSz = constraint.size[0] if isGP: dual = cvx.matrix(result[zskey][indzs], (matSz, matSz)) indzs += 1 else: dual = cvx.matrix( result[zskey][indzs:indzs + consSz], (matSz, matSz)) indzs += consSz duals.append(dual) # Retrieve objective value. if result is None: objectiveValue = None elif isGP: objectiveValue = 'toEval' else: p = result['primal objective'] d = result['dual objective'] if p is not None and d is not None: objectiveValue = 0.5 * (p + d) elif p is not None: objectiveValue = p elif d is not None: objectiveValue = d else: objectiveValue = None if self.ext.objective[0] == 'max' and objectiveValue is not None: objectiveValue = -objectiveValue # Retrieve solution metadata. meta = { 'cvxopt_sol': result, 'status': result['status'] if result else "unavailable" } return (primals, duals, objectiveValue, meta)
def F(x=None, z=None): """ Evaluates the objective and nonlinear constraint functions. """ if x is None: # Include power mismatch constraint twice to force equality. nln_N = self.om.nln_N + neqnln return nln_N, x0 # Evaluate objective function ------------------------------------- Pgen = x[Pg.i1:Pg.iN + 1] # Active generation in p.u. Qgen = x[Qg.i1:Qg.iN + 1] # Reactive generation in p.u. xx = matrix([Pgen, Qgen]) * base_mva # Evaluate the objective function value. if len(ipol) > 0: # FIXME: Implement reactive power costs. f0 = sum([g.total_cost(xx[i]) for i, g in enumerate(gn)]) else: f0 = 0 # Piecewise linear cost of P and Q. if ny: y = self.om.get_var("y") ccost = spmatrix(matrix(1.0, (ny, 1)), range(y.i1, y.iN + 1), matrix(0.0, (ny, 1)), size=(nxyz, 1)).T f0 = f0 + ccost * x else: ccost = matrix(0.0, (1, nxyz)) # TODO: Generalised cost term. # Evaluate cost gradient ------------------------------------------ iPg = range(Pg.i1, Pg.iN + 1) iQg = range(Qg.i1, Qg.iN + 1) # Polynomial cost of P and Q. df_dPgQg = matrix(0.0, (2 * ng, 1)) # w.r.t p.u. Pg and Qg for i in ipol: df_dPgQg[i] = \ base_mva * polyval(polyder(list(gn[i].p_cost)), xx[i]) df0 = matrix(0.0, (nxyz, 1)) df0[iPg] = df_dPgQg[:ng] df0[iQg] = df_dPgQg[ng:ng + ng] # Piecewise linear cost of P and Q. df0 = df0 + ccost.T # TODO: Generalised cost term. # Evaluate cost Hessian ------------------------------------------- # d2f = None # Evaluate nonlinear equality constraints ------------------------- for i, g in enumerate(gn): g.p = Pgen[i] * base_mva # active generation in MW g.q = Qgen[i] * base_mva # reactive generation in MVAr # Rebuild the net complex bus power injection vector in p.u. Sbus = matrix(case.getSbus(bs)) Vang = x[Va.i1:Va.iN + 1] Vmag = x[Vm.i1:Vm.iN + 1] V = mul(Vmag, exp(1j * Vang)) # Evaluate the power flow equations. mis = mul(V, conj(Ybus * V)) - Sbus # Equality constraints (power flow). g = matrix([mis.real(), # active power mismatch for all buses mis.imag()]) # reactive power mismatch for all buses # Evaluate nonlinear inequality constraints ----------------------- # Inequality constraints (branch flow limits). # (line constraint is actually on square of limit) flow_max = matrix([(l.rate_a / base_mva)**2 for l in ln]) # FIXME: There must be a more elegant way to do this. for i, rate in enumerate(flow_max): if rate == 0.0: flow_max[i] = 1e5 if self.flow_lim == IFLOW: If = Yf * V It = Yt * V # Branch current limits. h = matrix([(If * conj(If)) - flow_max, (If * conj(It)) - flow_max]) else: i_fbus = [e.from_bus._i for e in ln] i_tbus = [e.to_bus._i for e in ln] # Complex power injected at "from" bus (p.u.). Sf = mul(V[i_fbus], conj(Yf * V)) # Complex power injected at "to" bus (p.u.). St = mul(V[i_tbus], conj(Yt * V)) if self.flow_lim == PFLOW: # active power limit, P (Pan Wei) # Branch real power limits. h = matrix([Sf.real()**2 - flow_max, St.real()**2 - flow_max]) elif self.flow_lim == SFLOW: # apparent power limit, |S| # Branch apparent power limits. h = matrix([mul(Sf, conj(Sf)) - flow_max, mul(St, conj(St)) - flow_max]).real() else: raise ValueError # Evaluate partial derivatives of constraints --------------------- iVa = matrix(range(Va.i1, Va.iN + 1)) iVm = matrix(range(Vm.i1, Vm.iN + 1)) iPg = matrix(range(Pg.i1, Pg.iN + 1)) iQg = matrix(range(Qg.i1, Qg.iN + 1)) iVaVmPgQg = matrix([iVa, iVm, iPg, iQg]).T # Compute partials of injected bus powers. dSbus_dVm, dSbus_dVa = dSbus_dV(Ybus, V) i_gbus = [gen.bus._i for gen in gn] neg_Cg = spmatrix(matrix(-1.0, (ng, 1)), i_gbus, range(ng), (nb, ng)) # Transposed Jacobian of the power balance equality constraints. dg = spmatrix([], [], [], (nxyz, 2 * nb)) blank = spmatrix([], [], [], (nb, ng)) dg[iVaVmPgQg, :] = sparse([ [dSbus_dVa.real(), dSbus_dVa.imag()], [dSbus_dVm.real(), dSbus_dVm.imag()], [neg_Cg, blank], [blank, neg_Cg] ]).T # Compute partials of flows w.r.t V. if self.flow_lim == IFLOW: dFf_dVa, dFf_dVm, dFt_dVa, dFt_dVm, Ff, Ft = \ dIbr_dV(Yf, Yt, V) else: dFf_dVa, dFf_dVm, dFt_dVa, dFt_dVm, Ff, Ft = \ dSbr_dV(Yf, Yt, V, bs, ln) if self.flow_lim == PFLOW: dFf_dVa = dFf_dVa.real dFf_dVm = dFf_dVm.real dFt_dVa = dFt_dVa.real dFt_dVm = dFt_dVm.real Ff = Ff.real Ft = Ft.real # Squared magnitude of flow (complex power, current or real power). df_dVa, df_dVm, dt_dVa, dt_dVm = \ dAbr_dV(dFf_dVa, dFf_dVm, dFt_dVa, dFt_dVm, Ff, Ft) # Construct Jacobian of inequality constraints (branch limits) and # transpose it. dh = spmatrix([], [], [], (nxyz, 2 * nl)) dh[matrix([iVa, iVm]).T, :] = sparse([[df_dVa, dt_dVa], [df_dVm, dt_dVm]]).T f = matrix([f0, g, h, -g]) df = matrix([[df0], [dg], [dh], [-dg]]).T if z is None: return f, df # Evaluate cost Hessian ------------------------------------------- nxtra = nxyz - (2 * nb) # Evaluate d2f ---------------------------------------------------- d2f_dPg2 = matrix(0.0, (ng, 1)) # w.r.t p.u. Pg d2f_dQg2 = matrix(0.0, (ng, 1)) # w.r.t p.u. Qg for i in ipol: d2f_dPg2[i, 0] = polyval(polyder(list(gn[i].p_cost), 2), Pg.v0[i] * base_mva) * base_mva**2 # TODO: Reactive power costs. # for i in ipol: # d2f_dQg2[i] = polyval(polyder(list(gn[i].q_cost), 2), # Qg.v0[i] * base_mva) * base_mva**2 i = matrix([range(Pg.i1, Pg.iN + 1), range(Qg.i1, Qg.iN + 1)]) d2f = spmatrix(matrix([d2f_dPg2, d2f_dQg2]), i, i, (nxyz, nxyz)) # TODO: Generalised cost model. d2f = d2f * self.opt["cost_mult"] # Evaluate Hessian of power balance constraints ------------------- eqnonlin = z[1:neqnln + 1] nlam = len(eqnonlin) / 2 lamP = eqnonlin[:nlam] lamQ = eqnonlin[nlam:nlam + nlam] Gpaa, Gpav, Gpva, Gpvv = d2Sbus_dV2(Ybus, V, lamP) Gqaa, Gqav, Gqva, Gqvv = d2Sbus_dV2(Ybus, V, lamQ) d2G_1 = sparse([[sparse([[Gpaa, Gpva], [Gpav, Gpvv]]).real() + sparse([[Gqaa, Gqva], [Gqav, Gqvv]]).imag()], [spmatrix([], [], [], (2 * nb, nxtra))]]) d2G_2 = spmatrix([], [], [], (nxtra, 2 * nb + nxtra)) d2G = sparse([d2G_1, d2G_2]) # Evaluate Hessian of flow constraints --------------------------- ineqnonlin = z[1 + neqnln:1 + neqnln + niqnln] nmu = len(ineqnonlin) / 2 muF = ineqnonlin[:nmu] muT = ineqnonlin[nmu:nmu + nmu] if self.flow_lim == IFLOW: dIf_dVa, dIf_dVm, dIt_dVa, dIt_dVm, If, It = \ dIbr_dV(Yf, Yt, V) Hfaa, Hfav, Hfva, Hfvv = \ d2AIbr_dV2(dIf_dVa, dIf_dVm, If, Yf, V, muF) Htaa, Htav, Htva, Htvv = \ d2AIbr_dV2(dIt_dVa, dIt_dVm, It, Yt, V, muT) else: fr = [e.from_bus._i for e in ln] to = [e.to_bus._i for e in ln] # Line-bus connection matrices. Cf = spmatrix(1.0, range(nl), fr, (nl, nb)) Ct = spmatrix(1.0, range(nl), to, (nl, nb)) dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St = \ dSbr_dV(Yf, Yt, V, bs, ln) if self.flow_lim == PFLOW: Hfaa, Hfav, Hfva, Hfvv = \ d2ASbr_dV2(dSf_dVa.real(), dSf_dVm.real(), Sf.real(), Cf, Yf, V, muF) Htaa, Htav, Htva, Htvv = \ d2ASbr_dV2(dSt_dVa.real(), dSt_dVm.real(), St.real(), Ct, Yt, V, muT) elif self.flow_lim == SFLOW: Hfaa, Hfav, Hfva, Hfvv = \ d2ASbr_dV2(dSf_dVa, dSf_dVm, Sf, Cf, Yf, V, muF) Htaa, Htav, Htva, Htvv = \ d2ASbr_dV2(dSt_dVa, dSt_dVm, St, Ct, Yt, V, muT) else: raise ValueError d2H_1 = sparse([[sparse([[Hfaa, Hfva], [Hfav, Hfvv]]) + sparse([[Htaa, Htva], [Htav, Htvv]])], [spmatrix([], [], [], (2 * nb, nxtra))]]) d2H_2 = spmatrix([], [], [], (nxtra, 2 * nb + nxtra)) d2H = sparse([d2H_1, d2H_2]) Lxx = d2f + d2G + d2H return f, df, Lxx