def test_rng_without_seed(self): # Note: No need to patch random since we are expecting actual random outcome in this test # Run this twice and assure results are different result1 = solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds) result2 = solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds) self.assertNotEqual(str(result1), str(result2))
def test_bad_eq_constraints(self): # Eq function without values with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, start_guess_sampling=[NormalDistribution(1, 0.1)], eq_func=alkyla_equality_function) # Eq values without function with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, start_guess_sampling=[NormalDistribution(1, 0.1)], eq_values=equality_values) # Eq func not callable without function with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, start_guess_sampling=[NormalDistribution(1, 0.1)], eq_func={"Not", "Callable"}, eq_values=equality_values) # Eq values not of fixed length with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, start_guess_sampling=[NormalDistribution(1, 0.1)], eq_func=alkyla_equality_function, eq_values=2)
def test_electron_optimization_penalty_barrier_function_single_process( self): objective_function = lambda x: self.electron.objective_function(x) equality_function = lambda x: self.electron.equality_function(x) equality_bounds = self.electron.equality_constraint_bounds upper_bounds = self.electron.parameter_upper_bound lower_bounds = self.electron.parameter_lower_bound results = solve( obj_func=objective_function, eq_func=equality_function, eq_values=equality_bounds, par_lower_limit=lower_bounds, par_upper_limit=upper_bounds, number_of_restarts=2, number_of_simulations=20000, number_of_processes=None, seed=443, pysolnp_max_major_iter=100, evaluation_type=EvaluationType.PENALTY_BARRIER_FUNCTION, debug=False) optimum = results.best_solution.parameters equality_function_value = equality_function(optimum) for index, value in enumerate(optimum): self.assertGreaterEqual(value, lower_bounds[index]) self.assertLessEqual(value, upper_bounds[index]) for index, value in enumerate(equality_function_value): self.assertAlmostEqual(value, equality_bounds[index], 3) self.assertLessEqual(results.best_solution.obj_value, 244)
def test_electron_optimization_exclude_inequalities_multiple_processes( self): equality_bounds = self.electron.equality_constraint_bounds upper_bounds = self.electron.parameter_upper_bound lower_bounds = self.electron.parameter_lower_bound results = solve( obj_func=obj_func, eq_func=eq_func, eq_values=equality_bounds, par_lower_limit=lower_bounds, par_upper_limit=upper_bounds, number_of_restarts=20, number_of_simulations=20000, number_of_processes=4, seed=443, pysolnp_max_major_iter=100, evaluation_type=EvaluationType.OBJECTIVE_FUNC_EXCLUDE_INEQ, debug=False) optimum = results.best_solution.parameters equality_function_value = eq_func(optimum) for index, value in enumerate(optimum): self.assertGreaterEqual(value, lower_bounds[index]) self.assertLessEqual(value, upper_bounds[index]) for index, value in enumerate(equality_function_value): self.assertAlmostEqual(value, equality_bounds[index], 3) self.assertLessEqual(results.best_solution.obj_value, 244)
def test_permutations_optimization_penalty_barrier_function_single_process( self): objective_function = permutation_function upper_bounds = parameter_upper_bounds lower_bounds = parameter_lower_bounds results = solve( obj_func=objective_function, par_lower_limit=lower_bounds, par_upper_limit=upper_bounds, number_of_restarts=20, number_of_simulations=20000, number_of_processes=None, seed=443, pysolnp_max_major_iter=100, evaluation_type=EvaluationType.PENALTY_BARRIER_FUNCTION, debug=False) optimum = results.best_solution.parameters for index, value in enumerate(optimum): self.assertGreaterEqual(value, lower_bounds[index]) self.assertLessEqual(value, upper_bounds[index]) self.assertLessEqual(results.best_solution.obj_value, 0.5)
def test_permuation_optimization_exclude_indequalities_single_process( self): objective_function = permutation_function upper_bounds = parameter_upper_bounds lower_bounds = parameter_lower_bounds results = solve( obj_func=objective_function, par_lower_limit=lower_bounds, par_upper_limit=upper_bounds, number_of_restarts=20, number_of_simulations=20000, number_of_processes=None, seed=443, pysolnp_max_major_iter=100, evaluation_type=EvaluationType.OBJECTIVE_FUNC_EXCLUDE_INEQ, debug=False) optimum = results.best_solution.parameters for index, value in enumerate(optimum): self.assertGreaterEqual(value, lower_bounds[index]) self.assertLessEqual(value, upper_bounds[index]) self.assertLessEqual(results.best_solution.obj_value, 0.5)
def test_number_of_restarts(self): number_of_restarts = 2 seed = 1234567 results = solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, number_of_restarts=number_of_restarts, seed=seed) self.assertEqual(len(results.all_results), 2)
def test_rng_with_seed(self): # RNG with seed, note that we remove the constraints to the problem to make it easier to find a solution seed = 15 results = solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, seed=seed) self.assertAlmostEqual(results.best_solution.obj_value, -2597.805528666477, 4)
def test_number_of_simulations(self): number_of_simulations = 5 seed = 1234567 results = solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, number_of_simulations=number_of_simulations, seed=seed) # We have one guess for each parameter in each simulation expected_number_of_starting_guesses = number_of_simulations * len( parameter_lower_bounds) self.assertEqual(len(results.starting_guesses), expected_number_of_starting_guesses)
def test_evaluation_type(self): seed = 1234567 # Eval Type OBJECTIVE_FUNC_EXCLUDE_INEQ has a hard time locating starting points for problems with narrow inequality bounds # Alkyla is a bad function in this sense, but with enough luck and enough simulations we find something... results = solve( obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, seed=seed, evaluation_type=EvaluationType.OBJECTIVE_FUNC_EXCLUDE_INEQ, number_of_simulations=100000) self.assertAlmostEqual(results.best_solution.obj_value, -172.64110132537394, 4) # Eval Type PENALTY_BARRIER_FUNCTION is better at locating starting points for problems with narrow inequality bounds results = solve( obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, seed=seed, evaluation_type=EvaluationType.PENALTY_BARRIER_FUNCTION.value) self.assertAlmostEqual(results.best_solution.obj_value, -170.98167226891587, 4)
def test_bad_pygosolnp_parameters(self): # Needs strictly more than 0 simulations with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, number_of_simulations=0) # Needs strictly more than 0 restarts with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, number_of_restarts=0) # Needs strictly more than 0 processes with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, number_of_processes=0)
def test_bad_ineq_constraints(self): # Ineq func without bounds with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function) # Ineq lower bound without func or upper bound with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_lower_bounds=inequality_lower_bounds) # Ineq func not callable with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=[1, 2, 3], ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds) # Ineq lower bounds not of fixed size with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=itertools.cycle("abcd"), ineq_upper_bounds=inequality_upper_bounds) # Ineq upper bounds not of fixed size with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=itertools.cycle("efgh")) # Ineq lower and upper bounds of different length with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=[1, 2, 3], ineq_upper_bounds=inequality_upper_bounds)
def test_bad_pysolnp_parameters(self): # Various pysolnp parameters as wrong variable type with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, pysolnp_tolerance="a") with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, pysolnp_max_minor_iter="a") with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, pysolnp_max_major_iter="a") with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, pysolnp_rho="a") with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, pysolnp_delta="a") with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, debug="a") with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, pysolnp_max_minor_iter=0) with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, pysolnp_max_major_iter=0)
def test_bad_objective_function(self): # Missing mandatory data with self.assertRaises(ValueError): solve(obj_func=None, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds) with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=None, par_upper_limit=parameter_upper_bounds) with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=None) # Non-callable objective function with self.assertRaises(ValueError): solve(obj_func={"hello": "world"}, par_lower_limit=[1, 2, 3], par_upper_limit=parameter_upper_bounds) # Lower bounds missing length attribute with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=2, par_upper_limit=parameter_upper_bounds) # Upper bounds missing length attribute with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=1515, par_upper_limit=parameter_upper_bounds) # Different length of bounds with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=[1, 2, 3], par_upper_limit=parameter_upper_bounds) # Random number distribution not same length as parameters with self.assertRaises(ValueError): solve(obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, start_guess_sampling=[NormalDistribution(1, 0.1)])
def test_distribution_settings(self): # Test the built-in distributions: ## UniformDistribution (default) ## TriangleDistribution ## ConstantValue (not really a distribution, but anyway...) ## NormalDistribution (not bound to the problem limits, so can cause ValueErrors) # For examples with truncated normal distribution or grid sampling, see the pygosolnp/python_examples/ folder. seed = 1234567 random_number_distribution = [ UniformDistribution(lower=parameter_lower_bounds[0], upper=parameter_upper_bounds[0]), UniformDistribution(lower=parameter_lower_bounds[1], upper=parameter_upper_bounds[1]), UniformDistribution(lower=parameter_lower_bounds[2], upper=parameter_upper_bounds[2]), UniformDistribution(lower=parameter_lower_bounds[3], upper=parameter_upper_bounds[3]), UniformDistribution(lower=parameter_lower_bounds[4], upper=parameter_upper_bounds[4]), UniformDistribution(lower=parameter_lower_bounds[5], upper=parameter_upper_bounds[5]), UniformDistribution(lower=parameter_lower_bounds[6], upper=parameter_upper_bounds[6]), TriangleDistribution( lower=parameter_lower_bounds[7], upper=parameter_upper_bounds[7], mode=(parameter_upper_bounds[7] + parameter_lower_bounds[7]) / 2), ConstantValue(value=3.6), # Forced to always be 3.6 NormalDistribution( mean=parameter_lower_bounds[9] + (parameter_upper_bounds[9] - parameter_lower_bounds[9]) / 2, standard_deviation=(parameter_upper_bounds[9] - parameter_lower_bounds[9]) / 2) ] results = solve( obj_func=alkyla_objective_function, par_lower_limit=parameter_lower_bounds, par_upper_limit=parameter_upper_bounds, eq_func=alkyla_equality_function, eq_values=equality_values, ineq_func=alkyla_inequality_function, ineq_lower_bounds=inequality_lower_bounds, ineq_upper_bounds=inequality_upper_bounds, number_of_simulations=10, number_of_restarts=1, seed=seed, evaluation_type=EvaluationType.PENALTY_BARRIER_FUNCTION, start_guess_sampling=random_number_distribution) expected = [ 19.262864952192448, 3.771726139520572, 69.77797447275604, 19.068793973427482, 19.33182084216137, 89.89207643509036, 16.299077190999093, 7.656803716342179, 3.6, 141.68084366746555, 16.527810282976148, 2.8024116596314954, 113.8847499219252, 41.913648375763266, 13.653863317763928, 89.36107961371863, 31.65003670354735, 6.742247466242993, 3.6, 144.41878023451304, 9.155674825062048, 10.587247668990255, 89.6903787978092, 38.29483391669842, 8.064799536849511, 89.43255250817325, 86.41114587298019, 5.961162104738718, 3.6, 147.6264662441887, 10.067591751749159, 13.136604255021913, 73.43265943827133, 44.724776804281476, 0.7740903344904604, 88.462319551243, 50.21684783727512, 5.77672041074722, 3.6, 145.39269004124904, 9.068225746042762, 12.61405383313014, 68.82767844281483, 16.611623195615945, 9.00169037647699, 85.31447609370339, 51.318693144764346, 9.28229782560638, 3.6, 150.88899802298727, 2.853206753025248, 13.650346506177705, 12.332917949430415, 43.013069327734556, 19.840074115550717, 91.20142486328595, 79.33118000010684, 3.8956025310633953, 3.6, 153.4160006648588, 0.6434958413807812, 2.9463400863302613, 102.90608010105203, 38.77132597397568, 3.023003386685923, 85.51893369450241, 59.20378581486704, 4.856217794173671, 3.6, 159.0155564965776, 19.650096860859275, 14.557888535778906, 24.793341705879453, 28.499566032377153, 12.098785988152493, 92.47510246654802, 44.847907830159485, 7.819085343574262, 3.6, 154.12786686990134, 8.266201078057069, 10.758463796133531, 0.2800364042800263, 23.509199466708623, 6.6730557487734306, 86.50613863644213, 65.27792963956803, 10.344369491252513, 3.6, 153.0090154093769, 13.044272915070119, 3.896854881633315, 86.85241703973514, 22.201841915524042, 17.718325429729628, 89.780805965076, 64.98014550674284, 8.237553597176323, 3.6, 150.8605530994913 ] self.assertListEqual(results.starting_guesses, expected)