Ejemplo n.º 1
0
    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