def test_project(self): """Test that project() works as intended. """ # Test that project works for legal values. structure = param.DirectParam(np.array([0, 0.5, 1, 0.5])) structure.project() self.assertEqual(structure.get_structure().tolist(), [0, 0.5, 1, 0.5]) # Test that project works when values exceed range. structure = param.DirectParam(np.array([0, -0.5, 1.2, 0.5])) structure.project() self.assertEqual(structure.get_structure().tolist(), [0, 0, 1, 0.5])
def test_get_bounds(self): structure = param.DirectParam(np.array([0])) self.assertEqual(structure.get_bounds(), ((0, ), (1, ))) structure = param.DirectParam(np.array([0.1, 1])) self.assertEqual(structure.get_bounds(), ((0, 0), (1, 1))) structure = param.DirectParam(np.array([0.1, 1, 2]), bounds=(2, 3)) self.assertEqual(structure.get_bounds(), ((2, 2, 2), (3, 3, 3))) structure = param.DirectParam(np.array([0.1, 1, 2]), bounds=((1, 2, 3), (4, 5, 6))) self.assertEqual(structure.get_bounds(), ((1, 2, 3), (4, 5, 6)))
def test_eval(): param = parametrization.DirectParam((1, 2, 3, 4, 5)) x = problem.Variable(5) obj = (x[0] * x[1] - x[2]**2) * (x[3] + 2 * x[4]) assert graph_executor.eval_fun(obj, param) == -98 np.testing.assert_array_equal(graph_executor.eval_grad(obj, param), [28, 14, -84, -7, -14])
def test_eval_old_in_new(): """Tests evals when a new-style function depends on old-style function.""" param = parametrization.DirectParam((3, 2)) x = problem.Variable(2) obj = OldPower(x[0], 2) + x[0] assert graph_executor.eval_fun(obj, param) == 12 np.testing.assert_array_equal(graph_executor.eval_grad(obj, param), [7, 0])
def test_eval_multiple(): param = parametrization.DirectParam((1, 2, 3, 4, 5)) x = problem.Variable(5) obj_part1 = x[3] + 2 * x[4] obj_part2 = x[0] * x[1] - x[2]**2 obj = obj_part1 * obj_part2 assert graph_executor.eval_fun([obj, obj_part1, obj_part2], param) == [-98, 14, -7]
def test_grating_edge_discretization(cont, disc, min_feature): param = parametrization.DirectParam(cont) trans = grating.GratingEdgeDiscretization(param, 40 * min_feature, 40) param_disc = parametrization.GratingParam([], num_pixels=len( param.to_vector())) trans(param_disc, None) np.testing.assert_almost_equal(param_disc.to_vector(), disc)
def test_eval_heavy_compute_end_on_heavy(): param = parametrization.DirectParam((-3, 2)) x = problem.Variable(2) obj = HeavyIdentity(x[0] * x[1]) np.testing.assert_array_almost_equal(graph_executor.eval_fun(obj, param), -6) np.testing.assert_array_equal(graph_executor.eval_grad(obj, param), [2, -3])
def test_from_vector(self): # Test that from_vector works. structure = param.DirectParam(np.array([0, 0, 0])) structure.from_vector(np.array([0.5, 0.1, 0.3])) self.assertEqual(structure.encode().tolist(), [0.5, 0.1, 0.3]) # Check for projection. structure.from_vector(np.array([-1, 2, 3])) self.assertEqual(structure.encode().tolist(), [0, 1, 1])
def test_eval_fun_no_in_node_works(): """Tests when no input node is found. This can happen if the input node is fed only to the old-style function, which does not list its dependencies. Consequently, no input node can be found. """ param = parametrization.DirectParam((2, )) x = problem.Variable(1) obj = OldPower(x[0], 2) + OldPower(x[0], 3) assert graph_executor.eval_fun(obj, param) == 12 np.testing.assert_array_equal(graph_executor.eval_grad(obj, param), [16])
def test_eval_heavy_compute(): param = parametrization.DirectParam((-1, 2, 1.2, 3, 5.1)) x = problem.Variable(5) obj = HeavyIdentity(x[1] * x[0] * x[3]) obj2 = HeavyIdentity(x[3] + x[1]**3) obj3 = obj * (x[0] + 2) + obj2 - x[4] np.testing.assert_array_almost_equal(graph_executor.eval_fun(obj3, param), -0.1) np.testing.assert_array_equal(graph_executor.eval_grad(obj3, param), [0, 9, 0, -1, -1])
def test_fdfd_simulation_grad(): # Create a 3x3 2D grid to brute force check adjoint gradients. shape = [3, 3, 1] # Setup epsilon (pure vacuum). epsilon = [np.ones(shape) for i in range(3)] # Setup dxes. Assume dx = 40. dxes = [[np.ones(shape[i]) * 40 for i in range(3)] for j in range(2)] # Setup a point source in the center. J = [np.zeros(shape).astype(complex) for i in range(3)] J[2][1, 0, 0] = 1.2j J[2][1, 1, 0] = 1 # Setup target fields. target_fields = [np.zeros(shape).astype(np.complex128) for i in range(3)] target_fields[2][:, :, 0] = 20j + 1 overlap_vec = fdfd_tools.vec(target_fields) # TODO(logansu): Deal with this. class SimspaceMock: @property def dxes(self): return dxes @property def pml_layers(self): return [0] * 6 eps_param = parametrization.DirectParam(fdfd_tools.vec(epsilon), bounds=[0, 100]) eps_fun = problem.Variable(len(fdfd_tools.vec(epsilon))) sim_fun = creator_em.FdfdSimulation( eps=eps_fun, solver=local_matrix_solvers.DirectSolver(), wlen=1500, source=J, simspace=SimspaceMock(), ) obj_fun = problem.AbsoluteValue( objective=creator_em.OverlapFunction(sim_fun, overlap_vec))**2 grad_actual = obj_fun.calculate_gradient(eps_param) def eval_fun(vec: np.ndarray): eps_param.from_vector(vec) return obj_fun.calculate_objective_function(eps_param) grad_brute = eval_grad_brute(fdfd_tools.vec(epsilon), eval_fun) np.testing.assert_array_almost_equal(grad_actual, grad_brute, decimal=0)
def test_get_structure(self): """ Tests that get_structure() works as intended. """ structure = param.DirectParam(np.array([0, 0.5, 1, 0.5])) self.assertEqual(structure.get_structure().tolist(), [0, 0.5, 1, 0.5])
def test_eval_fun_multiple_variables_raises_value_error(): with pytest.raises(ValueError, match=r"Multiple Variable"): param = parametrization.DirectParam((1, 2)) x = problem.Variable(2) y = problem.Variable(2) graph_executor.eval_fun(x + y, param)
def test_encode(self): # Test that encode works. structure = param.DirectParam(np.array([0, 0.5, 1, 0.5])) self.assertEqual(structure.encode().tolist(), [0, 0.5, 1, 0.5])
def test_decode(self): # Test that decode works properly. structure = param.DirectParam(np.array([0, 0])) structure.decode(np.array([1, 2, 3])) self.assertEqual(structure.encode().tolist(), [1, 2, 3])
def test_grating_edge_discretization_min_feature_too_small_raises_error(): param = parametrization.DirectParam([0, 1, 2, 3]) with pytest.raises(ValueError, match="feature size must be larger"): trans = grating.GratingEdgeDiscretization(param, 30, 40)
def test_to_vector(self): # Test that to_vector works. structure = param.DirectParam(np.array([0, 0.5, 1, 0.5])) self.assertEqual(structure.to_vector().tolist(), [0, 0.5, 1, 0.5])
def create_pixel_param( params: optplan.PixelParametrization, work: workspace.Workspace) -> parametrization.DirectParam: design_dims = work.get_object(params.simulation_space).design_dims init_val = work.get_object(params.init_method)(design_dims) return parametrization.DirectParam(init_val.flatten(order="F"))
def test_no_bounds(self): structure = param.DirectParam([1000, -1234], bounds=None) structure.project() self.assertEqual(structure.to_vector().tolist(), [1000, -1234]) self.assertEqual(structure.get_bounds(), ((None, None), (None, None)))