def solve(self, problem: Problem, init_vars: np.ndarray = None, show_process: bool = False): if init_vars is None: init_vars = np.random.rand(problem.dim) self.reset() start = time.time() # Step1: calculate the gradient and its norm named 'ng' vars_current = init_vars grad_value = problem.cal_gradient(vars_current) ng = np.linalg.norm(grad_value) objv_current = problem.aim_func(vars_current) # Record self.cpu_time_arr.append(0) self.f_value_arr.append(objv_current) self.g_norm_arr.append(ng) # Step2: Iteration iter_count = 0 while iter_count < self.max_iter: current = time.time() # INNER STEP1: get d_k lambda_val = self.lambda_at(iter_count) d_k = project(vars_current - lambda_val * grad_value, problem.b_s) - vars_current d_k_norm = np.linalg.norm(d_k) if d_k_norm <= lambda_val * self.tol: break # INNER STEP2: get a_k alpha = self.s # initial alpha as self.s objv_next = problem.aim_func(vars_current + alpha * d_k) while np.isnan(objv_next) or ( (objv_next - objv_current) > (self.gamma * alpha * grad_value @ d_k)): alpha *= self.sigma objv_next = problem.aim_func(vars_current + alpha * d_k) vars_current = vars_current + alpha * d_k # Update vars objv_current = problem.aim_func(vars_current) grad_value = problem.cal_gradient(vars_current) ng = np.linalg.norm(grad_value) iter_count += 1 if show_process: print(f'iteration {iter_count} : {round(ng, 8)}', end=' ') print( f'time: {round(time.time() - current, 3)} second(self.s)') # Record self.cpu_time_arr.append(time.time() - start) self.f_value_arr.append(objv_current) self.g_norm_arr.append(ng) self.final_solution = vars_current self.surface_points = problem.get_all_surface_points(vars_current) self.support_points = problem.get_all_support_points() return vars_current, grad_value, objv_current, ng, iter_count
def solve(self, problem: Problem, init_vars: np.ndarray = None, show_process: bool = False): if init_vars is None: init_vars = np.random.rand(problem.dim) self.reset() start = time.time() def aim_func(penalty_alpha: float, vars: np.ndarray) -> float: g_vals = problem.b_s(vars) - vars return problem.aim_func(vars) + 1 / 2 * penalty_alpha * np.sum( np.maximum(0, g_vals)**2) def cal_gradient(penalty_alpha: float, vars: np.ndarray) -> float: g_vals = problem.b_s(vars) - vars return problem.cal_gradient(vars) - penalty_alpha * np.sum( np.maximum(0, g_vals)) class PenaltyProblem(MinimalSurfaceProblem): def __init__(self, penalty_alpha) -> None: self.penalty_alpha = penalty_alpha @overrides def aim_func(self, vars: np.ndarray): return aim_func(self.penalty_alpha, vars) @overrides def cal_gradient(self, vars: np.ndarray): return cal_gradient(self.penalty_alpha, vars) @overrides def cal_hessian(*_): pass @overrides def get_all_surface_points(*_): pass penalty_alpha = self.penalty_s current_problem = PenaltyProblem(penalty_alpha) vars_current, grad_value, objv_current, ng, _ = self.solver.solve( current_problem, init_vars) ng = np.linalg.norm(grad_value) # Record self.cpu_time_arr.append(0) self.f_value_arr.append(objv_current) self.g_norm_arr.append(ng) iter_count = 0 while iter_count < self.max_iter: current = time.time() current_problem = PenaltyProblem(penalty_alpha) vars_current, grad_value, objv_current, ng, _ = self.solver.solve( current_problem, vars_current) penalty_alpha *= self.penalty_gamma iter_count += 1 if reduce(np.logical_and, np.abs(vars_current - problem.b_s(vars_current)) < 1e-2): break if show_process: print(f'iteration {iter_count} : {round(ng, 8)}', end=' ') print( f'time: {round(time.time() - current, 3)} second(self.s)') # Record self.cpu_time_arr.append(time.time() - start) self.f_value_arr.append(objv_current) self.g_norm_arr.append(ng) self.final_solution = vars_current self.surface_points = problem.get_all_surface_points(vars_current) self.support_points = problem.get_all_support_points() return vars_current, grad_value, objv_current, ng, iter_count