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()
        # 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
Ejemplo n.º 2
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