Spaces:
Runtime error
Runtime error
Basis function family selection added.
Browse files- app.py +9 -4
- src/main.py +37 -17
app.py
CHANGED
|
@@ -38,6 +38,8 @@ with st.container():
|
|
| 38 |
available_functions = ["testfunc_2d", "rastrigin_2d", "camel3_2d", "camel16_2d", "treccani_2d", "goldstein_2d", "branin_2d",
|
| 39 |
"rosenbrock_2d", "ackley_2d", "rosenbrock_10d", "griewank_10d", "rastrigin_10d"]
|
| 40 |
|
|
|
|
|
|
|
| 41 |
st.sidebar.header('User Inputs')
|
| 42 |
|
| 43 |
interactive_plot = st.sidebar.checkbox("Interactive Plot")
|
|
@@ -46,6 +48,7 @@ N = st.sidebar.slider("Number of samples:", 100, 10000, 1000, 100)
|
|
| 46 |
|
| 47 |
# n = st.sidebar.slider("Number of variables: ", 1, 10, 2, 1)
|
| 48 |
function_name = st.sidebar.selectbox("Test function:", available_functions)
|
|
|
|
| 49 |
legendreDegree = st.sidebar.slider("Legendre Degree:", 1, 20, 7, 1)
|
| 50 |
|
| 51 |
st.sidebar.write("Function interval: ")
|
|
@@ -61,6 +64,8 @@ random_init = st.sidebar.checkbox("Random Initialization")
|
|
| 61 |
if not random_init:
|
| 62 |
default_x0 = utils.get_function_x0(function_name=function_name.split('_')[0])
|
| 63 |
x0 = st.sidebar.text_input("required format: x1,x2,...,xn",str(default_x0))
|
|
|
|
|
|
|
| 64 |
|
| 65 |
is_adaptive = st.sidebar.checkbox("Adaptive HDMR")
|
| 66 |
|
|
@@ -76,11 +81,11 @@ if st.sidebar.button("Calculate HDMR"):
|
|
| 76 |
|
| 77 |
main.is_streamlit = interactive_plot
|
| 78 |
if is_adaptive:
|
| 79 |
-
status_hdmr, runtime, plt1, plt2, plt3, file_name = main.main_function(N, n, function_name,
|
| 80 |
-
random_init, x0, is_adaptive, num_closest_points, epsilon, clip)
|
| 81 |
else:
|
| 82 |
-
status_hdmr, runtime, plt1, plt2, plt3, file_name = main.main_function(N, n, function_name,
|
| 83 |
-
random_init, x0, is_adaptive)
|
| 84 |
st.subheader("Results")
|
| 85 |
st.write(f"hdmr_opt status Success: {status_hdmr.success} - X: {status_hdmr.x}")
|
| 86 |
st.write("Runtime: {runtime} seconds")
|
|
|
|
| 38 |
available_functions = ["testfunc_2d", "rastrigin_2d", "camel3_2d", "camel16_2d", "treccani_2d", "goldstein_2d", "branin_2d",
|
| 39 |
"rosenbrock_2d", "ackley_2d", "rosenbrock_10d", "griewank_10d", "rastrigin_10d"]
|
| 40 |
|
| 41 |
+
basis_functions = ["Legendre", "Cosine"]
|
| 42 |
+
|
| 43 |
st.sidebar.header('User Inputs')
|
| 44 |
|
| 45 |
interactive_plot = st.sidebar.checkbox("Interactive Plot")
|
|
|
|
| 48 |
|
| 49 |
# n = st.sidebar.slider("Number of variables: ", 1, 10, 2, 1)
|
| 50 |
function_name = st.sidebar.selectbox("Test function:", available_functions)
|
| 51 |
+
basis_funtion = st.sidebar.selectbox("Legendre Basis", basis_functions)
|
| 52 |
legendreDegree = st.sidebar.slider("Legendre Degree:", 1, 20, 7, 1)
|
| 53 |
|
| 54 |
st.sidebar.write("Function interval: ")
|
|
|
|
| 64 |
if not random_init:
|
| 65 |
default_x0 = utils.get_function_x0(function_name=function_name.split('_')[0])
|
| 66 |
x0 = st.sidebar.text_input("required format: x1,x2,...,xn",str(default_x0))
|
| 67 |
+
else:
|
| 68 |
+
x0 = None
|
| 69 |
|
| 70 |
is_adaptive = st.sidebar.checkbox("Adaptive HDMR")
|
| 71 |
|
|
|
|
| 81 |
|
| 82 |
main.is_streamlit = interactive_plot
|
| 83 |
if is_adaptive:
|
| 84 |
+
status_hdmr, runtime, plt1, plt2, plt3, file_name = main.main_function(N, n, function_name, basis_funtion, legendreDegree,
|
| 85 |
+
interval[0], interval[1], random_init, x0, is_adaptive, num_closest_points, epsilon, clip)
|
| 86 |
else:
|
| 87 |
+
status_hdmr, runtime, plt1, plt2, plt3, file_name = main.main_function(N, n, function_name, basis_funtion, legendreDegree,
|
| 88 |
+
interval[0], interval[1], random_init, x0, is_adaptive)
|
| 89 |
st.subheader("Results")
|
| 90 |
st.write(f"hdmr_opt status Success: {status_hdmr.success} - X: {status_hdmr.x}")
|
| 91 |
st.write("Runtime: {runtime} seconds")
|
src/main.py
CHANGED
|
@@ -60,23 +60,31 @@ def test_func(x):
|
|
| 60 |
y = np.sum(x**2, axis=axis, keepdims=True)
|
| 61 |
return y
|
| 62 |
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
disp=False, return_all=False, finite_diff_rel_step=None,
|
| 66 |
-
**unknown_options):
|
| 67 |
-
global plt1, plt2, plt3, a, b, xs
|
| 68 |
-
|
| 69 |
-
def Pn(m, x):
|
| 70 |
if m == 0:
|
| 71 |
return np.ones_like(x)
|
| 72 |
elif m == 1:
|
| 73 |
return x
|
| 74 |
else:
|
| 75 |
return (2*m-1)*x*Pn(m-1, x)/m - (m-1)*Pn(m-2, x)/m
|
| 76 |
-
|
| 77 |
-
|
| 78 |
return np.sqrt((2*m+1)/(b-a))*Pn(m, 2*(x-b)/(b-a)+1)
|
| 79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
def calculate_alpha_coeff(xs):
|
| 81 |
N, n = xs.shape
|
| 82 |
alpha = np.zeros((m, n))
|
|
@@ -84,7 +92,7 @@ def hdmr_opt(fun, x0, args=(), jac=None, callback=None,
|
|
| 84 |
f0 = np.mean(y)
|
| 85 |
for r in range(m): # Iterate degree of the Legendre polynomial
|
| 86 |
for i in range(n): # Iterate number of variable
|
| 87 |
-
alpha[r, i] = (b - a) * np.mean((y-f0) *
|
| 88 |
return alpha
|
| 89 |
|
| 90 |
def evalute_hdmr(x, f0, alpha):
|
|
@@ -93,21 +101,21 @@ def hdmr_opt(fun, x0, args=(), jac=None, callback=None,
|
|
| 93 |
y = f0 * np.ones((N,1))
|
| 94 |
for r in range(m):
|
| 95 |
for i in range(n):
|
| 96 |
-
y = y + alpha[r, i] *
|
| 97 |
return y
|
| 98 |
|
| 99 |
def one_dim_evaluate_hdmr(x):
|
| 100 |
m, _ = alpha.shape
|
| 101 |
f = 0
|
| 102 |
for r in range(m):
|
| 103 |
-
f = f + alpha[r,i] *
|
| 104 |
return f
|
| 105 |
|
| 106 |
def one_dim_evaluate_hdmr_for_test(x, idx_var):
|
| 107 |
m, _ = alpha.shape
|
| 108 |
f = np.zeros((N,1))
|
| 109 |
for r in range(m):
|
| 110 |
-
f = f + alpha[r,idx_var] *
|
| 111 |
return f
|
| 112 |
|
| 113 |
def plot_results():
|
|
@@ -359,18 +367,27 @@ def hdmr_opt(fun, x0, args=(), jac=None, callback=None,
|
|
| 359 |
plt2 = None
|
| 360 |
return result
|
| 361 |
|
| 362 |
-
def main_function(N_, n_, function_name_, m_, a_, b_, random_init_, x0_, is_adaptive_, k_=None, epsilon_=None, clip_=None):
|
| 363 |
-
global N, n, function_name, m, a, b, random_init, is_adaptive, k, epsilon, clip
|
|
|
|
|
|
|
|
|
|
| 364 |
|
| 365 |
N = N_
|
| 366 |
n = n_
|
| 367 |
function_name = function_name_
|
|
|
|
| 368 |
m = m_
|
| 369 |
a = a_
|
| 370 |
b = b_
|
| 371 |
random_init = random_init_
|
| 372 |
is_adaptive = is_adaptive_
|
| 373 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 374 |
if is_adaptive:
|
| 375 |
k = k_
|
| 376 |
epsilon = epsilon_
|
|
@@ -387,9 +404,10 @@ def main_function(N_, n_, function_name_, m_, a_, b_, random_init_, x0_, is_adap
|
|
| 387 |
file_name += '_randomInit'
|
| 388 |
if function_name.split('_')[1] == '2d':
|
| 389 |
x0 = np.random.rand(2) * (b - a) + a # Initial value of function for optimizing process
|
|
|
|
| 390 |
elif function_name.split('_')[1] == '10d':
|
| 391 |
x0 = np.random.rand(10) * (b - a) + a
|
| 392 |
-
|
| 393 |
|
| 394 |
# status_bfgs = minimize(test_function, x0, method="BFGS") # Applying direct optimization method to the function
|
| 395 |
# print(f"BFGS status: {status_bfgs}")
|
|
@@ -412,6 +430,7 @@ if __name__ == "__main__":
|
|
| 412 |
parser.add_argument('--min', type=float, help='Lower range of the test function.', required=True)
|
| 413 |
parser.add_argument('--max', type=float, help='Upper range of the test function.', required=True)
|
| 414 |
parser.add_argument('--randomInit', action='store_true', help='Initializes x0 as random numbers in the range of xs. Default is initializing as 0.')
|
|
|
|
| 415 |
parser.add_argument('--legendreDegree', type=int, default=7, help='Number of legendre polynomial. Default is 7.')
|
| 416 |
parser.add_argument('--adaptive', action='store_true', help='Uses iterative method when set.')
|
| 417 |
parser.add_argument('--numClosestPoints', type=int, help='Number of closest points to x0. Default is 1000.', default=100)
|
|
@@ -424,6 +443,7 @@ if __name__ == "__main__":
|
|
| 424 |
N_ = global_args.numSamples # Number of samples to calculate alpha coefficients
|
| 425 |
n_ = global_args.numVariables # Number of variable
|
| 426 |
function_name_ = global_args.function
|
|
|
|
| 427 |
m_ = global_args.legendreDegree # Degree of the Legendre polynomial
|
| 428 |
a_ = global_args.min # Range of the function
|
| 429 |
b_ = global_args.max # Range of the function
|
|
@@ -433,7 +453,7 @@ if __name__ == "__main__":
|
|
| 433 |
epsilon_ = global_args.epsilon
|
| 434 |
clip_ = global_args.clip
|
| 435 |
|
| 436 |
-
status_hdmr, runtime, _, _, _, file_name = main_function(N_, n_, function_name_, m_, a_, b_, random_init_,
|
| 437 |
is_adaptive_, k_, epsilon_, clip_)
|
| 438 |
print(f"{runtime} seconds")
|
| 439 |
print(f"hdmr_opt status: {status_hdmr}")
|
|
|
|
| 60 |
y = np.sum(x**2, axis=axis, keepdims=True)
|
| 61 |
return y
|
| 62 |
|
| 63 |
+
## ------------------ BASIS FUNCTIONS START ------------------ ##
|
| 64 |
+
def Pn(m, x):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
if m == 0:
|
| 66 |
return np.ones_like(x)
|
| 67 |
elif m == 1:
|
| 68 |
return x
|
| 69 |
else:
|
| 70 |
return (2*m-1)*x*Pn(m-1, x)/m - (m-1)*Pn(m-2, x)/m
|
| 71 |
+
|
| 72 |
+
def Legendre(a,b,m,x):
|
| 73 |
return np.sqrt((2*m+1)/(b-a))*Pn(m, 2*(x-b)/(b-a)+1)
|
| 74 |
|
| 75 |
+
def Cosine(a,b,m,x):
|
| 76 |
+
square_root_term = np.sqrt(1 / (b-a) * 8 * math.pi * m / (math.sin(4 * math.pi * m) + 4 * math.pi * m))
|
| 77 |
+
outer_term = np.cos(2 * math.pi * m * (x - a) / (b - a))
|
| 78 |
+
return square_root_term * outer_term
|
| 79 |
+
|
| 80 |
+
## ------------------ BASIS FUNCTIONS END ------------------ ##
|
| 81 |
+
|
| 82 |
+
def hdmr_opt(fun, x0, args=(), jac=None, callback=None,
|
| 83 |
+
gtol=1e-5, maxiter=None,
|
| 84 |
+
disp=False, return_all=False, finite_diff_rel_step=None,
|
| 85 |
+
**unknown_options):
|
| 86 |
+
global plt1, plt2, plt3, a, b, xs
|
| 87 |
+
|
| 88 |
def calculate_alpha_coeff(xs):
|
| 89 |
N, n = xs.shape
|
| 90 |
alpha = np.zeros((m, n))
|
|
|
|
| 92 |
f0 = np.mean(y)
|
| 93 |
for r in range(m): # Iterate degree of the Legendre polynomial
|
| 94 |
for i in range(n): # Iterate number of variable
|
| 95 |
+
alpha[r, i] = (b - a) * np.mean((y-f0) * BasisFunction(a, b, r+1, np.array(xs[:, [i]])))
|
| 96 |
return alpha
|
| 97 |
|
| 98 |
def evalute_hdmr(x, f0, alpha):
|
|
|
|
| 101 |
y = f0 * np.ones((N,1))
|
| 102 |
for r in range(m):
|
| 103 |
for i in range(n):
|
| 104 |
+
y = y + alpha[r, i] * BasisFunction(a, b, r+1, np.array(x[:, [i]])) # Meta-model
|
| 105 |
return y
|
| 106 |
|
| 107 |
def one_dim_evaluate_hdmr(x):
|
| 108 |
m, _ = alpha.shape
|
| 109 |
f = 0
|
| 110 |
for r in range(m):
|
| 111 |
+
f = f + alpha[r,i] * BasisFunction(a, b, r+1, x) # One dimensional functions
|
| 112 |
return f
|
| 113 |
|
| 114 |
def one_dim_evaluate_hdmr_for_test(x, idx_var):
|
| 115 |
m, _ = alpha.shape
|
| 116 |
f = np.zeros((N,1))
|
| 117 |
for r in range(m):
|
| 118 |
+
f = f + alpha[r,idx_var] * BasisFunction(a, b, r+1, x)
|
| 119 |
return f
|
| 120 |
|
| 121 |
def plot_results():
|
|
|
|
| 367 |
plt2 = None
|
| 368 |
return result
|
| 369 |
|
| 370 |
+
def main_function(N_, n_, function_name_, basis_function_, m_, a_, b_, random_init_, x0_, is_adaptive_, k_=None, epsilon_=None, clip_=None):
|
| 371 |
+
global N, n, function_name, basis_function, BasisFunction, m, a, b, random_init, is_adaptive, k, epsilon, clip
|
| 372 |
+
|
| 373 |
+
if basis_function_ not in ["Legendre", "Cosine"]:
|
| 374 |
+
raise ValueError("basis_function should be Cosine or Legendre.")
|
| 375 |
|
| 376 |
N = N_
|
| 377 |
n = n_
|
| 378 |
function_name = function_name_
|
| 379 |
+
basis_function = basis_function_
|
| 380 |
m = m_
|
| 381 |
a = a_
|
| 382 |
b = b_
|
| 383 |
random_init = random_init_
|
| 384 |
is_adaptive = is_adaptive_
|
| 385 |
|
| 386 |
+
if basis_function == "Legendre":
|
| 387 |
+
BasisFunction = Legendre
|
| 388 |
+
elif basis_function == "Cosine":
|
| 389 |
+
BasisFunction = Cosine
|
| 390 |
+
|
| 391 |
if is_adaptive:
|
| 392 |
k = k_
|
| 393 |
epsilon = epsilon_
|
|
|
|
| 404 |
file_name += '_randomInit'
|
| 405 |
if function_name.split('_')[1] == '2d':
|
| 406 |
x0 = np.random.rand(2) * (b - a) + a # Initial value of function for optimizing process
|
| 407 |
+
x0_ = x0
|
| 408 |
elif function_name.split('_')[1] == '10d':
|
| 409 |
x0 = np.random.rand(10) * (b - a) + a
|
| 410 |
+
x0_ = x0
|
| 411 |
|
| 412 |
# status_bfgs = minimize(test_function, x0, method="BFGS") # Applying direct optimization method to the function
|
| 413 |
# print(f"BFGS status: {status_bfgs}")
|
|
|
|
| 430 |
parser.add_argument('--min', type=float, help='Lower range of the test function.', required=True)
|
| 431 |
parser.add_argument('--max', type=float, help='Upper range of the test function.', required=True)
|
| 432 |
parser.add_argument('--randomInit', action='store_true', help='Initializes x0 as random numbers in the range of xs. Default is initializing as 0.')
|
| 433 |
+
parser.add_argument('--basisFunction', type=int, default="Cosine", help='Basis function that will be used in HDMR. Legendre or Cosine. Default is Cosine.')
|
| 434 |
parser.add_argument('--legendreDegree', type=int, default=7, help='Number of legendre polynomial. Default is 7.')
|
| 435 |
parser.add_argument('--adaptive', action='store_true', help='Uses iterative method when set.')
|
| 436 |
parser.add_argument('--numClosestPoints', type=int, help='Number of closest points to x0. Default is 1000.', default=100)
|
|
|
|
| 443 |
N_ = global_args.numSamples # Number of samples to calculate alpha coefficients
|
| 444 |
n_ = global_args.numVariables # Number of variable
|
| 445 |
function_name_ = global_args.function
|
| 446 |
+
basis_function_ = global_args.basis_function
|
| 447 |
m_ = global_args.legendreDegree # Degree of the Legendre polynomial
|
| 448 |
a_ = global_args.min # Range of the function
|
| 449 |
b_ = global_args.max # Range of the function
|
|
|
|
| 453 |
epsilon_ = global_args.epsilon
|
| 454 |
clip_ = global_args.clip
|
| 455 |
|
| 456 |
+
status_hdmr, runtime, _, _, _, file_name = main_function(N_, n_, function_name_, basis_function_, m_, a_, b_, random_init_,
|
| 457 |
is_adaptive_, k_, epsilon_, clip_)
|
| 458 |
print(f"{runtime} seconds")
|
| 459 |
print(f"hdmr_opt status: {status_hdmr}")
|