Exemplo n.º 1
0
class Box:
    def __init__(self, x0, f, a=1.3, e=1e-6, g=None, xd=None, xg=None):
        self.x0 = x0
        self.F = f
        self.a = a
        self.e = e
        self.g = g
        self.xd = xd
        self.xg = xg
        self.idx_h = None
        self.idx_h2 = None
        self.xc = Matrix(self.x0.n, self.x0.m)
        self.xr = Matrix(self.x0.n, self.x0.m)
        self.dimension = self.x0.n
        self.function_calls = 0
        self.points = [self.x0.copy()]

    def check_explicit_conditions(self, x):
        for idx in range(self.dimension):
            if not (self.xd[idx, 0] <= x[idx, 0] <= self.xg[idx, 0]):
                return False
        return True

    def check_implicit_conditions(self, x):
        for g_i in self.g:
            if g_i(x) < 0:
                return False
        return True

    def find_h(self):
        max_value = -math.inf
        f_xh2 = 0
        for idx, point in enumerate(self.points):
            value = self.F.f(point)
            self.function_calls += 1
            if value > max_value:
                f_xh2 = max_value
                max_value = value
                self.idx_h2 = self.idx_h
                self.idx_h = idx
        return f_xh2

    def calculate_points(self):
        for t in range(0, 2 * self.dimension):
            new_point = Matrix(self.dimension, 1)

            for idx in range(0, self.dimension):
                new_point[idx, 0] = self.xd[idx, 0] + random.random() * (
                    self.xg[idx, 0] - self.xd[idx, 0])

            while self.check_implicit_conditions(new_point) is False:
                new_point = self.move_to_centroid(new_point)

            self.points.append(new_point)
            self.tmp_centroid()
        return

    def tmp_centroid(self):
        self.xc = Matrix(self.x0.n, self.x0.m)
        for idx in range(len(self.points)):
            self.xc += self.points[idx]
        self.xc *= 1 / (len(self.points))

    def centroid(self):
        self.xc = Matrix(self.x0.n, self.x0.m)
        for idx in range(len(self.points)):
            if idx == self.idx_h:
                continue
            self.xc += self.points[idx]
        self.xc *= 1 / (len(self.points) - 1)

    def reflection(self):
        self.xr = (1 + self.a) * self.xc - self.a * self.points[self.idx_h]

    def move_to_centroid(self, point):
        return 0.5 * (self.xc + point)

    def stopping_condition(self):
        for idx in range(self.dimension):
            if abs(self.xc[idx, 0] - self.points[self.idx_h][idx, 0]) < self.e:
                return True
        return False

    def calculate(self):
        if not (self.check_explicit_conditions(
                self.x0)) or not (self.check_implicit_conditions(self.x0)):
            print("pocetna nisu zadovoljena")
            return None

        self.xc = self.x0.copy()
        self.calculate_points()

        min_f = None
        i = 0

        while i < 150:
            f_h = self.find_h()
            self.centroid()
            self.reflection()

            for idx in range(0, self.dimension):
                if self.xr[idx, 0] < self.xd[idx, 0]:
                    self.xr[idx, 0] = self.xd[idx, 0]
                elif self.xr[idx, 0] > self.xg[idx, 0]:
                    self.xr[idx, 0] = self.xg[idx, 0]

            while self.check_implicit_conditions(self.xr) is False:
                self.xr = self.move_to_centroid(self.xr)

            if self.F.f(self.xr) >= f_h:
                self.xr = self.move_to_centroid(self.xr)

            self.points[self.idx_h] = self.xr.copy()
            if self.stopping_condition():
                break
            f_xc = self.F.f(self.xc)
            if min_f is None:
                min_f = f_xc
            elif f_xc < min_f:
                min_f = f_xc
                i = 0
            else:
                i += 1

        return self.xc
