def is_unimodal(interval_start, interval_end, fn, step): x = (interval_start + interval_end) / 2 if (eval_math_fn(fn, {'x': interval_start}) > eval_math_fn(fn, {'x': x})) and (eval_math_fn(fn, {'x': interval_end}) > eval_math_fn(fn, {'x': x})): print( f'Funkcja jest prawdopodobnie unimodalna w przedziale [{interval_start}, {interval_end}]') return True else: new_interval_start = x - step new_interval_end = x + step counter = 0 print( f'Funkcja nie jest unimodalna w przedziale [{interval_start}, {interval_end}]') while not (eval_math_fn(fn, {'x': new_interval_start}) > eval_math_fn(fn, {'x': x})) and (eval_math_fn(fn, {'x': new_interval_end}) > eval_math_fn(fn, {'x': x})) and counter <= 100: new_interval_start -= step new_interval_end += step counter += 1 if counter <= 100: print( f'Funkcja jest unimodalna w przedziale [{new_interval_start}, {new_interval_end}]') else: print( f'Funkcja prawdopodobnie nie posiada minimum lokalnego') return False
def bisection(plot, fn, epsilon, a, b, iter_count): interval_start = a interval_end = b xm = (interval_start + interval_end) / 2 mark_interval(plot, fn, interval_start, interval_end) for k in range(1, iter_count + 1): l = interval_end - interval_start x1 = interval_start + l / 4 x2 = interval_end - l / 4 vfx1 = eval_math_fn(fn, {'x': x1}) vfx2 = eval_math_fn(fn, {'x': x2}) vfxm = eval_math_fn(fn, {'x': xm}) if abs(interval_end - interval_start) <= 2 * epsilon: print(f'Minimum: {xm}') break elif vfx1 < vfxm: interval_end = xm xm = x1 elif vfx2 < vfxm: interval_start = xm xm = x2 else: interval_start = x1 interval_end = x2 print(f'Przedział {k}: [{interval_start}, {interval_end}]') print(f'Przedział {k}: minimum: {xm}') mark_interval(plot, fn, interval_start, interval_end) mark_point(plot, fn, xm)
def fibonacci(plot, fn, epsilon, a, b, iteration_count): n = get_n(b, a, epsilon) c = a + nth_fibonacci_number(n - 2) / nth_fibonacci_number(n) * (b - a) d = a + nth_fibonacci_number(n - 1) / nth_fibonacci_number(n) * (b - a) fc = eval_math_fn(fn, {"x": c}) fd = eval_math_fn(fn, {"x": d}) k = 1 while n > 2 and k <= iteration_count: print(f'Przedział {k}: [{a}, {b}]') mark_interval(plot, fn, a, b) k += 1 n -= 1 if fc < fd: b = d d = c fd = fc c = a + nth_fibonacci_number(n - 2) / nth_fibonacci_number(n) * (b - a) fc = eval_math_fn(fn, {"x": c}) else: a = c c = d fc = fd d = a + nth_fibonacci_number(n - 1) / nth_fibonacci_number(n) * (b - a) fd = eval_math_fn(fn, {"x": d}) minimum = (a + b) / 2 mark_point(plot, fn, minimum) print(f'Wynik: min: {minimum}, liczba iteracji: {k - 1}')
def calculate(method): # get values from input interval_start = float(interval_s.get()) interval_end = float(interval_e.get()) fun = fn.get() eps = float(epsilon.get()) iter_c = int(iteration_count.get()) # calculate plot points arrayX = np.arange(interval_start, interval_end + 1, 0.01) arrayY = np.array(list(map(lambda x: eval_math_fn(fun, {'x': x}), arrayX))) # clear plot plot.cla() if is_unimodal(interval_start, interval_end, fun, 0.2): mark_unimodal_interval(plot, fun, interval_start, interval_end) # choose method if method == Method.BISECTION: bisection(plot, fun, eps, interval_start, interval_end, iter_c) elif method == Method.FIBONACCI: fibonacci(plot, fun, eps, interval_start, interval_end, iter_c) # optimize with scipy scipy_optimize(fun, interval_start, interval_end, eps, iter_c) # plotting x and y axys plot.plot(arrayX, arrayY) canvas.draw()
def f(x): return eval_math_fn(fun, {'x': x})
def mark_unimodal_interval(plot, fn, start, end): plot.scatter(start, eval_math_fn(fn, {'x': start}), marker="x", linewidths=1, c='green') plot.scatter(end, eval_math_fn(fn, {'x': end}), marker="x", linewidths=1, c='green')
def mark_interval(plot, fn, start, end): plot.scatter(start, eval_math_fn(fn, {'x': start}), marker="|", linewidths=2, c='black') plot.scatter(end, eval_math_fn(fn, {'x': end}), marker="|", linewidths=2, c='black')
def mark_point(plot, fn, x): plot.scatter(x, eval_math_fn(fn, {'x': x}), marker='o', c='red')