|
| 1 | +# Implementing the task |
| 2 | +# Optimization of smooth and non-smooth functions |
| 3 | + |
| 4 | + |
| 5 | +import numpy as np |
| 6 | +import matplotlib.pyplot as plt |
| 7 | +from scipy import optimize |
| 8 | + |
| 9 | + |
| 10 | +# Task 1 - smooth function |
| 11 | +# Initial smooth function |
| 12 | +# f(x) = sin(x / 5) * exp(x / 10) + 5 * exp(-x / 2) |
| 13 | +# Function returns array with 'y' results from input array of 'x' for plotting by using 'np' instead of 'math' |
| 14 | +def f_array(k): |
| 15 | + return np.sin(k / 5) * np.exp(k / 10) + 5 * np.exp(-k / 2) |
| 16 | + |
| 17 | + |
| 18 | +# Finding minimum of smooth function with 'BFGS' method |
| 19 | +# Setting initial point in form of 'ndarray' as 'minimize' function requires it in form of 'ndarray' |
| 20 | +x0_start = np.array([2]) |
| 21 | +# print(type(x)) --> <class 'numpy.ndarray'> |
| 22 | +# print(x.shape) --> (1,) |
| 23 | +# Finding minimum of the function from starting point 'x_start = 2' |
| 24 | +# Using 'minimize' function from 'scipy.optimize' library |
| 25 | +y0_min = optimize.minimize(f_array, x0_start, method='BFGS') |
| 26 | +print(y0_min) # fun = 1.7452682903449388, iterations = 6 |
| 27 | +print() |
| 28 | + |
| 29 | + |
| 30 | +# Setting initial point in form of 'ndarray' as 'minimize' function requires it in form of 'ndarray' |
| 31 | +x1_start = np.array([30]) |
| 32 | +# print(type(x)) --> <class 'numpy.ndarray'> |
| 33 | +# print(x.shape) --> (1,) |
| 34 | +# Finding minimum of smooth function from starting point 'x_start = 30' |
| 35 | +# Using 'minimize' function from 'scipy.optimize' library |
| 36 | +y1_min = optimize.minimize(f_array, x1_start, method='BFGS') |
| 37 | +print(y1_min) # fun = -11.898894665981285, iterations = 6 |
| 38 | +print() |
| 39 | + |
| 40 | + |
| 41 | +# Finding minimum of smooth function with 'differential evolution' method |
| 42 | +# Searching in the range [1, 30] |
| 43 | +# Setting the range for searching in form of tuple inside list as function requires it |
| 44 | +x2_range = [(1, 30)] # tuple inside list |
| 45 | +# Finding minimum of smooth function |
| 46 | +y2_min = optimize.differential_evolution(f_array, [(1, 30)]) |
| 47 | +print(y2_min) # fun = -11.89889467, iterations = 5 |
| 48 | +print() |
| 49 | + |
| 50 | + |
| 51 | +# Task 2 - non-smooth function |
| 52 | +# Initial non-smooth function |
| 53 | +# We take here the same function but only with integer results |
| 54 | +# By using 'np.int_' we return 'numpy.ndarray' of integer numbers |
| 55 | +def h_array(k): |
| 56 | + return np.int_(f_array(k)) |
| 57 | + |
| 58 | + |
| 59 | +# Finding minimum of non-smooth function with 'BFGS' method |
| 60 | +# Setting initial point in form of 'ndarray' as 'minimize' function requires it in form of 'ndarray' |
| 61 | +x3_start = np.array([30]) |
| 62 | +# print(type(x)) --> <class 'numpy.ndarray'> |
| 63 | +# print(x.shape) --> (1,) |
| 64 | +# Finding minimum of the function from starting point 'x_start = 30' |
| 65 | +# Using 'minimize' function from 'scipy.optimize' library |
| 66 | +y3_min = optimize.minimize(h_array, x3_start, method='BFGS') |
| 67 | +print(y3_min) # fun = -5, iterations = 0 |
| 68 | +print() |
| 69 | + |
| 70 | +# Finding minimum of non-smooth function with 'differential evolution' method |
| 71 | +# Searching in the range [1, 30] |
| 72 | +# Setting the range for searching in form of tuple inside list as function requires it |
| 73 | +x4_range = [(1, 30)] # tuple inside list |
| 74 | +# Finding minimum of smooth function |
| 75 | +y4_min = optimize.differential_evolution(h_array, [(1, 30)]) |
| 76 | +print(y4_min) # fun = -11.0, iterations = 3 |
| 77 | +print() |
| 78 | + |
| 79 | +# Plotting smooth and non-smooth functions with found points |
| 80 | +# Creating a figure with subplots |
| 81 | +figure, ax = plt.subplots(nrows=1, ncols=2) |
| 82 | +# ax is (1, 2) np array and to make it easier to read we use 'flatten' function |
| 83 | +# Or we can call each time ax[0, 0] |
| 84 | +ax0, ax1 = ax.flatten() |
| 85 | + |
| 86 | +# Preparing data for plotting smooth function |
| 87 | +# Creating list with numpy method 'arange' |
| 88 | +x0 = np.arange(1, 30, 0.1) |
| 89 | +y0 = f_array(x0) |
| 90 | + |
| 91 | +# Plotting smooth function in range [1, 30] |
| 92 | +# Giving title to the figure and axises |
| 93 | +ax0.set_title('Smooth function f(x)') |
| 94 | +ax0.set_xlabel('x') |
| 95 | +ax0.set_ylabel('y') |
| 96 | +# Showing dashed lines to the found minimums |
| 97 | +# By defining 'ymax' or 'xmax' we limit the end of the lines |
| 98 | +# 'ymax' or 'xmax' can be in range between 0 and 1 |
| 99 | +ax0.axvline(x=4.1362, ymax=0.85, color='c', linestyle='--', linewidth=0.8) |
| 100 | +ax0.axhline(y=1.7452, xmax=0.14, color='c', linestyle='--', linewidth=0.8) |
| 101 | +ax0.axvline(x=25.8801, ymax=0.05, color='r', linestyle='--', linewidth=0.8) |
| 102 | +ax0.axhline(y=-11.8988, xmax=0.83, color='r', linestyle='--', linewidth=0.8) |
| 103 | +# Another way to draw the limited line is as following: |
| 104 | +# ax0.plot(np.arange(1, 10, 2), np.array([2]*5)) # arrays fo axises 'x' and 'y' has to have the same dimensions |
| 105 | +# Creating the figure for smooth function |
| 106 | +ax0.plot(x0, y0, 'b', 4.1362, 1.7452, 'co', 25.8801, -11.8988, 'ro') |
| 107 | + |
| 108 | + |
| 109 | +# Preparing data for plotting non-smooth function |
| 110 | +# Creating list with numpy method 'arange' |
| 111 | +x1 = np.arange(1, 30, 0.1) |
| 112 | +y1 = h_array(x1) |
| 113 | + |
| 114 | +# Plotting non-smooth function in range [1, 30] |
| 115 | +# Giving title to the figure and axises |
| 116 | +ax1.set_title('Non-smooth function h(int(f(x)))') |
| 117 | +ax1.set_xlabel('x') |
| 118 | +ax1.set_ylabel('y') |
| 119 | +# Showing dashed lines to the found minimum |
| 120 | +# By defining 'ymax' or 'xmax' we limit the end of the lines |
| 121 | +# 'ymax' or 'xmax' can be in range between 0 and 1 |
| 122 | +ax1.axvline(x=25.0463, ymax=0.05, color='r', linestyle='--', linewidth=0.8) |
| 123 | +ax1.axhline(y=-11, xmax=0.85, color='r', linestyle='--', linewidth=0.8) |
| 124 | +ax1.axvline(x=30, ymax=0.43, color='c', linestyle='--', linewidth=0.8) |
| 125 | +ax1.axhline(y=-5, xmax=0.95, color='c', linestyle='--', linewidth=0.8) |
| 126 | +# Another way to draw the limited line is as following: |
| 127 | +# ax0.plot(np.arange(1, 10, 2), np.array([2]*5)) # arrays fo axises 'x' and 'y' has to have the same dimensions |
| 128 | +# Creating the figure for non-smooth function |
| 129 | +ax1.plot(x1, y1, 'b', 30, -5, 'co', 25.0463, -11.0, 'ro') |
| 130 | + |
| 131 | + |
| 132 | +# Function to make distance between figures |
| 133 | +plt.tight_layout() |
| 134 | +# Giving the name to the window with figures |
| 135 | +figure.canvas.set_window_title('Smooth and non-smooth functions to be optimized') |
| 136 | +# Showing result |
| 137 | +plt.show() |
0 commit comments