Exemplo n.º 2
0
class Simplex:
    def __init__(self,
                 x0,
                 f,
                 a=1,
                 b=0.5,
                 g=2,
                 s=0.5,
                 e=1e-6,
                 h=1,
                 print_states=False,
                 print_short=False):
        self.x0 = x0
        self.F = f
        self.a = a
        self.b = b
        self.g = g
        self.s = s
        self.e = e
        self.h = h
        self.printing = print_states
        self.printing1 = print_short
        self.xh = None
        self.xl = None
        self.idx_h = None
        self.idx_l = None
        self.xc = Matrix(self.x0.n, self.x0.m)
        self.xe = Matrix(self.x0.n, self.x0.m)
        self.xr = Matrix(self.x0.n, self.x0.m)
        self.xk = Matrix(self.x0.n, self.x0.m)
        self.dimension = self.x0.n
        self.function_calls = 0
        self.points = [self.x0.copy()]
        for i in range(self.dimension):
            e_i = self.x0.copy()
            e_i[i, 0] += h
            self.points.append(e_i)

    def calculate(self):
        i = 0
        while True:
            flag = False
            f_xh, f_xl = self.find_h_l()
            self.centroid()
            f_xc = self.F(self.xc)
            if self.printing1:
                print("F(xc) = {}, za xc >>\n{}".format(f_xc, self.xc))
            self.reflection()
            f_xr = self.F(self.xr)
            self.function_calls += 2
            if self.printing:
                print("\n\nIteracija:{}, Početni simpleks je >>".format(i),
                      end='')
                for p in self.points:
                    print("{} ".format(p[0, 0]), end='')
                print('')
                print(
                    "\txh: {}, f(xh):{}, xl:{}, f(xl):{}, xc: {}, f(xc): {}, xr:{}, f(xr):{}"
                    .format(self.xh[0, 0], f_xh, self.xl[0, 0], f_xl,
                            self.xc[0, 0], f_xc, self.xr[0, 0], f_xr))
            if f_xr < f_xl:
                self.expansion()
                if self.printing:
                    print("\tIzračunata ekspanzija, xe:{}, f(xe):{}".format(
                        self.xe[0, 0], self.F.f(self.xe)))
                if self.F(self.xe) < f_xl:
                    self.points[self.idx_h] = self.xe.copy()
                    self.xh = self.xe.copy()
                else:
                    self.points[self.idx_h] = self.xr.copy()
                    self.xh = self.xr.copy()
                self.function_calls += 1
            else:
                for point in self.points:
                    if point == self.xh:
                        continue
                    self.function_calls += 1
                    if f_xr <= self.F(point):
                        flag = True
                        break
                if flag:
                    self.points[self.idx_h] = self.xr.copy()
                    self.xh = self.xr.copy()
                    continue
                else:
                    if f_xr < f_xh:
                        self.points[self.idx_h] = self.xr.copy()
                        self.xh = self.xr.copy()
                    self.contraction()
                    if self.printing:
                        print(
                            "\tIzračunata kontrakcija, xk:{}, f(xk):{}".format(
                                self.xk[0, 0], self.F(self.xk)))
                    if self.F(self.xk) < f_xh:
                        self.points[self.idx_h] = self.xk.copy()
                        self.xh = self.xk.copy()
                    else:
                        self.move_points()
                        if self.printing:
                            print("\tTočke su pomaknute, novi simpleks je >>",
                                  end='')
                            for p in self.points:
                                print("\t{} ".format(p[0, 0]), end='')
                            print('')
                    self.function_calls += 1
            if self.printing:
                print("\tSimpleks na kraju iteracije je >>", end='')
                for p in self.points:
                    print("\t{} ".format(p[0, 0]), end='')
                print('')
            if self.stop_condition(f_xc) <= self.e:
                break
            i += 1
        return self.xc

    def stop_condition(self, f_xc):
        result = 0
        for point in self.points:
            result += (self.F(point) - f_xc)**2
            self.function_calls += 1
        result /= len(self.points)
        a = math.sqrt(result)
        return a

    def find_h_l(self):
        max_value = -math.inf
        min_value = math.inf
        f_xh, f_xl = 0, 0
        for idx, point in enumerate(self.points):
            value = self.F(point)
            self.function_calls += 1
            if value > max_value:
                max_value = value
                self.xh = point.copy()
                self.idx_h = idx
                f_xh = value
            if value < min_value:
                min_value = value
                self.xl = point.copy()
                self.idx_l = idx
                f_xl = value
        return f_xh, f_xl

    def centroid(self):
        self.xc = Matrix(self.x0.n, self.x0.m)
        for point in self.points:
            if point == self.xh:
                continue
            self.xc += point
        self.xc *= 1 / (len(self.points) - 1)

    def reflection(self):
        self.xr = (1 + self.a) * self.xc - self.a * self.xh

    def expansion(self):
        self.xe = (1 - self.g) * self.xc + self.g * self.xr

    def contraction(self):
        self.xk = (1 - self.b) * self.xc + self.b * self.xh

    def move_points(self):
        for i in range(len(self.points)):
            self.points[i] = self.s * (self.points[i] + self.xl)