def test_supply_attribute(self): """ Test that we can supply an attribute instead of a function. """ iden = Identity() lst = LeastSquaresTerm(Target(iden, 'x'), 3, weight=0.1) self.assertEqual(lst.goal, 3) self.assertAlmostEqual(lst.weight, 0.1, places=13) iden.set_dofs([17]) self.assertEqual(lst.f_in(), 17) correct_value = 0.1 * ((17 - 3) ** 2) self.assertAlmostEqual(lst.f_out(), correct_value, places=13)
def test_supply_property(self): """ Test that we can supply a property instead of a function. """ iden = Identity() lst = LeastSquaresTerm.from_sigma(Target(iden, 'f'), 3, sigma=0.1) self.assertEqual(lst.goal, 3) self.assertAlmostEqual(lst.weight, 100, places=13) iden.set_dofs([17]) self.assertEqual(lst.f_in(), 17) correct_value = ((17 - 3) / 0.1) ** 2 self.assertAlmostEqual(lst.f_out(), correct_value, places=11)
def test_supply_object(self): """ Test that we can supply an object with a J function instead of a function. """ iden = Identity() # Note here we supply iden instead of iden.J lst = LeastSquaresTerm.from_sigma(iden, 3, sigma=0.1) self.assertEqual(lst.f_in, iden.J) self.assertEqual(lst.goal, 3) self.assertAlmostEqual(lst.weight, 100, places=13) iden.set_dofs([17]) self.assertEqual(lst.f_in(), 17) correct_value = ((17 - 3) / 0.1) ** 2 self.assertAlmostEqual(lst.f_out(), correct_value, places=11)
def test_supply_tuples(self): """ Test basic usage """ # Objective function f(x) = ((x - 3) / 2) ** 2 iden1 = Identity() term1 = (iden1.J, 3, 0.25) prob = LeastSquaresProblem([term1]) self.assertAlmostEqual(prob.objective(), 2.25) self.assertAlmostEqual(prob.objective(), sum(t.f_out() for t in prob.terms)) self.assertEqual(len(prob.dofs.f()), 1) self.assertAlmostEqual(prob.dofs.f()[0], 0) self.assertEqual(len(prob.f()), 1) self.assertAlmostEqual(prob.f()[0], -1.5) self.assertAlmostEqual(prob.objective_from_shifted_f(prob.f()), 2.25) self.assertAlmostEqual(prob.objective_from_unshifted_f(prob.dofs.f()), 2.25) iden1.set_dofs([10]) self.assertAlmostEqual(prob.objective(), 12.25) self.assertAlmostEqual(prob.objective(), sum(t.f_out() for t in prob.terms)) self.assertAlmostEqual(prob.objective_from_shifted_f(prob.f()), 12.25) self.assertAlmostEqual(prob.objective_from_unshifted_f(prob.dofs.f()), 12.25) self.assertAlmostEqual(prob.objective([0]), 2.25) self.assertAlmostEqual(prob.objective([10]), 12.25) self.assertEqual(prob.dofs.all_owners, [iden1]) self.assertEqual(prob.dofs.dof_owners, [iden1]) # Objective function # f(x,y) = ((x - 3) / 2) ** 2 + ((y + 4) / 5) ** 2 iden2 = Identity() term2 = (iden2.J, -4, 0.04) prob = LeastSquaresProblem([term1, term2]) self.assertAlmostEqual(prob.objective(), 12.89) self.assertAlmostEqual(prob.objective(), sum(t.f_out() for t in prob.terms)) self.assertEqual(len(prob.f()), 2) self.assertAlmostEqual(prob.objective_from_shifted_f(prob.f()), 12.89) self.assertAlmostEqual(prob.objective_from_unshifted_f(prob.dofs.f()), 12.89) iden1.set_dofs([5]) iden2.set_dofs([-7]) self.assertAlmostEqual(prob.objective(), 1.36) self.assertAlmostEqual(prob.objective(), sum(t.f_out() for t in prob.terms)) self.assertEqual(len(prob.f()), 2) self.assertAlmostEqual(prob.objective_from_shifted_f(prob.f()), 1.36) self.assertAlmostEqual(prob.objective_from_unshifted_f(prob.dofs.f()), 1.36) self.assertAlmostEqual(prob.objective([10, 0]), 12.89) self.assertAlmostEqual(prob.objective([5, -7]), 1.36) self.assertEqual(prob.dofs.dof_owners, [iden1, iden2]) self.assertEqual(prob.dofs.all_owners, [iden1, iden2])
def test_no_dependents(self): """ For an object that does not depend on anything, just return the original object. """ obj = object() self.assertEqual(get_owners(obj), [obj]) iden = Identity() self.assertEqual(get_owners(iden), [iden])
def test_circular2(self): """ Verify that a circular dependency among 2 objects is detected. """ o1 = Identity() o2 = Identity() o1.depends_on = ["o2"] o2.depends_on = ["o1"] o1.o2 = o2 o2.o1 = o1 with self.assertRaises(RuntimeError): get_owners(o1)
def test_basic(self): """ Test basic usage """ iden = Identity() lst = LeastSquaresTerm(iden.J, 3, weight=0.1) self.assertEqual(lst.f_in, iden.J) self.assertEqual(lst.goal, 3) self.assertAlmostEqual(lst.weight, 0.1, places=13) lst = LeastSquaresTerm.from_sigma(iden.J, 3, sigma=0.1) self.assertEqual(lst.f_in, iden.J) self.assertEqual(lst.goal, 3) self.assertAlmostEqual(lst.weight, 100.0, places=13) iden.set_dofs([17]) self.assertEqual(lst.f_in(), 17) correct_value = ((17 - 3) / 0.1) ** 2 self.assertAlmostEqual(lst.f_out(), correct_value, places=11)
def test_depth_2(self): """ Check cases in which the original object depends on another, which depends on another. """ o1 = Identity() o2 = Identity() o3 = object() o1.depends_on = ["o2"] o2.depends_on = ["o3"] o1.o2 = o2 o2.o3 = o3 self.assertEqual(get_owners(o1), [o1, o2, o3])
def test_solve_quadratic(self): """ Minimize f(x,y,z) = 1 * (x - 1) ^ 2 + 2 * (y - 2) ^ 2 + 3 * (z - 3) ^ 2. The optimum is at (x,y,z)=(1,2,3), and f=0 at this point. """ for solver in solvers: iden1 = Identity() iden2 = Identity() iden3 = Identity() term1 = (iden1.J, 1, 1) term2 = (iden2.J, 2, 2) term3 = (iden3.J, 3, 3) prob = LeastSquaresProblem([term1, term2, term3]) if solver == serial_solve: solver(prob, tol=1e-12) else: solver(prob) self.assertAlmostEqual(prob.objective(), 0) self.assertAlmostEqual(iden1.x, 1) self.assertAlmostEqual(iden2.x, 2) self.assertAlmostEqual(iden3.x, 3)
def test_depth_1(self): """ Check cases in which the original object depends on 1 or more others. """ o1 = Identity() o2 = Identity() o1.o2 = o2 o1.depends_on = ["o2"] self.assertEqual(get_owners(o1), [o1, o2]) o3 = object() o1.depends_on = ["o3", "o2"] o1.o3 = o3 self.assertEqual(get_owners(o1), [o1, o3, o2])
def test_gradient(self): iden = Identity() for n in range(1, 10): iden.set_dofs([np.random.rand() * 4 - 2]) # Supply an object to finite_difference(): fd_grad = Dofs([iden]).fd_jac().flatten() np.testing.assert_allclose(fd_grad, iden.df) np.testing.assert_allclose(fd_grad, iden.dJ()) # Supply a function to finite_difference(): fd_grad = Dofs([iden.J]).fd_jac().flatten() np.testing.assert_allclose(fd_grad, iden.df) np.testing.assert_allclose(fd_grad, iden.dJ()) # Supply an attribute to finite_difference(): fd_grad = Dofs([Target(iden, "f")]).fd_jac().flatten() np.testing.assert_allclose(fd_grad, iden.df) np.testing.assert_allclose(fd_grad, iden.dJ())
def test_exceptions(self): """ Test that exceptions are thrown when invalid inputs are provided. """ # First argument must be callable with self.assertRaises(TypeError): lst = LeastSquaresTerm(2, 3, 0.1) # Second and third arguments must be real numbers iden = Identity() #with self.assertRaises(TypeError): # lst = LeastSquaresTerm(iden.J, "hello", sigma=0.1) with self.assertRaises(TypeError): lst = LeastSquaresTerm.from_sigma(iden.J, 3, sigma=iden) #with self.assertRaises(TypeError): # lst = LeastSquaresTerm(iden.J, "hello", weight=0.1) with self.assertRaises(TypeError): lst = LeastSquaresTerm(iden.J, 3, weight=iden) # sigma cannot be zero with self.assertRaises(ValueError): lst = LeastSquaresTerm.from_sigma(iden.J, 3, sigma=0) with self.assertRaises(ValueError): lst = LeastSquaresTerm.from_sigma(iden.J, 3, sigma=0.0) # Cannot specify both weight and sigma with self.assertRaises(TypeError): lst = LeastSquaresTerm(iden.J, 3, sigma=1.2, weight=3.4) # Must specify either weight or sigma with self.assertRaises(TypeError): lst = LeastSquaresTerm(iden.J, 3) # Weight cannot be negative with self.assertRaises(ValueError): lst = LeastSquaresTerm(iden.J, 3, weight=-1.0)
def test_solve_quadratic_fixed_supplying_attributes(self): """ Same as test_solve_quadratic_fixed, except supplying attributes rather than functions as targets. """ for solver in solvers: iden1 = Identity() iden2 = Identity() iden3 = Identity() iden1.x = 4 iden2.x = 5 iden3.x = 6 iden1.names = ['x1'] iden2.names = ['x2'] iden3.names = ['x3'] iden1.fixed = [True] iden3.fixed = [True] # Try a mix of explicit LeastSquaresTerms and tuples term1 = LeastSquaresTerm(Target(iden1, 'x'), 1, 1) term2 = (iden2, 'x', 2, 1 / 4.) term3 = (iden3, 'x', 3, 1 / 9.) prob = LeastSquaresProblem([term1, term2, term3]) solver(prob) self.assertAlmostEqual(prob.objective(), 10) self.assertAlmostEqual(iden1.x, 4) self.assertAlmostEqual(iden2.x, 2) self.assertAlmostEqual(iden3.x, 6)
def test_basic(self): iden = Identity() self.assertAlmostEqual(iden.J(), 0, places=13) np.testing.assert_allclose(iden.get_dofs(), np.array([0.0])) np.testing.assert_allclose(iden.fixed, np.array([False])) x = 3.5 iden = Identity(x) self.assertAlmostEqual(iden.J(), x, places=13) np.testing.assert_allclose(iden.get_dofs(), np.array([x])) np.testing.assert_allclose(iden.fixed, np.array([False])) y = -2 iden.set_dofs([y]) self.assertAlmostEqual(iden.J(), y, places=13) np.testing.assert_allclose(iden.get_dofs(), np.array([y])) np.testing.assert_allclose(iden.fixed, np.array([False]))
def test_solve_quadratic_fixed_supplying_objects(self): """ Same as test_solve_quadratic_fixed, except supplying objects rather than functions as targets. """ for solver in solvers: iden1 = Identity() iden2 = Identity() iden3 = Identity() iden1.x = 4 iden2.x = 5 iden3.x = 6 iden1.names = ['x1'] iden2.names = ['x2'] iden3.names = ['x3'] iden1.fixed = [True] iden3.fixed = [True] term1 = [iden1, 1, 1] term2 = [iden2, 2, 1 / 4.] term3 = [iden3, 3, 1 / 9.] prob = LeastSquaresProblem([term1, term2, term3]) solver(prob) self.assertAlmostEqual(prob.objective(), 10) self.assertAlmostEqual(iden1.x, 4) self.assertAlmostEqual(iden2.x, 2) self.assertAlmostEqual(iden3.x, 6)
def test_solve_quadratic_fixed_supplying_properties(self): """ Same as test_solve_quadratic_fixed, except supplying @properties rather than functions as targets. """ for solver in solvers: iden1 = Identity() iden2 = Identity() iden3 = Identity() iden1.x = 4 iden2.x = 5 iden3.x = 6 iden1.names = ['x1'] iden2.names = ['x2'] iden3.names = ['x3'] iden1.fixed = [True] iden3.fixed = [True] # Try a mix of explicit LeastSquaresTerms and lists term1 = [iden1, 'f', 1, 1] term2 = [iden2, 'f', 2, 1 / 4.] term3 = LeastSquaresTerm.from_sigma(Target(iden3, 'f'), 3, sigma=3) prob = LeastSquaresProblem([term1, term2, term3]) solver(prob) self.assertAlmostEqual(prob.objective(), 10) self.assertAlmostEqual(iden1.x, 4) self.assertAlmostEqual(iden2.x, 2) self.assertAlmostEqual(iden3.x, 6)
def test_solve_quadratic_fixed(self): """ Same as test_solve_quadratic, except with different weights and x and z are fixed, so only y is optimized. """ for solver in solvers: iden1 = Identity() iden2 = Identity() iden3 = Identity() iden1.x = 4 iden2.x = 5 iden3.x = 6 iden1.names = ['x1'] iden2.names = ['x2'] iden3.names = ['x3'] iden1.fixed = [True] iden3.fixed = [True] term1 = (iden1.J, 1, 1) term2 = (iden2.J, 2, 1 / 4.) term3 = (iden3.J, 3, 1 / 9.) prob = LeastSquaresProblem([term1, term2, term3]) solver(prob) self.assertAlmostEqual(prob.objective(), 10) self.assertAlmostEqual(iden1.x, 4) self.assertAlmostEqual(iden2.x, 2) self.assertAlmostEqual(iden3.x, 6)
def test_circular4(self): """ Verify that a circular dependency among 4 objects is detected. """ o1 = Identity() o2 = Identity() o3 = Identity() o4 = Identity() o1.depends_on = ["o2"] o2.depends_on = ["o3"] o3.depends_on = ["o4"] o4.depends_on = ["o1"] o1.o2 = o2 o2.o3 = o3 o3.o4 = o4 o4.o1 = o1 with self.assertRaises(RuntimeError): get_owners(o1)
from simsopt.objectives.functions import Identity from simsopt.objectives.least_squares import LeastSquaresProblem from simsopt.solve.serial import least_squares_serial_solve """ Minimize f(x,y,z) = ((x-1)/1)^2 + ((y-2)/2)^2 + ((z-3)/3)^2. The optimum is at (x,y,z)=(1,2,3), and f=0 at this point. """ # To print out diagnostic information along the way, uncomment this # next line: #logging.basicConfig(level=logging.INFO) # Define some Target objects that depend on Parameter objects. In the # future these functions would involve codes like VMEC, but for now we # just use the functions f(x) = x. iden1 = Identity() iden2 = Identity() iden3 = Identity() # Parameters are all not fixed by default, meaning they will not be # optimized. You can choose to exclude any subset of the parameters # from the space of independent variables by setting their 'fixed' # property to True. #iden1.fixed[0] = True #iden2.fixed[0] = True #iden3.fixed[0] = True # Each Target is then equipped with a shift and weight, to become a # term in a least-squares objective function term1 = (iden1, 1, 1) term2 = (iden2, 2, 2)