def test_vertex_rectangular(m = 5): np.random.seed(0) dom = BoxDomain(-np.ones(m), np.ones(m)) Xhat = dom.sample(10) X0 = dom.sample(100) L = np.ones((1, m)) check_vertex_sample(dom, Xhat, X0, L = L)
def test_vertex_eq(m = 5): np.random.seed(0) dom = BoxDomain(-np.ones(m), np.ones(m)) dom = dom.add_constraints(A_eq = np.ones(m), b_eq = [0]) Xhat = dom.sample(10) X0 = dom.sample(5) check_vertex_sample(dom, Xhat, X0)
def test_vertex_weight(m = 5): np.random.seed(0) dom = BoxDomain(-np.ones(m), np.ones(m)) Xhat = dom.sample(10) X0 = dom.sample(100) L = np.diag(1./np.arange(1,m+1)) check_vertex_sample(dom, Xhat, X0, L = L)
def test_vertex_low_rank_nonrandomize(m = 5): np.random.seed(0) dom = BoxDomain(-np.ones(m), np.ones(m)) Xhat = dom.sample(10) X0 = dom.sample(100) L = np.diag(1./np.arange(1,m+1)) L[0,0] = 0. check_vertex_sample(dom, Xhat, X0, L = L, randomize = False)
def test_sample_grid(m=3): lb = 0 * np.ones(m) ub = 1 * np.ones(m) dom = BoxDomain(lb, ub) X = dom.sample_grid(5) assert len(X) == 5**m
def test_func(): client = Client(processes = False) dom = BoxDomain(-1,1) fun = Function(func, dom, dask_client = client) X = dom.sample(5) res = fun.eval_async(X) for r, x in zip(res, X): print(r.result()) assert np.isclose(x, r.result())
def test_isinside(m=5): np.random.seed(0) dom = BoxDomain(-10 * np.ones(m), -5 * np.ones(m)) X = dom.sample(10) Xg = dom.sample_grid(2) hull = ConvexHullDomain(Xg) assert np.all(hull.isinside(X))
def test_fill_distance(m = 5): dom = BoxDomain(-np.ones(m), np.ones(m)) Xhat = dom.sample(10) X0 = dom.sample(1e2) x = seq_maximin_sample(dom, Xhat, X0 = X0) d = np.min(cdist(x.reshape(1,-1), Xhat)) d2 = fill_distance_estimate(dom, Xhat, X0 = X0) assert np.isclose(d, d2)
def test_box(m=10): dom = BoxDomain(-np.ones(m), np.ones(m)) assert len(dom) == m x = dom.corner(np.ones(m)) assert np.all(np.isclose(x, np.ones(m))) A = np.ones((1, m)) b = np.zeros(1) dom2 = dom.add_constraints(A_eq=A, b_eq=b) x = dom2.sample() assert np.isclose(np.dot(A, x), b)
def no_test_lipschitz_sample(N = 5, m = 3): dom = BoxDomain(-np.ones(m), np.ones(m)) # Add an inequality constraint so some combinations aren't feasible dom = dom.add_constraints(A = np.ones((1,m)), b = np.ones(1)) Ls = [np.random.randn(1,m) for j in range(2)] # Limit the number of iterations to reduce computational cost X = psdr.lipschitz_sample(dom, N, Ls, maxiter = 3, jiggle = False) print(X) assert np.all(dom.isinside(X)) # Verify that each point is distinct in projections for L in Ls: y = L.dot(X.T).T print(y) assert np.min(pdist(y)) > 0, "points not distinct in projection"
def test_return_grad2(m=3): A = np.random.randn(m, m) A += A.T B = np.random.randn(m, m) B += B.T def func(x, return_grad = False): fx = [0.5*x.dot(A.dot(x)), 0.5*x.dot(B.dot(x))] if return_grad: grad = [A.dot(x), B.dot(x)] return fx, grad else: return fx dom = BoxDomain(-2*np.ones(m), 2*np.ones(m)) fun = Function(func, dom, return_grad = True) X = fun.domain.sample(4) fX, grads = fun(X, return_grad = True) assert fX.shape == (len(X), 2) assert grads.shape == (len(X), 2, m) for x, grad in zip(X, grads): assert np.all(np.isclose(grad, fun.grad(x)))
def build_otl_circuit_domain(): # Parameters # R_b1, R_b2, R_f, R_c1, R_c2, beta lb = np.array([50, 25, 0.5, 1.2, 0.25, 50]) ub = np.array([150, 70, 3, 2.5, 1.2, 300]) return BoxDomain(lb, ub)
def build_borehole_domain(): # Parameters # r_w, r, T_u, H_u, T_l, H_l, L, K_w lb = np.array([0.05, 100, 63070, 990, 63.1, 700, 1120, 9855]) ub = np.array([0.15, 50e3, 115600, 1110, 116, 820, 1680, 12045]) return BoxDomain(lb, ub)
def test_lambda(): dom = BoxDomain(-1,1) def f(x): return x #f = lambda x: x print('about to start client') # We use a threaded version for sanity # https://github.com/dask/distributed/issues/2515 client = Client(processes = False) print(client) fun = Function(f, dom, dask_client = client) x = dom.sample(1) res = fun.eval_async(x) print(x, res.result()) assert np.isclose(x, res.result())
def build_oas_design_domain(n_cp=3): # Twist domain_twist = BoxDomain(-1 * np.ones(n_cp), 1 * np.ones(n_cp), names=['twist %d' % (i, ) for i in range(1, 4)]) # Thick domain_thick = BoxDomain( 0.005 * np.ones(n_cp), 0.05 * np.ones(n_cp), names=['thickness %d' % (i, ) for i in range(1, 4)]) # Root Chord domain_root_chord = BoxDomain(0.7, 1.3, names=['root chord']) # Taper ratio domain_taper_ratio = BoxDomain(0.75, 1.25, names=['taper ratio']) return TensorProductDomain( [domain_twist, domain_thick, domain_root_chord, domain_taper_ratio])
def build_beam_domain(): # Note the book has an invalid range for height "(20mm > b > 250 mm)" and breadth "(10 mm > b > 50mm)" # Here we follow the dimensions implied in the corresponding matlab code # b = x(1)*0.045 +0.005 # h = x(2)*0.23 + 0.02 # I assume these definitions are in meters domain = BoxDomain([5e-3, 0.02], [50e-3, 0.25], names=['breadth (m)', 'height (m)']) return domain
def build_golinski_design_domain(): return BoxDomain([2.6, 0.7, 7.3, 7.3, 2.9, 5.0], [3.6, 0.8, 8.3, 8.3, 3.9, 5.5], names=[ "width of gear face", "teeth module", "shaft 1 length between bearings", "shaft 2 length between bearings", "diameter of shaft 1", "diameter of shaft 2" ])
def test_mult_output(M= 10,m = 5): dom = BoxDomain(-np.ones(m), np.ones(m)) X = dom.sample(M) a = np.random.randn(m) b = np.random.randn(m) def fun_a(X): return a.dot(X.T) def fun_b(X): return b.dot(X.T) def fun(X): return np.vstack([X.dot(a), X.dot(b)]).T print("Single function with multiple outputs") for vectorized in [True, False]: myfun = Function(fun, dom, vectorized = vectorized) print(fun(X)) print("vectorized", vectorized) print(myfun(X).shape) assert myfun(X).shape == (M, 2) print(myfun(X[0]).shape) assert myfun(X[0]).shape == (2,) fX = fun(X) for i, x in enumerate(X): assert np.all(np.isclose(fX[i], fun(x))) print("Two functions with a single output each") for vectorized in [True, False]: myfun = Function([fun_a, fun_b], dom, vectorized = vectorized) print(fun(X)) print("vectorized", vectorized) print(myfun(X).shape) assert myfun(X).shape == (M, 2) print(myfun(X[0]).shape) assert myfun(X[0]).shape == (2,) fX = fun(X) for i, x in enumerate(X): assert np.all(np.isclose(fX[i], fun(x)))
def test_cheb(m=5): lb = -np.ones(m) ub = np.ones(m) dom = BoxDomain(lb, ub) A = np.ones((1, m)) b = np.zeros(1, ) dom2 = dom.add_constraints(A, b) center, radius = dom2.chebyshev_center() print center print radius assert dom2.isinside(center), "Center must be inside" for i in range(100): p = np.random.randn(m) p /= np.linalg.norm(p) assert dom2.extent(center, p) >= radius, "violated radius assumption"
def test_constraints(m=3): np.random.seed(0) dom = BoxDomain(-1 * np.ones(m), np.ones(m)) # Lower pyramid portion dom_con = dom.add_constraints(A=np.ones((1, m)), b=np.ones(1)) # Convex hull describes the same space as dom_con X = dom.sample_grid(2) hull = ConvexHullDomain(X, A=dom_con.A, b=dom_con.b) # Check that the same points are inside X = dom.sample(100) assert np.all(hull.isinside(X) == dom_con.isinside(X)) # Check sampling X = hull.sample(100) assert np.all(dom_con.isinside(X))
def test_vertex_full(m = 2): np.random.seed(0) dom = BoxDomain(-np.ones(m), np.ones(m)) Xhat = dom.sample(10) #check_vertex(dom, Xhat) # Check with degenerate points Xhat[1] = Xhat[0] #check_vertex(dom, Xhat) # Check with a Lipschitz matrix np.random.seed(0) Xhat = dom.sample(5) #L = np.random.randn(m,m) L = np.diag(np.arange(1, m+1)) print(L) print("Checking with a Lipschitz matrix") check_vertex(dom, Xhat, L = L)
def test_bad_scaling(): # TODO: This fails with ub = 1e7 # This is mainly due to solver tolerances lb = [-1, 1e7] ub = [1, 2e7] dom1 = BoxDomain(lb=lb, ub=ub) dom2 = LinQuadDomain(lb=lb, ub=ub, verbose=True) # Check quality of solution p = np.ones(len(dom1)) # this calls an algebraic formula x1 = dom1.corner(p) # whereas this calls a linear program x2 = dom2.corner(p) for x1_, x2_, lb_, ub_ in zip(x1, x2, dom2.lb, dom2.ub): print("x1:%+15.15e x2:%+15.15e delta:%+15.15e; lb: %+5.2e ub: %+5.2e" % (x1_, x2_, np.abs(x1_ - x2_), lb_, ub_)) assert np.all(np.isclose(x1, x2, rtol=1e-4, atol=1e-4))
def build_robot_arm_domain(): # Parameters # theta 1-4, L 1-4 lb = np.array([0, 0, 0, 0, 0, 0, 0, 0]) ub = np.array([2 * np.pi, 2 * np.pi, 2 * np.pi, 2 * np.pi, 1, 1, 1, 1]) return BoxDomain(lb, ub, names=[ 'theta_1', 'theta_2', 'theta_3', 'theta_4', 'L_1', 'L_2', 'L_3', 'L_4' ])
def test_closest_point(m=5): Ls = [np.eye(m)] ys = [np.zeros(m)] rhos = [1] dom1 = LinQuadDomain(Ls=Ls, ys=ys, rhos=rhos) dom2 = BoxDomain([2], [3]) dom = dom1 * dom2 x0 = np.zeros(m + 1) x = dom.closest_point(x0) assert np.all(np.isclose(x[0:m], 0)) assert np.all(np.isclose(x[-1], 2))
def build_hartmann_domain(): # Ranges are taken from GCSW17, Table 2 # The second parameter 'fluid density' does not appear in either function return BoxDomain( [0.05, 0.5, 0.5, 0.1], [0.2, 3, 3, 1], names=[ 'fluid viscosity', # mu 'applied pressure gradient', # d p_0/ dx 'resistivity', # eta 'applied magnetic field' # B_0 ])
def test_initial_sample(m = 10): dom = BoxDomain(-np.ones(m), np.ones(m)) L1 = np.random.randn(1,m) L2 = np.random.randn(2,m) L3 = np.random.randn(3,m) Nsamp = 100 for L in [L1, L2, L3]: # Standard uniform sampling X1 = dom.sample(Nsamp) LX1 = L.dot(X1.T).T d1 = pdist(LX1) # initial sample algorithm X2 = initial_sample(dom, L, Nsamp = Nsamp) assert np.all(dom.isinside(X2)) LX2 = L.dot(X2.T).T d2 = pdist(LX2) print("uniform sampling mean distance", np.mean(d1), 'min', np.min(d1)) print("initial sampling mean distance", np.mean(d2), 'min', np.min(d2)) assert np.mean(d2) > np.mean(d1), "Initial sampling ineffective"
def test_bad_scaling(): # TODO: This fails with ub = 1e7 # This is mainly due to solver tolerances lb = [-1, 1e7] ub = [1, 2e7] dom1 = BoxDomain(lb=lb, ub=ub) dom2 = LinQuadDomain(lb=lb, ub=ub) # Check quality of solution p = np.ones(len(dom1)) x1 = dom1.corner(p) x2 = dom2.corner(p, verbose=True, solver='ECOS', abstol=4e-10, reltol=1e-14, feastol=1e-14, max_iters=500) for x1_, x2_, lb_, ub_ in zip(x1, x2, dom2.lb, dom2.ub): print "x1:%+15.15e x2:%+15.15e delta:%+15.15e; lb: %+5.2e ub: %+5.2e" % ( x1_, x2_, np.abs(x1_ - x2_), lb_, ub_) assert np.all(np.isclose(x1, x2))
def test_point(m=3): lb = 0 * np.ones(m) ub = 1 * np.ones(m) dom = BoxDomain(lb, ub) assert dom.is_point == False dom = BoxDomain(ub, ub) assert dom.is_point == True dom = BoxDomain(lb, ub) dom = dom.add_constraints(A_eq=np.ones((1, m)), b_eq=[0]) assert dom.is_point == True
def build_borehole_domain(): r""" Constructs a deterministic domain associated with the borehole function Returns ------- dom: BoxDomain Domain associated with the borehole function """ # Parameters # r_w, r, T_u, H_u, T_l, H_l, L, K_w lb = np.array([0.05, 100, 63070, 990, 63.1, 700, 1120, 9855]) ub = np.array([0.15, 50e3, 115600, 1110, 116, 820, 1680, 12045]) return BoxDomain( lb, ub, names=['r_w', 'r', 'T_u', 'H_u', 'T_l', 'H_l', 'L', 'K_w'])
def test_gp_fit(m=3, M=100): """ check """ dom = BoxDomain(-np.ones(m), np.ones(m)) a = np.ones(m) b = np.ones(m) b[0] = 0 f = lambda x: np.sin(x.dot(a)) + x.dot(b)**2 fun = Function(f, dom) X = dom.sample(M) fX = f(X) for structure in ['const', 'diag', 'tril']: for degree in [None, 0, 1]: gp = GaussianProcess(structure=structure, degree=degree) gp.fit(X, fX) print(gp.L) I = ~np.isclose(gp(X), fX) print(fX[I]) print(gp(X[I])) assert np.all(np.isclose( gp(X), fX, atol=1e-5)), "we should interpolate samples" _, cov = gp.eval(X, return_cov=True) assert np.all(np.isclose( cov, 0, atol=1e-3)), "Covariance should be small at samples"