This is a demo for Bayesian Optimization using PFN (Prior-Data Fitted Networks). \n",
+ " Select your objective function by clicking on one of the check boxes below, then enter the iteration number to run the optimization process. \n",
+ " The results will be visualized in the radar chart and convergence plot.
Pre-trained Transformer for Constrained Bayesian Optimization
\n",
+ "
This is a demo for Bayesian Optimization using PFN (Prior-Data Fitted Networks). \n",
+ " Select your objective function by clicking on one of the check boxes below, then enter the iteration number to run the optimization process. \n",
+ " The results will be visualized in the radar chart and convergence plot.
\n",
+ " \n",
+ "\n",
+ "
\n",
+ " \"\"\"\n",
+ " )\n",
+ "\n",
+ " selected_objective = gr.State(None) # To store the selected objective function\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ " \n",
+ " with gr.Row():\n",
+ " \n",
+ " objective_checkbox_group = gr.CheckboxGroup(\n",
+ " choices=[\"JLH1\", \"JLH2\", \"GKXWC1\", \"GKXWC2\", \"Ackley2D\", \"Ackley6D\", \"Ackley10D\", \"Keane Bump\", \"Three Truss\", \"Reinforced Concrete Beam\", \"Pressure Vessel\", \"Welded Beam\", \"Speed Reducer\", \"Car\"],\n",
+ " label=\"Select the design problem:\"\n",
+ " )\n",
+ " with gr.Row():\n",
+ " iteration_input = gr.Number(label=\"Enter Iteration Number:\", value=10)\n",
+ " \n",
+ "\n",
+ " # Row for the Clear and Submit buttons\n",
+ " with gr.Row():\n",
+ " clear_button = gr.Button(\"Clear\")\n",
+ " submit_button = gr.Button(\"Submit\", variant=\"primary\")\n",
+ " \n",
+ " \n",
+ " with gr.Row():\n",
+ " with gr.Column():\n",
+ " radar_plot = gr.Plot(label=\"Resulting Design\")\n",
+ " with gr.Column():\n",
+ " convergence_plot = gr.Plot(label=\"Convergence Plot\")\n",
+ "\n",
+ "\n",
+ "\n",
+ " # Define actions for buttons\n",
+ " def clear_action():\n",
+ " return None, None, None\n",
+ "\n",
+ " def submit_action(objective_function_choices, iteration_input):\n",
+ " # Handle the case where multiple choices are selected\n",
+ " if len(objective_function_choices) > 0:\n",
+ " selected_function = objective_function_choices[0] # Assuming using the first selected function\n",
+ " return optimize(selected_function, iteration_input)\n",
+ " return None, None\n",
+ "\n",
+ " # Button click actions\n",
+ " clear_button.click(clear_action, outputs=[objective_checkbox_group, radar_plot, convergence_plot])\n",
+ " submit_button.click(\n",
+ " submit_action, \n",
+ " inputs=[objective_checkbox_group, iteration_input], \n",
+ " outputs=[radar_plot, convergence_plot]\n",
+ " )\n",
+ "\n",
+ "demo.launch(share=True)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "352d0291-93b4-43eb-b683-3d48776dc670",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "92ecbbe6-dea6-4e7f-aae1-f0d442dbda3b",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ba69b5f9-c52c-4c23-8645-c81c27f7a815",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "05789fba-2099-46b7-8675-64b7969427a1",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Running on local URL: http://127.0.0.1:7899\n",
+ "\n",
+ "To create a public link, set `share=True` in `launch()`.\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import gradio as gr\n",
+ "\n",
+ "def calculator(num1, operation, num2):\n",
+ " if operation == \"add\":\n",
+ " return num1 + num2\n",
+ " elif operation == \"subtract\":\n",
+ " return num1 - num2\n",
+ " elif operation == \"multiply\":\n",
+ " return num1 * num2\n",
+ " elif operation == \"divide\":\n",
+ " return num1 / num2\n",
+ "\n",
+ "with gr.Blocks() as demo:\n",
+ " with gr.Row():\n",
+ " with gr.Column():\n",
+ " num_1 = gr.Number(value=4)\n",
+ " operation = gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"])\n",
+ " num_2 = gr.Number(value=0)\n",
+ " submit_btn = gr.Button(value=\"Calculate\")\n",
+ " with gr.Column():\n",
+ " result = gr.Number()\n",
+ "\n",
+ " submit_btn.click(\n",
+ " calculator, inputs=[num_1, operation, num_2], outputs=[result], api_name=False\n",
+ " )\n",
+ " examples = gr.Examples(\n",
+ " examples=[\n",
+ " [5, \"add\", 3],\n",
+ " [4, \"divide\", 2],\n",
+ " [-4, \"multiply\", 2.5],\n",
+ " [0, \"subtract\", 1.2],\n",
+ " ],\n",
+ " inputs=[num_1, operation, num_2],\n",
+ " )\n",
+ "\n",
+ "if __name__ == \"__main__\":\n",
+ " demo.launch(show_api=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a4bf709a-ff0a-4aac-a4b4-fd98cd5948bb",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "679f7647-ca68-46f9-a1da-81d6c96267c9",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ea40bfac-e090-4cd5-9caa-99b06db3ea8d",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 50,
+ "id": "928ac99a-af8f-401c-8c0b-ef83cfef5ba9",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Running on local URL: http://127.0.0.1:7890\n",
+ "\n",
+ "To create a public link, set `share=True` in `launch()`.\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import gradio as gr\n",
+ "\n",
+ "def calculator(num1, operation, num2):\n",
+ " if operation == \"add\":\n",
+ " return num1 + num2\n",
+ " elif operation == \"subtract\":\n",
+ " return num1 - num2\n",
+ " elif operation == \"multiply\":\n",
+ " return num1 * num2\n",
+ " elif operation == \"divide\":\n",
+ " return num1 / num2\n",
+ "\n",
+ "with gr.Blocks() as demo:\n",
+ " with gr.Row():\n",
+ " with gr.Column():\n",
+ " num_1 = gr.Number(value=4)\n",
+ " operation = gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"])\n",
+ " num_2 = gr.Number(value=0)\n",
+ " submit_btn = gr.Button(value=\"Calculate\")\n",
+ " with gr.Column():\n",
+ " result = gr.Number()\n",
+ "\n",
+ " submit_btn.click(\n",
+ " calculator, inputs=[num_1, operation, num_2], outputs=[result], api_name=False\n",
+ " )\n",
+ " examples = gr.Examples(\n",
+ " examples=[\n",
+ " [5, \"add\", 3],\n",
+ " [4, \"divide\", 2],\n",
+ " [-4, \"multiply\", 2.5],\n",
+ " [0, \"subtract\", 1.2],\n",
+ " ],\n",
+ " inputs=[num_1, operation, num_2],\n",
+ " )\n",
+ "\n",
+ "if __name__ == \"__main__\":\n",
+ " demo.launch(show_api=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "id": "09a251df-4076-4925-8799-9a2a59cb8246",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# import gradio as gr\n",
+ "\n",
+ "# def greet(selected_options):\n",
+ "# return f\"You selected: {', '.join(selected_options)}\"\n",
+ "\n",
+ "# with gr.Blocks() as demo:\n",
+ "# with gr.Row():\n",
+ "# checkbox_group = gr.CheckboxGroup(\n",
+ "# choices=[\"Option 1\", \"Option 2\"],\n",
+ "# label=\"Select your options\",\n",
+ "# elem_id=\"custom_checkbox_group\"\n",
+ "# )\n",
+ "# output = gr.Textbox(label=\"Output\")\n",
+ " \n",
+ "# checkbox_group.change(greet, checkbox_group, output)\n",
+ "\n",
+ "# gr.HTML(\n",
+ "# f\"\"\"\n",
+ "# \n",
+ "# \n",
+ "# \"\"\"\n",
+ "# )\n",
+ "\n",
+ "# demo.launch()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f52549d5-4be0-4672-be6d-df462957cb56",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.14"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/HeatExchanger.png b/HeatExchanger.png
new file mode 100644
index 0000000000000000000000000000000000000000..f39f7ea770061ba76a7f099143f75ab7c750bbab
Binary files /dev/null and b/HeatExchanger.png differ
diff --git a/HeatExchanger_CEI_Avg_Obj.pt b/HeatExchanger_CEI_Avg_Obj.pt
new file mode 100644
index 0000000000000000000000000000000000000000..82c9dc0c254a831dc14c6b19559c3cfafa486411
--- /dev/null
+++ b/HeatExchanger_CEI_Avg_Obj.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6fc95574634750d3dc892076b26e55c6f79d4dbb128d5b65e6832e83783c89a8
+size 3432
diff --git a/HeatExchanger_CEI_Avg_Time.pt b/HeatExchanger_CEI_Avg_Time.pt
new file mode 100644
index 0000000000000000000000000000000000000000..95244d405e1a11063e9cad7ce46b520e293fc381
--- /dev/null
+++ b/HeatExchanger_CEI_Avg_Time.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0ed8e01768b9cc8bf82c51f523c9ea46c4f3e7e3e9e6c8e04edb0d615032f1e9
+size 3500
diff --git a/PressureVessel.png b/PressureVessel.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3c520ca046c0cebea4d8092a45cce025bfd71af
Binary files /dev/null and b/PressureVessel.png differ
diff --git a/PressureVessel_CEI_Avg_Obj.pt b/PressureVessel_CEI_Avg_Obj.pt
new file mode 100644
index 0000000000000000000000000000000000000000..43e2fba66fc94b86cf90e35bbed18bbfa7575dc4
--- /dev/null
+++ b/PressureVessel_CEI_Avg_Obj.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f7c81ea242bdcb45cb644cd5f18b941ff8ebbcbbb81b9965eea251c01f9f6c78
+size 3628
diff --git a/PressureVessel_CEI_Avg_Time.pt b/PressureVessel_CEI_Avg_Time.pt
new file mode 100644
index 0000000000000000000000000000000000000000..3db420c0bcf0d85fb9273b8624371d949ad271e8
--- /dev/null
+++ b/PressureVessel_CEI_Avg_Time.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:eb204723d0523baebbfda6e4f1fdbc7506c66bfc0ed0cbc7ec5ea485451660a7
+size 3504
diff --git a/ReinforcedConcreteBeam_CEI_Avg_Obj.pt b/ReinforcedConcreteBeam_CEI_Avg_Obj.pt
new file mode 100644
index 0000000000000000000000000000000000000000..d23fdb38ab7b5c83c4f107dc975b81ecb392e3cf
--- /dev/null
+++ b/ReinforcedConcreteBeam_CEI_Avg_Obj.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5d2e3212a28eb9cb59212d876c1ddae2f1b37950974eed01683c7d4180206c7e
+size 3532
diff --git a/ReinforcedConcreteBeam_CEI_Avg_Time.pt b/ReinforcedConcreteBeam_CEI_Avg_Time.pt
new file mode 100644
index 0000000000000000000000000000000000000000..3e648a4d2cebcc833c9e725820ecb6b711c33ee1
--- /dev/null
+++ b/ReinforcedConcreteBeam_CEI_Avg_Time.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aae5672638e75081965450635cc15310f90ee167c3264399bee07afc2ad3a58d
+size 3472
diff --git a/Reinforcement.png b/Reinforcement.png
new file mode 100644
index 0000000000000000000000000000000000000000..468a4667432799d9c499e5799be732fd63971789
Binary files /dev/null and b/Reinforcement.png differ
diff --git a/Rosen_PFN4BO.py b/Rosen_PFN4BO.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a0ab3809cd7c46d667ecb6afc4585ee3407adf4
--- /dev/null
+++ b/Rosen_PFN4BO.py
@@ -0,0 +1,442 @@
+import contextlib
+import torch
+import scipy
+import math
+from sklearn.preprocessing import power_transform, PowerTransformer, StandardScaler
+
+from torchvision.transforms.functional import to_tensor
+from pfns4bo import transformer
+from pfns4bo import bar_distribution
+
+import torch
+import numpy as np
+
+import pfns4bo
+from pfns4bo.scripts.acquisition_functions import TransformerBOMethod
+
+
+import warnings
+warnings.filterwarnings('ignore')
+
+device = torch.device("cpu")
+# device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+dtype = torch.float32
+
+
+from sklearn.utils import resample
+
+@torch.enable_grad()
+def Rosen_PFN(model_name,
+ trained_X,
+ trained_Y,
+ X_pen,
+ trasform_type,
+ what_do_you_want
+ ):
+
+ PFN = TransformerBOMethod(torch.load(model_name).requires_grad_(False), device=device)
+
+ # X_pen.requires_grad_(True)
+
+ # with torch.no_grad():
+
+
+ dim = trained_X.shape[1]
+
+ x_given = trained_X
+ x_eval = X_pen
+ x_predict = torch.cat([x_given, x_eval], dim=0)
+ x_full_feed = torch.cat([x_given, x_given, x_eval], dim=0).unsqueeze(1)
+
+
+
+ if trasform_type== 'std':
+ pt = StandardScaler()
+ pt.fit(trained_Y)
+ PT_trained_Y = pt.transform(trained_Y)
+ trained_Y = to_tensor(PT_trained_Y).to(torch.float32).reshape(trained_Y.shape)
+ elif trasform_type== 'power':
+ pt = PowerTransformer(method="yeo-johnson")
+ pt.fit(trained_Y.detach().numpy())
+ # PT_trained_Y = pt.transform(trained_Y.detach().numpy())
+ # trained_Y = to_tensor(PT_trained_Y).to(torch.float32).reshape(trained_Y.shape)
+ # print(trained_Y.shape)
+
+ # print(trained_Y)
+ trained_Y, _ = general_power_transform(trained_Y,
+ trained_Y,
+ .0,
+ less_safe=False) #.squeeze(1)
+ # print(trained_Y.shape)
+ # .squeeze(1)
+
+
+ # y_given = general_power_transform(y_given.unsqueeze(1),
+ # y_given.unsqueeze(1),
+ # .0,
+ # less_safe=False).squeeze(1)
+
+ y_given = trained_Y
+
+ y_given = y_given.reshape(-1)
+ y_full_feed = y_given.unsqueeze(1)
+
+ criterion: bar_distribution.BarDistribution = PFN.model.criterion
+
+ style = None
+ logits = PFN.model(
+ (style,
+ x_full_feed.repeat_interleave(dim=1, repeats=y_full_feed.shape[1]),
+ y_full_feed.repeat(1,x_full_feed.shape[1])),
+ single_eval_pos=len(x_given)
+ )
+
+ # logits = logits.softmax(-1).log_()
+ logits = logits.softmax(-1).log()
+
+ logits_given = logits[:len(x_given)]
+ logits_eval = logits[len(x_given):]
+
+ best_f = torch.max(y_given)
+
+ if what_do_you_want == 'mean':
+ output = criterion.mean(logits_eval)
+
+
+ if trasform_type== 'std' or trasform_type== 'power':
+
+ if pt.standardize:
+ XX = output.clone()
+ scale = torch.from_numpy(pt._scaler.scale_)
+ std_mean = torch.from_numpy(pt._scaler.mean_)
+ XX = torch_std_inverse_transform(XX, scale, std_mean)
+
+ for i, lmbda in enumerate(pt.lambdas_):
+ with np.errstate(invalid="ignore"): # hide NaN warnings
+ XX = torch_power_inverse_transform(XX, lmbda)
+ # print(XX)
+ return XX
+
+
+
+
+
+ # output = pt.inverse_transform(output)
+ # output = torch.from_numpy(output)
+
+
+ elif what_do_you_want == 'ei':
+ output = criterion.ei(logits_eval, best_f)
+
+ elif what_do_you_want == 'ucb':
+ acq_function = criterion.ucb
+ ucb_rest_prob = .05
+ if ucb_rest_prob is not None:
+ acq_function = lambda *args: criterion.ucb(*args, rest_prob=ucb_rest_prob)
+ output = acq_ensembling(acq_function(logits_eval, best_f))
+
+ elif what_do_you_want == 'variance':
+ output = criterion.variance(logits_eval)
+
+ elif what_do_you_want == 'mode':
+ output = criterion.mode(logits_eval)
+
+ elif what_do_you_want == 'ts':
+ mn = criterion.mean(logits_eval)
+
+
+ if trasform_type== 'std' or trasform_type== 'power':
+
+ if pt.standardize:
+ XX = mn.clone()
+ scale = torch.from_numpy(pt._scaler.scale_)
+ std_mean = torch.from_numpy(pt._scaler.mean_)
+ XX = torch_std_inverse_transform(XX, scale, std_mean)
+
+ for i, lmbda in enumerate(pt.lambdas_):
+ with np.errstate(invalid="ignore"): # hide NaN warnings
+ XX = torch_power_inverse_transform(XX, lmbda)
+
+ var = criterion.variance(logits_eval)
+
+ return XX, var
+
+ return output
+
+
+
+
+
+
+
+
+
+
+
+def Rosen_PFN_Parallel(model_name,
+ trained_X,
+ trained_Y,
+ GX,
+ X_pen,
+ trasform_type,
+ what_do_you_want
+ ):
+
+ PFN = TransformerBOMethod(torch.load(model_name), device=device)
+
+ with torch.no_grad():
+
+
+ dim = trained_X.shape[1]
+
+ x_given = trained_X
+ x_eval = X_pen
+ x_predict = torch.cat([x_given, x_eval], dim=0)
+ x_full_feed = torch.cat([x_given, x_given, x_eval], dim=0).unsqueeze(1)
+
+
+
+ y_given = trained_Y
+ y_given = y_given.reshape(-1)
+
+ ######################################################################
+ # Objective Power Transform
+ y_given, pt_y = general_power_transform(y_given.unsqueeze(1),
+ y_given.unsqueeze(1),
+ .0,
+ less_safe=False)
+ y_given = y_given.squeeze(1)
+ ######################################################################
+
+
+ ######################################################################
+ # Constraints Power Transform
+ # Changes for Parallel:
+ GX = -GX
+ GX_t, pt_GX = general_power_transform(GX, GX, .0, less_safe=False)
+ G_thres, _ = general_power_transform(GX,
+ torch.zeros((1, GX.shape[1])).to(GX.device),
+ .0,
+ less_safe=False)
+ GX = GX_t
+ ######################################################################
+
+
+
+ y_full_feed = y_given.unsqueeze(1)
+
+ criterion: bar_distribution.BarDistribution = PFN.model.criterion
+
+ style = None
+ logits = PFN.model(
+ (style,
+ x_full_feed.repeat_interleave(dim=1, repeats=y_full_feed.shape[1]+GX.shape[1]),
+ torch.cat([y_full_feed, GX], dim=1).unsqueeze(2) ),
+ single_eval_pos=len(x_given)
+ )
+
+ logits = logits.softmax(-1).log_()
+
+ logits_given = logits[:len(x_given)]
+ logits_eval = logits[len(x_given):]
+
+ best_f = torch.max(y_given)
+
+ objective_given = logits_given[:,0,:].unsqueeze(1)
+ objective_eval = logits_eval[:,0,:].unsqueeze(1)
+ constraint_given = logits_given[:,1:,:]
+ constraint_eval = logits_eval[:,1:,:]
+
+
+
+ if what_do_you_want == 'mean':
+ obj_output = criterion.mean(objective_eval)
+ con_output = criterion.mean(constraint_eval)
+
+ elif what_do_you_want == 'ei':
+ # Changes for CEI
+
+ # Objective
+ tau = torch.max(y_given)
+ objective_acq_value = acq_ensembling(criterion.ei(objective_eval, tau))
+
+ # Constraints
+ constraints_acq_value = acq_ensembling(criterion.pi(constraint_eval[:,0,:].unsqueeze(1), G_thres[0, 0].item()))
+ constraints_acq_value = constraints_acq_value.unsqueeze(1)
+
+
+ for jj in range(1,constraint_eval.shape[1]):
+ next_constraints_acq_value = acq_ensembling(criterion.pi(constraint_eval[:,jj,:].unsqueeze(1), G_thres[0, jj].item()))
+ next_constraints_acq_value = next_constraints_acq_value.unsqueeze(1)
+ constraints_acq_value = torch.cat([constraints_acq_value,next_constraints_acq_value], dim=1)
+
+ return objective_acq_value, constraints_acq_value
+
+
+ elif what_do_you_want == 'variance':
+ output = criterion.variance(logits_eval)
+ elif what_do_you_want == 'mode':
+ output = criterion.mode(logits_eval)
+ elif what_do_you_want == 'cts':
+ obj_mnn = criterion.mean(objective_eval)
+ obj_mnn = pt_y.inverse_transform(obj_mnn)
+ obj_mnn = torch.from_numpy(obj_mnn)
+
+
+ con_mnn = criterion.mean(constraint_eval)
+ con_mnn = pt_GX.inverse_transform(con_mnn)
+ con_mnn = torch.from_numpy(-con_mnn)
+
+ obj_varr = criterion.variance(objective_eval)
+ con_varr = criterion.variance(constraint_eval)
+
+ return obj_mnn, obj_varr, con_mnn, con_varr
+
+
+
+ return output
+
+
+
+
+def acq_ensembling(acq_values): # (points, ensemble dim)
+ return acq_values.max(1).values
+
+
+
+
+
+
+
+def torch_std_inverse_transform(X, scale, mean):
+ X *= scale
+ X += mean
+ return X
+
+
+def torch_power_inverse_transform(x, lmbda):
+ out = torch.zeros_like(x)
+ pos = x >= 0
+
+ # when x >= 0
+ if abs(lmbda) < np.spacing(1.0):
+ out[pos] = torch.exp(x[pos])-1
+ else: # lmbda != 0
+ out[pos] = torch.pow(x[pos] * lmbda + 1, 1 / lmbda) - 1
+
+ # when x < 0
+ if abs(lmbda - 2) > np.spacing(1.0):
+ out[~pos] = 1 - torch.pow(-(2 - lmbda) * x[~pos] + 1, 1 / (2 - lmbda))
+ else: # lmbda == 2
+ out[~pos] = 1 - torch.exp(-x[~pos])
+
+ return out
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+################################################################################
+## PFN defined functions
+################################################################################
+
+
+def log01(x, eps=.0000001, input_between_zero_and_one=False):
+ logx = torch.log(x + eps)
+ if input_between_zero_and_one:
+ return (logx - math.log(eps)) / (math.log(1 + eps) - math.log(eps))
+ return (logx - logx.min(0)[0]) / (logx.max(0)[0] - logx.min(0)[0])
+
+def log01_batch(x, eps=.0000001, input_between_zero_and_one=False):
+ x = x.repeat(1, x.shape[-1] + 1, 1)
+ for b in range(x.shape[-1]):
+ x[:, b, b] = log01(x[:, b, b], eps=eps, input_between_zero_and_one=input_between_zero_and_one)
+ return x
+
+def lognormed_batch(x, eval_pos, eps=.0000001):
+ x = x.repeat(1, x.shape[-1] + 1, 1)
+ for b in range(x.shape[-1]):
+ logx = torch.log(x[:, b, b]+eps)
+ x[:, b, b] = (logx - logx[:eval_pos].mean(0))/logx[:eval_pos].std(0)
+ return x
+
+def _rank_transform(x_train, x):
+ assert len(x_train.shape) == len(x.shape) == 1
+ relative_to = torch.cat((torch.zeros_like(x_train[:1]),x_train.unique(sorted=True,), torch.ones_like(x_train[-1:])),-1)
+ higher_comparison = (relative_to < x[...,None]).sum(-1).clamp(min=1)
+ pos_inside_interval = (x - relative_to[higher_comparison-1])/(relative_to[higher_comparison] - relative_to[higher_comparison-1])
+ x_transformed = higher_comparison - 1 + pos_inside_interval
+ return x_transformed/(len(relative_to)-1.)
+
+def rank_transform(x_train, x):
+ assert x.shape[1] == x_train.shape[1], f"{x.shape=} and {x_train.shape=}"
+ # make sure everything is between 0 and 1
+ assert (x_train >= 0.).all() and (x_train <= 1.).all(), f"{x_train=}"
+ assert (x >= 0.).all() and (x <= 1.).all(), f"{x=}"
+ return_x = x.clone()
+ for feature_dim in range(x.shape[1]):
+ return_x[:, feature_dim] = _rank_transform(x_train[:, feature_dim], x[:, feature_dim])
+ return return_x
+
+
+
+def general_power_transform(x_train, x_apply, eps, less_safe=False):
+
+ # print('in function')
+ # print(x_train)
+ # print(x_apply)
+ # print('in function')
+
+ if eps > 0:
+ try:
+ pt = PowerTransformer(method='box-cox')
+ pt.fit(x_train.cpu()+eps)
+ x_out = torch.tensor(pt.transform(x_apply.cpu()+eps), dtype=x_apply.dtype, device=x_apply.device)
+ except Exception as e:
+ print(e)
+ x_out = x_apply - x_train.mean(0)
+ print(x_train)
+ print(x_out)
+ else:
+ pt = PowerTransformer(method='yeo-johnson')
+ if not less_safe and (x_train.std() > 1_000 or x_train.mean().abs() > 1_000):
+ x_apply = (x_apply - x_train.mean(0)) / x_train.std(0)
+ x_train = (x_train - x_train.mean(0)) / x_train.std(0)
+ # print('inputs are LAARGEe, normalizing them')
+ try:
+ pt.fit(x_train.cpu().double())
+ # except ValueError as e:
+ except Exception as e:
+ # print(x_train)
+ # print('caught this errrr', e)
+ if less_safe:
+ x_train = (x_train - x_train.mean(0)) / x_train.std(0)
+ x_apply = (x_apply - x_train.mean(0)) / x_train.std(0)
+ else:
+ x_train = x_train - x_train.mean(0)
+ x_apply = x_apply - x_train.mean(0)
+ # print(x_train)
+ pt.fit(x_train.cpu().double())
+ # print(x_train)
+ x_out = torch.tensor(pt.transform(x_apply.cpu()), dtype=x_apply.dtype, device=x_apply.device)
+ if torch.isnan(x_out).any() or torch.isinf(x_out).any():
+ print('WARNING: power transform failed')
+ print(f"{x_train=} and {x_apply=}")
+ x_out = x_apply - x_train.mean(0)
+ return x_out, pt
\ No newline at end of file
diff --git a/SpeedReducer.png b/SpeedReducer.png
new file mode 100644
index 0000000000000000000000000000000000000000..8ea8e54054900006357b8db30c62d0945e44f983
Binary files /dev/null and b/SpeedReducer.png differ
diff --git a/SpeedReducer_CEI_Avg_Obj.pt b/SpeedReducer_CEI_Avg_Obj.pt
new file mode 100644
index 0000000000000000000000000000000000000000..5c9dcb201981687b1563b9fad5fdef0160015d06
--- /dev/null
+++ b/SpeedReducer_CEI_Avg_Obj.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1567f1e9557cb6d701605a2ec74c6e294c42a85c88ddf3c0f33e307bf7f9a07f
+size 3684
diff --git a/SpeedReducer_CEI_Avg_Time.pt b/SpeedReducer_CEI_Avg_Time.pt
new file mode 100644
index 0000000000000000000000000000000000000000..b04fb01cf06319cc3ed70a1ba1cacd4f42387b59
--- /dev/null
+++ b/SpeedReducer_CEI_Avg_Time.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9cfa75441b15a3e1b8dbdc1e4a074e7a3682c41c9a85924793c67a41bec86acd
+size 3496
diff --git a/Test_formulation.png b/Test_formulation.png
new file mode 100644
index 0000000000000000000000000000000000000000..7fb1d44bf88e52e750a5065b68c8f55a696f0d72
Binary files /dev/null and b/Test_formulation.png differ
diff --git a/Test_formulation_default.png b/Test_formulation_default.png
new file mode 100644
index 0000000000000000000000000000000000000000..c97f6256dd5afc15a3aa2cf1985b4c74adbaefe5
Binary files /dev/null and b/Test_formulation_default.png differ
diff --git a/ThreeTruss.png b/ThreeTruss.png
new file mode 100644
index 0000000000000000000000000000000000000000..77438e7d5f2f7b09ac4d2877183890edef7de2f8
Binary files /dev/null and b/ThreeTruss.png differ
diff --git a/ThreeTruss_CEI_Avg_Obj.pt b/ThreeTruss_CEI_Avg_Obj.pt
new file mode 100644
index 0000000000000000000000000000000000000000..1562daf7371f61fd8c92577b1e27949d88f99067
--- /dev/null
+++ b/ThreeTruss_CEI_Avg_Obj.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b02d1c95ef3aee57fee8804a82119d9b68453e182184cf47970779742d059bed
+size 2844
diff --git a/ThreeTruss_CEI_Avg_Time.pt b/ThreeTruss_CEI_Avg_Time.pt
new file mode 100644
index 0000000000000000000000000000000000000000..6889f68a1f2ce98da90265771b6072562733df38
--- /dev/null
+++ b/ThreeTruss_CEI_Avg_Time.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7e9b30e0f99096ab84b8a545d2c1f24b80cd2d0bce1df6bc7f268b32c88a5b4f
+size 2912
diff --git a/WeldedBeam.png b/WeldedBeam.png
new file mode 100644
index 0000000000000000000000000000000000000000..e458a67ecddcc59fb5d005b4ed9b39b772883a4d
Binary files /dev/null and b/WeldedBeam.png differ
diff --git a/WeldedBeam_CEI_Avg_Obj.pt b/WeldedBeam_CEI_Avg_Obj.pt
new file mode 100644
index 0000000000000000000000000000000000000000..00edaa629933a62bf40e6abcfd742c2e2ee265f0
--- /dev/null
+++ b/WeldedBeam_CEI_Avg_Obj.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:efba0c05f0ac9803ee75caa3396983535bc3a104b47db2a3e463b1497ab5a93b
+size 3164
diff --git a/WeldedBeam_CEI_Avg_Time.pt b/WeldedBeam_CEI_Avg_Time.pt
new file mode 100644
index 0000000000000000000000000000000000000000..21f6588150984e57007e754d8c5c5f4aee6dc5ee
--- /dev/null
+++ b/WeldedBeam_CEI_Avg_Time.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:06225c2be0d11a0cb563f1eb525401d5f5536401694d7ed7e3f7179a1f51352b
+size 3552
diff --git a/__pycache__/Rosen_PFN4BO.cpython-310.pyc b/__pycache__/Rosen_PFN4BO.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0de793531938fc73e96a742359cb7a6d85ea8d67
Binary files /dev/null and b/__pycache__/Rosen_PFN4BO.cpython-310.pyc differ
diff --git a/final_models/Cyril_500features.pt b/final_models/Cyril_500features.pt
new file mode 100644
index 0000000000000000000000000000000000000000..546e21e5d710f7bd30906671c2fc820ecbf40aaf
--- /dev/null
+++ b/final_models/Cyril_500features.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:43218823860a5ca71657fd25c50bcc1209c3c570bcbb9df9ed2822bbb9f6f9c8
+size 239411934
diff --git a/final_models/Cyril_500features_800epoch_cpu.pt b/final_models/Cyril_500features_800epoch_cpu.pt
new file mode 100644
index 0000000000000000000000000000000000000000..a2138c0f2e6efc531b1e214c929db56ac9bfde53
--- /dev/null
+++ b/final_models/Cyril_500features_800epoch_cpu.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:25884174687cfbde831badc4f1d05e94f860711dc3a07f4dde09930860e63603
+size 239408346
diff --git a/final_models/Cyril_50features.pt b/final_models/Cyril_50features.pt
new file mode 100644
index 0000000000000000000000000000000000000000..51df20a16c2c6a314bb2624e60ec7d9fb30cdc8a
--- /dev/null
+++ b/final_models/Cyril_50features.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d5b680c4b72e72a33a21896885de7e8fba52c42612a6165a7cf60afede2e425d
+size 107333480
diff --git a/final_models/hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt b/final_models/hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt
new file mode 100644
index 0000000000000000000000000000000000000000..f9fcc34a790ac2e735e998380d1b526338a754d7
--- /dev/null
+++ b/final_models/hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ff2a4aa60feeca59e80f3b272d7b2ab521e1e82189469db494068de33dcaba17
+size 107378616
diff --git a/final_models/heboplus_500features_retrain_epoch800_cpu.pt b/final_models/heboplus_500features_retrain_epoch800_cpu.pt
new file mode 100644
index 0000000000000000000000000000000000000000..a2138c0f2e6efc531b1e214c929db56ac9bfde53
--- /dev/null
+++ b/final_models/heboplus_500features_retrain_epoch800_cpu.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:25884174687cfbde831badc4f1d05e94f860711dc3a07f4dde09930860e63603
+size 239408346
diff --git a/final_models/model_hebo_morebudget_9_unused_features_3.pt b/final_models/model_hebo_morebudget_9_unused_features_3.pt
new file mode 100644
index 0000000000000000000000000000000000000000..73639886ad326b8e70cd2b2ddb6141442a3b8a60
--- /dev/null
+++ b/final_models/model_hebo_morebudget_9_unused_features_3.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cc7f6f4b9b06e59987e42845b7b0d31ffa5b414b9eddfe14d88b25120e3cd4f8
+size 107262245
diff --git a/final_models/model_sampled_warp_simple_mlp_for_hpob_46.pt b/final_models/model_sampled_warp_simple_mlp_for_hpob_46.pt
new file mode 100644
index 0000000000000000000000000000000000000000..ee1d9c2412a5e49e06640daf60366e667b530868
--- /dev/null
+++ b/final_models/model_sampled_warp_simple_mlp_for_hpob_46.pt
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ebb2d4d7f419ca4617fdf85c663a69b3b0285fef91712e0dd69d5ab2d61754fd
+size 56761718
diff --git a/pfns4bo/.ipynb_checkpoints/__init__-checkpoint.py b/pfns4bo/.ipynb_checkpoints/__init__-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae03d9da8b56c67c031869ad84d136826541397a
--- /dev/null
+++ b/pfns4bo/.ipynb_checkpoints/__init__-checkpoint.py
@@ -0,0 +1,50 @@
+import os
+
+model_path = 'final_models'
+
+def prepare_models():
+ pfns4bo_dir = os.path.dirname(__file__)
+ model_names = ['hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt',
+ 'model_sampled_warp_simple_mlp_for_hpob_46.pt',
+ 'model_hebo_morebudget_9_unused_features_3.pt',]
+
+ for name in model_names:
+ weights_path = os.path.join(pfns4bo_dir, model_path, name)
+ compressed_weights_path = os.path.join(pfns4bo_dir, model_path, name + '.gz')
+ if not os.path.exists(weights_path):
+ if not os.path.exists(compressed_weights_path):
+ print("Downloading", os.path.abspath(compressed_weights_path))
+ import requests
+ url = f'https://github.com/automl/PFNs4BO/raw/main/pfns4bo/final_models/{name + ".gz"}'
+ r = requests.get(url, allow_redirects=True)
+ os.makedirs(os.path.dirname(compressed_weights_path), exist_ok=True)
+ with open(compressed_weights_path, 'wb') as f:
+ f.write(r.content)
+ if os.path.exists(compressed_weights_path):
+ print("Unzipping", name)
+ os.system(f"gzip -dk {compressed_weights_path}")
+ else:
+ print("Failed to find", compressed_weights_path)
+ print("Make sure you have an internet connection to download the model automatically..")
+ if os.path.exists(weights_path):
+ print("Successfully located model at", weights_path)
+
+
+model_dict = {
+ 'hebo_plus_userprior_model': os.path.join(os.path.dirname(__file__),model_path,
+ 'hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt'),
+ 'hebo_plus_model': os.path.join(os.path.dirname(__file__),model_path,
+ 'model_hebo_morebudget_9_unused_features_3.pt'),
+ 'bnn_model': os.path.join(os.path.dirname(__file__),model_path,'model_sampled_warp_simple_mlp_for_hpob_46.pt')
+}
+
+
+def __getattr__(name):
+ if name in model_dict:
+ if not os.path.exists(model_dict[name]):
+ print("Can't find", os.path.abspath(model_dict[name]), "thus unzipping/downloading models now.")
+ print("This might take a while..")
+ prepare_models()
+ return model_dict[name]
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
+
diff --git a/pfns4bo/.ipynb_checkpoints/bar_distribution-checkpoint.py b/pfns4bo/.ipynb_checkpoints/bar_distribution-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc846866c3bfedf45bb48c1b75af93d4e1670f2a
--- /dev/null
+++ b/pfns4bo/.ipynb_checkpoints/bar_distribution-checkpoint.py
@@ -0,0 +1,410 @@
+from .utils import print_once
+
+import torch
+from torch import nn
+
+
+class BarDistribution(nn.Module):
+ def __init__(self, borders: torch.Tensor, smoothing=.0, ignore_nan_targets=True): # here borders should start with min and end with max, where all values lie in (min,max) and are sorted
+ '''
+ :param borders:
+ :param smoothing:
+ :param append_mean_pred: Whether to predict the mean of the other positions as a last output in forward,
+ is enabled when additionally y has a sequence length 1 shorter than logits, i.e. len(logits) == 1 + len(y)
+ '''
+ super().__init__()
+ assert len(borders.shape) == 1
+ self.register_buffer('borders', borders)
+ self.register_buffer('smoothing', torch.tensor(smoothing))
+ self.register_buffer('bucket_widths', self.borders[1:] - self.borders[:-1])
+ full_width = self.bucket_widths.sum()
+
+ assert (1 - (full_width / (self.borders[-1] - self.borders[0]))).abs() < 1e-2, f'diff: {full_width - (self.borders[-1] - self.borders[0])} with {full_width} {self.borders[-1]} {self.borders[0]}'
+ assert (self.bucket_widths >= 0.0).all() , "Please provide sorted borders!" # This also allows size zero buckets
+ self.num_bars = len(borders) - 1
+ self.ignore_nan_targets = ignore_nan_targets
+ self.to(borders.device)
+
+ def __setstate__(self, state):
+ super().__setstate__(state)
+ self.__dict__.setdefault('append_mean_pred', False)
+
+ def map_to_bucket_idx(self, y):
+ target_sample = torch.searchsorted(self.borders, y) - 1
+ target_sample[y == self.borders[0]] = 0
+ target_sample[y == self.borders[-1]] = self.num_bars - 1
+ return target_sample
+
+ def ignore_init(self, y):
+ ignore_loss_mask = torch.isnan(y)
+ if ignore_loss_mask.any():
+ if not self.ignore_nan_targets: raise ValueError(f'Found NaN in target {y}')
+ print_once("A loss was ignored because there was nan target.")
+ y[ignore_loss_mask] = self.borders[0] # this is just a default value, it will be ignored anyway
+ return ignore_loss_mask
+
+ def compute_scaled_log_probs(self, logits):
+ # this is equivalent to log(p(y)) of the density p
+ bucket_log_probs = torch.log_softmax(logits, -1)
+ scaled_bucket_log_probs = bucket_log_probs - torch.log(self.bucket_widths)
+ return scaled_bucket_log_probs
+
+ def forward(self, logits, y, mean_prediction_logits=None): # gives the negative log density (the _loss_), y: T x B, logits: T x B x self.num_bars
+ y = y.clone().view(*logits.shape[:-1]) # no trailing one dimension
+ ignore_loss_mask = self.ignore_init(y)
+ target_sample = self.map_to_bucket_idx(y)
+ assert (target_sample >= 0).all() and (target_sample < self.num_bars).all(), f'y {y} not in support set for borders (min_y, max_y) {self.borders}'
+ assert logits.shape[-1] == self.num_bars, f'{logits.shape[-1]} vs {self.num_bars}'
+
+ scaled_bucket_log_probs = self.compute_scaled_log_probs(logits)
+ nll_loss = -scaled_bucket_log_probs.gather(-1,target_sample[..., None]).squeeze(-1) # T x B
+
+ if mean_prediction_logits is not None:
+ if not self.training:
+ print('Calculating loss incl mean prediction loss for nonmyopic BO.')
+ scaled_mean_log_probs = self.compute_scaled_log_probs(mean_prediction_logits)
+ nll_loss = torch.cat((nll_loss, self.mean_loss(logits, scaled_mean_log_probs)), 0)
+
+ smooth_loss = -scaled_bucket_log_probs.mean(dim=-1)
+ smoothing = self.smoothing if self.training else 0.
+ loss = (1. - smoothing) * nll_loss + smoothing * smooth_loss
+ loss[ignore_loss_mask] = 0.
+ return loss
+
+ def mean_loss(self, logits, scaled_mean_logits):
+ assert (len(logits.shape) == 3) and (len(scaled_mean_logits.shape) == 2), \
+ (len(logits.shape), len(scaled_mean_logits.shape))
+ means = self.mean(logits).detach() # T x B
+ target_mean = self.map_to_bucket_idx(means).clamp_(0, self.num_bars - 1) # T x B
+ return -scaled_mean_logits.gather(1, target_mean.T).mean(1).unsqueeze(0) # 1 x B
+
+ def mean(self, logits):
+ bucket_means = self.borders[:-1] + self.bucket_widths/2
+ p = torch.softmax(logits, -1)
+ return p @ bucket_means
+
+ def median(self, logits):
+ return self.icdf(logits, 0.5)
+
+ def icdf(self, logits, left_prob):
+ """
+ Implementation of the quantile function
+ :param logits: Tensor of any shape, with the last dimension being logits
+ :param left_prob: float: The probability mass to the left of the result.
+ :return: Position with `left_prob` probability weight to the left.
+ """
+ probs = logits.softmax(-1)
+ cumprobs = torch.cumsum(probs, -1)
+ idx = torch.searchsorted(cumprobs, left_prob * torch.ones(*cumprobs.shape[:-1], 1, device=logits.device))\
+ .squeeze(-1).clamp(0, cumprobs.shape[-1] - 1) # this might not do the right for outliers
+ cumprobs = torch.cat([torch.zeros(*cumprobs.shape[:-1], 1, device=logits.device), cumprobs], -1)
+
+ rest_prob = left_prob - cumprobs.gather(-1, idx[..., None]).squeeze(-1)
+ left_border = self.borders[idx]
+ right_border = self.borders[idx+1]
+ return left_border + (right_border - left_border) * rest_prob / probs.gather(-1, idx[..., None]).squeeze(-1)
+
+ def quantile(self, logits, center_prob=.682):
+ side_probs = (1.-center_prob)/2
+ return torch.stack((self.icdf(logits, side_probs), self.icdf(logits, 1.-side_probs)),-1)
+
+ def ucb(self, logits, best_f, rest_prob=(1-.682)/2, maximize=True):
+ """
+ UCB utility. Rest Prob is the amount of utility above (below) the confidence interval that is ignored.
+ Higher rest_prob is equivalent to lower beta in the standard GP-UCB formulation.
+ :param logits: Logits, as returned by the Transformer.
+ :param rest_prob: The amount of utility above (below) the confidence interval that is ignored.
+ The default is equivalent to using GP-UCB with `beta=1`.
+ To get the corresponding `beta`, where `beta` is from
+ the standard GP definition of UCB `ucb_utility = mean + beta * std`,
+ you can use this computation: `beta = math.sqrt(2)*torch.erfinv(torch.tensor(2*(1-rest_prob)-1))`.
+ :param maximize:
+ :return: utility
+ """
+ if maximize:
+ rest_prob = 1 - rest_prob
+ return self.icdf(logits, rest_prob)
+
+ def mode(self, logits):
+ mode_inds = logits.argmax(-1)
+ bucket_means = self.borders[:-1] + self.bucket_widths/2
+ return bucket_means[mode_inds]
+
+ def ei(self, logits, best_f, maximize=True): # logits: evaluation_points x batch x feature_dim
+ bucket_diffs = self.borders[1:] - self.borders[:-1]
+ assert maximize
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device)
+
+ best_f = best_f[..., None].repeat(*[1]*len(best_f.shape), logits.shape[-1])
+ clamped_best_f = best_f.clamp(self.borders[:-1], self.borders[1:])
+
+ #bucket_contributions = (best_f[...,None] < self.borders[:-1]).float() * bucket_means
+ # true bucket contributions
+ bucket_contributions = ((self.borders[1:]**2-clamped_best_f**2)/2 - best_f*(self.borders[1:] - clamped_best_f))/bucket_diffs
+
+ p = torch.softmax(logits, -1)
+ return torch.einsum("...b,...b->...", p, bucket_contributions)
+
+ def pi(self, logits, best_f, maximize=True):# logits: evaluation_points x batch x feature_dim
+ """
+ Acquisition Function: Probability of Improvement
+ :param logits: as returned by Transformer
+ :param best_f: best evaluation so far (the incumbent)
+ :param maximize: whether to maximize
+ :return: utility
+ """
+ assert maximize is True
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device)
+ p = torch.softmax(logits, -1)
+ border_widths = self.borders[1:] - self.borders[:-1]
+ factor = 1. - ((best_f[...,None] - self.borders[:-1]) / border_widths).clamp(0., 1.)
+ return (p * factor).sum(-1)
+
+
+ def mean_of_square(self, logits):
+ """
+ Computes E[x^2].
+ :param logits: Output of the model.
+ """
+ left_borders = self.borders[:-1]
+ right_borders = self.borders[1:]
+ bucket_mean_of_square = (left_borders.square() + right_borders.square() + left_borders*right_borders)/3.
+ p = torch.softmax(logits, -1)
+ return p @ bucket_mean_of_square
+
+ def variance(self, logits):
+ return self.mean_of_square(logits) - self.mean(logits).square()
+
+ def pi(self, logits, best_f, maximize=True):# logits: evaluation_points x batch x feature_dim
+ """
+ Acquisition Function: Probability of Improvement
+ :param logits: as returned by Transformer
+ :param best_f: best evaluation so far (the incumbent)
+ :param maximize: whether to maximize
+ :return: utility
+ """
+ assert maximize is True
+ p = torch.softmax(logits, -1)
+ border_widths = self.borders[1:] - self.borders[:-1]
+ factor = 1. - ((best_f - self.borders[:-1]) / border_widths).clamp(0., 1.)
+ return (p * factor).sum(-1)
+
+
+ def mean_of_square(self, logits):
+ """
+ Computes E[x^2].
+ :param logits: Output of the model.
+ """
+ left_borders = self.borders[:-1]
+ right_borders = self.borders[1:]
+ bucket_mean_of_square = (left_borders.square() + right_borders.square() + left_borders*right_borders)/3.
+ p = torch.softmax(logits, -1)
+ return p @ bucket_mean_of_square
+
+ def variance(self, logits):
+ return self.mean_of_square(logits) - self.mean(logits).square()
+
+
+class FullSupportBarDistribution(BarDistribution):
+ @staticmethod
+ def halfnormal_with_p_weight_before(range_max,p=.5):
+ s = range_max / torch.distributions.HalfNormal(torch.tensor(1.)).icdf(torch.tensor(p))
+ return torch.distributions.HalfNormal(s)
+
+
+ def forward(self, logits, y, mean_prediction_logits=None): # gives the negative log density (the _loss_), y: T x B, logits: T x B x self.num_bars
+ assert self.num_bars > 1
+ y = y.clone().view(len(y),-1) # no trailing one dimension
+ ignore_loss_mask = self.ignore_init(y) # alters y
+ target_sample = self.map_to_bucket_idx(y) # shape: T x B (same as y)
+ target_sample.clamp_(0, self.num_bars - 1)
+
+ assert logits.shape[-1] == self.num_bars, f'{logits.shape[-1]} vs {self.num_bars}'
+ assert (target_sample >= 0).all() and (target_sample < self.num_bars).all(), \
+ f'y {y} not in support set for borders (min_y, max_y) {self.borders}'
+ assert logits.shape[-1] == self.num_bars, f'{logits.shape[-1]} vs {self.num_bars}'
+ # ignore all position with nan values
+
+
+ scaled_bucket_log_probs = self.compute_scaled_log_probs(logits)
+
+ assert len(scaled_bucket_log_probs) == len(target_sample), (len(scaled_bucket_log_probs), len(target_sample))
+ log_probs = scaled_bucket_log_probs.gather(-1, target_sample.unsqueeze(-1)).squeeze(-1)
+
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]), self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+
+
+ log_probs[target_sample == 0] += side_normals[0].log_prob((self.borders[1]-y[target_sample == 0]).clamp(min=.00000001)) + torch.log(self.bucket_widths[0])
+ log_probs[target_sample == self.num_bars-1] += side_normals[1].log_prob((y[target_sample == self.num_bars-1]-self.borders[-2]).clamp(min=.00000001)) + torch.log(self.bucket_widths[-1])
+
+ nll_loss = -log_probs
+
+ if mean_prediction_logits is not None:
+ assert not ignore_loss_mask.any(), "Ignoring examples is not implemented with mean pred."
+ if not self.training:
+ print('Calculating loss incl mean prediction loss for nonmyopic BO.')
+ if not torch.is_grad_enabled():
+ print("Warning: loss is not correct in absolute terms, only the gradient is right, when using `append_mean_pred`.")
+ scaled_mean_log_probs = self.compute_scaled_log_probs(mean_prediction_logits)
+ nll_loss = torch.cat((nll_loss, self.mean_loss(logits, scaled_mean_log_probs)), 0)
+ #ignore_loss_mask = torch.zeros_like(nll_loss, dtype=torch.bool)
+
+ if self.smoothing:
+ smooth_loss = -scaled_bucket_log_probs.mean(dim=-1)
+ smoothing = self.smoothing if self.training else 0.
+ nll_loss = (1. - smoothing) * nll_loss + smoothing * smooth_loss
+
+ if ignore_loss_mask.any():
+ nll_loss[ignore_loss_mask] = 0.
+
+ return nll_loss
+
+ def mean(self, logits):
+ bucket_means = self.borders[:-1] + self.bucket_widths / 2
+ p = torch.softmax(logits, -1)
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ bucket_means[0] = -side_normals[0].mean + self.borders[1]
+ bucket_means[-1] = side_normals[1].mean + self.borders[-2]
+ return p @ bucket_means.to(logits.device)
+
+ def mean_of_square(self, logits):
+ """
+ Computes E[x^2].
+ :param logits: Output of the model.
+ """
+ left_borders = self.borders[:-1]
+ right_borders = self.borders[1:]
+ bucket_mean_of_square = (left_borders.square() + right_borders.square() + left_borders*right_borders)/3.
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ bucket_mean_of_square[0] = side_normals[0].variance + (-side_normals[0].mean + self.borders[1]).square()
+ bucket_mean_of_square[-1] = side_normals[1].variance + (side_normals[1].variance + self.borders[-2]).square()
+ p = torch.softmax(logits, -1)
+ return p @ bucket_mean_of_square
+
+ def pi(self, logits, best_f, maximize=True):# logits: evaluation_points x batch x feature_dim
+ """
+ Acquisition Function: Probability of Improvement
+ :param logits: as returned by Transformer (evaluation_points x batch x feature_dim)
+ :param best_f: best evaluation so far (the incumbent)
+ :param maximize: whether to maximize
+ :return: utility
+ """
+ assert maximize is True
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device) # evaluation_points x batch
+ assert best_f.shape == logits[...,0].shape, f"best_f.shape: {best_f.shape}, logits.shape: {logits.shape}"
+ p = torch.softmax(logits, -1) # evaluation_points x batch
+ border_widths = self.borders[1:] - self.borders[:-1]
+ factor = 1. - ((best_f[...,None] - self.borders[:-1]) / border_widths).clamp(0., 1.) # evaluation_points x batch x num_bars
+
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ position_in_side_normals = (-(best_f - self.borders[1]).clamp(max=0.), (best_f - self.borders[-2]).clamp(min=0.)) # evaluation_points x batch
+ factor[...,0] = 0.
+ factor[...,0][position_in_side_normals[0] > 0.] = side_normals[0].cdf(position_in_side_normals[0][position_in_side_normals[0] > 0.])
+ factor[...,-1] = 1.
+ factor[...,-1][position_in_side_normals[1] > 0.] = 1. - side_normals[1].cdf(position_in_side_normals[1][position_in_side_normals[1] > 0.])
+ return (p * factor).sum(-1)
+
+
+ def ei_for_halfnormal(self, scale, best_f, maximize=True):
+ """
+ This is the EI for a standard normal distribution with mean 0 and variance `scale` times 2.
+ Which is the same as the half normal EI.
+ I tested this with MC approximation:
+ ei_for_halfnormal = lambda scale, best_f: (torch.distributions.HalfNormal(torch.tensor(scale)).sample((10_000_000,))- best_f ).clamp(min=0.).mean()
+ print([(ei_for_halfnormal(scale,best_f), FullSupportBarDistribution().ei_for_halfnormal(scale,best_f)) for scale in [0.1,1.,10.] for best_f in [.1,10.,4.]])
+ :param scale:
+ :param best_f:
+ :param maximize:
+ :return:
+ """
+ assert maximize
+ mean = torch.tensor(0.)
+ u = (mean - best_f) / scale
+ normal = torch.distributions.Normal(torch.zeros_like(u), torch.ones_like(u))
+ try:
+ ucdf = normal.cdf(u)
+ except ValueError:
+ print(f"u: {u}, best_f: {best_f}, scale: {scale}")
+ raise
+ updf = torch.exp(normal.log_prob(u))
+ normal_ei = scale * (updf + u * ucdf)
+ return 2*normal_ei
+
+ def ei(self, logits, best_f, maximize=True): # logits: evaluation_points x batch x feature_dim
+ if torch.isnan(logits).any():
+ raise ValueError(f"logits contains NaNs: {logits}")
+ bucket_diffs = self.borders[1:] - self.borders[:-1]
+ assert maximize
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device)
+ assert best_f.shape == logits[...,0].shape, f"best_f.shape: {best_f.shape}, logits.shape: {logits.shape}"
+
+
+ best_f_per_logit = best_f[..., None].repeat(*[1]*len(best_f.shape), logits.shape[-1])
+ clamped_best_f = best_f_per_logit.clamp(self.borders[:-1], self.borders[1:])
+
+ # true bucket contributions
+ bucket_contributions = ((self.borders[1:]**2-clamped_best_f**2)/2 - best_f_per_logit*(self.borders[1:] - clamped_best_f))/bucket_diffs
+
+ # extra stuff for continuous
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ position_in_side_normals = (-(best_f - self.borders[1]).clamp(max=0.),
+ (best_f - self.borders[-2]).clamp(min=0.)) # evaluation_points x batch
+
+ bucket_contributions[...,-1] = self.ei_for_halfnormal(side_normals[1].scale, position_in_side_normals[1])
+
+ bucket_contributions[...,0] = self.ei_for_halfnormal(side_normals[0].scale, torch.zeros_like(position_in_side_normals[0])) \
+ - self.ei_for_halfnormal(side_normals[0].scale, position_in_side_normals[0])
+
+ p = torch.softmax(logits, -1)
+ return torch.einsum("...b,...b->...", p, bucket_contributions)
+
+
+def get_bucket_limits(num_outputs:int, full_range:tuple=None, ys:torch.Tensor=None, verbose:bool=False):
+ assert (ys is None) != (full_range is None), 'Either full_range or ys must be passed.'
+
+ if ys is not None:
+ ys = ys.flatten()
+ ys = ys[~torch.isnan(ys)]
+ if len(ys) % num_outputs: ys = ys[:-(len(ys) % num_outputs)]
+ print(f'Using {len(ys)} y evals to estimate {num_outputs} buckets. Cut off the last {len(ys) % num_outputs} ys.')
+ ys_per_bucket = len(ys) // num_outputs
+ if full_range is None:
+ full_range = (ys.min(), ys.max())
+ else:
+ assert full_range[0] <= ys.min() and full_range[1] >= ys.max(), f'full_range {full_range} not in range of ys {ys.min(), ys.max()}'
+ full_range = torch.tensor(full_range)
+ ys_sorted, ys_order = ys.sort(0)
+ bucket_limits = (ys_sorted[ys_per_bucket-1::ys_per_bucket][:-1]+ys_sorted[ys_per_bucket::ys_per_bucket])/2
+ if verbose:
+ print(f'Using {len(ys)} y evals to estimate {num_outputs} buckets. Cut off the last {len(ys) % num_outputs} ys.')
+ print(full_range)
+ bucket_limits = torch.cat([full_range[0].unsqueeze(0), bucket_limits, full_range[1].unsqueeze(0)],0)
+
+ else:
+ class_width = (full_range[1] - full_range[0]) / num_outputs
+ bucket_limits = torch.cat([full_range[0] + torch.arange(num_outputs).float()*class_width, torch.tensor(full_range[1]).unsqueeze(0)], 0)
+
+ assert len(bucket_limits) - 1 == num_outputs, f'len(bucket_limits) - 1 == {len(bucket_limits) - 1} != {num_outputs} == num_outputs'
+ assert full_range[0] == bucket_limits[0], f'{full_range[0]} != {bucket_limits[0]}'
+ assert full_range[-1] == bucket_limits[-1], f'{full_range[-1]} != {bucket_limits[-1]}'
+
+ return bucket_limits
+
+
+def get_custom_bar_dist(borders, criterion):
+ # Tested that a bar_dist with borders 0.54 (-> softplus 1.0) yields the same bar distribution as the passed one.
+ borders_ = torch.nn.functional.softplus(borders) + 0.001
+ borders_ = (torch.cumsum(torch.cat([criterion.borders[0:1], criterion.bucket_widths]) * borders_, 0))
+ criterion_ = criterion.__class__(borders=borders_, handle_nans=criterion.handle_nans)
+ return criterion_
+
+
+
diff --git a/pfns4bo/.ipynb_checkpoints/lost_functions-checkpoint.py b/pfns4bo/.ipynb_checkpoints/lost_functions-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..091a8fc30930299e0ae37baab8dd3688c9c7f692
--- /dev/null
+++ b/pfns4bo/.ipynb_checkpoints/lost_functions-checkpoint.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python3
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+r"""
+A converter that simplifies using numpy-based optimizers with generic torch
+`nn.Module` classes. This enables using a `scipy.optim.minimize` optimizer
+for optimizing module parameters.
+"""
+
+from __future__ import annotations
+
+from collections import OrderedDict
+from math import inf
+from numbers import Number
+from typing import Dict, List, Optional, Set, Tuple
+from warnings import warn
+
+import numpy as np
+import torch
+from botorch.optim.utils import (
+ _get_extra_mll_args,
+ _handle_numerical_errors,
+ get_name_filter,
+ get_parameters_and_bounds,
+ TorchAttr,
+)
+from gpytorch.mlls import MarginalLogLikelihood
+from torch.nn import Module
+
+
+def module_to_array(
+ module: Module,
+ bounds: Optional[Dict[str, Tuple[Optional[float], Optional[float]]]] = None,
+ exclude: Optional[Set[str]] = None,
+) -> Tuple[np.ndarray, Dict[str, TorchAttr], Optional[np.ndarray]]:
+ r"""Extract named parameters from a module into a numpy array.
+
+ Only extracts parameters with requires_grad, since it is meant for optimizing.
+
+ Args:
+ module: A module with parameters. May specify parameter constraints in
+ a `named_parameters_and_constraints` method.
+ bounds: A dictionary mapping parameter names t lower and upper bounds.
+ of lower and upper bounds. Bounds specified here take precedence
+ over bounds on the same parameters specified in the constraints
+ registered with the module.
+ exclude: A list of parameter names that are to be excluded from extraction.
+
+ Returns:
+ 3-element tuple containing
+ - The parameter values as a numpy array.
+ - An ordered dictionary with the name and tensor attributes of each
+ parameter.
+ - A `2 x n_params` numpy array with lower and upper bounds if at least
+ one constraint is finite, and None otherwise.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ """
+ warn(
+ "`module_to_array` is marked for deprecation, consider using "
+ "`get_parameters_and_bounds`, `get_parameters_as_ndarray_1d`, or "
+ "`get_bounds_as_ndarray` instead.",
+ DeprecationWarning,
+ )
+ param_dict, bounds_dict = get_parameters_and_bounds(
+ module=module,
+ name_filter=None if exclude is None else get_name_filter(exclude),
+ requires_grad=True,
+ )
+ if bounds is not None:
+ bounds_dict.update(bounds)
+
+ # Record tensor metadata and read parameter values to the tape
+ param_tape: List[Number] = []
+ property_dict = OrderedDict()
+ with torch.no_grad():
+ for name, param in param_dict.items():
+ property_dict[name] = TorchAttr(param.shape, param.dtype, param.device)
+ param_tape.extend(param.view(-1).cpu().double().tolist())
+
+ # Extract lower and upper bounds
+ start = 0
+ bounds_np = None
+ params_np = np.asarray(param_tape)
+ for name, param in param_dict.items():
+ numel = param.numel()
+ if name in bounds_dict:
+ for row, bound in enumerate(bounds_dict[name]):
+ if bound is None:
+ continue
+
+ if torch.is_tensor(bound):
+ if (bound == (2 * row - 1) * inf).all():
+ continue
+ bound = bound.detach().cpu()
+
+ elif bound == (2 * row - 1) * inf:
+ continue
+
+ if bounds_np is None:
+ bounds_np = np.full((2, len(params_np)), ((-inf,), (inf,)))
+
+ bounds_np[row, start : start + numel] = bound
+ start += numel
+
+ return params_np, property_dict, bounds_np
+
+
+
+
+def set_params_with_array(
+ module: Module, x: np.ndarray, property_dict: Dict[str, TorchAttr]
+) -> Module:
+ r"""Set module parameters with values from numpy array.
+
+ Args:
+ module: Module with parameters to be set
+ x: Numpy array with parameter values
+ property_dict: Dictionary of parameter names and torch attributes as
+ returned by module_to_array.
+
+ Returns:
+ Module: module with parameters updated in-place.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ >>> parameter_array += 0.1 # perturb parameters (for example only)
+ >>> mll = set_params_with_array(mll, parameter_array, property_dict)
+ """
+ warn(
+ "`_set_params_with_array` is marked for deprecation, consider using "
+ "`set_parameters_from_ndarray_1d` instead.",
+ DeprecationWarning,
+ )
+ param_dict = OrderedDict(module.named_parameters())
+ start_idx = 0
+ for p_name, attrs in property_dict.items():
+ # Construct the new tensor
+ if len(attrs.shape) == 0: # deal with scalar tensors
+ end_idx = start_idx + 1
+ new_data = torch.tensor(
+ x[start_idx], dtype=attrs.dtype, device=attrs.device
+ )
+ else:
+ end_idx = start_idx + np.prod(attrs.shape)
+ new_data = torch.tensor(
+ x[start_idx:end_idx], dtype=attrs.dtype, device=attrs.device
+ ).view(*attrs.shape)
+ start_idx = end_idx
+ # Update corresponding parameter in-place. Disable autograd to update.
+ param_dict[p_name].requires_grad_(False)
+ param_dict[p_name].copy_(new_data)
+ param_dict[p_name].requires_grad_(True)
+ return module
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pfns4bo/.ipynb_checkpoints/transformer-checkpoint.py b/pfns4bo/.ipynb_checkpoints/transformer-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..594b64793c5556567d53336dd0dfd40bb6ae00ed
--- /dev/null
+++ b/pfns4bo/.ipynb_checkpoints/transformer-checkpoint.py
@@ -0,0 +1,327 @@
+import math
+from typing import Optional
+
+import torch
+import torch.nn as nn
+from torch import Tensor
+from torch.nn import Module, TransformerEncoder
+
+from .layer import TransformerEncoderLayer, _get_activation_fn
+from .utils import SeqBN, bool_mask_to_att_mask
+
+
+
+class TransformerModel(nn.Module):
+ def __init__(self, encoder, ninp, nhead, nhid, nlayers, dropout=0.0, style_encoder=None, y_encoder=None,
+ pos_encoder=None, decoder_dict=None, input_normalization=False, init_method=None, pre_norm=False,
+ activation='gelu', recompute_attn=False, num_global_att_tokens=0, full_attention=False,
+ all_layers_same_init=False, efficient_eval_masking=True, decoder_once_dict=None, return_all_outputs=False,
+ save_trainingset_representations=False):
+ super().__init__()
+ self.model_type = 'Transformer'
+ encoder_layer_creator = lambda: TransformerEncoderLayer(ninp, nhead, nhid, dropout, activation=activation,
+ pre_norm=pre_norm, recompute_attn=recompute_attn,
+ save_trainingset_representations=save_trainingset_representations)
+ self.transformer_encoder = TransformerEncoder(encoder_layer_creator(), nlayers)\
+ if all_layers_same_init else TransformerEncoderDiffInit(encoder_layer_creator, nlayers)
+ self.ninp = ninp
+ self.encoder = encoder
+ self.y_encoder = y_encoder
+ self.pos_encoder = pos_encoder
+ self.return_all_outputs = return_all_outputs
+
+ def make_decoder_dict(decoder_description_dict):
+ if decoder_description_dict is None or len(decoder_description_dict) == 0:
+ return None
+ initialized_decoder_dict = {}
+ for decoder_key in decoder_description_dict:
+ decoder_model, decoder_n_out = decoder_description_dict[decoder_key]
+ if decoder_model is None:
+ initialized_decoder_dict[decoder_key] = nn.Sequential(nn.Linear(ninp, nhid), nn.GELU(), nn.Linear(nhid, decoder_n_out))
+ else:
+ initialized_decoder_dict[decoder_key] = decoder_model(ninp, nhid, decoder_n_out)
+ print('Initialized decoder for', decoder_key, 'with', decoder_description_dict[decoder_key], ' and nout', decoder_n_out)
+ return torch.nn.ModuleDict(initialized_decoder_dict)
+
+ self.decoder_dict = make_decoder_dict(decoder_dict)
+ self.decoder_dict_once = make_decoder_dict(decoder_once_dict)
+
+ # N(0,1) is the initialization as the default of nn.Embedding
+ self.decoder_dict_once_embeddings = torch.nn.Parameter(torch.randn((len(self.decoder_dict_once), 1, ninp))) if self.decoder_dict_once is not None else None
+ #nn.Embedding(len(self.decoder_dict.keys()), nhid)
+ self.input_ln = SeqBN(ninp) if input_normalization else None
+ self.style_encoder = style_encoder
+ self.init_method = init_method
+ if num_global_att_tokens is not None:
+ assert not full_attention
+ self.global_att_embeddings = nn.Embedding(num_global_att_tokens, ninp) if num_global_att_tokens else None
+ self.full_attention = full_attention
+ self.efficient_eval_masking = efficient_eval_masking
+
+ self.nhid = nhid
+
+ self.init_weights()
+
+ def __setstate__(self, state):
+ super().__setstate__(state)
+ self.__dict__.setdefault('efficient_eval_masking', False)
+ if not hasattr(self, 'decoder_dict_once'):
+ self.__dict__.setdefault('decoder_dict_once', None)
+ if hasattr(self, 'decoder') and not hasattr(self, 'decoder_dict'):
+ self.add_module('decoder_dict', nn.ModuleDict({'standard': self.decoder}))
+ self.__dict__.setdefault('return_all_outputs', False)
+
+ def add_approximate_false(module):
+ if isinstance(module, nn.GELU):
+ module.__dict__.setdefault('approximate', 'none')
+
+ self.apply(add_approximate_false)
+
+ @staticmethod
+ def generate_square_subsequent_mask(sz):
+ mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_D_q_matrix(sz, query_size):
+ train_size = sz-query_size
+ mask = torch.zeros(sz,sz) == 0
+ mask[:,train_size:].zero_()
+ mask |= torch.eye(sz) == 1
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_global_att_query_matrix(num_global_att_tokens, seq_len, num_query_tokens):
+ train_size = seq_len + num_global_att_tokens - num_query_tokens
+ sz = seq_len + num_global_att_tokens
+ mask = torch.zeros(num_query_tokens, sz) == 0
+ mask[:,train_size:].zero_()
+ mask[:,train_size:] |= torch.eye(num_query_tokens) == 1
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_global_att_trainset_matrix(num_global_att_tokens, seq_len, num_query_tokens):
+ train_size = seq_len + num_global_att_tokens - num_query_tokens
+ trainset_size = seq_len - num_query_tokens
+ mask = torch.zeros(trainset_size, num_global_att_tokens) == 0
+ #mask[:,num_global_att_tokens:].zero_()
+ #mask[:,num_global_att_tokens:] |= torch.eye(trainset_size) == 1
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_global_att_globaltokens_matrix(num_global_att_tokens, seq_len, num_query_tokens):
+ mask = torch.zeros(num_global_att_tokens, num_global_att_tokens+seq_len-num_query_tokens) == 0
+ return bool_mask_to_att_mask(mask)
+
+ def init_weights(self):
+ initrange = 1.
+ # if isinstance(self.encoder,EmbeddingEncoder):
+ # self.encoder.weight.data.uniform_(-initrange, initrange)
+ # self.decoder.bias.data.zero_()
+ # self.decoder.weight.data.uniform_(-initrange, initrange)
+ if self.init_method is not None:
+ self.apply(self.init_method)
+ for layer in self.transformer_encoder.layers:
+ nn.init.zeros_(layer.linear2.weight)
+ nn.init.zeros_(layer.linear2.bias)
+ attns = layer.self_attn if isinstance(layer.self_attn, nn.ModuleList) else [layer.self_attn]
+ for attn in attns:
+ nn.init.zeros_(attn.out_proj.weight)
+ nn.init.zeros_(attn.out_proj.bias)
+
+ def forward(self, *args, **kwargs):
+ """
+ This will perform a forward-pass (possibly recording gradients) of the model.
+ We have multiple interfaces we support with this model:
+
+ model(train_x, train_y, test_x, src_mask=None, style=None, only_return_standard_out=True)
+ model((x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ model((style,x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ """
+ if len(args) == 3:
+ # case model(train_x, train_y, test_x, src_mask=None, style=None, only_return_standard_out=True)
+ assert all(kwarg in {'src_mask', 'style', 'only_return_standard_out'} for kwarg in kwargs.keys()), \
+ f"Unrecognized keyword argument in kwargs: {set(kwargs.keys()) - {'src_mask', 'style', 'only_return_standard_out'}}"
+ x = args[0]
+ if args[2] is not None:
+ x = torch.cat((x, args[2]), dim=0)
+ style = kwargs.pop('style', None)
+ return self._forward((style, x, args[1]), single_eval_pos=len(args[0]), **kwargs)
+ elif len(args) == 1 and isinstance(args, tuple):
+ # case model((x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ # case model((style,x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ assert all(kwarg in {'src_mask', 'single_eval_pos', 'only_return_standard_out'} for kwarg in kwargs.keys()), \
+ f"Unrecognized keyword argument in kwargs: {set(kwargs.keys()) - {'src_mask', 'single_eval_pos', 'only_return_standard_out'}}"
+ return self._forward(*args, **kwargs)
+
+ def _forward(self, src, src_mask=None, single_eval_pos=None, only_return_standard_out=True):
+ assert isinstance(src, tuple), 'inputs (src) have to be given as (x,y) or (style,x,y) tuple'
+
+ if len(src) == 2: # (x,y) and no style
+ src = (None,) + src
+
+ style_src, x_src, y_src = src
+
+ if single_eval_pos is None:
+ single_eval_pos = x_src.shape[0]
+
+
+ x_src = self.encoder(x_src)
+
+ if self.decoder_dict_once is not None:
+ x_src = torch.cat([x_src, self.decoder_dict_once_embeddings.repeat(1, x_src.shape[1], 1)], dim=0)
+
+ y_src = self.y_encoder(y_src.unsqueeze(-1) if len(y_src.shape) < len(x_src.shape) else y_src) if y_src is not None else None
+ if self.style_encoder:
+ assert style_src is not None, 'style_src must be given if style_encoder is used'
+ style_src = self.style_encoder(style_src).unsqueeze(0)
+ else:
+ style_src = torch.tensor([], device=x_src.device)
+ global_src = torch.tensor([], device=x_src.device) if self.global_att_embeddings is None else \
+ self.global_att_embeddings.weight.unsqueeze(1).repeat(1, x_src.shape[1], 1)
+
+ if src_mask is not None:
+ assert self.global_att_embeddings is None or isinstance(src_mask, tuple)
+
+ if src_mask is None:
+ if self.global_att_embeddings is None:
+ full_len = len(x_src) + len(style_src)
+ if self.full_attention:
+ src_mask = bool_mask_to_att_mask(torch.ones((full_len, full_len), dtype=torch.bool)).to(x_src.device)
+ elif self.efficient_eval_masking:
+ src_mask = single_eval_pos + len(style_src)
+ else:
+ src_mask = self.generate_D_q_matrix(full_len, len(x_src) - single_eval_pos).to(x_src.device)
+ else:
+ src_mask_args = (self.global_att_embeddings.num_embeddings,
+ len(x_src) + len(style_src),
+ len(x_src) + len(style_src) - single_eval_pos)
+ src_mask = (self.generate_global_att_globaltokens_matrix(*src_mask_args).to(x_src.device),
+ self.generate_global_att_trainset_matrix(*src_mask_args).to(x_src.device),
+ self.generate_global_att_query_matrix(*src_mask_args).to(x_src.device))
+
+ train_x = x_src[:single_eval_pos]
+ if y_src is not None:
+ train_x = train_x + y_src[:single_eval_pos]
+ src = torch.cat([global_src, style_src, train_x, x_src[single_eval_pos:]], 0)
+
+ if self.input_ln is not None:
+ src = self.input_ln(src)
+
+ if self.pos_encoder is not None:
+ src = self.pos_encoder(src)
+
+
+ output = self.transformer_encoder(src, src_mask)
+
+ num_prefix_positions = len(style_src)+(self.global_att_embeddings.num_embeddings if self.global_att_embeddings else 0)
+ if self.return_all_outputs:
+ out_range_start = num_prefix_positions
+ else:
+ out_range_start = single_eval_pos + num_prefix_positions
+
+ # In the line below, we use the indexing feature, that we have `x[i:None] == x[i:]`
+ out_range_end = -len(self.decoder_dict_once_embeddings) if self.decoder_dict_once is not None else None
+
+ # take care the output once are counted from the end
+ output_once = {k: v(output[-(i+1)]) for i, (k, v) in enumerate(self.decoder_dict_once.items())}\
+ if self.decoder_dict_once is not None else {}
+
+ output = {k: v(output[out_range_start:out_range_end]) for k,v in self.decoder_dict.items()}\
+ if self.decoder_dict is not None else {}
+
+ if only_return_standard_out:
+ return output['standard']
+
+ if output_once:
+ return output, output_once
+ return output
+
+ @torch.no_grad()
+ def init_from_small_model(self, small_model):
+ assert isinstance(self.decoder, nn.Linear) and isinstance(self.encoder, (nn.Linear, nn.Sequential)) \
+ and isinstance(self.y_encoder, (nn.Linear, nn.Sequential))
+
+ def set_encoder_weights(my_encoder, small_model_encoder):
+ my_encoder_linear, small_encoder_linear = (my_encoder, small_model_encoder) \
+ if isinstance(my_encoder, nn.Linear) else (my_encoder[-1], small_model_encoder[-1])
+ small_in_dim = small_encoder_linear.out_features
+ my_encoder_linear.weight.zero_()
+ my_encoder_linear.bias.zero_()
+ my_encoder_linear.weight[:small_in_dim] = small_encoder_linear.weight
+ my_encoder_linear.bias[:small_in_dim] = small_encoder_linear.bias
+
+ set_encoder_weights(self.encoder, small_model.encoder)
+ set_encoder_weights(self.y_encoder, small_model.y_encoder)
+
+ small_in_dim = small_model.decoder.in_features
+
+ self.decoder.weight[:, :small_in_dim] = small_model.decoder.weight
+ self.decoder.bias = small_model.decoder.bias
+
+ for my_layer, small_layer in zip(self.transformer_encoder.layers, small_model.transformer_encoder.layers):
+ small_hid_dim = small_layer.linear1.out_features
+ my_in_dim = my_layer.linear1.in_features
+
+ # packed along q,k,v order in first dim
+ my_in_proj_w = my_layer.self_attn.in_proj_weight
+ small_in_proj_w = small_layer.self_attn.in_proj_weight
+
+ my_in_proj_w.view(3, my_in_dim, my_in_dim)[:, :small_in_dim, :small_in_dim] = small_in_proj_w.view(3,
+ small_in_dim,
+ small_in_dim)
+ my_layer.self_attn.in_proj_bias.view(3, my_in_dim)[:,
+ :small_in_dim] = small_layer.self_attn.in_proj_bias.view(3, small_in_dim)
+
+ my_layer.self_attn.out_proj.weight[:small_in_dim, :small_in_dim] = small_layer.self_attn.out_proj.weight
+ my_layer.self_attn.out_proj.bias[:small_in_dim] = small_layer.self_attn.out_proj.bias
+
+ my_layer.linear1.weight[:small_hid_dim, :small_in_dim] = small_layer.linear1.weight
+ my_layer.linear1.bias[:small_hid_dim] = small_layer.linear1.bias
+
+ my_layer.linear2.weight[:small_in_dim, :small_hid_dim] = small_layer.linear2.weight
+ my_layer.linear2.bias[:small_in_dim] = small_layer.linear2.bias
+
+ my_layer.norm1.weight[:small_in_dim] = math.sqrt(small_in_dim / my_in_dim) * small_layer.norm1.weight
+ my_layer.norm2.weight[:small_in_dim] = math.sqrt(small_in_dim / my_in_dim) * small_layer.norm2.weight
+
+ my_layer.norm1.bias[:small_in_dim] = small_layer.norm1.bias
+ my_layer.norm2.bias[:small_in_dim] = small_layer.norm2.bias
+
+
+class TransformerEncoderDiffInit(Module):
+ r"""TransformerEncoder is a stack of N encoder layers
+
+ Args:
+ encoder_layer_creator: a function generating objects of TransformerEncoderLayer class without args (required).
+ num_layers: the number of sub-encoder-layers in the encoder (required).
+ norm: the layer normalization component (optional).
+ """
+ __constants__ = ['norm']
+
+ def __init__(self, encoder_layer_creator, num_layers, norm=None):
+ super().__init__()
+ self.layers = nn.ModuleList([encoder_layer_creator() for _ in range(num_layers)])
+ self.num_layers = num_layers
+ self.norm = norm
+
+ def forward(self, src: Tensor, mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None) -> Tensor:
+ r"""Pass the input through the encoder layers in turn.
+
+ Args:
+ src: the sequence to the encoder (required).
+ mask: the mask for the src sequence (optional).
+ src_key_padding_mask: the mask for the src keys per batch (optional).
+
+ Shape:
+ see the docs in Transformer class.
+ """
+ output = src
+
+ for mod in self.layers:
+ output = mod(output, src_mask=mask, src_key_padding_mask=src_key_padding_mask)
+
+ if self.norm is not None:
+ output = self.norm(output)
+
+ return output
diff --git a/pfns4bo/__init__.py b/pfns4bo/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae03d9da8b56c67c031869ad84d136826541397a
--- /dev/null
+++ b/pfns4bo/__init__.py
@@ -0,0 +1,50 @@
+import os
+
+model_path = 'final_models'
+
+def prepare_models():
+ pfns4bo_dir = os.path.dirname(__file__)
+ model_names = ['hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt',
+ 'model_sampled_warp_simple_mlp_for_hpob_46.pt',
+ 'model_hebo_morebudget_9_unused_features_3.pt',]
+
+ for name in model_names:
+ weights_path = os.path.join(pfns4bo_dir, model_path, name)
+ compressed_weights_path = os.path.join(pfns4bo_dir, model_path, name + '.gz')
+ if not os.path.exists(weights_path):
+ if not os.path.exists(compressed_weights_path):
+ print("Downloading", os.path.abspath(compressed_weights_path))
+ import requests
+ url = f'https://github.com/automl/PFNs4BO/raw/main/pfns4bo/final_models/{name + ".gz"}'
+ r = requests.get(url, allow_redirects=True)
+ os.makedirs(os.path.dirname(compressed_weights_path), exist_ok=True)
+ with open(compressed_weights_path, 'wb') as f:
+ f.write(r.content)
+ if os.path.exists(compressed_weights_path):
+ print("Unzipping", name)
+ os.system(f"gzip -dk {compressed_weights_path}")
+ else:
+ print("Failed to find", compressed_weights_path)
+ print("Make sure you have an internet connection to download the model automatically..")
+ if os.path.exists(weights_path):
+ print("Successfully located model at", weights_path)
+
+
+model_dict = {
+ 'hebo_plus_userprior_model': os.path.join(os.path.dirname(__file__),model_path,
+ 'hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt'),
+ 'hebo_plus_model': os.path.join(os.path.dirname(__file__),model_path,
+ 'model_hebo_morebudget_9_unused_features_3.pt'),
+ 'bnn_model': os.path.join(os.path.dirname(__file__),model_path,'model_sampled_warp_simple_mlp_for_hpob_46.pt')
+}
+
+
+def __getattr__(name):
+ if name in model_dict:
+ if not os.path.exists(model_dict[name]):
+ print("Can't find", os.path.abspath(model_dict[name]), "thus unzipping/downloading models now.")
+ print("This might take a while..")
+ prepare_models()
+ return model_dict[name]
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
+
diff --git a/pfns4bo/__pycache__/__init__.cpython-310.pyc b/pfns4bo/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..efc98edf8fef2d6c5ffc32263c02e2ea00e5ce76
Binary files /dev/null and b/pfns4bo/__pycache__/__init__.cpython-310.pyc differ
diff --git a/pfns4bo/__pycache__/__init__.cpython-311.pyc b/pfns4bo/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3fdde29f1e1334cdea57252fca96b348837042f0
Binary files /dev/null and b/pfns4bo/__pycache__/__init__.cpython-311.pyc differ
diff --git a/pfns4bo/__pycache__/__init__.cpython-38.pyc b/pfns4bo/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cda57481e3570093d99061ccaabdba5695f9c87d
Binary files /dev/null and b/pfns4bo/__pycache__/__init__.cpython-38.pyc differ
diff --git a/pfns4bo/__pycache__/__init__.cpython-39.pyc b/pfns4bo/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4d5bd37b071cb17723a2bbebbc0c1594008e3c48
Binary files /dev/null and b/pfns4bo/__pycache__/__init__.cpython-39.pyc differ
diff --git a/pfns4bo/__pycache__/bar_distribution.cpython-310.pyc b/pfns4bo/__pycache__/bar_distribution.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5c244b6dda8c98c5c10d3fe5f90faed5f45820e3
Binary files /dev/null and b/pfns4bo/__pycache__/bar_distribution.cpython-310.pyc differ
diff --git a/pfns4bo/__pycache__/bar_distribution.cpython-311.pyc b/pfns4bo/__pycache__/bar_distribution.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3e1b68485a31cb73f6a2845f5c3add499ad2a008
Binary files /dev/null and b/pfns4bo/__pycache__/bar_distribution.cpython-311.pyc differ
diff --git a/pfns4bo/__pycache__/bar_distribution.cpython-38.pyc b/pfns4bo/__pycache__/bar_distribution.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1941739e4cc92d574059f2b34ad5c5c8772d717d
Binary files /dev/null and b/pfns4bo/__pycache__/bar_distribution.cpython-38.pyc differ
diff --git a/pfns4bo/__pycache__/bar_distribution.cpython-39.pyc b/pfns4bo/__pycache__/bar_distribution.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a0e2e4df0327c301bc46ec3bbd4c8b6f090ed3af
Binary files /dev/null and b/pfns4bo/__pycache__/bar_distribution.cpython-39.pyc differ
diff --git a/pfns4bo/__pycache__/encoders.cpython-310.pyc b/pfns4bo/__pycache__/encoders.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3c814adf9aba13694368b887e51a3fdcf52fc66a
Binary files /dev/null and b/pfns4bo/__pycache__/encoders.cpython-310.pyc differ
diff --git a/pfns4bo/__pycache__/encoders.cpython-311.pyc b/pfns4bo/__pycache__/encoders.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d42aaaab82d46a447636d481d190d8f29f426336
Binary files /dev/null and b/pfns4bo/__pycache__/encoders.cpython-311.pyc differ
diff --git a/pfns4bo/__pycache__/encoders.cpython-39.pyc b/pfns4bo/__pycache__/encoders.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7b093892dfc046026a15a2a6ce4db58f5ec59f2d
Binary files /dev/null and b/pfns4bo/__pycache__/encoders.cpython-39.pyc differ
diff --git a/pfns4bo/__pycache__/layer.cpython-310.pyc b/pfns4bo/__pycache__/layer.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..947d5797078a2c39174f177d6d4794e9725eddbe
Binary files /dev/null and b/pfns4bo/__pycache__/layer.cpython-310.pyc differ
diff --git a/pfns4bo/__pycache__/layer.cpython-311.pyc b/pfns4bo/__pycache__/layer.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ce47c26268acfb4bd96312f122f5d0a0d362565b
Binary files /dev/null and b/pfns4bo/__pycache__/layer.cpython-311.pyc differ
diff --git a/pfns4bo/__pycache__/layer.cpython-38.pyc b/pfns4bo/__pycache__/layer.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ea978d02af6529e8b2564e2e4995b0f082575ed7
Binary files /dev/null and b/pfns4bo/__pycache__/layer.cpython-38.pyc differ
diff --git a/pfns4bo/__pycache__/layer.cpython-39.pyc b/pfns4bo/__pycache__/layer.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..956be20df025737d9609e48499da5d2f7ad1cd00
Binary files /dev/null and b/pfns4bo/__pycache__/layer.cpython-39.pyc differ
diff --git a/pfns4bo/__pycache__/positional_encodings.cpython-310.pyc b/pfns4bo/__pycache__/positional_encodings.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8c0f7bdb523442060249cd7c7ae408eb2dc03dba
Binary files /dev/null and b/pfns4bo/__pycache__/positional_encodings.cpython-310.pyc differ
diff --git a/pfns4bo/__pycache__/positional_encodings.cpython-311.pyc b/pfns4bo/__pycache__/positional_encodings.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1e2bfb3894ee85cf016514290d45485a9907f651
Binary files /dev/null and b/pfns4bo/__pycache__/positional_encodings.cpython-311.pyc differ
diff --git a/pfns4bo/__pycache__/positional_encodings.cpython-39.pyc b/pfns4bo/__pycache__/positional_encodings.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2dbfb2447dd87445f5c1e18a7aaaa7eec6865101
Binary files /dev/null and b/pfns4bo/__pycache__/positional_encodings.cpython-39.pyc differ
diff --git a/pfns4bo/__pycache__/transformer.cpython-310.pyc b/pfns4bo/__pycache__/transformer.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7adea3f8165cabf87e647f614f4962484636d840
Binary files /dev/null and b/pfns4bo/__pycache__/transformer.cpython-310.pyc differ
diff --git a/pfns4bo/__pycache__/transformer.cpython-311.pyc b/pfns4bo/__pycache__/transformer.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..46b551a9f3a25be6c6388c9325a360948a949f5f
Binary files /dev/null and b/pfns4bo/__pycache__/transformer.cpython-311.pyc differ
diff --git a/pfns4bo/__pycache__/transformer.cpython-38.pyc b/pfns4bo/__pycache__/transformer.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f8ef8d30196856282bcbadf59dec8338f2b091e6
Binary files /dev/null and b/pfns4bo/__pycache__/transformer.cpython-38.pyc differ
diff --git a/pfns4bo/__pycache__/transformer.cpython-39.pyc b/pfns4bo/__pycache__/transformer.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b51cbad99d627f8fce2ee344e48366ec6db7f48a
Binary files /dev/null and b/pfns4bo/__pycache__/transformer.cpython-39.pyc differ
diff --git a/pfns4bo/__pycache__/utils.cpython-310.pyc b/pfns4bo/__pycache__/utils.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e7c1dd52a9f56f32101f651822b62c89281e7ab3
Binary files /dev/null and b/pfns4bo/__pycache__/utils.cpython-310.pyc differ
diff --git a/pfns4bo/__pycache__/utils.cpython-311.pyc b/pfns4bo/__pycache__/utils.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3e13c4fdcaa6c870d68fbcc3bee5ec5ff46f1bec
Binary files /dev/null and b/pfns4bo/__pycache__/utils.cpython-311.pyc differ
diff --git a/pfns4bo/__pycache__/utils.cpython-38.pyc b/pfns4bo/__pycache__/utils.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ea07b8c5543a64d7acb40662d475132ddc727c10
Binary files /dev/null and b/pfns4bo/__pycache__/utils.cpython-38.pyc differ
diff --git a/pfns4bo/__pycache__/utils.cpython-39.pyc b/pfns4bo/__pycache__/utils.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5953dfe7f8606ec5accd809bcb567fd205c390ef
Binary files /dev/null and b/pfns4bo/__pycache__/utils.cpython-39.pyc differ
diff --git a/pfns4bo/bar_distribution.py b/pfns4bo/bar_distribution.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc846866c3bfedf45bb48c1b75af93d4e1670f2a
--- /dev/null
+++ b/pfns4bo/bar_distribution.py
@@ -0,0 +1,410 @@
+from .utils import print_once
+
+import torch
+from torch import nn
+
+
+class BarDistribution(nn.Module):
+ def __init__(self, borders: torch.Tensor, smoothing=.0, ignore_nan_targets=True): # here borders should start with min and end with max, where all values lie in (min,max) and are sorted
+ '''
+ :param borders:
+ :param smoothing:
+ :param append_mean_pred: Whether to predict the mean of the other positions as a last output in forward,
+ is enabled when additionally y has a sequence length 1 shorter than logits, i.e. len(logits) == 1 + len(y)
+ '''
+ super().__init__()
+ assert len(borders.shape) == 1
+ self.register_buffer('borders', borders)
+ self.register_buffer('smoothing', torch.tensor(smoothing))
+ self.register_buffer('bucket_widths', self.borders[1:] - self.borders[:-1])
+ full_width = self.bucket_widths.sum()
+
+ assert (1 - (full_width / (self.borders[-1] - self.borders[0]))).abs() < 1e-2, f'diff: {full_width - (self.borders[-1] - self.borders[0])} with {full_width} {self.borders[-1]} {self.borders[0]}'
+ assert (self.bucket_widths >= 0.0).all() , "Please provide sorted borders!" # This also allows size zero buckets
+ self.num_bars = len(borders) - 1
+ self.ignore_nan_targets = ignore_nan_targets
+ self.to(borders.device)
+
+ def __setstate__(self, state):
+ super().__setstate__(state)
+ self.__dict__.setdefault('append_mean_pred', False)
+
+ def map_to_bucket_idx(self, y):
+ target_sample = torch.searchsorted(self.borders, y) - 1
+ target_sample[y == self.borders[0]] = 0
+ target_sample[y == self.borders[-1]] = self.num_bars - 1
+ return target_sample
+
+ def ignore_init(self, y):
+ ignore_loss_mask = torch.isnan(y)
+ if ignore_loss_mask.any():
+ if not self.ignore_nan_targets: raise ValueError(f'Found NaN in target {y}')
+ print_once("A loss was ignored because there was nan target.")
+ y[ignore_loss_mask] = self.borders[0] # this is just a default value, it will be ignored anyway
+ return ignore_loss_mask
+
+ def compute_scaled_log_probs(self, logits):
+ # this is equivalent to log(p(y)) of the density p
+ bucket_log_probs = torch.log_softmax(logits, -1)
+ scaled_bucket_log_probs = bucket_log_probs - torch.log(self.bucket_widths)
+ return scaled_bucket_log_probs
+
+ def forward(self, logits, y, mean_prediction_logits=None): # gives the negative log density (the _loss_), y: T x B, logits: T x B x self.num_bars
+ y = y.clone().view(*logits.shape[:-1]) # no trailing one dimension
+ ignore_loss_mask = self.ignore_init(y)
+ target_sample = self.map_to_bucket_idx(y)
+ assert (target_sample >= 0).all() and (target_sample < self.num_bars).all(), f'y {y} not in support set for borders (min_y, max_y) {self.borders}'
+ assert logits.shape[-1] == self.num_bars, f'{logits.shape[-1]} vs {self.num_bars}'
+
+ scaled_bucket_log_probs = self.compute_scaled_log_probs(logits)
+ nll_loss = -scaled_bucket_log_probs.gather(-1,target_sample[..., None]).squeeze(-1) # T x B
+
+ if mean_prediction_logits is not None:
+ if not self.training:
+ print('Calculating loss incl mean prediction loss for nonmyopic BO.')
+ scaled_mean_log_probs = self.compute_scaled_log_probs(mean_prediction_logits)
+ nll_loss = torch.cat((nll_loss, self.mean_loss(logits, scaled_mean_log_probs)), 0)
+
+ smooth_loss = -scaled_bucket_log_probs.mean(dim=-1)
+ smoothing = self.smoothing if self.training else 0.
+ loss = (1. - smoothing) * nll_loss + smoothing * smooth_loss
+ loss[ignore_loss_mask] = 0.
+ return loss
+
+ def mean_loss(self, logits, scaled_mean_logits):
+ assert (len(logits.shape) == 3) and (len(scaled_mean_logits.shape) == 2), \
+ (len(logits.shape), len(scaled_mean_logits.shape))
+ means = self.mean(logits).detach() # T x B
+ target_mean = self.map_to_bucket_idx(means).clamp_(0, self.num_bars - 1) # T x B
+ return -scaled_mean_logits.gather(1, target_mean.T).mean(1).unsqueeze(0) # 1 x B
+
+ def mean(self, logits):
+ bucket_means = self.borders[:-1] + self.bucket_widths/2
+ p = torch.softmax(logits, -1)
+ return p @ bucket_means
+
+ def median(self, logits):
+ return self.icdf(logits, 0.5)
+
+ def icdf(self, logits, left_prob):
+ """
+ Implementation of the quantile function
+ :param logits: Tensor of any shape, with the last dimension being logits
+ :param left_prob: float: The probability mass to the left of the result.
+ :return: Position with `left_prob` probability weight to the left.
+ """
+ probs = logits.softmax(-1)
+ cumprobs = torch.cumsum(probs, -1)
+ idx = torch.searchsorted(cumprobs, left_prob * torch.ones(*cumprobs.shape[:-1], 1, device=logits.device))\
+ .squeeze(-1).clamp(0, cumprobs.shape[-1] - 1) # this might not do the right for outliers
+ cumprobs = torch.cat([torch.zeros(*cumprobs.shape[:-1], 1, device=logits.device), cumprobs], -1)
+
+ rest_prob = left_prob - cumprobs.gather(-1, idx[..., None]).squeeze(-1)
+ left_border = self.borders[idx]
+ right_border = self.borders[idx+1]
+ return left_border + (right_border - left_border) * rest_prob / probs.gather(-1, idx[..., None]).squeeze(-1)
+
+ def quantile(self, logits, center_prob=.682):
+ side_probs = (1.-center_prob)/2
+ return torch.stack((self.icdf(logits, side_probs), self.icdf(logits, 1.-side_probs)),-1)
+
+ def ucb(self, logits, best_f, rest_prob=(1-.682)/2, maximize=True):
+ """
+ UCB utility. Rest Prob is the amount of utility above (below) the confidence interval that is ignored.
+ Higher rest_prob is equivalent to lower beta in the standard GP-UCB formulation.
+ :param logits: Logits, as returned by the Transformer.
+ :param rest_prob: The amount of utility above (below) the confidence interval that is ignored.
+ The default is equivalent to using GP-UCB with `beta=1`.
+ To get the corresponding `beta`, where `beta` is from
+ the standard GP definition of UCB `ucb_utility = mean + beta * std`,
+ you can use this computation: `beta = math.sqrt(2)*torch.erfinv(torch.tensor(2*(1-rest_prob)-1))`.
+ :param maximize:
+ :return: utility
+ """
+ if maximize:
+ rest_prob = 1 - rest_prob
+ return self.icdf(logits, rest_prob)
+
+ def mode(self, logits):
+ mode_inds = logits.argmax(-1)
+ bucket_means = self.borders[:-1] + self.bucket_widths/2
+ return bucket_means[mode_inds]
+
+ def ei(self, logits, best_f, maximize=True): # logits: evaluation_points x batch x feature_dim
+ bucket_diffs = self.borders[1:] - self.borders[:-1]
+ assert maximize
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device)
+
+ best_f = best_f[..., None].repeat(*[1]*len(best_f.shape), logits.shape[-1])
+ clamped_best_f = best_f.clamp(self.borders[:-1], self.borders[1:])
+
+ #bucket_contributions = (best_f[...,None] < self.borders[:-1]).float() * bucket_means
+ # true bucket contributions
+ bucket_contributions = ((self.borders[1:]**2-clamped_best_f**2)/2 - best_f*(self.borders[1:] - clamped_best_f))/bucket_diffs
+
+ p = torch.softmax(logits, -1)
+ return torch.einsum("...b,...b->...", p, bucket_contributions)
+
+ def pi(self, logits, best_f, maximize=True):# logits: evaluation_points x batch x feature_dim
+ """
+ Acquisition Function: Probability of Improvement
+ :param logits: as returned by Transformer
+ :param best_f: best evaluation so far (the incumbent)
+ :param maximize: whether to maximize
+ :return: utility
+ """
+ assert maximize is True
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device)
+ p = torch.softmax(logits, -1)
+ border_widths = self.borders[1:] - self.borders[:-1]
+ factor = 1. - ((best_f[...,None] - self.borders[:-1]) / border_widths).clamp(0., 1.)
+ return (p * factor).sum(-1)
+
+
+ def mean_of_square(self, logits):
+ """
+ Computes E[x^2].
+ :param logits: Output of the model.
+ """
+ left_borders = self.borders[:-1]
+ right_borders = self.borders[1:]
+ bucket_mean_of_square = (left_borders.square() + right_borders.square() + left_borders*right_borders)/3.
+ p = torch.softmax(logits, -1)
+ return p @ bucket_mean_of_square
+
+ def variance(self, logits):
+ return self.mean_of_square(logits) - self.mean(logits).square()
+
+ def pi(self, logits, best_f, maximize=True):# logits: evaluation_points x batch x feature_dim
+ """
+ Acquisition Function: Probability of Improvement
+ :param logits: as returned by Transformer
+ :param best_f: best evaluation so far (the incumbent)
+ :param maximize: whether to maximize
+ :return: utility
+ """
+ assert maximize is True
+ p = torch.softmax(logits, -1)
+ border_widths = self.borders[1:] - self.borders[:-1]
+ factor = 1. - ((best_f - self.borders[:-1]) / border_widths).clamp(0., 1.)
+ return (p * factor).sum(-1)
+
+
+ def mean_of_square(self, logits):
+ """
+ Computes E[x^2].
+ :param logits: Output of the model.
+ """
+ left_borders = self.borders[:-1]
+ right_borders = self.borders[1:]
+ bucket_mean_of_square = (left_borders.square() + right_borders.square() + left_borders*right_borders)/3.
+ p = torch.softmax(logits, -1)
+ return p @ bucket_mean_of_square
+
+ def variance(self, logits):
+ return self.mean_of_square(logits) - self.mean(logits).square()
+
+
+class FullSupportBarDistribution(BarDistribution):
+ @staticmethod
+ def halfnormal_with_p_weight_before(range_max,p=.5):
+ s = range_max / torch.distributions.HalfNormal(torch.tensor(1.)).icdf(torch.tensor(p))
+ return torch.distributions.HalfNormal(s)
+
+
+ def forward(self, logits, y, mean_prediction_logits=None): # gives the negative log density (the _loss_), y: T x B, logits: T x B x self.num_bars
+ assert self.num_bars > 1
+ y = y.clone().view(len(y),-1) # no trailing one dimension
+ ignore_loss_mask = self.ignore_init(y) # alters y
+ target_sample = self.map_to_bucket_idx(y) # shape: T x B (same as y)
+ target_sample.clamp_(0, self.num_bars - 1)
+
+ assert logits.shape[-1] == self.num_bars, f'{logits.shape[-1]} vs {self.num_bars}'
+ assert (target_sample >= 0).all() and (target_sample < self.num_bars).all(), \
+ f'y {y} not in support set for borders (min_y, max_y) {self.borders}'
+ assert logits.shape[-1] == self.num_bars, f'{logits.shape[-1]} vs {self.num_bars}'
+ # ignore all position with nan values
+
+
+ scaled_bucket_log_probs = self.compute_scaled_log_probs(logits)
+
+ assert len(scaled_bucket_log_probs) == len(target_sample), (len(scaled_bucket_log_probs), len(target_sample))
+ log_probs = scaled_bucket_log_probs.gather(-1, target_sample.unsqueeze(-1)).squeeze(-1)
+
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]), self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+
+
+ log_probs[target_sample == 0] += side_normals[0].log_prob((self.borders[1]-y[target_sample == 0]).clamp(min=.00000001)) + torch.log(self.bucket_widths[0])
+ log_probs[target_sample == self.num_bars-1] += side_normals[1].log_prob((y[target_sample == self.num_bars-1]-self.borders[-2]).clamp(min=.00000001)) + torch.log(self.bucket_widths[-1])
+
+ nll_loss = -log_probs
+
+ if mean_prediction_logits is not None:
+ assert not ignore_loss_mask.any(), "Ignoring examples is not implemented with mean pred."
+ if not self.training:
+ print('Calculating loss incl mean prediction loss for nonmyopic BO.')
+ if not torch.is_grad_enabled():
+ print("Warning: loss is not correct in absolute terms, only the gradient is right, when using `append_mean_pred`.")
+ scaled_mean_log_probs = self.compute_scaled_log_probs(mean_prediction_logits)
+ nll_loss = torch.cat((nll_loss, self.mean_loss(logits, scaled_mean_log_probs)), 0)
+ #ignore_loss_mask = torch.zeros_like(nll_loss, dtype=torch.bool)
+
+ if self.smoothing:
+ smooth_loss = -scaled_bucket_log_probs.mean(dim=-1)
+ smoothing = self.smoothing if self.training else 0.
+ nll_loss = (1. - smoothing) * nll_loss + smoothing * smooth_loss
+
+ if ignore_loss_mask.any():
+ nll_loss[ignore_loss_mask] = 0.
+
+ return nll_loss
+
+ def mean(self, logits):
+ bucket_means = self.borders[:-1] + self.bucket_widths / 2
+ p = torch.softmax(logits, -1)
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ bucket_means[0] = -side_normals[0].mean + self.borders[1]
+ bucket_means[-1] = side_normals[1].mean + self.borders[-2]
+ return p @ bucket_means.to(logits.device)
+
+ def mean_of_square(self, logits):
+ """
+ Computes E[x^2].
+ :param logits: Output of the model.
+ """
+ left_borders = self.borders[:-1]
+ right_borders = self.borders[1:]
+ bucket_mean_of_square = (left_borders.square() + right_borders.square() + left_borders*right_borders)/3.
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ bucket_mean_of_square[0] = side_normals[0].variance + (-side_normals[0].mean + self.borders[1]).square()
+ bucket_mean_of_square[-1] = side_normals[1].variance + (side_normals[1].variance + self.borders[-2]).square()
+ p = torch.softmax(logits, -1)
+ return p @ bucket_mean_of_square
+
+ def pi(self, logits, best_f, maximize=True):# logits: evaluation_points x batch x feature_dim
+ """
+ Acquisition Function: Probability of Improvement
+ :param logits: as returned by Transformer (evaluation_points x batch x feature_dim)
+ :param best_f: best evaluation so far (the incumbent)
+ :param maximize: whether to maximize
+ :return: utility
+ """
+ assert maximize is True
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device) # evaluation_points x batch
+ assert best_f.shape == logits[...,0].shape, f"best_f.shape: {best_f.shape}, logits.shape: {logits.shape}"
+ p = torch.softmax(logits, -1) # evaluation_points x batch
+ border_widths = self.borders[1:] - self.borders[:-1]
+ factor = 1. - ((best_f[...,None] - self.borders[:-1]) / border_widths).clamp(0., 1.) # evaluation_points x batch x num_bars
+
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ position_in_side_normals = (-(best_f - self.borders[1]).clamp(max=0.), (best_f - self.borders[-2]).clamp(min=0.)) # evaluation_points x batch
+ factor[...,0] = 0.
+ factor[...,0][position_in_side_normals[0] > 0.] = side_normals[0].cdf(position_in_side_normals[0][position_in_side_normals[0] > 0.])
+ factor[...,-1] = 1.
+ factor[...,-1][position_in_side_normals[1] > 0.] = 1. - side_normals[1].cdf(position_in_side_normals[1][position_in_side_normals[1] > 0.])
+ return (p * factor).sum(-1)
+
+
+ def ei_for_halfnormal(self, scale, best_f, maximize=True):
+ """
+ This is the EI for a standard normal distribution with mean 0 and variance `scale` times 2.
+ Which is the same as the half normal EI.
+ I tested this with MC approximation:
+ ei_for_halfnormal = lambda scale, best_f: (torch.distributions.HalfNormal(torch.tensor(scale)).sample((10_000_000,))- best_f ).clamp(min=0.).mean()
+ print([(ei_for_halfnormal(scale,best_f), FullSupportBarDistribution().ei_for_halfnormal(scale,best_f)) for scale in [0.1,1.,10.] for best_f in [.1,10.,4.]])
+ :param scale:
+ :param best_f:
+ :param maximize:
+ :return:
+ """
+ assert maximize
+ mean = torch.tensor(0.)
+ u = (mean - best_f) / scale
+ normal = torch.distributions.Normal(torch.zeros_like(u), torch.ones_like(u))
+ try:
+ ucdf = normal.cdf(u)
+ except ValueError:
+ print(f"u: {u}, best_f: {best_f}, scale: {scale}")
+ raise
+ updf = torch.exp(normal.log_prob(u))
+ normal_ei = scale * (updf + u * ucdf)
+ return 2*normal_ei
+
+ def ei(self, logits, best_f, maximize=True): # logits: evaluation_points x batch x feature_dim
+ if torch.isnan(logits).any():
+ raise ValueError(f"logits contains NaNs: {logits}")
+ bucket_diffs = self.borders[1:] - self.borders[:-1]
+ assert maximize
+ if not torch.is_tensor(best_f) or not len(best_f.shape):
+ best_f = torch.full(logits[...,0].shape, best_f, device=logits.device)
+ assert best_f.shape == logits[...,0].shape, f"best_f.shape: {best_f.shape}, logits.shape: {logits.shape}"
+
+
+ best_f_per_logit = best_f[..., None].repeat(*[1]*len(best_f.shape), logits.shape[-1])
+ clamped_best_f = best_f_per_logit.clamp(self.borders[:-1], self.borders[1:])
+
+ # true bucket contributions
+ bucket_contributions = ((self.borders[1:]**2-clamped_best_f**2)/2 - best_f_per_logit*(self.borders[1:] - clamped_best_f))/bucket_diffs
+
+ # extra stuff for continuous
+ side_normals = (self.halfnormal_with_p_weight_before(self.bucket_widths[0]),
+ self.halfnormal_with_p_weight_before(self.bucket_widths[-1]))
+ position_in_side_normals = (-(best_f - self.borders[1]).clamp(max=0.),
+ (best_f - self.borders[-2]).clamp(min=0.)) # evaluation_points x batch
+
+ bucket_contributions[...,-1] = self.ei_for_halfnormal(side_normals[1].scale, position_in_side_normals[1])
+
+ bucket_contributions[...,0] = self.ei_for_halfnormal(side_normals[0].scale, torch.zeros_like(position_in_side_normals[0])) \
+ - self.ei_for_halfnormal(side_normals[0].scale, position_in_side_normals[0])
+
+ p = torch.softmax(logits, -1)
+ return torch.einsum("...b,...b->...", p, bucket_contributions)
+
+
+def get_bucket_limits(num_outputs:int, full_range:tuple=None, ys:torch.Tensor=None, verbose:bool=False):
+ assert (ys is None) != (full_range is None), 'Either full_range or ys must be passed.'
+
+ if ys is not None:
+ ys = ys.flatten()
+ ys = ys[~torch.isnan(ys)]
+ if len(ys) % num_outputs: ys = ys[:-(len(ys) % num_outputs)]
+ print(f'Using {len(ys)} y evals to estimate {num_outputs} buckets. Cut off the last {len(ys) % num_outputs} ys.')
+ ys_per_bucket = len(ys) // num_outputs
+ if full_range is None:
+ full_range = (ys.min(), ys.max())
+ else:
+ assert full_range[0] <= ys.min() and full_range[1] >= ys.max(), f'full_range {full_range} not in range of ys {ys.min(), ys.max()}'
+ full_range = torch.tensor(full_range)
+ ys_sorted, ys_order = ys.sort(0)
+ bucket_limits = (ys_sorted[ys_per_bucket-1::ys_per_bucket][:-1]+ys_sorted[ys_per_bucket::ys_per_bucket])/2
+ if verbose:
+ print(f'Using {len(ys)} y evals to estimate {num_outputs} buckets. Cut off the last {len(ys) % num_outputs} ys.')
+ print(full_range)
+ bucket_limits = torch.cat([full_range[0].unsqueeze(0), bucket_limits, full_range[1].unsqueeze(0)],0)
+
+ else:
+ class_width = (full_range[1] - full_range[0]) / num_outputs
+ bucket_limits = torch.cat([full_range[0] + torch.arange(num_outputs).float()*class_width, torch.tensor(full_range[1]).unsqueeze(0)], 0)
+
+ assert len(bucket_limits) - 1 == num_outputs, f'len(bucket_limits) - 1 == {len(bucket_limits) - 1} != {num_outputs} == num_outputs'
+ assert full_range[0] == bucket_limits[0], f'{full_range[0]} != {bucket_limits[0]}'
+ assert full_range[-1] == bucket_limits[-1], f'{full_range[-1]} != {bucket_limits[-1]}'
+
+ return bucket_limits
+
+
+def get_custom_bar_dist(borders, criterion):
+ # Tested that a bar_dist with borders 0.54 (-> softplus 1.0) yields the same bar distribution as the passed one.
+ borders_ = torch.nn.functional.softplus(borders) + 0.001
+ borders_ = (torch.cumsum(torch.cat([criterion.borders[0:1], criterion.bucket_widths]) * borders_, 0))
+ criterion_ = criterion.__class__(borders=borders_, handle_nans=criterion.handle_nans)
+ return criterion_
+
+
+
diff --git a/pfns4bo/config.json b/pfns4bo/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78fa42672b56ce5e3ec8a0e17ccd6900a6010370
--- /dev/null
+++ b/pfns4bo/config.json
@@ -0,0 +1,56 @@
+{
+ "PFN-lbfgs-minimizer-sampleonlyvalid-fast-sobol-gpu": [
+ "pfn_bo_bayesmark.py",
+ {
+ "pfn_file" : "final_models/model_hebo_morebudget_9_unused_features_3.pt",
+ "minimize": 1,
+ "device": "cuda:0",
+ "fit_encoder_from_step": null,
+ "sample_only_valid": 1,
+ "pre_sample_size": 1000,
+ "num_candidates": 10,
+ "sobol_sampler": 1
+ }
+ ],
+ "PFN-lbfgs-minimizer-sampleonlyvalid-fast-max1id0-gpu": [
+ "pfn_bo_bayesmark.py",
+ {
+ "pfn_file" : "final_models/model_hebo_morebudget_9_unused_features_3.pt",
+ "minimize": 1,
+ "device": "cuda:0",
+ "fit_encoder_from_step": null,
+ "sample_only_valid": 1,
+ "pre_sample_size": 1000,
+ "num_candidates": 10,
+ "max_initial_design": 1,
+ "fixed_initial_guess": 0.0
+ }
+ ],
+ "PFN-lbfgs-minimizer-sampleonlyvalid-fast-max1id0.5-gpu": [
+ "pfn_bo_bayesmark.py",
+ {
+ "pfn_file" : "final_models/model_hebo_morebudget_9_unused_features_3.pt",
+ "minimize": 1,
+ "device": "cuda:0",
+ "fit_encoder_from_step": null,
+ "sample_only_valid": 1,
+ "pre_sample_size": 1000,
+ "num_candidates": 10,
+ "max_initial_design": 1,
+ "fixed_initial_guess": 0.0
+ }
+ ],
+ "PFN-lbfgs-minimizer-sampleonlyvalid-fast-bnn-sobol-gpu": [
+ "pfn_bo_bayesmark.py",
+ {
+ "pfn_file" : "final_models/model_sampled_warp_simple_mlp_for_hpob_46.pt",
+ "minimize": 1,
+ "device": "cuda:0",
+ "fit_encoder_from_step": null,
+ "sample_only_valid": 1,
+ "pre_sample_size": 1000,
+ "num_candidates": 10,
+ "sobol_sampler": 1
+ }
+ ],
+}
\ No newline at end of file
diff --git a/pfns4bo/decoders.py b/pfns4bo/decoders.py
new file mode 100644
index 0000000000000000000000000000000000000000..efdd8fcb624c1b0a6d127fcf0aa8548c4ca1524d
--- /dev/null
+++ b/pfns4bo/decoders.py
@@ -0,0 +1,30 @@
+import torch
+from torch import nn
+import random
+
+
+class ScaledDecoder(nn.Module):
+ def __init__(self, ninp, nhid, nout):
+ super().__init__()
+ self.linear = nn.Linear(ninp, nhid)
+ self.linear1 = nn.Linear(nhid, nout)
+ self.linear2 = nn.Linear(nhid, 10)
+
+ def forward(self, x):
+ #return torch.cat([self.linear1(x), self.linear2(x)], -1)
+ x = self.linear(x)
+ x = nn.GELU()(x)
+ temps = self.linear2(x).softmax(-1) @ torch.tensor([1.,1.4,1.7,2.,5.,10.,20.,40.,80.,160.], device=x.device)
+ if random.random() > .99:
+ print(temps.shape,temps[:,:2])
+ return self.linear1(x) / temps.unsqueeze(-1)
+
+class FixedScaledDecoder(nn.Module):
+ def __init__(self, ninp, nhid, nout):
+ super().__init__()
+ self.mapper = nn.Sequential(nn.Linear(ninp, nhid), nn.GELU(), nn.Linear(nhid, nout))
+ self.T = nn.Parameter(torch.ones(10000)/10000)
+
+ def forward(self, x):
+ return self.mapper(x)/self.T.sum()
+
diff --git a/pfns4bo/encoders.py b/pfns4bo/encoders.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0b429e5936bb2669d11baf2529372aa334ed9d8
--- /dev/null
+++ b/pfns4bo/encoders.py
@@ -0,0 +1,277 @@
+import math
+
+import torch
+import torch.nn as nn
+from .utils import normalize_data
+
+
+class StyleEncoder(nn.Module):
+ def __init__(self, num_hyperparameters, em_size):
+ super().__init__()
+ self.em_size = em_size
+ self.embedding = nn.Linear(num_hyperparameters, self.em_size)
+
+ def forward(self, hyperparameters): # B x num_hps
+ return self.embedding(hyperparameters)
+
+
+class StyleEmbEncoder(nn.Module):
+ def __init__(self, num_hyperparameters, em_size, num_embeddings=100):
+ super().__init__()
+ assert num_hyperparameters == 1
+ self.em_size = em_size
+ self.embedding = nn.Embedding(num_embeddings, self.em_size)
+
+ def forward(self, hyperparameters): # B x num_hps
+ return self.embedding(hyperparameters.squeeze(1))
+
+
+class _PositionalEncoding(nn.Module):
+ def __init__(self, d_model, dropout=0.):
+ super().__init__()
+ self.dropout = nn.Dropout(p=dropout)
+ self.d_model = d_model
+ self.device_test_tensor = nn.Parameter(torch.tensor(1.))
+
+ def forward(self, x):# T x B x num_features
+ assert self.d_model % x.shape[-1]*2 == 0
+ d_per_feature = self.d_model // x.shape[-1]
+ pe = torch.zeros(*x.shape, d_per_feature, device=self.device_test_tensor.device)
+ #position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
+ interval_size = 10
+ div_term = (1./interval_size) * 2*math.pi*torch.exp(torch.arange(0, d_per_feature, 2, device=self.device_test_tensor.device).float()*math.log(math.sqrt(2)))
+ #print(div_term/2/math.pi)
+ pe[..., 0::2] = torch.sin(x.unsqueeze(-1) * div_term)
+ pe[..., 1::2] = torch.cos(x.unsqueeze(-1) * div_term)
+ return self.dropout(pe).view(x.shape[0],x.shape[1],self.d_model)
+
+
+Positional = lambda _, emsize: _PositionalEncoding(d_model=emsize)
+
+class EmbeddingEncoder(nn.Module):
+ def __init__(self, num_features, em_size, num_embs=100):
+ super().__init__()
+ self.num_embs = num_embs
+ self.embeddings = nn.Embedding(num_embs * num_features, em_size, max_norm=True)
+ self.init_weights(.1)
+ self.min_max = (-2,+2)
+
+ @property
+ def width(self):
+ return self.min_max[1] - self.min_max[0]
+
+ def init_weights(self, initrange):
+ self.embeddings.weight.data.uniform_(-initrange, initrange)
+
+ def discretize(self, x):
+ split_size = self.width / self.num_embs
+ return (x - self.min_max[0] // split_size).int().clamp(0, self.num_embs - 1)
+
+ def forward(self, x): # T x B x num_features
+ x_idxs = self.discretize(x)
+ x_idxs += torch.arange(x.shape[-1], device=x.device).view(1, 1, -1) * self.num_embs
+ # print(x_idxs,self.embeddings.weight.shape)
+ return self.embeddings(x_idxs).mean(-2)
+
+
+class Normalize(nn.Module):
+ def __init__(self, mean, std):
+ super().__init__()
+ self.mean = mean
+ self.std = std
+
+ def forward(self, x):
+ return (x-self.mean)/self.std
+
+
+class SqueezeBetween0and1(nn.Module): # take care of test set here
+ def forward(self, x):
+ width = x.max(0).values - x.min(0).values
+ result = (x - x.min(0).values) / width
+ result[(width == 0)[None].repeat(len(x),*[1]*(len(x.shape)-1))] = .5
+ return result
+
+
+def get_normalized_uniform_encoder(encoder_creator):
+ """
+ This can be used to wrap an encoder that is fed uniform samples in [0,1] and normalizes these to 0 mean and 1 std.
+ For example, it can be used as `encoder_creator = get_normalized_uniform_encoder(encoders.Linear)`, now this can
+ be initialized with `encoder_creator(feature_dim, in_dim)`.
+ :param encoder:
+ :return:
+ """
+ return lambda in_dim, out_dim: nn.Sequential(Normalize(.5, math.sqrt(1/12)), encoder_creator(in_dim, out_dim))
+
+
+def get_normalized_encoder(encoder_creator, data_std):
+ return lambda in_dim, out_dim: nn.Sequential(Normalize(0., data_std), encoder_creator(in_dim, out_dim))
+
+def get_log_dims(x, eps=1e-10):
+ logged_x = ((x+eps).log()-math.log(eps))/(math.log(1.+eps)-math.log(eps))
+ return logged_x
+
+def add_log_neglog_dims(x, eps=1e-10):
+ logged_x = get_log_dims(x,eps)/2.
+ neglogged_x = 1-get_log_dims(1-x,eps)/2.
+ logged_x[x > .5] = neglogged_x[x > .5]
+ return torch.stack([x,logged_x],-1).view(*x.shape[:-1],-1)
+
+class AddLogNegLogDims(nn.Module):
+ def __init__(self, eps=1e-10):
+ super().__init__()
+ self.eps = eps
+
+ def forward(self, x):
+ return add_log_neglog_dims(x, self.eps)
+
+def get_logdim_encoder(encoder_creator, eps=1e-10):
+ return lambda in_dim, out_dim: nn.Sequential(AddLogNegLogDims(eps), encoder_creator(in_dim*2, out_dim))
+
+class ZNormalize(nn.Module):
+ def forward(self, x):
+ std = x.std(-1,keepdim=True)
+ std[std==0.] = 1.
+ return (x-x.mean(-1,keepdim=True))/std
+
+
+class ZNormalizePerDataset(nn.Module):
+ def forward(self, x):
+ std = x.std(0,keepdim=True)
+ std[std==0.] = 1.
+ return (x-x.mean(0,keepdim=True))/std
+
+
+class AppendEmbeddingEncoder(nn.Module):
+ def __init__(self, base_encoder, num_features, emsize):
+ super().__init__()
+ self.num_features = num_features
+ self.base_encoder = base_encoder
+ self.emb = nn.Parameter(torch.zeros(emsize))
+
+ def forward(self, x):
+ if (x[-1] == 1.).all():
+ append_embedding = True
+ else:
+ assert (x[-1] == 0.).all(), "You need to specify as last position whether to append embedding. " \
+ "If you don't want this behavior, please use the wrapped encoder instead."
+ append_embedding = False
+ x = x[:-1]
+ encoded_x = self.base_encoder(x)
+ if append_embedding:
+ encoded_x = torch.cat([encoded_x, self.emb[None, None, :].repeat(1, encoded_x.shape[1], 1)], 0)
+ return encoded_x
+
+def get_append_embedding_encoder(encoder_creator):
+ return lambda num_features, emsize: AppendEmbeddingEncoder(encoder_creator(num_features, emsize), num_features, emsize)
+
+
+class VariableNumFeaturesEncoder(nn.Module):
+ def __init__(self, base_encoder, num_features):
+ super().__init__()
+ self.base_encoder = base_encoder
+ self.num_features = num_features
+
+ def forward(self, x):
+ x = x * (self.num_features/x.shape[-1])
+ x = torch.cat((x, torch.zeros(*x.shape[:-1], self.num_features - x.shape[-1], device=x.device)), -1)
+ return self.base_encoder(x)
+
+
+def get_variable_num_features_encoder(encoder_creator):
+ return lambda num_features, emsize: VariableNumFeaturesEncoder(encoder_creator(num_features, emsize), num_features)
+
+class NoMeanEncoder(nn.Module):
+ """
+ This can be useful for any prior that is translation invariant in x or y.
+ A standard GP for example is translation invariant in x.
+ That is, GP(x_test+const,x_train+const,y_train) = GP(x_test,x_train,y_train).
+ """
+ def __init__(self, base_encoder):
+ super().__init__()
+ self.base_encoder = base_encoder
+
+ def forward(self, x):
+ return self.base_encoder(x - x.mean(0, keepdim=True))
+
+
+def get_no_mean_encoder(encoder_creator):
+ return lambda num_features, emsize: NoMeanEncoder(encoder_creator(num_features, emsize))
+
+MLP = lambda num_features, emsize: nn.Sequential(nn.Linear(num_features,emsize*2),
+ nn.ReLU(),
+ nn.Linear(emsize*2,emsize))
+
+class NanHandlingEncoder(nn.Module):
+ def __init__(self, num_features, emsize, keep_nans=True):
+ super().__init__()
+ self.num_features = 2 * num_features if keep_nans else num_features
+ self.emsize = emsize
+ self.keep_nans = keep_nans
+ self.layer = nn.Linear(self.num_features, self.emsize)
+
+ def forward(self, x):
+ if self.keep_nans:
+ x = torch.cat([torch.nan_to_num(x, nan=0.0), normalize_data(torch.isnan(x) * -1
+ + torch.logical_and(torch.isinf(x), torch.sign(x) == 1) * 1
+ + torch.logical_and(torch.isinf(x), torch.sign(x) == -1) * 2
+ )], -1)
+ else:
+ x = torch.nan_to_num(x, nan=0.0)
+ return self.layer(x)
+
+
+class Linear(nn.Linear):
+ def __init__(self, num_features, emsize, replace_nan_by_zero=False):
+ super().__init__(num_features, emsize)
+ self.num_features = num_features
+ self.emsize = emsize
+ self.replace_nan_by_zero = replace_nan_by_zero
+
+ def forward(self, x):
+ if self.replace_nan_by_zero:
+ x = torch.nan_to_num(x, nan=0.0)
+ return super().forward(x)
+
+ def __setstate__(self, state):
+ super().__setstate__(state)
+ self.__dict__.setdefault('replace_nan_by_zero', True)
+
+
+class Conv(nn.Module):
+ def __init__(self, input_size, emsize):
+ super().__init__()
+ self.convs = torch.nn.ModuleList([nn.Conv2d(64 if i else 1, 64, 3) for i in range(5)])
+ self.linear = nn.Linear(64,emsize)
+
+ def forward(self, x):
+ size = math.isqrt(x.shape[-1])
+ assert size*size == x.shape[-1]
+ x = x.reshape(*x.shape[:-1], 1, size, size)
+ for conv in self.convs:
+ if x.shape[-1] < 4:
+ break
+ x = conv(x)
+ x.relu_()
+ x = nn.AdaptiveAvgPool2d((1,1))(x).squeeze(-1).squeeze(-1)
+ return self.linear(x)
+
+
+class CanEmb(nn.Embedding):
+ def __init__(self, num_features, num_embeddings: int, embedding_dim: int, *args, **kwargs):
+ assert embedding_dim % num_features == 0
+ embedding_dim = embedding_dim // num_features
+ super().__init__(num_embeddings, embedding_dim, *args, **kwargs)
+
+ def forward(self, x):
+ lx = x.long()
+ assert (lx == x).all(), "CanEmb only works with tensors of whole numbers"
+ x = super().forward(lx)
+ return x.view(*x.shape[:-2], -1)
+
+
+def get_Canonical(num_classes):
+ return lambda num_features, emsize: CanEmb(num_features, num_classes, emsize)
+
+
+def get_Embedding(num_embs_per_feature=100):
+ return lambda num_features, emsize: EmbeddingEncoder(num_features, emsize, num_embs=num_embs_per_feature)
diff --git a/pfns4bo/final_models/hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt.gz b/pfns4bo/final_models/hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..d627e843958f13ad8dba786b2b5f22263fdb071a
--- /dev/null
+++ b/pfns4bo/final_models/hebo_morebudget_9_unused_features_3_userpriorperdim2_8.pt.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:55f3982bb9eee39de83c11d069da88aee718ff1e03c6ef101baff5a2912d5d97
+size 99675562
diff --git a/pfns4bo/final_models/model_hebo_morebudget_9_unused_features_3.pt.gz b/pfns4bo/final_models/model_hebo_morebudget_9_unused_features_3.pt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..a88ef2f8f000956e46f2cc6b023183b81b6c73db
--- /dev/null
+++ b/pfns4bo/final_models/model_hebo_morebudget_9_unused_features_3.pt.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ad7af1d807db9eaffb152dc89eaae9262c10e2bb99b81bb12ae5cf8f80aba432
+size 99440314
diff --git a/pfns4bo/final_models/model_sampled_warp_simple_mlp_for_hpob_46.pt.gz b/pfns4bo/final_models/model_sampled_warp_simple_mlp_for_hpob_46.pt.gz
new file mode 100644
index 0000000000000000000000000000000000000000..5695d5efc342ff7dc28123df86472d940ec2c4ad
--- /dev/null
+++ b/pfns4bo/final_models/model_sampled_warp_simple_mlp_for_hpob_46.pt.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6cfd0f663190986d8034e3a1e790acad38e30ed4ab7933ce4d67ec2b769f485d
+size 52657986
diff --git a/pfns4bo/initializers.py b/pfns4bo/initializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a2de2711a62676223950c35e5ce88cabcb086a0
--- /dev/null
+++ b/pfns4bo/initializers.py
@@ -0,0 +1,9 @@
+import torch
+from torch import nn
+
+def get_NormalInitializer(std):
+ def initializer(m):
+ if isinstance(m, nn.Linear):
+ nn.init.normal_(m.weight, 0, std)
+ nn.init.normal_(m.bias, 0, std)
+ return initializer
\ No newline at end of file
diff --git a/pfns4bo/layer.py b/pfns4bo/layer.py
new file mode 100644
index 0000000000000000000000000000000000000000..766452b7e7d1ce976345038c50b97caeb53dec6a
--- /dev/null
+++ b/pfns4bo/layer.py
@@ -0,0 +1,147 @@
+from functools import partial
+
+import torch
+from torch import nn
+from torch.nn.modules.transformer import _get_activation_fn, Module, Tensor, Optional, MultiheadAttention, Linear, Dropout, LayerNorm
+
+from torch.utils.checkpoint import checkpoint
+
+
+class TransformerEncoderLayer(Module):
+ r"""TransformerEncoderLayer is made up of self-attn and feedforward network.
+ This standard encoder layer is based on the paper "Attention Is All You Need".
+ Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N Gomez,
+ Lukasz Kaiser, and Illia Polosukhin. 2017. Attention is all you need. In Advances in
+ Neural Information Processing Systems, pages 6000-6010. Users may modify or implement
+ in a different way during application.
+
+ Args:
+ d_model: the number of expected features in the input (required).
+ nhead: the number of heads in the multiheadattention models (required).
+ dim_feedforward: the dimension of the feedforward network model (default=2048).
+ dropout: the dropout value (default=0.1).
+ activation: the activation function of intermediate layer, relu or gelu (default=relu).
+ layer_norm_eps: the eps value in layer normalization components (default=1e-5).
+ batch_first: If ``True``, then the input and output tensors are provided
+ as (batch, seq, feature). Default: ``False``.
+
+ Examples::
+ >>> encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8)
+ >>> src = torch.rand(10, 32, 512)
+ >>> out = encoder_layer(src)
+
+ Alternatively, when ``batch_first`` is ``True``:
+ >>> encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8, batch_first=True)
+ >>> src = torch.rand(32, 10, 512)
+ >>> out = encoder_layer(src)
+ """
+ __constants__ = ['batch_first']
+
+ def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1, activation="relu",
+ layer_norm_eps=1e-5, batch_first=False, pre_norm=False,
+ device=None, dtype=None, recompute_attn=False, save_trainingset_representations=False) -> None:
+ factory_kwargs = {'device': device, 'dtype': dtype}
+ super().__init__()
+ self.self_attn = MultiheadAttention(d_model, nhead, dropout=dropout, batch_first=batch_first,
+ **factory_kwargs)
+ # Implementation of Feedforward model
+ self.linear1 = Linear(d_model, dim_feedforward, **factory_kwargs)
+ self.dropout = Dropout(dropout)
+ self.linear2 = Linear(dim_feedforward, d_model, **factory_kwargs)
+
+ self.norm1 = LayerNorm(d_model, eps=layer_norm_eps, **factory_kwargs)
+ self.norm2 = LayerNorm(d_model, eps=layer_norm_eps, **factory_kwargs)
+ self.dropout1 = Dropout(dropout)
+ self.dropout2 = Dropout(dropout)
+ self.pre_norm = pre_norm
+ self.recompute_attn = recompute_attn
+ self.save_trainingset_representations = save_trainingset_representations
+ self.saved_src_to_attend_to = None
+
+ self.activation = _get_activation_fn(activation)
+
+ def __setstate__(self, state):
+ if 'activation' not in state:
+ state['activation'] = F.relu
+ super().__setstate__(state)
+ self.__dict__.setdefault('save_trainingset_representations', False)
+
+ def forward(self, src: Tensor, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None) -> Tensor:
+ r"""Pass the input through the encoder layer.
+
+ Args:
+ src: the sequence to the encoder layer (required).
+ src_mask: the mask for the src sequence (optional).
+ src_key_padding_mask: the mask for the src keys per batch (optional).
+
+ Shape:
+ see the docs in Transformer class.
+ """
+ if self.save_trainingset_representations: assert isinstance(src_mask, int) and not self.training, \
+ "save_trainingset_representations is only supported in eval mode and requires src_mask to be an int"
+
+ if self.pre_norm:
+ src_ = self.norm1(src)
+ else:
+ src_ = src
+ if isinstance(src_mask, tuple):
+ # global attention setup
+ assert not self.self_attn.batch_first
+ assert src_key_padding_mask is None
+
+ global_src_mask, trainset_src_mask, valset_src_mask = src_mask
+
+ num_global_tokens = global_src_mask.shape[0]
+ num_train_tokens = trainset_src_mask.shape[0]
+
+ global_tokens_src = src_[:num_global_tokens]
+ train_tokens_src = src_[num_global_tokens:num_global_tokens+num_train_tokens]
+ global_and_train_tokens_src = src_[:num_global_tokens+num_train_tokens]
+ eval_tokens_src = src_[num_global_tokens+num_train_tokens:]
+
+
+ attn = partial(checkpoint, self.self_attn) if self.recompute_attn else self.self_attn
+
+ global_tokens_src2 = attn(global_tokens_src, global_and_train_tokens_src, global_and_train_tokens_src, None, True, global_src_mask)[0]
+ train_tokens_src2 = attn(train_tokens_src, global_tokens_src, global_tokens_src, None, True, trainset_src_mask)[0]
+ eval_tokens_src2 = attn(eval_tokens_src, src_, src_,
+ None, True, valset_src_mask)[0]
+
+ src2 = torch.cat([global_tokens_src2, train_tokens_src2, eval_tokens_src2], dim=0)
+
+ elif isinstance(src_mask, int):
+ assert src_key_padding_mask is None
+ single_eval_position = src_mask
+ src_to_attend_to = src_[:single_eval_position]
+ if self.save_trainingset_representations:
+ if single_eval_position == src_.shape[0] or single_eval_position is None:
+ self.saved_src_to_attend_to = src_to_attend_to
+ elif single_eval_position == 0:
+ if self.saved_src_to_attend_to is None:
+ raise ValueError("First save the trainingset representations by passing in a src_mask of None or the length of the src")
+ src_to_attend_to = self.saved_src_to_attend_to
+ else:
+ raise ValueError("save_trainingset_representations only supports single_eval_position == 0 or single_eval_position == src.shape[0]")
+ src_left = self.self_attn(src_[:single_eval_position], src_[:single_eval_position], src_[:single_eval_position])[0]
+ src_right = self.self_attn(src_[single_eval_position:], src_to_attend_to, src_to_attend_to)[0]
+ src2 = torch.cat([src_left, src_right], dim=0)
+ else:
+ if self.recompute_attn:
+ src2 = checkpoint(self.self_attn, src_, src_, src_, src_key_padding_mask, True, src_mask)[0]
+ else:
+ src2 = self.self_attn(src_, src_, src_, attn_mask=src_mask,
+ key_padding_mask=src_key_padding_mask)[0]
+ src = src + self.dropout1(src2)
+ if not self.pre_norm:
+ src = self.norm1(src)
+
+ if self.pre_norm:
+ src_ = self.norm2(src)
+ else:
+ src_ = src
+ src2 = self.linear2(self.dropout(self.activation(self.linear1(src_))))
+ src = src + self.dropout2(src2)
+
+ if not self.pre_norm:
+ src = self.norm2(src)
+ return src
\ No newline at end of file
diff --git a/pfns4bo/lost_functions.py b/pfns4bo/lost_functions.py
new file mode 100644
index 0000000000000000000000000000000000000000..091a8fc30930299e0ae37baab8dd3688c9c7f692
--- /dev/null
+++ b/pfns4bo/lost_functions.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python3
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+r"""
+A converter that simplifies using numpy-based optimizers with generic torch
+`nn.Module` classes. This enables using a `scipy.optim.minimize` optimizer
+for optimizing module parameters.
+"""
+
+from __future__ import annotations
+
+from collections import OrderedDict
+from math import inf
+from numbers import Number
+from typing import Dict, List, Optional, Set, Tuple
+from warnings import warn
+
+import numpy as np
+import torch
+from botorch.optim.utils import (
+ _get_extra_mll_args,
+ _handle_numerical_errors,
+ get_name_filter,
+ get_parameters_and_bounds,
+ TorchAttr,
+)
+from gpytorch.mlls import MarginalLogLikelihood
+from torch.nn import Module
+
+
+def module_to_array(
+ module: Module,
+ bounds: Optional[Dict[str, Tuple[Optional[float], Optional[float]]]] = None,
+ exclude: Optional[Set[str]] = None,
+) -> Tuple[np.ndarray, Dict[str, TorchAttr], Optional[np.ndarray]]:
+ r"""Extract named parameters from a module into a numpy array.
+
+ Only extracts parameters with requires_grad, since it is meant for optimizing.
+
+ Args:
+ module: A module with parameters. May specify parameter constraints in
+ a `named_parameters_and_constraints` method.
+ bounds: A dictionary mapping parameter names t lower and upper bounds.
+ of lower and upper bounds. Bounds specified here take precedence
+ over bounds on the same parameters specified in the constraints
+ registered with the module.
+ exclude: A list of parameter names that are to be excluded from extraction.
+
+ Returns:
+ 3-element tuple containing
+ - The parameter values as a numpy array.
+ - An ordered dictionary with the name and tensor attributes of each
+ parameter.
+ - A `2 x n_params` numpy array with lower and upper bounds if at least
+ one constraint is finite, and None otherwise.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ """
+ warn(
+ "`module_to_array` is marked for deprecation, consider using "
+ "`get_parameters_and_bounds`, `get_parameters_as_ndarray_1d`, or "
+ "`get_bounds_as_ndarray` instead.",
+ DeprecationWarning,
+ )
+ param_dict, bounds_dict = get_parameters_and_bounds(
+ module=module,
+ name_filter=None if exclude is None else get_name_filter(exclude),
+ requires_grad=True,
+ )
+ if bounds is not None:
+ bounds_dict.update(bounds)
+
+ # Record tensor metadata and read parameter values to the tape
+ param_tape: List[Number] = []
+ property_dict = OrderedDict()
+ with torch.no_grad():
+ for name, param in param_dict.items():
+ property_dict[name] = TorchAttr(param.shape, param.dtype, param.device)
+ param_tape.extend(param.view(-1).cpu().double().tolist())
+
+ # Extract lower and upper bounds
+ start = 0
+ bounds_np = None
+ params_np = np.asarray(param_tape)
+ for name, param in param_dict.items():
+ numel = param.numel()
+ if name in bounds_dict:
+ for row, bound in enumerate(bounds_dict[name]):
+ if bound is None:
+ continue
+
+ if torch.is_tensor(bound):
+ if (bound == (2 * row - 1) * inf).all():
+ continue
+ bound = bound.detach().cpu()
+
+ elif bound == (2 * row - 1) * inf:
+ continue
+
+ if bounds_np is None:
+ bounds_np = np.full((2, len(params_np)), ((-inf,), (inf,)))
+
+ bounds_np[row, start : start + numel] = bound
+ start += numel
+
+ return params_np, property_dict, bounds_np
+
+
+
+
+def set_params_with_array(
+ module: Module, x: np.ndarray, property_dict: Dict[str, TorchAttr]
+) -> Module:
+ r"""Set module parameters with values from numpy array.
+
+ Args:
+ module: Module with parameters to be set
+ x: Numpy array with parameter values
+ property_dict: Dictionary of parameter names and torch attributes as
+ returned by module_to_array.
+
+ Returns:
+ Module: module with parameters updated in-place.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ >>> parameter_array += 0.1 # perturb parameters (for example only)
+ >>> mll = set_params_with_array(mll, parameter_array, property_dict)
+ """
+ warn(
+ "`_set_params_with_array` is marked for deprecation, consider using "
+ "`set_parameters_from_ndarray_1d` instead.",
+ DeprecationWarning,
+ )
+ param_dict = OrderedDict(module.named_parameters())
+ start_idx = 0
+ for p_name, attrs in property_dict.items():
+ # Construct the new tensor
+ if len(attrs.shape) == 0: # deal with scalar tensors
+ end_idx = start_idx + 1
+ new_data = torch.tensor(
+ x[start_idx], dtype=attrs.dtype, device=attrs.device
+ )
+ else:
+ end_idx = start_idx + np.prod(attrs.shape)
+ new_data = torch.tensor(
+ x[start_idx:end_idx], dtype=attrs.dtype, device=attrs.device
+ ).view(*attrs.shape)
+ start_idx = end_idx
+ # Update corresponding parameter in-place. Disable autograd to update.
+ param_dict[p_name].requires_grad_(False)
+ param_dict[p_name].copy_(new_data)
+ param_dict[p_name].requires_grad_(True)
+ return module
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pfns4bo/pfn_bo_bayesmark.py b/pfns4bo/pfn_bo_bayesmark.py
new file mode 100644
index 0000000000000000000000000000000000000000..d1f60398dbebd8bdffcdedafd1e98541ae941ed8
--- /dev/null
+++ b/pfns4bo/pfn_bo_bayesmark.py
@@ -0,0 +1,388 @@
+import os
+from copy import deepcopy
+from bayesmark.abstract_optimizer import AbstractOptimizer
+from bayesmark.experiment import experiment_main
+from bayesmark.space import JointSpace
+import torch
+import logging
+from sklearn.preprocessing import MinMaxScaler, StandardScaler
+import numpy as np
+from sklearn.compose import ColumnTransformer
+from scipy.special import logit, expit
+# from scipy.stats import qmc
+from torch.quasirandom import SobolEngine
+from .scripts import acquisition_functions, tune_input_warping
+
+class PFNOptimizer(AbstractOptimizer):
+ # Used for determining the version number of package used
+ # primary_import = ""
+
+ def __init__(self, api_config, pfn_file, minimize=True, acqf_optimizer_name="lbfgs", sobol_sampler=False,
+ device="cpu:0", fit_encoder_from_step=None, verbose=False, rand_bool=False, sample_only_valid=False,
+ round_suggests_to=4, min_initial_design=0, max_initial_design=None, rand_sugg_after_x_steps_of_stagnation=None,
+ fixed_initial_guess=None,minmax_encode_y=False,**acqf_kwargs):
+ """Build wrapper class to use optimizer in benchmark.
+
+ Parameters
+ ----------
+ api_config : dict-like of dict-like
+ Configuration of the optimization variables. See API description.
+ """
+ assert not 'fit_encoder' in acqf_kwargs
+ AbstractOptimizer.__init__(self, api_config)
+ # Do whatever other setup is needed
+ # ...
+
+ self.space_x = JointSpace(api_config)
+ self.bounds = self.space_x.get_bounds()
+ self.device = device
+
+ self.model = torch.load(pfn_file) if pfn_file.startswith('/') else torch.load(os.path.dirname(__file__) + '/' + pfn_file)
+
+ self.X = []
+ self.y = []
+ self.api_config = {key: value for key, value in sorted(api_config.items())}
+ self.hp_names = list(self.api_config.keys())
+ # self.model.encoder.num_features = 18
+
+ self.epsilon = 1e-8
+ self.minimize = minimize
+ self.sobol_sampler = sobol_sampler
+ self.create_scaler()
+ self.sobol = SobolEngine(len(self.max_values), scramble=True)
+ self.acqf_optimizer_name = acqf_optimizer_name
+ self.acqf_kwargs = acqf_kwargs
+ self.fit_encoder_from_step = fit_encoder_from_step
+ assert not (rand_bool and sample_only_valid)
+ self.rand_bool = rand_bool
+ self.sample_only_valid = sample_only_valid
+ self.verbose = verbose
+ self.round_suggests_to = round_suggests_to
+ self.min_initial_design = min_initial_design
+ self.max_initial_design = max_initial_design
+ self.fixed_initial_guess = fixed_initial_guess
+ self.minmax_encode_y = minmax_encode_y
+ self.rand_sugg_after_x_steps_of_stagnation = rand_sugg_after_x_steps_of_stagnation
+ self.model.eval()
+
+ print(api_config)
+
+ def create_scaler(self):
+
+ list_of_scalers = []
+ self.min_values = []
+ self.max_values = []
+ self.spaces = []
+ self.types = []
+
+ for i, feature in enumerate(self.api_config):
+ # list_of_scalers.append((feature, MinMaxScaler(feature_range),i))
+ self.spaces.append(self.api_config[feature].get("space", "bool"))
+ self.types.append(self.api_config[feature]["type"])
+
+ if self.types[-1] == "bool":
+ feature_range = [0, 1]
+ else:
+ feature_range = list(self.api_config[feature]["range"])
+
+ feature_range[0] = self.transform_feature(feature_range[0], -1)
+ feature_range[1] = self.transform_feature(feature_range[1], -1)
+
+ self.min_values.append(feature_range[0])
+ self.max_values.append(feature_range[1])
+
+ self.column_scaler = ColumnTransformer(list_of_scalers)
+ self.max_values: np.array = np.array(self.max_values)
+ self.min_values: np.array = np.array(self.min_values)
+
+ def transform_feature_inverse(self, x, feature_index):
+
+ if self.spaces[feature_index] == "log":
+ x = np.exp(x)
+ elif self.spaces[feature_index] == "logit":
+ x = expit(x)
+ if self.types[feature_index] == "int":
+ if self.rand_bool:
+ x = int(x) + int(np.random.rand() < (x-int(x)))
+ else:
+ x = int(np.round(x))
+ elif self.types[feature_index] == "bool":
+ if self.rand_bool:
+ x = np.random.rand() < x
+ else:
+ x = bool(np.round(x))
+
+ return x
+
+ def transform_feature(self, x, feature_index):
+
+ if np.isinf(x) or np.isnan(x):
+ return 0
+
+ if self.spaces[feature_index] == "log":
+ x = np.log(x)
+
+ elif self.spaces[feature_index] == "logit":
+ x = logit(x)
+
+ elif self.types[feature_index] == "bool":
+ x = int(x)
+ return x
+
+ def random_suggest(self):
+ self.rand_prev = True
+
+ if self.sobol_sampler:
+
+ # sampler = qmc.Sobol(d=len(self.max_values), scramble=False)
+ # temp_guess = sampler.random_base2(m=len(self.max_values))
+ temp_guess = self.sobol.draw(1).numpy()[0]
+ temp_guess = temp_guess * (self.max_values - self.min_values) + self.min_values
+
+ x_guess = {}
+ for j, feature in enumerate(self.api_config):
+ x = self.transform_feature_inverse(temp_guess[j], j)
+ x_guess[feature] = x
+ x_guess = [x_guess]
+
+ else:
+ x_guess = {}
+ for i, feature in enumerate(self.api_config):
+ temp_guess = np.random.uniform(self.min_values[i], self.max_values[i], 1)[0]
+ temp_guess = self.transform_feature_inverse(temp_guess, i)
+
+ x_guess[feature] = temp_guess
+ x_guess = [x_guess]
+ return x_guess
+
+ def transform_back(self, x_guess):
+ if self.round_suggests_to is not None:
+ x_guess = np.round(x_guess, self.round_suggests_to) # make sure very similar values are actually the same
+ x_guess = x_guess * (self.max_values - self.min_values) + self.min_values
+ x_guess = x_guess.tolist()
+ return self.transform_inverse(x_guess)
+
+ def min_max_encode(self, temp_X):
+ # this, combined with transform is the inverse of transform_back
+ temp_X = (temp_X - self.min_values) / (self.max_values - self.min_values)
+ temp_X = torch.tensor(temp_X).to(torch.float32)
+ temp_X = torch.clamp(temp_X, min=0., max=1.)
+ return temp_X
+
+
+ @torch.no_grad()
+ def suggest(self, n_suggestions=1):
+ """Get suggestion from the optimizer.
+
+ Parameters
+ ----------
+ n_suggestions : int
+ Desired number of parallel suggestions in the output
+
+ Returns
+ -------
+ next_guess : list of dict
+ List of `n_suggestions` suggestions to evaluate the objective
+ function. Each suggestion is a dictionary where each key
+ corresponds to a parameter being optimized.
+ """
+ assert n_suggestions == 1, "Only one suggestion at a time is supported"
+ # Do whatever is needed to get the parallel guesses
+ # ...
+ # scaler = MinMaxScaler()
+ # scaler.fit(self.X)
+ try:
+ num_initial_design = max(len(self.bounds), self.min_initial_design)
+ if self.max_initial_design is not None:
+ num_initial_design = min(num_initial_design, self.max_initial_design)
+ if len(self.X) < num_initial_design:
+ if len(self.X) == 0 and self.fixed_initial_guess is not None:
+ x_guess = [self.transform_back(np.array([self.fixed_initial_guess for _ in range(len(self.bounds))]))]
+ else:
+ x_guess = self.random_suggest()
+ return x_guess
+ else:
+ temp_X = np.array(self.X)
+ temp_X = self.min_max_encode(temp_X)
+ if self.minmax_encode_y:
+ temp_y = MinMaxScaler().fit_transform(np.array(self.y).reshape(-1, 1)).reshape(-1)
+ else:
+ temp_y = np.array(self.y)
+ temp_y = torch.tensor(temp_y).to(torch.float32)
+ if self.rand_sugg_after_x_steps_of_stagnation is not None \
+ and len(self.y) > self.rand_sugg_after_x_steps_of_stagnation\
+ and not self.rand_prev:
+ if temp_y[:-self.rand_sugg_after_x_steps_of_stagnation].max() == temp_y.max():
+ print(f"Random suggestion after >= {self.rand_sugg_after_x_steps_of_stagnation} steps of stagnation")
+ x_guess = self.random_suggest()
+ return x_guess
+ if self.verbose:
+ from matplotlib import pyplot as plt
+ print(f"{temp_X=}, {temp_y=}")
+ if temp_X.shape[1] == 2:
+ from scipy.stats import rankdata
+ plt.title('Observations, red -> blue.')
+ plt.scatter(temp_X[:,0], temp_X[:,1], cmap='RdBu', c=rankdata(temp_y))
+ plt.show()
+
+ temp_X = temp_X.to(self.device)
+ temp_y = temp_y.to(self.device)
+
+ if self.fit_encoder_from_step and self.fit_encoder_from_step <= len(self.X):
+ with torch.enable_grad():
+ w = tune_input_warping.fit_input_warping(self.model, temp_X, temp_y)
+ temp_X_warped = w(temp_X).detach()
+ else:
+ temp_X_warped = temp_X
+
+ with torch.enable_grad():
+ if self.acqf_optimizer_name == "lbfgs":
+ def rand_sample_func(n):
+ pre_samples = torch.rand(n, temp_X_warped.shape[1], device='cpu')
+ back_transformed_samples = [self.transform_back(sample) for sample in pre_samples]
+ samples = np.array([self.transform(deepcopy(bt_sample)) for bt_sample in back_transformed_samples])
+ samples = self.min_max_encode(samples)
+ return samples.to(self.device)
+
+ if self.sample_only_valid:
+ rand_sample_func = rand_sample_func
+ # dims with bool or int are not continuous, thus no gradient opt is applied
+ dims_wo_gradient_opt = [i for i, t in enumerate(self.types) if t != "real"]
+ else:
+ rand_sample_func = None
+ dims_wo_gradient_opt = []
+
+ x_guess, x_options, eis, x_rs, x_rs_eis = acquisition_functions.optimize_acq_w_lbfgs(
+ self.model, temp_X_warped, temp_y, device=self.device,
+ verbose=self.verbose, rand_sample_func=rand_sample_func,
+ dims_wo_gradient_opt=dims_wo_gradient_opt, **{'apply_power_transform':True,**self.acqf_kwargs}
+ )
+
+ elif self.acqf_optimizer_name == 'adam':
+ x_guess = acquisition_functions.optimize_acq(self.model, temp_X_warped, temp_y, apply_power_transform=True, device=self.device, **self.acqf_kwargs
+ ).detach().cpu().numpy()
+ else:
+ raise ValueError("Optimizer not recognized, set `acqf_optimizer_name` to 'lbfgs' or 'adam'")
+
+
+ back_transformed_x_options = [self.transform_back(x) for x in x_options]
+ opt_X = np.array([self.transform(deepcopy(transformed_x_options)) for transformed_x_options in back_transformed_x_options])
+ opt_X = self.min_max_encode(opt_X)
+ opt_new = ~(opt_X[:,None] == temp_X[None].cpu()).all(-1).any(1)
+ for i, x in enumerate(opt_X):
+ if opt_new[i]:
+ if self.verbose: print(f"New point at pos {i}: {back_transformed_x_options[i], x_options[i]}")
+ self.rand_prev = False
+ return [back_transformed_x_options[i]]
+ print('backup from initial rand search')
+ back_transformed_x_options = [self.transform_back(x) for x in x_rs]
+ opt_X = np.array([self.transform(deepcopy(transformed_x_options)) for transformed_x_options in back_transformed_x_options])
+ opt_X = self.min_max_encode(opt_X)
+ opt_new = ~(opt_X[:,None] == temp_X[None].cpu()).all(-1).any(1)
+ for i, x in enumerate(opt_X):
+ if opt_new[i]:
+ if self.verbose: print(f"New point at pos {i}: {back_transformed_x_options[i], x_rs[i]} with ei {x_rs_eis[i]}")
+ self.rand_prev = False
+ return [back_transformed_x_options[i]]
+ print("No new points found, random suggestion")
+ return self.random_suggest()
+ except Exception as e:
+ raise e
+
+ def transform(self, X_dict):
+ X_tf = []
+ for i, feature in enumerate(X_dict.keys()):
+ X_dict[feature] = self.transform_feature(X_dict[feature], i)
+ X_tf.append(X_dict[feature])
+ return X_tf
+
+ def transform_inverse(self, X_list):
+ X_tf = {}
+ for i, hp_name in enumerate(self.hp_names):
+ X_tf[hp_name] = self.transform_feature_inverse(X_list[i], i)
+ return X_tf
+
+
+ def observe(self, X, y):
+ """Feed an observation back.
+
+ Parameters
+ ----------
+ X : list of dict-like
+ Places where the objective function has already been evaluated.
+ Each suggestion is a dictionary where each key corresponds to a
+ parameter being optimized.
+ y : array-like, shape (n,)
+ Corresponding values where objective has been evaluated
+ """
+ # Update the model with new objective function observations
+ # ...
+ # No return statement needed
+ if np.isinf(y) and y > 0:
+ y[:] = 1e10
+
+ if not np.isnan(y) and not np.isinf(y):
+ assert len(y) == 1 and len(X) == 1, "Only one suggestion at a time is supported"
+ X = {key: value for key, value in sorted(X[0].items())}
+ assert list(X.keys()) == list(self.api_config.keys()) == list(self.hp_names) == list(
+ self.space_x.param_list)
+ if self.verbose:
+ print(f"{X=}, {y=}")
+ X = self.transform(X)
+ if self.verbose:
+ print(f"transformed {X=}")
+ self.X.append(X)
+ if self.minimize:
+ self.y.append(-y[0])
+ else:
+ self.y.append(y[0])
+ else:
+ assert False
+
+def test():
+ from bayesmark.experiment import _build_test_problem, run_study, OBJECTIVE_NAMES
+ #function_instance = _build_test_problem(model_name='ada', dataset='breast', scorer='nll', path=None)
+ function_instance = _build_test_problem(model_name='kNN', dataset='boston', scorer='mse', path=None)
+
+ # Setup optimizer
+ api_config = function_instance.get_api_config()
+ import os
+ # check is file
+
+
+ config = {
+ "pfn_file": 'final_models/model_hebo_morebudget_9_unused_features_3.pt',
+ "minimize": 1,
+ "device": "cpu:0",
+ "fit_encoder_from_step": None,
+ 'pre_sample_size': 1_000,
+ 'num_grad_steps': 15_000,
+ 'num_candidates': 10,
+ 'rand_bool': True,
+ }
+ opt = PFNOptimizer(api_config, verbose=True, **config)
+
+ function_evals, timing, suggest_log = run_study(
+ opt, function_instance, 50, 1, callback=None, n_obj=len(OBJECTIVE_NAMES),
+ )
+
+
+if __name__ == "__main__":
+ import uuid
+ from bayesmark.serialize import XRSerializer
+ from bayesmark.cmd_parse import CmdArgs
+ import bayesmark.cmd_parse as cmd
+ import bayesmark.constants as cc
+
+ description = "Run a study with one benchmark function and an optimizer"
+ args = cmd.parse_args(cmd.experiment_parser(description))
+
+ run_uuid = uuid.UUID(args[CmdArgs.uuid])
+
+
+ # set global logging level
+ logging.basicConfig(level=logging.DEBUG)
+ # This is the entry point for experiments, so pass the class to experiment_main to use this optimizer.
+ # This statement must be included in the wrapper class file:
+
+ experiment_main(PFNOptimizer, args=args)
\ No newline at end of file
diff --git a/pfns4bo/positional_encodings.py b/pfns4bo/positional_encodings.py
new file mode 100644
index 0000000000000000000000000000000000000000..05580e052d6bb1fe782441e7e65088f7989e8e0b
--- /dev/null
+++ b/pfns4bo/positional_encodings.py
@@ -0,0 +1,70 @@
+import math
+
+import torch
+from torch import nn
+
+
+# Protocol for positonal encodings.
+# __init__(d_model, max_len=..[, more optionals])
+# forward(x: (seq_len, bs, d_model)) -> Tensor of shape (*x.shape[:2],d_model) containing pos. embeddings
+
+
+class NoPositionalEncoding(nn.Module):
+ def __init__(self, d_model, max_len=None):
+ super(NoPositionalEncoding, self).__init__()
+ pass
+
+ def forward(self, x):
+ return x #* math.sqrt(x.shape[-1])
+
+
+class PositionalEncoding(nn.Module):
+ def __init__(self, d_model, max_len=5000):
+ super(PositionalEncoding, self).__init__()
+ pe = torch.zeros(max_len, d_model)
+ position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
+ div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
+ pe[:, 0::2] = torch.sin(position * div_term)
+ pe[:, 1::2] = torch.cos(position * div_term)
+ pe = pe.unsqueeze(0).transpose(0, 1)
+ self.register_buffer('pe', pe)
+
+ def forward(self, x):
+ x = self.pe[:x.size(0), :] + x # * math.sqrt(x.shape[-1])
+ return x
+
+
+class LearnedPositionalEncoding(nn.Module):
+ def __init__(self, d_model, max_len=5000):
+ super(LearnedPositionalEncoding, self).__init__()
+ self.max_seq_len = max_len
+ #self.positional_embeddings = nn.Embedding(max_len, d_model)
+ self.positional_embeddings = nn.Parameter(torch.empty(max_len, d_model))
+ nn.init.normal_(self.positional_embeddings, mean=0, std=d_model ** -0.5)
+
+ def forward(self, x):
+ seq_len, bs, d_model = x.shape
+ assert seq_len <= len(self.positional_embeddings), 'seq_len can be at most max_len.'
+ pos_emb = self.positional_embeddings[:seq_len]
+ return pos_emb.unsqueeze(1).expand(seq_len, bs, d_model) + x #* math.sqrt(x.shape[-1])
+
+
+class PairedScrambledPositionalEncodings(LearnedPositionalEncoding):
+ # TODO check whether it is a problem to use the same perm. for full batch
+ def forward(self, x):
+ seq_len, bs, d_model = x.shape
+ assert seq_len <= len(self.positional_embeddings), 'seq_len can be at most max_len.'
+ assert len(self.positional_embeddings) % 2 == 0, 'Please specify an even max_len.'
+
+ paired_embs = self.positional_embeddings.view(len(self.positional_embeddings), -1, 2)
+ pos_emb = paired_embs[torch.randperm(len(paired_embs))].view(*self.positional_embeddings.shape)[:seq_len]
+
+ return pos_emb.unsqueeze(1).expand(seq_len, bs, d_model) + x #* math.sqrt(x.shape[-1])
+
+
+
+
+
+
+
+
diff --git a/pfns4bo/priors/__init__.py b/pfns4bo/priors/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..59640bfffe4f05e1e2d1ff55687db28edf92abab
--- /dev/null
+++ b/pfns4bo/priors/__init__.py
@@ -0,0 +1,3 @@
+from . import fast_gp, nonmyopic_bo, utils, normalize_with_style, simple_mlp, hyperparameter_sampling, input_warping, hebo_prior, condition_on_area_of_opt
+from .utils import get_batch_sequence as get_batch_sequence, get_batch_to_dataloader as get_batch_to_dataloader
+from .prior import Batch
diff --git a/pfns4bo/priors/__pycache__/__init__.cpython-311.pyc b/pfns4bo/priors/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b404fce3ce562dfbc4766048e87255041965984f
Binary files /dev/null and b/pfns4bo/priors/__pycache__/__init__.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/__init__.cpython-39.pyc b/pfns4bo/priors/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cf714d73061dce94a6e29dc00c17a33b3f6a7162
Binary files /dev/null and b/pfns4bo/priors/__pycache__/__init__.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/condition_on_area_of_opt.cpython-311.pyc b/pfns4bo/priors/__pycache__/condition_on_area_of_opt.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..831d88d82626d28f89ba50d2bfc025ca56913fc2
Binary files /dev/null and b/pfns4bo/priors/__pycache__/condition_on_area_of_opt.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/condition_on_area_of_opt.cpython-39.pyc b/pfns4bo/priors/__pycache__/condition_on_area_of_opt.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fa4d0b41f4d9cae93efc4c400eda2cf82d7a4f2e
Binary files /dev/null and b/pfns4bo/priors/__pycache__/condition_on_area_of_opt.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/fast_gp.cpython-311.pyc b/pfns4bo/priors/__pycache__/fast_gp.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..65d13ca02ed2492eba57309624a7702cc6e52918
Binary files /dev/null and b/pfns4bo/priors/__pycache__/fast_gp.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/fast_gp.cpython-39.pyc b/pfns4bo/priors/__pycache__/fast_gp.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bdef6ba21e4077974f000a091c6ebbaef6b87f4b
Binary files /dev/null and b/pfns4bo/priors/__pycache__/fast_gp.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/hebo_prior.cpython-311.pyc b/pfns4bo/priors/__pycache__/hebo_prior.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..34f7c4fd630d4fd16a169024f32c09d9068f90ef
Binary files /dev/null and b/pfns4bo/priors/__pycache__/hebo_prior.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/hebo_prior.cpython-39.pyc b/pfns4bo/priors/__pycache__/hebo_prior.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7724e21b60ad571538d6e74999b4677729567ff0
Binary files /dev/null and b/pfns4bo/priors/__pycache__/hebo_prior.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/hyperparameter_sampling.cpython-311.pyc b/pfns4bo/priors/__pycache__/hyperparameter_sampling.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..536ce73661a6c4b0ba7dd7e94308109bf818c599
Binary files /dev/null and b/pfns4bo/priors/__pycache__/hyperparameter_sampling.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/hyperparameter_sampling.cpython-39.pyc b/pfns4bo/priors/__pycache__/hyperparameter_sampling.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c48ea80ba696051f6460690b468d9a12b9673473
Binary files /dev/null and b/pfns4bo/priors/__pycache__/hyperparameter_sampling.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/input_warping.cpython-311.pyc b/pfns4bo/priors/__pycache__/input_warping.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..634ee041c9dc309d818160ae5ec5c8c9b222dbcb
Binary files /dev/null and b/pfns4bo/priors/__pycache__/input_warping.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/input_warping.cpython-39.pyc b/pfns4bo/priors/__pycache__/input_warping.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..51adc14c2aa5a00385af5cfc6671be76c7936dd8
Binary files /dev/null and b/pfns4bo/priors/__pycache__/input_warping.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/nonmyopic_bo.cpython-311.pyc b/pfns4bo/priors/__pycache__/nonmyopic_bo.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b12c12b8cecd8e887b4c79e781f5a331a8b69e8f
Binary files /dev/null and b/pfns4bo/priors/__pycache__/nonmyopic_bo.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/nonmyopic_bo.cpython-39.pyc b/pfns4bo/priors/__pycache__/nonmyopic_bo.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1bfdc0d17e0396d2b8ca87bc39f50f1203a05159
Binary files /dev/null and b/pfns4bo/priors/__pycache__/nonmyopic_bo.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/normalize_with_style.cpython-311.pyc b/pfns4bo/priors/__pycache__/normalize_with_style.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c92ecac36d5ce0ca0b16a881cd92c0839fa0a7e5
Binary files /dev/null and b/pfns4bo/priors/__pycache__/normalize_with_style.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/normalize_with_style.cpython-39.pyc b/pfns4bo/priors/__pycache__/normalize_with_style.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f4affff6a2028f3ec693f8cbe025316349464453
Binary files /dev/null and b/pfns4bo/priors/__pycache__/normalize_with_style.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/prior.cpython-311.pyc b/pfns4bo/priors/__pycache__/prior.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1e713ae993f05f4f67bdc50fb0b4a6afc097fff5
Binary files /dev/null and b/pfns4bo/priors/__pycache__/prior.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/prior.cpython-39.pyc b/pfns4bo/priors/__pycache__/prior.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..22bc38619b30832360c72d1ab7daedef61733667
Binary files /dev/null and b/pfns4bo/priors/__pycache__/prior.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/simple_mlp.cpython-311.pyc b/pfns4bo/priors/__pycache__/simple_mlp.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2a1dada326d855afb964d1f568f198f09e6638d0
Binary files /dev/null and b/pfns4bo/priors/__pycache__/simple_mlp.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/simple_mlp.cpython-39.pyc b/pfns4bo/priors/__pycache__/simple_mlp.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f206b6778f31cc36e10b6b2ff013007f9ff764e3
Binary files /dev/null and b/pfns4bo/priors/__pycache__/simple_mlp.cpython-39.pyc differ
diff --git a/pfns4bo/priors/__pycache__/utils.cpython-311.pyc b/pfns4bo/priors/__pycache__/utils.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c33b0e8098bd0dc20f1eae589423581dbc034edd
Binary files /dev/null and b/pfns4bo/priors/__pycache__/utils.cpython-311.pyc differ
diff --git a/pfns4bo/priors/__pycache__/utils.cpython-39.pyc b/pfns4bo/priors/__pycache__/utils.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f3eb44367e2f9e1ec17a7433fd9cbd1ea1a0b652
Binary files /dev/null and b/pfns4bo/priors/__pycache__/utils.cpython-39.pyc differ
diff --git a/pfns4bo/priors/condition_on_area_of_opt.py b/pfns4bo/priors/condition_on_area_of_opt.py
new file mode 100644
index 0000000000000000000000000000000000000000..9e9975953cb8d314350bf9661d9ba2ba1d77ee97
--- /dev/null
+++ b/pfns4bo/priors/condition_on_area_of_opt.py
@@ -0,0 +1,63 @@
+import torch
+
+from .prior import Batch
+from ..utils import default_device
+
+
+@torch.no_grad()
+def get_batch(batch_size, seq_len, num_features, get_batch, epoch, device=default_device, hyperparameters={}, **kwargs):
+ """
+ This function assumes that every x is in the range [0, 1].
+ Style shape is (batch_size, 3*num_features) under the assumption that get_batch returns a batch
+ with shape (seq_len, batch_size, num_features).
+ The style is build the following way: [prob_of_feature_1_in_range, range_min_of_feature_1, range_max_of_feature_1, ...]
+
+
+
+ :param batch_size:
+ :param seq_len:
+ :param num_features:
+ :param get_batch:
+ :param epoch:
+ :param device:
+ :param hyperparameters:
+ :param kwargs:
+ :return:
+ """
+
+ max_num_divisions = hyperparameters.get('condition_on_area_max_num_divisions', 5)
+ maximize = hyperparameters.get('condition_on_area_maximize', True)
+ remove_correct_from_rand = hyperparameters.get('condition_on_area_remove_correct_from_rand', False)
+ assert remove_correct_from_rand is False, 'implement it'
+
+ batch: Batch = get_batch(batch_size=batch_size, seq_len=seq_len,
+ num_features=num_features, device=device,
+ hyperparameters=hyperparameters,
+ epoch=epoch, **kwargs)
+ assert batch.style is None
+
+ d = batch.x.shape[2]
+
+ prob_correct = torch.rand(batch_size, d, device=device)
+ correct_opt = torch.rand(batch_size, d, device=device) < prob_correct
+ division_size = torch.randint(1, max_num_divisions + 1, (batch_size, d), device=device, dtype=torch.long)
+
+ optima_inds = batch.target_y.argmax(0).squeeze() if maximize else batch.target_y.argmin(0).squeeze() # batch_size
+ optima = batch.x[optima_inds, torch.arange(batch_size, device=device)] # shape: (batch_size, d)
+
+ optima_sections = torch.min(torch.floor(optima * division_size).long(), division_size - 1)
+ random_sections = torch.min(torch.floor(torch.rand(batch_size, batch.x.shape[2], device=device) * division_size).long(), division_size - 1)
+
+ sections = torch.where(correct_opt, optima_sections, random_sections).float() # shape: (batch_size, d)
+ sections /= division_size.float()
+ assert tuple(sections.shape) == (batch_size, d)
+ batch.style = torch.stack([prob_correct, sections, sections + 1 / division_size], 2).view(batch_size, -1) # shape: (batch_size, 3*d)
+
+ return batch
+
+
+
+
+
+
+
diff --git a/pfns4bo/priors/condition_on_area_of_opt_continuous.py b/pfns4bo/priors/condition_on_area_of_opt_continuous.py
new file mode 100644
index 0000000000000000000000000000000000000000..a9baa7b1243afe0f846e13d7ccddbbba81f36cb3
--- /dev/null
+++ b/pfns4bo/priors/condition_on_area_of_opt_continuous.py
@@ -0,0 +1,76 @@
+import torch
+
+from .prior import Batch
+from ..utils import default_device
+
+
+@torch.no_grad()
+def get_batch(batch_size, seq_len, num_features, get_batch, epoch, device=default_device, hyperparameters={}, **kwargs):
+ """
+ This is not part of the paper, but feel welcome to use this to write a better version of our user prior.
+
+
+ This function assumes that every x is in the range [0, 1].
+ Style shape is (batch_size, 3*num_features) under the assumption that get_batch returns a batch
+ with shape (seq_len, batch_size, num_features).
+ The style is build the following way: [prob_of_feature_1_in_range, range_min_of_feature_1, range_max_of_feature_1, ...]
+
+
+
+ :param batch_size:
+ :param seq_len:
+ :param num_features:
+ :param get_batch:
+ :param epoch:
+ :param device:
+ :param hyperparameters:
+ :param kwargs:
+ :return:
+ """
+
+ maximize = hyperparameters.get('condition_on_area_maximize', True)
+ size_range = hyperparameters.get('condition_on_area_size_range', (0.1, 0.5))
+ distribution = hyperparameters.get('condition_on_area_distribution', 'uniform')
+ assert distribution in ['uniform']
+
+
+ batch: Batch = get_batch(batch_size=batch_size, seq_len=seq_len,
+ num_features=num_features, device=device,
+ hyperparameters=hyperparameters,
+ epoch=epoch, **kwargs)
+ assert batch.style is None
+
+ d = batch.x.shape[2]
+
+ prob_correct = torch.rand(batch_size, d, device=device)
+ correct_opt = torch.rand(batch_size, d, device=device) < prob_correct
+ division_size = torch.rand(batch_size, d, device=device) * (size_range[1] - size_range[0]) + size_range[0]
+
+ optima = batch.target_y.argmax(0).squeeze() if maximize else batch.target_y.argmin(0).squeeze() # batch_size, d
+
+ optima_hints = batch.x[optima, torch.arange(batch_size, device=device)] - division_size/2 + torch.rand(batch_size, d, device=device)*division_size # shape: (batch_size, d)
+ optima_hints = optima_hints.clamp(0, 1)
+
+ optima_division_lower_bound = (optima_hints - division_size/2).clamp(0, 1)
+ optima_division_upper_bound = (optima_hints + division_size/2).clamp(0, 1)
+
+ random_hints = torch.rand(batch_size, d, device=device) - division_size/2 + torch.rand(batch_size, d, device=device)*division_size # shape: (batch_size, d)
+ random_hints = random_hints.clamp(0, 1)
+
+ random_division_lower_bound = (random_hints - division_size/2).clamp(0, 1)
+ random_division_upper_bound = (random_hints + division_size/2).clamp(0, 1)
+
+
+ lower_bounds = torch.where(correct_opt, optima_division_lower_bound, random_division_lower_bound)
+ upper_bounds = torch.where(correct_opt, optima_division_upper_bound, random_division_upper_bound)
+
+ batch.style = torch.stack([prob_correct, lower_bounds, upper_bounds], 2).view(batch_size, -1) # shape: (batch_size, 3*d)
+
+ return batch
+
+
+
+
+
+
+
diff --git a/pfns4bo/priors/fast_gp.py b/pfns4bo/priors/fast_gp.py
new file mode 100644
index 0000000000000000000000000000000000000000..9496b98e19338aea2ef35843043f6ca50d12d054
--- /dev/null
+++ b/pfns4bo/priors/fast_gp.py
@@ -0,0 +1,203 @@
+import time
+
+import torch
+from torch import nn
+import gpytorch
+
+from .prior import Batch
+from .utils import get_batch_to_dataloader
+from ..utils import default_device
+
+
+# We will use the simplest form of GP model, exact inference
+class ExactGPModel(gpytorch.models.ExactGP):
+ def __init__(self, train_x, train_y, likelihood):
+ super(ExactGPModel, self).__init__(train_x, train_y, likelihood)
+ self.mean_module = gpytorch.means.ConstantMean()
+ self.covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.RBFKernel())
+
+ def forward(self, x):
+ mean_x = self.mean_module(x)
+ covar_x = self.covar_module(x)
+ return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)
+
+
+def get_model(x, y, hyperparameters):
+ likelihood = gpytorch.likelihoods.GaussianLikelihood(noise_constraint=gpytorch.constraints.GreaterThan(1.e-9))
+ model = ExactGPModel(x, y, likelihood)
+ model.likelihood.noise = torch.ones_like(model.likelihood.noise) * hyperparameters["noise"]
+ model.covar_module.outputscale = torch.ones_like(model.covar_module.outputscale) * hyperparameters["outputscale"]
+ model.covar_module.base_kernel.lengthscale = torch.ones_like(model.covar_module.base_kernel.lengthscale) * \
+ hyperparameters["lengthscale"]
+ return model, likelihood
+
+
+@torch.no_grad()
+def get_batch(batch_size, seq_len, num_features, device=default_device, hyperparameters=None,
+ equidistant_x=False, fix_x=None, **kwargs):
+ if isinstance(hyperparameters, (tuple, list)):
+ hyperparameters = {"noise": hyperparameters[0]
+ , "outputscale": hyperparameters[1]
+ , "lengthscale": hyperparameters[2]
+ , "is_binary_classification": hyperparameters[3]
+ # , "num_features_used": hyperparameters[4]
+ , "normalize_by_used_features": hyperparameters[5]
+ , "order_y": hyperparameters[6]
+ , "sampling": hyperparameters[7]
+ }
+ elif hyperparameters is None:
+ hyperparameters = {"noise": .1, "outputscale": .1, "lengthscale": .1}
+
+ if 'verbose' in hyperparameters and hyperparameters['verbose']:
+ print({"noise": hyperparameters['noise'], "outputscale": hyperparameters['outputscale']
+ , "lengthscale": hyperparameters['lengthscale'], 'batch_size': batch_size, 'sampling': hyperparameters['sampling']})
+ observation_noise = hyperparameters.get("observation_noise", True)
+
+ # hyperparameters = {k: hyperparameters[k]() if callable(hyperparameters[k]) else hyperparameters[k] for k in
+ # hyperparameters.keys()}
+ assert not (equidistant_x and (fix_x is not None))
+
+ with gpytorch.settings.fast_computations(*hyperparameters.get('fast_computations', (True, True, True))):
+ if equidistant_x:
+ assert num_features == 1
+ x = torch.linspace(0, 1., seq_len).unsqueeze(0).repeat(batch_size, 1).unsqueeze(-1)
+ elif fix_x is not None:
+ assert fix_x.shape == (seq_len, num_features)
+ x = fix_x.unsqueeze(0).repeat(batch_size, 1, 1).to(device)
+ else:
+ if hyperparameters.get('sampling','uniform') == 'uniform':
+ x = torch.rand(batch_size, seq_len, num_features, device=device)
+ elif hyperparameters.get('sampling','uniform') == 'normal':
+ x = torch.randn(batch_size, seq_len, num_features, device=device)
+ elif isinstance(hyperparameters['sampling'], str) and hyperparameters['sampling'].startswith('uniform_'):
+ left_border, right_border = [float(v) for v in hyperparameters['sampling'][len('uniform_'):].split('_')]
+ x = torch.rand(batch_size, seq_len, num_features, device=device) * (right_border - left_border) + left_border
+ elif isinstance(hyperparameters['sampling'], str) and hyperparameters['sampling'].startswith('clustered_'):
+ dist_std, local_dist_std, base_likelihood = [float(v) for v in hyperparameters['sampling'][len('clustered_'):].split('_')]
+
+ def first_sample(dist):
+ return dist().unsqueeze(0)
+
+ def append_sample(samples, dist, local_dist, base_likelihood):
+ if samples is None:
+ return first_sample(dist)
+ num_samples, batch_size, num_features = samples.shape
+ use_base = torch.rand(batch_size) < base_likelihood
+ sample_mean = torch.where(use_base[:, None].repeat(1, num_features),
+ torch.zeros(batch_size, num_features),
+ samples[torch.randint(num_samples, (batch_size,)),
+ torch.arange(batch_size), :])
+ return torch.cat((samples, (local_dist() + sample_mean).unsqueeze(0)), 0)
+
+ def create_sample(num_samples, dist, local_dist, base_likelihood):
+ samples = None
+ for i in range(num_samples):
+ samples = append_sample(samples, dist, local_dist, base_likelihood)
+
+ return samples[torch.randperm(num_samples)]
+
+ x = create_sample(seq_len, lambda: torch.randn(batch_size, num_features)*dist_std,
+ lambda: torch.rand(batch_size, num_features)*local_dist_std, base_likelihood)\
+ .transpose(0,1).to(device)
+ elif isinstance(hyperparameters['sampling'], str) and hyperparameters['sampling'].startswith(
+ 'gmix_'):
+ blob_width, n_centers_max, stddev = [float(v) for v in
+ hyperparameters['sampling'][len('gmix_'):].split('_')]
+ n_centers_max = int(n_centers_max)
+ def get_x(batch_size, n_samples, num_features, blob_width, n_centers_max, stddev, device):
+ n_centers = torch.randint(1, n_centers_max, tuple(), device=device)
+ centers = torch.rand((batch_size, n_centers, num_features), device=device) * blob_width - blob_width / 2
+ center_assignments = torch.randint(n_centers, (batch_size, n_samples,), device=device)
+ noise = torch.randn((batch_size, n_samples, num_features), device=device) * stddev
+ return centers.gather(1, center_assignments[..., None].repeat(1, 1,
+ num_features)) + noise # centers: (b, m, f), ass: (b,n)
+ x = get_x(batch_size, seq_len, num_features, blob_width, n_centers_max, stddev, device)
+ elif isinstance(hyperparameters['sampling'], str) and hyperparameters['sampling'].startswith(
+ 'grep_'):
+ stddev, = [float(v) for v in hyperparameters['sampling'][len('grep_'):].split('_')]
+ x = torch.randn(batch_size, seq_len//2, num_features, device=device) * stddev
+ x = x.repeat(1,2,1)
+ x = x[:,torch.randperm(x.shape[1]),:]
+ else:
+ x = torch.randn(batch_size, seq_len, num_features, device=device) * hyperparameters.get('sampling', 1.)
+ model, likelihood = get_model(x, torch.Tensor(), hyperparameters)
+ model.to(device)
+ # trained_model = ExactGPModel(train_x, train_y, likelihood).cuda()
+ # trained_model.eval()
+ successful_sample = False
+ while not successful_sample:
+ try:
+ with gpytorch.settings.prior_mode(True):
+ model, likelihood = get_model(x, torch.Tensor(), hyperparameters)
+ model.to(device)
+
+ d = model(x)
+ if observation_noise:
+ target_sample = sample = likelihood(d).sample().transpose(0, 1)
+ else:
+ target_sample = d.sample().transpose(0, 1) # this will be the target for the loss
+ sample = likelihood(target_sample).sample() # this will be the input to the Transformer
+ successful_sample = True
+ except RuntimeError: # This can happen when torch.linalg.eigh fails. Restart with new init resolves this.
+ print('GP Sampling unsuccessful, retrying.. ')
+ print(x)
+ print(hyperparameters)
+
+ if bool(torch.any(torch.isnan(x)).detach().cpu().numpy()):
+ print({"noise": hyperparameters['noise'], "outputscale": hyperparameters['outputscale']
+ , "lengthscale": hyperparameters['lengthscale'], 'batch_size': batch_size})
+
+ if hyperparameters.get('improvement_classification', False):
+ single_eval_pos = kwargs['single_eval_pos']
+ max_so_far = sample[:single_eval_pos].max(0).values
+ sample[single_eval_pos:] = (sample > max_so_far).float()[single_eval_pos:]
+
+ return Batch(x=x.transpose(0, 1), y=sample, target_y=target_sample)
+
+DataLoader = get_batch_to_dataloader(get_batch)
+
+def get_model_on_device(x,y,hyperparameters,device):
+ model, likelihood = get_model(x, y, hyperparameters)
+ model.to(device)
+ return model, likelihood
+
+
+@torch.no_grad()
+def evaluate(x, y, y_non_noisy, use_mse=False, hyperparameters={}, get_model_on_device=get_model_on_device, device=default_device, step_size=1, start_pos=0):
+ start_time = time.time()
+ losses_after_t = [.0] if start_pos == 0 else []
+ all_losses_after_t = []
+
+ with gpytorch.settings.fast_computations(*hyperparameters.get('fast_computations',(True,True,True))), gpytorch.settings.fast_pred_var(False):
+ for t in range(max(start_pos, 1), len(x), step_size):
+ loss_sum = 0.
+ model, likelihood = get_model_on_device(x[:t].transpose(0, 1), y[:t].transpose(0, 1), hyperparameters, device)
+
+
+ model.eval()
+ # print([t.shape for t in model.train_inputs])
+ # print(x[:t].transpose(0,1).shape, x[t].unsqueeze(1).shape, y[:t].transpose(0,1).shape)
+ f = model(x[t].unsqueeze(1))
+ l = likelihood(f)
+ means = l.mean.squeeze()
+ varis = l.covariance_matrix.squeeze()
+ # print(l.variance.squeeze(), l.mean.squeeze(), y[t])
+
+ assert len(means.shape) == len(varis.shape) == 1
+ assert len(means) == len(varis) == x.shape[1]
+
+ if use_mse:
+ c = nn.MSELoss(reduction='none')
+ ls = c(means, y[t])
+ else:
+ ls = -l.log_prob(y[t].unsqueeze(1))
+
+ losses_after_t.append(ls.mean())
+ all_losses_after_t.append(ls.flatten())
+ return torch.stack(all_losses_after_t).to('cpu'), torch.tensor(losses_after_t).to('cpu'), time.time() - start_time
+
+if __name__ == '__main__':
+ hps = (.1,.1,.1)
+ for redo_idx in range(1):
+ print(
+ evaluate(*get_batch(1000, 10, hyperparameters=hps, num_features=10), use_mse=False, hyperparameters=hps))
diff --git a/pfns4bo/priors/gp.py b/pfns4bo/priors/gp.py
new file mode 100644
index 0000000000000000000000000000000000000000..8de7aac1e91d7d4510dc120a542bb35274ce75c2
--- /dev/null
+++ b/pfns4bo/priors/gp.py
@@ -0,0 +1,69 @@
+import time
+import random
+
+import torch
+from torch import nn
+from sklearn.gaussian_process import GaussianProcessRegressor
+from sklearn.gaussian_process.kernels import RBF, DotProduct, WhiteKernel
+from .prior import Batch
+from .utils import get_batch_to_dataloader
+
+
+length_scale_sampling_gp = .6
+
+def get_gp(length_scale=None):
+ return GaussianProcessRegressor(
+ kernel=RBF(length_scale=length_scale or length_scale_sampling_gp, length_scale_bounds='fixed'),
+ random_state=0, optimizer=None)
+
+
+def get_batch(batch_size, seq_len, num_features, noisy_std=None, **kwargs):
+ # m = torch.normal(0.,.1,size=(batch_size,num_features))
+ # m2 = torch.rand(batch_size,num_features)
+ # b = 0 # torch.rand(batch_size)
+ x_t = torch.rand(batch_size, seq_len, num_features)
+ # gp_b = TensorGP(kernel=TensorRBF(noisy_std))
+ # y_t = gp_b.sample_from_GP_prior(x_t).detach()
+
+ gpr = get_gp(noisy_std)
+ y_t = torch.zeros(batch_size, seq_len)
+
+ for i in range(len(y_t)):
+ y_t[i] += gpr.sample_y(x_t[i], random_state=random.randint(0, 2 ** 32)).squeeze()
+ x, y = x_t.transpose(0, 1), y_t.transpose(0, 1)
+ # x, _ = torch.sort(x,dim=0)
+ return Batch(x=x, y=y, target_y=y)
+
+
+DataLoader = get_batch_to_dataloader(get_batch)
+
+def evaluate(x, y, y_non_noisy, use_mse=False, length_scale=length_scale_sampling_gp):
+ start_time = time.time()
+ losses_after_t = [.0]
+ for t in range(1, len(x)):
+ loss_sum = 0.
+ for b_i in range(x.shape[1]):
+ gpr = get_gp(length_scale).fit(x[:t, b_i], y[:t, b_i])
+ means, stds = gpr.predict(x[t, b_i].unsqueeze(0), return_std=True)
+ assert len(means) == 1 == len(stds)
+ if use_mse:
+ c = nn.MSELoss()
+ l = c(torch.tensor(means), y[t, b_i].unsqueeze(-1))
+ else:
+ c = nn.GaussianNLLLoss(full=True)
+ l = c(torch.tensor(means), y[t, b_i].unsqueeze(-1),
+ var=torch.tensor(stds) ** 2)
+ loss_sum += l
+
+
+ losses_after_t.append(loss_sum / x.shape[1])
+
+ return torch.tensor(losses_after_t), time.time()-start_time
+
+if __name__ == '__main__':
+ ls = .1
+ for alpha in set([ls, ls * 1.1, ls * .9]):
+ print(alpha)
+ for redo_idx in range(1):
+ print(
+ evaluate(*get_batch(1000, 10, noisy_std=ls, num_features=10), use_mse=False, length_scale=alpha))
\ No newline at end of file
diff --git a/pfns4bo/priors/hebo_prior.py b/pfns4bo/priors/hebo_prior.py
new file mode 100644
index 0000000000000000000000000000000000000000..05d60c47e7011f6c934da41694e04b0b27d051df
--- /dev/null
+++ b/pfns4bo/priors/hebo_prior.py
@@ -0,0 +1,500 @@
+import time
+import functools
+import random
+import math
+import traceback
+import warnings
+
+import numpy as np
+import torch
+from torch import nn
+import gpytorch
+import botorch
+from botorch.models import SingleTaskGP
+from botorch.models.gp_regression import MIN_INFERRED_NOISE_LEVEL
+from botorch.fit import fit_gpytorch_model
+from gpytorch.mlls import ExactMarginalLogLikelihood
+from gpytorch.likelihoods import GaussianLikelihood
+from gpytorch.priors.torch_priors import GammaPrior, UniformPrior, LogNormalPrior
+from gpytorch.means import ZeroMean
+from botorch.models.transforms.input import *
+from gpytorch.constraints import GreaterThan
+
+from . import utils
+from ..utils import default_device, to_tensor
+from .prior import Batch
+from .utils import get_batch_to_dataloader
+
+class Warp(gpytorch.Module):
+ r"""A transform that uses learned input warping functions.
+
+ Each specified input dimension is warped using the CDF of a
+ Kumaraswamy distribution. Typically, MAP estimates of the
+ parameters of the Kumaraswamy distribution, for each input
+ dimension, are learned jointly with the GP hyperparameters.
+
+ for each output in batched multi-output and multi-task models.
+
+ For now, ModelListGPs should be used to learn independent warping
+ functions for each output.
+ """
+
+ _min_concentration_level = 1e-4
+
+ def __init__(
+ self,
+ indices: List[int],
+ transform_on_train: bool = True,
+ transform_on_eval: bool = True,
+ transform_on_fantasize: bool = True,
+ reverse: bool = False,
+ eps: float = 1e-7,
+ concentration1_prior: Optional[Prior] = None,
+ concentration0_prior: Optional[Prior] = None,
+ batch_shape: Optional[torch.Size] = None,
+ ) -> None:
+ r"""Initialize transform.
+
+ Args:
+ indices: The indices of the inputs to warp.
+ transform_on_train: A boolean indicating whether to apply the
+ transforms in train() mode. Default: True.
+ transform_on_eval: A boolean indicating whether to apply the
+ transform in eval() mode. Default: True.
+ transform_on_fantasize: A boolean indicating whether to apply the
+ transform when called from within a `fantasize` call. Default: True.
+ reverse: A boolean indicating whether the forward pass should untransform
+ the inputs.
+ eps: A small value used to clip values to be in the interval (0, 1).
+ concentration1_prior: A prior distribution on the concentration1 parameter
+ of the Kumaraswamy distribution.
+ concentration0_prior: A prior distribution on the concentration0 parameter
+ of the Kumaraswamy distribution.
+ batch_shape: The batch shape.
+ """
+ super().__init__()
+ self.register_buffer("indices", torch.tensor(indices, dtype=torch.long))
+ self.transform_on_train = transform_on_train
+ self.transform_on_eval = transform_on_eval
+ self.transform_on_fantasize = transform_on_fantasize
+ self.reverse = reverse
+ self.batch_shape = batch_shape or torch.Size([])
+ self._X_min = eps
+ self._X_range = 1 - 2 * eps
+ if len(self.batch_shape) > 0:
+ # Note: this follows the gpytorch shape convention for lengthscales
+ # There is ongoing discussion about the extra `1`.
+ # https://github.com/cornellius-gp/gpytorch/issues/1317
+ batch_shape = self.batch_shape + torch.Size([1])
+ else:
+ batch_shape = self.batch_shape
+ for i in (0, 1):
+ p_name = f"concentration{i}"
+ self.register_parameter(
+ p_name,
+ nn.Parameter(torch.full(batch_shape + self.indices.shape, 1.0)),
+ )
+ if concentration0_prior is not None:
+ def closure(m):
+ #print(m.concentration0)
+ return m.concentration0
+ self.register_prior(
+ "concentration0_prior",
+ concentration0_prior,
+ closure,
+ lambda m, v: m._set_concentration(i=0, value=v),
+ )
+ if concentration1_prior is not None:
+ def closure(m):
+ #print(m.concentration1)
+ return m.concentration1
+ self.register_prior(
+ "concentration1_prior",
+ concentration1_prior,
+ closure,
+ lambda m, v: m._set_concentration(i=1, value=v),
+ )
+ for i in (0, 1):
+ p_name = f"concentration{i}"
+ constraint = GreaterThan(
+ self._min_concentration_level,
+ transform=None,
+ # set the initial value to be the identity transformation
+ initial_value=1.0,
+ )
+ self.register_constraint(param_name=p_name, constraint=constraint)
+
+ def _set_concentration(self, i: int, value: Union[float, Tensor]) -> None:
+ if not torch.is_tensor(value):
+ value = torch.as_tensor(value).to(self.concentration0)
+ self.initialize(**{f"concentration{i}": value})
+
+ def _transform(self, X: Tensor) -> Tensor:
+ r"""Warp the inputs through the Kumaraswamy CDF.
+
+ Args:
+ X: A `input_batch_shape x (batch_shape) x n x d`-dim tensor of inputs.
+ batch_shape here can either be self.batch_shape or 1's such that
+ it is broadcastable with self.batch_shape if self.batch_shape is set.
+
+ Returns:
+ A `input_batch_shape x (batch_shape) x n x d`-dim tensor of transformed
+ inputs.
+ """
+ X_tf = expand_and_copy_tensor(X=X, batch_shape=self.batch_shape)
+ k = Kumaraswamy(
+ concentration1=self.concentration1, concentration0=self.concentration0
+ )
+ # normalize to [eps, 1-eps]
+ X_tf[..., self.indices] = k.cdf(
+ torch.clamp(
+ X_tf[..., self.indices] * self._X_range + self._X_min,
+ self._X_min,
+ 1.0 - self._X_min,
+ )
+ )
+ return X_tf
+
+ def _untransform(self, X: Tensor) -> Tensor:
+ r"""Warp the inputs through the Kumaraswamy inverse CDF.
+
+ Args:
+ X: A `input_batch_shape x batch_shape x n x d`-dim tensor of inputs.
+
+ Returns:
+ A `input_batch_shape x batch_shape x n x d`-dim tensor of transformed
+ inputs.
+ """
+ if len(self.batch_shape) > 0:
+ if self.batch_shape != X.shape[-2 - len(self.batch_shape) : -2]:
+ raise BotorchTensorDimensionError(
+ "The right most batch dims of X must match self.batch_shape: "
+ f"({self.batch_shape})."
+ )
+ X_tf = X.clone()
+ k = Kumaraswamy(
+ concentration1=self.concentration1, concentration0=self.concentration0
+ )
+ # unnormalize from [eps, 1-eps] to [0,1]
+ X_tf[..., self.indices] = (
+ (k.icdf(X_tf[..., self.indices]) - self._X_min) / self._X_range
+ ).clamp(0.0, 1.0)
+ return X_tf
+
+ def transform(self, X: Tensor) -> Tensor:
+ r"""Transform the inputs.
+
+ Args:
+ X: A `batch_shape x n x d`-dim tensor of inputs.
+
+ Returns:
+ A `batch_shape x n x d`-dim tensor of transformed inputs.
+ """
+ return self._untransform(X) if self.reverse else self._transform(X)
+
+ def untransform(self, X: Tensor) -> Tensor:
+ r"""Un-transform the inputs.
+
+ Args:
+ X: A `batch_shape x n x d`-dim tensor of inputs.
+
+ Returns:
+ A `batch_shape x n x d`-dim tensor of un-transformed inputs.
+ """
+ return self._transform(X) if self.reverse else self._untransform(X)
+
+ def equals(self, other: InputTransform) -> bool:
+ r"""Check if another input transform is equivalent.
+
+ Note: The reason that a custom equals method is defined rather than
+ defining an __eq__ method is because defining an __eq__ method sets
+ the __hash__ method to None. Hashing modules is currently used in
+ pytorch. See https://github.com/pytorch/pytorch/issues/7733.
+
+ Args:
+ other: Another input transform.
+
+ Returns:
+ A boolean indicating if the other transform is equivalent.
+ """
+ other_state_dict = other.state_dict()
+ return (
+ type(self) == type(other)
+ and (self.transform_on_train == other.transform_on_train)
+ and (self.transform_on_eval == other.transform_on_eval)
+ and (self.transform_on_fantasize == other.transform_on_fantasize)
+ and all(
+ torch.allclose(v, other_state_dict[k].to(v))
+ for k, v in self.state_dict().items()
+ )
+ )
+
+ def preprocess_transform(self, X: Tensor) -> Tensor:
+ r"""Apply transforms for preprocessing inputs.
+
+ The main use cases for this method are 1) to preprocess training data
+ before calling `set_train_data` and 2) preprocess `X_baseline` for noisy
+ acquisition functions so that `X_baseline` is "preprocessed" with the
+ same transformations as the cached training inputs.
+
+ Args:
+ X: A `batch_shape x n x d`-dim tensor of inputs.
+
+ Returns:
+ A `batch_shape x n x d`-dim tensor of (transformed) inputs.
+ """
+ if self.transform_on_train:
+ # We need to disable learning of bounds here.
+ # See why: https://github.com/pytorch/botorch/issues/1078.
+ if hasattr(self, "learn_bounds"):
+ learn_bounds = self.learn_bounds
+ self.learn_bounds = False
+ result = self.transform(X)
+ self.learn_bounds = learn_bounds
+ return result
+ else:
+ return self.transform(X)
+ return X
+
+ def forward(self, X: Tensor) -> Tensor:
+ r"""Transform the inputs to a model.
+
+ Args:
+ X: A `batch_shape x n x d`-dim tensor of inputs.
+
+ Returns:
+ A `batch_shape x n' x d`-dim tensor of transformed inputs.
+ """
+ if self.training:
+ if self.transform_on_train:
+ return self.transform(X)
+ elif self.transform_on_eval:
+ if fantasize.off() or self.transform_on_fantasize:
+ return self.transform(X)
+ return X
+
+def constraint_based_on_distribution_support(prior: torch.distributions.Distribution, device, sample_from_path):
+ if sample_from_path:
+ return None
+
+ if hasattr(prior.support, 'upper_bound'):
+ return gpytorch.constraints.Interval(to_tensor(prior.support.lower_bound,device=device),
+ to_tensor(prior.support.upper_bound,device=device))
+ else:
+ return gpytorch.constraints.GreaterThan(to_tensor(prior.support.lower_bound,device=device))
+
+
+loaded_things = {}
+def torch_load(path):
+ '''
+ Cached torch load. Caution: This does not copy the output but keeps pointers.
+ That means, if you modify the output, you modify the output of later calls to this function with the same args.
+ :param path:
+ :return:
+ '''
+ if path not in loaded_things:
+ print(f'loading {path}')
+ with open(path, 'rb') as f:
+ loaded_things[path] = torch.load(f)
+ return loaded_things[path]
+
+
+def get_model(x, y, hyperparameters: dict, sample=True):
+ sample_from_path = hyperparameters.get('sample_from_extra_prior', None)
+ device = x.device
+ num_features = x.shape[-1]
+ likelihood = gpytorch.likelihoods.GaussianLikelihood(noise_constraint=gpytorch.constraints.Positive())
+ likelihood.register_prior("noise_prior",
+ LogNormalPrior(torch.tensor(hyperparameters.get('hebo_noise_logmean',-4.63), device=device),
+ torch.tensor(hyperparameters.get('hebo_noise_std', 0.5), device=device)
+ ),
+ "noise")
+ lengthscale_prior = \
+ GammaPrior(
+ torch.tensor(hyperparameters['lengthscale_concentration'], device=device),
+ torch.tensor(hyperparameters['lengthscale_rate'], device=device))\
+ if hyperparameters.get('lengthscale_concentration', None) else\
+ UniformPrior(torch.tensor(0.0, device=device), torch.tensor(1.0, device=device))
+ covar_module = gpytorch.kernels.MaternKernel(nu=3 / 2, ard_num_dims=num_features,
+ lengthscale_prior=lengthscale_prior,
+ lengthscale_constraint=\
+ constraint_based_on_distribution_support(lengthscale_prior, device, sample_from_path))
+ # ORIG DIFF: orig lengthscale has no prior
+ #covar_module.register_prior("lengthscale_prior",
+ #UniformPrior(.000000001, 1.),
+ #GammaPrior(concentration=hyperparameters.get('lengthscale_concentration', 1.),
+ # rate=hyperparameters.get('lengthscale_rate', .1)),
+ # skewness is controllled by concentration only, want somthing like concetration in [0.1,1.], rate around [.05,1] seems reasonable
+ #"lengthscale")
+ outputscale_prior = \
+ GammaPrior(concentration=hyperparameters.get('outputscale_concentration', .5),
+ rate=hyperparameters.get('outputscale_rate', 1.))
+ covar_module = gpytorch.kernels.ScaleKernel(covar_module, outputscale_prior=outputscale_prior,
+ outputscale_constraint=constraint_based_on_distribution_support(outputscale_prior, device, sample_from_path))
+
+ if random.random() < float(hyperparameters.get('add_linear_kernel', True)):
+ # ORIG DIFF: added priors for variance and outputscale of linear kernel
+ var_prior = UniformPrior(torch.tensor(0.0, device=device), torch.tensor(1.0, device=device))
+ out_prior = UniformPrior(torch.tensor(0.0, device=device), torch.tensor(1.0, device=device))
+ lincovar_module = gpytorch.kernels.ScaleKernel(
+ gpytorch.kernels.LinearKernel(
+ variance_prior=var_prior,
+ variance_constraint=constraint_based_on_distribution_support(var_prior,device,sample_from_path),
+ ),
+ outputscale_prior=out_prior,
+ outputscale_constraint=constraint_based_on_distribution_support(out_prior,device,sample_from_path),
+ )
+ covar_module = covar_module + lincovar_module
+
+ if hyperparameters.get('hebo_warping', False):
+ # initialize input_warping transformation
+ warp_tf = Warp(
+ indices=list(range(num_features)),
+ # use a prior with median at 1.
+ # when a=1 and b=1, the Kumaraswamy CDF is the identity function
+ concentration1_prior=LogNormalPrior(torch.tensor(0.0, device=device), torch.tensor(hyperparameters.get('hebo_input_warping_c1_std',.75), device=device)),
+ concentration0_prior=LogNormalPrior(torch.tensor(0.0, device=device), torch.tensor(hyperparameters.get('hebo_input_warping_c0_std',.75), device=device)),
+ )
+ else:
+ warp_tf = None
+ # assume mean 0 always!
+ if len(y.shape) < len(x.shape):
+ y = y.unsqueeze(-1)
+ model = botorch.models.SingleTaskGP(x, y, likelihood, covar_module=covar_module, input_transform=warp_tf)
+ model.mean_module = ZeroMean(x.shape[:-2])
+ model.to(device)
+ likelihood.to(device)
+
+ if sample:
+ model = model.pyro_sample_from_prior()
+ if sample_from_path:
+ parameter_sample_distribution = torch_load(sample_from_path) # dict with entries for each parameter
+ idx_for_len = {}
+ for parameter_name, parameter_values in parameter_sample_distribution.items():
+ assert len(parameter_values.shape) == 1
+ try:
+ p = eval(parameter_name)
+ if len(parameter_values) in idx_for_len:
+ idx = idx_for_len[len(parameter_values)].view(p.shape)
+ else:
+ idx = torch.randint(len(parameter_values), p.shape)
+ idx_for_len[len(parameter_values)] = idx
+ new_sample = parameter_values[idx].to(device).view(p.shape) # noqa
+ assert new_sample.shape == p.shape
+ with torch.no_grad():
+ p.data = new_sample
+ except AttributeError:
+ utils.print_once(f'could not find parameter {parameter_name} in model for `sample_from_extra_prior`')
+ model.requires_grad_(False)
+ likelihood.requires_grad_(False)
+ return model, model.likelihood
+ else:
+ assert not(hyperparameters.get('sigmoid', False)) and not(hyperparameters.get('y_minmax_norm', False)), "Sigmoid and y_minmax_norm can only be used to sample models..."
+ return model, likelihood
+
+
+@torch.no_grad()
+def get_batch(batch_size, seq_len, num_features, device=default_device, hyperparameters=None,
+ batch_size_per_gp_sample=None, single_eval_pos=None,
+ fix_to_range=None, equidistant_x=False, verbose=False, **kwargs):
+ '''
+ This function is very similar to the equivalent in .fast_gp. The only difference is that this function operates over
+ a mixture of GP priors.
+ :param batch_size:
+ :param seq_len:
+ :param num_features:
+ :param device:
+ :param hyperparameters:
+ :param for_regression:
+ :return:
+ '''
+ hyperparameters = hyperparameters or {}
+ with gpytorch.settings.fast_computations(*hyperparameters.get('fast_computations',(True,True,True))):
+ batch_size_per_gp_sample = (batch_size_per_gp_sample or max(batch_size // 4,1))
+ assert batch_size % batch_size_per_gp_sample == 0
+
+ total_num_candidates = batch_size*(2**(fix_to_range is not None))
+ num_candidates = batch_size_per_gp_sample * (2**(fix_to_range is not None))
+ unused_feature_likelihood = hyperparameters.get('unused_feature_likelihood', False)
+ if equidistant_x:
+ assert num_features == 1
+ assert not unused_feature_likelihood
+ x = torch.linspace(0,1.,seq_len).unsqueeze(0).repeat(total_num_candidates,1).unsqueeze(-1)
+ else:
+ x = torch.rand(total_num_candidates, seq_len, num_features, device=device)
+ samples = []
+ samples_wo_noise = []
+ for i in range(0, total_num_candidates, num_candidates):
+ local_x = x[i:i+num_candidates]
+ if unused_feature_likelihood:
+ r = torch.rand(num_features)
+ unused_feature_mask = r < unused_feature_likelihood
+ if unused_feature_mask.all():
+ unused_feature_mask[r.argmin()] = False
+ used_local_x = local_x[...,~unused_feature_mask]
+ else:
+ used_local_x = local_x
+ get_model_and_likelihood = lambda: get_model(used_local_x, torch.zeros(num_candidates,x.shape[1], device=device), hyperparameters)
+ model, likelihood = get_model_and_likelihood()
+ if verbose: print(list(model.named_parameters()),
+ (list(model.input_transform.named_parameters()), model.input_transform.concentration1, model.input_transform.concentration0)
+ if model.input_transform is not None else None,
+ )
+
+ # trained_model = ExactGPModel(train_x, train_y, likelihood).cuda()
+ # trained_model.eval()
+ successful_sample = 0
+ throwaway_share = 0.
+ while successful_sample < 1:
+ with gpytorch.settings.prior_mode(True):
+ #print(x.device, device, f'{model.covar_module.base_kernel.lengthscale=}, {model.covar_module.base_kernel.lengthscale.device=}')
+ d = model(used_local_x)
+ try:
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ sample_wo_noise = d.sample()
+ d = likelihood(sample_wo_noise)
+ except (RuntimeError, ValueError) as e:
+ successful_sample -= 1
+ model, likelihood = get_model_and_likelihood()
+ if successful_sample < -100:
+ print(f'Could not sample from model {i} after {successful_sample} attempts. {e}')
+ raise e
+ continue
+ sample = d.sample() # bs_per_gp_s x T
+ if fix_to_range is None:
+ #for k, v in model.named_parameters(): print(k,v)
+ samples.append(sample.transpose(0, 1))
+ samples_wo_noise.append(sample_wo_noise.transpose(0, 1))
+ break
+ smaller_mask = sample < fix_to_range[0]
+ larger_mask = sample >= fix_to_range[1]
+ in_range_mask = ~ (smaller_mask | larger_mask).any(1)
+ throwaway_share += (~in_range_mask[:batch_size_per_gp_sample]).sum()/batch_size_per_gp_sample
+ if in_range_mask.sum() < batch_size_per_gp_sample:
+ successful_sample -= 1
+ if successful_sample < 100:
+ print("Please change hyper-parameters (e.g. decrease outputscale_mean) it"
+ "seems like the range is set to tight for your hyper-parameters.")
+ continue
+
+ x[i:i+batch_size_per_gp_sample] = local_x[in_range_mask][:batch_size_per_gp_sample]
+ sample = sample[in_range_mask][:batch_size_per_gp_sample]
+ samples.append(sample.transpose(0, 1))
+ samples_wo_noise.append(sample_wo_noise.transpose(0, 1))
+ successful_sample = True
+
+ if random.random() < .01:
+ print('throwaway share', throwaway_share/(batch_size//batch_size_per_gp_sample))
+
+ #print(f'took {time.time() - start}')
+ sample = torch.cat(samples, 1)[...,None]
+ sample_wo_noise = torch.cat(samples_wo_noise, 1)[...,None]
+ x = x.view(-1,batch_size,seq_len,num_features)[0]
+ # TODO think about enabling the line below
+ #sample = sample - sample[0, :].unsqueeze(0).expand(*sample.shape)
+ x = x.transpose(0,1)
+ assert x.shape[:2] == sample.shape[:2]
+ return Batch(x=x, y=sample, target_y=sample if hyperparameters.get('observation_noise', True) else sample_wo_noise)
+
+DataLoader = get_batch_to_dataloader(get_batch)
diff --git a/pfns4bo/priors/hyperparameter_sampling.py b/pfns4bo/priors/hyperparameter_sampling.py
new file mode 100644
index 0000000000000000000000000000000000000000..f1befb9b9740da1fb33dce81a0391494bc883c12
--- /dev/null
+++ b/pfns4bo/priors/hyperparameter_sampling.py
@@ -0,0 +1,66 @@
+# this is a wrapper prior that samples hyperparameters which are set to be ConfigSpace parameters
+import torch
+from .prior import Batch
+
+from ConfigSpace import hyperparameters as CSH
+import ConfigSpace as CS
+from copy import deepcopy
+
+
+def list_all_hps_in_nested(config):
+ if isinstance(config, CSH.Hyperparameter):
+ return [config]
+ elif isinstance(config, dict):
+ result = []
+ for k, v in config.items():
+ result += list_all_hps_in_nested(v)
+ return result
+ else:
+ return []
+
+
+def create_configspace_from_hierarchical(config):
+ cs = CS.ConfigurationSpace()
+ for hp in list_all_hps_in_nested(config):
+ cs.add_hyperparameter(hp)
+ return cs
+
+
+def fill_in_configsample(config, configsample):
+ # config is our dict that defines config distribution
+ # configsample is a CS.Configuration
+ hierarchical_configsample = deepcopy(config)
+ for k, v in config.items():
+ if isinstance(v, CSH.Hyperparameter):
+ hierarchical_configsample[k] = configsample[v.name]
+ elif isinstance(v, dict):
+ hierarchical_configsample[k] = fill_in_configsample(v, configsample)
+ return hierarchical_configsample
+
+
+def sample_configspace_hyperparameters(hyperparameters):
+ cs = create_configspace_from_hierarchical(hyperparameters)
+ cs_sample = cs.sample_configuration()
+ return fill_in_configsample(hyperparameters, cs_sample)
+
+
+def get_batch(batch_size, *args, hyperparameters, get_batch, **kwargs):
+ num_models = min(hyperparameters.get('num_hyperparameter_samples_per_batch', 1), batch_size)
+ if num_models == -1:
+ num_models = batch_size
+ assert batch_size % num_models == 0, 'batch_size must be a multiple of num_models'
+ cs = create_configspace_from_hierarchical(hyperparameters)
+ sub_batches = []
+ for i in range(num_models):
+ cs_sample = cs.sample_configuration()
+ hyperparameters_sample = fill_in_configsample(hyperparameters, cs_sample)
+ sub_batch = get_batch(batch_size//num_models, *args, hyperparameters=hyperparameters_sample, **kwargs)
+ sub_batches.append(sub_batch)
+
+ # concat x, y, target (and maybe style)
+ #assert 3 <= len(sub_batch) <= 4
+ #return tuple(torch.cat([sb[i] for sb in sub_batches], dim=(0 if i == 3 else 1)) for i in range(len(sub_batch)))
+ assert all(not b.other_filled_attributes(set_of_attributes=('x', 'y', 'target_y')) for b in sub_batches)
+ return Batch(x=torch.cat([b.x for b in sub_batches], dim=1),
+ y=torch.cat([b.y for b in sub_batches], dim=1),
+ target_y=torch.cat([b.target_y for b in sub_batches], dim=1))
diff --git a/pfns4bo/priors/input_warping.py b/pfns4bo/priors/input_warping.py
new file mode 100644
index 0000000000000000000000000000000000000000..c99e8f999d557d3e3aaedcf4464f295d33ef7978
--- /dev/null
+++ b/pfns4bo/priors/input_warping.py
@@ -0,0 +1,93 @@
+import torch
+from torch.distributions import Kumaraswamy
+
+
+def exp_in_prev_range(x,factor):
+ mini, maxi = x.min(0)[0], x.max(0)[0]
+ expx = (factor*x).exp()
+ expx_01 = (expx - expx.min(0)[0]) / (expx.max(0)[0] - expx.min(0)[0])
+ return expx_01 * (maxi - mini) + mini
+
+
+@torch.no_grad()
+def get_batch(*args, hyperparameters, get_batch, **kwargs):
+ """
+ This `get_batch` can be used to wrap another `get_batch` and apply a Kumaraswamy transform to the input.
+ The x's have to be in [0,1] for this to work!
+ """
+ returns = get_batch(*args, hyperparameters=hyperparameters, **kwargs)
+
+ input_warping_type = hyperparameters.get('input_warping_type', 'kumar')
+ # controls what part of the batch ('x', 'y' or 'xy') to apply the warping to
+ input_warping_groups = hyperparameters.get('input_warping_groups', 'x')
+ # whether to norm inputs between 0 and 1 before warping, as warping is only possible in that range.
+ input_warping_norm = hyperparameters.get('input_warping_norm', False)
+ use_icdf = hyperparameters.get('input_warping_use_icdf', False)
+
+ def norm_to_0_1(x):
+ eps = .00001
+ maxima = torch.max(x, 0)[0]
+ minima = torch.min(x, 0)[0]
+ normed_x = (x - minima) / (maxima - minima + eps)
+
+ def denorm(normed_x):
+ return normed_x * (maxima - minima + eps) + minima
+
+ return normed_x, denorm
+
+ def warp_input(x):
+ if input_warping_norm:
+ x, denorm = norm_to_0_1(x)
+
+ if input_warping_type == 'kumar':
+ if 'input_warping_c_std' in hyperparameters:
+ assert 'input_warping_c0_std' not in hyperparameters and 'input_warping_c1_std' not in hyperparameters
+ hyperparameters['input_warping_c0_std'] = hyperparameters['input_warping_c_std']
+ hyperparameters['input_warping_c1_std'] = hyperparameters['input_warping_c_std']
+ inside = 0
+ while not inside:
+ c1 = (torch.randn(*x.shape[1:], device=x.device) * hyperparameters.get('input_warping_c1_std', .75)).exp()
+ c0 = (torch.randn(*x.shape[1:], device=x.device) * hyperparameters.get('input_warping_c0_std', .75)).exp()
+ if not hyperparameters.get('input_warping_in_range', False):
+ inside = True
+ elif (c1 < 10).all() and (c1 > 0).all() and (c0 < 10).all() and (c0 > 0).all():
+ inside = True
+ else:
+ inside -= 1
+ if inside < -100:
+ print('It seems that the input warping is not working.')
+ if c1_v := hyperparameters.get('fix_input_warping_c1', False):
+ c1[:] = c1_v
+ if c0_v := hyperparameters.get('fix_input_warping_c0', False):
+ c0[:] = c0_v
+ if hyperparameters.get('verbose', False):
+ print(f'c1: {c1}, c0: {c0}')
+ k = Kumaraswamy(concentration1=c1, concentration0=c0)
+ x_transformed = k.icdf(x) if use_icdf else k.cdf(x)
+ elif input_warping_type == 'exp':
+ transform_likelihood = hyperparameters.get('input_warping_transform_likelihood', 0.2)
+ to_be_transformed = torch.rand_like(x[0,0]) < transform_likelihood
+ transform_factors = torch.rand_like(x[0,0]) * hyperparameters.get('input_warping_transform_factor', 1.)
+ log_direction = torch.rand_like(x[0,0]) < 0.5
+ exp_x = exp_in_prev_range(x, transform_factors)
+ minus_exp_x = 1.-exp_in_prev_range(1.-x, transform_factors)
+ exp_x = torch.where(log_direction, exp_x, minus_exp_x)
+ x_transformed = torch.where(to_be_transformed[None,None,:], exp_x, x)
+ elif input_warping_type is None or input_warping_type == 'none':
+ x_transformed = x
+ else:
+ raise ValueError(f"Unknown input_warping_type: {input_warping_type}")
+
+ if input_warping_norm:
+ x_transformed = denorm(x_transformed)
+ return x_transformed
+
+ if 'x' in input_warping_groups:
+ returns.x = warp_input(returns.x)
+ if 'y' in input_warping_groups:
+ returns.y = warp_input(returns.y)
+ returns.target_y = warp_input(returns.target_y)
+
+ return returns
+
+
diff --git a/pfns4bo/priors/nonmyopic_bo.py b/pfns4bo/priors/nonmyopic_bo.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ac8e4463d6351c3a68f10ff507d45941635ae64
--- /dev/null
+++ b/pfns4bo/priors/nonmyopic_bo.py
@@ -0,0 +1,159 @@
+import torch
+
+from .prior import Batch
+from ..utils import default_device
+
+
+loaded_models = {}
+
+def get_model(model_name, device):
+ if model_name not in loaded_models:
+ import submitit
+ group, index = model_name.split(':')
+ ex = submitit.get_executor()
+ model = ex.get_group(group)[int(index)].results()[0][2]
+ model.to(device)
+ loaded_models[model_name] = model
+ return loaded_models[model_name]
+
+@torch.no_grad()
+def get_batch(batch_size, seq_len, num_features, get_batch, model, single_eval_pos, epoch, device=default_device, hyperparameters=None, **kwargs):
+ """
+ Important Assumptions:
+ 'inf_batch_size', 'max_level', 'sample_only_one_level', 'eval_seq_len' and 'epochs_per_level' in hyperparameters
+
+ You can train a new model, based on an old one to only sample from a single level.
+ You specify `level_0_model` as a group:index string and the model will be loaded from the checkpoint.
+
+
+
+ :param batch_size:
+ :param seq_len:
+ :param num_features:
+ :param get_batch:
+ :param model:
+ :param single_eval_pos:
+ :param epoch:
+ :param device:
+ :param hyperparameters:
+ :param kwargs:
+ :return:
+ """
+ if level_0_model := hyperparameters.get('level_0_model', None):
+ assert hyperparameters['sample_only_one_level'], "level_0_model only makes sense if you sample only one level"
+ assert hyperparameters['max_level'] == 1, "level_0_model only makes sense if you sample only one level"
+ level_0_model = get_model(level_0_model, device)
+ model = level_0_model
+
+ # the level describes how many fantasized steps are possible. This starts at 0 for the first epochs.
+ epochs_per_level = hyperparameters['epochs_per_level']
+ share_predict_mean_distribution = hyperparameters.get('share_predict_mean_distribution', 0.)
+ use_mean_prediction = share_predict_mean_distribution or\
+ (model.decoder_dict_once is not None and 'mean_prediction' in model.decoder_dict_once)
+ num_evals = seq_len - single_eval_pos
+ level = min(min(epoch // epochs_per_level, hyperparameters['max_level']), num_evals - 1)
+ if level_0_model:
+ level = 1
+ eval_seq_len = hyperparameters['eval_seq_len']
+ add_seq_len = 0 if use_mean_prediction else eval_seq_len
+ long_seq_len = seq_len + add_seq_len
+
+ if level_0_model:
+ styles = torch.ones(batch_size, 1, device=device, dtype=torch.long)
+ elif hyperparameters['sample_only_one_level']:
+ styles = torch.randint(level + 1, (1, 1), device=device).repeat(batch_size, 1) # styles are sorted :)
+ else:
+ styles = torch.randint(level + 1, (batch_size,1), device=device).sort(0).values # styles are sorted :)
+
+ predict_mean_distribution = None
+ if share_predict_mean_distribution:
+ max_used_level = max(styles)
+ # below code assumes epochs are base 0!
+ share_of_training = epoch / epochs_per_level
+ #print(share_of_training, (max_used_level + 1. - share_predict_mean_distribution), max_used_level, level, epoch)
+ predict_mean_distribution = (share_of_training >= (max_used_level + 1. - share_predict_mean_distribution)) and (max_used_level < hyperparameters['max_level'])
+
+ x, y, targets = [], [], []
+
+ for considered_level in range(level+1):
+ num_elements = (styles == considered_level).sum()
+ if not num_elements:
+ continue
+ returns: Batch = get_batch(batch_size=num_elements, seq_len=long_seq_len,
+ num_features=num_features, device=device,
+ hyperparameters=hyperparameters, model=model,
+ single_eval_pos=single_eval_pos, epoch=epoch,
+ **kwargs)
+ levels_x, levels_y, levels_targets = returns.x, returns.y, returns.target_y
+ assert not returns.other_filled_attributes(), f"Unexpected filled attributes: {returns.other_filled_attributes()}"
+
+ assert levels_y is levels_targets
+ levels_targets = levels_targets.clone()
+ if len(levels_y.shape) == 2:
+ levels_y = levels_y.unsqueeze(2)
+ levels_targets = levels_targets.unsqueeze(2)
+ if considered_level > 0:
+
+ feed_x = levels_x[:single_eval_pos + 1 + add_seq_len].repeat(1, num_evals, 1)
+ feed_x[single_eval_pos, :] = levels_x[single_eval_pos:seq_len].reshape(-1, *levels_x.shape[2:])
+ if not use_mean_prediction:
+ feed_x[single_eval_pos + 1:] = levels_x[seq_len:].repeat(1, num_evals, 1)
+
+ feed_y = levels_y[:single_eval_pos + 1 + add_seq_len].repeat(1, num_evals, 1)
+ feed_y[single_eval_pos, :] = levels_y[single_eval_pos:seq_len].reshape(-1, *levels_y.shape[2:])
+ if not use_mean_prediction:
+ feed_y[single_eval_pos + 1:] = levels_y[seq_len:].repeat(1, num_evals, 1)
+
+ model.eval()
+ means = []
+ for feed_x_b, feed_y_b in zip(torch.split(feed_x, hyperparameters['inf_batch_size'], dim=1),
+ torch.split(feed_y, hyperparameters['inf_batch_size'], dim=1)):
+ with torch.cuda.amp.autocast():
+ style = torch.zeros(feed_x_b.shape[1], 1, dtype=torch.int64, device=device) + considered_level - 1
+ if level_0_model is not None and level_0_model.style_encoder is None:
+ style = None
+ out = model(
+ (style, feed_x_b, feed_y_b),
+ single_eval_pos=single_eval_pos+1, only_return_standard_out=False
+ )
+ if isinstance(out, tuple):
+ output, once_output = out
+ else:
+ output = out
+ once_output = {}
+
+ if once_output and 'mean_prediction' in once_output:
+ mean_pred_logits = once_output['mean_prediction'].float()
+ assert tuple(mean_pred_logits.shape) == (feed_x_b.shape[1], model.criterion.num_bars),\
+ f"{tuple(mean_pred_logits.shape)} vs {(feed_x_b.shape[1], model.criterion.num_bars)}"
+ means.append(model.criterion.icdf(mean_pred_logits, 1.-1./eval_seq_len))
+ else:
+ logits = output['standard'].float()
+ means.append(model.criterion.mean(logits).max(0).values)
+ means = torch.cat(means, 0)
+ levels_targets_new = means.view(seq_len-single_eval_pos, *levels_y.shape[1:])
+ levels_targets[single_eval_pos:seq_len] = levels_targets_new #- levels_targets_new.mean(0)
+ model.train()
+
+ levels_x = levels_x[:seq_len]
+ levels_y = levels_y[:seq_len]
+ levels_targets = levels_targets[:seq_len]
+
+ x.append(levels_x)
+ y.append(levels_y)
+ targets.append(levels_targets)
+
+ x = torch.cat(x, 1)
+ # if predict_mean_distribution: print(f'predict mean dist in b, {epoch=}, {max_used_level=}')
+ return Batch(x=x, y=torch.cat(y, 1), target_y=torch.cat(targets, 1), style=styles,
+ mean_prediction=predict_mean_distribution.item() if predict_mean_distribution is not None else None)
+
+
+
+
+
+
+
+
+
+
diff --git a/pfns4bo/priors/normalize_with_style.py b/pfns4bo/priors/normalize_with_style.py
new file mode 100644
index 0000000000000000000000000000000000000000..d1bc34982d5f84e161706211006ac1c3815c1cd6
--- /dev/null
+++ b/pfns4bo/priors/normalize_with_style.py
@@ -0,0 +1,59 @@
+import torch
+
+from ..utils import default_device
+
+
+@torch.no_grad()
+def get_batch(batch_size, seq_len, num_features, get_batch, model, single_eval_pos, epoch, device=default_device, hyperparameters={}, **kwargs):
+ if hyperparameters.get('normalize_x', False):
+ uniform_float = torch.rand(tuple()).clamp(.1,1.).item()
+ new_hyperparameters = {**hyperparameters, 'sampling': uniform_float * hyperparameters['sampling']}
+ else:
+ new_hyperparameters = hyperparameters
+ returns = get_batch(batch_size=batch_size, seq_len=seq_len,
+ num_features=num_features, device=device,
+ hyperparameters=new_hyperparameters, model=model,
+ single_eval_pos=single_eval_pos, epoch=epoch, **kwargs)
+
+ style = []
+
+ if normalize_x_mode := hyperparameters.get('normalize_x', False):
+ returns.x, mean_style, std_style = normalize_data_by_first_k(returns.x, single_eval_pos if normalize_x_mode == 'train' else len(returns.x))
+ if hyperparameters.get('style_includes_mean_from_normalization', True) or normalize_x_mode == 'train':
+ style.append(mean_style)
+ style.append(std_style)
+
+ if hyperparameters.get('normalize_y', False):
+ returns.y, mean_style, std_style = normalize_data_by_first_k(returns.y, single_eval_pos)
+ style += [mean_style, std_style]
+
+ returns.style = torch.cat(style,1) if style else None
+ return returns
+
+
+def normalize_data_by_first_k(x, k):
+ # x has shape seq_len, batch_size, num_features or seq_len, num_features
+ # k is the number of elements to normalize by
+ unsqueezed_x = False
+ if len(x.shape) == 2:
+ x.unsqueeze_(2)
+ unsqueezed_x = True
+
+ if k > 1:
+ relevant_x = x[:k]
+ mean_style = relevant_x.mean(0)
+ std_style = relevant_x.std(0)
+ x = (x - relevant_x.mean(0, keepdim=True)) / relevant_x.std(0, keepdim=True)
+ elif k == 1:
+ mean_style = x[0]
+ std_style = torch.ones_like(x[0])
+ x = (x - x[0])
+ else: # it is 0
+ mean_style = torch.zeros_like(x[0])
+ std_style = torch.ones_like(x[0])
+
+ if unsqueezed_x:
+ x.squeeze_(2)
+
+ return x, mean_style, std_style
+
diff --git a/pfns4bo/priors/prior.py b/pfns4bo/priors/prior.py
new file mode 100644
index 0000000000000000000000000000000000000000..abd3779fd8e137bd7ed7e7fce6d30fd5484f42dd
--- /dev/null
+++ b/pfns4bo/priors/prior.py
@@ -0,0 +1,98 @@
+from abc import ABCMeta, abstractmethod
+from typing import Set, Optional
+from dataclasses import dataclass, fields
+import torch
+from torch.utils.data import DataLoader
+
+@dataclass
+class Batch:
+ """
+ A batch of data, with non-optional x, y, and target_y attributes.
+ All other attributes are optional.
+
+ If you want to add an attribute for testing only, you can just assign it after creation like:
+ ```
+ batch = Batch(x=x, y=y, target_y=target_y)
+ batch.test_attribute = test_attribute
+ ```
+ """
+ # Required entries
+ x: torch.Tensor
+ y: torch.Tensor
+ target_y: torch.Tensor
+
+ # Optional Batch Entries
+ style: Optional[torch.Tensor] = None
+ style_hyperparameter_values: Optional[torch.Tensor] = None
+ single_eval_pos: Optional[torch.Tensor] = None
+ causal_model_dag: Optional[object] = None
+ mean_prediction: Optional[bool] = None # this controls whether to do mean prediction in bar_distribution for nonmyopic BO
+
+ def other_filled_attributes(self, set_of_attributes: Set[str] = frozenset(('x', 'y', 'target_y'))):
+ return [f.name for f in fields(self)
+ if f.name not in set_of_attributes and
+ getattr(self, f.name) is not None]
+
+
+def safe_merge_batches_in_batch_dim(*batches, ignore_attributes=[]):
+ """
+ Merge all supported non-None fields in a pre-specified (general) way,
+ e.g. mutliple batch.x are concatenated in the batch dimension.
+ :param ignore_attributes: attributes to remove from the merged batch, treated as if they were None.
+ :return:
+ """
+ not_none_fields = [f.name for f in fields(batches[0]) if f.name not in ignore_attributes and getattr(batches[0], f.name) is not None]
+ assert all([set(not_none_fields) == set([f.name for f in fields(b) if f.name not in ignore_attributes and getattr(b, f.name) is not None]) for b in batches]), 'All batches must have the same fields!'
+ merge_funcs = {
+ 'x': lambda xs: torch.cat(xs, 1),
+ 'y': lambda ys: torch.cat(ys, 1),
+ 'target_y': lambda target_ys: torch.cat(target_ys, 1),
+ 'style': lambda styles: torch.cat(styles, 0),
+ }
+ assert all(f in merge_funcs for f in not_none_fields), f'Unknown fields encountered in `safe_merge_batches_in_batch_dim`.'
+ return Batch(**{f: merge_funcs[f]([getattr(batch, f) for batch in batches]) for f in not_none_fields})
+
+
+def merge_batches(*batches, ignore_attributes=[]):
+ assert False, "TODO: isn't this broken!? because catting in dim 0 seems wrong!?"
+ def merge_attribute(attr_name, batch_sizes):
+ attr = [getattr(batch, attr_name) for batch in batches]
+ if type(attr[0]) is list:
+ def make_list(sublist, i):
+ if sublist is None:
+ return [None for _ in range(batch_sizes[i])]
+ return sublist
+ return sum([make_list(sublist, i) for i, sublist in enumerate(attr)], [])
+ elif type(attr[0]) is torch.Tensor:
+ return torch.cat(attr, 0)
+ else:
+ assert all(a is None for a in attr), f'Unknown type encountered in `merge_batches`.'\
+ f'To ignore this, please add `{attr}` to the `ignore_attributes`.'\
+ f'The following values are the problem: {attr_name}.'
+ return None
+ batch_sizes = [batch.x.shape[0] for batch in batches]
+ return Batch(**{f.name: merge_attribute(f.name, batch_sizes) for f in fields(batches[0]) if f.name not in ignore_attributes})
+
+
+
+class PriorDataLoader(DataLoader, metaclass=ABCMeta):
+ @abstractmethod
+ def __init__(self, num_steps, batch_size, eval_pos_seq_len_sampler, seq_len_maximum, device, **kwargs):
+ """
+
+ :param num_steps: int, first argument, the number of steps to take per epoch, i.e. iteration of the DataLoader
+ :param batch_size: int, number of datasets per batch
+ :param eval_pos_seq_len_sampler: callable, it takes no arguments and returns a tuple (single eval pos, bptt)
+ :param kwargs: for future compatibility it is good to have a final all catch, as new kwargs might be introduced
+ """
+ pass
+
+ # A class or object variable `num_features`: int
+ # Optional: `validate` function that accepts a transformer model
+
+ # The DataLoader iter should return batches of the form ([style], x, y), target_y, single_eval_pos
+ # We follow sequence len (s) first, batch size (b) second. So x: (s,b,num_features), y,target_y: (s,b)
+ # and style: Optional[(b,num_style_params)], style can be omitted or set to None, if it is not intended to be used.
+
+ # For more references, see `priors/utils.py` for a pretty general implementation of a DataLoader
+ # and `train.py` for the only call of it.
diff --git a/pfns4bo/priors/prior_bag.py b/pfns4bo/priors/prior_bag.py
new file mode 100644
index 0000000000000000000000000000000000000000..6d954b650502566f504da62705e48a02f21b3579
--- /dev/null
+++ b/pfns4bo/priors/prior_bag.py
@@ -0,0 +1,45 @@
+from typing import List
+import torch
+
+import utils
+from .prior import Batch
+from .utils import get_batch_to_dataloader
+from ..utils import default_device
+
+def get_batch(batch_size, seq_len, num_features, device=default_device
+ , hyperparameters=None, batch_size_per_gp_sample=None, **kwargs):
+ batch_size_per_gp_sample = batch_size_per_gp_sample or (min(64, batch_size))
+ num_models = batch_size // batch_size_per_gp_sample
+ assert num_models * batch_size_per_gp_sample == batch_size, f'Batch size ({batch_size}) not divisible by batch_size_per_gp_sample ({batch_size_per_gp_sample})'
+
+ args = {'device': device,
+ 'seq_len': seq_len,
+ 'num_features': num_features,
+ 'batch_size': batch_size_per_gp_sample}
+
+ prior_bag_priors_get_batch = hyperparameters['prior_bag_get_batch']
+ prior_bag_priors_p = [1.0] + [hyperparameters[f'prior_bag_exp_weights_{i}'] for i in range(1, len(prior_bag_priors_get_batch))]
+
+ weights = torch.tensor(prior_bag_priors_p, dtype=torch.float) # create a tensor of weights
+ batch_assignments = torch.multinomial(torch.softmax(weights, 0), num_models, replacement=True).numpy()
+
+ if 'verbose' in hyperparameters and hyperparameters['verbose']:
+ print('PRIOR_BAG:', weights, batch_assignments, num_models, batch_size_per_gp_sample, batch_size)
+
+ sample: List[Batch] = \
+ [prior_bag_priors_get_batch[int(prior_idx)](hyperparameters=hyperparameters, **args, **kwargs) for prior_idx in batch_assignments]
+
+ def merge(sample, k):
+ x = [getattr(x_,k) for x_ in sample]
+ if torch.is_tensor(x[0]):
+ return torch.cat(x, 1).detach()
+ else:
+ return [*x]
+ utils.print_once('prior bag, merging attributes', [s.other_filled_attributes([]) for s in sample])
+ sample = {k: merge(sample, k) for k in sample[0].other_filled_attributes([])}
+ if hyperparameters.get('verbose'):
+ print({k: v.shape for k,v in sample.items()})
+
+ return Batch(**sample)
+
+DataLoader = get_batch_to_dataloader(get_batch)
\ No newline at end of file
diff --git a/pfns4bo/priors/simple_mlp.py b/pfns4bo/priors/simple_mlp.py
new file mode 100644
index 0000000000000000000000000000000000000000..804179d16c1e77be89184f6384cb9d477de0f6ca
--- /dev/null
+++ b/pfns4bo/priors/simple_mlp.py
@@ -0,0 +1,126 @@
+import random
+import math
+
+import torch
+from torch import nn
+import time
+import numpy as np
+
+from ..utils import default_device
+from .prior import Batch
+from .utils import get_batch_to_dataloader
+
+
+class MLP(torch.nn.Module):
+ def __init__(self, num_inputs, num_layers, num_hidden, num_outputs, init_std=None, sparseness=0.0,
+ preactivation_noise_std=0.0, activation='tanh'):
+ super(MLP, self).__init__()
+ self.linears = nn.ModuleList(
+ [nn.Linear(num_inputs, num_hidden)] + \
+ [nn.Linear(num_hidden,num_hidden) for _ in range(num_layers-2)] + \
+ [nn.Linear(num_hidden,num_outputs)]
+ )
+
+ self.init_std = init_std
+ self.sparseness = sparseness
+ self.reset_parameters()
+
+ self.preactivation_noise_std = preactivation_noise_std
+ self.activation = {
+ 'tanh': torch.nn.Tanh(),
+ 'relu': torch.nn.ReLU(),
+ 'elu': torch.nn.ELU(),
+ 'identity': torch.nn.Identity(),
+ }[activation]
+
+ def reset_parameters(self, init_std=None, sparseness=None):
+ init_std = init_std if init_std is not None else self.init_std
+ sparseness = sparseness if sparseness is not None else self.sparseness
+ for linear in self.linears:
+ linear.reset_parameters()
+
+ with torch.no_grad():
+ if init_std is not None:
+ for linear in self.linears:
+ linear.weight.normal_(0, init_std)
+ linear.bias.normal_(0, init_std)
+
+ if sparseness > 0.0:
+ for linear in self.linears[1:-1]:
+ linear.weight /= (1. - sparseness) ** (1 / 2)
+ linear.weight *= torch.bernoulli(torch.ones_like(linear.weight) * (1. - sparseness))
+
+ def forward(self, x):
+ for linear in self.linears[:-1]:
+ x = linear(x)
+ x = x + torch.randn_like(x) * self.preactivation_noise_std
+ x = torch.tanh(x)
+ x = self.linears[-1](x)
+ return x
+
+
+def sample_input(input_sampling_setting, batch_size, seq_len, num_features, device=default_device):
+ if input_sampling_setting == 'normal':
+ x = torch.randn(batch_size, seq_len, num_features, device=device)
+ x_for_mlp = x
+ elif input_sampling_setting == 'uniform':
+ x = torch.rand(batch_size, seq_len, num_features, device=device)
+ x_for_mlp = (x - .5)/math.sqrt(1/12)
+ else:
+ raise ValueError(f"Unknown input_sampling: {input_sampling_setting}")
+ return x, x_for_mlp
+
+
+@torch.no_grad()
+def get_batch(batch_size, seq_len, num_features, hyperparameters, device=default_device, num_outputs=1, **kwargs):
+ if hyperparameters is None:
+ hyperparameters = {
+ 'mlp_num_layers': 2,
+ 'mlp_num_hidden': 64,
+ 'mlp_init_std': 0.1,
+ 'mlp_sparseness': 0.2,
+ 'mlp_input_sampling': 'normal',
+ 'mlp_output_noise': 0.0,
+ 'mlp_noisy_targets': False,
+ 'mlp_preactivation_noise_std': 0.0,
+ }
+
+ x, x_for_mlp = sample_input(hyperparameters.get('mlp_input_sampling', 'normal'), batch_size, seq_len, num_features,
+ device=device)
+
+ model = MLP(num_features, hyperparameters['mlp_num_layers'], hyperparameters['mlp_num_hidden'],
+ num_outputs, hyperparameters['mlp_init_std'], hyperparameters['mlp_sparseness'],
+ hyperparameters['mlp_preactivation_noise_std'], hyperparameters.get('activation', 'tanh')).to(device)
+
+ no_noise_model = MLP(num_features, hyperparameters['mlp_num_layers'], hyperparameters['mlp_num_hidden'],
+ num_outputs, hyperparameters['mlp_init_std'], hyperparameters['mlp_sparseness'],
+ 0., hyperparameters.get('activation', 'tanh')).to(device)
+
+ ys = []
+ targets = []
+ for x_ in x_for_mlp:
+ model.reset_parameters()
+ y = model(x_ / math.sqrt(num_features))
+ ys.append(y.unsqueeze(1))
+ if not hyperparameters.get('mlp_preactivation_noise_in_targets', True):
+ assert not hyperparameters['mlp_noisy_targets']
+ no_noise_model.load_state_dict(model.state_dict())
+ target = no_noise_model(x_ / math.sqrt(num_features))
+ targets.append(target.unsqueeze(1))
+
+ y = torch.cat(ys, dim=1)
+ targets = torch.cat(targets, dim=1) if targets else y
+
+ noisy_y = y + torch.randn_like(y) * hyperparameters['mlp_output_noise']
+
+ #return x.transpose(0, 1), noisy_y, (noisy_y if hyperparameters['mlp_noisy_targets'] else targets)
+ return Batch(x.transpose(0, 1), noisy_y, (noisy_y if hyperparameters['mlp_noisy_targets'] else targets))
+
+DataLoader = get_batch_to_dataloader(get_batch)
+
+
+
+
+
+
+
diff --git a/pfns4bo/priors/utils.py b/pfns4bo/priors/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..efe4925e0d55659b9fe9ed8dd5bbf0590eceeea1
--- /dev/null
+++ b/pfns4bo/priors/utils.py
@@ -0,0 +1,277 @@
+import time
+import types
+import inspect
+import random
+from functools import partial
+
+import torch
+
+from ..utils import set_locals_in_self, normalize_data
+from .prior import PriorDataLoader, Batch
+from torch import nn
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.gridspec as gridspec
+import scipy.stats as stats
+import math
+
+def get_batch_to_dataloader(get_batch_method_):
+ #DL = partial(DL, get_batch_method=get_batch_method_)
+ class DL(PriorDataLoader):
+ get_batch_method = get_batch_method_
+
+ # Caution, you might need to set self.num_features manually if it is not part of the args.
+ def __init__(self, num_steps, **get_batch_kwargs):
+ set_locals_in_self(locals())
+
+ # The stuff outside the or is set as class attribute before instantiation.
+ self.num_features = get_batch_kwargs.get('num_features') or self.num_features
+ self.epoch_count = 0
+ print('DataLoader.__dict__', self.__dict__)
+
+ @staticmethod
+ def gbm(*args, eval_pos_seq_len_sampler, **kwargs):
+ kwargs['single_eval_pos'], kwargs['seq_len'] = eval_pos_seq_len_sampler()
+ # Scales the batch size dynamically with the power of 'dynamic_batch_size'.
+ # A transformer with quadratic memory usage in the seq len would need a power of 2 to keep memory constant.
+ if 'dynamic_batch_size' in kwargs and kwargs['dynamic_batch_size'] > 0 and kwargs['dynamic_batch_size'] is not None:
+ kwargs['batch_size'] = kwargs['batch_size'] * math.floor(
+ math.pow(kwargs['seq_len_maximum'], kwargs['dynamic_batch_size'])
+ / math.pow(kwargs['seq_len'], kwargs['dynamic_batch_size'])
+ )
+ batch: Batch = get_batch_method_(*args, **kwargs)
+ if batch.single_eval_pos is None:
+ batch.single_eval_pos = kwargs['single_eval_pos']
+ return batch
+
+ def __len__(self):
+ return self.num_steps
+
+ def get_test_batch(self, **kwargs): # does not increase epoch_count
+ return self.gbm(**self.get_batch_kwargs, epoch=self.epoch_count, model=self.model if hasattr(self, 'model') else None, **kwargs)
+
+ def __iter__(self):
+ assert hasattr(self, 'model'), "Please assign model with `dl.model = ...` before training."
+ self.epoch_count += 1
+ return iter(self.gbm(**self.get_batch_kwargs, epoch=self.epoch_count - 1, model=self.model) for _ in range(self.num_steps))
+
+ return DL
+
+
+def plot_features(data, targets, fig=None, categorical=True, plot_diagonal=True):
+ import seaborn as sns
+ if torch.is_tensor(data):
+ data = data.detach().cpu().numpy()
+ targets = targets.detach().cpu().numpy()
+
+ fig2 = fig if fig else plt.figure(figsize=(8, 8))
+ spec2 = gridspec.GridSpec(ncols=data.shape[1], nrows=data.shape[1], figure=fig2)
+ for d in range(0, data.shape[1]):
+ for d2 in range(0, data.shape[1]):
+ if d > d2:
+ continue
+ sub_ax = fig2.add_subplot(spec2[d, d2])
+ sub_ax.set_xticks([])
+ sub_ax.set_yticks([])
+ if d == d2:
+ if plot_diagonal:
+ if categorical:
+ sns.histplot(data[:, d],hue=targets[:],ax=sub_ax,legend=False, palette="deep")
+ else:
+ sns.histplot(data[:, d], ax=sub_ax, legend=False)
+ sub_ax.set(ylabel=None)
+ else:
+ if categorical:
+ sns.scatterplot(x=data[:, d], y=data[:, d2],
+ hue=targets[:],legend=False, palette="deep")
+ else:
+ sns.scatterplot(x=data[:, d], y=data[:, d2],
+ hue=targets[:], legend=False)
+ #plt.scatter(data[:, d], data[:, d2],
+ # c=targets[:])
+ #sub_ax.get_xaxis().set_ticks([])
+ #sub_ax.get_yaxis().set_ticks([])
+ plt.subplots_adjust(wspace=0.05, hspace=0.05)
+ fig2.show()
+
+
+def plot_prior(prior, samples=1000, buckets=50):
+ s = np.array([prior() for _ in range(0, samples)])
+ count, bins, ignored = plt.hist(s, buckets, density=True)
+ print(s.min())
+ plt.show()
+
+trunc_norm_sampler_f = lambda mu, sigma : lambda: stats.truncnorm((0 - mu) / sigma, (1000000 - mu) / sigma, loc=mu, scale=sigma).rvs(1)[0]
+beta_sampler_f = lambda a, b : lambda : np.random.beta(a, b)
+gamma_sampler_f = lambda a, b : lambda : np.random.gamma(a, b)
+uniform_sampler_f = lambda a, b : lambda : np.random.uniform(a, b)
+uniform_int_sampler_f = lambda a, b : lambda : round(np.random.uniform(a, b))
+def zipf_sampler_f(a, b, c):
+ x = np.arange(b, c)
+ weights = x ** (-a)
+ weights /= weights.sum()
+ return lambda : stats.rv_discrete(name='bounded_zipf', values=(x, weights)).rvs(1)
+scaled_beta_sampler_f = lambda a, b, scale, minimum : lambda : minimum + round(beta_sampler_f(a, b)() * (scale - minimum))
+
+
+def normalize_by_used_features_f(x, num_features_used, num_features, normalize_with_sqrt=False):
+ if normalize_with_sqrt:
+ return x / (num_features_used / num_features)**(1 / 2)
+ return x / (num_features_used / num_features)
+
+
+def order_by_y(x, y):
+ order = torch.argsort(y if random.randint(0, 1) else -y, dim=0)[:, 0, 0]
+ order = order.reshape(2, -1).transpose(0, 1).reshape(-1)#.reshape(seq_len)
+ x = x[order] # .reshape(2, -1).transpose(0, 1).reshape(-1).flip([0]).reshape(seq_len, 1, -1)
+ y = y[order] # .reshape(2, -1).transpose(0, 1).reshape(-1).reshape(seq_len, 1, -1)
+
+ return x, y
+
+def randomize_classes(x, num_classes):
+ classes = torch.arange(0, num_classes, device=x.device)
+ random_classes = torch.randperm(num_classes, device=x.device).type(x.type())
+ x = ((x.unsqueeze(-1) == classes) * random_classes).sum(-1)
+ return x
+
+@torch.no_grad()
+def sample_num_feaetures_get_batch(batch_size, seq_len, num_features, hyperparameters, get_batch, **kwargs):
+ if hyperparameters.get('sample_num_features', True) and kwargs['epoch'] > 0: # don't sample on test batch
+ num_features = random.randint(1, num_features)
+ return get_batch(batch_size, seq_len, num_features, hyperparameters=hyperparameters, **kwargs)
+
+
+class CategoricalActivation(nn.Module):
+ def __init__(self, categorical_p=0.1, ordered_p=0.7
+ , keep_activation_size=False
+ , num_classes_sampler=zipf_sampler_f(0.8, 1, 10)):
+ self.categorical_p = categorical_p
+ self.ordered_p = ordered_p
+ self.keep_activation_size = keep_activation_size
+ self.num_classes_sampler = num_classes_sampler
+
+ super().__init__()
+
+ def forward(self, x):
+ # x shape: T, B, H
+
+ x = nn.Softsign()(x)
+
+ num_classes = self.num_classes_sampler()
+ hid_strength = torch.abs(x).mean(0).unsqueeze(0) if self.keep_activation_size else None
+
+ categorical_classes = torch.rand((x.shape[1], x.shape[2])) < self.categorical_p
+ class_boundaries = torch.zeros((num_classes - 1, x.shape[1], x.shape[2]), device=x.device, dtype=x.dtype)
+ # Sample a different index for each hidden dimension, but shared for all batches
+ for b in range(x.shape[1]):
+ for h in range(x.shape[2]):
+ ind = torch.randint(0, x.shape[0], (num_classes - 1,))
+ class_boundaries[:, b, h] = x[ind, b, h]
+
+ for b in range(x.shape[1]):
+ x_rel = x[:, b, categorical_classes[b]]
+ boundaries_rel = class_boundaries[:, b, categorical_classes[b]].unsqueeze(1)
+ x[:, b, categorical_classes[b]] = (x_rel > boundaries_rel).sum(dim=0).float() - num_classes / 2
+
+ ordered_classes = torch.rand((x.shape[1],x.shape[2])) < self.ordered_p
+ ordered_classes = torch.logical_and(ordered_classes, categorical_classes)
+ x[:, ordered_classes] = randomize_classes(x[:, ordered_classes], num_classes)
+
+ x = x * hid_strength if self.keep_activation_size else x
+
+ return x
+
+class QuantizationActivation(torch.nn.Module):
+ def __init__(self, n_thresholds, reorder_p = 0.5) -> None:
+ super().__init__()
+ self.n_thresholds = n_thresholds
+ self.reorder_p = reorder_p
+ self.thresholds = torch.nn.Parameter(torch.randn(self.n_thresholds))
+
+ def forward(self, x):
+ x = normalize_data(x).unsqueeze(-1)
+ x = (x > self.thresholds).sum(-1)
+
+ if random.random() < self.reorder_p:
+ x = randomize_classes(x.unsqueeze(-1), self.n_thresholds).squeeze(-1)
+ #x = ((x.float() - self.n_thresholds/2) / self.n_thresholds)# * data_std + data_mean
+ x = normalize_data(x)
+ return x
+
+class NormalizationActivation(torch.nn.Module):
+ def __init__(self) -> None:
+ super().__init__()
+
+ def forward(self, x):
+ x = normalize_data(x)
+ return x
+
+class PowerActivation(torch.nn.Module):
+ def __init__(self) -> None:
+ super().__init__()
+ #self.exp = torch.nn.Parameter(0.5 * torch.ones(1))
+ self.shared_exp_strength = 0.5
+ # TODO: Somehow this is only initialized once, so it's the same for all runs
+
+ def forward(self, x):
+ #print(torch.nn.functional.softplus(x), self.exp)
+ shared_exp = torch.randn(1)
+ exp = torch.nn.Parameter((shared_exp*self.shared_exp_strength + shared_exp * torch.randn(x.shape[-1])*(1-self.shared_exp_strength)) * 2 + 0.5).to(x.device)
+ x_ = torch.pow(torch.nn.functional.softplus(x) + 0.001, exp)
+ if False:
+ print(x[0:3, 0, 0].cpu().numpy()
+ , torch.nn.functional.softplus(x[0:3, 0, 0]).cpu().numpy()
+ , x_[0:3, 0, 0].cpu().numpy()
+ , normalize_data(x_)[0:3, 0, 0].cpu().numpy()
+ , self.exp.cpu().numpy())
+ return x_
+
+
+def lambda_time(f, name='', enabled=True):
+ if not enabled:
+ return f()
+ start = time.time()
+ r = f()
+ print('Timing', name, time.time()-start)
+ return r
+
+
+def pretty_get_batch(get_batch):
+ """
+ Genereate string representation of get_batch function
+ :param get_batch:
+ :return:
+ """
+ if isinstance(get_batch, types.FunctionType):
+ return f'<{get_batch.__module__}.{get_batch.__name__} {inspect.signature(get_batch)}'
+ else:
+ return repr(get_batch)
+
+
+class get_batch_sequence(list):
+ '''
+ This will call the get_batch_methods in order from the back and pass the previous as `get_batch` kwarg.
+ For example for `get_batch_methods=[get_batch_1, get_batch_2, get_batch_3]` this will produce a call
+ equivalent to `get_batch_3(*args,get_batch=partial(partial(get_batch_2),get_batch=get_batch_1,**kwargs))`.
+ get_batch_methods: all priors, but the first, muste have a `get_batch` argument
+ '''
+
+ def __init__(self, *get_batch_methods):
+ if len(get_batch_methods) == 0:
+ raise ValueError('Must have at least one get_batch method')
+ super().__init__(get_batch_methods)
+
+ def __repr__(self):
+ s = ',\n\t'.join([f"{pretty_get_batch(get_batch)}" for get_batch in self])
+ return f"get_batch_sequence(\n\t{s}\n)"
+
+ def __call__(self, *args, **kwargs):
+ """
+
+ Standard kwargs are: batch_size, seq_len, num_features
+ This returns a priors.Batch object.
+ """
+ final_get_batch = self[0]
+ for get_batch in self[1:]:
+ final_get_batch = partial(get_batch, get_batch=final_get_batch)
+ return final_get_batch(*args, **kwargs)
diff --git a/pfns4bo/scripts/.ipynb_checkpoints/acquisition_functions-checkpoint.py b/pfns4bo/scripts/.ipynb_checkpoints/acquisition_functions-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..700f367914fe7b9d88892d0c5212148fe69fb50b
--- /dev/null
+++ b/pfns4bo/scripts/.ipynb_checkpoints/acquisition_functions-checkpoint.py
@@ -0,0 +1,509 @@
+import contextlib
+
+from .. import transformer
+from .. import bar_distribution
+import torch
+import scipy
+import math
+from sklearn.preprocessing import power_transform, PowerTransformer
+
+def log01(x, eps=.0000001, input_between_zero_and_one=False):
+ logx = torch.log(x + eps)
+ if input_between_zero_and_one:
+ return (logx - math.log(eps)) / (math.log(1 + eps) - math.log(eps))
+ return (logx - logx.min(0)[0]) / (logx.max(0)[0] - logx.min(0)[0])
+
+def log01_batch(x, eps=.0000001, input_between_zero_and_one=False):
+ x = x.repeat(1, x.shape[-1] + 1, 1)
+ for b in range(x.shape[-1]):
+ x[:, b, b] = log01(x[:, b, b], eps=eps, input_between_zero_and_one=input_between_zero_and_one)
+ return x
+
+def lognormed_batch(x, eval_pos, eps=.0000001):
+ x = x.repeat(1, x.shape[-1] + 1, 1)
+ for b in range(x.shape[-1]):
+ logx = torch.log(x[:, b, b]+eps)
+ x[:, b, b] = (logx - logx[:eval_pos].mean(0))/logx[:eval_pos].std(0)
+ return x
+
+def _rank_transform(x_train, x):
+ assert len(x_train.shape) == len(x.shape) == 1
+ relative_to = torch.cat((torch.zeros_like(x_train[:1]),x_train.unique(sorted=True,), torch.ones_like(x_train[-1:])),-1)
+ higher_comparison = (relative_to < x[...,None]).sum(-1).clamp(min=1)
+ pos_inside_interval = (x - relative_to[higher_comparison-1])/(relative_to[higher_comparison] - relative_to[higher_comparison-1])
+ x_transformed = higher_comparison - 1 + pos_inside_interval
+ return x_transformed/(len(relative_to)-1.)
+
+def rank_transform(x_train, x):
+ assert x.shape[1] == x_train.shape[1], f"{x.shape=} and {x_train.shape=}"
+ # make sure everything is between 0 and 1
+ assert (x_train >= 0.).all() and (x_train <= 1.).all(), f"{x_train=}"
+ assert (x >= 0.).all() and (x <= 1.).all(), f"{x=}"
+ return_x = x.clone()
+ for feature_dim in range(x.shape[1]):
+ return_x[:, feature_dim] = _rank_transform(x_train[:, feature_dim], x[:, feature_dim])
+ return return_x
+
+
+
+def general_power_transform(x_train, x_apply, eps, less_safe=False):
+ if eps > 0:
+ try:
+ pt = PowerTransformer(method='box-cox')
+ pt.fit(x_train.cpu()+eps)
+ x_out = torch.tensor(pt.transform(x_apply.cpu()+eps), dtype=x_apply.dtype, device=x_apply.device)
+ except ValueError as e:
+ print(e)
+ x_out = x_apply - x_train.mean(0)
+ else:
+ pt = PowerTransformer(method='yeo-johnson')
+ if not less_safe and (x_train.std() > 1_000 or x_train.mean().abs() > 1_000):
+ x_apply = (x_apply - x_train.mean(0)) / x_train.std(0)
+ x_train = (x_train - x_train.mean(0)) / x_train.std(0)
+ # print('inputs are LAARGEe, normalizing them')
+ try:
+ pt.fit(x_train.cpu().double())
+ except ValueError as e:
+ print('caught this errrr', e)
+ if less_safe:
+ x_train = (x_train - x_train.mean(0)) / x_train.std(0)
+ x_apply = (x_apply - x_train.mean(0)) / x_train.std(0)
+ else:
+ x_train = x_train - x_train.mean(0)
+ x_apply = x_apply - x_train.mean(0)
+ pt.fit(x_train.cpu().double())
+ x_out = torch.tensor(pt.transform(x_apply.cpu()), dtype=x_apply.dtype, device=x_apply.device)
+ if torch.isnan(x_out).any() or torch.isinf(x_out).any():
+ print('WARNING: power transform failed')
+ print(f"{x_train=} and {x_apply=}")
+ x_out = x_apply - x_train.mean(0)
+ return x_out
+
+
+
+#@torch.inference_mode()
+def general_acq_function(model: transformer.TransformerModel, x_given, y_given, x_eval, apply_power_transform=True,
+ rand_sample=False, znormalize=False, pre_normalize=False, pre_znormalize=False, predicted_mean_fbest=False,
+ input_znormalize=False, max_dataset_size=10_000, remove_features_with_one_value_only=False,
+ return_actual_ei=False, acq_function='ei', ucb_rest_prob=.05, ensemble_log_dims=False,
+ ensemble_type='mean_probs', # in ('mean_probs', 'max_acq')
+ input_power_transform=False, power_transform_eps=.0, input_power_transform_eps=.0,
+ input_rank_transform=False, ensemble_input_rank_transform=False,
+ ensemble_power_transform=False, ensemble_feature_rotation=False,
+ style=None, outlier_stretching_interval=0.0, verbose=False, unsafe_power_transform=False,
+ ):
+ """
+ Differences to HEBO:
+ - The noise can't be set in the same way, as it depends on the tuning of HPs via VI.
+ - Log EI and PI are always used directly instead of using the approximation.
+
+ This is a stochastic function, relying on torch.randn
+
+ :param model:
+ :param x_given: torch.Tensor of shape (N, D)
+ :param y_given: torch.Tensor of shape (N, 1) or (N,)
+ :param x_eval: torch.Tensor of shape (M, D)
+ :param kappa:
+ :param eps:
+ :return:
+ """
+ assert ensemble_type in ('mean_probs', 'max_acq')
+ if rand_sample is not False \
+ and (len(x_given) == 0 or
+ ((1 + x_given.shape[1] if rand_sample is None else max(2, rand_sample)) > x_given.shape[0])):
+ print('rando')
+ return torch.zeros_like(x_eval[:,0]) #torch.randperm(x_eval.shape[0])[0]
+ y_given = y_given.reshape(-1)
+ assert len(y_given) == len(x_given)
+ if apply_power_transform:
+ if pre_normalize:
+ y_normed = y_given / y_given.std()
+ if not torch.isinf(y_normed).any() and not torch.isnan(y_normed).any():
+ y_given = y_normed
+ elif pre_znormalize:
+ y_znormed = (y_given - y_given.mean()) / y_given.std()
+ if not torch.isinf(y_znormed).any() and not torch.isnan(y_znormed).any():
+ y_given = y_znormed
+ y_given = general_power_transform(y_given.unsqueeze(1), y_given.unsqueeze(1), power_transform_eps, less_safe=unsafe_power_transform).squeeze(1)
+ if verbose:
+ print(f"{y_given=}")
+ #y_given = torch.tensor(power_transform(y_given.cpu().unsqueeze(1), method='yeo-johnson', standardize=znormalize), device=y_given.device, dtype=y_given.dtype,).squeeze(1)
+ y_given_std = torch.tensor(1., device=y_given.device, dtype=y_given.dtype)
+ if znormalize and not apply_power_transform:
+ if len(y_given) > 1:
+ y_given_std = y_given.std()
+ y_given_mean = y_given.mean()
+ y_given = (y_given - y_given_mean) / y_given_std
+
+ if remove_features_with_one_value_only:
+ x_all = torch.cat([x_given, x_eval], dim=0)
+ only_one_value_feature = torch.tensor([len(torch.unique(x_all[:,i])) for i in range(x_all.shape[1])]) == 1
+ x_given = x_given[:,~only_one_value_feature]
+ x_eval = x_eval[:,~only_one_value_feature]
+
+ if outlier_stretching_interval > 0.:
+ tx = torch.cat([x_given, x_eval], dim=0)
+ m = outlier_stretching_interval
+ eps = 1e-10
+ small_values = (tx < m) & (tx > 0.)
+ tx[small_values] = m * (torch.log(tx[small_values] + eps) - math.log(eps)) / (math.log(m + eps) - math.log(eps))
+
+ large_values = (tx > 1. - m) & (tx < 1.)
+ tx[large_values] = 1. - m * (torch.log(1 - tx[large_values] + eps) - math.log(eps)) / (
+ math.log(m + eps) - math.log(eps))
+ x_given = tx[:len(x_given)]
+ x_eval = tx[len(x_given):]
+
+ if input_znormalize: # implementation that relies on the test set, too...
+ std = x_given.std(dim=0)
+ std[std == 0.] = 1.
+ mean = x_given.mean(dim=0)
+ x_given = (x_given - mean) / std
+ x_eval = (x_eval - mean) / std
+
+ if input_power_transform:
+ x_given = general_power_transform(x_given, x_given, input_power_transform_eps)
+ x_eval = general_power_transform(x_given, x_eval, input_power_transform_eps)
+
+ if input_rank_transform is True or input_rank_transform == 'full': # uses test set x statistics...
+ x_all = torch.cat((x_given,x_eval), dim=0)
+ for feature_dim in range(x_all.shape[-1]):
+ uniques = torch.sort(torch.unique(x_all[..., feature_dim])).values
+ x_eval[...,feature_dim] = torch.searchsorted(uniques,x_eval[..., feature_dim]).float() / (len(uniques)-1)
+ x_given[...,feature_dim] = torch.searchsorted(uniques,x_given[..., feature_dim]).float() / (len(uniques)-1)
+ elif input_rank_transform is False:
+ pass
+ elif input_rank_transform == 'train':
+ x_given = rank_transform(x_given, x_given)
+ x_eval = rank_transform(x_given, x_eval)
+ elif input_rank_transform.startswith('train'):
+ likelihood = float(input_rank_transform.split('_')[-1])
+ if torch.rand(1).item() < likelihood:
+ print('rank transform')
+ x_given = rank_transform(x_given, x_given)
+ x_eval = rank_transform(x_given, x_eval)
+ else:
+ raise NotImplementedError
+
+
+ # compute logits
+ criterion: bar_distribution.BarDistribution = model.criterion
+ x_predict = torch.cat([x_given, x_eval], dim=0)
+
+
+ logits_list = []
+ for x_feed in torch.split(x_predict, max_dataset_size, dim=0):
+ x_full_feed = torch.cat([x_given, x_feed], dim=0).unsqueeze(1)
+ y_full_feed = y_given.unsqueeze(1)
+ if ensemble_log_dims == '01':
+ x_full_feed = log01_batch(x_full_feed)
+ elif ensemble_log_dims == 'global01' or ensemble_log_dims is True:
+ x_full_feed = log01_batch(x_full_feed, input_between_zero_and_one=True)
+ elif ensemble_log_dims == '01-10':
+ x_full_feed = torch.cat((log01_batch(x_full_feed)[:, :-1], log01_batch(1. - x_full_feed)), 1)
+ elif ensemble_log_dims == 'norm':
+ x_full_feed = lognormed_batch(x_full_feed, len(x_given))
+ elif ensemble_log_dims is not False:
+ raise NotImplementedError
+
+ if ensemble_feature_rotation:
+ x_full_feed = torch.cat([x_full_feed[:, :, (i+torch.arange(x_full_feed.shape[2])) % x_full_feed.shape[2]] for i in range(x_full_feed.shape[2])], dim=1)
+
+ if ensemble_input_rank_transform == 'train' or ensemble_input_rank_transform is True:
+ x_full_feed = torch.cat([rank_transform(x_given, x_full_feed[:,i,:])[:,None] for i in range(x_full_feed.shape[1])] + [x_full_feed], dim=1)
+
+ if ensemble_power_transform:
+ assert apply_power_transform is False
+ y_full_feed = torch.cat((general_power_transform(y_full_feed, y_full_feed, power_transform_eps), y_full_feed), dim=1)
+
+
+ if style is not None:
+ if callable(style):
+ style = style()
+
+ if isinstance(style, torch.Tensor):
+ style = style.to(x_full_feed.device)
+ else:
+ style = torch.tensor(style, device=x_full_feed.device).view(1, 1).repeat(x_full_feed.shape[1], 1)
+
+
+ logits = model(
+ (style,
+ x_full_feed.repeat_interleave(dim=1, repeats=y_full_feed.shape[1]),
+ y_full_feed.repeat(1,x_full_feed.shape[1])),
+ single_eval_pos=len(x_given)
+ )
+ if ensemble_type == 'mean_probs':
+ logits = logits.softmax(-1).mean(1, keepdim=True).log_() # (num given + num eval, 1, num buckets)
+ # print('in ensemble_type == mean_probs ')
+
+ logits_list.append(logits) # (< max_dataset_size, 1 , num_buckets)
+ logits = torch.cat(logits_list, dim=0) # (num given + num eval, 1 or (num_features+1), num buckets)
+ del logits_list, x_full_feed
+ if torch.isnan(logits).any():
+ print('nan logits')
+ print(f"y_given: {y_given}, x_given: {x_given}, x_eval: {x_eval}")
+ print(f"logits: {logits}")
+ return torch.zeros_like(x_eval[:,0])
+
+ #logits = model((torch.cat([x_given, x_given, x_eval], dim=0).unsqueeze(1),
+ # torch.cat([y_given, torch.zeros(len(x_eval)+len(x_given), device=y_given.device)], dim=0).unsqueeze(1)),
+ # single_eval_pos=len(x_given))[:,0] # (N + M, num_buckets)
+ logits_given = logits[:len(x_given)]
+ logits_eval = logits[len(x_given):]
+
+ #tau = criterion.mean(logits_given)[torch.argmax(y_given)] # predicted mean at the best y
+ if predicted_mean_fbest:
+ tau = criterion.mean(logits_given)[torch.argmax(y_given)].squeeze(0)
+ else:
+ tau = torch.max(y_given)
+ #log_ei = torch.stack([criterion.ei(logits_eval[:,i], noisy_best_f[i]).log() for i in range(len(logits_eval))],0)
+
+ def acq_ensembling(acq_values): # (points, ensemble dim)
+ return acq_values.max(1).values
+
+ if isinstance(acq_function, (dict,list)):
+ acq_function = acq_function[style]
+
+ if acq_function == 'ei':
+ acq_value = acq_ensembling(criterion.ei(logits_eval, tau))
+ elif acq_function == 'ei_or_rand':
+ if torch.rand(1).item() < 0.5:
+ acq_value = torch.rand(len(x_eval))
+ else:
+ acq_value = acq_ensembling(criterion.ei(logits_eval, tau))
+ elif acq_function == 'pi':
+ acq_value = acq_ensembling(criterion.pi(logits_eval, tau))
+ elif acq_function == 'ucb':
+ acq_function = criterion.ucb
+ if ucb_rest_prob is not None:
+ acq_function = lambda *args: criterion.ucb(*args, rest_prob=ucb_rest_prob)
+ acq_value = acq_ensembling(acq_function(logits_eval, tau))
+ elif acq_function == 'mean':
+ acq_value = acq_ensembling(criterion.mean(logits_eval))
+ elif acq_function.startswith('hebo'):
+ noise, upsi, delta, eps = (float(v) for v in acq_function.split('_')[1:])
+ noise = y_given_std * math.sqrt(2 * noise)
+ kappa = math.sqrt(upsi * 2 * ((2.0 + x_given.shape[1] / 2.0) * math.log(max(1, len(x_given))) + math.log(
+ 3 * math.pi ** 2 / (3 * delta))))
+ rest_prob = 1. - .5 * (1 + torch.erf(torch.tensor(kappa / math.sqrt(2), device=logits.device)))
+ ucb = acq_ensembling(criterion.ucb(logits_eval, None, rest_prob=rest_prob)) \
+ + torch.randn(len(logits_eval), device=logits_eval.device) * noise
+ noisy_best_f = tau + eps + \
+ noise * torch.randn(len(logits_eval), device=logits_eval.device)[:, None].repeat(1, logits_eval.shape[1])
+
+ log_pi = acq_ensembling(criterion.pi(logits_eval, noisy_best_f).log())
+ # log_ei = torch.stack([criterion.ei(logits_eval[:,i], noisy_best_f[i]).log() for i in range(len(logits_eval))],0)
+ log_ei = acq_ensembling(criterion.ei(logits_eval, noisy_best_f).log())
+
+ acq_values = torch.stack([ucb, log_ei, log_pi], dim=1)
+
+ def is_pareto_efficient(costs):
+ """
+ Find the pareto-efficient points
+ :param costs: An (n_points, n_costs) array
+ :return: A (n_points, ) boolean array, indicating whether each point is Pareto efficient
+ """
+ is_efficient = torch.ones(costs.shape[0], dtype=bool, device=costs.device)
+ for i, c in enumerate(costs):
+ if is_efficient[i]:
+ is_efficient[is_efficient.clone()] = (costs[is_efficient] < c).any(
+ 1) # Keep any point with a lower cost
+ is_efficient[i] = True # And keep self
+ return is_efficient
+
+ acq_value = is_pareto_efficient(-acq_values)
+ else:
+ raise ValueError(f'Unknown acquisition function: {acq_function}')
+
+ max_acq = acq_value.max()
+
+ return acq_value if return_actual_ei else (acq_value == max_acq)
+
+
+def optimize_acq(model, known_x, known_y, num_grad_steps=10, num_random_samples=100, lr=.01, **kwargs):
+ """
+ intervals are assumed to be between 0 and 1
+ only works with ei
+ recommended extra kwarg: ensemble_input_rank_transform=='train'
+
+ :param model: model to optimize, should already handle different num_features with its encoder
+ You can add this simply with `model.encoder = encoders.VariableNumFeaturesEncoder(model.encoder, model.encoder.num_features)`
+ :param known_x: (N, num_features)
+ :param known_y: (N,)
+ :param num_grad_steps: int
+ :param num_random_samples: int
+ :param lr: float
+ :param kwargs: will be given to `general_acq_function`
+ :return:
+ """
+ x_eval = torch.rand(num_random_samples, known_x.shape[1]).requires_grad_(True)
+ opt = torch.optim.Adam(params=[x_eval], lr=lr)
+ best_acq, best_x = -float('inf'), x_eval[0].detach()
+ for grad_step in range(num_grad_steps):
+ acq = general_acq_function(model, known_x, known_y, x_eval, return_actual_ei=True, **kwargs)
+ max_acq = acq.detach().max().item()
+ if max_acq > best_acq:
+ best_x = x_eval[acq.argmax()].detach()
+ best_acq = max_acq
+
+ (-acq.mean()).backward()
+ assert (x_eval.grad != 0.).any()
+ if torch.isfinite(x_eval.grad).all():
+ opt.step()
+ opt.zero_grad()
+ with torch.no_grad():
+ x_eval.clamp_(min=0., max=1.)
+
+ return best_x
+
+
+def optimize_acq_w_lbfgs(model, known_x, known_y, num_grad_steps=15_000, num_candidates=100, pre_sample_size=100_000, device='cpu',
+ verbose=False, dims_wo_gradient_opt=[], rand_sample_func=None, **kwargs):
+ """
+ intervals are assumed to be between 0 and 1
+ only works with deterministic acq
+ recommended extra kwarg: ensemble_input_rank_transform=='train'
+
+ :param model: model to optimize, should already handle different num_features with its encoder
+ You can add this simply with `model.encoder = encoders.VariableNumFeaturesEncoder(model.encoder, model.encoder.num_features)`
+ :param known_x: (N, num_features)
+ :param known_y: (N,)
+ :param num_grad_steps: int: how many steps to take inside of scipy, can be left high, as it stops most of the time automatically early
+ :param num_candidates: int: how many candidates to optimize with LBFGS, increases costs when higher
+ :param pre_sample_size: int: how many settings to try first with a random search, before optimizing the best with grads
+ :param dims_wo_gradient_opt: int: which dimensions to not optimize with gradients, but with random search only
+ :param rand_sample_func: function: how to sample random points, should be a function that takes a number of samples and returns a tensor
+ For example `lambda n: torch.rand(n, known_x.shape[1])`.
+ :param kwargs: will be given to `general_acq_function`
+ :return:
+ """
+ num_features = known_x.shape[1]
+ dims_w_gradient_opt = sorted(set(range(num_features)) - set(dims_wo_gradient_opt))
+ known_x = known_x.to(device)
+ known_y = known_y.to(device)
+ pre_sample_size = max(pre_sample_size, num_candidates)
+ rand_sample_func = rand_sample_func or (lambda n: torch.rand(n, num_features, device=device))
+ if len(known_x) < pre_sample_size:
+ x_initial = torch.cat((rand_sample_func(pre_sample_size-len(known_x)).to(device), known_x), 0)
+ else:
+ x_initial = rand_sample_func(pre_sample_size)
+ x_initial = x_initial.clamp(min=0., max=1.)
+ x_initial_all = x_initial
+ model.to(device)
+
+ with torch.no_grad():
+ acq = general_acq_function(model, known_x, known_y, x_initial.to(device), return_actual_ei=True, **kwargs)
+ if verbose:
+ import matplotlib.pyplot as plt
+ if x_initial.shape[1] == 2:
+ plt.title('initial acq values, red -> blue')
+ plt.scatter(x_initial[:, 0][:100], x_initial[:, 1][:100], c=acq.cpu().numpy()[:100], cmap='RdBu')
+ x_initial = x_initial[acq.argsort(descending=True)[:num_candidates].cpu()].detach() # num_candidates x num_features
+
+ x_initial_all_ei = acq.cpu().detach()
+
+ def opt_f(x):
+ x_eval = torch.tensor(x).view(-1, len(dims_w_gradient_opt)).float().to(device).requires_grad_(True)
+ x_eval_new = x_initial.clone().detach().to(device)
+ x_eval_new[:, dims_w_gradient_opt] = x_eval
+
+ assert x_eval_new.requires_grad
+ assert not torch.isnan(x_eval_new).any()
+ model.requires_grad_(False)
+ acq = general_acq_function(model, known_x, known_y, x_eval_new, return_actual_ei=True, **kwargs)
+ neg_mean_acq = -acq.mean()
+ neg_mean_acq.backward()
+ #print(neg_mean_acq.detach().numpy(), x_eval.grad.detach().view(*x.shape).numpy())
+ with torch.no_grad():
+ x_eval.grad[x_eval.grad != x_eval.grad] = 0.
+ return neg_mean_acq.detach().cpu().to(torch.float64).numpy(), \
+ x_eval.grad.detach().view(*x.shape).cpu().to(torch.float64).numpy()
+
+ # Optimize best candidates with LBFGS
+ if num_grad_steps > 0 and len(dims_w_gradient_opt) > 0:
+ # the columns not in dims_wo_gradient_opt will be optimized with gradients
+ x_initial_for_gradient_opt = x_initial[:, dims_w_gradient_opt].detach().cpu().flatten().numpy() # x_initial.cpu().flatten().numpy()
+ res = scipy.optimize.minimize(opt_f, x_initial_for_gradient_opt, method='L-BFGS-B', jac=True,
+ bounds=[(0, 1)]*x_initial_for_gradient_opt.size,
+ options={'maxiter': num_grad_steps})
+ results = x_initial.cpu()
+ results[:, dims_w_gradient_opt] = torch.tensor(res.x).float().view(-1, len(dims_w_gradient_opt))
+
+ else:
+ results = x_initial.cpu()
+
+ results = results.clamp(min=0., max=1.)
+
+ # Recalculate the acq values for the best candidates
+ with torch.no_grad():
+ acq = general_acq_function(model, known_x, known_y, results.to(device), return_actual_ei=True, verbose=verbose, **kwargs)
+ #print(acq)
+ if verbose:
+ from scipy.stats import rankdata
+ import matplotlib.pyplot as plt
+ if results.shape[1] == 2:
+ plt.scatter(results[:, 0], results[:, 1], c=rankdata(acq.cpu().numpy()), marker='x', cmap='RdBu')
+ plt.show()
+ best_x = results[acq.argmax().item()].detach()
+
+ acq_order = acq.argsort(descending=True).cpu()
+ all_order = x_initial_all_ei.argsort(descending=True).cpu()
+
+ return best_x.detach(), results[acq_order].detach(), acq.cpu()[acq_order].detach(), x_initial_all.cpu()[all_order].detach(), x_initial_all_ei.cpu()[all_order].detach()
+
+from ..utils import to_tensor
+
+class TransformerBOMethod:
+
+ def __init__(self, model, acq_f=general_acq_function, device='cpu:0', fit_encoder=None, **kwargs):
+ self.model = model
+ self.device = device
+ self.kwargs = kwargs
+ self.acq_function = acq_f
+ self.fit_encoder = fit_encoder
+
+ @torch.no_grad()
+ def observe_and_suggest(self, X_obs, y_obs, X_pen, return_actual_ei=False):
+ # assert X_pen is not None
+ # assumptions about X_obs and X_pen:
+ # X_obs is a numpy array of shape (n_samples, n_features)
+ # y_obs is a numpy array of shape (n_samples,), between 0 and 1
+ # X_pen is a numpy array of shape (n_samples_left, n_features)
+ X_obs = to_tensor(X_obs, device=self.device).to(torch.float32)
+ y_obs = to_tensor(y_obs, device=self.device).to(torch.float32).view(-1)
+ X_pen = to_tensor(X_pen, device=self.device).to(torch.float32)
+
+ assert len(X_obs) == len(y_obs), "make sure both X_obs and y_obs have the same length."
+
+ self.model.to(self.device)
+
+ if self.fit_encoder is not None:
+ w = self.fit_encoder(self.model, X_obs, y_obs)
+ X_obs = w(X_obs)
+ X_pen = w(X_pen)
+
+
+ # with (torch.cuda.amp.autocast() if self.device.type != 'cpu' else contextlib.nullcontext()):
+ with (torch.cuda.amp.autocast() if self.device[:3] != 'cpu' else contextlib.nullcontext()):
+ acq_values = self.acq_function(self.model, X_obs, y_obs,
+ X_pen, return_actual_ei=return_actual_ei, **self.kwargs).cpu().clone() # bool array
+ acq_mask = acq_values.max() == acq_values
+ possible_next = torch.arange(len(X_pen))[acq_mask]
+ if len(possible_next) == 0:
+ possible_next = torch.arange(len(X_pen))
+
+ r = possible_next[torch.randperm(len(possible_next))[0]].cpu().item()
+
+
+ if return_actual_ei:
+ return r, acq_values
+ else:
+ return r
+
+
+
+
+
+
+
diff --git a/pfns4bo/scripts/.ipynb_checkpoints/tune_input_warping-checkpoint.py b/pfns4bo/scripts/.ipynb_checkpoints/tune_input_warping-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb18f2384579bdace84f6c1f333e126d892467a5
--- /dev/null
+++ b/pfns4bo/scripts/.ipynb_checkpoints/tune_input_warping-checkpoint.py
@@ -0,0 +1,538 @@
+from __future__ import annotations
+
+import random
+from collections import OrderedDict
+import torch
+
+from .. import utils
+from ..priors.hebo_prior import Warp
+from gpytorch.priors import LogNormalPrior
+
+# from botorch.optim import module_to_array, set_params_with_array
+# from .. import module_to_array, set_params_with_array
+
+import scipy
+from scipy.optimize import Bounds
+from typing import OrderedDict
+import numpy as np
+from functools import partial
+
+device = 'cpu'
+
+
+def fit_lbfgs(x, w, nll, num_grad_steps=10, ignore_prior=True, params0=None):
+ bounds_ = {}
+ if hasattr(w, "named_parameters_and_constraints"):
+ for param_name, _, constraint in w.named_parameters_and_constraints():
+ if constraint is not None and not constraint.enforced:
+ bounds_[param_name] = constraint.lower_bound, constraint.upper_bound
+ params0_, property_dict, bounds_ = module_to_array(
+ module=w, bounds=bounds_, exclude=None
+ )
+ if params0 is None: params0 = params0_
+ bounds = Bounds(lb=bounds_[0], ub=bounds_[1], keep_feasible=True)
+
+ def loss_f(params, w):
+ w = set_params_with_array(w, params, property_dict)
+ w.requires_grad_(True)
+ loss = 0.
+ if not ignore_prior:
+ for name, module, prior, closure, _ in w.named_priors():
+ prior_term = prior.log_prob(closure(module))
+ loss -= prior_term.sum(dim=-1)
+ negll = nll(w(x.to(torch.float64)).to(torch.float)).sum()
+ #if loss != 0.:
+ # print(loss.item(), negll.item())
+ loss = loss + negll
+ return w, loss
+
+ def opt_f(params, w):
+ w, loss = loss_f(params, w)
+
+ w.zero_grad()
+ loss.backward()
+ grad = []
+ param_dict = OrderedDict(w.named_parameters())
+
+ for p_name in property_dict:
+ t = param_dict[p_name].grad
+ if t is None:
+ # this deals with parameters that do not affect the loss
+ grad.append(np.zeros(property_dict[p_name].shape.numel()))
+ else:
+ grad.append(t.detach().view(-1).cpu().double().clone().numpy())
+ w.zero_grad()
+ # print(neg_mean_acq.detach().numpy(), x_eval.grad.detach().view(*x.shape).numpy())
+ return loss.item(), np.concatenate(grad)
+
+ if num_grad_steps:
+ return scipy.optimize.minimize(partial(opt_f, w=w), params0, method='L-BFGS-B', jac=True, bounds=bounds,
+ options={'maxiter': num_grad_steps})
+ else:
+ with torch.no_grad():
+ return loss_f(params0, w), params0
+
+
+def log_vs_nonlog(x, w, *args, **kwargs):
+ if "true_nll" in kwargs:
+ true_nll = kwargs["true_nll"]
+ del kwargs["true_nll"]
+ else:
+ true_nll = None
+ params, property_dict, _ = module_to_array(module=w)
+ no_log = np.ones_like(params)
+ log = np.array([1.9, 0.11] * (int(len(property_dict) / 2)))
+ loss_no_log = fit_lbfgs(x, w, *args, **{**kwargs, 'num_grad_steps': 0}, params0=no_log)
+ loss_log = fit_lbfgs(x, w, *args, **{**kwargs, 'num_grad_steps': 0}, params0=log)
+ print("loss no log", loss_no_log[0][1], "loss log", loss_log[0][1])
+ if loss_no_log[0][1] < loss_log[0][1]:
+ set_params_with_array(module=w, x=loss_no_log[1], property_dict=property_dict)
+ if true_nll:
+ best_params, _, _ = module_to_array(module=w)
+ print("true nll", fit_lbfgs(x, w, true_nll, **{**kwargs, 'num_grad_steps': 0}, params0=best_params))
+
+
+def fit_lbfgs_with_restarts(x, w, *args, old_solution=None, rs_size=50, **kwargs):
+ if "true_nll" in kwargs:
+ true_nll = kwargs["true_nll"]
+ del kwargs["true_nll"]
+ else:
+ true_nll = None
+ rs_results = []
+ if old_solution:
+ rs_results.append(fit_lbfgs(x, old_solution, *args, **{**kwargs, 'num_grad_steps': 0}))
+ for i in range(rs_size):
+ with torch.no_grad():
+ w.concentration0[:] = w.concentration0_prior()
+ w.concentration1[:] = w.concentration1_prior()
+ rs_results.append(fit_lbfgs(x, w, *args, **{**kwargs, 'num_grad_steps': 0}))
+ best_r = min(rs_results, key=lambda r: r[0][1])
+ print('best r', best_r)
+ with torch.set_grad_enabled(True):
+ r = fit_lbfgs(x, w, *args, **kwargs, params0=best_r[1])
+ _, property_dict, _ = module_to_array(module=w)
+ set_params_with_array(module=w, x=r.x, property_dict=property_dict)
+ print('final r', r)
+ if true_nll:
+ print("true nll", fit_lbfgs(x, w, true_nll, **{**kwargs, 'num_grad_steps': 0}, params0=r.x))
+ return r
+
+
+# use seed 0 for sampling indices, and reset seed afterwards
+old_seed = random.getstate()
+random.seed(0)
+one_out_indices_sampled_per_num_obs = [None]+[random.sample(range(i), min(10, i)) for i in range(1, 100)]
+random.setstate(old_seed)
+
+# use seed 0 for sampling subsets
+old_seed = random.getstate()
+random.seed(0)
+subsets = [None]+[[random.sample(range(i), i//2) for _ in range(10)] for i in range(1, 100)]
+neg_subsets = [None]+[[list(set(range(i)) - set(s)) for s in ss] for i, ss in enumerate(subsets[1:], 1)]
+random.setstate(old_seed)
+
+
+
+def fit_input_warping(model, x, y, nll_type='fast', old_solution=None, opt_method="lbfgs", **kwargs):
+ """
+
+ :param model:
+ :param x: shape (n, d)
+ :param y: shape (n, 1)
+ :param nll_type:
+ :param kwargs: Possible kwargs: `num_grad_steps`, `rs_size`
+ :return:
+ """
+ device = x.device
+ assert y.device == device, y.device
+
+ model.requires_grad_(False)
+
+ w = Warp(range(x.shape[1]),
+ concentration1_prior=LogNormalPrior(torch.tensor(0.0, device=device), torch.tensor(.75, device=device)),
+ concentration0_prior=LogNormalPrior(torch.tensor(0.0, device=device), torch.tensor(.75, device=device)),
+ eps=1e-12)
+ w.to(device)
+
+ def fast_nll(x): # noqa actually used with `eval` below
+ model.requires_grad_(False)
+ if model.style_encoder is not None:
+ style = torch.zeros(1, 1, dtype=torch.int64, device=device)
+ utils.print_once("WARNING: using style 0 for input warping, this is set for nonmyopic BO setting.")
+ else:
+ style = None
+ logits = model(x[:, None], y[:, None], x[:, None], style=style, only_return_standard_out=True)
+ loss = model.criterion(logits, y[:, None]).squeeze(1)
+ return loss
+
+ def true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ total_nll = 0.
+ for cutoff in range(len(x)):
+ logits = model(x[:cutoff, None], y[:cutoff, None], x[cutoff:cutoff + 1, None])
+ total_nll = total_nll + model.criterion(logits, y[cutoff:cutoff + 1, None]).squeeze()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def repeated_true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ total_nll = 0.
+ for i in range(5):
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ x_ = x.clone()[shuffle_idx]
+ y_ = y.clone()[shuffle_idx]
+ for cutoff in range(len(x)):
+ logits = model(x_[:cutoff, None], y_[:cutoff, None], x_[cutoff:cutoff + 1, None])
+ total_nll = total_nll + model.criterion(logits, y_[cutoff:cutoff + 1, None]).squeeze()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def repeated_true_100_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ total_nll = 0.
+ for i in range(100):
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ x_ = x.clone()[shuffle_idx]
+ y_ = y.clone()[shuffle_idx]
+ for cutoff in range(len(x)):
+ logits = model(x_[:cutoff, None], y_[:cutoff, None], x_[cutoff:cutoff + 1, None])
+ total_nll = total_nll + model.criterion(logits, y_[cutoff:cutoff + 1, None]).squeeze()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll / 100
+
+ def batched_repeated_chunked_true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ assert len(x.shape) == 2 and len(y.shape) == 1
+ model.requires_grad_(False)
+ n_features = x.shape[1] if len(x.shape) > 1 else 1
+ batch_size = 10
+
+ X = []
+ Y = []
+
+ for i in range(batch_size):
+ #if i == 0:
+ # shuffle_idx = list(range(len(x)))
+ #else:
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ X.append(x.clone()[shuffle_idx])
+ Y.append(y.clone()[shuffle_idx])
+ X = torch.stack(X, dim=1).view((x.shape[0], batch_size, n_features))
+ Y = torch.stack(Y, dim=1).view((x.shape[0], batch_size, 1))
+
+ total_nll = 0.
+ batch_indizes = sorted(list(set(np.linspace(0, len(x), 10, dtype=int))))
+
+ for chunk_start, chunk_end in zip(batch_indizes[:-1], batch_indizes[1:]):
+ X_cutoff = X[:chunk_start]
+ Y_cutoff = Y[:chunk_start]
+ X_after_cutoff = X[chunk_start:chunk_end]
+ Y_after_cutoff = Y[chunk_start:chunk_end]
+
+ pending_x = X_after_cutoff.reshape(X_after_cutoff.shape[0], batch_size, n_features) # n_pen x batch_size x n_feat
+ observed_x = X_cutoff.reshape(X_cutoff.shape[0], batch_size, n_features) # n_obs x batch_size x n_feat
+ X_tmp = torch.cat((observed_x, pending_x), dim=0) # (n_obs+n_pen) x batch_size x n_feat
+
+ logits = model((X_tmp, Y_cutoff), single_eval_pos=int(chunk_start))
+ total_nll = total_nll + model.criterion(logits, Y_after_cutoff).sum()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def batched_repeated_true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ n_features = x.shape[1] if len(x.shape) > 1 else 1
+ batch_size = 10
+
+ X = []
+ Y = []
+
+ for i in range(batch_size):
+ #if i == 0:
+ # shuffle_idx = list(range(len(x)))
+ #else:
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ X.append(x.clone()[shuffle_idx])
+ Y.append(y.clone()[shuffle_idx])
+ X = torch.cat(X, dim=1).reshape((x.shape[0], batch_size, n_features))
+ Y = torch.cat(Y, dim=1).reshape((x.shape[0], batch_size, 1))
+
+ total_nll = 0.
+
+ for cutoff in range(0, len(x)):
+ X_cutoff = X[:cutoff]
+ Y_cutoff = Y[:cutoff]
+ X_after_cutoff = X[cutoff:cutoff+1]
+ Y_after_cutoff = Y[cutoff:cutoff+1]
+
+ pending_x = X_after_cutoff.reshape(X_after_cutoff.shape[0], batch_size, n_features) # n_pen x batch_size x n_feat
+ observed_x = X_cutoff.reshape(X_cutoff.shape[0], batch_size, n_features) # n_obs x batch_size x n_feat
+ X_tmp = torch.cat((observed_x, pending_x), dim=0) # (n_obs+n_pen) x batch_size x n_feat
+
+ pad_y = torch.zeros((X_after_cutoff.shape[0], batch_size, 1)) # (n_obs+n_pen) x batch_size
+ Y_tmp = torch.cat((Y_cutoff, pad_y), dim=0)
+
+ logits = model((X_tmp, Y_tmp), single_eval_pos=cutoff)
+ total_nll = total_nll + model.criterion(logits, Y_after_cutoff).sum()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def one_out_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "one out nll not implemented for style encoder, see above for an example impl"
+ # x shape: (n, d)
+ # iterate over a pre-defined set of
+ model.requires_grad_(False)
+ #indices = one_out_indices_sampled_per_num_obs[len(x)]
+ indices = list(range(x.shape[0]))
+
+ # create batch by moving the one out index to the end
+ eval_x = x[indices][None] # shape (1, 10, d)
+ eval_y = y[indices][None] # shape (1, 10, 1)
+ # all other indices are used for training
+ train_x = torch.stack([torch.cat([x[:i], x[i + 1:]]) for i in indices], 1)
+ train_y = torch.stack([torch.cat([y[:i], y[i + 1:]]) for i in indices], 1)
+
+ logits = model(train_x, train_y, eval_x)
+ return model.criterion(logits, eval_y).squeeze(0)
+
+ def subset_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "subset nll not implemented for style encoder, see above for an example impl"
+ # x shape: (n, d)
+ # iterate over a pre-defined set of
+ model.requires_grad_(False)
+ eval_indices = torch.tensor(subsets[len(x)])
+ train_indices = torch.tensor(neg_subsets[len(x)])
+
+ # batch by using all eval_indices
+ eval_x = x[eval_indices.flatten()].view(eval_indices.shape + (-1,)) # shape (10, n//2, d)
+ eval_y = y[eval_indices.flatten()].view(eval_indices.shape + (-1,)) # shape (10, n//2, 1)
+ # all other indices are used for training
+ train_x = x[train_indices.flatten()].view(train_indices.shape + (-1,)) # shape (10, n//2, d)
+ train_y = y[train_indices.flatten()].view(train_indices.shape + (-1,)) # shape (10, n//2, 1)
+
+ logits = model(train_x.transpose(0, 1), train_y.transpose(0, 1), eval_x.transpose(0, 1))
+ return model.criterion(logits, eval_y.transpose(0, 1))
+
+ if opt_method == "log_vs_nolog":
+ log_vs_nonlog(x, w, eval(nll_type + '_nll'),
+ ignore_prior=True, # true_nll=repeated_true_100_nll,
+ **kwargs)
+ elif opt_method == "lbfgs":
+ fit_lbfgs_with_restarts(
+ x, w, eval(nll_type + '_nll'),
+ ignore_prior=True, old_solution=old_solution, # true_nll=repeated_true_100_nll,
+ **kwargs)
+ elif opt_method == "lbfgs_w_prior":
+ fit_lbfgs_with_restarts(
+ x, w, eval(nll_type + '_nll'),
+ ignore_prior=False, old_solution=old_solution, # true_nll=repeated_true_100_nll,
+ **kwargs)
+ else:
+ raise ValueError(opt_method)
+
+ return w
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#!/usr/bin/env python3
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+r"""
+A converter that simplifies using numpy-based optimizers with generic torch
+`nn.Module` classes. This enables using a `scipy.optim.minimize` optimizer
+for optimizing module parameters.
+"""
+
+
+
+from collections import OrderedDict
+from math import inf
+from numbers import Number
+from typing import Dict, List, Optional, Set, Tuple
+from warnings import warn
+
+import numpy as np
+import torch
+from botorch.optim.utils import (
+ _get_extra_mll_args,
+ _handle_numerical_errors,
+ get_name_filter,
+ get_parameters_and_bounds,
+ TorchAttr,
+)
+from gpytorch.mlls import MarginalLogLikelihood
+from torch.nn import Module
+
+
+def module_to_array(
+ module: Module,
+ bounds: Optional[Dict[str, Tuple[Optional[float], Optional[float]]]] = None,
+ exclude: Optional[Set[str]] = None,
+) -> Tuple[np.ndarray, Dict[str, TorchAttr], Optional[np.ndarray]]:
+ r"""Extract named parameters from a module into a numpy array.
+
+ Only extracts parameters with requires_grad, since it is meant for optimizing.
+
+ Args:
+ module: A module with parameters. May specify parameter constraints in
+ a `named_parameters_and_constraints` method.
+ bounds: A dictionary mapping parameter names t lower and upper bounds.
+ of lower and upper bounds. Bounds specified here take precedence
+ over bounds on the same parameters specified in the constraints
+ registered with the module.
+ exclude: A list of parameter names that are to be excluded from extraction.
+
+ Returns:
+ 3-element tuple containing
+ - The parameter values as a numpy array.
+ - An ordered dictionary with the name and tensor attributes of each
+ parameter.
+ - A `2 x n_params` numpy array with lower and upper bounds if at least
+ one constraint is finite, and None otherwise.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ """
+ warn(
+ "`module_to_array` is marked for deprecation, consider using "
+ "`get_parameters_and_bounds`, `get_parameters_as_ndarray_1d`, or "
+ "`get_bounds_as_ndarray` instead.",
+ DeprecationWarning,
+ )
+ param_dict, bounds_dict = get_parameters_and_bounds(
+ module=module,
+ name_filter=None if exclude is None else get_name_filter(exclude),
+ requires_grad=True,
+ )
+ if bounds is not None:
+ bounds_dict.update(bounds)
+
+ # Record tensor metadata and read parameter values to the tape
+ param_tape: List[Number] = []
+ property_dict = OrderedDict()
+ with torch.no_grad():
+ for name, param in param_dict.items():
+ property_dict[name] = TorchAttr(param.shape, param.dtype, param.device)
+ param_tape.extend(param.view(-1).cpu().double().tolist())
+
+ # Extract lower and upper bounds
+ start = 0
+ bounds_np = None
+ params_np = np.asarray(param_tape)
+ for name, param in param_dict.items():
+ numel = param.numel()
+ if name in bounds_dict:
+ for row, bound in enumerate(bounds_dict[name]):
+ if bound is None:
+ continue
+
+ if torch.is_tensor(bound):
+ if (bound == (2 * row - 1) * inf).all():
+ continue
+ bound = bound.detach().cpu()
+
+ elif bound == (2 * row - 1) * inf:
+ continue
+
+ if bounds_np is None:
+ bounds_np = np.full((2, len(params_np)), ((-inf,), (inf,)))
+
+ bounds_np[row, start : start + numel] = bound
+ start += numel
+
+ return params_np, property_dict, bounds_np
+
+
+
+
+def set_params_with_array(
+ module: Module, x: np.ndarray, property_dict: Dict[str, TorchAttr]
+) -> Module:
+ r"""Set module parameters with values from numpy array.
+
+ Args:
+ module: Module with parameters to be set
+ x: Numpy array with parameter values
+ property_dict: Dictionary of parameter names and torch attributes as
+ returned by module_to_array.
+
+ Returns:
+ Module: module with parameters updated in-place.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ >>> parameter_array += 0.1 # perturb parameters (for example only)
+ >>> mll = set_params_with_array(mll, parameter_array, property_dict)
+ """
+ warn(
+ "`_set_params_with_array` is marked for deprecation, consider using "
+ "`set_parameters_from_ndarray_1d` instead.",
+ DeprecationWarning,
+ )
+ param_dict = OrderedDict(module.named_parameters())
+ start_idx = 0
+ for p_name, attrs in property_dict.items():
+ # Construct the new tensor
+ if len(attrs.shape) == 0: # deal with scalar tensors
+ end_idx = start_idx + 1
+ new_data = torch.tensor(
+ x[start_idx], dtype=attrs.dtype, device=attrs.device
+ )
+ else:
+ end_idx = start_idx + np.prod(attrs.shape)
+ new_data = torch.tensor(
+ x[start_idx:end_idx], dtype=attrs.dtype, device=attrs.device
+ ).view(*attrs.shape)
+ start_idx = end_idx
+ # Update corresponding parameter in-place. Disable autograd to update.
+ param_dict[p_name].requires_grad_(False)
+ param_dict[p_name].copy_(new_data)
+ param_dict[p_name].requires_grad_(True)
+ return module
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-310.pyc b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..959217118386bd8a25ac95f8c011aa1bdcbf5d2c
Binary files /dev/null and b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-310.pyc differ
diff --git a/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-311.pyc b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9912c13f6a45ceb9babb337ba03602f2eee09fe4
Binary files /dev/null and b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-311.pyc differ
diff --git a/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-38.pyc b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8db8301fee9d2e1d1eac613ade1e5c5d1226f6c7
Binary files /dev/null and b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-38.pyc differ
diff --git a/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-39.pyc b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1b47b2891aeaa7c8158f00d845df5663608189c1
Binary files /dev/null and b/pfns4bo/scripts/__pycache__/acquisition_functions.cpython-39.pyc differ
diff --git a/pfns4bo/scripts/__pycache__/tune_input_warping.cpython-311.pyc b/pfns4bo/scripts/__pycache__/tune_input_warping.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b0d34065bc688a9a76e59dce990d614c6d0656c7
Binary files /dev/null and b/pfns4bo/scripts/__pycache__/tune_input_warping.cpython-311.pyc differ
diff --git a/pfns4bo/scripts/__pycache__/tune_input_warping.cpython-39.pyc b/pfns4bo/scripts/__pycache__/tune_input_warping.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f9887201c9e6b92953f23d00c86bf9a8544f08c2
Binary files /dev/null and b/pfns4bo/scripts/__pycache__/tune_input_warping.cpython-39.pyc differ
diff --git a/pfns4bo/scripts/acquisition_functions.py b/pfns4bo/scripts/acquisition_functions.py
new file mode 100644
index 0000000000000000000000000000000000000000..700f367914fe7b9d88892d0c5212148fe69fb50b
--- /dev/null
+++ b/pfns4bo/scripts/acquisition_functions.py
@@ -0,0 +1,509 @@
+import contextlib
+
+from .. import transformer
+from .. import bar_distribution
+import torch
+import scipy
+import math
+from sklearn.preprocessing import power_transform, PowerTransformer
+
+def log01(x, eps=.0000001, input_between_zero_and_one=False):
+ logx = torch.log(x + eps)
+ if input_between_zero_and_one:
+ return (logx - math.log(eps)) / (math.log(1 + eps) - math.log(eps))
+ return (logx - logx.min(0)[0]) / (logx.max(0)[0] - logx.min(0)[0])
+
+def log01_batch(x, eps=.0000001, input_between_zero_and_one=False):
+ x = x.repeat(1, x.shape[-1] + 1, 1)
+ for b in range(x.shape[-1]):
+ x[:, b, b] = log01(x[:, b, b], eps=eps, input_between_zero_and_one=input_between_zero_and_one)
+ return x
+
+def lognormed_batch(x, eval_pos, eps=.0000001):
+ x = x.repeat(1, x.shape[-1] + 1, 1)
+ for b in range(x.shape[-1]):
+ logx = torch.log(x[:, b, b]+eps)
+ x[:, b, b] = (logx - logx[:eval_pos].mean(0))/logx[:eval_pos].std(0)
+ return x
+
+def _rank_transform(x_train, x):
+ assert len(x_train.shape) == len(x.shape) == 1
+ relative_to = torch.cat((torch.zeros_like(x_train[:1]),x_train.unique(sorted=True,), torch.ones_like(x_train[-1:])),-1)
+ higher_comparison = (relative_to < x[...,None]).sum(-1).clamp(min=1)
+ pos_inside_interval = (x - relative_to[higher_comparison-1])/(relative_to[higher_comparison] - relative_to[higher_comparison-1])
+ x_transformed = higher_comparison - 1 + pos_inside_interval
+ return x_transformed/(len(relative_to)-1.)
+
+def rank_transform(x_train, x):
+ assert x.shape[1] == x_train.shape[1], f"{x.shape=} and {x_train.shape=}"
+ # make sure everything is between 0 and 1
+ assert (x_train >= 0.).all() and (x_train <= 1.).all(), f"{x_train=}"
+ assert (x >= 0.).all() and (x <= 1.).all(), f"{x=}"
+ return_x = x.clone()
+ for feature_dim in range(x.shape[1]):
+ return_x[:, feature_dim] = _rank_transform(x_train[:, feature_dim], x[:, feature_dim])
+ return return_x
+
+
+
+def general_power_transform(x_train, x_apply, eps, less_safe=False):
+ if eps > 0:
+ try:
+ pt = PowerTransformer(method='box-cox')
+ pt.fit(x_train.cpu()+eps)
+ x_out = torch.tensor(pt.transform(x_apply.cpu()+eps), dtype=x_apply.dtype, device=x_apply.device)
+ except ValueError as e:
+ print(e)
+ x_out = x_apply - x_train.mean(0)
+ else:
+ pt = PowerTransformer(method='yeo-johnson')
+ if not less_safe and (x_train.std() > 1_000 or x_train.mean().abs() > 1_000):
+ x_apply = (x_apply - x_train.mean(0)) / x_train.std(0)
+ x_train = (x_train - x_train.mean(0)) / x_train.std(0)
+ # print('inputs are LAARGEe, normalizing them')
+ try:
+ pt.fit(x_train.cpu().double())
+ except ValueError as e:
+ print('caught this errrr', e)
+ if less_safe:
+ x_train = (x_train - x_train.mean(0)) / x_train.std(0)
+ x_apply = (x_apply - x_train.mean(0)) / x_train.std(0)
+ else:
+ x_train = x_train - x_train.mean(0)
+ x_apply = x_apply - x_train.mean(0)
+ pt.fit(x_train.cpu().double())
+ x_out = torch.tensor(pt.transform(x_apply.cpu()), dtype=x_apply.dtype, device=x_apply.device)
+ if torch.isnan(x_out).any() or torch.isinf(x_out).any():
+ print('WARNING: power transform failed')
+ print(f"{x_train=} and {x_apply=}")
+ x_out = x_apply - x_train.mean(0)
+ return x_out
+
+
+
+#@torch.inference_mode()
+def general_acq_function(model: transformer.TransformerModel, x_given, y_given, x_eval, apply_power_transform=True,
+ rand_sample=False, znormalize=False, pre_normalize=False, pre_znormalize=False, predicted_mean_fbest=False,
+ input_znormalize=False, max_dataset_size=10_000, remove_features_with_one_value_only=False,
+ return_actual_ei=False, acq_function='ei', ucb_rest_prob=.05, ensemble_log_dims=False,
+ ensemble_type='mean_probs', # in ('mean_probs', 'max_acq')
+ input_power_transform=False, power_transform_eps=.0, input_power_transform_eps=.0,
+ input_rank_transform=False, ensemble_input_rank_transform=False,
+ ensemble_power_transform=False, ensemble_feature_rotation=False,
+ style=None, outlier_stretching_interval=0.0, verbose=False, unsafe_power_transform=False,
+ ):
+ """
+ Differences to HEBO:
+ - The noise can't be set in the same way, as it depends on the tuning of HPs via VI.
+ - Log EI and PI are always used directly instead of using the approximation.
+
+ This is a stochastic function, relying on torch.randn
+
+ :param model:
+ :param x_given: torch.Tensor of shape (N, D)
+ :param y_given: torch.Tensor of shape (N, 1) or (N,)
+ :param x_eval: torch.Tensor of shape (M, D)
+ :param kappa:
+ :param eps:
+ :return:
+ """
+ assert ensemble_type in ('mean_probs', 'max_acq')
+ if rand_sample is not False \
+ and (len(x_given) == 0 or
+ ((1 + x_given.shape[1] if rand_sample is None else max(2, rand_sample)) > x_given.shape[0])):
+ print('rando')
+ return torch.zeros_like(x_eval[:,0]) #torch.randperm(x_eval.shape[0])[0]
+ y_given = y_given.reshape(-1)
+ assert len(y_given) == len(x_given)
+ if apply_power_transform:
+ if pre_normalize:
+ y_normed = y_given / y_given.std()
+ if not torch.isinf(y_normed).any() and not torch.isnan(y_normed).any():
+ y_given = y_normed
+ elif pre_znormalize:
+ y_znormed = (y_given - y_given.mean()) / y_given.std()
+ if not torch.isinf(y_znormed).any() and not torch.isnan(y_znormed).any():
+ y_given = y_znormed
+ y_given = general_power_transform(y_given.unsqueeze(1), y_given.unsqueeze(1), power_transform_eps, less_safe=unsafe_power_transform).squeeze(1)
+ if verbose:
+ print(f"{y_given=}")
+ #y_given = torch.tensor(power_transform(y_given.cpu().unsqueeze(1), method='yeo-johnson', standardize=znormalize), device=y_given.device, dtype=y_given.dtype,).squeeze(1)
+ y_given_std = torch.tensor(1., device=y_given.device, dtype=y_given.dtype)
+ if znormalize and not apply_power_transform:
+ if len(y_given) > 1:
+ y_given_std = y_given.std()
+ y_given_mean = y_given.mean()
+ y_given = (y_given - y_given_mean) / y_given_std
+
+ if remove_features_with_one_value_only:
+ x_all = torch.cat([x_given, x_eval], dim=0)
+ only_one_value_feature = torch.tensor([len(torch.unique(x_all[:,i])) for i in range(x_all.shape[1])]) == 1
+ x_given = x_given[:,~only_one_value_feature]
+ x_eval = x_eval[:,~only_one_value_feature]
+
+ if outlier_stretching_interval > 0.:
+ tx = torch.cat([x_given, x_eval], dim=0)
+ m = outlier_stretching_interval
+ eps = 1e-10
+ small_values = (tx < m) & (tx > 0.)
+ tx[small_values] = m * (torch.log(tx[small_values] + eps) - math.log(eps)) / (math.log(m + eps) - math.log(eps))
+
+ large_values = (tx > 1. - m) & (tx < 1.)
+ tx[large_values] = 1. - m * (torch.log(1 - tx[large_values] + eps) - math.log(eps)) / (
+ math.log(m + eps) - math.log(eps))
+ x_given = tx[:len(x_given)]
+ x_eval = tx[len(x_given):]
+
+ if input_znormalize: # implementation that relies on the test set, too...
+ std = x_given.std(dim=0)
+ std[std == 0.] = 1.
+ mean = x_given.mean(dim=0)
+ x_given = (x_given - mean) / std
+ x_eval = (x_eval - mean) / std
+
+ if input_power_transform:
+ x_given = general_power_transform(x_given, x_given, input_power_transform_eps)
+ x_eval = general_power_transform(x_given, x_eval, input_power_transform_eps)
+
+ if input_rank_transform is True or input_rank_transform == 'full': # uses test set x statistics...
+ x_all = torch.cat((x_given,x_eval), dim=0)
+ for feature_dim in range(x_all.shape[-1]):
+ uniques = torch.sort(torch.unique(x_all[..., feature_dim])).values
+ x_eval[...,feature_dim] = torch.searchsorted(uniques,x_eval[..., feature_dim]).float() / (len(uniques)-1)
+ x_given[...,feature_dim] = torch.searchsorted(uniques,x_given[..., feature_dim]).float() / (len(uniques)-1)
+ elif input_rank_transform is False:
+ pass
+ elif input_rank_transform == 'train':
+ x_given = rank_transform(x_given, x_given)
+ x_eval = rank_transform(x_given, x_eval)
+ elif input_rank_transform.startswith('train'):
+ likelihood = float(input_rank_transform.split('_')[-1])
+ if torch.rand(1).item() < likelihood:
+ print('rank transform')
+ x_given = rank_transform(x_given, x_given)
+ x_eval = rank_transform(x_given, x_eval)
+ else:
+ raise NotImplementedError
+
+
+ # compute logits
+ criterion: bar_distribution.BarDistribution = model.criterion
+ x_predict = torch.cat([x_given, x_eval], dim=0)
+
+
+ logits_list = []
+ for x_feed in torch.split(x_predict, max_dataset_size, dim=0):
+ x_full_feed = torch.cat([x_given, x_feed], dim=0).unsqueeze(1)
+ y_full_feed = y_given.unsqueeze(1)
+ if ensemble_log_dims == '01':
+ x_full_feed = log01_batch(x_full_feed)
+ elif ensemble_log_dims == 'global01' or ensemble_log_dims is True:
+ x_full_feed = log01_batch(x_full_feed, input_between_zero_and_one=True)
+ elif ensemble_log_dims == '01-10':
+ x_full_feed = torch.cat((log01_batch(x_full_feed)[:, :-1], log01_batch(1. - x_full_feed)), 1)
+ elif ensemble_log_dims == 'norm':
+ x_full_feed = lognormed_batch(x_full_feed, len(x_given))
+ elif ensemble_log_dims is not False:
+ raise NotImplementedError
+
+ if ensemble_feature_rotation:
+ x_full_feed = torch.cat([x_full_feed[:, :, (i+torch.arange(x_full_feed.shape[2])) % x_full_feed.shape[2]] for i in range(x_full_feed.shape[2])], dim=1)
+
+ if ensemble_input_rank_transform == 'train' or ensemble_input_rank_transform is True:
+ x_full_feed = torch.cat([rank_transform(x_given, x_full_feed[:,i,:])[:,None] for i in range(x_full_feed.shape[1])] + [x_full_feed], dim=1)
+
+ if ensemble_power_transform:
+ assert apply_power_transform is False
+ y_full_feed = torch.cat((general_power_transform(y_full_feed, y_full_feed, power_transform_eps), y_full_feed), dim=1)
+
+
+ if style is not None:
+ if callable(style):
+ style = style()
+
+ if isinstance(style, torch.Tensor):
+ style = style.to(x_full_feed.device)
+ else:
+ style = torch.tensor(style, device=x_full_feed.device).view(1, 1).repeat(x_full_feed.shape[1], 1)
+
+
+ logits = model(
+ (style,
+ x_full_feed.repeat_interleave(dim=1, repeats=y_full_feed.shape[1]),
+ y_full_feed.repeat(1,x_full_feed.shape[1])),
+ single_eval_pos=len(x_given)
+ )
+ if ensemble_type == 'mean_probs':
+ logits = logits.softmax(-1).mean(1, keepdim=True).log_() # (num given + num eval, 1, num buckets)
+ # print('in ensemble_type == mean_probs ')
+
+ logits_list.append(logits) # (< max_dataset_size, 1 , num_buckets)
+ logits = torch.cat(logits_list, dim=0) # (num given + num eval, 1 or (num_features+1), num buckets)
+ del logits_list, x_full_feed
+ if torch.isnan(logits).any():
+ print('nan logits')
+ print(f"y_given: {y_given}, x_given: {x_given}, x_eval: {x_eval}")
+ print(f"logits: {logits}")
+ return torch.zeros_like(x_eval[:,0])
+
+ #logits = model((torch.cat([x_given, x_given, x_eval], dim=0).unsqueeze(1),
+ # torch.cat([y_given, torch.zeros(len(x_eval)+len(x_given), device=y_given.device)], dim=0).unsqueeze(1)),
+ # single_eval_pos=len(x_given))[:,0] # (N + M, num_buckets)
+ logits_given = logits[:len(x_given)]
+ logits_eval = logits[len(x_given):]
+
+ #tau = criterion.mean(logits_given)[torch.argmax(y_given)] # predicted mean at the best y
+ if predicted_mean_fbest:
+ tau = criterion.mean(logits_given)[torch.argmax(y_given)].squeeze(0)
+ else:
+ tau = torch.max(y_given)
+ #log_ei = torch.stack([criterion.ei(logits_eval[:,i], noisy_best_f[i]).log() for i in range(len(logits_eval))],0)
+
+ def acq_ensembling(acq_values): # (points, ensemble dim)
+ return acq_values.max(1).values
+
+ if isinstance(acq_function, (dict,list)):
+ acq_function = acq_function[style]
+
+ if acq_function == 'ei':
+ acq_value = acq_ensembling(criterion.ei(logits_eval, tau))
+ elif acq_function == 'ei_or_rand':
+ if torch.rand(1).item() < 0.5:
+ acq_value = torch.rand(len(x_eval))
+ else:
+ acq_value = acq_ensembling(criterion.ei(logits_eval, tau))
+ elif acq_function == 'pi':
+ acq_value = acq_ensembling(criterion.pi(logits_eval, tau))
+ elif acq_function == 'ucb':
+ acq_function = criterion.ucb
+ if ucb_rest_prob is not None:
+ acq_function = lambda *args: criterion.ucb(*args, rest_prob=ucb_rest_prob)
+ acq_value = acq_ensembling(acq_function(logits_eval, tau))
+ elif acq_function == 'mean':
+ acq_value = acq_ensembling(criterion.mean(logits_eval))
+ elif acq_function.startswith('hebo'):
+ noise, upsi, delta, eps = (float(v) for v in acq_function.split('_')[1:])
+ noise = y_given_std * math.sqrt(2 * noise)
+ kappa = math.sqrt(upsi * 2 * ((2.0 + x_given.shape[1] / 2.0) * math.log(max(1, len(x_given))) + math.log(
+ 3 * math.pi ** 2 / (3 * delta))))
+ rest_prob = 1. - .5 * (1 + torch.erf(torch.tensor(kappa / math.sqrt(2), device=logits.device)))
+ ucb = acq_ensembling(criterion.ucb(logits_eval, None, rest_prob=rest_prob)) \
+ + torch.randn(len(logits_eval), device=logits_eval.device) * noise
+ noisy_best_f = tau + eps + \
+ noise * torch.randn(len(logits_eval), device=logits_eval.device)[:, None].repeat(1, logits_eval.shape[1])
+
+ log_pi = acq_ensembling(criterion.pi(logits_eval, noisy_best_f).log())
+ # log_ei = torch.stack([criterion.ei(logits_eval[:,i], noisy_best_f[i]).log() for i in range(len(logits_eval))],0)
+ log_ei = acq_ensembling(criterion.ei(logits_eval, noisy_best_f).log())
+
+ acq_values = torch.stack([ucb, log_ei, log_pi], dim=1)
+
+ def is_pareto_efficient(costs):
+ """
+ Find the pareto-efficient points
+ :param costs: An (n_points, n_costs) array
+ :return: A (n_points, ) boolean array, indicating whether each point is Pareto efficient
+ """
+ is_efficient = torch.ones(costs.shape[0], dtype=bool, device=costs.device)
+ for i, c in enumerate(costs):
+ if is_efficient[i]:
+ is_efficient[is_efficient.clone()] = (costs[is_efficient] < c).any(
+ 1) # Keep any point with a lower cost
+ is_efficient[i] = True # And keep self
+ return is_efficient
+
+ acq_value = is_pareto_efficient(-acq_values)
+ else:
+ raise ValueError(f'Unknown acquisition function: {acq_function}')
+
+ max_acq = acq_value.max()
+
+ return acq_value if return_actual_ei else (acq_value == max_acq)
+
+
+def optimize_acq(model, known_x, known_y, num_grad_steps=10, num_random_samples=100, lr=.01, **kwargs):
+ """
+ intervals are assumed to be between 0 and 1
+ only works with ei
+ recommended extra kwarg: ensemble_input_rank_transform=='train'
+
+ :param model: model to optimize, should already handle different num_features with its encoder
+ You can add this simply with `model.encoder = encoders.VariableNumFeaturesEncoder(model.encoder, model.encoder.num_features)`
+ :param known_x: (N, num_features)
+ :param known_y: (N,)
+ :param num_grad_steps: int
+ :param num_random_samples: int
+ :param lr: float
+ :param kwargs: will be given to `general_acq_function`
+ :return:
+ """
+ x_eval = torch.rand(num_random_samples, known_x.shape[1]).requires_grad_(True)
+ opt = torch.optim.Adam(params=[x_eval], lr=lr)
+ best_acq, best_x = -float('inf'), x_eval[0].detach()
+ for grad_step in range(num_grad_steps):
+ acq = general_acq_function(model, known_x, known_y, x_eval, return_actual_ei=True, **kwargs)
+ max_acq = acq.detach().max().item()
+ if max_acq > best_acq:
+ best_x = x_eval[acq.argmax()].detach()
+ best_acq = max_acq
+
+ (-acq.mean()).backward()
+ assert (x_eval.grad != 0.).any()
+ if torch.isfinite(x_eval.grad).all():
+ opt.step()
+ opt.zero_grad()
+ with torch.no_grad():
+ x_eval.clamp_(min=0., max=1.)
+
+ return best_x
+
+
+def optimize_acq_w_lbfgs(model, known_x, known_y, num_grad_steps=15_000, num_candidates=100, pre_sample_size=100_000, device='cpu',
+ verbose=False, dims_wo_gradient_opt=[], rand_sample_func=None, **kwargs):
+ """
+ intervals are assumed to be between 0 and 1
+ only works with deterministic acq
+ recommended extra kwarg: ensemble_input_rank_transform=='train'
+
+ :param model: model to optimize, should already handle different num_features with its encoder
+ You can add this simply with `model.encoder = encoders.VariableNumFeaturesEncoder(model.encoder, model.encoder.num_features)`
+ :param known_x: (N, num_features)
+ :param known_y: (N,)
+ :param num_grad_steps: int: how many steps to take inside of scipy, can be left high, as it stops most of the time automatically early
+ :param num_candidates: int: how many candidates to optimize with LBFGS, increases costs when higher
+ :param pre_sample_size: int: how many settings to try first with a random search, before optimizing the best with grads
+ :param dims_wo_gradient_opt: int: which dimensions to not optimize with gradients, but with random search only
+ :param rand_sample_func: function: how to sample random points, should be a function that takes a number of samples and returns a tensor
+ For example `lambda n: torch.rand(n, known_x.shape[1])`.
+ :param kwargs: will be given to `general_acq_function`
+ :return:
+ """
+ num_features = known_x.shape[1]
+ dims_w_gradient_opt = sorted(set(range(num_features)) - set(dims_wo_gradient_opt))
+ known_x = known_x.to(device)
+ known_y = known_y.to(device)
+ pre_sample_size = max(pre_sample_size, num_candidates)
+ rand_sample_func = rand_sample_func or (lambda n: torch.rand(n, num_features, device=device))
+ if len(known_x) < pre_sample_size:
+ x_initial = torch.cat((rand_sample_func(pre_sample_size-len(known_x)).to(device), known_x), 0)
+ else:
+ x_initial = rand_sample_func(pre_sample_size)
+ x_initial = x_initial.clamp(min=0., max=1.)
+ x_initial_all = x_initial
+ model.to(device)
+
+ with torch.no_grad():
+ acq = general_acq_function(model, known_x, known_y, x_initial.to(device), return_actual_ei=True, **kwargs)
+ if verbose:
+ import matplotlib.pyplot as plt
+ if x_initial.shape[1] == 2:
+ plt.title('initial acq values, red -> blue')
+ plt.scatter(x_initial[:, 0][:100], x_initial[:, 1][:100], c=acq.cpu().numpy()[:100], cmap='RdBu')
+ x_initial = x_initial[acq.argsort(descending=True)[:num_candidates].cpu()].detach() # num_candidates x num_features
+
+ x_initial_all_ei = acq.cpu().detach()
+
+ def opt_f(x):
+ x_eval = torch.tensor(x).view(-1, len(dims_w_gradient_opt)).float().to(device).requires_grad_(True)
+ x_eval_new = x_initial.clone().detach().to(device)
+ x_eval_new[:, dims_w_gradient_opt] = x_eval
+
+ assert x_eval_new.requires_grad
+ assert not torch.isnan(x_eval_new).any()
+ model.requires_grad_(False)
+ acq = general_acq_function(model, known_x, known_y, x_eval_new, return_actual_ei=True, **kwargs)
+ neg_mean_acq = -acq.mean()
+ neg_mean_acq.backward()
+ #print(neg_mean_acq.detach().numpy(), x_eval.grad.detach().view(*x.shape).numpy())
+ with torch.no_grad():
+ x_eval.grad[x_eval.grad != x_eval.grad] = 0.
+ return neg_mean_acq.detach().cpu().to(torch.float64).numpy(), \
+ x_eval.grad.detach().view(*x.shape).cpu().to(torch.float64).numpy()
+
+ # Optimize best candidates with LBFGS
+ if num_grad_steps > 0 and len(dims_w_gradient_opt) > 0:
+ # the columns not in dims_wo_gradient_opt will be optimized with gradients
+ x_initial_for_gradient_opt = x_initial[:, dims_w_gradient_opt].detach().cpu().flatten().numpy() # x_initial.cpu().flatten().numpy()
+ res = scipy.optimize.minimize(opt_f, x_initial_for_gradient_opt, method='L-BFGS-B', jac=True,
+ bounds=[(0, 1)]*x_initial_for_gradient_opt.size,
+ options={'maxiter': num_grad_steps})
+ results = x_initial.cpu()
+ results[:, dims_w_gradient_opt] = torch.tensor(res.x).float().view(-1, len(dims_w_gradient_opt))
+
+ else:
+ results = x_initial.cpu()
+
+ results = results.clamp(min=0., max=1.)
+
+ # Recalculate the acq values for the best candidates
+ with torch.no_grad():
+ acq = general_acq_function(model, known_x, known_y, results.to(device), return_actual_ei=True, verbose=verbose, **kwargs)
+ #print(acq)
+ if verbose:
+ from scipy.stats import rankdata
+ import matplotlib.pyplot as plt
+ if results.shape[1] == 2:
+ plt.scatter(results[:, 0], results[:, 1], c=rankdata(acq.cpu().numpy()), marker='x', cmap='RdBu')
+ plt.show()
+ best_x = results[acq.argmax().item()].detach()
+
+ acq_order = acq.argsort(descending=True).cpu()
+ all_order = x_initial_all_ei.argsort(descending=True).cpu()
+
+ return best_x.detach(), results[acq_order].detach(), acq.cpu()[acq_order].detach(), x_initial_all.cpu()[all_order].detach(), x_initial_all_ei.cpu()[all_order].detach()
+
+from ..utils import to_tensor
+
+class TransformerBOMethod:
+
+ def __init__(self, model, acq_f=general_acq_function, device='cpu:0', fit_encoder=None, **kwargs):
+ self.model = model
+ self.device = device
+ self.kwargs = kwargs
+ self.acq_function = acq_f
+ self.fit_encoder = fit_encoder
+
+ @torch.no_grad()
+ def observe_and_suggest(self, X_obs, y_obs, X_pen, return_actual_ei=False):
+ # assert X_pen is not None
+ # assumptions about X_obs and X_pen:
+ # X_obs is a numpy array of shape (n_samples, n_features)
+ # y_obs is a numpy array of shape (n_samples,), between 0 and 1
+ # X_pen is a numpy array of shape (n_samples_left, n_features)
+ X_obs = to_tensor(X_obs, device=self.device).to(torch.float32)
+ y_obs = to_tensor(y_obs, device=self.device).to(torch.float32).view(-1)
+ X_pen = to_tensor(X_pen, device=self.device).to(torch.float32)
+
+ assert len(X_obs) == len(y_obs), "make sure both X_obs and y_obs have the same length."
+
+ self.model.to(self.device)
+
+ if self.fit_encoder is not None:
+ w = self.fit_encoder(self.model, X_obs, y_obs)
+ X_obs = w(X_obs)
+ X_pen = w(X_pen)
+
+
+ # with (torch.cuda.amp.autocast() if self.device.type != 'cpu' else contextlib.nullcontext()):
+ with (torch.cuda.amp.autocast() if self.device[:3] != 'cpu' else contextlib.nullcontext()):
+ acq_values = self.acq_function(self.model, X_obs, y_obs,
+ X_pen, return_actual_ei=return_actual_ei, **self.kwargs).cpu().clone() # bool array
+ acq_mask = acq_values.max() == acq_values
+ possible_next = torch.arange(len(X_pen))[acq_mask]
+ if len(possible_next) == 0:
+ possible_next = torch.arange(len(X_pen))
+
+ r = possible_next[torch.randperm(len(possible_next))[0]].cpu().item()
+
+
+ if return_actual_ei:
+ return r, acq_values
+ else:
+ return r
+
+
+
+
+
+
+
diff --git a/pfns4bo/scripts/tune_input_warping.py b/pfns4bo/scripts/tune_input_warping.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb18f2384579bdace84f6c1f333e126d892467a5
--- /dev/null
+++ b/pfns4bo/scripts/tune_input_warping.py
@@ -0,0 +1,538 @@
+from __future__ import annotations
+
+import random
+from collections import OrderedDict
+import torch
+
+from .. import utils
+from ..priors.hebo_prior import Warp
+from gpytorch.priors import LogNormalPrior
+
+# from botorch.optim import module_to_array, set_params_with_array
+# from .. import module_to_array, set_params_with_array
+
+import scipy
+from scipy.optimize import Bounds
+from typing import OrderedDict
+import numpy as np
+from functools import partial
+
+device = 'cpu'
+
+
+def fit_lbfgs(x, w, nll, num_grad_steps=10, ignore_prior=True, params0=None):
+ bounds_ = {}
+ if hasattr(w, "named_parameters_and_constraints"):
+ for param_name, _, constraint in w.named_parameters_and_constraints():
+ if constraint is not None and not constraint.enforced:
+ bounds_[param_name] = constraint.lower_bound, constraint.upper_bound
+ params0_, property_dict, bounds_ = module_to_array(
+ module=w, bounds=bounds_, exclude=None
+ )
+ if params0 is None: params0 = params0_
+ bounds = Bounds(lb=bounds_[0], ub=bounds_[1], keep_feasible=True)
+
+ def loss_f(params, w):
+ w = set_params_with_array(w, params, property_dict)
+ w.requires_grad_(True)
+ loss = 0.
+ if not ignore_prior:
+ for name, module, prior, closure, _ in w.named_priors():
+ prior_term = prior.log_prob(closure(module))
+ loss -= prior_term.sum(dim=-1)
+ negll = nll(w(x.to(torch.float64)).to(torch.float)).sum()
+ #if loss != 0.:
+ # print(loss.item(), negll.item())
+ loss = loss + negll
+ return w, loss
+
+ def opt_f(params, w):
+ w, loss = loss_f(params, w)
+
+ w.zero_grad()
+ loss.backward()
+ grad = []
+ param_dict = OrderedDict(w.named_parameters())
+
+ for p_name in property_dict:
+ t = param_dict[p_name].grad
+ if t is None:
+ # this deals with parameters that do not affect the loss
+ grad.append(np.zeros(property_dict[p_name].shape.numel()))
+ else:
+ grad.append(t.detach().view(-1).cpu().double().clone().numpy())
+ w.zero_grad()
+ # print(neg_mean_acq.detach().numpy(), x_eval.grad.detach().view(*x.shape).numpy())
+ return loss.item(), np.concatenate(grad)
+
+ if num_grad_steps:
+ return scipy.optimize.minimize(partial(opt_f, w=w), params0, method='L-BFGS-B', jac=True, bounds=bounds,
+ options={'maxiter': num_grad_steps})
+ else:
+ with torch.no_grad():
+ return loss_f(params0, w), params0
+
+
+def log_vs_nonlog(x, w, *args, **kwargs):
+ if "true_nll" in kwargs:
+ true_nll = kwargs["true_nll"]
+ del kwargs["true_nll"]
+ else:
+ true_nll = None
+ params, property_dict, _ = module_to_array(module=w)
+ no_log = np.ones_like(params)
+ log = np.array([1.9, 0.11] * (int(len(property_dict) / 2)))
+ loss_no_log = fit_lbfgs(x, w, *args, **{**kwargs, 'num_grad_steps': 0}, params0=no_log)
+ loss_log = fit_lbfgs(x, w, *args, **{**kwargs, 'num_grad_steps': 0}, params0=log)
+ print("loss no log", loss_no_log[0][1], "loss log", loss_log[0][1])
+ if loss_no_log[0][1] < loss_log[0][1]:
+ set_params_with_array(module=w, x=loss_no_log[1], property_dict=property_dict)
+ if true_nll:
+ best_params, _, _ = module_to_array(module=w)
+ print("true nll", fit_lbfgs(x, w, true_nll, **{**kwargs, 'num_grad_steps': 0}, params0=best_params))
+
+
+def fit_lbfgs_with_restarts(x, w, *args, old_solution=None, rs_size=50, **kwargs):
+ if "true_nll" in kwargs:
+ true_nll = kwargs["true_nll"]
+ del kwargs["true_nll"]
+ else:
+ true_nll = None
+ rs_results = []
+ if old_solution:
+ rs_results.append(fit_lbfgs(x, old_solution, *args, **{**kwargs, 'num_grad_steps': 0}))
+ for i in range(rs_size):
+ with torch.no_grad():
+ w.concentration0[:] = w.concentration0_prior()
+ w.concentration1[:] = w.concentration1_prior()
+ rs_results.append(fit_lbfgs(x, w, *args, **{**kwargs, 'num_grad_steps': 0}))
+ best_r = min(rs_results, key=lambda r: r[0][1])
+ print('best r', best_r)
+ with torch.set_grad_enabled(True):
+ r = fit_lbfgs(x, w, *args, **kwargs, params0=best_r[1])
+ _, property_dict, _ = module_to_array(module=w)
+ set_params_with_array(module=w, x=r.x, property_dict=property_dict)
+ print('final r', r)
+ if true_nll:
+ print("true nll", fit_lbfgs(x, w, true_nll, **{**kwargs, 'num_grad_steps': 0}, params0=r.x))
+ return r
+
+
+# use seed 0 for sampling indices, and reset seed afterwards
+old_seed = random.getstate()
+random.seed(0)
+one_out_indices_sampled_per_num_obs = [None]+[random.sample(range(i), min(10, i)) for i in range(1, 100)]
+random.setstate(old_seed)
+
+# use seed 0 for sampling subsets
+old_seed = random.getstate()
+random.seed(0)
+subsets = [None]+[[random.sample(range(i), i//2) for _ in range(10)] for i in range(1, 100)]
+neg_subsets = [None]+[[list(set(range(i)) - set(s)) for s in ss] for i, ss in enumerate(subsets[1:], 1)]
+random.setstate(old_seed)
+
+
+
+def fit_input_warping(model, x, y, nll_type='fast', old_solution=None, opt_method="lbfgs", **kwargs):
+ """
+
+ :param model:
+ :param x: shape (n, d)
+ :param y: shape (n, 1)
+ :param nll_type:
+ :param kwargs: Possible kwargs: `num_grad_steps`, `rs_size`
+ :return:
+ """
+ device = x.device
+ assert y.device == device, y.device
+
+ model.requires_grad_(False)
+
+ w = Warp(range(x.shape[1]),
+ concentration1_prior=LogNormalPrior(torch.tensor(0.0, device=device), torch.tensor(.75, device=device)),
+ concentration0_prior=LogNormalPrior(torch.tensor(0.0, device=device), torch.tensor(.75, device=device)),
+ eps=1e-12)
+ w.to(device)
+
+ def fast_nll(x): # noqa actually used with `eval` below
+ model.requires_grad_(False)
+ if model.style_encoder is not None:
+ style = torch.zeros(1, 1, dtype=torch.int64, device=device)
+ utils.print_once("WARNING: using style 0 for input warping, this is set for nonmyopic BO setting.")
+ else:
+ style = None
+ logits = model(x[:, None], y[:, None], x[:, None], style=style, only_return_standard_out=True)
+ loss = model.criterion(logits, y[:, None]).squeeze(1)
+ return loss
+
+ def true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ total_nll = 0.
+ for cutoff in range(len(x)):
+ logits = model(x[:cutoff, None], y[:cutoff, None], x[cutoff:cutoff + 1, None])
+ total_nll = total_nll + model.criterion(logits, y[cutoff:cutoff + 1, None]).squeeze()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def repeated_true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ total_nll = 0.
+ for i in range(5):
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ x_ = x.clone()[shuffle_idx]
+ y_ = y.clone()[shuffle_idx]
+ for cutoff in range(len(x)):
+ logits = model(x_[:cutoff, None], y_[:cutoff, None], x_[cutoff:cutoff + 1, None])
+ total_nll = total_nll + model.criterion(logits, y_[cutoff:cutoff + 1, None]).squeeze()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def repeated_true_100_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ total_nll = 0.
+ for i in range(100):
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ x_ = x.clone()[shuffle_idx]
+ y_ = y.clone()[shuffle_idx]
+ for cutoff in range(len(x)):
+ logits = model(x_[:cutoff, None], y_[:cutoff, None], x_[cutoff:cutoff + 1, None])
+ total_nll = total_nll + model.criterion(logits, y_[cutoff:cutoff + 1, None]).squeeze()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll / 100
+
+ def batched_repeated_chunked_true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ assert len(x.shape) == 2 and len(y.shape) == 1
+ model.requires_grad_(False)
+ n_features = x.shape[1] if len(x.shape) > 1 else 1
+ batch_size = 10
+
+ X = []
+ Y = []
+
+ for i in range(batch_size):
+ #if i == 0:
+ # shuffle_idx = list(range(len(x)))
+ #else:
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ X.append(x.clone()[shuffle_idx])
+ Y.append(y.clone()[shuffle_idx])
+ X = torch.stack(X, dim=1).view((x.shape[0], batch_size, n_features))
+ Y = torch.stack(Y, dim=1).view((x.shape[0], batch_size, 1))
+
+ total_nll = 0.
+ batch_indizes = sorted(list(set(np.linspace(0, len(x), 10, dtype=int))))
+
+ for chunk_start, chunk_end in zip(batch_indizes[:-1], batch_indizes[1:]):
+ X_cutoff = X[:chunk_start]
+ Y_cutoff = Y[:chunk_start]
+ X_after_cutoff = X[chunk_start:chunk_end]
+ Y_after_cutoff = Y[chunk_start:chunk_end]
+
+ pending_x = X_after_cutoff.reshape(X_after_cutoff.shape[0], batch_size, n_features) # n_pen x batch_size x n_feat
+ observed_x = X_cutoff.reshape(X_cutoff.shape[0], batch_size, n_features) # n_obs x batch_size x n_feat
+ X_tmp = torch.cat((observed_x, pending_x), dim=0) # (n_obs+n_pen) x batch_size x n_feat
+
+ logits = model((X_tmp, Y_cutoff), single_eval_pos=int(chunk_start))
+ total_nll = total_nll + model.criterion(logits, Y_after_cutoff).sum()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def batched_repeated_true_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "true nll not implemented for style encoder, see above for an example impl"
+ model.requires_grad_(False)
+ n_features = x.shape[1] if len(x.shape) > 1 else 1
+ batch_size = 10
+
+ X = []
+ Y = []
+
+ for i in range(batch_size):
+ #if i == 0:
+ # shuffle_idx = list(range(len(x)))
+ #else:
+ rs = np.random.RandomState(i)
+ shuffle_idx = rs.permutation(len(x))
+ X.append(x.clone()[shuffle_idx])
+ Y.append(y.clone()[shuffle_idx])
+ X = torch.cat(X, dim=1).reshape((x.shape[0], batch_size, n_features))
+ Y = torch.cat(Y, dim=1).reshape((x.shape[0], batch_size, 1))
+
+ total_nll = 0.
+
+ for cutoff in range(0, len(x)):
+ X_cutoff = X[:cutoff]
+ Y_cutoff = Y[:cutoff]
+ X_after_cutoff = X[cutoff:cutoff+1]
+ Y_after_cutoff = Y[cutoff:cutoff+1]
+
+ pending_x = X_after_cutoff.reshape(X_after_cutoff.shape[0], batch_size, n_features) # n_pen x batch_size x n_feat
+ observed_x = X_cutoff.reshape(X_cutoff.shape[0], batch_size, n_features) # n_obs x batch_size x n_feat
+ X_tmp = torch.cat((observed_x, pending_x), dim=0) # (n_obs+n_pen) x batch_size x n_feat
+
+ pad_y = torch.zeros((X_after_cutoff.shape[0], batch_size, 1)) # (n_obs+n_pen) x batch_size
+ Y_tmp = torch.cat((Y_cutoff, pad_y), dim=0)
+
+ logits = model((X_tmp, Y_tmp), single_eval_pos=cutoff)
+ total_nll = total_nll + model.criterion(logits, Y_after_cutoff).sum()
+ assert len(total_nll.shape) == 0, f"{total_nll.shape=}"
+ return total_nll
+
+ def one_out_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "one out nll not implemented for style encoder, see above for an example impl"
+ # x shape: (n, d)
+ # iterate over a pre-defined set of
+ model.requires_grad_(False)
+ #indices = one_out_indices_sampled_per_num_obs[len(x)]
+ indices = list(range(x.shape[0]))
+
+ # create batch by moving the one out index to the end
+ eval_x = x[indices][None] # shape (1, 10, d)
+ eval_y = y[indices][None] # shape (1, 10, 1)
+ # all other indices are used for training
+ train_x = torch.stack([torch.cat([x[:i], x[i + 1:]]) for i in indices], 1)
+ train_y = torch.stack([torch.cat([y[:i], y[i + 1:]]) for i in indices], 1)
+
+ logits = model(train_x, train_y, eval_x)
+ return model.criterion(logits, eval_y).squeeze(0)
+
+ def subset_nll(x): # noqa actually used with `eval` below
+ assert model.style_encoder is None, "subset nll not implemented for style encoder, see above for an example impl"
+ # x shape: (n, d)
+ # iterate over a pre-defined set of
+ model.requires_grad_(False)
+ eval_indices = torch.tensor(subsets[len(x)])
+ train_indices = torch.tensor(neg_subsets[len(x)])
+
+ # batch by using all eval_indices
+ eval_x = x[eval_indices.flatten()].view(eval_indices.shape + (-1,)) # shape (10, n//2, d)
+ eval_y = y[eval_indices.flatten()].view(eval_indices.shape + (-1,)) # shape (10, n//2, 1)
+ # all other indices are used for training
+ train_x = x[train_indices.flatten()].view(train_indices.shape + (-1,)) # shape (10, n//2, d)
+ train_y = y[train_indices.flatten()].view(train_indices.shape + (-1,)) # shape (10, n//2, 1)
+
+ logits = model(train_x.transpose(0, 1), train_y.transpose(0, 1), eval_x.transpose(0, 1))
+ return model.criterion(logits, eval_y.transpose(0, 1))
+
+ if opt_method == "log_vs_nolog":
+ log_vs_nonlog(x, w, eval(nll_type + '_nll'),
+ ignore_prior=True, # true_nll=repeated_true_100_nll,
+ **kwargs)
+ elif opt_method == "lbfgs":
+ fit_lbfgs_with_restarts(
+ x, w, eval(nll_type + '_nll'),
+ ignore_prior=True, old_solution=old_solution, # true_nll=repeated_true_100_nll,
+ **kwargs)
+ elif opt_method == "lbfgs_w_prior":
+ fit_lbfgs_with_restarts(
+ x, w, eval(nll_type + '_nll'),
+ ignore_prior=False, old_solution=old_solution, # true_nll=repeated_true_100_nll,
+ **kwargs)
+ else:
+ raise ValueError(opt_method)
+
+ return w
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#!/usr/bin/env python3
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+#
+# This source code is licensed under the MIT license found in the
+# LICENSE file in the root directory of this source tree.
+
+r"""
+A converter that simplifies using numpy-based optimizers with generic torch
+`nn.Module` classes. This enables using a `scipy.optim.minimize` optimizer
+for optimizing module parameters.
+"""
+
+
+
+from collections import OrderedDict
+from math import inf
+from numbers import Number
+from typing import Dict, List, Optional, Set, Tuple
+from warnings import warn
+
+import numpy as np
+import torch
+from botorch.optim.utils import (
+ _get_extra_mll_args,
+ _handle_numerical_errors,
+ get_name_filter,
+ get_parameters_and_bounds,
+ TorchAttr,
+)
+from gpytorch.mlls import MarginalLogLikelihood
+from torch.nn import Module
+
+
+def module_to_array(
+ module: Module,
+ bounds: Optional[Dict[str, Tuple[Optional[float], Optional[float]]]] = None,
+ exclude: Optional[Set[str]] = None,
+) -> Tuple[np.ndarray, Dict[str, TorchAttr], Optional[np.ndarray]]:
+ r"""Extract named parameters from a module into a numpy array.
+
+ Only extracts parameters with requires_grad, since it is meant for optimizing.
+
+ Args:
+ module: A module with parameters. May specify parameter constraints in
+ a `named_parameters_and_constraints` method.
+ bounds: A dictionary mapping parameter names t lower and upper bounds.
+ of lower and upper bounds. Bounds specified here take precedence
+ over bounds on the same parameters specified in the constraints
+ registered with the module.
+ exclude: A list of parameter names that are to be excluded from extraction.
+
+ Returns:
+ 3-element tuple containing
+ - The parameter values as a numpy array.
+ - An ordered dictionary with the name and tensor attributes of each
+ parameter.
+ - A `2 x n_params` numpy array with lower and upper bounds if at least
+ one constraint is finite, and None otherwise.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ """
+ warn(
+ "`module_to_array` is marked for deprecation, consider using "
+ "`get_parameters_and_bounds`, `get_parameters_as_ndarray_1d`, or "
+ "`get_bounds_as_ndarray` instead.",
+ DeprecationWarning,
+ )
+ param_dict, bounds_dict = get_parameters_and_bounds(
+ module=module,
+ name_filter=None if exclude is None else get_name_filter(exclude),
+ requires_grad=True,
+ )
+ if bounds is not None:
+ bounds_dict.update(bounds)
+
+ # Record tensor metadata and read parameter values to the tape
+ param_tape: List[Number] = []
+ property_dict = OrderedDict()
+ with torch.no_grad():
+ for name, param in param_dict.items():
+ property_dict[name] = TorchAttr(param.shape, param.dtype, param.device)
+ param_tape.extend(param.view(-1).cpu().double().tolist())
+
+ # Extract lower and upper bounds
+ start = 0
+ bounds_np = None
+ params_np = np.asarray(param_tape)
+ for name, param in param_dict.items():
+ numel = param.numel()
+ if name in bounds_dict:
+ for row, bound in enumerate(bounds_dict[name]):
+ if bound is None:
+ continue
+
+ if torch.is_tensor(bound):
+ if (bound == (2 * row - 1) * inf).all():
+ continue
+ bound = bound.detach().cpu()
+
+ elif bound == (2 * row - 1) * inf:
+ continue
+
+ if bounds_np is None:
+ bounds_np = np.full((2, len(params_np)), ((-inf,), (inf,)))
+
+ bounds_np[row, start : start + numel] = bound
+ start += numel
+
+ return params_np, property_dict, bounds_np
+
+
+
+
+def set_params_with_array(
+ module: Module, x: np.ndarray, property_dict: Dict[str, TorchAttr]
+) -> Module:
+ r"""Set module parameters with values from numpy array.
+
+ Args:
+ module: Module with parameters to be set
+ x: Numpy array with parameter values
+ property_dict: Dictionary of parameter names and torch attributes as
+ returned by module_to_array.
+
+ Returns:
+ Module: module with parameters updated in-place.
+
+ Example:
+ >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
+ >>> parameter_array, property_dict, bounds_out = module_to_array(mll)
+ >>> parameter_array += 0.1 # perturb parameters (for example only)
+ >>> mll = set_params_with_array(mll, parameter_array, property_dict)
+ """
+ warn(
+ "`_set_params_with_array` is marked for deprecation, consider using "
+ "`set_parameters_from_ndarray_1d` instead.",
+ DeprecationWarning,
+ )
+ param_dict = OrderedDict(module.named_parameters())
+ start_idx = 0
+ for p_name, attrs in property_dict.items():
+ # Construct the new tensor
+ if len(attrs.shape) == 0: # deal with scalar tensors
+ end_idx = start_idx + 1
+ new_data = torch.tensor(
+ x[start_idx], dtype=attrs.dtype, device=attrs.device
+ )
+ else:
+ end_idx = start_idx + np.prod(attrs.shape)
+ new_data = torch.tensor(
+ x[start_idx:end_idx], dtype=attrs.dtype, device=attrs.device
+ ).view(*attrs.shape)
+ start_idx = end_idx
+ # Update corresponding parameter in-place. Disable autograd to update.
+ param_dict[p_name].requires_grad_(False)
+ param_dict[p_name].copy_(new_data)
+ param_dict[p_name].requires_grad_(True)
+ return module
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pfns4bo/train.py b/pfns4bo/train.py
new file mode 100644
index 0000000000000000000000000000000000000000..46e6e7ec1795e63929a6abb7369b96b39a81ac77
--- /dev/null
+++ b/pfns4bo/train.py
@@ -0,0 +1,330 @@
+from __future__ import annotations
+
+import itertools
+import time
+import yaml
+from contextlib import nullcontext
+from tqdm import tqdm
+
+import torch
+from torch import nn
+from torch.cuda.amp import autocast, GradScaler
+
+from . import utils
+from .priors import prior
+from . import priors
+from .transformer import TransformerModel
+from .bar_distribution import BarDistribution, FullSupportBarDistribution, get_bucket_limits, get_custom_bar_dist
+from .utils import get_cosine_schedule_with_warmup, get_openai_lr, StoreDictKeyPair, get_weighted_single_eval_pos_sampler, get_uniform_single_eval_pos_sampler
+from . import positional_encodings
+from .utils import init_dist
+
+class Losses():
+ gaussian = nn.GaussianNLLLoss(full=True, reduction='none')
+ mse = nn.MSELoss(reduction='none')
+ ce = lambda num_classes: nn.CrossEntropyLoss(reduction='none', weight=torch.ones(num_classes))
+ bce = nn.BCEWithLogitsLoss(reduction='none')
+ get_BarDistribution = BarDistribution
+
+
+def train(priordataloader_class_or_get_batch: prior.PriorDataLoader | callable, criterion, encoder_generator, emsize=200, nhid=200, nlayers=6, nhead=2, dropout=0.0,
+ epochs=10, steps_per_epoch=100, batch_size=200, seq_len=10, lr=None, weight_decay=0.0, warmup_epochs=10, input_normalization=False,
+ y_encoder_generator=None, pos_encoder_generator=None, decoder_dict={}, extra_prior_kwargs_dict={}, scheduler=get_cosine_schedule_with_warmup,
+ load_weights_from_this_state_dict=None, validation_period=10, single_eval_pos_gen=None, gpu_device='cuda:0',
+ aggregate_k_gradients=1, verbose=True, style_encoder_generator=None, epoch_callback=None, step_callback=None, continue_model=None,
+ initializer=None, initialize_with_model=None, train_mixed_precision=False, efficient_eval_masking=True, border_decoder=None
+ , num_global_att_tokens=0, progress_bar=False, **model_extra_args):
+ device = gpu_device if torch.cuda.is_available() else 'cpu:0'
+ print(f'Using {device} device')
+ using_dist, rank, device = init_dist(device)
+ single_eval_pos_gen = single_eval_pos_gen if callable(single_eval_pos_gen) else lambda: single_eval_pos_gen
+
+ if not isinstance(priordataloader_class_or_get_batch, prior.PriorDataLoader):
+ priordataloader_class = priors.utils.get_batch_to_dataloader(priordataloader_class_or_get_batch)
+ else:
+ priordataloader_class = priordataloader_class_or_get_batch
+
+ def eval_pos_seq_len_sampler():
+ single_eval_pos = single_eval_pos_gen()
+ return single_eval_pos, seq_len
+ dl = priordataloader_class(num_steps=steps_per_epoch,
+ batch_size=batch_size,
+ eval_pos_seq_len_sampler=eval_pos_seq_len_sampler,
+ seq_len_maximum=seq_len,
+ device=device,
+ **extra_prior_kwargs_dict)
+
+ test_batch: prior.Batch = dl.get_test_batch()
+ style_def = test_batch.style
+ print(f'Style definition of first 3 examples: {style_def[:3] if style_def is not None else None}')
+ style_encoder = style_encoder_generator(style_def.shape[1], emsize) if (style_def is not None) else None
+ pos_encoder = (pos_encoder_generator or positional_encodings.NoPositionalEncoding)(emsize, seq_len * 2)
+ if isinstance(criterion, nn.GaussianNLLLoss):
+ n_out = 2
+ elif isinstance(criterion, BarDistribution) or "BarDistribution" in criterion.__class__.__name__: # TODO remove this fix (only for dev)
+ n_out = criterion.num_bars
+ elif isinstance(criterion, nn.CrossEntropyLoss):
+ n_out = criterion.weight.shape[0]
+ else:
+ n_out = 1
+
+ #border_decoder = None if border_decoder is None else border_decoder(emsize, criterion.num_bars + 1).to(device)
+
+ if continue_model:
+ model = continue_model
+ else:
+ decoder_dict = decoder_dict if decoder_dict else {'standard': (None, n_out)}
+
+ decoder_once_dict = {}
+ if test_batch.mean_prediction is not None:
+ decoder_once_dict['mean_prediction'] = decoder_dict['standard']
+
+ encoder = encoder_generator(dl.num_features, emsize)
+ model = TransformerModel(encoder=encoder
+ , nhead=nhead
+ , ninp=emsize
+ , nhid=nhid
+ , nlayers=nlayers
+ , dropout=dropout
+ , style_encoder=style_encoder
+ , y_encoder=y_encoder_generator(1, emsize)
+ , input_normalization=input_normalization
+ , pos_encoder=pos_encoder
+ , decoder_dict=decoder_dict
+ , init_method=initializer
+ , efficient_eval_masking=efficient_eval_masking
+ , decoder_once_dict=decoder_once_dict
+ , num_global_att_tokens=num_global_att_tokens
+ , **model_extra_args
+ )
+ model.criterion = criterion
+ if load_weights_from_this_state_dict is not None:
+ model.load_state_dict(load_weights_from_this_state_dict)
+ if initialize_with_model is not None:
+ model.init_from_small_model(initialize_with_model)
+
+ print(f"Using a Transformer with {sum(p.numel() for p in model.parameters())/1000/1000:.{2}f} M parameters")
+
+ try:
+ for (k, v), (k2, v2) in zip(model.state_dict().items(), initialize_with_model.state_dict().items()):
+ print(k, ((v - v2) / v).abs().mean(), v.shape)
+ except Exception:
+ pass
+
+ model.to(device)
+ if using_dist:
+ print("Distributed training")
+ model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[rank],
+ output_device=rank,
+ broadcast_buffers=False,
+ find_unused_parameters=test_batch.mean_prediction is not None)
+ dl.model = model.module # use local model, should not use multi-gpu functionality..
+ else:
+ dl.model = model
+
+
+ # learning rate
+ if lr is None:
+ lr = get_openai_lr(model)
+ print(f"Using OpenAI max lr of {lr}.")
+ optimizer = torch.optim.AdamW(model.parameters(), lr=lr, weight_decay=weight_decay)
+ scheduler = scheduler(optimizer, warmup_epochs, epochs if epochs is not None else 100) # when training for fixed time lr schedule takes 100 steps
+
+ scaler = GradScaler() if train_mixed_precision else None
+
+ # check that everything uses up-to-date APIs
+ utils.check_compatibility(dl)
+
+ def train_epoch():
+ model.train() # Turn on the train mode
+ total_loss = 0.
+ total_positional_losses = 0.
+ total_positional_losses_recorded = 0
+ nan_steps = 0
+ ignore_steps = 0
+ before_get_batch = time.time()
+ assert len(dl) % aggregate_k_gradients == 0, 'Please set the number of steps per epoch s.t. `aggregate_k_gradients` divides it.'
+ tqdm_iter = tqdm(range(len(dl)), desc='Training Epoch') if rank==0 and progress_bar else None # , disable=not verbose
+
+ for batch, full_data in enumerate(dl):
+ data, targets, single_eval_pos = (full_data.style, full_data.x, full_data.y), full_data.target_y, full_data.single_eval_pos
+
+ def get_metrics():
+ return total_loss / steps_per_epoch, (
+ total_positional_losses / total_positional_losses_recorded).tolist(), \
+ time_to_get_batch, forward_time, step_time, nan_steps.cpu().item() / (batch + 1), \
+ ignore_steps.cpu().item() / (batch + 1)
+
+ tqdm_iter.update() if tqdm_iter is not None else None
+ if using_dist and not (batch % aggregate_k_gradients == aggregate_k_gradients - 1):
+ cm = model.no_sync()
+ else:
+ cm = nullcontext()
+ with cm:
+ time_to_get_batch = time.time() - before_get_batch
+ before_forward = time.time()
+ try:
+ metrics_to_log = {}
+ with autocast(enabled=scaler is not None):
+ # If style is set to None, it should not be transferred to device
+ out = model(tuple(e.to(device) if torch.is_tensor(e) else e for e in data),
+ single_eval_pos=single_eval_pos, only_return_standard_out=False)
+
+ # this handling is for training old models only, this can be deleted soon(ish)
+ # to only support models that return a tuple of dicts
+ out, output_once = out if isinstance(out, tuple) else (out, None)
+ output = out['standard'] if isinstance(out, dict) else out
+
+ forward_time = time.time() - before_forward
+
+ if single_eval_pos is not None:
+ targets = targets[single_eval_pos:]
+
+ if len(targets.shape) == len(output.shape):
+ # this implies the prior uses a trailing 1 dimesnion
+ # below we assume this not to be the case
+ targets = targets.squeeze(-1)
+ assert targets.shape == output.shape[:-1], f"Target shape {targets.shape} " \
+ "does not match output shape {output.shape}"
+ if isinstance(criterion, nn.GaussianNLLLoss):
+ assert output.shape[-1] == 2, \
+ 'need to write a little bit of code to handle multiple regression targets at once'
+
+ mean_pred = output[..., 0]
+ var_pred = output[..., 1].abs()
+ losses = criterion(mean_pred.flatten(), targets.flatten(), var=var_pred.flatten())
+ elif isinstance(criterion, (nn.MSELoss, nn.BCEWithLogitsLoss)):
+ targets[torch.isnan(targets)] = -100
+ losses = criterion(output.flatten(), targets.flatten())
+ elif isinstance(criterion, nn.CrossEntropyLoss):
+ targets[torch.isnan(targets)] = -100
+ print(f"{targets.min()=}, {targets.max()=}")
+ losses = criterion(output.reshape(-1, n_out), targets.long().flatten())
+ elif border_decoder is not None:
+ def apply_batch_wise_criterion(i):
+ output_, targets_, borders_ = output_adaptive[:, i], targets[:, i], borders[i]
+ criterion_ = get_custom_bar_dist(borders_, criterion).to(device)
+ return criterion_(output_, targets_)
+ output_adaptive, borders = out['adaptive_bar'], output_once['borders']
+ losses_adaptive_bar = torch.stack([apply_batch_wise_criterion(i) for i in range(output_adaptive.shape[1])], 1)
+ losses_fixed_bar = criterion(output, targets)
+ losses = (losses_adaptive_bar + losses_fixed_bar) / 2
+
+ metrics_to_log = {**metrics_to_log,
+ **{'loss_fixed_bar': losses_fixed_bar.mean().cpu().detach().item(),
+ 'loss_adaptive_bar': losses_adaptive_bar.mean().cpu().detach().item()}}
+ elif isinstance(criterion, BarDistribution) and full_data.mean_prediction:
+ assert 'mean_prediction' in output_once
+ utils.print_once('Using mean prediction for loss')
+ losses = criterion(output, targets, mean_prediction_logits=output_once['mean_prediction'])
+ # the mean pred loss appears as the last per sequence
+ else:
+ losses = criterion(output, targets)
+ losses = losses.view(-1, output.shape[1]) # sometimes the seq length can be one off
+ # that is because bar dist appends the mean
+ loss, nan_share = utils.torch_nanmean(losses.mean(0), return_nanshare=True)
+ loss_scaled = loss / aggregate_k_gradients
+
+ if scaler: loss_scaled = scaler.scale(loss_scaled)
+ loss_scaled.backward()
+
+ if batch % aggregate_k_gradients == aggregate_k_gradients - 1:
+ if scaler: scaler.unscale_(optimizer)
+ torch.nn.utils.clip_grad_norm_(model.parameters(), 1.)
+ if scaler:
+ scaler.step(optimizer)
+ scaler.update()
+ else:
+ optimizer.step()
+ optimizer.zero_grad()
+
+ step_time = time.time() - before_forward
+
+ if not torch.isnan(loss):
+ total_loss += loss.cpu().detach().item()
+ total_positional_losses += losses.mean(1).cpu().detach() if single_eval_pos is None else \
+ nn.functional.one_hot(torch.tensor(single_eval_pos), seq_len)*\
+ utils.torch_nanmean(losses[:seq_len-single_eval_pos].mean(0)).cpu().detach()
+
+ total_positional_losses_recorded += torch.ones(seq_len) if single_eval_pos is None else \
+ nn.functional.one_hot(torch.tensor(single_eval_pos), seq_len)
+
+ metrics_to_log = {**metrics_to_log, **{f"loss": loss, "single_eval_pos": single_eval_pos}}
+ if step_callback is not None and rank == 0:
+ step_callback(metrics_to_log)
+ nan_steps += nan_share
+ ignore_steps += (targets == -100).float().mean()
+ except Exception as e:
+ print("Invalid step encountered, skipping...")
+ print(e)
+ raise(e)
+
+ #total_loss, total_positional_losses, time_to_get_batch, forward_time, step_time, nan_share, ignore_share = get_metrics()
+ if tqdm_iter:
+ tqdm_iter.set_postfix({'data_time': time_to_get_batch, 'step_time': step_time, 'mean_loss': total_loss / (batch+1)})
+
+ before_get_batch = time.time()
+ return get_metrics()
+
+ total_loss = float('inf')
+ total_positional_losses = float('inf')
+ try:
+ # Initially test the epoch callback function
+ if epoch_callback is not None and rank == 0:
+ epoch_callback(model, 1, data_loader=dl, scheduler=scheduler)
+ for epoch in (range(1, epochs + 1) if epochs is not None else itertools.count(1)):
+ epoch_start_time = time.time()
+ try:
+ total_loss, total_positional_losses, time_to_get_batch, forward_time, step_time, nan_share, ignore_share =\
+ train_epoch()
+ except Exception as e:
+ print("Invalid epoch encountered, skipping...")
+ print(e)
+ raise (e)
+ if hasattr(dl, 'validate') and epoch % validation_period == 0:
+ with torch.no_grad():
+ val_score = dl.validate(model)
+
+ else:
+ val_score = None
+
+ if verbose:
+ print('-' * 89)
+ print(
+ f'| end of epoch {epoch:3d} | time: {(time.time() - epoch_start_time):5.2f}s | mean loss {total_loss:5.2f} | '
+ f"pos losses {','.join([f'{l:5.2f}' for l in total_positional_losses])}, lr {scheduler.get_last_lr()[0]}"
+ f' data time {time_to_get_batch:5.2f} step time {step_time:5.2f}'
+ f' forward time {forward_time:5.2f}'
+ f' nan share {nan_share:5.2f} ignore share (for classification tasks) {ignore_share:5.4f}'
+ + (f'val score {val_score}' if val_score is not None else ''))
+ print('-' * 89)
+
+ # stepping with wallclock time based scheduler
+ if epoch_callback is not None and rank == 0:
+ epoch_callback(model, epoch, data_loader=dl, scheduler=scheduler)
+ scheduler.step()
+ except KeyboardInterrupt:
+ pass
+
+ if rank == 0: # trivially true for non-parallel training
+ if isinstance(model, torch.nn.parallel.DistributedDataParallel):
+ model = model.module
+ dl = None
+ return total_loss, total_positional_losses, model.to('cpu'), dl
+
+def _parse_args(config_parser, parser):
+ # Do we have a config file to parse?
+ args_config, remaining = config_parser.parse_known_args()
+ if args_config.config:
+ with open(args_config.config, 'r') as f:
+ cfg = yaml.safe_load(f)
+ parser.set_defaults(**cfg)
+
+ # The main arg parser parses the rest of the args, the usual
+ # defaults will have been overridden if config file specified.
+ args = parser.parse_args(remaining)
+
+ # Cache the args as a text string to save them in the output dir later
+ args_text = yaml.safe_dump(args.__dict__, default_flow_style=False)
+ return args, args_text
+
diff --git a/pfns4bo/transformer.py b/pfns4bo/transformer.py
new file mode 100644
index 0000000000000000000000000000000000000000..594b64793c5556567d53336dd0dfd40bb6ae00ed
--- /dev/null
+++ b/pfns4bo/transformer.py
@@ -0,0 +1,327 @@
+import math
+from typing import Optional
+
+import torch
+import torch.nn as nn
+from torch import Tensor
+from torch.nn import Module, TransformerEncoder
+
+from .layer import TransformerEncoderLayer, _get_activation_fn
+from .utils import SeqBN, bool_mask_to_att_mask
+
+
+
+class TransformerModel(nn.Module):
+ def __init__(self, encoder, ninp, nhead, nhid, nlayers, dropout=0.0, style_encoder=None, y_encoder=None,
+ pos_encoder=None, decoder_dict=None, input_normalization=False, init_method=None, pre_norm=False,
+ activation='gelu', recompute_attn=False, num_global_att_tokens=0, full_attention=False,
+ all_layers_same_init=False, efficient_eval_masking=True, decoder_once_dict=None, return_all_outputs=False,
+ save_trainingset_representations=False):
+ super().__init__()
+ self.model_type = 'Transformer'
+ encoder_layer_creator = lambda: TransformerEncoderLayer(ninp, nhead, nhid, dropout, activation=activation,
+ pre_norm=pre_norm, recompute_attn=recompute_attn,
+ save_trainingset_representations=save_trainingset_representations)
+ self.transformer_encoder = TransformerEncoder(encoder_layer_creator(), nlayers)\
+ if all_layers_same_init else TransformerEncoderDiffInit(encoder_layer_creator, nlayers)
+ self.ninp = ninp
+ self.encoder = encoder
+ self.y_encoder = y_encoder
+ self.pos_encoder = pos_encoder
+ self.return_all_outputs = return_all_outputs
+
+ def make_decoder_dict(decoder_description_dict):
+ if decoder_description_dict is None or len(decoder_description_dict) == 0:
+ return None
+ initialized_decoder_dict = {}
+ for decoder_key in decoder_description_dict:
+ decoder_model, decoder_n_out = decoder_description_dict[decoder_key]
+ if decoder_model is None:
+ initialized_decoder_dict[decoder_key] = nn.Sequential(nn.Linear(ninp, nhid), nn.GELU(), nn.Linear(nhid, decoder_n_out))
+ else:
+ initialized_decoder_dict[decoder_key] = decoder_model(ninp, nhid, decoder_n_out)
+ print('Initialized decoder for', decoder_key, 'with', decoder_description_dict[decoder_key], ' and nout', decoder_n_out)
+ return torch.nn.ModuleDict(initialized_decoder_dict)
+
+ self.decoder_dict = make_decoder_dict(decoder_dict)
+ self.decoder_dict_once = make_decoder_dict(decoder_once_dict)
+
+ # N(0,1) is the initialization as the default of nn.Embedding
+ self.decoder_dict_once_embeddings = torch.nn.Parameter(torch.randn((len(self.decoder_dict_once), 1, ninp))) if self.decoder_dict_once is not None else None
+ #nn.Embedding(len(self.decoder_dict.keys()), nhid)
+ self.input_ln = SeqBN(ninp) if input_normalization else None
+ self.style_encoder = style_encoder
+ self.init_method = init_method
+ if num_global_att_tokens is not None:
+ assert not full_attention
+ self.global_att_embeddings = nn.Embedding(num_global_att_tokens, ninp) if num_global_att_tokens else None
+ self.full_attention = full_attention
+ self.efficient_eval_masking = efficient_eval_masking
+
+ self.nhid = nhid
+
+ self.init_weights()
+
+ def __setstate__(self, state):
+ super().__setstate__(state)
+ self.__dict__.setdefault('efficient_eval_masking', False)
+ if not hasattr(self, 'decoder_dict_once'):
+ self.__dict__.setdefault('decoder_dict_once', None)
+ if hasattr(self, 'decoder') and not hasattr(self, 'decoder_dict'):
+ self.add_module('decoder_dict', nn.ModuleDict({'standard': self.decoder}))
+ self.__dict__.setdefault('return_all_outputs', False)
+
+ def add_approximate_false(module):
+ if isinstance(module, nn.GELU):
+ module.__dict__.setdefault('approximate', 'none')
+
+ self.apply(add_approximate_false)
+
+ @staticmethod
+ def generate_square_subsequent_mask(sz):
+ mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_D_q_matrix(sz, query_size):
+ train_size = sz-query_size
+ mask = torch.zeros(sz,sz) == 0
+ mask[:,train_size:].zero_()
+ mask |= torch.eye(sz) == 1
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_global_att_query_matrix(num_global_att_tokens, seq_len, num_query_tokens):
+ train_size = seq_len + num_global_att_tokens - num_query_tokens
+ sz = seq_len + num_global_att_tokens
+ mask = torch.zeros(num_query_tokens, sz) == 0
+ mask[:,train_size:].zero_()
+ mask[:,train_size:] |= torch.eye(num_query_tokens) == 1
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_global_att_trainset_matrix(num_global_att_tokens, seq_len, num_query_tokens):
+ train_size = seq_len + num_global_att_tokens - num_query_tokens
+ trainset_size = seq_len - num_query_tokens
+ mask = torch.zeros(trainset_size, num_global_att_tokens) == 0
+ #mask[:,num_global_att_tokens:].zero_()
+ #mask[:,num_global_att_tokens:] |= torch.eye(trainset_size) == 1
+ return bool_mask_to_att_mask(mask)
+
+ @staticmethod
+ def generate_global_att_globaltokens_matrix(num_global_att_tokens, seq_len, num_query_tokens):
+ mask = torch.zeros(num_global_att_tokens, num_global_att_tokens+seq_len-num_query_tokens) == 0
+ return bool_mask_to_att_mask(mask)
+
+ def init_weights(self):
+ initrange = 1.
+ # if isinstance(self.encoder,EmbeddingEncoder):
+ # self.encoder.weight.data.uniform_(-initrange, initrange)
+ # self.decoder.bias.data.zero_()
+ # self.decoder.weight.data.uniform_(-initrange, initrange)
+ if self.init_method is not None:
+ self.apply(self.init_method)
+ for layer in self.transformer_encoder.layers:
+ nn.init.zeros_(layer.linear2.weight)
+ nn.init.zeros_(layer.linear2.bias)
+ attns = layer.self_attn if isinstance(layer.self_attn, nn.ModuleList) else [layer.self_attn]
+ for attn in attns:
+ nn.init.zeros_(attn.out_proj.weight)
+ nn.init.zeros_(attn.out_proj.bias)
+
+ def forward(self, *args, **kwargs):
+ """
+ This will perform a forward-pass (possibly recording gradients) of the model.
+ We have multiple interfaces we support with this model:
+
+ model(train_x, train_y, test_x, src_mask=None, style=None, only_return_standard_out=True)
+ model((x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ model((style,x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ """
+ if len(args) == 3:
+ # case model(train_x, train_y, test_x, src_mask=None, style=None, only_return_standard_out=True)
+ assert all(kwarg in {'src_mask', 'style', 'only_return_standard_out'} for kwarg in kwargs.keys()), \
+ f"Unrecognized keyword argument in kwargs: {set(kwargs.keys()) - {'src_mask', 'style', 'only_return_standard_out'}}"
+ x = args[0]
+ if args[2] is not None:
+ x = torch.cat((x, args[2]), dim=0)
+ style = kwargs.pop('style', None)
+ return self._forward((style, x, args[1]), single_eval_pos=len(args[0]), **kwargs)
+ elif len(args) == 1 and isinstance(args, tuple):
+ # case model((x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ # case model((style,x,y), src_mask=None, single_eval_pos=None, only_return_standard_out=True)
+ assert all(kwarg in {'src_mask', 'single_eval_pos', 'only_return_standard_out'} for kwarg in kwargs.keys()), \
+ f"Unrecognized keyword argument in kwargs: {set(kwargs.keys()) - {'src_mask', 'single_eval_pos', 'only_return_standard_out'}}"
+ return self._forward(*args, **kwargs)
+
+ def _forward(self, src, src_mask=None, single_eval_pos=None, only_return_standard_out=True):
+ assert isinstance(src, tuple), 'inputs (src) have to be given as (x,y) or (style,x,y) tuple'
+
+ if len(src) == 2: # (x,y) and no style
+ src = (None,) + src
+
+ style_src, x_src, y_src = src
+
+ if single_eval_pos is None:
+ single_eval_pos = x_src.shape[0]
+
+
+ x_src = self.encoder(x_src)
+
+ if self.decoder_dict_once is not None:
+ x_src = torch.cat([x_src, self.decoder_dict_once_embeddings.repeat(1, x_src.shape[1], 1)], dim=0)
+
+ y_src = self.y_encoder(y_src.unsqueeze(-1) if len(y_src.shape) < len(x_src.shape) else y_src) if y_src is not None else None
+ if self.style_encoder:
+ assert style_src is not None, 'style_src must be given if style_encoder is used'
+ style_src = self.style_encoder(style_src).unsqueeze(0)
+ else:
+ style_src = torch.tensor([], device=x_src.device)
+ global_src = torch.tensor([], device=x_src.device) if self.global_att_embeddings is None else \
+ self.global_att_embeddings.weight.unsqueeze(1).repeat(1, x_src.shape[1], 1)
+
+ if src_mask is not None:
+ assert self.global_att_embeddings is None or isinstance(src_mask, tuple)
+
+ if src_mask is None:
+ if self.global_att_embeddings is None:
+ full_len = len(x_src) + len(style_src)
+ if self.full_attention:
+ src_mask = bool_mask_to_att_mask(torch.ones((full_len, full_len), dtype=torch.bool)).to(x_src.device)
+ elif self.efficient_eval_masking:
+ src_mask = single_eval_pos + len(style_src)
+ else:
+ src_mask = self.generate_D_q_matrix(full_len, len(x_src) - single_eval_pos).to(x_src.device)
+ else:
+ src_mask_args = (self.global_att_embeddings.num_embeddings,
+ len(x_src) + len(style_src),
+ len(x_src) + len(style_src) - single_eval_pos)
+ src_mask = (self.generate_global_att_globaltokens_matrix(*src_mask_args).to(x_src.device),
+ self.generate_global_att_trainset_matrix(*src_mask_args).to(x_src.device),
+ self.generate_global_att_query_matrix(*src_mask_args).to(x_src.device))
+
+ train_x = x_src[:single_eval_pos]
+ if y_src is not None:
+ train_x = train_x + y_src[:single_eval_pos]
+ src = torch.cat([global_src, style_src, train_x, x_src[single_eval_pos:]], 0)
+
+ if self.input_ln is not None:
+ src = self.input_ln(src)
+
+ if self.pos_encoder is not None:
+ src = self.pos_encoder(src)
+
+
+ output = self.transformer_encoder(src, src_mask)
+
+ num_prefix_positions = len(style_src)+(self.global_att_embeddings.num_embeddings if self.global_att_embeddings else 0)
+ if self.return_all_outputs:
+ out_range_start = num_prefix_positions
+ else:
+ out_range_start = single_eval_pos + num_prefix_positions
+
+ # In the line below, we use the indexing feature, that we have `x[i:None] == x[i:]`
+ out_range_end = -len(self.decoder_dict_once_embeddings) if self.decoder_dict_once is not None else None
+
+ # take care the output once are counted from the end
+ output_once = {k: v(output[-(i+1)]) for i, (k, v) in enumerate(self.decoder_dict_once.items())}\
+ if self.decoder_dict_once is not None else {}
+
+ output = {k: v(output[out_range_start:out_range_end]) for k,v in self.decoder_dict.items()}\
+ if self.decoder_dict is not None else {}
+
+ if only_return_standard_out:
+ return output['standard']
+
+ if output_once:
+ return output, output_once
+ return output
+
+ @torch.no_grad()
+ def init_from_small_model(self, small_model):
+ assert isinstance(self.decoder, nn.Linear) and isinstance(self.encoder, (nn.Linear, nn.Sequential)) \
+ and isinstance(self.y_encoder, (nn.Linear, nn.Sequential))
+
+ def set_encoder_weights(my_encoder, small_model_encoder):
+ my_encoder_linear, small_encoder_linear = (my_encoder, small_model_encoder) \
+ if isinstance(my_encoder, nn.Linear) else (my_encoder[-1], small_model_encoder[-1])
+ small_in_dim = small_encoder_linear.out_features
+ my_encoder_linear.weight.zero_()
+ my_encoder_linear.bias.zero_()
+ my_encoder_linear.weight[:small_in_dim] = small_encoder_linear.weight
+ my_encoder_linear.bias[:small_in_dim] = small_encoder_linear.bias
+
+ set_encoder_weights(self.encoder, small_model.encoder)
+ set_encoder_weights(self.y_encoder, small_model.y_encoder)
+
+ small_in_dim = small_model.decoder.in_features
+
+ self.decoder.weight[:, :small_in_dim] = small_model.decoder.weight
+ self.decoder.bias = small_model.decoder.bias
+
+ for my_layer, small_layer in zip(self.transformer_encoder.layers, small_model.transformer_encoder.layers):
+ small_hid_dim = small_layer.linear1.out_features
+ my_in_dim = my_layer.linear1.in_features
+
+ # packed along q,k,v order in first dim
+ my_in_proj_w = my_layer.self_attn.in_proj_weight
+ small_in_proj_w = small_layer.self_attn.in_proj_weight
+
+ my_in_proj_w.view(3, my_in_dim, my_in_dim)[:, :small_in_dim, :small_in_dim] = small_in_proj_w.view(3,
+ small_in_dim,
+ small_in_dim)
+ my_layer.self_attn.in_proj_bias.view(3, my_in_dim)[:,
+ :small_in_dim] = small_layer.self_attn.in_proj_bias.view(3, small_in_dim)
+
+ my_layer.self_attn.out_proj.weight[:small_in_dim, :small_in_dim] = small_layer.self_attn.out_proj.weight
+ my_layer.self_attn.out_proj.bias[:small_in_dim] = small_layer.self_attn.out_proj.bias
+
+ my_layer.linear1.weight[:small_hid_dim, :small_in_dim] = small_layer.linear1.weight
+ my_layer.linear1.bias[:small_hid_dim] = small_layer.linear1.bias
+
+ my_layer.linear2.weight[:small_in_dim, :small_hid_dim] = small_layer.linear2.weight
+ my_layer.linear2.bias[:small_in_dim] = small_layer.linear2.bias
+
+ my_layer.norm1.weight[:small_in_dim] = math.sqrt(small_in_dim / my_in_dim) * small_layer.norm1.weight
+ my_layer.norm2.weight[:small_in_dim] = math.sqrt(small_in_dim / my_in_dim) * small_layer.norm2.weight
+
+ my_layer.norm1.bias[:small_in_dim] = small_layer.norm1.bias
+ my_layer.norm2.bias[:small_in_dim] = small_layer.norm2.bias
+
+
+class TransformerEncoderDiffInit(Module):
+ r"""TransformerEncoder is a stack of N encoder layers
+
+ Args:
+ encoder_layer_creator: a function generating objects of TransformerEncoderLayer class without args (required).
+ num_layers: the number of sub-encoder-layers in the encoder (required).
+ norm: the layer normalization component (optional).
+ """
+ __constants__ = ['norm']
+
+ def __init__(self, encoder_layer_creator, num_layers, norm=None):
+ super().__init__()
+ self.layers = nn.ModuleList([encoder_layer_creator() for _ in range(num_layers)])
+ self.num_layers = num_layers
+ self.norm = norm
+
+ def forward(self, src: Tensor, mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None) -> Tensor:
+ r"""Pass the input through the encoder layers in turn.
+
+ Args:
+ src: the sequence to the encoder (required).
+ mask: the mask for the src sequence (optional).
+ src_key_padding_mask: the mask for the src keys per batch (optional).
+
+ Shape:
+ see the docs in Transformer class.
+ """
+ output = src
+
+ for mod in self.layers:
+ output = mod(output, src_mask=mask, src_key_padding_mask=src_key_padding_mask)
+
+ if self.norm is not None:
+ output = self.norm(output)
+
+ return output
diff --git a/pfns4bo/utils.py b/pfns4bo/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..479c80be8780c9c0eff4a5367a1eae5121f0b81f
--- /dev/null
+++ b/pfns4bo/utils.py
@@ -0,0 +1,308 @@
+import os
+import math
+import argparse
+import random
+import datetime
+import itertools
+
+import torch
+from torch import nn
+from torch.optim.lr_scheduler import LambdaLR
+import numpy as np
+
+# copied from huggingface
+def get_cosine_schedule_with_warmup(optimizer, num_warmup_steps, num_training_steps, num_cycles=0.5, last_epoch=-1):
+ """ Create a schedule with a learning rate that decreases following the
+ values of the cosine function between 0 and `pi * cycles` after a warmup
+ period during which it increases linearly between 0 and 1.
+ """
+
+ def lr_lambda(current_step):
+ if current_step < num_warmup_steps:
+ return float(current_step) / float(max(1, num_warmup_steps))
+ progress = float(current_step - num_warmup_steps) / float(max(1, num_training_steps - num_warmup_steps))
+ return max(0.0, 0.5 * (1.0 + math.cos(math.pi * float(num_cycles) * 2.0 * progress)))
+
+ return LambdaLR(optimizer, lr_lambda, last_epoch)
+
+# copied from huggingface
+def get_restarting_cosine_schedule_with_warmup(optimizer, num_warmup_steps, num_training_steps, steps_per_restart, num_cycles=0.5, last_epoch=-1):
+ assert num_training_steps % steps_per_restart == 0
+
+ def inner_lr_lambda(current_step, num_warmup_steps, num_training_steps):
+ if current_step < num_warmup_steps:
+ return float(current_step) / float(max(1, num_warmup_steps))
+ progress = float(current_step - num_warmup_steps) / float(max(1, num_training_steps - num_warmup_steps))
+ return max(0.0, 0.5 * (1.0 + math.cos(math.pi * float(num_cycles) * 2.0 * progress)))
+
+ def lr_lambda(current_step):
+ inner_step = current_step % steps_per_restart
+ return inner_lr_lambda(inner_step,
+ num_warmup_steps if current_step < steps_per_restart else 0,
+ steps_per_restart
+ )
+
+
+ return LambdaLR(optimizer, lr_lambda, last_epoch)
+
+# copied from huggingface
+def get_linear_schedule_with_warmup(optimizer, num_warmup_steps, num_training_steps, last_epoch=-1):
+ """
+ Create a schedule with a learning rate that decreases linearly from the initial lr set in the optimizer to 0, after
+ a warmup period during which it increases linearly from 0 to the initial lr set in the optimizer.
+
+ Args:
+ optimizer (:class:`~torch.optim.Optimizer`):
+ The optimizer for which to schedule the learning rate.
+ num_warmup_steps (:obj:`int`):
+ The number of steps for the warmup phase.
+ num_training_steps (:obj:`int`):
+ The total number of training steps.
+ last_epoch (:obj:`int`, `optional`, defaults to -1):
+ The index of the last epoch when resuming training.
+
+ Return:
+ :obj:`torch.optim.lr_scheduler.LambdaLR` with the appropriate schedule.
+ """
+
+ def lr_lambda(current_step: int):
+ if current_step < num_warmup_steps:
+ return float(current_step) / float(max(1, num_warmup_steps))
+ return max(
+ 0.0, float(num_training_steps - current_step) / float(max(1, num_training_steps - num_warmup_steps))
+ )
+
+ return LambdaLR(optimizer, lr_lambda, last_epoch)
+
+
+def get_openai_lr(transformer_model):
+ num_params = sum(p.numel() for p in transformer_model.parameters())
+ return 0.003239 - 0.0001395 * math.log(num_params)
+
+
+def get_weighted_single_eval_pos_sampler(max_len, min_len=0, p=1.0):
+ """
+ This gives a sampler that can be used for `single_eval_pos` which yields good performance for all positions p,
+ where p <= `max_len`. At most `max_len` - 1 examples are shown to the Transformer.
+ :return: Sampler that can be fed to `train()` as `single_eval_pos_gen`.
+ """
+ return lambda: random.choices(range(min_len, max_len), [1 / math.pow(((max_len - min_len) - i), p) for i in range(max_len - min_len)])[0]
+
+
+def get_uniform_single_eval_pos_sampler(max_len, min_len=0):
+ """
+ Just sample any evaluation position with the same weight
+ :return: Sampler that can be fed to `train()` as `single_eval_pos_gen`.
+ """
+ return lambda: random.choices(range(min_len, max_len))[0]
+
+
+class SeqBN(nn.Module):
+ def __init__(self, d_model):
+ super().__init__()
+ self.bn = nn.BatchNorm1d(d_model)
+ self.d_model = d_model
+
+ def forward(self, x):
+ assert self.d_model == x.shape[-1]
+ flat_x = x.view(-1, self.d_model)
+ flat_x = self.bn(flat_x)
+ return flat_x.view(*x.shape)
+
+
+def set_locals_in_self(locals):
+ """
+ Call this function like `set_locals_in_self(locals())` to set all local variables as object variables.
+ Especially useful right at the beginning of `__init__`.
+ :param locals: `locals()`
+ """
+ self = locals['self']
+ for var_name, val in locals.items():
+ if var_name != 'self': setattr(self, var_name, val)
+
+
+default_device = 'cuda:0' if torch.cuda.is_available() else 'cpu:0'
+
+
+# Copied from StackOverflow, but we do an eval on the values additionally
+class StoreDictKeyPair(argparse.Action):
+ def __init__(self, option_strings, dest, nargs=None, **kwargs):
+ self._nargs = nargs
+ super(StoreDictKeyPair, self).__init__(option_strings, dest, nargs=nargs, **kwargs)
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ my_dict = {}
+ for kv in values:
+ k, v = kv.split("=")
+ try:
+ my_dict[k] = eval(v)
+ except NameError:
+ my_dict[k] = v
+ setattr(namespace, self.dest, my_dict)
+ print("dict values: {}".format(my_dict))
+
+def get_nan_value(v, set_value_to_nan=1.0):
+ if random.random() < set_value_to_nan:
+ return v
+ else:
+ return random.choice([-999, 0, 1, 999])
+
+def to_ranking(data):
+ x = (data >= data.unsqueeze(-3))
+ x = x.sum(0)
+ return x
+# TODO: Is there a better way to do this?
+# 1. Cmparing to unique elements: When all values are different we still get quadratic blowup
+# 2. Argsort(Argsort()) returns ranking, but with duplicate values there is an ordering which is problematic
+# 3. Argsort(Argsort(Unique))->Scatter seems a bit complicated, doesn't have quadratic blowup, but how fast?
+def to_ranking_low_mem(data):
+ x = torch.zeros_like(data)
+ for col in range(data.shape[-1]):
+ x_ = (data[:, :, col] >= data[:, :, col].unsqueeze(-2))
+ x_ = x_.sum(0)
+ x[:, :, col] = x_
+ return x
+
+def nan_handling_missing_for_unknown_reason_value(nan_prob=1.0):
+ return get_nan_value(float('nan'), nan_prob)
+
+def nan_handling_missing_for_no_reason_value(nan_prob=1.0):
+ return get_nan_value(float('-inf'), nan_prob)
+
+def nan_handling_missing_for_a_reason_value(nan_prob=1.0):
+ return get_nan_value(float('inf'), nan_prob)
+
+def torch_nanmean(x, axis=0, return_nanshare=False):
+ num = torch.where(torch.isnan(x), torch.full_like(x, 0), torch.full_like(x, 1)).sum(axis=axis)
+ value = torch.where(torch.isnan(x), torch.full_like(x, 0), x).sum(axis=axis)
+ if return_nanshare:
+ return value / num, 1.-num/x.shape[axis]
+ return value / num
+
+def torch_nanstd(x, axis=0):
+ num = torch.where(torch.isnan(x), torch.full_like(x, 0), torch.full_like(x, 1)).sum(axis=axis)
+ value = torch.where(torch.isnan(x), torch.full_like(x, 0), x).sum(axis=axis)
+ mean = value / num
+ mean_broadcast = torch.repeat_interleave(mean.unsqueeze(axis), x.shape[axis], dim=axis)
+ return torch.sqrt(torch.nansum(torch.square(mean_broadcast - x), axis=axis) / (num - 1))
+
+def normalize_data(data, normalize_positions=-1, return_scaling=False):
+ if normalize_positions > 0:
+ mean = torch_nanmean(data[:normalize_positions], axis=0)
+ std = torch_nanstd(data[:normalize_positions], axis=0) + .000001
+ else:
+ mean = torch_nanmean(data, axis=0)
+ std = torch_nanstd(data, axis=0) + .000001
+ data = (data - mean) / std
+ data = torch.clip(data, min=-100, max=100)
+
+ if return_scaling:
+ return data, (mean, std)
+ return data
+
+def remove_outliers(X, n_sigma=4, normalize_positions=-1):
+ # Expects T, B, H
+ assert len(X.shape) == 3, "X must be T,B,H"
+ #for b in range(X.shape[1]):
+ #for col in range(X.shape[2]):
+ data = X if normalize_positions == -1 else X[:normalize_positions]
+ data_clean = data[:].clone()
+ data_mean, data_std = torch_nanmean(data, axis=0), torch_nanstd(data, axis=0)
+ cut_off = data_std * n_sigma
+ lower, upper = data_mean - cut_off, data_mean + cut_off
+
+ data_clean[torch.logical_or(data_clean > upper, data_clean < lower)] = np.nan
+ data_mean, data_std = torch_nanmean(data_clean, axis=0), torch_nanstd(data_clean, axis=0)
+ cut_off = data_std * n_sigma
+ lower, upper = data_mean - cut_off, data_mean + cut_off
+
+ X = torch.maximum(-torch.log(1+torch.abs(X)) + lower, X)
+ X = torch.minimum(torch.log(1+torch.abs(X)) + upper, X)
+ # print(ds[1][data < lower, col], ds[1][data > upper, col], ds[1][~np.isnan(data), col].shape, data_mean, data_std)
+ return X
+
+def bool_mask_to_att_mask(mask):
+ return mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
+
+def print_on_master_only(is_master):
+ import builtins as __builtin__
+
+ builtin_print = __builtin__.print
+
+ def print(*args, **kwargs):
+ force = kwargs.pop("force", False)
+ if is_master or force:
+ builtin_print(*args, **kwargs)
+
+ __builtin__.print = print
+
+
+def init_dist(device):
+ print('init dist')
+ if 'LOCAL_RANK' in os.environ:
+ # launched with torch.distributed.launch
+ rank = int(os.environ["LOCAL_RANK"])
+ print('torch.distributed.launch and my rank is', rank)
+ torch.cuda.set_device(rank)
+ os.environ['CUDA_VISIBLE_DEVICES'] = str(rank)
+ torch.distributed.init_process_group(backend="nccl", init_method="env://", timeout=datetime.timedelta(seconds=20),
+ world_size=torch.cuda.device_count(), rank=rank)
+ torch.distributed.barrier()
+ print_on_master_only(rank == 0)
+ print(f"Distributed training on {torch.cuda.device_count()} GPUs, this is rank {rank}, "
+ "only I can print, but when using print(..., force=True) it will print on all ranks.")
+ return True, rank, f'cuda:{rank}'
+ elif 'SLURM_PROCID' in os.environ and torch.cuda.device_count() > 1:
+ # this is for multi gpu when starting with submitit
+ assert device != 'cpu:0'
+ rank = int(os.environ['SLURM_PROCID'])
+ os.environ['MASTER_ADDR'] = 'localhost'
+ os.environ['MASTER_PORT'] = '12355'
+ torch.cuda.set_device(rank)
+ os.environ['CUDA_VISIBLE_DEVICES'] = str(rank)
+ print('distributed submitit launch and my rank is', rank)
+ torch.distributed.init_process_group(backend="nccl", init_method="env://", timeout=datetime.timedelta(seconds=20),
+ world_size=torch.cuda.device_count(), rank=rank)
+ torch.distributed.barrier()
+ print_on_master_only(rank == 0)
+ print(f"Distributed training on {torch.cuda.device_count()} GPUs, this is rank {rank}, "
+ "only I can print, but when using print(..., force=True) it will print on all ranks.")
+
+ return True, rank, f'cuda:{rank}'
+ else:
+ print('Not using distributed')
+ # will not change any of the behavior of print, but allows putting the force=True in the print calls
+ print_on_master_only(True)
+ return False, 0, device
+
+# NOP decorator for python with statements (x = NOP(); with x:)
+class NOP():
+ def __enter__(self):
+ pass
+ def __exit__(self, type, value, traceback):
+ pass
+
+def check_compatibility(dl):
+ if hasattr(dl, 'num_outputs'):
+ print('`num_outputs` for the DataLoader is deprecated. It is assumed to be 1 from now on.')
+ assert dl.num_outputs != 1, "We assume num_outputs to be 1. Instead of the num_ouputs change your loss." \
+ "We specify the number of classes in the CE loss."
+
+def product_dict(dic):
+ keys = dic.keys()
+ vals = dic.values()
+ for instance in itertools.product(*vals):
+ yield dict(zip(keys, instance))
+
+def to_tensor(x, device=None):
+ if isinstance(x, torch.Tensor):
+ return x.to(device)
+ else:
+ return torch.tensor(x,device=device)
+
+printed_already = set()
+def print_once(*msgs: str):
+ msg = ' '.join([repr(m) for m in msgs])
+ if msg not in printed_already:
+ print(msg)
+ printed_already.add(msg)
diff --git a/test_functions/.ipynb_checkpoints/Ackley10D-checkpoint.py b/test_functions/.ipynb_checkpoints/Ackley10D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..bcbdd92651d536b2ce473e5d94d9f7847109c582
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Ackley10D-checkpoint.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley10D: 10D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 10
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley10D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Ackley2D-checkpoint.py b/test_functions/.ipynb_checkpoints/Ackley2D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed442f5037a6bebce0548f07faeb4bd5bbb5c7f1
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Ackley2D-checkpoint.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley2D: 2D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley2D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley2D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Ackley2DEmbedd-checkpoint.py b/test_functions/.ipynb_checkpoints/Ackley2DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..09e983a179ba11e87fbaa95599132fa627e2f6c0
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Ackley2DEmbedd-checkpoint.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Ackley2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Ackley2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15-5
+ return X_scaled
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Ackley500D-checkpoint.py b/test_functions/.ipynb_checkpoints/Ackley500D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee928e3b651d44c0c2b523d1cfbc6ab5d296c93a
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Ackley500D-checkpoint.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def Ackley500D(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) - 1000 # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1) - 115 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley500D_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Ackley6D-checkpoint.py b/test_functions/.ipynb_checkpoints/Ackley6D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c48a191cd35d9cf785c777aea245f622df5b54c
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Ackley6D-checkpoint.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley6D: 6D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley6D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 6
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley6D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/AckleyND-checkpoint.py b/test_functions/.ipynb_checkpoints/AckleyND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..638f92e9fb5cb852545b6bae1b7d729e428f3e99
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/AckleyND-checkpoint.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def AckleyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def AckleyND_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Branin2DEmbedd-checkpoint.py b/test_functions/.ipynb_checkpoints/Branin2DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba11caa4938034d78f3221b465c85a7efa55eb24
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Branin2DEmbedd-checkpoint.py
@@ -0,0 +1,38 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Branin
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Branin2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Branin(negate=True)
+ fun.bounds[0, 0].fill_(-5.0)
+ fun.bounds[1, 0].fill_(10.0)
+ fun.bounds[0, 1].fill_(0.0)
+ fun.bounds[1, 1].fill_(15.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Branin2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15
+ return X_scaled
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Bukin-checkpoint.py b/test_functions/.ipynb_checkpoints/Bukin-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..562576be84619a079760227f4d009334e4151ae9
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Bukin-checkpoint.py
@@ -0,0 +1,46 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+# class Bukin(SyntheticTestFunction):
+
+# dim = 2
+# _bounds = [(-15.0, -5.0), (-3.0, 3.0)]
+# _optimal_value = 0.0
+# _optimizers = [(-10.0, 1.0)]
+# _check_grad_at_opt: bool = False
+
+
+# [docs]
+# def evaluate_true(self, X: Tensor) -> Tensor:
+# part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+# part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+# return part1 + part2
+
+
+def Bukin(X):
+
+ part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+ part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+ fx = part1 + part2
+
+ return fx
+
+def Bukin_Scaling(X):
+ X_scaled = torch.zeros(X.shape)
+
+ X_scaled[:,0] = -(X[..., 0]*10+5)
+ X_scaled[:,1] = X[..., 0]*6-3
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/CantileverBeam-checkpoint.py b/test_functions/.ipynb_checkpoints/CantileverBeam-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0599ce7836e96aa76ce1fc59780e34f61d8e170
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/CantileverBeam-checkpoint.py
@@ -0,0 +1,193 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CantileverBeam: 10D objective, 11 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+
+
+
+
+
+def CantileverBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+
+ P = 50000
+ E = 2*107
+ L = 100
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1*x6*L + x2*x7*L + x3*x8*L + x4*x9*L + x5*x10*L )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 600 * P / (x5*x10*x10) - 14000
+ g2 = 6 * P * (L*2) / (x4*x9*x9) - 14000
+ g3 = 6 * P * (L*3) / (x3*x8*x8) - 14000
+ g4 = 6 * P * (L*4) / (x2*x7*x7) - 14000
+ g5 = 6 * P * (L*5) / (x1*x6*x6) - 14000
+ g6 = P* L**3 * (1/L + 7/L + 19/L + 37/L + 61/L) / (3*E) -2.7
+ g7 = x10/x5 - 20
+ g8 = x9/x4 - 20
+ g9 = x8/x3 - 20
+ g10 = x7/x2 - 20
+ g11 = x6/x1 - 20
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+ gx10.append( g10 )
+ gx11.append( g11 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx10 = torch.tensor(gx10)
+ gx10 = gx4.reshape((n, 1))
+
+ gx11 = torch.tensor(gx11)
+ gx11 = gx4.reshape((n, 1))
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10, gx11), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def CantileverBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ x1 = (X[:,0] * (5-1) + 1).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (5-1) + 1).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (5-1) + 1).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (5-1) + 1).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (5-1) + 1).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (65-30) + 30).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (65-30) + 30).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (65-30) + 30).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (65-30) + 30).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (65-30) + 30).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Car-checkpoint.py b/test_functions/.ipynb_checkpoints/Car-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7193b96109cd5fc9c3f4ff3a5661bb344338e60
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Car-checkpoint.py
@@ -0,0 +1,253 @@
+import torch
+import numpy as np
+
+
+#
+#
+# Car: 11D objective, 10 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def Car(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def Car_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ x1 = (X[:,0] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (1.35-0.45) + 0.45).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (-20)).reshape(X.shape[0],1)
+ x11 = (X[:,10] * (-20)).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11), dim=1)
+ return X_scaled
+
+
+
+
+
+
+def Car_softpen(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+ cost = gx
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ fx = fx + cost
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/CompressionSpring-checkpoint.py b/test_functions/.ipynb_checkpoints/CompressionSpring-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5443f7da043f74660ae96e1c1867f69101013d4
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/CompressionSpring-checkpoint.py
@@ -0,0 +1,100 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CompressionSpring: 8D objective, 6 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def CompressionSpring(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ d = x[0]
+ D = x[1]
+ N = x[2]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( (N+2)*D*d**2 )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 1 - ( D*D*D * N / (71785* d*d*d*d) )
+ g2 = (4*D*D - D*d) / (12566 * (D*d*d*d - d*d*d*d)) + 1/(5108*d*d) - 1
+ g3 = 1 - 140.45*d / (D*D * N)
+ g4 = (D+d)/1.5 - 1
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+
+ return gx, fx
+
+
+
+def CompressionSpring_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ d = (X[:,0] * ( 1 - 0.05 ) + 0.05 ).reshape(X.shape[0],1)
+ D = (X[:,1] * ( 1.3 - 0.25 ) + 0.25 ).reshape(X.shape[0],1)
+ N = (X[:,2] * ( 15 - 2 ) + 2 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((d, D, N), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/DixonPriceND-checkpoint.py b/test_functions/.ipynb_checkpoints/DixonPriceND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406802fb9029db8327a08acf6601783ba9d5a51
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/DixonPriceND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DixonPriceND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = DixonPrice(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def DixonPriceND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/DummyFixConsDim-checkpoint.py b/test_functions/.ipynb_checkpoints/DummyFixConsDim-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..de6e1b6b1ad0683d3064bc42d6a58c62c905d4ab
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/DummyFixConsDim-checkpoint.py
@@ -0,0 +1,28 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DummyFixConsDim(individuals):
+ n = individuals.size(0)
+ GX = torch.rand(n, 20)
+ Y = torch.rand(n, 1)
+
+ return GX, Y
+
+
+
+def DummyFixConsDim_Scaling(X):
+
+ X_scaled = X
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Finder24-checkpoint.py b/test_functions/.ipynb_checkpoints/Finder24-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..9f7a4752b9e54183f145947fa4f06c51283ca754
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Finder24-checkpoint.py
@@ -0,0 +1,172 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ # START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z, n_candidate=None):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+
+ if n_candidate==None:
+ n_candidate = 2000
+
+ Z_samples = sobol.draw(n_candidate)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Finder24_no_timer-checkpoint.py b/test_functions/.ipynb_checkpoints/Finder24_no_timer-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd3e0475a77fe66303e3dd345bc0aec41ece7fe5
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Finder24_no_timer-checkpoint.py
@@ -0,0 +1,173 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_Adam_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+ Z_samples = sobol.draw(2000)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/GKXWC1-checkpoint.py b/test_functions/.ipynb_checkpoints/GKXWC1-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..2dfa59da9637b4c64377a6e6471c742f9f9c53f3
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/GKXWC1-checkpoint.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC1: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+
+def GKXWC1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+ for x in individuals:
+ g = np.cos(x[0])*np.cos(x[1]) - np.sin(x[0])*np.sin(x[1]) -0.5
+ fx.append( - np.cos(2*x[0])*np.cos(x[1]) - np.sin(x[0]) )
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+ return gx, fx
+
+
+def GKXWC1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/GKXWC2-checkpoint.py b/test_functions/.ipynb_checkpoints/GKXWC2-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..5db203c32b693009590b8e9b9b79177d3cc3bba9
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/GKXWC2-checkpoint.py
@@ -0,0 +1,80 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC2: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+def GKXWC2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ g = np.sin(x[0])*np.sin(x[1]) + 0.95
+ fx.append( - np.sin(x[0]) - x[1] ) # maximize -(x1^2 +x 2^2)
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+def GKXWC2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Griewank2DEmbedd-checkpoint.py b/test_functions/.ipynb_checkpoints/Griewank2DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e6128b1f5987182c740bab54875152b58635979
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Griewank2DEmbedd-checkpoint.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Griewank2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Griewank2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled = X_scaled * 1200 - 600
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/GriewankND-checkpoint.py b/test_functions/.ipynb_checkpoints/GriewankND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406c4f067885c9d6c726f526688c222b89c8a3a
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/GriewankND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def GriewankND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def GriewankND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*1200-600
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Hartmann6DEmbedd-checkpoint.py b/test_functions/.ipynb_checkpoints/Hartmann6DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..94115986eb19db5747d36fcd38d7ffc5308af125
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Hartmann6DEmbedd-checkpoint.py
@@ -0,0 +1,35 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Hartmann
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Hartmann6DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[0,1,2,3,4,5]]
+ n = X.size(0)
+ dimm = 6
+ fun = Hartmann(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(1.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Hartmann6DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ return X_scaled
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/HeatExchanger-checkpoint.py b/test_functions/.ipynb_checkpoints/HeatExchanger-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f74bb6ed047a5537a898628f467e732d71e9669
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/HeatExchanger-checkpoint.py
@@ -0,0 +1,191 @@
+import torch
+import numpy as np
+
+#
+#
+# HeatExchanger: 8D objective, 6 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+def HeatExchanger(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1+x2+x3 )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 0.0025 * (x4+x6) - 1
+ g2 = 0.0025 * (x5 + x7 - x4) - 1
+ g3 = 0.01 *(x8-x5) - 1
+ g4 = 833.33252*x4 + 100*x1 - x1*x6 - 83333.333
+ g5 = 1250*x5 + x2*x4 - x2*x7 - 125*x4
+ g6 = x3*x5 - 2500*x5 - x3*x8 + 125*10000
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6), 1)
+
+
+ return gx, fx
+
+
+
+
+
+def HeatExchanger_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ x1 = (X[:,0] * (10000-100) + 100).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1000-10) + 10).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1000-10) + 10).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1000-10) + 10).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1000-10) + 10).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (1000-10) + 10).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/JLH1-checkpoint.py b/test_functions/.ipynb_checkpoints/JLH1-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..27b7f05394a22a18d0349cbe2632c31c471a83b7
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/JLH1-checkpoint.py
@@ -0,0 +1,57 @@
+import torch
+import numpy as np
+
+#
+# JLH1: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+def JLH1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+ test_function = (- (x[0]-0.5)**2 - (x[1]-0.5)**2 )
+ fx.append(test_function)
+ gx.append( x[0] + x[1] - 0.75 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+
+
+def JLH1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/JLH2-checkpoint.py b/test_functions/.ipynb_checkpoints/JLH2-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ce7c5e5e65c8fbfda31d4485babc0a84bf6f1aa
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/JLH2-checkpoint.py
@@ -0,0 +1,68 @@
+import torch
+import numpy as np
+
+
+#
+# JLH2: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+
+def JLH2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( np.cos(2*x[0])*np.cos(x[1]) + np.sin(x[0]) )
+
+ fx.append(test_function)
+ gx.append( ((x[0]+5)**2)/4 + (x[1]**2)/100 -2.5 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+def JLH2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ # X = individuals
+ X1 = X[:,0].reshape(X.size(0),1)
+ X1 = X1*5-5
+ X2 = X[:,1].reshape(X.size(0),1)
+ X2 = X2*10-5
+ X_scaled = torch.tensor(np.concatenate((X1,X2), axis=1))
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/KeaneBump-checkpoint.py b/test_functions/.ipynb_checkpoints/KeaneBump-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ff354c8c76334acb87fbbaac3baf79d1ac2fa23
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/KeaneBump-checkpoint.py
@@ -0,0 +1,88 @@
+import torch
+import numpy as np
+
+#
+#
+# KeaneBump: N-D objective (can take data of different dimention; we use 18),
+# 2 constraints
+#
+# Reference:
+# Keane A (1994) Experiences with optimizers in
+# structural design. In: Proceedings of the con-
+# ference on adaptive computing in engineering
+# design and control, pp 14–27
+#
+#
+
+
+
+def KeaneBump(X):
+
+
+
+ fx = torch.zeros(X.shape[0], 1)
+ gx1 = torch.zeros(X.shape[0], 1)
+ gx2 = torch.zeros(X.shape[0], 1)
+
+
+
+ for i in range(X.shape[0]):
+ x = X[i,:]
+
+ cos4 = 0
+ cos2 = 1
+ sq_denom = 0
+
+ pi_sum = 1
+ sigma_sum = 0
+
+ for j in range(X.shape[1]):
+ cos4 += torch.cos(x[j]) ** 4
+ cos2 *= torch.cos(x[j]) ** 2
+ sq_denom += (j+1) * (x[j])**2
+
+ pi_sum *= x[j]
+ sigma_sum += x[j]
+
+
+ # Objective
+ test_function = torch.abs( (cos4 - 2*cos2) / torch.sqrt(sq_denom) )
+ fx[i] = test_function
+
+ # Constraints
+ gx1[i] = 0.75 - pi_sum
+ gx2[i] = sigma_sum - 7.5* (X.shape[1])
+
+ gx = torch.cat((gx1, gx2), 1)
+ return gx, fx
+
+
+
+
+
+def KeaneBump_Scaling(X):
+
+ X_scaled = X*10
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/LevyND-checkpoint.py b/test_functions/.ipynb_checkpoints/LevyND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b0c6e40d653c0b964655eb80c5d87787506ec3a
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/LevyND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Levy
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def LevyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Levy(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def LevyND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/MOPTA08_Car-checkpoint.py b/test_functions/.ipynb_checkpoints/MOPTA08_Car-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..09894738e0c6f340e6feb5cc8119726fd81ac95c
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/MOPTA08_Car-checkpoint.py
@@ -0,0 +1,133 @@
+import os
+import subprocess
+import sys
+import tempfile
+from pathlib import Path
+from platform import machine
+
+import numpy as np
+import torch
+import stat
+
+
+def MOPTA08_Car_single(x):
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ sysarch = 64 if sys.maxsize > 2 ** 32 else 32
+ # machine = machine().lower()
+
+ # if machine == "armv7l":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_armhf.bin"
+ # elif machine == "x86_64":
+ # assert sysarch == 64, "Not supported"
+ # mopta_exectutable = "mopta08_elf64.bin"
+ # elif machine == "i386":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_elf32.bin"
+ # else:
+ # raise RuntimeError("Machine with this architecture is not supported")
+
+ machine = "x86_64"
+ mopta_exectutable = "mopta08_elf64.bin"
+
+ mopta_full_path = os.path.join(
+ "mopta08", mopta_exectutable
+ )
+ # print(mopta_full_path)
+
+ directory_file_descriptor = tempfile.TemporaryDirectory()
+ # directory_name = directory_file_descriptor.name
+ directory_name = Path(__file__).parent
+
+ ##########################################################################################
+ # Input here
+ # if x == None:
+ # x = np.random.rand(124)
+ # print(x.shape)
+ ##########################################################################################
+ with open(os.path.join(directory_name, "input.txt"), "w+") as tmp_file:
+ for _x in x:
+ tmp_file.write(f"{_x}\n")
+ popen = subprocess.Popen(
+ mopta_full_path,
+ # '#!/home/rosen/Dropbox (MIT)/Rosen_DeC0De/MOPTA_Test/mopta08/mopta08_elf64.bin',
+ stdout=subprocess.PIPE,
+ cwd=directory_name,
+ shell=True,
+ )
+ popen.wait()
+
+ with open(os.path.join(directory_name, "output.txt"), "r") as tmp_file:
+ output = (
+ tmp_file
+ .read()
+ .split("\n")
+ )
+ # print(output)
+ # print(x)
+ # print(output)
+ output = [x.strip() for x in output]
+ output = np.array([float(x) for x in output if len(x) > 0])
+ value = output[0]
+ constraints = output[1:]
+ # print(value, constraints)
+
+ return constraints, value
+
+
+
+def MOPTA08_Car(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = -fx
+
+ return GX, FX
+
+
+
+
+def MOPTA08_Car_softpen(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = fx
+
+ cost = GX
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ FX = FX + cost
+
+ return GX, -FX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Mazda-checkpoint.py b/test_functions/.ipynb_checkpoints/Mazda-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..52f586cbf98f52df78c8d6e9ba0045535a113602
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Mazda-checkpoint.py
@@ -0,0 +1,242 @@
+import os
+import subprocess
+import stat
+import pandas as pd
+import torch
+import numpy as np
+
+
+
+def Mazda(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+def Mazda_softpen(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+
+ cost = cons_data_tensor
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ objs_data_tensor = objs_data_tensor + cost
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/MichalewiczND-checkpoint.py b/test_functions/.ipynb_checkpoints/MichalewiczND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..55cd932393e207d7deb9ddebde8b93a408c48400
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/MichalewiczND-checkpoint.py
@@ -0,0 +1,59 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def MichalewiczND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Michalewicz(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(math.pi)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def MichalewiczND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*math.pi
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/PressureVessel-checkpoint.py b/test_functions/.ipynb_checkpoints/PressureVessel-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..eeefcd177c3ec800e56c2a3b1b9ca4c573e79990
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/PressureVessel-checkpoint.py
@@ -0,0 +1,169 @@
+import torch
+import numpy as np
+
+#
+#
+# PressureVessel: 4D objective, 4 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def PressureVessel(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ C1 = 0.6224
+ C2 = 1.7781
+ C3 = 3.1661
+ C4 = 19.84
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ Ts = x[0]
+ Th = x[1]
+ R = x[2]
+ L = x[3]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( C1*Ts*R*L + C2*Th*R*R + C3*Ts*Ts*L + C4*Ts*Ts*R )
+ fx.append(test_function)
+
+
+ g1 = -Ts + 0.0193*R
+ g2 = -Th + 0.00954*R
+ g3 = (-1)*np.pi*R*R*L + (-1)*4/3*np.pi*R*R*R + 750*1728
+ g4 = L-240
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def PressureVessel_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ Ts = (X[:,0] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ Th = (X[:,1] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ R = (X[:,2] * (200-10) + 10).reshape(X.shape[0],1)
+ L = (X[:,3] * (200-10) ).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((Ts, Th, R, L), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/ReinforcedConcreteBeam-checkpoint.py b/test_functions/.ipynb_checkpoints/ReinforcedConcreteBeam-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1729e66ee7ac88f8fe7fdc60b984b8ba6d784a72
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/ReinforcedConcreteBeam-checkpoint.py
@@ -0,0 +1,90 @@
+import torch
+import numpy as np
+
+#
+#
+# ReinforcedConcreteBeam: 3D objective, 9 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def ReinforcedConcreteBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ As = x[0]
+ h = x[1]
+ b = x[2]
+
+
+ test_function = - ( 29.4*As + 0.6*b*h )
+ fx.append(test_function)
+
+ g1 = h/b - 4
+ g2 = 180 + 7.35*As*As/b - As*h
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def ReinforcedConcreteBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ As = (X[:,0] * (15-0.2) + 0.2).reshape(X.shape[0],1)
+ b = (X[:,1] * (40-28) +28).reshape(X.shape[0],1)
+ h = (X[:,2] * 5 + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((As, b, h), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Rosenbrock3DEmbedd-checkpoint.py b/test_functions/.ipynb_checkpoints/Rosenbrock3DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1625595859baca53628812cede1b6f68f8e7ea14
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Rosenbrock3DEmbedd-checkpoint.py
@@ -0,0 +1,40 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Rosenbrock3DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2,3]]
+ n = X.size(0)
+ dimm = 3
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-2.0)
+ fun.bounds[1, :].fill_(2.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Rosenbrock3DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+
+ X_scaled[:,1] = X_scaled[:,1]*4 - 2
+ X_scaled[:,2] = X_scaled[:,2]*4 - 2
+ X_scaled[:,3] = X_scaled[:,3]*4 - 2
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/RosenbrockND-checkpoint.py b/test_functions/.ipynb_checkpoints/RosenbrockND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb46001f9d022a9a9f4a73633f2a89dc882f44a3
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/RosenbrockND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def RosenbrockND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/RosenbrockND2-checkpoint.py b/test_functions/.ipynb_checkpoints/RosenbrockND2-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..635099799fbf64f4b501d187b19eecdd63c2e417
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/RosenbrockND2-checkpoint.py
@@ -0,0 +1,56 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock, Levy, DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND2(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+
+
+ Rosenbrockfun = Rosenbrock(dim=dimm, negate=True)
+ Rosenbrockfun.bounds[0, :].fill_(-3.0)
+ Rosenbrockfun.bounds[1, :].fill_(5.0)
+
+ fx = Rosenbrockfun(individuals)
+ fx = fx.reshape(individuals.shape[0],1)
+
+ Levyfun = Levy(dim=dimm, negate=False)
+ Levyfun.bounds[0, :].fill_(-3.0)
+ Levyfun.bounds[1, :].fill_(5.0)
+
+
+ DixonPricefun = DixonPrice(dim=dimm, negate=False)
+ DixonPricefun.bounds[0, :].fill_(-3.0)
+ DixonPricefun.bounds[1, :].fill_(5.0)
+
+
+ G1 = Levyfun(individuals) -1e3
+ G2 = DixonPricefun(individuals) -4e7
+
+ gx = torch.cat((G1.reshape(individuals.shape[0],1), G2.reshape(individuals.shape[0],1)), 1)
+
+
+ return gx, fx
+
+
+def RosenbrockND2_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*8-3
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/SpeedReducer-checkpoint.py b/test_functions/.ipynb_checkpoints/SpeedReducer-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b8ec3cbabd1652d9d75361e332658fb06e7ff6b
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/SpeedReducer-checkpoint.py
@@ -0,0 +1,188 @@
+import torch
+import numpy as np
+
+#
+#
+# SpeedReducer: 7D objective, 9 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+def SpeedReducer(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ b = x[0]
+ m = x[1]
+ z = x[2]
+ L1 = x[3]
+ L2 = x[4]
+ d1 = x[5]
+ d2 = x[6]
+
+ C1 = 0.7854*b*m*m
+ C2 = 3.3333*z*z + 14.9334*z - 43.0934
+ C3 = 1.508*b*(d1*d1 + d2*d2)
+ C4 = 7.4777*(d1*d1*d1 + d2*d2*d2)
+ C5 = 0.7854*(L1*d1*d1 + L2*d2*d2)
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 0.7854*b*m*m * (3.3333*z*z + 14.9334*z - 43.0934) - 1.508*b*(d1*d1 + d2*d2) + 7.4777*(d1*d1*d1 + d2*d2*d2) + 0.7854*(L1*d1*d1 + L2*d2*d2) )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 27/(b*m*m*z) - 1
+ g2 = 397.5/(b*m*m*z*z) - 1
+
+ g3 = 1.93*L1**3 /(m*z *d1**4) - 1
+ g4 = 1.93*L2**3 /(m*z *d2**4) - 1
+
+ g5 = np.sqrt( (745*L1/(m*z))**2 + 1.69*1e6 ) / (110*d1**3) -1
+ g6 = np.sqrt( (745*L2/(m*z))**2 + 157.5*1e6 ) / (85*d2**3) -1
+ g7 = m*z/40 - 1
+ g8 = 5*m/(b) - 1
+ g9 = b/(12*m) -1
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9), 1)
+
+
+ return gx, fx
+
+
+
+def SpeedReducer_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ b = (X[:,0] * ( 3.6 - 2.6 ) + 2.6).reshape(X.shape[0],1)
+ m = (X[:,1] * ( 0.8 - 0.7 ) + 0.7).reshape(X.shape[0],1)
+ z = (X[:,2] * ( 28 - 17 ) + 17).reshape(X.shape[0],1)
+ L1 = (X[:,3] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ L2 = (X[:,4] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ d1 = (X[:,5] * ( 3.9 - 2.9 ) + 2.9).reshape(X.shape[0],1)
+ d2 = (X[:,6] * ( 5.5 - 5 ) + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((b, m, z, L1, L2, d1, d2), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/ThreeTruss-checkpoint.py b/test_functions/.ipynb_checkpoints/ThreeTruss-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e4b3f2ef3416ea17b6626d2ea87c2dd7a9c2362
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/ThreeTruss-checkpoint.py
@@ -0,0 +1,144 @@
+import torch
+import numpy as np
+
+
+#
+#
+# ThreeTruss: 2D objective, 3 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+def ThreeTruss(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ x1 = x[0]
+ x2 = x[1]
+
+ if x1 <=1e-5:
+ x1 = 1e-5
+ if x2 <=1e-5:
+ x2 = 1e-5
+
+ L = 100
+ P = 2
+ sigma = 2
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 2*np.sqrt(2)*x1 + x2 ) * L
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = ( np.sqrt(2)*x1 + x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g2 = ( x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g3 = ( 1 ) / (x1 + np.sqrt(2)*x2) * P - sigma
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def ThreeTruss_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Truss10D-checkpoint.py b/test_functions/.ipynb_checkpoints/Truss10D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc0ea12f999aa1d58eb4516b4fc08112f711583b
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Truss10D-checkpoint.py
@@ -0,0 +1,66 @@
+
+from TrussSolvers import *
+import torch
+import numpy as np
+
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(individuals[ii,:])
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/TrussSolvers-checkpoint.py b/test_functions/.ipynb_checkpoints/TrussSolvers-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec6d915060eeaacae4989257c47b9212c1f3e235
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/TrussSolvers-checkpoint.py
@@ -0,0 +1,2958 @@
+import matplotlib.pyplot as plt
+import torch
+import numpy as np
+
+from slientruss3d.truss import Truss
+from slientruss3d.type import SupportType, MemberType
+from slientruss3d.plot import TrussPlotter
+
+
+
+
+
+def TestPlot(truss):
+ # -------------------- Global variables --------------------
+ # Files settings:
+ TEST_FILE_NUMBER = 25
+ TEST_LOAD_CASE = 0
+ TEST_INPUT_FILE = f"./data/bar-{TEST_FILE_NUMBER}_output_{TEST_LOAD_CASE}.json"
+ TEST_PLOT_SAVE_PATH = f"./plot/bar-{TEST_FILE_NUMBER}_plot_{TEST_LOAD_CASE}.png"
+
+ # Truss dimension setting:
+ TRUSS_DIMENSION = 3
+
+ # Figure layout settings:
+ IS_SAVE_PLOT = False # Whether to save truss figure or not.
+ IS_EQUAL_AXIS = True # Whether to use actual aspect ratio in the truss figure or not.
+ IS_PLOT_STRESS = True # If True, the color of each displaced member gives expression to [stress]. Otherwise, [force magnitude].
+ MAX_SCALED_DISPLACEMENT = 15 # Scale the max value of all dimensions of displacements.
+ MAX_SCALED_FORCE = 50 # Scale the max value of all dimensions of force arrows.
+ POINT_SIZE_SCALE_FACTOR = 1 # Scale the default size of joint point in the truss figure.
+ ARROW_SIZE_SCALE_FACTOR = 1 # Scale the default size of force arrow in the truss figure.
+ # ----------------------------------------------------------
+
+ # Truss object:
+ # truss = Truss(dim=TRUSS_DIMENSION)
+
+ # You could directly read the output .json file.
+ # truss.LoadFromJSON(TEST_INPUT_FILE, isOutputFile=True)
+
+ # Show or save the structural analysis result figure:
+ TrussPlotter(truss,
+ isEqualAxis=IS_EQUAL_AXIS,
+ isPlotStress=IS_PLOT_STRESS,
+ maxScaledDisplace=MAX_SCALED_DISPLACEMENT,
+ maxScaledForce=MAX_SCALED_FORCE,
+ pointScale=POINT_SIZE_SCALE_FACTOR,
+ arrowScale=ARROW_SIZE_SCALE_FACTOR).Plot(IS_SAVE_PLOT, TEST_PLOT_SAVE_PATH)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss10bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(0, 0),
+ (360, 0),
+ (720, 0),
+ (0, 360),
+ (360, 360),
+ (720, 360)
+ ]
+
+
+ supports = [SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ ]
+ forces = [(1, (0, -1e5)), (2, (0, -1e5))]
+
+
+ members = [(0, 1),
+ (0, 4),
+ (1, 2),
+ (1, 3),
+ (1, 4),
+ (1, 5),
+ (2, 4),
+ (2, 5),
+ (3, 4),
+ (4, 5)
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # Default: 0.1, 1e7, 1
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss25bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(62.5, 100, 200),
+ (137.5, 100, 200),
+ (62.5, 137.5, 100),
+ (137.5, 137.5, 100),
+ (137.5, 62.5, 100),
+ (62.5, 62.5, 100),
+ (0, 200, 0),
+ (200, 200, 0),
+ (200, 0, 0),
+ (0, 0, 0)
+ ]
+
+
+ supports = [SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+ forces = [(0, (1000, 20000, -5000)),
+ (1, (0, -20000, -5000)),
+ (2, (500, 0, 0)),
+ (5, (500, 0, 0)),
+ ]
+
+
+ members = [(0, 1),
+ (0, 3),
+ (1, 2),
+ (0, 4),
+ (1, 5),
+ (0, 2),
+ (0, 5),
+ (1, 3),
+ (1, 4),
+ (2, 5),
+ (3, 4),
+ (2, 3),
+ (4, 5),
+ (2, 9),
+ (5, 6),
+ (3, 8),
+ (4, 7),
+ (2, 7),
+ (3, 6),
+ (5, 8),
+ (4, 9),
+ (2, 6),
+ (3, 7),
+ (4, 8),
+ (5, 9),
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+
+ # Default: 0.1, 1e7, .1
+
+ memberType = MemberType(A[index].item(), 3e7, .283)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), .283)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 3e7, Rho[index].item())
+
+
+
+ # memberType = MemberType(A[index].item(), 1e7, .1)
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+
+def Truss47bar(A, E, Rho, version):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(-60, 0),
+ (60, 0),
+ (-60, 120),
+ (60, 120),
+ (-60, 240),
+ (60, 240),
+ (-60, 360),
+ (60, 360),
+ (-30, 420),
+ (30, 420),
+ (-30, 480),
+ (30, 480),
+ (-30, 540),
+ (30, 540),
+ (-90, 570),
+ (90, 570),
+ (-150, 600),
+ (-90, 600),
+ (-30, 600),
+ (30, 600),
+ (90, 600),
+ (150, 600)]
+
+ supports = [SupportType.PIN, SupportType.PIN,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO]
+
+
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ if version == 1:
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ elif version == 2:
+ forces = [(16, (6000, -14000))]
+
+ elif version == 3:
+ forces = [(21, (6000, -14000))]
+
+
+
+
+ members = [(0, 2), (0, 3), (1, 2), (1, 3),
+ (2, 3), (2, 4), (2, 5), (3, 4), (3, 5),
+ (4, 5), (4, 6), (4, 7), (5, 6), (5, 7),
+ (6, 7), (6, 8), (6, 9), (7, 8), (7, 9), (8, 9),
+ (8, 10), (8, 11), (9, 10), (9, 11),
+ (10, 11), (10, 12), (10, 13), (11, 12), (11, 13),
+ (12, 13), (12, 14), (12, 18), (12, 19),
+ (13, 18), (13, 19), (13, 15), (14, 16),
+ (14, 17), (14, 18), (15, 19), (15, 20),
+ (15, 21), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21)]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+
+ # Default: 0.1, 300000000.0, 0.3
+
+ memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.3)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 300000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss120bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 275.59),
+ (273.26, 0.0, 230.31),
+ (236.65010183813573, 136.62999999999997, 230.31),
+ (136.62999999999997, 236.65010183813573, 230.31),
+ (0.0, 273.26, 230.31),
+ (-136.62999999999997, 236.65010183813573, 230.31),
+ (-236.65010183813573, 136.62999999999997, 230.31),
+ (-273.26, 0.0, 230.31),
+ (-236.65010183813573, -136.62999999999997, 230.31),
+ (-136.62999999999997, -236.65010183813573, 230.31),
+ (0.0, -273.26, 230.31),
+ (136.62999999999997, -236.65010183813573, 230.31),
+ (236.65010183813573, -136.62999999999997, 230.31),
+ (492.12, 0.0, 118.11),
+ (475.3514176333763, 127.37002847585251, 118.11),
+ (426.18842171039796, 246.05999999999997, 118.11),
+ (347.9813891575237, 347.9813891575237, 118.11),
+ (246.05999999999997, 426.18842171039796, 118.11),
+ (127.37002847585251, 475.3514176333763, 118.11),
+ (0.0, 492.12, 118.11),
+ (-127.37002847585251, 475.3514176333763, 118.11),
+ (-246.05999999999997, 426.18842171039796, 118.11),
+ (-347.9813891575237, 347.9813891575237, 118.11),
+ (-426.18842171039796, 246.05999999999997, 118.11),
+ (-475.3514176333763, 127.37002847585251, 118.11),
+ (-492.12, 0.0, 118.11),
+ (-475.3514176333763, -127.37002847585251, 118.11),
+ (-426.18842171039796, -246.05999999999997, 118.11),
+ (-347.9813891575237, -347.9813891575237, 118.11),
+ (-246.05999999999997, -426.18842171039796, 118.11),
+ (-127.37002847585251, -475.3514176333763, 118.11),
+ (0.0, -492.12, 118.11),
+ (127.37002847585251, -475.3514176333763, 118.11),
+ (246.05999999999997, -426.18842171039796, 118.11),
+ (347.9813891575237, -347.9813891575237, 118.11),
+ (426.18842171039796, -246.05999999999997, 118.11),
+ (475.3514176333763, -127.37002847585251, 118.11),
+ (625.59, 0.0, 0.0),
+ (541.7768323535071, 312.79499999999996, 0.0),
+ (312.79499999999996, 541.7768323535071, 0.0),
+ (0.0, 625.59, 0.0),
+ (-312.79499999999996, 541.7768323535071, 0.0),
+ (-541.7768323535071, 312.79499999999996, 0.0),
+ (-625.59, 0.0, 0.0),
+ (-541.7768323535071, -312.79499999999996, 0.0),
+ (-312.79499999999996, -541.7768323535071, 0.0),
+ (0.0, -625.59, 0.0),
+ (312.79499999999996, -541.7768323535071, 0.0),
+ (541.7768323535071, -312.79499999999996, 0.0)
+ ]
+
+ supports = [
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+
+ # print(len(joints))
+ # print(len(supports))
+
+
+
+ forces = [
+ (0, (0.0, 0.0, -13490.0)),
+ (1, (0.0, 0.0, -6744.0)),
+ (2, (0.0, 0.0, -6744.0)),
+ (3, (0.0, 0.0, -6744.0)),
+ (4, (0.0, 0.0, -6744.0)),
+ (5, (0.0, 0.0, -6744.0)),
+ (6, (0.0, 0.0, -6744.0)),
+ (7, (0.0, 0.0, -6744.0)),
+ (8, (0.0, 0.0, -6744.0)),
+ (9, (0.0, 0.0, -6744.0)),
+ (10, (0.0, 0.0, -6744.0)),
+ (11, (0.0, 0.0, -6744.0)),
+ (12, (0.0, 0.0, -6744.0)),
+ (13, (0.0, 0.0, -6744.0)),
+ (14, (0.0, 0.0, -2248.0)),
+ (15, (0.0, 0.0, -2248.0)),
+ (16, (0.0, 0.0, -2248.0)),
+ (17, (0.0, 0.0, -2248.0)),
+ (18, (0.0, 0.0, -2248.0)),
+ (19, (0.0, 0.0, -2248.0)),
+ (20, (0.0, 0.0, -2248.0)),
+ (21, (0.0, 0.0, -2248.0)),
+ (22, (0.0, 0.0, -2248.0)),
+ (23, (0.0, 0.0, -2248.0)),
+ (24, (0.0, 0.0, -2248.0)),
+ (25, (0.0, 0.0, -2248.0)),
+ (26, (0.0, 0.0, -2248.0)),
+ (27, (0.0, 0.0, -2248.0)),
+ (28, (0.0, 0.0, -2248.0)),
+ (29, (0.0, 0.0, -2248.0)),
+ (30, (0.0, 0.0, -2248.0)),
+ (31, (0.0, 0.0, -2248.0)),
+ (32, (0.0, 0.0, -2248.0)),
+ (33, (0.0, 0.0, -2248.0)),
+ (34, (0.0, 0.0, -2248.0)),
+ (35, (0.0, 0.0, -2248.0)),
+ (36, (0.0, 0.0, -2248.0))
+ ]
+
+
+
+ members = [
+ (0, 1),
+ (0, 2),
+ (0, 3),
+ (0, 4),
+ (0, 5),
+ (0, 6),
+ (0, 7),
+ (0, 8),
+ (0, 9),
+ (0, 10),
+ (0, 11),
+ (0, 12),
+ (1, 2),
+ (2, 3),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 12),
+ (12, 1),
+ (1, 13),
+ (2, 15),
+ (3, 17),
+ (4, 19),
+ (5, 21),
+ (6, 23),
+ (7, 25),
+ (8, 27),
+ (9, 29),
+ (10, 31),
+ (11, 33),
+ (12, 35),
+ (1, 14),
+ (2, 14),
+ (2, 16),
+ (3, 16),
+ (3, 18),
+ (4, 18),
+ (4, 20),
+ (5, 20),
+ (5, 22),
+ (6, 22),
+ (6, 24),
+ (7, 24),
+ (7, 26),
+ (8, 26),
+ (8, 28),
+ (9, 28),
+ (9, 30),
+ (10, 30),
+ (10, 32),
+ (11, 32),
+ (11, 34),
+ (12, 34),
+ (12, 36),
+ (1, 36),
+ (13, 14),
+ (14, 15),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 20),
+ (20, 21),
+ (21, 22),
+ (22, 23),
+ (23, 24),
+ (24, 25),
+ (25, 26),
+ (26, 27),
+ (27, 28),
+ (28, 29),
+ (29, 30),
+ (30, 31),
+ (31, 32),
+ (32, 33),
+ (33, 34),
+ (34, 35),
+ (35, 36),
+ (36, 13),
+ (13, 37),
+ (15, 38),
+ (17, 39),
+ (19, 40),
+ (21, 41),
+ (23, 42),
+ (25, 43),
+ (27, 44),
+ (29, 45),
+ (31, 46),
+ (33, 47),
+ (35, 48),
+ (14, 37),
+ (14, 38),
+ (16, 38),
+ (16, 39),
+ (18, 39),
+ (18, 40),
+ (20, 40),
+ (20, 41),
+ (22, 41),
+ (22, 42),
+ (24, 42),
+ (24, 43),
+ (26, 43),
+ (26, 44),
+ (28, 44),
+ (28, 45),
+ (30, 45),
+ (30, 46),
+ (32, 46),
+ (32, 47),
+ (34, 47),
+ (34, 48),
+ (36, 48),
+ (36, 37)
+ ]
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 30450000, 0.288)
+ # print(A.shape)
+ memberType = MemberType(A[index].item(), 30450000, 0.288)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.288)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 30450000, Rho[index].item())
+
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_4forces(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (0.0, 0.0, -5000.0)),
+ (17, (0.0, 0.0, -5000.0)),
+ (18, (0.0, 0.0, -5000.0)),
+ (19, (0.0, 0.0, -5000.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_single(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (5000.0, 5000.0, -5000.0)),
+ (17, (0.0, 0.0, 0.0)),
+ (18, (0.0, 0.0, 0.0)),
+ (19, (0.0, 0.0, 0.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss942bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ [24.5, 24.5, 312.0],
+ [38.5, 24.5, 312.0],
+ [24.5, 38.5, 312.0],
+ [38.5, 38.5, 312.0],
+ [24.5, 24.5, 300.0],
+ [38.5, 24.5, 300.0],
+ [24.5, 38.5, 300.0],
+ [38.5, 38.5, 300.0],
+ [24.5, 24.5, 288.0],
+ [38.5, 24.5, 288.0],
+ [24.5, 38.5, 288.0],
+ [38.5, 38.5, 288.0],
+ [24.5, 24.5, 276.0],
+ [38.5, 24.5, 276.0],
+ [24.5, 38.5, 276.0],
+ [38.5, 38.5, 276.0],
+ [24.5, 24.5, 264.0],
+ [38.5, 24.5, 264.0],
+ [24.5, 38.5, 264.0],
+ [38.5, 38.5, 264.0],
+ [24.5, 24.5, 252.0],
+ [38.5, 24.5, 252.0],
+ [24.5, 38.5, 252.0],
+ [38.5, 38.5, 252.0],
+ [21.6005, 21.6005, 240.0],
+ [31.5, 17.5, 240.0],
+ [41.3995, 21.6005, 240.0],
+ [17.5, 31.5, 240.0],
+ [45.5, 31.5, 240.0],
+ [21.6005, 41.3995, 240.0],
+ [31.5, 45.5, 240.0],
+ [41.3995, 41.3995, 240.0],
+ [21.6005, 21.6005, 228.0],
+ [31.5, 17.5, 228.0],
+ [41.3995, 21.6005, 228.0],
+ [17.5, 31.5, 228.0],
+ [45.5, 31.5, 228.0],
+ [21.6005, 41.3995, 228.0],
+ [31.5, 45.5, 228.0],
+ [41.3995, 41.3995, 228.0],
+ [21.6005, 21.6005, 216.0],
+ [31.5, 17.5, 216.0],
+ [41.3995, 21.6005, 216.0],
+ [17.5, 31.5, 216.0],
+ [45.5, 31.5, 216.0],
+ [21.6005, 41.3995, 216.0],
+ [31.5, 45.5, 216.0],
+ [41.3995, 41.3995, 216.0],
+ [21.6005, 21.6005, 204.0],
+ [31.5, 17.5, 204.0],
+ [41.3995, 21.6005, 204.0],
+ [17.5, 31.5, 204.0],
+ [45.5, 31.5, 204.0],
+ [21.6005, 41.3995, 204.0],
+ [31.5, 45.5, 204.0],
+ [41.3995, 41.3995, 204.0],
+ [21.6005, 21.6005, 192.0],
+ [31.5, 17.5, 192.0],
+ [41.3995, 21.6005, 192.0],
+ [17.5, 31.5, 192.0],
+ [45.5, 31.5, 192.0],
+ [21.6005, 41.3995, 192.0],
+ [31.5, 45.5, 192.0],
+ [41.3995, 41.3995, 192.0],
+ [21.6005, 21.6005, 180.0],
+ [31.5, 17.5, 180.0],
+ [41.3995, 21.6005, 180.0],
+ [17.5, 31.5, 180.0],
+ [45.5, 31.5, 180.0],
+ [21.6005, 41.3995, 180.0],
+ [31.5, 45.5, 180.0],
+ [41.3995, 41.3995, 180.0],
+ [21.6005, 21.6005, 168.0],
+ [31.5, 17.5, 168.0],
+ [41.3995, 21.6005, 168.0],
+ [17.5, 31.5, 168.0],
+ [45.5, 31.5, 168.0],
+ [21.6005, 41.3995, 168.0],
+ [31.5, 45.5, 168.0],
+ [41.3995, 41.3995, 168.0],
+ [21.6005, 21.6005, 156.0],
+ [31.5, 17.5, 156.0],
+ [41.3995, 21.6005, 156.0],
+ [17.5, 31.5, 156.0],
+ [45.5, 31.5, 156.0],
+ [21.6005, 41.3995, 156.0],
+ [31.5, 45.5, 156.0],
+ [41.3995, 41.3995, 156.0],
+ [7.0, 24.5, 144.0],
+ [11.1199, 11.1199, 144.0],
+ [24.5, 7.0, 144.0],
+ [38.5, 7.0, 144.0],
+ [51.8801, 11.1199, 144.0],
+ [56.0, 24.5, 144.0],
+ [7.0, 38.5, 144.0],
+ [11.1199, 51.8801, 144.0],
+ [24.5, 56.0, 144.0],
+ [38.5, 56.0, 144.0],
+ [51.8801, 51.8801, 144.0],
+ [56.0, 38.5, 144.0],
+ [7.0, 24.5, 132.0],
+ [11.1199, 11.1199, 132.0],
+ [24.5, 7.0, 132.0],
+ [38.5, 7.0, 132.0],
+ [51.8801, 11.1199, 132.0],
+ [56.0, 24.5, 132.0],
+ [7.0, 38.5, 132.0],
+ [11.1199, 51.8801, 132.0],
+ [24.5, 56.0, 132.0],
+ [38.5, 56.0, 132.0],
+ [51.8801, 51.8801, 132.0],
+ [56.0, 38.5, 132.0],
+ [7.0, 24.5, 120.0],
+ [11.1199, 11.1199, 120.0],
+ [24.5, 7.0, 120.0],
+ [38.5, 7.0, 120.0],
+ [51.8801, 11.1199, 120.0],
+ [56.0, 24.5, 120.0],
+ [7.0, 38.5, 120.0],
+ [11.1199, 51.8801, 120.0],
+ [24.5, 56.0, 120.0],
+ [38.5, 56.0, 120.0],
+ [51.8801, 51.8801, 120.0],
+ [56.0, 38.5, 120.0],
+ [7.0, 24.5, 108.0],
+ [11.1199, 11.1199, 108.0],
+ [24.5, 7.0, 108.0],
+ [38.5, 7.0, 108.0],
+ [51.8801, 11.1199, 108.0],
+ [56.0, 24.5, 108.0],
+ [7.0, 38.5, 108.0],
+ [11.1199, 51.8801, 108.0],
+ [24.5, 56.0, 108.0],
+ [38.5, 56.0, 108.0],
+ [51.8801, 51.8801, 108.0],
+ [56.0, 38.5, 108.0],
+ [7.0, 24.5, 96.0],
+ [11.1199, 11.1199, 96.0],
+ [24.5, 7.0, 96.0],
+ [38.5, 7.0, 96.0],
+ [51.8801, 11.1199, 96.0],
+ [56.0, 24.5, 96.0],
+ [7.0, 38.5, 96.0],
+ [11.1199, 51.8801, 96.0],
+ [24.5, 56.0, 96.0],
+ [38.5, 56.0, 96.0],
+ [51.8801, 51.8801, 96.0],
+ [56.0, 38.5, 96.0],
+ [7.0, 24.5, 84.0],
+ [11.1199, 11.1199, 84.0],
+ [24.5, 7.0, 84.0],
+ [38.5, 7.0, 84.0],
+ [51.8801, 11.1199, 84.0],
+ [56.0, 24.5, 84.0],
+ [7.0, 38.5, 84.0],
+ [11.1199, 51.8801, 84.0],
+ [24.5, 56.0, 84.0],
+ [38.5, 56.0, 84.0],
+ [51.8801, 51.8801, 84.0],
+ [56.0, 38.5, 84.0],
+ [7.0, 24.5, 72.0],
+ [11.1199, 11.1199, 72.0],
+ [24.5, 7.0, 72.0],
+ [38.5, 7.0, 72.0],
+ [51.8801, 11.1199, 72.0],
+ [56.0, 24.5, 72.0],
+ [7.0, 38.5, 72.0],
+ [11.1199, 51.8801, 72.0],
+ [24.5, 56.0, 72.0],
+ [38.5, 56.0, 72.0],
+ [51.8801, 51.8801, 72.0],
+ [56.0, 38.5, 72.0],
+ [7.0, 24.5, 60.0],
+ [11.1199, 11.1199, 60.0],
+ [24.5, 7.0, 60.0],
+ [38.5, 7.0, 60.0],
+ [51.8801, 11.1199, 60.0],
+ [56.0, 24.5, 60.0],
+ [7.0, 38.5, 60.0],
+ [11.1199, 51.8801, 60.0],
+ [24.5, 56.0, 60.0],
+ [38.5, 56.0, 60.0],
+ [51.8801, 51.8801, 60.0],
+ [56.0, 38.5, 60.0],
+ [7.0, 24.5, 48.0],
+ [11.1199, 11.1199, 48.0],
+ [24.5, 7.0, 48.0],
+ [38.5, 7.0, 48.0],
+ [51.8801, 11.1199, 48.0],
+ [56.0, 24.5, 48.0],
+ [7.0, 38.5, 48.0],
+ [11.1199, 51.8801, 48.0],
+ [24.5, 56.0, 48.0],
+ [38.5, 56.0, 48.0],
+ [51.8801, 51.8801, 48.0],
+ [56.0, 38.5, 48.0],
+ [7.0, 24.5, 36.0],
+ [11.1199, 11.1199, 36.0],
+ [24.5, 7.0, 36.0],
+ [38.5, 7.0, 36.0],
+ [51.8801, 11.1199, 36.0],
+ [56.0, 24.5, 36.0],
+ [7.0, 38.5, 36.0],
+ [11.1199, 51.8801, 36.0],
+ [24.5, 56.0, 36.0],
+ [38.5, 56.0, 36.0],
+ [51.8801, 51.8801, 36.0],
+ [56.0, 38.5, 36.0],
+ [7.0, 24.5, 24.0],
+ [11.1199, 11.1199, 24.0],
+ [24.5, 7.0, 24.0],
+ [38.5, 7.0, 24.0],
+ [51.8801, 11.1199, 24.0],
+ [56.0, 24.5, 24.0],
+ [7.0, 38.5, 24.0],
+ [11.1199, 51.8801, 24.0],
+ [24.5, 56.0, 24.0],
+ [38.5, 56.0, 24.0],
+ [51.8801, 51.8801, 24.0],
+ [56.0, 38.5, 24.0],
+ [7.0, 24.5, 12.0],
+ [11.1199, 11.1199, 12.0],
+ [24.5, 7.0, 12.0],
+ [38.5, 7.0, 12.0],
+ [51.8801, 11.1199, 12.0],
+ [56.0, 24.5, 12.0],
+ [7.0, 38.5, 12.0],
+ [11.1199, 51.8801, 12.0],
+ [24.5, 56.0, 12.0],
+ [38.5, 56.0, 12.0],
+ [51.8801, 51.8801, 12.0],
+ [56.0, 38.5, 12.0],
+ [7.0, 24.5, 0.0],
+ [11.1199, 11.1199, 0.0],
+ [24.5, 7.0, 0.0],
+ [38.5, 7.0, 0.0],
+ [51.8801, 11.1199, 0.0],
+ [56.0, 24.5, 0.0],
+ [7.0, 38.5, 0.0],
+ [11.1199, 51.8801, 0.0],
+ [24.5, 56.0, 0.0],
+ [38.5, 56.0, 0.0],
+ [51.8801, 51.8801, 0.0],
+ [56.0, 38.5, 0.0]
+ ]
+
+
+ supports = []
+ for ii in range(244-12):
+ supports.append(SupportType.NO)
+ for ii in range(12):
+ supports.append(SupportType.PIN)
+
+
+ forces = [
+ (0, (1.5, -1.0, -3.0)),
+ (1, (-1.0, -1.0, -3.0)),
+ (2, (1.5, -1.0, -3.0)),
+ (3, (-1.0, 1.0, -3.0)),
+ (4, (1.5, -1.0, -3.0)),
+ (5, (-1.0, -1.0, -3.0)),
+ (6, (1.5, -1.0, -3.0)),
+ (7, (-1.0, 1.0, -3.0)),
+ (8, (1.5, -1.0, -3.0)),
+ (9, (-1.0, -1.0, -3.0)),
+ (10, (1.5, -1.0, -3.0)),
+ (11, (-1.0, 1.0, -3.0)),
+ (12, (1.5, -1.0, -3.0)),
+ (13, (-1.0, -1.0, -3.0)),
+ (14, (1.5, -1.0, -3.0)),
+ (15, (-1.0, 1.0, -3.0)),
+ (16, (1.5, -1.0, -3.0)),
+ (17, (-1.0, -1.0, -3.0)),
+ (18, (1.5, -1.0, -3.0)),
+ (19, (-1.0, 1.0, -3.0)),
+ (20, (1.5, -1.0, -3.0)),
+ (21, (-1.0, -1.0, -3.0)),
+ (22, (1.5, -1.0, -3.0)),
+ (23, (-1.0, 1.0, -3.0)),
+ (24, (1.5, -1.0, -3.0)),
+ (25, (0.0, -1.0, -3.0)),
+ (26, (-1.0, -1.0, -3.0)),
+ (27, (1.5, 0.0, -3.0)),
+ (28, (-1.0, 0.0, -3.0)),
+ (29, (1.5, 1.0, -3.0)),
+ (30, (0.0, 1.0, -3.0)),
+ (31, (-1.0, 1.0, -3.0)),
+ (32, (1.5, -1.0, -6.0)),
+ (33, (0.0, -1.0, -6.0)),
+ (34, (-1.0, -1.0, -6.0)),
+ (35, (1.5, 0.0, -6.0)),
+ (36, (-1.0, 0.0, -6.0)),
+ (37, (1.5, 1.0, -6.0)),
+ (38, (0.0, 1.0, -6.0)),
+ (39, (-1.0, 1.0, -6.0)),
+ (40, (1.5, -1.0, -6.0)),
+ (41, (0.0, -1.0, -6.0)),
+ (42, (-1.0, -1.0, -6.0)),
+ (43, (1.5, 0.0, -6.0)),
+ (44, (-1.0, 0.0, -6.0)),
+ (45, (1.5, 1.0, -6.0)),
+ (46, (0.0, 1.0, -6.0)),
+ (47, (-1.0, 1.0, -6.0)),
+ (48, (1.5, -1.0, -6.0)),
+ (49, (0.0, -1.0, -6.0)),
+ (50, (-1.0, -1.0, -6.0)),
+ (51, (1.5, 0.0, -6.0)),
+ (52, (-1.0, 0.0, -6.0)),
+ (53, (1.5, 1.0, -6.0)),
+ (54, (0.0, 1.0, -6.0)),
+ (55, (-1.0, 1.0, -6.0)),
+ (56, (1.5, -1.0, -6.0)),
+ (57, (0.0, -1.0, -6.0)),
+ (58, (-1.0, -1.0, -6.0)),
+ (59, (1.5, 0.0, -6.0)),
+ (60, (-1.0, 0.0, -6.0)),
+ (61, (1.5, 1.0, -6.0)),
+ (62, (0.0, 1.0, -6.0)),
+ (63, (-1.0, 1.0, -6.0)),
+ (64, (1.5, -1.0, -6.0)),
+ (65, (0.0, -1.0, -6.0)),
+ (66, (-1.0, -1.0, -6.0)),
+ (67, (1.5, 0.0, -6.0)),
+ (68, (-1.0, 0.0, -6.0)),
+ (69, (1.5, 1.0, -6.0)),
+ (70, (0.0, 1.0, -6.0)),
+ (71, (-1.0, 1.0, -6.0)),
+ (72, (1.5, -1.0, -6.0)),
+ (73, (0.0, -1.0, -6.0)),
+ (74, (-1.0, -1.0, -6.0)),
+ (75, (1.5, 0.0, -6.0)),
+ (76, (-1.0, 0.0, -6.0)),
+ (77, (1.5, 1.0, -6.0)),
+ (78, (0.0, 1.0, -6.0)),
+ (79, (-1.0, 1.0, -6.0)),
+ (80, (1.5, -1.0, -6.0)),
+ (81, (0.0, -1.0, -6.0)),
+ (82, (-1.0, -1.0, -6.0)),
+ (83, (1.5, 0.0, -6.0)),
+ (84, (-1.0, 0.0, -6.0)),
+ (85, (1.5, 1.0, -6.0)),
+ (86, (0.0, 1.0, -6.0)),
+ (87, (-1.0, 1.0, -6.0)),
+ (88, (1.5, -1.0, -6.0)),
+ (89, (1.5, -1.0, -6.0)),
+ (90, (1.5, -1.0, -6.0)),
+ (91, (-1.0, -1.0, -6.0)),
+ (92, (-1.0, -1.0, -6.0)),
+ (93, (-1.0, -1.0, -6.0)),
+ (94, (1.5, 1.0, -6.0)),
+ (95, (1.5, 1.0, -6.0)),
+ (96, (1.5, 1.0, -6.0)),
+ (97, (-1.0, 1.0, -6.0)),
+ (98, (-1.0, 1.0, -6.0)),
+ (99, (-1.0, 1.0, -6.0)),
+ (100, (1.5, -1.0, -9.0)),
+ (101, (1.5, -1.0, -9.0)),
+ (102, (1.5, -1.0, -9.0)),
+ (103, (-1.0, -1.0, -9.0)),
+ (104, (-1.0, -1.0, -9.0)),
+ (105, (-1.0, -1.0, -9.0)),
+ (106, (1.5, 1.0, -9.0)),
+ (107, (1.5, 1.0, -9.0)),
+ (108, (1.5, 1.0, -9.0)),
+ (109, (-1.0, 1.0, -9.0)),
+ (110, (-1.0, 1.0, -9.0)),
+ (111, (-1.0, 1.0, -9.0)),
+ (112, (1.5, -1.0, -9.0)),
+ (113, (1.5, -1.0, -9.0)),
+ (114, (1.5, -1.0, -9.0)),
+ (115, (-1.0, -1.0, -9.0)),
+ (116, (-1.0, -1.0, -9.0)),
+ (117, (-1.0, -1.0, -9.0)),
+ (118, (1.5, 1.0, -9.0)),
+ (119, (1.5, 1.0, -9.0)),
+ (120, (1.5, 1.0, -9.0)),
+ (121, (-1.0, 1.0, -9.0)),
+ (122, (-1.0, 1.0, -9.0)),
+ (123, (-1.0, 1.0, -9.0)),
+ (124, (1.5, -1.0, -9.0)),
+ (125, (1.5, -1.0, -9.0)),
+ (126, (1.5, -1.0, -9.0)),
+ (127, (-1.0, -1.0, -9.0)),
+ (128, (-1.0, -1.0, -9.0)),
+ (129, (-1.0, -1.0, -9.0)),
+ (130, (1.5, 1.0, -9.0)),
+ (131, (1.5, 1.0, -9.0)),
+ (132, (1.5, 1.0, -9.0)),
+ (133, (-1.0, 1.0, -9.0)),
+ (134, (-1.0, 1.0, -9.0)),
+ (135, (-1.0, 1.0, -9.0)),
+ (136, (1.5, -1.0, -9.0)),
+ (137, (1.5, -1.0, -9.0)),
+ (138, (1.5, -1.0, -9.0)),
+ (139, (-1.0, -1.0, -9.0)),
+ (140, (-1.0, -1.0, -9.0)),
+ (141, (-1.0, -1.0, -9.0)),
+ (142, (1.5, 1.0, -9.0)),
+ (143, (1.5, 1.0, -9.0)),
+ (144, (1.5, 1.0, -9.0)),
+ (145, (-1.0, 1.0, -9.0)),
+ (146, (-1.0, 1.0, -9.0)),
+ (147, (-1.0, 1.0, -9.0)),
+ (148, (1.5, -1.0, -9.0)),
+ (149, (1.5, -1.0, -9.0)),
+ (150, (1.5, -1.0, -9.0)),
+ (151, (-1.0, -1.0, -9.0)),
+ (152, (-1.0, -1.0, -9.0)),
+ (153, (-1.0, -1.0, -9.0)),
+ (154, (1.5, 1.0, -9.0)),
+ (155, (1.5, 1.0, -9.0)),
+ (156, (1.5, 1.0, -9.0)),
+ (157, (-1.0, 1.0, -9.0)),
+ (158, (-1.0, 1.0, -9.0)),
+ (159, (-1.0, 1.0, -9.0)),
+ (160, (1.5, -1.0, -9.0)),
+ (161, (1.5, -1.0, -9.0)),
+ (162, (1.5, -1.0, -9.0)),
+ (163, (-1.0, -1.0, -9.0)),
+ (164, (-1.0, -1.0, -9.0)),
+ (165, (-1.0, -1.0, -9.0)),
+ (166, (1.5, 1.0, -9.0)),
+ (167, (1.5, 1.0, -9.0)),
+ (168, (1.5, 1.0, -9.0)),
+ (169, (-1.0, 1.0, -9.0)),
+ (170, (-1.0, 1.0, -9.0)),
+ (171, (-1.0, 1.0, -9.0)),
+ (172, (1.5, -1.0, -9.0)),
+ (173, (1.5, -1.0, -9.0)),
+ (174, (1.5, -1.0, -9.0)),
+ (175, (-1.0, -1.0, -9.0)),
+ (176, (-1.0, -1.0, -9.0)),
+ (177, (-1.0, -1.0, -9.0)),
+ (178, (1.5, 1.0, -9.0)),
+ (179, (1.5, 1.0, -9.0)),
+ (180, (1.5, 1.0, -9.0)),
+ (181, (-1.0, 1.0, -9.0)),
+ (182, (-1.0, 1.0, -9.0)),
+ (183, (-1.0, 1.0, -9.0)),
+ (184, (1.5, -1.0, -9.0)),
+ (185, (1.5, -1.0, -9.0)),
+ (186, (1.5, -1.0, -9.0)),
+ (187, (-1.0, -1.0, -9.0)),
+ (188, (-1.0, -1.0, -9.0)),
+ (189, (-1.0, -1.0, -9.0)),
+ (190, (1.5, 1.0, -9.0)),
+ (191, (1.5, 1.0, -9.0)),
+ (192, (1.5, 1.0, -9.0)),
+ (193, (-1.0, 1.0, -9.0)),
+ (194, (-1.0, 1.0, -9.0)),
+ (195, (-1.0, 1.0, -9.0)),
+ (196, (1.5, -1.0, -9.0)),
+ (197, (1.5, -1.0, -9.0)),
+ (198, (1.5, -1.0, -9.0)),
+ (199, (-1.0, -1.0, -9.0)),
+ (200, (-1.0, -1.0, -9.0)),
+ (201, (-1.0, -1.0, -9.0)),
+ (202, (1.5, 1.0, -9.0)),
+ (203, (1.5, 1.0, -9.0)),
+ (204, (1.5, 1.0, -9.0)),
+ (205, (-1.0, 1.0, -9.0)),
+ (206, (-1.0, 1.0, -9.0)),
+ (207, (-1.0, 1.0, -9.0)),
+ (208, (1.5, -1.0, -9.0)),
+ (209, (1.5, -1.0, -9.0)),
+ (210, (1.5, -1.0, -9.0)),
+ (211, (-1.0, -1.0, -9.0)),
+ (212, (-1.0, -1.0, -9.0)),
+ (213, (-1.0, -1.0, -9.0)),
+ (214, (1.5, 1.0, -9.0)),
+ (215, (1.5, 1.0, -9.0)),
+ (216, (1.5, 1.0, -9.0)),
+ (217, (-1.0, 1.0, -9.0)),
+ (218, (-1.0, 1.0, -9.0)),
+ (219, (-1.0, 1.0, -9.0)),
+ (220, (1.5, -1.0, -9.0)),
+ (221, (1.5, -1.0, -9.0)),
+ (222, (1.5, -1.0, -9.0)),
+ (223, (-1.0, -1.0, -9.0)),
+ (224, (-1.0, -1.0, -9.0)),
+ (225, (-1.0, -1.0, -9.0)),
+ (226, (1.5, 1.0, -9.0)),
+ (227, (1.5, 1.0, -9.0)),
+ (228, (1.5, 1.0, -9.0)),
+ (229, (-1.0, 1.0, -9.0)),
+ (230, (-1.0, 1.0, -9.0)),
+ (231, (-1.0, 1.0, -9.0))
+ ]
+
+
+
+
+ members = [
+ (0, 3),
+ (1, 2),
+ (0, 1),
+ (2, 3),
+ (0, 2),
+ (1, 3),
+ (4, 5),
+ (6, 7),
+ (4, 6),
+ (5, 7),
+ (1, 5),
+ (0, 4),
+ (3, 7),
+ (2, 6),
+ (5, 9),
+ (4, 8),
+ (7, 11),
+ (6, 10),
+ (1, 4),
+ (0, 5),
+ (1, 7),
+ (3, 5),
+ (3, 6),
+ (2, 7),
+ (0, 6),
+ (2, 4),
+ (5, 8),
+ (4, 9),
+ (5, 11),
+ (7, 9),
+ (7, 10),
+ (6, 11),
+ (6, 8),
+ (4, 10),
+ (8, 9),
+ (10, 11),
+ (8, 10),
+ (9, 11),
+ (12, 13),
+ (14, 15),
+ (12, 14),
+ (13, 15),
+ (16, 17),
+ (18, 19),
+ (16, 18),
+ (17, 19),
+ (9, 13),
+ (8, 12),
+ (11, 15),
+ (10, 14),
+ (13, 17),
+ (12, 16),
+ (15, 19),
+ (16, 18),
+ (17, 21),
+ (16, 20),
+ (19, 23),
+ (18, 22),
+ (8, 13),
+ (9, 12),
+ (9, 15),
+ (11, 13),
+ (11, 14),
+ (10, 15),
+ (10, 12),
+ (8, 14),
+ (12, 17),
+ (13, 16),
+ (13, 19),
+ (15, 17),
+ (15, 18),
+ (14, 19),
+ (14, 16),
+ (12, 18),
+ (16, 21),
+ (17, 20),
+ (17, 23),
+ (19, 21),
+ (19, 22),
+ (18, 23),
+ (18, 20),
+ (16, 22),
+ (20, 21),
+ (22, 23),
+ (20, 22),
+ (21, 23),
+ (21, 24),
+ (20, 26),
+ (21, 31),
+ (23, 26),
+ (23, 29),
+ (22, 31),
+ (22, 24),
+ (20, 29),
+ (21, 26),
+ (20, 24),
+ (23, 31),
+ (22, 29),
+ (21, 25),
+ (20, 25),
+ (21, 28),
+ (23, 28),
+ (23, 30),
+ (22, 30),
+ (22, 27),
+ (20, 27),
+ (24, 25),
+ (25, 26),
+ (24, 27),
+ (27, 29),
+ (29, 30),
+ (30, 31),
+ (26, 28),
+ (28, 31),
+ (32, 33),
+ (33, 34),
+ (32, 35),
+ (35, 37),
+ (37, 38),
+ (38, 39),
+ (34, 36),
+ (36, 39),
+ (24, 32),
+ (26, 34),
+ (29, 37),
+ (31, 39),
+ (32, 40),
+ (34, 42),
+ (37, 45),
+ (39, 47),
+ (24, 33),
+ (25, 32),
+ (25, 34),
+ (26, 33),
+ (27, 32),
+ (24, 35),
+ (26, 36),
+ (28, 34),
+ (28, 39),
+ (31, 36),
+ (31, 38),
+ (30, 39),
+ (30, 37),
+ (29, 38),
+ (29, 35),
+ (27, 37),
+ (32, 41),
+ (33, 40),
+ (33, 42),
+ (34, 41),
+ (34, 44),
+ (36, 42),
+ (36, 47),
+ (39, 44),
+ (39, 46),
+ (38, 47),
+ (38, 45),
+ (37, 46),
+ (37, 43),
+ (35, 45),
+ (35, 40),
+ (32, 43),
+ (25, 33),
+ (27, 35),
+ (30, 38),
+ (28, 36),
+ (33, 41),
+ (35, 43),
+ (38, 46),
+ (36, 44),
+ (40, 41),
+ (41, 42),
+ (40, 43),
+ (42, 44),
+ (43, 45),
+ (45, 46),
+ (46, 47),
+ (44, 47),
+ (48, 49),
+ (49, 50),
+ (48, 51),
+ (50, 52),
+ (51, 53),
+ (53, 54),
+ (54, 55),
+ (52, 55),
+ (42, 50),
+ (40, 48),
+ (45, 53),
+ (47, 55),
+ (48, 56),
+ (50, 58),
+ (53, 61),
+ (55, 63),
+ (40, 49),
+ (41, 48),
+ (41, 50),
+ (42, 49),
+ (42, 52),
+ (44, 50),
+ (44, 55),
+ (47, 52),
+ (47, 54),
+ (46, 55),
+ (46, 53),
+ (45, 54),
+ (45, 51),
+ (43, 53),
+ (43, 48),
+ (40, 51),
+ (48, 57),
+ (49, 56),
+ (49, 58),
+ (50, 57),
+ (50, 60),
+ (52, 58),
+ (52, 63),
+ (55, 60),
+ (55, 62),
+ (54, 63),
+ (54, 61),
+ (53, 62),
+ (53, 59),
+ (51, 61),
+ (51, 56),
+ (48, 59),
+ (41, 49),
+ (43, 51),
+ (44, 52),
+ (46, 54),
+ (49, 57),
+ (51, 59),
+ (52, 60),
+ (54, 62),
+ (56, 57),
+ (57, 58),
+ (56, 59),
+ (58, 60),
+ (59, 61),
+ (60, 63),
+ (61, 62),
+ (62, 63),
+ (64, 65),
+ (65, 66),
+ (64, 67),
+ (66, 68),
+ (67, 69),
+ (68, 71),
+ (69, 70),
+ (70, 71),
+ (72, 73),
+ (73, 74),
+ (72, 75),
+ (74, 76),
+ (75, 77),
+ (76, 79),
+ (77, 78),
+ (78, 79),
+ (56, 64),
+ (58, 66),
+ (61, 69),
+ (63, 71),
+ (64, 72),
+ (66, 74),
+ (69, 77),
+ (71, 79),
+ (72, 80),
+ (74, 82),
+ (77, 85),
+ (79, 87),
+ (56, 65),
+ (57, 64),
+ (57, 66),
+ (58, 65),
+ (58, 68),
+ (60, 66),
+ (60, 71),
+ (63, 68),
+ (63, 70),
+ (62, 71),
+ (62, 69),
+ (61, 70),
+ (61, 67),
+ (59, 69),
+ (59, 64),
+ (56, 67),
+ (64, 73),
+ (65, 72),
+ (65, 74),
+ (66, 73),
+ (66, 76),
+ (68, 74),
+ (68, 79),
+ (71, 76),
+ (71, 78),
+ (70, 79),
+ (70, 77),
+ (69, 78),
+ (69, 75),
+ (67, 77),
+ (67, 72),
+ (64, 75),
+ (72, 81),
+ (73, 80),
+ (73, 82),
+ (74, 81),
+ (74, 84),
+ (76, 82),
+ (76, 87),
+ (79, 84),
+ (79, 86),
+ (78, 87),
+ (78, 85),
+ (77, 86),
+ (77, 83),
+ (75, 85),
+ (75, 80),
+ (72, 83),
+ (57, 65),
+ (59, 67),
+ (60, 68),
+ (62, 70),
+ (65, 73),
+ (67, 75),
+ (68, 76),
+ (70, 78),
+ (73, 81),
+ (75, 83),
+ (76, 84),
+ (78, 86),
+ (80, 81),
+ (81, 82),
+ (80, 83),
+ (82, 84),
+ (83, 85),
+ (84, 87),
+ (85, 86),
+ (86, 87),
+ (80, 89),
+ (82, 92),
+ (85, 95),
+ (87, 98),
+ (81, 89),
+ (81, 92),
+ (84, 92),
+ (84, 98),
+ (83, 95),
+ (83, 89),
+ (86, 95),
+ (86, 98),
+ (82, 91),
+ (80, 90),
+ (82, 93),
+ (87, 99),
+ (80, 88),
+ (85, 94),
+ (85, 96),
+ (87, 97),
+ (81, 91),
+ (81, 90),
+ (83, 88),
+ (83, 94),
+ (84, 93),
+ (84, 99),
+ (86, 96),
+ (86, 97),
+ (89, 90),
+ (91, 92),
+ (88, 89),
+ (92, 93),
+ (94, 95),
+ (95, 96),
+ (97, 98),
+ (98, 99),
+ (101, 102),
+ (103, 104),
+ (100, 101),
+ (104, 105),
+ (106, 107),
+ (107, 108),
+ (109, 110),
+ (110, 111),
+ (90, 91),
+ (88, 94),
+ (93, 99),
+ (96, 97),
+ (102, 103),
+ (100, 106),
+ (105, 111),
+ (108, 109),
+ (89, 101),
+ (92, 104),
+ (95, 107),
+ (98, 110),
+ (101, 113),
+ (104, 116),
+ (107, 119),
+ (110, 122),
+ (92, 103),
+ (91, 104),
+ (89, 102),
+ (90, 101),
+ (88, 101),
+ (89, 100),
+ (92, 105),
+ (93, 104),
+ (99, 110),
+ (98, 111),
+ (98, 109),
+ (97, 110),
+ (96, 107),
+ (95, 108),
+ (95, 106),
+ (94, 107),
+ (101, 114),
+ (102, 113),
+ (101, 112),
+ (100, 113),
+ (103, 116),
+ (104, 115),
+ (104, 117),
+ (105, 116),
+ (111, 122),
+ (110, 123),
+ (110, 121),
+ (109, 122),
+ (108, 119),
+ (107, 120),
+ (107, 118),
+ (106, 119),
+ (90, 102),
+ (91, 103),
+ (96, 108),
+ (97, 109),
+ (88, 100),
+ (94, 106),
+ (93, 105),
+ (99, 111),
+ (102, 114),
+ (103, 115),
+ (108, 120),
+ (109, 121),
+ (100, 112),
+ (106, 118),
+ (105, 117),
+ (111, 123),
+ (90, 103),
+ (91, 102),
+ (96, 109),
+ (97, 108),
+ (88, 106),
+ (94, 100),
+ (93, 111),
+ (99, 105),
+ (102, 115),
+ (103, 114),
+ (108, 121),
+ (109, 120),
+ (105, 123),
+ (111, 117),
+ (100, 118),
+ (106, 112),
+ (112, 113),
+ (113, 114),
+ (115, 116),
+ (116, 117),
+ (118, 119),
+ (119, 120),
+ (121, 122),
+ (122, 123),
+ (124, 125),
+ (125, 126),
+ (127, 128),
+ (128, 129),
+ (130, 131),
+ (131, 132),
+ (133, 134),
+ (134, 135),
+ (136, 137),
+ (137, 138),
+ (139, 140),
+ (140, 141),
+ (142, 143),
+ (143, 144),
+ (145, 146),
+ (146, 147),
+ (114, 115),
+ (120, 121),
+ (112, 118),
+ (117, 123),
+ (126, 127),
+ (132, 133),
+ (124, 130),
+ (129, 135),
+ (138, 139),
+ (144, 145),
+ (136, 142),
+ (141, 147),
+ (113, 125),
+ (116, 128),
+ (119, 131),
+ (122, 134),
+ (125, 137),
+ (128, 140),
+ (131, 143),
+ (134, 146),
+ (137, 149),
+ (140, 152),
+ (143, 155),
+ (146, 158),
+ (112, 125),
+ (113, 124),
+ (113, 126),
+ (114, 125),
+ (115, 128),
+ (116, 127),
+ (116, 129),
+ (117, 128),
+ (118, 131),
+ (119, 130),
+ (119, 132),
+ (120, 131),
+ (121, 134),
+ (122, 133),
+ (122, 135),
+ (123, 134),
+ (124, 137),
+ (125, 136),
+ (125, 138),
+ (126, 137),
+ (127, 140),
+ (128, 139),
+ (128, 141),
+ (129, 140),
+ (130, 143),
+ (131, 142),
+ (131, 144),
+ (132, 143),
+ (133, 146),
+ (134, 145),
+ (134, 147),
+ (135, 146),
+ (136, 149),
+ (137, 148),
+ (137, 150),
+ (138, 149),
+ (139, 152),
+ (140, 151),
+ (140, 153),
+ (141, 152),
+ (142, 155),
+ (143, 154),
+ (143, 156),
+ (144, 155),
+ (145, 158),
+ (146, 157),
+ (146, 159),
+ (147, 158),
+ (114, 126),
+ (115, 127),
+ (120, 132),
+ (121, 133),
+ (112, 124),
+ (118, 130),
+ (117, 129),
+ (123, 135),
+ (126, 138),
+ (127, 139),
+ (132, 144),
+ (133, 145),
+ (124, 136),
+ (130, 142),
+ (129, 141),
+ (135, 147),
+ (138, 150),
+ (139, 151),
+ (144, 156),
+ (145, 157),
+ (136, 148),
+ (142, 154),
+ (141, 153),
+ (147, 159),
+ (114, 127),
+ (115, 126),
+ (120, 133),
+ (121, 132),
+ (112, 130),
+ (118, 124),
+ (117, 135),
+ (123, 129),
+ (126, 139),
+ (127, 138),
+ (132, 145),
+ (133, 144),
+ (124, 142),
+ (130, 136),
+ (129, 147),
+ (135, 141),
+ (138, 151),
+ (139, 150),
+ (144, 157),
+ (145, 156),
+ (136, 154),
+ (142, 148),
+ (141, 153),
+ (147, 153),
+ (148, 149),
+ (149, 150),
+ (151, 152),
+ (152, 153),
+ (154, 155),
+ (155, 156),
+ (157, 158),
+ (158, 159),
+ (160, 161),
+ (161, 162),
+ (163, 164),
+ (164, 165),
+ (166, 167),
+ (167, 168),
+ (169, 170),
+ (170, 171),
+ (172, 173),
+ (173, 174),
+ (175, 176),
+ (176, 177),
+ (178, 179),
+ (179, 180),
+ (181, 182),
+ (182, 183),
+ (150, 151),
+ (156, 157),
+ (148, 154),
+ (153, 159),
+ (162, 163),
+ (168, 169),
+ (160, 166),
+ (165, 171),
+ (174, 175),
+ (180, 181),
+ (172, 178),
+ (177, 183),
+ (149, 161),
+ (152, 164),
+ (155, 167),
+ (158, 170),
+ (161, 173),
+ (164, 176),
+ (167, 179),
+ (170, 182),
+ (173, 185),
+ (176, 188),
+ (179, 191),
+ (182, 194),
+ (148, 161),
+ (149, 160),
+ (149, 162),
+ (150, 161),
+ (151, 164),
+ (152, 163),
+ (152, 165),
+ (153, 164),
+ (154, 167),
+ (155, 166),
+ (155, 168),
+ (156, 167),
+ (157, 170),
+ (158, 169),
+ (158, 171),
+ (159, 170),
+ (160, 173),
+ (161, 172),
+ (161, 174),
+ (162, 173),
+ (163, 176),
+ (164, 175),
+ (164, 177),
+ (165, 176),
+ (166, 179),
+ (167, 178),
+ (167, 180),
+ (168, 179),
+ (169, 182),
+ (170, 181),
+ (170, 183),
+ (171, 182),
+ (172, 185),
+ (173, 184),
+ (173, 186),
+ (174, 185),
+ (175, 188),
+ (176, 187),
+ (176, 189),
+ (177, 188),
+ (178, 191),
+ (179, 190),
+ (179, 192),
+ (180, 191),
+ (181, 194),
+ (182, 193),
+ (182, 195),
+ (183, 194),
+ (150, 162),
+ (151, 163),
+ (156, 168),
+ (157, 169),
+ (148, 160),
+ (154, 166),
+ (153, 165),
+ (159, 171),
+ (162, 174),
+ (163, 175),
+ (168, 180),
+ (169, 181),
+ (160, 172),
+ (166, 178),
+ (165, 177),
+ (171, 183),
+ (174, 186),
+ (175, 187),
+ (180, 192),
+ (181, 193),
+ (172, 184),
+ (178, 190),
+ (177, 189),
+ (183, 195),
+ (150, 163),
+ (151, 162),
+ (156, 169),
+ (157, 168),
+ (148, 166),
+ (154, 160),
+ (153, 171),
+ (159, 165),
+ (162, 175),
+ (163, 174),
+ (168, 181),
+ (169, 180),
+ (160, 178),
+ (166, 172),
+ (165, 183),
+ (171, 177),
+ (174, 187),
+ (175, 186),
+ (180, 193),
+ (180, 192),
+ (172, 190),
+ (178, 184),
+ (177, 195),
+ (183, 189),
+ (184, 185),
+ (185, 186),
+ (187, 188),
+ (188, 189),
+ (190, 191),
+ (191, 192),
+ (193, 194),
+ (194, 195),
+ (196, 197),
+ (197, 198),
+ (199, 200),
+ (200, 201),
+ (202, 203),
+ (203, 204),
+ (205, 206),
+ (206, 207),
+ (208, 209),
+ (209, 210),
+ (211, 212),
+ (212, 213),
+ (214, 215),
+ (215, 216),
+ (217, 218),
+ (218, 219),
+ (186, 187),
+ (192, 193),
+ (184, 190),
+ (189, 195),
+ (198, 199),
+ (204, 205),
+ (196, 202),
+ (201, 207),
+ (210, 211),
+ (216, 217),
+ (208, 214),
+ (213, 219),
+ (185, 197),
+ (188, 200),
+ (191, 203),
+ (194, 206),
+ (197, 209),
+ (200, 212),
+ (203, 215),
+ (206, 218),
+ (209, 221),
+ (212, 224),
+ (215, 227),
+ (218, 230),
+ (184, 197),
+ (185, 196),
+ (185, 198),
+ (186, 197),
+ (187, 200),
+ (188, 199),
+ (188, 201),
+ (189, 200),
+ (190, 203),
+ (191, 202),
+ (191, 204),
+ (192, 203),
+ (193, 206),
+ (194, 205),
+ (194, 207),
+ (195, 206),
+ (196, 209),
+ (197, 208),
+ (197, 210),
+ (198, 209),
+ (199, 212),
+ (200, 211),
+ (200, 213),
+ (201, 212),
+ (202, 215),
+ (203, 214),
+ (203, 216),
+ (204, 215),
+ (205, 218),
+ (206, 217),
+ (206, 219),
+ (207, 218),
+ (208, 221),
+ (209, 220),
+ (209, 222),
+ (210, 221),
+ (211, 224),
+ (212, 223),
+ (212, 225),
+ (213, 224),
+ (214, 227),
+ (215, 226),
+ (215, 228),
+ (216, 227),
+ (217, 230),
+ (218, 229),
+ (218, 231),
+ (219, 230),
+ (186, 198),
+ (187, 199),
+ (192, 204),
+ (193, 205),
+ (184, 196),
+ (190, 202),
+ (189, 201),
+ (195, 207),
+ (198, 210),
+ (199, 211),
+ (204, 216),
+ (205, 217),
+ (196, 208),
+ (202, 214),
+ (201, 213),
+ (207, 219),
+ (210, 222),
+ (211, 223),
+ (216, 228),
+ (217, 229),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (186, 199),
+ (187, 198),
+ (192, 205),
+ (193, 204),
+ (184, 202),
+ (190, 196),
+ (189, 207),
+ (195, 201),
+ (198, 211),
+ (199, 210),
+ (204, 217),
+ (205, 216),
+ (196, 214),
+ (202, 208),
+ (201, 219),
+ (207, 213),
+ (210, 223),
+ (211, 222),
+ (216, 229),
+ (217, 228),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (220, 221),
+ (221, 222),
+ (223, 224),
+ (224, 225),
+ (226, 227),
+ (227, 228),
+ (229, 230),
+ (230, 231),
+ (222, 223),
+ (228, 229),
+ (220, 226),
+ (225, 231),
+ (221, 233),
+ (224, 236),
+ (227, 239),
+ (230, 242),
+ (222, 233),
+ (220, 233),
+ (223, 236),
+ (225, 236),
+ (226, 239),
+ (228, 239),
+ (229, 242),
+ (231, 242),
+ (221, 234),
+ (221, 232),
+ (224, 235),
+ (224, 237),
+ (227, 238),
+ (227, 240),
+ (230, 241),
+ (230, 243),
+ (222, 234),
+ (223, 235),
+ (228, 240),
+ (229, 241),
+ (220, 232),
+ (226, 238),
+ (225, 237),
+ (231, 243),
+ (222, 235),
+ (223, 234),
+ (228, 241),
+ (229, 240),
+ (220, 238),
+ (226, 232),
+ (225, 243),
+ (231, 237)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+
+
+def Truss10D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ X_scaled = X * (35-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss25D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ X_scaled = X * (10-0.31) + 0.31
+
+ return X_scaled
+
+
+def Truss72D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ X_scaled = X * (10-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss120D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = X * (20-0.775) + 0.775
+
+ return X_scaled
+
+def Truss360D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = torch.zeros(X.shape)
+ X_scaled[:,:120] = X[:,:120] * (20-0.775) + 0.775
+ X_scaled[:,120:240] = X[:,120:240] * (5e4-1e3) + 1e3
+ X_scaled[:,240:360] = X[:,240:360] * (0.3-0.05) + 0.05
+
+ return X_scaled
+
+
+
+
+def Truss10D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ gx[ii,10] = max(abs(displace[1][0]), abs(displace[1][1])) - 2
+ gx[ii,11] = max(abs(displace[2][0]), abs(displace[2][1])) - 2
+ gx[ii,12] = max(abs(displace[4][0]), abs(displace[4][1])) - 2
+ gx[ii,13] = max(abs(displace[5][0]), abs(displace[5][1])) - 2
+
+ return gx, fx
+
+
+
+def Truss25D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 25 bar stress constraints, 6 displacement constraints
+ gx = torch.zeros(n,31)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 40ksi (34809)
+ for ss in range(25):
+ gx[ii,ss] = abs(stress[ss]) - 34809
+
+ # Max displacement in x and y direction less than .4 inches
+ for dd in range(6):
+ # print(displace[dd])
+ gx[ii,25+dd] = max(abs(displace[dd][0]), abs(displace[dd][1])) - 0.039
+
+
+ return gx, fx
+
+
+
+
+
+
+def Truss72D_4forces(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 72 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,76)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 25000
+ for ss in range(72):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ # Max displacement in x and y direction less than .25 inches
+ # print(displace[16], displace[17], displace[18], displace[19])
+ gx[ii,72] = max(abs(displace[16][0]), abs(displace[16][1])) - 0.25
+ gx[ii,73] = max(abs(displace[17][0]), abs(displace[17][1])) - 0.25
+ gx[ii,74] = max(abs(displace[18][0]), abs(displace[18][1])) - 0.25
+ gx[ii,75] = max(abs(displace[19][0]), abs(displace[19][1])) - 0.25
+
+
+ return gx, fx
+
+
+
+def Truss120D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss360D(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ A = X[:,:120]
+ E = X[:,120:240]
+ Rho = X[:,240:360]
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+
+ # if (E != None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ # elif (E != None) & (Rho==None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ # elif (E == None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+ # gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/Untitled-checkpoint.ipynb b/test_functions/.ipynb_checkpoints/Untitled-checkpoint.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..363fcab7ed6e9634e198cf5555ceb88932c9a245
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/Untitled-checkpoint.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/test_functions/.ipynb_checkpoints/WeldedBeam-checkpoint.py b/test_functions/.ipynb_checkpoints/WeldedBeam-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1fd4d446c972834fc592de6b1484c772ea820ac
--- /dev/null
+++ b/test_functions/.ipynb_checkpoints/WeldedBeam-checkpoint.py
@@ -0,0 +1,94 @@
+import torch
+import numpy as np
+
+#
+#
+# WeldedBeam: 4D objective, 5 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+def WeldedBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+
+ C1 = 1.10471
+ C2 = 0.04811
+ C3 = 14.0
+ fx = torch.zeros(individuals.shape[0], 1)
+ gx1 = torch.zeros(individuals.shape[0], 1)
+ gx2 = torch.zeros(individuals.shape[0], 1)
+ gx3 = torch.zeros(individuals.shape[0], 1)
+ gx4 = torch.zeros(individuals.shape[0], 1)
+ gx5 = torch.zeros(individuals.shape[0], 1)
+
+ for i in range(individuals.shape[0]):
+
+ x = individuals[i,:]
+
+ h = x[0]
+ l = x[1]
+ t = x[2]
+ b = x[3]
+
+ test_function = - ( C1*h*h*l + C2*t*b*(C3+l) )
+ fx[i] = test_function
+
+ ## Calculate constraints terms
+ tao_dx = 6000 / (np.sqrt(2)*h*l)
+
+ tao_dxx = 6000*(14+0.5*l)*np.sqrt( 0.25*(l**2 + (h+t)**2 ) ) / (2* (0.707*h*l * ( l**2 /12 + 0.25*(h+t)**2 ) ) )
+
+ tao = np.sqrt( tao_dx**2 + tao_dxx**2 + l*tao_dx*tao_dxx / np.sqrt(0.25*(l**2 + (h+t)**2)) )
+
+ sigma = 504000/ (t**2 * b)
+
+ P_c = 64746*(1-0.0282346*t)* t * b**3
+
+ delta = 2.1952/ (t**3 *b)
+
+
+ ## Calculate 5 constraints
+ g1 = (-1) * (13600- tao)
+ g2 = (-1) * (30000 - sigma)
+ g3 = (-1) * (b - h)
+ g4 = (-1) * (P_c - 6000)
+ g5 = (-1) * (0.25 - delta)
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5), 1)
+ return gx, fx
+
+
+def WeldedBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ h = (X[:,0] * (10-0.125) + 0.125 ).reshape(X.shape[0],1)
+ l = (X[:,1] * (15-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ t = (X[:,2] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ b = (X[:,3] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((h, l, t, b), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions/.ipynb_checkpoints/__init__-checkpoint.py b/test_functions/.ipynb_checkpoints/__init__-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions/.ipynb_checkpoints/input-checkpoint.txt b/test_functions/.ipynb_checkpoints/input-checkpoint.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions/.ipynb_checkpoints/output-checkpoint.txt b/test_functions/.ipynb_checkpoints/output-checkpoint.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions/.ipynb_checkpoints/untitled-checkpoint.py b/test_functions/.ipynb_checkpoints/untitled-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions/Ackley10D.py b/test_functions/Ackley10D.py
new file mode 100644
index 0000000000000000000000000000000000000000..bcbdd92651d536b2ce473e5d94d9f7847109c582
--- /dev/null
+++ b/test_functions/Ackley10D.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley10D: 10D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 10
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley10D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Ackley2D.py b/test_functions/Ackley2D.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed442f5037a6bebce0548f07faeb4bd5bbb5c7f1
--- /dev/null
+++ b/test_functions/Ackley2D.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley2D: 2D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley2D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley2D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Ackley2DEmbedd.py b/test_functions/Ackley2DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..09e983a179ba11e87fbaa95599132fa627e2f6c0
--- /dev/null
+++ b/test_functions/Ackley2DEmbedd.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Ackley2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Ackley2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15-5
+ return X_scaled
+
+
+
+
diff --git a/test_functions/Ackley500D.py b/test_functions/Ackley500D.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee928e3b651d44c0c2b523d1cfbc6ab5d296c93a
--- /dev/null
+++ b/test_functions/Ackley500D.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def Ackley500D(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) - 1000 # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1) - 115 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley500D_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Ackley6D.py b/test_functions/Ackley6D.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c48a191cd35d9cf785c777aea245f622df5b54c
--- /dev/null
+++ b/test_functions/Ackley6D.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley6D: 6D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley6D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 6
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley6D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/AckleyND.py b/test_functions/AckleyND.py
new file mode 100644
index 0000000000000000000000000000000000000000..638f92e9fb5cb852545b6bae1b7d729e428f3e99
--- /dev/null
+++ b/test_functions/AckleyND.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def AckleyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def AckleyND_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Branin2DEmbedd.py b/test_functions/Branin2DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba11caa4938034d78f3221b465c85a7efa55eb24
--- /dev/null
+++ b/test_functions/Branin2DEmbedd.py
@@ -0,0 +1,38 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Branin
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Branin2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Branin(negate=True)
+ fun.bounds[0, 0].fill_(-5.0)
+ fun.bounds[1, 0].fill_(10.0)
+ fun.bounds[0, 1].fill_(0.0)
+ fun.bounds[1, 1].fill_(15.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Branin2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15
+ return X_scaled
+
+
+
+
diff --git a/test_functions/Bukin.py b/test_functions/Bukin.py
new file mode 100644
index 0000000000000000000000000000000000000000..562576be84619a079760227f4d009334e4151ae9
--- /dev/null
+++ b/test_functions/Bukin.py
@@ -0,0 +1,46 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+# class Bukin(SyntheticTestFunction):
+
+# dim = 2
+# _bounds = [(-15.0, -5.0), (-3.0, 3.0)]
+# _optimal_value = 0.0
+# _optimizers = [(-10.0, 1.0)]
+# _check_grad_at_opt: bool = False
+
+
+# [docs]
+# def evaluate_true(self, X: Tensor) -> Tensor:
+# part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+# part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+# return part1 + part2
+
+
+def Bukin(X):
+
+ part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+ part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+ fx = part1 + part2
+
+ return fx
+
+def Bukin_Scaling(X):
+ X_scaled = torch.zeros(X.shape)
+
+ X_scaled[:,0] = -(X[..., 0]*10+5)
+ X_scaled[:,1] = X[..., 0]*6-3
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions/CantileverBeam.py b/test_functions/CantileverBeam.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0599ce7836e96aa76ce1fc59780e34f61d8e170
--- /dev/null
+++ b/test_functions/CantileverBeam.py
@@ -0,0 +1,193 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CantileverBeam: 10D objective, 11 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+
+
+
+
+
+def CantileverBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+
+ P = 50000
+ E = 2*107
+ L = 100
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1*x6*L + x2*x7*L + x3*x8*L + x4*x9*L + x5*x10*L )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 600 * P / (x5*x10*x10) - 14000
+ g2 = 6 * P * (L*2) / (x4*x9*x9) - 14000
+ g3 = 6 * P * (L*3) / (x3*x8*x8) - 14000
+ g4 = 6 * P * (L*4) / (x2*x7*x7) - 14000
+ g5 = 6 * P * (L*5) / (x1*x6*x6) - 14000
+ g6 = P* L**3 * (1/L + 7/L + 19/L + 37/L + 61/L) / (3*E) -2.7
+ g7 = x10/x5 - 20
+ g8 = x9/x4 - 20
+ g9 = x8/x3 - 20
+ g10 = x7/x2 - 20
+ g11 = x6/x1 - 20
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+ gx10.append( g10 )
+ gx11.append( g11 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx10 = torch.tensor(gx10)
+ gx10 = gx4.reshape((n, 1))
+
+ gx11 = torch.tensor(gx11)
+ gx11 = gx4.reshape((n, 1))
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10, gx11), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def CantileverBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ x1 = (X[:,0] * (5-1) + 1).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (5-1) + 1).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (5-1) + 1).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (5-1) + 1).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (5-1) + 1).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (65-30) + 30).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (65-30) + 30).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (65-30) + 30).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (65-30) + 30).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (65-30) + 30).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Car.py b/test_functions/Car.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7193b96109cd5fc9c3f4ff3a5661bb344338e60
--- /dev/null
+++ b/test_functions/Car.py
@@ -0,0 +1,253 @@
+import torch
+import numpy as np
+
+
+#
+#
+# Car: 11D objective, 10 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def Car(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def Car_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ x1 = (X[:,0] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (1.35-0.45) + 0.45).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (-20)).reshape(X.shape[0],1)
+ x11 = (X[:,10] * (-20)).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11), dim=1)
+ return X_scaled
+
+
+
+
+
+
+def Car_softpen(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+ cost = gx
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ fx = fx + cost
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/CompressionSpring.py b/test_functions/CompressionSpring.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5443f7da043f74660ae96e1c1867f69101013d4
--- /dev/null
+++ b/test_functions/CompressionSpring.py
@@ -0,0 +1,100 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CompressionSpring: 8D objective, 6 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def CompressionSpring(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ d = x[0]
+ D = x[1]
+ N = x[2]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( (N+2)*D*d**2 )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 1 - ( D*D*D * N / (71785* d*d*d*d) )
+ g2 = (4*D*D - D*d) / (12566 * (D*d*d*d - d*d*d*d)) + 1/(5108*d*d) - 1
+ g3 = 1 - 140.45*d / (D*D * N)
+ g4 = (D+d)/1.5 - 1
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+
+ return gx, fx
+
+
+
+def CompressionSpring_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ d = (X[:,0] * ( 1 - 0.05 ) + 0.05 ).reshape(X.shape[0],1)
+ D = (X[:,1] * ( 1.3 - 0.25 ) + 0.25 ).reshape(X.shape[0],1)
+ N = (X[:,2] * ( 15 - 2 ) + 2 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((d, D, N), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions/DixonPriceND.py b/test_functions/DixonPriceND.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406802fb9029db8327a08acf6601783ba9d5a51
--- /dev/null
+++ b/test_functions/DixonPriceND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DixonPriceND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = DixonPrice(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def DixonPriceND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/DummyFixConsDim.py b/test_functions/DummyFixConsDim.py
new file mode 100644
index 0000000000000000000000000000000000000000..de6e1b6b1ad0683d3064bc42d6a58c62c905d4ab
--- /dev/null
+++ b/test_functions/DummyFixConsDim.py
@@ -0,0 +1,28 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DummyFixConsDim(individuals):
+ n = individuals.size(0)
+ GX = torch.rand(n, 20)
+ Y = torch.rand(n, 1)
+
+ return GX, Y
+
+
+
+def DummyFixConsDim_Scaling(X):
+
+ X_scaled = X
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/Finder24.py b/test_functions/Finder24.py
new file mode 100644
index 0000000000000000000000000000000000000000..9f7a4752b9e54183f145947fa4f06c51283ca754
--- /dev/null
+++ b/test_functions/Finder24.py
@@ -0,0 +1,172 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ # START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z, n_candidate=None):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+
+ if n_candidate==None:
+ n_candidate = 2000
+
+ Z_samples = sobol.draw(n_candidate)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions/Finder24_no_timer.py b/test_functions/Finder24_no_timer.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd3e0475a77fe66303e3dd345bc0aec41ece7fe5
--- /dev/null
+++ b/test_functions/Finder24_no_timer.py
@@ -0,0 +1,173 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_Adam_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+ Z_samples = sobol.draw(2000)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions/GKXWC1.py b/test_functions/GKXWC1.py
new file mode 100644
index 0000000000000000000000000000000000000000..2dfa59da9637b4c64377a6e6471c742f9f9c53f3
--- /dev/null
+++ b/test_functions/GKXWC1.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC1: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+
+def GKXWC1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+ for x in individuals:
+ g = np.cos(x[0])*np.cos(x[1]) - np.sin(x[0])*np.sin(x[1]) -0.5
+ fx.append( - np.cos(2*x[0])*np.cos(x[1]) - np.sin(x[0]) )
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+ return gx, fx
+
+
+def GKXWC1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/GKXWC2.py b/test_functions/GKXWC2.py
new file mode 100644
index 0000000000000000000000000000000000000000..5db203c32b693009590b8e9b9b79177d3cc3bba9
--- /dev/null
+++ b/test_functions/GKXWC2.py
@@ -0,0 +1,80 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC2: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+def GKXWC2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ g = np.sin(x[0])*np.sin(x[1]) + 0.95
+ fx.append( - np.sin(x[0]) - x[1] ) # maximize -(x1^2 +x 2^2)
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+def GKXWC2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Griewank2DEmbedd.py b/test_functions/Griewank2DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e6128b1f5987182c740bab54875152b58635979
--- /dev/null
+++ b/test_functions/Griewank2DEmbedd.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Griewank2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Griewank2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled = X_scaled * 1200 - 600
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions/GriewankND.py b/test_functions/GriewankND.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406c4f067885c9d6c726f526688c222b89c8a3a
--- /dev/null
+++ b/test_functions/GriewankND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def GriewankND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def GriewankND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*1200-600
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/Hartmann6DEmbedd.py b/test_functions/Hartmann6DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..94115986eb19db5747d36fcd38d7ffc5308af125
--- /dev/null
+++ b/test_functions/Hartmann6DEmbedd.py
@@ -0,0 +1,35 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Hartmann
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Hartmann6DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[0,1,2,3,4,5]]
+ n = X.size(0)
+ dimm = 6
+ fun = Hartmann(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(1.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Hartmann6DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ return X_scaled
+
+
+
+
diff --git a/test_functions/HeatExchanger.py b/test_functions/HeatExchanger.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f74bb6ed047a5537a898628f467e732d71e9669
--- /dev/null
+++ b/test_functions/HeatExchanger.py
@@ -0,0 +1,191 @@
+import torch
+import numpy as np
+
+#
+#
+# HeatExchanger: 8D objective, 6 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+def HeatExchanger(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1+x2+x3 )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 0.0025 * (x4+x6) - 1
+ g2 = 0.0025 * (x5 + x7 - x4) - 1
+ g3 = 0.01 *(x8-x5) - 1
+ g4 = 833.33252*x4 + 100*x1 - x1*x6 - 83333.333
+ g5 = 1250*x5 + x2*x4 - x2*x7 - 125*x4
+ g6 = x3*x5 - 2500*x5 - x3*x8 + 125*10000
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6), 1)
+
+
+ return gx, fx
+
+
+
+
+
+def HeatExchanger_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ x1 = (X[:,0] * (10000-100) + 100).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1000-10) + 10).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1000-10) + 10).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1000-10) + 10).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1000-10) + 10).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (1000-10) + 10).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/JLH1.py b/test_functions/JLH1.py
new file mode 100644
index 0000000000000000000000000000000000000000..27b7f05394a22a18d0349cbe2632c31c471a83b7
--- /dev/null
+++ b/test_functions/JLH1.py
@@ -0,0 +1,57 @@
+import torch
+import numpy as np
+
+#
+# JLH1: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+def JLH1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+ test_function = (- (x[0]-0.5)**2 - (x[1]-0.5)**2 )
+ fx.append(test_function)
+ gx.append( x[0] + x[1] - 0.75 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+
+
+def JLH1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/JLH2.py b/test_functions/JLH2.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ce7c5e5e65c8fbfda31d4485babc0a84bf6f1aa
--- /dev/null
+++ b/test_functions/JLH2.py
@@ -0,0 +1,68 @@
+import torch
+import numpy as np
+
+
+#
+# JLH2: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+
+def JLH2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( np.cos(2*x[0])*np.cos(x[1]) + np.sin(x[0]) )
+
+ fx.append(test_function)
+ gx.append( ((x[0]+5)**2)/4 + (x[1]**2)/100 -2.5 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+def JLH2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ # X = individuals
+ X1 = X[:,0].reshape(X.size(0),1)
+ X1 = X1*5-5
+ X2 = X[:,1].reshape(X.size(0),1)
+ X2 = X2*10-5
+ X_scaled = torch.tensor(np.concatenate((X1,X2), axis=1))
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/KeaneBump.py b/test_functions/KeaneBump.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ff354c8c76334acb87fbbaac3baf79d1ac2fa23
--- /dev/null
+++ b/test_functions/KeaneBump.py
@@ -0,0 +1,88 @@
+import torch
+import numpy as np
+
+#
+#
+# KeaneBump: N-D objective (can take data of different dimention; we use 18),
+# 2 constraints
+#
+# Reference:
+# Keane A (1994) Experiences with optimizers in
+# structural design. In: Proceedings of the con-
+# ference on adaptive computing in engineering
+# design and control, pp 14–27
+#
+#
+
+
+
+def KeaneBump(X):
+
+
+
+ fx = torch.zeros(X.shape[0], 1)
+ gx1 = torch.zeros(X.shape[0], 1)
+ gx2 = torch.zeros(X.shape[0], 1)
+
+
+
+ for i in range(X.shape[0]):
+ x = X[i,:]
+
+ cos4 = 0
+ cos2 = 1
+ sq_denom = 0
+
+ pi_sum = 1
+ sigma_sum = 0
+
+ for j in range(X.shape[1]):
+ cos4 += torch.cos(x[j]) ** 4
+ cos2 *= torch.cos(x[j]) ** 2
+ sq_denom += (j+1) * (x[j])**2
+
+ pi_sum *= x[j]
+ sigma_sum += x[j]
+
+
+ # Objective
+ test_function = torch.abs( (cos4 - 2*cos2) / torch.sqrt(sq_denom) )
+ fx[i] = test_function
+
+ # Constraints
+ gx1[i] = 0.75 - pi_sum
+ gx2[i] = sigma_sum - 7.5* (X.shape[1])
+
+ gx = torch.cat((gx1, gx2), 1)
+ return gx, fx
+
+
+
+
+
+def KeaneBump_Scaling(X):
+
+ X_scaled = X*10
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/LevyND.py b/test_functions/LevyND.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b0c6e40d653c0b964655eb80c5d87787506ec3a
--- /dev/null
+++ b/test_functions/LevyND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Levy
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def LevyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Levy(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def LevyND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/MOPTA08_Car.py b/test_functions/MOPTA08_Car.py
new file mode 100644
index 0000000000000000000000000000000000000000..09894738e0c6f340e6feb5cc8119726fd81ac95c
--- /dev/null
+++ b/test_functions/MOPTA08_Car.py
@@ -0,0 +1,133 @@
+import os
+import subprocess
+import sys
+import tempfile
+from pathlib import Path
+from platform import machine
+
+import numpy as np
+import torch
+import stat
+
+
+def MOPTA08_Car_single(x):
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ sysarch = 64 if sys.maxsize > 2 ** 32 else 32
+ # machine = machine().lower()
+
+ # if machine == "armv7l":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_armhf.bin"
+ # elif machine == "x86_64":
+ # assert sysarch == 64, "Not supported"
+ # mopta_exectutable = "mopta08_elf64.bin"
+ # elif machine == "i386":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_elf32.bin"
+ # else:
+ # raise RuntimeError("Machine with this architecture is not supported")
+
+ machine = "x86_64"
+ mopta_exectutable = "mopta08_elf64.bin"
+
+ mopta_full_path = os.path.join(
+ "mopta08", mopta_exectutable
+ )
+ # print(mopta_full_path)
+
+ directory_file_descriptor = tempfile.TemporaryDirectory()
+ # directory_name = directory_file_descriptor.name
+ directory_name = Path(__file__).parent
+
+ ##########################################################################################
+ # Input here
+ # if x == None:
+ # x = np.random.rand(124)
+ # print(x.shape)
+ ##########################################################################################
+ with open(os.path.join(directory_name, "input.txt"), "w+") as tmp_file:
+ for _x in x:
+ tmp_file.write(f"{_x}\n")
+ popen = subprocess.Popen(
+ mopta_full_path,
+ # '#!/home/rosen/Dropbox (MIT)/Rosen_DeC0De/MOPTA_Test/mopta08/mopta08_elf64.bin',
+ stdout=subprocess.PIPE,
+ cwd=directory_name,
+ shell=True,
+ )
+ popen.wait()
+
+ with open(os.path.join(directory_name, "output.txt"), "r") as tmp_file:
+ output = (
+ tmp_file
+ .read()
+ .split("\n")
+ )
+ # print(output)
+ # print(x)
+ # print(output)
+ output = [x.strip() for x in output]
+ output = np.array([float(x) for x in output if len(x) > 0])
+ value = output[0]
+ constraints = output[1:]
+ # print(value, constraints)
+
+ return constraints, value
+
+
+
+def MOPTA08_Car(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = -fx
+
+ return GX, FX
+
+
+
+
+def MOPTA08_Car_softpen(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = fx
+
+ cost = GX
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ FX = FX + cost
+
+ return GX, -FX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Mazda.py b/test_functions/Mazda.py
new file mode 100644
index 0000000000000000000000000000000000000000..52f586cbf98f52df78c8d6e9ba0045535a113602
--- /dev/null
+++ b/test_functions/Mazda.py
@@ -0,0 +1,242 @@
+import os
+import subprocess
+import stat
+import pandas as pd
+import torch
+import numpy as np
+
+
+
+def Mazda(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+def Mazda_softpen(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+
+ cost = cons_data_tensor
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ objs_data_tensor = objs_data_tensor + cost
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/MichalewiczND.py b/test_functions/MichalewiczND.py
new file mode 100644
index 0000000000000000000000000000000000000000..55cd932393e207d7deb9ddebde8b93a408c48400
--- /dev/null
+++ b/test_functions/MichalewiczND.py
@@ -0,0 +1,59 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def MichalewiczND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Michalewicz(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(math.pi)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def MichalewiczND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*math.pi
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/PressureVessel.py b/test_functions/PressureVessel.py
new file mode 100644
index 0000000000000000000000000000000000000000..eeefcd177c3ec800e56c2a3b1b9ca4c573e79990
--- /dev/null
+++ b/test_functions/PressureVessel.py
@@ -0,0 +1,169 @@
+import torch
+import numpy as np
+
+#
+#
+# PressureVessel: 4D objective, 4 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def PressureVessel(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ C1 = 0.6224
+ C2 = 1.7781
+ C3 = 3.1661
+ C4 = 19.84
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ Ts = x[0]
+ Th = x[1]
+ R = x[2]
+ L = x[3]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( C1*Ts*R*L + C2*Th*R*R + C3*Ts*Ts*L + C4*Ts*Ts*R )
+ fx.append(test_function)
+
+
+ g1 = -Ts + 0.0193*R
+ g2 = -Th + 0.00954*R
+ g3 = (-1)*np.pi*R*R*L + (-1)*4/3*np.pi*R*R*R + 750*1728
+ g4 = L-240
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def PressureVessel_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ Ts = (X[:,0] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ Th = (X[:,1] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ R = (X[:,2] * (200-10) + 10).reshape(X.shape[0],1)
+ L = (X[:,3] * (200-10) ).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((Ts, Th, R, L), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/ReinforcedConcreteBeam.py b/test_functions/ReinforcedConcreteBeam.py
new file mode 100644
index 0000000000000000000000000000000000000000..1729e66ee7ac88f8fe7fdc60b984b8ba6d784a72
--- /dev/null
+++ b/test_functions/ReinforcedConcreteBeam.py
@@ -0,0 +1,90 @@
+import torch
+import numpy as np
+
+#
+#
+# ReinforcedConcreteBeam: 3D objective, 9 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def ReinforcedConcreteBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ As = x[0]
+ h = x[1]
+ b = x[2]
+
+
+ test_function = - ( 29.4*As + 0.6*b*h )
+ fx.append(test_function)
+
+ g1 = h/b - 4
+ g2 = 180 + 7.35*As*As/b - As*h
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def ReinforcedConcreteBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ As = (X[:,0] * (15-0.2) + 0.2).reshape(X.shape[0],1)
+ b = (X[:,1] * (40-28) +28).reshape(X.shape[0],1)
+ h = (X[:,2] * 5 + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((As, b, h), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Rosenbrock3DEmbedd.py b/test_functions/Rosenbrock3DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..1625595859baca53628812cede1b6f68f8e7ea14
--- /dev/null
+++ b/test_functions/Rosenbrock3DEmbedd.py
@@ -0,0 +1,40 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Rosenbrock3DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2,3]]
+ n = X.size(0)
+ dimm = 3
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-2.0)
+ fun.bounds[1, :].fill_(2.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Rosenbrock3DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+
+ X_scaled[:,1] = X_scaled[:,1]*4 - 2
+ X_scaled[:,2] = X_scaled[:,2]*4 - 2
+ X_scaled[:,3] = X_scaled[:,3]*4 - 2
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions/RosenbrockND.py b/test_functions/RosenbrockND.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb46001f9d022a9a9f4a73633f2a89dc882f44a3
--- /dev/null
+++ b/test_functions/RosenbrockND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def RosenbrockND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/RosenbrockND2.py b/test_functions/RosenbrockND2.py
new file mode 100644
index 0000000000000000000000000000000000000000..635099799fbf64f4b501d187b19eecdd63c2e417
--- /dev/null
+++ b/test_functions/RosenbrockND2.py
@@ -0,0 +1,56 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock, Levy, DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND2(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+
+
+ Rosenbrockfun = Rosenbrock(dim=dimm, negate=True)
+ Rosenbrockfun.bounds[0, :].fill_(-3.0)
+ Rosenbrockfun.bounds[1, :].fill_(5.0)
+
+ fx = Rosenbrockfun(individuals)
+ fx = fx.reshape(individuals.shape[0],1)
+
+ Levyfun = Levy(dim=dimm, negate=False)
+ Levyfun.bounds[0, :].fill_(-3.0)
+ Levyfun.bounds[1, :].fill_(5.0)
+
+
+ DixonPricefun = DixonPrice(dim=dimm, negate=False)
+ DixonPricefun.bounds[0, :].fill_(-3.0)
+ DixonPricefun.bounds[1, :].fill_(5.0)
+
+
+ G1 = Levyfun(individuals) -1e3
+ G2 = DixonPricefun(individuals) -4e7
+
+ gx = torch.cat((G1.reshape(individuals.shape[0],1), G2.reshape(individuals.shape[0],1)), 1)
+
+
+ return gx, fx
+
+
+def RosenbrockND2_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*8-3
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions/SpeedReducer.py b/test_functions/SpeedReducer.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b8ec3cbabd1652d9d75361e332658fb06e7ff6b
--- /dev/null
+++ b/test_functions/SpeedReducer.py
@@ -0,0 +1,188 @@
+import torch
+import numpy as np
+
+#
+#
+# SpeedReducer: 7D objective, 9 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+def SpeedReducer(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ b = x[0]
+ m = x[1]
+ z = x[2]
+ L1 = x[3]
+ L2 = x[4]
+ d1 = x[5]
+ d2 = x[6]
+
+ C1 = 0.7854*b*m*m
+ C2 = 3.3333*z*z + 14.9334*z - 43.0934
+ C3 = 1.508*b*(d1*d1 + d2*d2)
+ C4 = 7.4777*(d1*d1*d1 + d2*d2*d2)
+ C5 = 0.7854*(L1*d1*d1 + L2*d2*d2)
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 0.7854*b*m*m * (3.3333*z*z + 14.9334*z - 43.0934) - 1.508*b*(d1*d1 + d2*d2) + 7.4777*(d1*d1*d1 + d2*d2*d2) + 0.7854*(L1*d1*d1 + L2*d2*d2) )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 27/(b*m*m*z) - 1
+ g2 = 397.5/(b*m*m*z*z) - 1
+
+ g3 = 1.93*L1**3 /(m*z *d1**4) - 1
+ g4 = 1.93*L2**3 /(m*z *d2**4) - 1
+
+ g5 = np.sqrt( (745*L1/(m*z))**2 + 1.69*1e6 ) / (110*d1**3) -1
+ g6 = np.sqrt( (745*L2/(m*z))**2 + 157.5*1e6 ) / (85*d2**3) -1
+ g7 = m*z/40 - 1
+ g8 = 5*m/(b) - 1
+ g9 = b/(12*m) -1
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9), 1)
+
+
+ return gx, fx
+
+
+
+def SpeedReducer_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ b = (X[:,0] * ( 3.6 - 2.6 ) + 2.6).reshape(X.shape[0],1)
+ m = (X[:,1] * ( 0.8 - 0.7 ) + 0.7).reshape(X.shape[0],1)
+ z = (X[:,2] * ( 28 - 17 ) + 17).reshape(X.shape[0],1)
+ L1 = (X[:,3] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ L2 = (X[:,4] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ d1 = (X[:,5] * ( 3.9 - 2.9 ) + 2.9).reshape(X.shape[0],1)
+ d2 = (X[:,6] * ( 5.5 - 5 ) + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((b, m, z, L1, L2, d1, d2), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/ThreeTruss.py b/test_functions/ThreeTruss.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e4b3f2ef3416ea17b6626d2ea87c2dd7a9c2362
--- /dev/null
+++ b/test_functions/ThreeTruss.py
@@ -0,0 +1,144 @@
+import torch
+import numpy as np
+
+
+#
+#
+# ThreeTruss: 2D objective, 3 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+def ThreeTruss(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ x1 = x[0]
+ x2 = x[1]
+
+ if x1 <=1e-5:
+ x1 = 1e-5
+ if x2 <=1e-5:
+ x2 = 1e-5
+
+ L = 100
+ P = 2
+ sigma = 2
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 2*np.sqrt(2)*x1 + x2 ) * L
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = ( np.sqrt(2)*x1 + x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g2 = ( x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g3 = ( 1 ) / (x1 + np.sqrt(2)*x2) * P - sigma
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def ThreeTruss_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Truss10D.py b/test_functions/Truss10D.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc0ea12f999aa1d58eb4516b4fc08112f711583b
--- /dev/null
+++ b/test_functions/Truss10D.py
@@ -0,0 +1,66 @@
+
+from TrussSolvers import *
+import torch
+import numpy as np
+
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(individuals[ii,:])
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/TrussSolvers.py b/test_functions/TrussSolvers.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec6d915060eeaacae4989257c47b9212c1f3e235
--- /dev/null
+++ b/test_functions/TrussSolvers.py
@@ -0,0 +1,2958 @@
+import matplotlib.pyplot as plt
+import torch
+import numpy as np
+
+from slientruss3d.truss import Truss
+from slientruss3d.type import SupportType, MemberType
+from slientruss3d.plot import TrussPlotter
+
+
+
+
+
+def TestPlot(truss):
+ # -------------------- Global variables --------------------
+ # Files settings:
+ TEST_FILE_NUMBER = 25
+ TEST_LOAD_CASE = 0
+ TEST_INPUT_FILE = f"./data/bar-{TEST_FILE_NUMBER}_output_{TEST_LOAD_CASE}.json"
+ TEST_PLOT_SAVE_PATH = f"./plot/bar-{TEST_FILE_NUMBER}_plot_{TEST_LOAD_CASE}.png"
+
+ # Truss dimension setting:
+ TRUSS_DIMENSION = 3
+
+ # Figure layout settings:
+ IS_SAVE_PLOT = False # Whether to save truss figure or not.
+ IS_EQUAL_AXIS = True # Whether to use actual aspect ratio in the truss figure or not.
+ IS_PLOT_STRESS = True # If True, the color of each displaced member gives expression to [stress]. Otherwise, [force magnitude].
+ MAX_SCALED_DISPLACEMENT = 15 # Scale the max value of all dimensions of displacements.
+ MAX_SCALED_FORCE = 50 # Scale the max value of all dimensions of force arrows.
+ POINT_SIZE_SCALE_FACTOR = 1 # Scale the default size of joint point in the truss figure.
+ ARROW_SIZE_SCALE_FACTOR = 1 # Scale the default size of force arrow in the truss figure.
+ # ----------------------------------------------------------
+
+ # Truss object:
+ # truss = Truss(dim=TRUSS_DIMENSION)
+
+ # You could directly read the output .json file.
+ # truss.LoadFromJSON(TEST_INPUT_FILE, isOutputFile=True)
+
+ # Show or save the structural analysis result figure:
+ TrussPlotter(truss,
+ isEqualAxis=IS_EQUAL_AXIS,
+ isPlotStress=IS_PLOT_STRESS,
+ maxScaledDisplace=MAX_SCALED_DISPLACEMENT,
+ maxScaledForce=MAX_SCALED_FORCE,
+ pointScale=POINT_SIZE_SCALE_FACTOR,
+ arrowScale=ARROW_SIZE_SCALE_FACTOR).Plot(IS_SAVE_PLOT, TEST_PLOT_SAVE_PATH)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss10bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(0, 0),
+ (360, 0),
+ (720, 0),
+ (0, 360),
+ (360, 360),
+ (720, 360)
+ ]
+
+
+ supports = [SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ ]
+ forces = [(1, (0, -1e5)), (2, (0, -1e5))]
+
+
+ members = [(0, 1),
+ (0, 4),
+ (1, 2),
+ (1, 3),
+ (1, 4),
+ (1, 5),
+ (2, 4),
+ (2, 5),
+ (3, 4),
+ (4, 5)
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # Default: 0.1, 1e7, 1
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss25bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(62.5, 100, 200),
+ (137.5, 100, 200),
+ (62.5, 137.5, 100),
+ (137.5, 137.5, 100),
+ (137.5, 62.5, 100),
+ (62.5, 62.5, 100),
+ (0, 200, 0),
+ (200, 200, 0),
+ (200, 0, 0),
+ (0, 0, 0)
+ ]
+
+
+ supports = [SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+ forces = [(0, (1000, 20000, -5000)),
+ (1, (0, -20000, -5000)),
+ (2, (500, 0, 0)),
+ (5, (500, 0, 0)),
+ ]
+
+
+ members = [(0, 1),
+ (0, 3),
+ (1, 2),
+ (0, 4),
+ (1, 5),
+ (0, 2),
+ (0, 5),
+ (1, 3),
+ (1, 4),
+ (2, 5),
+ (3, 4),
+ (2, 3),
+ (4, 5),
+ (2, 9),
+ (5, 6),
+ (3, 8),
+ (4, 7),
+ (2, 7),
+ (3, 6),
+ (5, 8),
+ (4, 9),
+ (2, 6),
+ (3, 7),
+ (4, 8),
+ (5, 9),
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+
+ # Default: 0.1, 1e7, .1
+
+ memberType = MemberType(A[index].item(), 3e7, .283)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), .283)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 3e7, Rho[index].item())
+
+
+
+ # memberType = MemberType(A[index].item(), 1e7, .1)
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+
+def Truss47bar(A, E, Rho, version):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(-60, 0),
+ (60, 0),
+ (-60, 120),
+ (60, 120),
+ (-60, 240),
+ (60, 240),
+ (-60, 360),
+ (60, 360),
+ (-30, 420),
+ (30, 420),
+ (-30, 480),
+ (30, 480),
+ (-30, 540),
+ (30, 540),
+ (-90, 570),
+ (90, 570),
+ (-150, 600),
+ (-90, 600),
+ (-30, 600),
+ (30, 600),
+ (90, 600),
+ (150, 600)]
+
+ supports = [SupportType.PIN, SupportType.PIN,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO]
+
+
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ if version == 1:
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ elif version == 2:
+ forces = [(16, (6000, -14000))]
+
+ elif version == 3:
+ forces = [(21, (6000, -14000))]
+
+
+
+
+ members = [(0, 2), (0, 3), (1, 2), (1, 3),
+ (2, 3), (2, 4), (2, 5), (3, 4), (3, 5),
+ (4, 5), (4, 6), (4, 7), (5, 6), (5, 7),
+ (6, 7), (6, 8), (6, 9), (7, 8), (7, 9), (8, 9),
+ (8, 10), (8, 11), (9, 10), (9, 11),
+ (10, 11), (10, 12), (10, 13), (11, 12), (11, 13),
+ (12, 13), (12, 14), (12, 18), (12, 19),
+ (13, 18), (13, 19), (13, 15), (14, 16),
+ (14, 17), (14, 18), (15, 19), (15, 20),
+ (15, 21), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21)]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+
+ # Default: 0.1, 300000000.0, 0.3
+
+ memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.3)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 300000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss120bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 275.59),
+ (273.26, 0.0, 230.31),
+ (236.65010183813573, 136.62999999999997, 230.31),
+ (136.62999999999997, 236.65010183813573, 230.31),
+ (0.0, 273.26, 230.31),
+ (-136.62999999999997, 236.65010183813573, 230.31),
+ (-236.65010183813573, 136.62999999999997, 230.31),
+ (-273.26, 0.0, 230.31),
+ (-236.65010183813573, -136.62999999999997, 230.31),
+ (-136.62999999999997, -236.65010183813573, 230.31),
+ (0.0, -273.26, 230.31),
+ (136.62999999999997, -236.65010183813573, 230.31),
+ (236.65010183813573, -136.62999999999997, 230.31),
+ (492.12, 0.0, 118.11),
+ (475.3514176333763, 127.37002847585251, 118.11),
+ (426.18842171039796, 246.05999999999997, 118.11),
+ (347.9813891575237, 347.9813891575237, 118.11),
+ (246.05999999999997, 426.18842171039796, 118.11),
+ (127.37002847585251, 475.3514176333763, 118.11),
+ (0.0, 492.12, 118.11),
+ (-127.37002847585251, 475.3514176333763, 118.11),
+ (-246.05999999999997, 426.18842171039796, 118.11),
+ (-347.9813891575237, 347.9813891575237, 118.11),
+ (-426.18842171039796, 246.05999999999997, 118.11),
+ (-475.3514176333763, 127.37002847585251, 118.11),
+ (-492.12, 0.0, 118.11),
+ (-475.3514176333763, -127.37002847585251, 118.11),
+ (-426.18842171039796, -246.05999999999997, 118.11),
+ (-347.9813891575237, -347.9813891575237, 118.11),
+ (-246.05999999999997, -426.18842171039796, 118.11),
+ (-127.37002847585251, -475.3514176333763, 118.11),
+ (0.0, -492.12, 118.11),
+ (127.37002847585251, -475.3514176333763, 118.11),
+ (246.05999999999997, -426.18842171039796, 118.11),
+ (347.9813891575237, -347.9813891575237, 118.11),
+ (426.18842171039796, -246.05999999999997, 118.11),
+ (475.3514176333763, -127.37002847585251, 118.11),
+ (625.59, 0.0, 0.0),
+ (541.7768323535071, 312.79499999999996, 0.0),
+ (312.79499999999996, 541.7768323535071, 0.0),
+ (0.0, 625.59, 0.0),
+ (-312.79499999999996, 541.7768323535071, 0.0),
+ (-541.7768323535071, 312.79499999999996, 0.0),
+ (-625.59, 0.0, 0.0),
+ (-541.7768323535071, -312.79499999999996, 0.0),
+ (-312.79499999999996, -541.7768323535071, 0.0),
+ (0.0, -625.59, 0.0),
+ (312.79499999999996, -541.7768323535071, 0.0),
+ (541.7768323535071, -312.79499999999996, 0.0)
+ ]
+
+ supports = [
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+
+ # print(len(joints))
+ # print(len(supports))
+
+
+
+ forces = [
+ (0, (0.0, 0.0, -13490.0)),
+ (1, (0.0, 0.0, -6744.0)),
+ (2, (0.0, 0.0, -6744.0)),
+ (3, (0.0, 0.0, -6744.0)),
+ (4, (0.0, 0.0, -6744.0)),
+ (5, (0.0, 0.0, -6744.0)),
+ (6, (0.0, 0.0, -6744.0)),
+ (7, (0.0, 0.0, -6744.0)),
+ (8, (0.0, 0.0, -6744.0)),
+ (9, (0.0, 0.0, -6744.0)),
+ (10, (0.0, 0.0, -6744.0)),
+ (11, (0.0, 0.0, -6744.0)),
+ (12, (0.0, 0.0, -6744.0)),
+ (13, (0.0, 0.0, -6744.0)),
+ (14, (0.0, 0.0, -2248.0)),
+ (15, (0.0, 0.0, -2248.0)),
+ (16, (0.0, 0.0, -2248.0)),
+ (17, (0.0, 0.0, -2248.0)),
+ (18, (0.0, 0.0, -2248.0)),
+ (19, (0.0, 0.0, -2248.0)),
+ (20, (0.0, 0.0, -2248.0)),
+ (21, (0.0, 0.0, -2248.0)),
+ (22, (0.0, 0.0, -2248.0)),
+ (23, (0.0, 0.0, -2248.0)),
+ (24, (0.0, 0.0, -2248.0)),
+ (25, (0.0, 0.0, -2248.0)),
+ (26, (0.0, 0.0, -2248.0)),
+ (27, (0.0, 0.0, -2248.0)),
+ (28, (0.0, 0.0, -2248.0)),
+ (29, (0.0, 0.0, -2248.0)),
+ (30, (0.0, 0.0, -2248.0)),
+ (31, (0.0, 0.0, -2248.0)),
+ (32, (0.0, 0.0, -2248.0)),
+ (33, (0.0, 0.0, -2248.0)),
+ (34, (0.0, 0.0, -2248.0)),
+ (35, (0.0, 0.0, -2248.0)),
+ (36, (0.0, 0.0, -2248.0))
+ ]
+
+
+
+ members = [
+ (0, 1),
+ (0, 2),
+ (0, 3),
+ (0, 4),
+ (0, 5),
+ (0, 6),
+ (0, 7),
+ (0, 8),
+ (0, 9),
+ (0, 10),
+ (0, 11),
+ (0, 12),
+ (1, 2),
+ (2, 3),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 12),
+ (12, 1),
+ (1, 13),
+ (2, 15),
+ (3, 17),
+ (4, 19),
+ (5, 21),
+ (6, 23),
+ (7, 25),
+ (8, 27),
+ (9, 29),
+ (10, 31),
+ (11, 33),
+ (12, 35),
+ (1, 14),
+ (2, 14),
+ (2, 16),
+ (3, 16),
+ (3, 18),
+ (4, 18),
+ (4, 20),
+ (5, 20),
+ (5, 22),
+ (6, 22),
+ (6, 24),
+ (7, 24),
+ (7, 26),
+ (8, 26),
+ (8, 28),
+ (9, 28),
+ (9, 30),
+ (10, 30),
+ (10, 32),
+ (11, 32),
+ (11, 34),
+ (12, 34),
+ (12, 36),
+ (1, 36),
+ (13, 14),
+ (14, 15),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 20),
+ (20, 21),
+ (21, 22),
+ (22, 23),
+ (23, 24),
+ (24, 25),
+ (25, 26),
+ (26, 27),
+ (27, 28),
+ (28, 29),
+ (29, 30),
+ (30, 31),
+ (31, 32),
+ (32, 33),
+ (33, 34),
+ (34, 35),
+ (35, 36),
+ (36, 13),
+ (13, 37),
+ (15, 38),
+ (17, 39),
+ (19, 40),
+ (21, 41),
+ (23, 42),
+ (25, 43),
+ (27, 44),
+ (29, 45),
+ (31, 46),
+ (33, 47),
+ (35, 48),
+ (14, 37),
+ (14, 38),
+ (16, 38),
+ (16, 39),
+ (18, 39),
+ (18, 40),
+ (20, 40),
+ (20, 41),
+ (22, 41),
+ (22, 42),
+ (24, 42),
+ (24, 43),
+ (26, 43),
+ (26, 44),
+ (28, 44),
+ (28, 45),
+ (30, 45),
+ (30, 46),
+ (32, 46),
+ (32, 47),
+ (34, 47),
+ (34, 48),
+ (36, 48),
+ (36, 37)
+ ]
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 30450000, 0.288)
+ # print(A.shape)
+ memberType = MemberType(A[index].item(), 30450000, 0.288)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.288)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 30450000, Rho[index].item())
+
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_4forces(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (0.0, 0.0, -5000.0)),
+ (17, (0.0, 0.0, -5000.0)),
+ (18, (0.0, 0.0, -5000.0)),
+ (19, (0.0, 0.0, -5000.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_single(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (5000.0, 5000.0, -5000.0)),
+ (17, (0.0, 0.0, 0.0)),
+ (18, (0.0, 0.0, 0.0)),
+ (19, (0.0, 0.0, 0.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss942bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ [24.5, 24.5, 312.0],
+ [38.5, 24.5, 312.0],
+ [24.5, 38.5, 312.0],
+ [38.5, 38.5, 312.0],
+ [24.5, 24.5, 300.0],
+ [38.5, 24.5, 300.0],
+ [24.5, 38.5, 300.0],
+ [38.5, 38.5, 300.0],
+ [24.5, 24.5, 288.0],
+ [38.5, 24.5, 288.0],
+ [24.5, 38.5, 288.0],
+ [38.5, 38.5, 288.0],
+ [24.5, 24.5, 276.0],
+ [38.5, 24.5, 276.0],
+ [24.5, 38.5, 276.0],
+ [38.5, 38.5, 276.0],
+ [24.5, 24.5, 264.0],
+ [38.5, 24.5, 264.0],
+ [24.5, 38.5, 264.0],
+ [38.5, 38.5, 264.0],
+ [24.5, 24.5, 252.0],
+ [38.5, 24.5, 252.0],
+ [24.5, 38.5, 252.0],
+ [38.5, 38.5, 252.0],
+ [21.6005, 21.6005, 240.0],
+ [31.5, 17.5, 240.0],
+ [41.3995, 21.6005, 240.0],
+ [17.5, 31.5, 240.0],
+ [45.5, 31.5, 240.0],
+ [21.6005, 41.3995, 240.0],
+ [31.5, 45.5, 240.0],
+ [41.3995, 41.3995, 240.0],
+ [21.6005, 21.6005, 228.0],
+ [31.5, 17.5, 228.0],
+ [41.3995, 21.6005, 228.0],
+ [17.5, 31.5, 228.0],
+ [45.5, 31.5, 228.0],
+ [21.6005, 41.3995, 228.0],
+ [31.5, 45.5, 228.0],
+ [41.3995, 41.3995, 228.0],
+ [21.6005, 21.6005, 216.0],
+ [31.5, 17.5, 216.0],
+ [41.3995, 21.6005, 216.0],
+ [17.5, 31.5, 216.0],
+ [45.5, 31.5, 216.0],
+ [21.6005, 41.3995, 216.0],
+ [31.5, 45.5, 216.0],
+ [41.3995, 41.3995, 216.0],
+ [21.6005, 21.6005, 204.0],
+ [31.5, 17.5, 204.0],
+ [41.3995, 21.6005, 204.0],
+ [17.5, 31.5, 204.0],
+ [45.5, 31.5, 204.0],
+ [21.6005, 41.3995, 204.0],
+ [31.5, 45.5, 204.0],
+ [41.3995, 41.3995, 204.0],
+ [21.6005, 21.6005, 192.0],
+ [31.5, 17.5, 192.0],
+ [41.3995, 21.6005, 192.0],
+ [17.5, 31.5, 192.0],
+ [45.5, 31.5, 192.0],
+ [21.6005, 41.3995, 192.0],
+ [31.5, 45.5, 192.0],
+ [41.3995, 41.3995, 192.0],
+ [21.6005, 21.6005, 180.0],
+ [31.5, 17.5, 180.0],
+ [41.3995, 21.6005, 180.0],
+ [17.5, 31.5, 180.0],
+ [45.5, 31.5, 180.0],
+ [21.6005, 41.3995, 180.0],
+ [31.5, 45.5, 180.0],
+ [41.3995, 41.3995, 180.0],
+ [21.6005, 21.6005, 168.0],
+ [31.5, 17.5, 168.0],
+ [41.3995, 21.6005, 168.0],
+ [17.5, 31.5, 168.0],
+ [45.5, 31.5, 168.0],
+ [21.6005, 41.3995, 168.0],
+ [31.5, 45.5, 168.0],
+ [41.3995, 41.3995, 168.0],
+ [21.6005, 21.6005, 156.0],
+ [31.5, 17.5, 156.0],
+ [41.3995, 21.6005, 156.0],
+ [17.5, 31.5, 156.0],
+ [45.5, 31.5, 156.0],
+ [21.6005, 41.3995, 156.0],
+ [31.5, 45.5, 156.0],
+ [41.3995, 41.3995, 156.0],
+ [7.0, 24.5, 144.0],
+ [11.1199, 11.1199, 144.0],
+ [24.5, 7.0, 144.0],
+ [38.5, 7.0, 144.0],
+ [51.8801, 11.1199, 144.0],
+ [56.0, 24.5, 144.0],
+ [7.0, 38.5, 144.0],
+ [11.1199, 51.8801, 144.0],
+ [24.5, 56.0, 144.0],
+ [38.5, 56.0, 144.0],
+ [51.8801, 51.8801, 144.0],
+ [56.0, 38.5, 144.0],
+ [7.0, 24.5, 132.0],
+ [11.1199, 11.1199, 132.0],
+ [24.5, 7.0, 132.0],
+ [38.5, 7.0, 132.0],
+ [51.8801, 11.1199, 132.0],
+ [56.0, 24.5, 132.0],
+ [7.0, 38.5, 132.0],
+ [11.1199, 51.8801, 132.0],
+ [24.5, 56.0, 132.0],
+ [38.5, 56.0, 132.0],
+ [51.8801, 51.8801, 132.0],
+ [56.0, 38.5, 132.0],
+ [7.0, 24.5, 120.0],
+ [11.1199, 11.1199, 120.0],
+ [24.5, 7.0, 120.0],
+ [38.5, 7.0, 120.0],
+ [51.8801, 11.1199, 120.0],
+ [56.0, 24.5, 120.0],
+ [7.0, 38.5, 120.0],
+ [11.1199, 51.8801, 120.0],
+ [24.5, 56.0, 120.0],
+ [38.5, 56.0, 120.0],
+ [51.8801, 51.8801, 120.0],
+ [56.0, 38.5, 120.0],
+ [7.0, 24.5, 108.0],
+ [11.1199, 11.1199, 108.0],
+ [24.5, 7.0, 108.0],
+ [38.5, 7.0, 108.0],
+ [51.8801, 11.1199, 108.0],
+ [56.0, 24.5, 108.0],
+ [7.0, 38.5, 108.0],
+ [11.1199, 51.8801, 108.0],
+ [24.5, 56.0, 108.0],
+ [38.5, 56.0, 108.0],
+ [51.8801, 51.8801, 108.0],
+ [56.0, 38.5, 108.0],
+ [7.0, 24.5, 96.0],
+ [11.1199, 11.1199, 96.0],
+ [24.5, 7.0, 96.0],
+ [38.5, 7.0, 96.0],
+ [51.8801, 11.1199, 96.0],
+ [56.0, 24.5, 96.0],
+ [7.0, 38.5, 96.0],
+ [11.1199, 51.8801, 96.0],
+ [24.5, 56.0, 96.0],
+ [38.5, 56.0, 96.0],
+ [51.8801, 51.8801, 96.0],
+ [56.0, 38.5, 96.0],
+ [7.0, 24.5, 84.0],
+ [11.1199, 11.1199, 84.0],
+ [24.5, 7.0, 84.0],
+ [38.5, 7.0, 84.0],
+ [51.8801, 11.1199, 84.0],
+ [56.0, 24.5, 84.0],
+ [7.0, 38.5, 84.0],
+ [11.1199, 51.8801, 84.0],
+ [24.5, 56.0, 84.0],
+ [38.5, 56.0, 84.0],
+ [51.8801, 51.8801, 84.0],
+ [56.0, 38.5, 84.0],
+ [7.0, 24.5, 72.0],
+ [11.1199, 11.1199, 72.0],
+ [24.5, 7.0, 72.0],
+ [38.5, 7.0, 72.0],
+ [51.8801, 11.1199, 72.0],
+ [56.0, 24.5, 72.0],
+ [7.0, 38.5, 72.0],
+ [11.1199, 51.8801, 72.0],
+ [24.5, 56.0, 72.0],
+ [38.5, 56.0, 72.0],
+ [51.8801, 51.8801, 72.0],
+ [56.0, 38.5, 72.0],
+ [7.0, 24.5, 60.0],
+ [11.1199, 11.1199, 60.0],
+ [24.5, 7.0, 60.0],
+ [38.5, 7.0, 60.0],
+ [51.8801, 11.1199, 60.0],
+ [56.0, 24.5, 60.0],
+ [7.0, 38.5, 60.0],
+ [11.1199, 51.8801, 60.0],
+ [24.5, 56.0, 60.0],
+ [38.5, 56.0, 60.0],
+ [51.8801, 51.8801, 60.0],
+ [56.0, 38.5, 60.0],
+ [7.0, 24.5, 48.0],
+ [11.1199, 11.1199, 48.0],
+ [24.5, 7.0, 48.0],
+ [38.5, 7.0, 48.0],
+ [51.8801, 11.1199, 48.0],
+ [56.0, 24.5, 48.0],
+ [7.0, 38.5, 48.0],
+ [11.1199, 51.8801, 48.0],
+ [24.5, 56.0, 48.0],
+ [38.5, 56.0, 48.0],
+ [51.8801, 51.8801, 48.0],
+ [56.0, 38.5, 48.0],
+ [7.0, 24.5, 36.0],
+ [11.1199, 11.1199, 36.0],
+ [24.5, 7.0, 36.0],
+ [38.5, 7.0, 36.0],
+ [51.8801, 11.1199, 36.0],
+ [56.0, 24.5, 36.0],
+ [7.0, 38.5, 36.0],
+ [11.1199, 51.8801, 36.0],
+ [24.5, 56.0, 36.0],
+ [38.5, 56.0, 36.0],
+ [51.8801, 51.8801, 36.0],
+ [56.0, 38.5, 36.0],
+ [7.0, 24.5, 24.0],
+ [11.1199, 11.1199, 24.0],
+ [24.5, 7.0, 24.0],
+ [38.5, 7.0, 24.0],
+ [51.8801, 11.1199, 24.0],
+ [56.0, 24.5, 24.0],
+ [7.0, 38.5, 24.0],
+ [11.1199, 51.8801, 24.0],
+ [24.5, 56.0, 24.0],
+ [38.5, 56.0, 24.0],
+ [51.8801, 51.8801, 24.0],
+ [56.0, 38.5, 24.0],
+ [7.0, 24.5, 12.0],
+ [11.1199, 11.1199, 12.0],
+ [24.5, 7.0, 12.0],
+ [38.5, 7.0, 12.0],
+ [51.8801, 11.1199, 12.0],
+ [56.0, 24.5, 12.0],
+ [7.0, 38.5, 12.0],
+ [11.1199, 51.8801, 12.0],
+ [24.5, 56.0, 12.0],
+ [38.5, 56.0, 12.0],
+ [51.8801, 51.8801, 12.0],
+ [56.0, 38.5, 12.0],
+ [7.0, 24.5, 0.0],
+ [11.1199, 11.1199, 0.0],
+ [24.5, 7.0, 0.0],
+ [38.5, 7.0, 0.0],
+ [51.8801, 11.1199, 0.0],
+ [56.0, 24.5, 0.0],
+ [7.0, 38.5, 0.0],
+ [11.1199, 51.8801, 0.0],
+ [24.5, 56.0, 0.0],
+ [38.5, 56.0, 0.0],
+ [51.8801, 51.8801, 0.0],
+ [56.0, 38.5, 0.0]
+ ]
+
+
+ supports = []
+ for ii in range(244-12):
+ supports.append(SupportType.NO)
+ for ii in range(12):
+ supports.append(SupportType.PIN)
+
+
+ forces = [
+ (0, (1.5, -1.0, -3.0)),
+ (1, (-1.0, -1.0, -3.0)),
+ (2, (1.5, -1.0, -3.0)),
+ (3, (-1.0, 1.0, -3.0)),
+ (4, (1.5, -1.0, -3.0)),
+ (5, (-1.0, -1.0, -3.0)),
+ (6, (1.5, -1.0, -3.0)),
+ (7, (-1.0, 1.0, -3.0)),
+ (8, (1.5, -1.0, -3.0)),
+ (9, (-1.0, -1.0, -3.0)),
+ (10, (1.5, -1.0, -3.0)),
+ (11, (-1.0, 1.0, -3.0)),
+ (12, (1.5, -1.0, -3.0)),
+ (13, (-1.0, -1.0, -3.0)),
+ (14, (1.5, -1.0, -3.0)),
+ (15, (-1.0, 1.0, -3.0)),
+ (16, (1.5, -1.0, -3.0)),
+ (17, (-1.0, -1.0, -3.0)),
+ (18, (1.5, -1.0, -3.0)),
+ (19, (-1.0, 1.0, -3.0)),
+ (20, (1.5, -1.0, -3.0)),
+ (21, (-1.0, -1.0, -3.0)),
+ (22, (1.5, -1.0, -3.0)),
+ (23, (-1.0, 1.0, -3.0)),
+ (24, (1.5, -1.0, -3.0)),
+ (25, (0.0, -1.0, -3.0)),
+ (26, (-1.0, -1.0, -3.0)),
+ (27, (1.5, 0.0, -3.0)),
+ (28, (-1.0, 0.0, -3.0)),
+ (29, (1.5, 1.0, -3.0)),
+ (30, (0.0, 1.0, -3.0)),
+ (31, (-1.0, 1.0, -3.0)),
+ (32, (1.5, -1.0, -6.0)),
+ (33, (0.0, -1.0, -6.0)),
+ (34, (-1.0, -1.0, -6.0)),
+ (35, (1.5, 0.0, -6.0)),
+ (36, (-1.0, 0.0, -6.0)),
+ (37, (1.5, 1.0, -6.0)),
+ (38, (0.0, 1.0, -6.0)),
+ (39, (-1.0, 1.0, -6.0)),
+ (40, (1.5, -1.0, -6.0)),
+ (41, (0.0, -1.0, -6.0)),
+ (42, (-1.0, -1.0, -6.0)),
+ (43, (1.5, 0.0, -6.0)),
+ (44, (-1.0, 0.0, -6.0)),
+ (45, (1.5, 1.0, -6.0)),
+ (46, (0.0, 1.0, -6.0)),
+ (47, (-1.0, 1.0, -6.0)),
+ (48, (1.5, -1.0, -6.0)),
+ (49, (0.0, -1.0, -6.0)),
+ (50, (-1.0, -1.0, -6.0)),
+ (51, (1.5, 0.0, -6.0)),
+ (52, (-1.0, 0.0, -6.0)),
+ (53, (1.5, 1.0, -6.0)),
+ (54, (0.0, 1.0, -6.0)),
+ (55, (-1.0, 1.0, -6.0)),
+ (56, (1.5, -1.0, -6.0)),
+ (57, (0.0, -1.0, -6.0)),
+ (58, (-1.0, -1.0, -6.0)),
+ (59, (1.5, 0.0, -6.0)),
+ (60, (-1.0, 0.0, -6.0)),
+ (61, (1.5, 1.0, -6.0)),
+ (62, (0.0, 1.0, -6.0)),
+ (63, (-1.0, 1.0, -6.0)),
+ (64, (1.5, -1.0, -6.0)),
+ (65, (0.0, -1.0, -6.0)),
+ (66, (-1.0, -1.0, -6.0)),
+ (67, (1.5, 0.0, -6.0)),
+ (68, (-1.0, 0.0, -6.0)),
+ (69, (1.5, 1.0, -6.0)),
+ (70, (0.0, 1.0, -6.0)),
+ (71, (-1.0, 1.0, -6.0)),
+ (72, (1.5, -1.0, -6.0)),
+ (73, (0.0, -1.0, -6.0)),
+ (74, (-1.0, -1.0, -6.0)),
+ (75, (1.5, 0.0, -6.0)),
+ (76, (-1.0, 0.0, -6.0)),
+ (77, (1.5, 1.0, -6.0)),
+ (78, (0.0, 1.0, -6.0)),
+ (79, (-1.0, 1.0, -6.0)),
+ (80, (1.5, -1.0, -6.0)),
+ (81, (0.0, -1.0, -6.0)),
+ (82, (-1.0, -1.0, -6.0)),
+ (83, (1.5, 0.0, -6.0)),
+ (84, (-1.0, 0.0, -6.0)),
+ (85, (1.5, 1.0, -6.0)),
+ (86, (0.0, 1.0, -6.0)),
+ (87, (-1.0, 1.0, -6.0)),
+ (88, (1.5, -1.0, -6.0)),
+ (89, (1.5, -1.0, -6.0)),
+ (90, (1.5, -1.0, -6.0)),
+ (91, (-1.0, -1.0, -6.0)),
+ (92, (-1.0, -1.0, -6.0)),
+ (93, (-1.0, -1.0, -6.0)),
+ (94, (1.5, 1.0, -6.0)),
+ (95, (1.5, 1.0, -6.0)),
+ (96, (1.5, 1.0, -6.0)),
+ (97, (-1.0, 1.0, -6.0)),
+ (98, (-1.0, 1.0, -6.0)),
+ (99, (-1.0, 1.0, -6.0)),
+ (100, (1.5, -1.0, -9.0)),
+ (101, (1.5, -1.0, -9.0)),
+ (102, (1.5, -1.0, -9.0)),
+ (103, (-1.0, -1.0, -9.0)),
+ (104, (-1.0, -1.0, -9.0)),
+ (105, (-1.0, -1.0, -9.0)),
+ (106, (1.5, 1.0, -9.0)),
+ (107, (1.5, 1.0, -9.0)),
+ (108, (1.5, 1.0, -9.0)),
+ (109, (-1.0, 1.0, -9.0)),
+ (110, (-1.0, 1.0, -9.0)),
+ (111, (-1.0, 1.0, -9.0)),
+ (112, (1.5, -1.0, -9.0)),
+ (113, (1.5, -1.0, -9.0)),
+ (114, (1.5, -1.0, -9.0)),
+ (115, (-1.0, -1.0, -9.0)),
+ (116, (-1.0, -1.0, -9.0)),
+ (117, (-1.0, -1.0, -9.0)),
+ (118, (1.5, 1.0, -9.0)),
+ (119, (1.5, 1.0, -9.0)),
+ (120, (1.5, 1.0, -9.0)),
+ (121, (-1.0, 1.0, -9.0)),
+ (122, (-1.0, 1.0, -9.0)),
+ (123, (-1.0, 1.0, -9.0)),
+ (124, (1.5, -1.0, -9.0)),
+ (125, (1.5, -1.0, -9.0)),
+ (126, (1.5, -1.0, -9.0)),
+ (127, (-1.0, -1.0, -9.0)),
+ (128, (-1.0, -1.0, -9.0)),
+ (129, (-1.0, -1.0, -9.0)),
+ (130, (1.5, 1.0, -9.0)),
+ (131, (1.5, 1.0, -9.0)),
+ (132, (1.5, 1.0, -9.0)),
+ (133, (-1.0, 1.0, -9.0)),
+ (134, (-1.0, 1.0, -9.0)),
+ (135, (-1.0, 1.0, -9.0)),
+ (136, (1.5, -1.0, -9.0)),
+ (137, (1.5, -1.0, -9.0)),
+ (138, (1.5, -1.0, -9.0)),
+ (139, (-1.0, -1.0, -9.0)),
+ (140, (-1.0, -1.0, -9.0)),
+ (141, (-1.0, -1.0, -9.0)),
+ (142, (1.5, 1.0, -9.0)),
+ (143, (1.5, 1.0, -9.0)),
+ (144, (1.5, 1.0, -9.0)),
+ (145, (-1.0, 1.0, -9.0)),
+ (146, (-1.0, 1.0, -9.0)),
+ (147, (-1.0, 1.0, -9.0)),
+ (148, (1.5, -1.0, -9.0)),
+ (149, (1.5, -1.0, -9.0)),
+ (150, (1.5, -1.0, -9.0)),
+ (151, (-1.0, -1.0, -9.0)),
+ (152, (-1.0, -1.0, -9.0)),
+ (153, (-1.0, -1.0, -9.0)),
+ (154, (1.5, 1.0, -9.0)),
+ (155, (1.5, 1.0, -9.0)),
+ (156, (1.5, 1.0, -9.0)),
+ (157, (-1.0, 1.0, -9.0)),
+ (158, (-1.0, 1.0, -9.0)),
+ (159, (-1.0, 1.0, -9.0)),
+ (160, (1.5, -1.0, -9.0)),
+ (161, (1.5, -1.0, -9.0)),
+ (162, (1.5, -1.0, -9.0)),
+ (163, (-1.0, -1.0, -9.0)),
+ (164, (-1.0, -1.0, -9.0)),
+ (165, (-1.0, -1.0, -9.0)),
+ (166, (1.5, 1.0, -9.0)),
+ (167, (1.5, 1.0, -9.0)),
+ (168, (1.5, 1.0, -9.0)),
+ (169, (-1.0, 1.0, -9.0)),
+ (170, (-1.0, 1.0, -9.0)),
+ (171, (-1.0, 1.0, -9.0)),
+ (172, (1.5, -1.0, -9.0)),
+ (173, (1.5, -1.0, -9.0)),
+ (174, (1.5, -1.0, -9.0)),
+ (175, (-1.0, -1.0, -9.0)),
+ (176, (-1.0, -1.0, -9.0)),
+ (177, (-1.0, -1.0, -9.0)),
+ (178, (1.5, 1.0, -9.0)),
+ (179, (1.5, 1.0, -9.0)),
+ (180, (1.5, 1.0, -9.0)),
+ (181, (-1.0, 1.0, -9.0)),
+ (182, (-1.0, 1.0, -9.0)),
+ (183, (-1.0, 1.0, -9.0)),
+ (184, (1.5, -1.0, -9.0)),
+ (185, (1.5, -1.0, -9.0)),
+ (186, (1.5, -1.0, -9.0)),
+ (187, (-1.0, -1.0, -9.0)),
+ (188, (-1.0, -1.0, -9.0)),
+ (189, (-1.0, -1.0, -9.0)),
+ (190, (1.5, 1.0, -9.0)),
+ (191, (1.5, 1.0, -9.0)),
+ (192, (1.5, 1.0, -9.0)),
+ (193, (-1.0, 1.0, -9.0)),
+ (194, (-1.0, 1.0, -9.0)),
+ (195, (-1.0, 1.0, -9.0)),
+ (196, (1.5, -1.0, -9.0)),
+ (197, (1.5, -1.0, -9.0)),
+ (198, (1.5, -1.0, -9.0)),
+ (199, (-1.0, -1.0, -9.0)),
+ (200, (-1.0, -1.0, -9.0)),
+ (201, (-1.0, -1.0, -9.0)),
+ (202, (1.5, 1.0, -9.0)),
+ (203, (1.5, 1.0, -9.0)),
+ (204, (1.5, 1.0, -9.0)),
+ (205, (-1.0, 1.0, -9.0)),
+ (206, (-1.0, 1.0, -9.0)),
+ (207, (-1.0, 1.0, -9.0)),
+ (208, (1.5, -1.0, -9.0)),
+ (209, (1.5, -1.0, -9.0)),
+ (210, (1.5, -1.0, -9.0)),
+ (211, (-1.0, -1.0, -9.0)),
+ (212, (-1.0, -1.0, -9.0)),
+ (213, (-1.0, -1.0, -9.0)),
+ (214, (1.5, 1.0, -9.0)),
+ (215, (1.5, 1.0, -9.0)),
+ (216, (1.5, 1.0, -9.0)),
+ (217, (-1.0, 1.0, -9.0)),
+ (218, (-1.0, 1.0, -9.0)),
+ (219, (-1.0, 1.0, -9.0)),
+ (220, (1.5, -1.0, -9.0)),
+ (221, (1.5, -1.0, -9.0)),
+ (222, (1.5, -1.0, -9.0)),
+ (223, (-1.0, -1.0, -9.0)),
+ (224, (-1.0, -1.0, -9.0)),
+ (225, (-1.0, -1.0, -9.0)),
+ (226, (1.5, 1.0, -9.0)),
+ (227, (1.5, 1.0, -9.0)),
+ (228, (1.5, 1.0, -9.0)),
+ (229, (-1.0, 1.0, -9.0)),
+ (230, (-1.0, 1.0, -9.0)),
+ (231, (-1.0, 1.0, -9.0))
+ ]
+
+
+
+
+ members = [
+ (0, 3),
+ (1, 2),
+ (0, 1),
+ (2, 3),
+ (0, 2),
+ (1, 3),
+ (4, 5),
+ (6, 7),
+ (4, 6),
+ (5, 7),
+ (1, 5),
+ (0, 4),
+ (3, 7),
+ (2, 6),
+ (5, 9),
+ (4, 8),
+ (7, 11),
+ (6, 10),
+ (1, 4),
+ (0, 5),
+ (1, 7),
+ (3, 5),
+ (3, 6),
+ (2, 7),
+ (0, 6),
+ (2, 4),
+ (5, 8),
+ (4, 9),
+ (5, 11),
+ (7, 9),
+ (7, 10),
+ (6, 11),
+ (6, 8),
+ (4, 10),
+ (8, 9),
+ (10, 11),
+ (8, 10),
+ (9, 11),
+ (12, 13),
+ (14, 15),
+ (12, 14),
+ (13, 15),
+ (16, 17),
+ (18, 19),
+ (16, 18),
+ (17, 19),
+ (9, 13),
+ (8, 12),
+ (11, 15),
+ (10, 14),
+ (13, 17),
+ (12, 16),
+ (15, 19),
+ (16, 18),
+ (17, 21),
+ (16, 20),
+ (19, 23),
+ (18, 22),
+ (8, 13),
+ (9, 12),
+ (9, 15),
+ (11, 13),
+ (11, 14),
+ (10, 15),
+ (10, 12),
+ (8, 14),
+ (12, 17),
+ (13, 16),
+ (13, 19),
+ (15, 17),
+ (15, 18),
+ (14, 19),
+ (14, 16),
+ (12, 18),
+ (16, 21),
+ (17, 20),
+ (17, 23),
+ (19, 21),
+ (19, 22),
+ (18, 23),
+ (18, 20),
+ (16, 22),
+ (20, 21),
+ (22, 23),
+ (20, 22),
+ (21, 23),
+ (21, 24),
+ (20, 26),
+ (21, 31),
+ (23, 26),
+ (23, 29),
+ (22, 31),
+ (22, 24),
+ (20, 29),
+ (21, 26),
+ (20, 24),
+ (23, 31),
+ (22, 29),
+ (21, 25),
+ (20, 25),
+ (21, 28),
+ (23, 28),
+ (23, 30),
+ (22, 30),
+ (22, 27),
+ (20, 27),
+ (24, 25),
+ (25, 26),
+ (24, 27),
+ (27, 29),
+ (29, 30),
+ (30, 31),
+ (26, 28),
+ (28, 31),
+ (32, 33),
+ (33, 34),
+ (32, 35),
+ (35, 37),
+ (37, 38),
+ (38, 39),
+ (34, 36),
+ (36, 39),
+ (24, 32),
+ (26, 34),
+ (29, 37),
+ (31, 39),
+ (32, 40),
+ (34, 42),
+ (37, 45),
+ (39, 47),
+ (24, 33),
+ (25, 32),
+ (25, 34),
+ (26, 33),
+ (27, 32),
+ (24, 35),
+ (26, 36),
+ (28, 34),
+ (28, 39),
+ (31, 36),
+ (31, 38),
+ (30, 39),
+ (30, 37),
+ (29, 38),
+ (29, 35),
+ (27, 37),
+ (32, 41),
+ (33, 40),
+ (33, 42),
+ (34, 41),
+ (34, 44),
+ (36, 42),
+ (36, 47),
+ (39, 44),
+ (39, 46),
+ (38, 47),
+ (38, 45),
+ (37, 46),
+ (37, 43),
+ (35, 45),
+ (35, 40),
+ (32, 43),
+ (25, 33),
+ (27, 35),
+ (30, 38),
+ (28, 36),
+ (33, 41),
+ (35, 43),
+ (38, 46),
+ (36, 44),
+ (40, 41),
+ (41, 42),
+ (40, 43),
+ (42, 44),
+ (43, 45),
+ (45, 46),
+ (46, 47),
+ (44, 47),
+ (48, 49),
+ (49, 50),
+ (48, 51),
+ (50, 52),
+ (51, 53),
+ (53, 54),
+ (54, 55),
+ (52, 55),
+ (42, 50),
+ (40, 48),
+ (45, 53),
+ (47, 55),
+ (48, 56),
+ (50, 58),
+ (53, 61),
+ (55, 63),
+ (40, 49),
+ (41, 48),
+ (41, 50),
+ (42, 49),
+ (42, 52),
+ (44, 50),
+ (44, 55),
+ (47, 52),
+ (47, 54),
+ (46, 55),
+ (46, 53),
+ (45, 54),
+ (45, 51),
+ (43, 53),
+ (43, 48),
+ (40, 51),
+ (48, 57),
+ (49, 56),
+ (49, 58),
+ (50, 57),
+ (50, 60),
+ (52, 58),
+ (52, 63),
+ (55, 60),
+ (55, 62),
+ (54, 63),
+ (54, 61),
+ (53, 62),
+ (53, 59),
+ (51, 61),
+ (51, 56),
+ (48, 59),
+ (41, 49),
+ (43, 51),
+ (44, 52),
+ (46, 54),
+ (49, 57),
+ (51, 59),
+ (52, 60),
+ (54, 62),
+ (56, 57),
+ (57, 58),
+ (56, 59),
+ (58, 60),
+ (59, 61),
+ (60, 63),
+ (61, 62),
+ (62, 63),
+ (64, 65),
+ (65, 66),
+ (64, 67),
+ (66, 68),
+ (67, 69),
+ (68, 71),
+ (69, 70),
+ (70, 71),
+ (72, 73),
+ (73, 74),
+ (72, 75),
+ (74, 76),
+ (75, 77),
+ (76, 79),
+ (77, 78),
+ (78, 79),
+ (56, 64),
+ (58, 66),
+ (61, 69),
+ (63, 71),
+ (64, 72),
+ (66, 74),
+ (69, 77),
+ (71, 79),
+ (72, 80),
+ (74, 82),
+ (77, 85),
+ (79, 87),
+ (56, 65),
+ (57, 64),
+ (57, 66),
+ (58, 65),
+ (58, 68),
+ (60, 66),
+ (60, 71),
+ (63, 68),
+ (63, 70),
+ (62, 71),
+ (62, 69),
+ (61, 70),
+ (61, 67),
+ (59, 69),
+ (59, 64),
+ (56, 67),
+ (64, 73),
+ (65, 72),
+ (65, 74),
+ (66, 73),
+ (66, 76),
+ (68, 74),
+ (68, 79),
+ (71, 76),
+ (71, 78),
+ (70, 79),
+ (70, 77),
+ (69, 78),
+ (69, 75),
+ (67, 77),
+ (67, 72),
+ (64, 75),
+ (72, 81),
+ (73, 80),
+ (73, 82),
+ (74, 81),
+ (74, 84),
+ (76, 82),
+ (76, 87),
+ (79, 84),
+ (79, 86),
+ (78, 87),
+ (78, 85),
+ (77, 86),
+ (77, 83),
+ (75, 85),
+ (75, 80),
+ (72, 83),
+ (57, 65),
+ (59, 67),
+ (60, 68),
+ (62, 70),
+ (65, 73),
+ (67, 75),
+ (68, 76),
+ (70, 78),
+ (73, 81),
+ (75, 83),
+ (76, 84),
+ (78, 86),
+ (80, 81),
+ (81, 82),
+ (80, 83),
+ (82, 84),
+ (83, 85),
+ (84, 87),
+ (85, 86),
+ (86, 87),
+ (80, 89),
+ (82, 92),
+ (85, 95),
+ (87, 98),
+ (81, 89),
+ (81, 92),
+ (84, 92),
+ (84, 98),
+ (83, 95),
+ (83, 89),
+ (86, 95),
+ (86, 98),
+ (82, 91),
+ (80, 90),
+ (82, 93),
+ (87, 99),
+ (80, 88),
+ (85, 94),
+ (85, 96),
+ (87, 97),
+ (81, 91),
+ (81, 90),
+ (83, 88),
+ (83, 94),
+ (84, 93),
+ (84, 99),
+ (86, 96),
+ (86, 97),
+ (89, 90),
+ (91, 92),
+ (88, 89),
+ (92, 93),
+ (94, 95),
+ (95, 96),
+ (97, 98),
+ (98, 99),
+ (101, 102),
+ (103, 104),
+ (100, 101),
+ (104, 105),
+ (106, 107),
+ (107, 108),
+ (109, 110),
+ (110, 111),
+ (90, 91),
+ (88, 94),
+ (93, 99),
+ (96, 97),
+ (102, 103),
+ (100, 106),
+ (105, 111),
+ (108, 109),
+ (89, 101),
+ (92, 104),
+ (95, 107),
+ (98, 110),
+ (101, 113),
+ (104, 116),
+ (107, 119),
+ (110, 122),
+ (92, 103),
+ (91, 104),
+ (89, 102),
+ (90, 101),
+ (88, 101),
+ (89, 100),
+ (92, 105),
+ (93, 104),
+ (99, 110),
+ (98, 111),
+ (98, 109),
+ (97, 110),
+ (96, 107),
+ (95, 108),
+ (95, 106),
+ (94, 107),
+ (101, 114),
+ (102, 113),
+ (101, 112),
+ (100, 113),
+ (103, 116),
+ (104, 115),
+ (104, 117),
+ (105, 116),
+ (111, 122),
+ (110, 123),
+ (110, 121),
+ (109, 122),
+ (108, 119),
+ (107, 120),
+ (107, 118),
+ (106, 119),
+ (90, 102),
+ (91, 103),
+ (96, 108),
+ (97, 109),
+ (88, 100),
+ (94, 106),
+ (93, 105),
+ (99, 111),
+ (102, 114),
+ (103, 115),
+ (108, 120),
+ (109, 121),
+ (100, 112),
+ (106, 118),
+ (105, 117),
+ (111, 123),
+ (90, 103),
+ (91, 102),
+ (96, 109),
+ (97, 108),
+ (88, 106),
+ (94, 100),
+ (93, 111),
+ (99, 105),
+ (102, 115),
+ (103, 114),
+ (108, 121),
+ (109, 120),
+ (105, 123),
+ (111, 117),
+ (100, 118),
+ (106, 112),
+ (112, 113),
+ (113, 114),
+ (115, 116),
+ (116, 117),
+ (118, 119),
+ (119, 120),
+ (121, 122),
+ (122, 123),
+ (124, 125),
+ (125, 126),
+ (127, 128),
+ (128, 129),
+ (130, 131),
+ (131, 132),
+ (133, 134),
+ (134, 135),
+ (136, 137),
+ (137, 138),
+ (139, 140),
+ (140, 141),
+ (142, 143),
+ (143, 144),
+ (145, 146),
+ (146, 147),
+ (114, 115),
+ (120, 121),
+ (112, 118),
+ (117, 123),
+ (126, 127),
+ (132, 133),
+ (124, 130),
+ (129, 135),
+ (138, 139),
+ (144, 145),
+ (136, 142),
+ (141, 147),
+ (113, 125),
+ (116, 128),
+ (119, 131),
+ (122, 134),
+ (125, 137),
+ (128, 140),
+ (131, 143),
+ (134, 146),
+ (137, 149),
+ (140, 152),
+ (143, 155),
+ (146, 158),
+ (112, 125),
+ (113, 124),
+ (113, 126),
+ (114, 125),
+ (115, 128),
+ (116, 127),
+ (116, 129),
+ (117, 128),
+ (118, 131),
+ (119, 130),
+ (119, 132),
+ (120, 131),
+ (121, 134),
+ (122, 133),
+ (122, 135),
+ (123, 134),
+ (124, 137),
+ (125, 136),
+ (125, 138),
+ (126, 137),
+ (127, 140),
+ (128, 139),
+ (128, 141),
+ (129, 140),
+ (130, 143),
+ (131, 142),
+ (131, 144),
+ (132, 143),
+ (133, 146),
+ (134, 145),
+ (134, 147),
+ (135, 146),
+ (136, 149),
+ (137, 148),
+ (137, 150),
+ (138, 149),
+ (139, 152),
+ (140, 151),
+ (140, 153),
+ (141, 152),
+ (142, 155),
+ (143, 154),
+ (143, 156),
+ (144, 155),
+ (145, 158),
+ (146, 157),
+ (146, 159),
+ (147, 158),
+ (114, 126),
+ (115, 127),
+ (120, 132),
+ (121, 133),
+ (112, 124),
+ (118, 130),
+ (117, 129),
+ (123, 135),
+ (126, 138),
+ (127, 139),
+ (132, 144),
+ (133, 145),
+ (124, 136),
+ (130, 142),
+ (129, 141),
+ (135, 147),
+ (138, 150),
+ (139, 151),
+ (144, 156),
+ (145, 157),
+ (136, 148),
+ (142, 154),
+ (141, 153),
+ (147, 159),
+ (114, 127),
+ (115, 126),
+ (120, 133),
+ (121, 132),
+ (112, 130),
+ (118, 124),
+ (117, 135),
+ (123, 129),
+ (126, 139),
+ (127, 138),
+ (132, 145),
+ (133, 144),
+ (124, 142),
+ (130, 136),
+ (129, 147),
+ (135, 141),
+ (138, 151),
+ (139, 150),
+ (144, 157),
+ (145, 156),
+ (136, 154),
+ (142, 148),
+ (141, 153),
+ (147, 153),
+ (148, 149),
+ (149, 150),
+ (151, 152),
+ (152, 153),
+ (154, 155),
+ (155, 156),
+ (157, 158),
+ (158, 159),
+ (160, 161),
+ (161, 162),
+ (163, 164),
+ (164, 165),
+ (166, 167),
+ (167, 168),
+ (169, 170),
+ (170, 171),
+ (172, 173),
+ (173, 174),
+ (175, 176),
+ (176, 177),
+ (178, 179),
+ (179, 180),
+ (181, 182),
+ (182, 183),
+ (150, 151),
+ (156, 157),
+ (148, 154),
+ (153, 159),
+ (162, 163),
+ (168, 169),
+ (160, 166),
+ (165, 171),
+ (174, 175),
+ (180, 181),
+ (172, 178),
+ (177, 183),
+ (149, 161),
+ (152, 164),
+ (155, 167),
+ (158, 170),
+ (161, 173),
+ (164, 176),
+ (167, 179),
+ (170, 182),
+ (173, 185),
+ (176, 188),
+ (179, 191),
+ (182, 194),
+ (148, 161),
+ (149, 160),
+ (149, 162),
+ (150, 161),
+ (151, 164),
+ (152, 163),
+ (152, 165),
+ (153, 164),
+ (154, 167),
+ (155, 166),
+ (155, 168),
+ (156, 167),
+ (157, 170),
+ (158, 169),
+ (158, 171),
+ (159, 170),
+ (160, 173),
+ (161, 172),
+ (161, 174),
+ (162, 173),
+ (163, 176),
+ (164, 175),
+ (164, 177),
+ (165, 176),
+ (166, 179),
+ (167, 178),
+ (167, 180),
+ (168, 179),
+ (169, 182),
+ (170, 181),
+ (170, 183),
+ (171, 182),
+ (172, 185),
+ (173, 184),
+ (173, 186),
+ (174, 185),
+ (175, 188),
+ (176, 187),
+ (176, 189),
+ (177, 188),
+ (178, 191),
+ (179, 190),
+ (179, 192),
+ (180, 191),
+ (181, 194),
+ (182, 193),
+ (182, 195),
+ (183, 194),
+ (150, 162),
+ (151, 163),
+ (156, 168),
+ (157, 169),
+ (148, 160),
+ (154, 166),
+ (153, 165),
+ (159, 171),
+ (162, 174),
+ (163, 175),
+ (168, 180),
+ (169, 181),
+ (160, 172),
+ (166, 178),
+ (165, 177),
+ (171, 183),
+ (174, 186),
+ (175, 187),
+ (180, 192),
+ (181, 193),
+ (172, 184),
+ (178, 190),
+ (177, 189),
+ (183, 195),
+ (150, 163),
+ (151, 162),
+ (156, 169),
+ (157, 168),
+ (148, 166),
+ (154, 160),
+ (153, 171),
+ (159, 165),
+ (162, 175),
+ (163, 174),
+ (168, 181),
+ (169, 180),
+ (160, 178),
+ (166, 172),
+ (165, 183),
+ (171, 177),
+ (174, 187),
+ (175, 186),
+ (180, 193),
+ (180, 192),
+ (172, 190),
+ (178, 184),
+ (177, 195),
+ (183, 189),
+ (184, 185),
+ (185, 186),
+ (187, 188),
+ (188, 189),
+ (190, 191),
+ (191, 192),
+ (193, 194),
+ (194, 195),
+ (196, 197),
+ (197, 198),
+ (199, 200),
+ (200, 201),
+ (202, 203),
+ (203, 204),
+ (205, 206),
+ (206, 207),
+ (208, 209),
+ (209, 210),
+ (211, 212),
+ (212, 213),
+ (214, 215),
+ (215, 216),
+ (217, 218),
+ (218, 219),
+ (186, 187),
+ (192, 193),
+ (184, 190),
+ (189, 195),
+ (198, 199),
+ (204, 205),
+ (196, 202),
+ (201, 207),
+ (210, 211),
+ (216, 217),
+ (208, 214),
+ (213, 219),
+ (185, 197),
+ (188, 200),
+ (191, 203),
+ (194, 206),
+ (197, 209),
+ (200, 212),
+ (203, 215),
+ (206, 218),
+ (209, 221),
+ (212, 224),
+ (215, 227),
+ (218, 230),
+ (184, 197),
+ (185, 196),
+ (185, 198),
+ (186, 197),
+ (187, 200),
+ (188, 199),
+ (188, 201),
+ (189, 200),
+ (190, 203),
+ (191, 202),
+ (191, 204),
+ (192, 203),
+ (193, 206),
+ (194, 205),
+ (194, 207),
+ (195, 206),
+ (196, 209),
+ (197, 208),
+ (197, 210),
+ (198, 209),
+ (199, 212),
+ (200, 211),
+ (200, 213),
+ (201, 212),
+ (202, 215),
+ (203, 214),
+ (203, 216),
+ (204, 215),
+ (205, 218),
+ (206, 217),
+ (206, 219),
+ (207, 218),
+ (208, 221),
+ (209, 220),
+ (209, 222),
+ (210, 221),
+ (211, 224),
+ (212, 223),
+ (212, 225),
+ (213, 224),
+ (214, 227),
+ (215, 226),
+ (215, 228),
+ (216, 227),
+ (217, 230),
+ (218, 229),
+ (218, 231),
+ (219, 230),
+ (186, 198),
+ (187, 199),
+ (192, 204),
+ (193, 205),
+ (184, 196),
+ (190, 202),
+ (189, 201),
+ (195, 207),
+ (198, 210),
+ (199, 211),
+ (204, 216),
+ (205, 217),
+ (196, 208),
+ (202, 214),
+ (201, 213),
+ (207, 219),
+ (210, 222),
+ (211, 223),
+ (216, 228),
+ (217, 229),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (186, 199),
+ (187, 198),
+ (192, 205),
+ (193, 204),
+ (184, 202),
+ (190, 196),
+ (189, 207),
+ (195, 201),
+ (198, 211),
+ (199, 210),
+ (204, 217),
+ (205, 216),
+ (196, 214),
+ (202, 208),
+ (201, 219),
+ (207, 213),
+ (210, 223),
+ (211, 222),
+ (216, 229),
+ (217, 228),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (220, 221),
+ (221, 222),
+ (223, 224),
+ (224, 225),
+ (226, 227),
+ (227, 228),
+ (229, 230),
+ (230, 231),
+ (222, 223),
+ (228, 229),
+ (220, 226),
+ (225, 231),
+ (221, 233),
+ (224, 236),
+ (227, 239),
+ (230, 242),
+ (222, 233),
+ (220, 233),
+ (223, 236),
+ (225, 236),
+ (226, 239),
+ (228, 239),
+ (229, 242),
+ (231, 242),
+ (221, 234),
+ (221, 232),
+ (224, 235),
+ (224, 237),
+ (227, 238),
+ (227, 240),
+ (230, 241),
+ (230, 243),
+ (222, 234),
+ (223, 235),
+ (228, 240),
+ (229, 241),
+ (220, 232),
+ (226, 238),
+ (225, 237),
+ (231, 243),
+ (222, 235),
+ (223, 234),
+ (228, 241),
+ (229, 240),
+ (220, 238),
+ (226, 232),
+ (225, 243),
+ (231, 237)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+
+
+def Truss10D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ X_scaled = X * (35-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss25D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ X_scaled = X * (10-0.31) + 0.31
+
+ return X_scaled
+
+
+def Truss72D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ X_scaled = X * (10-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss120D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = X * (20-0.775) + 0.775
+
+ return X_scaled
+
+def Truss360D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = torch.zeros(X.shape)
+ X_scaled[:,:120] = X[:,:120] * (20-0.775) + 0.775
+ X_scaled[:,120:240] = X[:,120:240] * (5e4-1e3) + 1e3
+ X_scaled[:,240:360] = X[:,240:360] * (0.3-0.05) + 0.05
+
+ return X_scaled
+
+
+
+
+def Truss10D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ gx[ii,10] = max(abs(displace[1][0]), abs(displace[1][1])) - 2
+ gx[ii,11] = max(abs(displace[2][0]), abs(displace[2][1])) - 2
+ gx[ii,12] = max(abs(displace[4][0]), abs(displace[4][1])) - 2
+ gx[ii,13] = max(abs(displace[5][0]), abs(displace[5][1])) - 2
+
+ return gx, fx
+
+
+
+def Truss25D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 25 bar stress constraints, 6 displacement constraints
+ gx = torch.zeros(n,31)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 40ksi (34809)
+ for ss in range(25):
+ gx[ii,ss] = abs(stress[ss]) - 34809
+
+ # Max displacement in x and y direction less than .4 inches
+ for dd in range(6):
+ # print(displace[dd])
+ gx[ii,25+dd] = max(abs(displace[dd][0]), abs(displace[dd][1])) - 0.039
+
+
+ return gx, fx
+
+
+
+
+
+
+def Truss72D_4forces(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 72 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,76)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 25000
+ for ss in range(72):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ # Max displacement in x and y direction less than .25 inches
+ # print(displace[16], displace[17], displace[18], displace[19])
+ gx[ii,72] = max(abs(displace[16][0]), abs(displace[16][1])) - 0.25
+ gx[ii,73] = max(abs(displace[17][0]), abs(displace[17][1])) - 0.25
+ gx[ii,74] = max(abs(displace[18][0]), abs(displace[18][1])) - 0.25
+ gx[ii,75] = max(abs(displace[19][0]), abs(displace[19][1])) - 0.25
+
+
+ return gx, fx
+
+
+
+def Truss120D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss360D(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ A = X[:,:120]
+ E = X[:,120:240]
+ Rho = X[:,240:360]
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+
+ # if (E != None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ # elif (E != None) & (Rho==None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ # elif (E == None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+ # gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Trusses/.ipynb_checkpoints/Truss10D-checkpoint.py b/test_functions/Trusses/.ipynb_checkpoints/Truss10D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c56f09cfc2d258e92feb09e0c0bf19477e45acd
--- /dev/null
+++ b/test_functions/Trusses/.ipynb_checkpoints/Truss10D-checkpoint.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+from .. import TrussSolvers
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(A)
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Trusses/Truss10D.py b/test_functions/Trusses/Truss10D.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c56f09cfc2d258e92feb09e0c0bf19477e45acd
--- /dev/null
+++ b/test_functions/Trusses/Truss10D.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+from .. import TrussSolvers
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(A)
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions/Trusses/__pycache__/Truss10D.cpython-311.pyc b/test_functions/Trusses/__pycache__/Truss10D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7805bcb57aaaeb456de17c80a26c30380821b4ef
Binary files /dev/null and b/test_functions/Trusses/__pycache__/Truss10D.cpython-311.pyc differ
diff --git a/test_functions/Untitled.ipynb b/test_functions/Untitled.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..363fcab7ed6e9634e198cf5555ceb88932c9a245
--- /dev/null
+++ b/test_functions/Untitled.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/test_functions/WeldedBeam.py b/test_functions/WeldedBeam.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1fd4d446c972834fc592de6b1484c772ea820ac
--- /dev/null
+++ b/test_functions/WeldedBeam.py
@@ -0,0 +1,94 @@
+import torch
+import numpy as np
+
+#
+#
+# WeldedBeam: 4D objective, 5 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+def WeldedBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+
+ C1 = 1.10471
+ C2 = 0.04811
+ C3 = 14.0
+ fx = torch.zeros(individuals.shape[0], 1)
+ gx1 = torch.zeros(individuals.shape[0], 1)
+ gx2 = torch.zeros(individuals.shape[0], 1)
+ gx3 = torch.zeros(individuals.shape[0], 1)
+ gx4 = torch.zeros(individuals.shape[0], 1)
+ gx5 = torch.zeros(individuals.shape[0], 1)
+
+ for i in range(individuals.shape[0]):
+
+ x = individuals[i,:]
+
+ h = x[0]
+ l = x[1]
+ t = x[2]
+ b = x[3]
+
+ test_function = - ( C1*h*h*l + C2*t*b*(C3+l) )
+ fx[i] = test_function
+
+ ## Calculate constraints terms
+ tao_dx = 6000 / (np.sqrt(2)*h*l)
+
+ tao_dxx = 6000*(14+0.5*l)*np.sqrt( 0.25*(l**2 + (h+t)**2 ) ) / (2* (0.707*h*l * ( l**2 /12 + 0.25*(h+t)**2 ) ) )
+
+ tao = np.sqrt( tao_dx**2 + tao_dxx**2 + l*tao_dx*tao_dxx / np.sqrt(0.25*(l**2 + (h+t)**2)) )
+
+ sigma = 504000/ (t**2 * b)
+
+ P_c = 64746*(1-0.0282346*t)* t * b**3
+
+ delta = 2.1952/ (t**3 *b)
+
+
+ ## Calculate 5 constraints
+ g1 = (-1) * (13600- tao)
+ g2 = (-1) * (30000 - sigma)
+ g3 = (-1) * (b - h)
+ g4 = (-1) * (P_c - 6000)
+ g5 = (-1) * (0.25 - delta)
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5), 1)
+ return gx, fx
+
+
+def WeldedBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ h = (X[:,0] * (10-0.125) + 0.125 ).reshape(X.shape[0],1)
+ l = (X[:,1] * (15-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ t = (X[:,2] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ b = (X[:,3] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((h, l, t, b), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions/__init__.py b/test_functions/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions/__pycache__/Ackley10D.cpython-310.pyc b/test_functions/__pycache__/Ackley10D.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..939c395963562b5e43943dd937217c9a0c158cf8
Binary files /dev/null and b/test_functions/__pycache__/Ackley10D.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Ackley10D.cpython-311.pyc b/test_functions/__pycache__/Ackley10D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3ae42be16174f26a558ce50a3d06697772a3c25c
Binary files /dev/null and b/test_functions/__pycache__/Ackley10D.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Ackley10D.cpython-38.pyc b/test_functions/__pycache__/Ackley10D.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a4a46205bee4741268a6e0b43afa9fe2d9b48852
Binary files /dev/null and b/test_functions/__pycache__/Ackley10D.cpython-38.pyc differ
diff --git a/test_functions/__pycache__/Ackley10D.cpython-39.pyc b/test_functions/__pycache__/Ackley10D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..95c62aee32e19b75ca36f1d3855d77a0dd26f867
Binary files /dev/null and b/test_functions/__pycache__/Ackley10D.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Ackley2D.cpython-310.pyc b/test_functions/__pycache__/Ackley2D.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..48696fe053334a107153dfa86c7e8051e6b36e5a
Binary files /dev/null and b/test_functions/__pycache__/Ackley2D.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Ackley2D.cpython-311.pyc b/test_functions/__pycache__/Ackley2D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..644ddef1084f73e8f24a285fdfd4d40e543cc0a7
Binary files /dev/null and b/test_functions/__pycache__/Ackley2D.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Ackley2D.cpython-39.pyc b/test_functions/__pycache__/Ackley2D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..418e674ed5473813101c3a684262d0490bfb69a8
Binary files /dev/null and b/test_functions/__pycache__/Ackley2D.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Ackley2DEmbedd.cpython-310.pyc b/test_functions/__pycache__/Ackley2DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..210499996825793de72e934a965a5c1c826be6e7
Binary files /dev/null and b/test_functions/__pycache__/Ackley2DEmbedd.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Ackley2DEmbedd.cpython-311.pyc b/test_functions/__pycache__/Ackley2DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9f12c863e2981114aee51e6abdc371456332922e
Binary files /dev/null and b/test_functions/__pycache__/Ackley2DEmbedd.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Ackley2DEmbedd.cpython-39.pyc b/test_functions/__pycache__/Ackley2DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f2db2bc5155d6638d45022e1093a1b9a0c706c75
Binary files /dev/null and b/test_functions/__pycache__/Ackley2DEmbedd.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Ackley500D.cpython-39.pyc b/test_functions/__pycache__/Ackley500D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..76e58d8dbc301bd9c89b75b519fcfc701c8a80e8
Binary files /dev/null and b/test_functions/__pycache__/Ackley500D.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Ackley6D.cpython-310.pyc b/test_functions/__pycache__/Ackley6D.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..83f4ad1b94ca40b3deadf33f7db8640ff67f23f0
Binary files /dev/null and b/test_functions/__pycache__/Ackley6D.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Ackley6D.cpython-311.pyc b/test_functions/__pycache__/Ackley6D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..14dd6827d006a8a622706304d0a401635a1df4e5
Binary files /dev/null and b/test_functions/__pycache__/Ackley6D.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Ackley6D.cpython-39.pyc b/test_functions/__pycache__/Ackley6D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3d7de45bbdb14792369732daa1507fcdfddfc60e
Binary files /dev/null and b/test_functions/__pycache__/Ackley6D.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/AckleyND.cpython-310.pyc b/test_functions/__pycache__/AckleyND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b7c064f93d72f66938ab3bbdbf21103959ff1baf
Binary files /dev/null and b/test_functions/__pycache__/AckleyND.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/AckleyND.cpython-311.pyc b/test_functions/__pycache__/AckleyND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..850434077b1be71540506552b318c1c19fb97693
Binary files /dev/null and b/test_functions/__pycache__/AckleyND.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/AckleyND.cpython-39.pyc b/test_functions/__pycache__/AckleyND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d4dbd31eb1085de872602aefcc7d904a0cf3bdbe
Binary files /dev/null and b/test_functions/__pycache__/AckleyND.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Branin2DEmbedd.cpython-310.pyc b/test_functions/__pycache__/Branin2DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d8b60958c0e8c5b973c3c069570095b9e99f927c
Binary files /dev/null and b/test_functions/__pycache__/Branin2DEmbedd.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Branin2DEmbedd.cpython-311.pyc b/test_functions/__pycache__/Branin2DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d86f86c1c005fd6b715fe5c0dec94dcb14d0f998
Binary files /dev/null and b/test_functions/__pycache__/Branin2DEmbedd.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Branin2DEmbedd.cpython-39.pyc b/test_functions/__pycache__/Branin2DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..77ece24a0ac413c34f6e99d5ddf29ce447adbe19
Binary files /dev/null and b/test_functions/__pycache__/Branin2DEmbedd.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Bukin.cpython-311.pyc b/test_functions/__pycache__/Bukin.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e3618d32603e6ac6c6a8bd8268c498d094cb0d3e
Binary files /dev/null and b/test_functions/__pycache__/Bukin.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/CantileverBeam.cpython-310.pyc b/test_functions/__pycache__/CantileverBeam.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e93b09863eae39b244c652aa7f2361a422ff6f5a
Binary files /dev/null and b/test_functions/__pycache__/CantileverBeam.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/CantileverBeam.cpython-311.pyc b/test_functions/__pycache__/CantileverBeam.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fa557da6eba8d0edeea57a272a070679a12f9809
Binary files /dev/null and b/test_functions/__pycache__/CantileverBeam.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/CantileverBeam.cpython-39.pyc b/test_functions/__pycache__/CantileverBeam.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6541fb6552f858709d8186ad8973ee674add5b59
Binary files /dev/null and b/test_functions/__pycache__/CantileverBeam.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Car.cpython-310.pyc b/test_functions/__pycache__/Car.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d41b5d3dcd430f72285141dffb6e7962d59c2e61
Binary files /dev/null and b/test_functions/__pycache__/Car.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Car.cpython-311.pyc b/test_functions/__pycache__/Car.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d6f0598a927366f93a45cf2dd53787c988e6129f
Binary files /dev/null and b/test_functions/__pycache__/Car.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Car.cpython-39.pyc b/test_functions/__pycache__/Car.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c043c7d33f164255c35e974ffb54e8e86329b3dd
Binary files /dev/null and b/test_functions/__pycache__/Car.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/CompressionSpring.cpython-310.pyc b/test_functions/__pycache__/CompressionSpring.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ab754c07b5beba79947d9d402bea5c9420aa6630
Binary files /dev/null and b/test_functions/__pycache__/CompressionSpring.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/CompressionSpring.cpython-311.pyc b/test_functions/__pycache__/CompressionSpring.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f5f3b7dd6129e869e1cc16a723d160b57ffad9ed
Binary files /dev/null and b/test_functions/__pycache__/CompressionSpring.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/CompressionSpring.cpython-39.pyc b/test_functions/__pycache__/CompressionSpring.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8c8ba9bb4c1e04c9e5f7bd1b5e98d39c0924fb82
Binary files /dev/null and b/test_functions/__pycache__/CompressionSpring.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/DixonPriceND.cpython-310.pyc b/test_functions/__pycache__/DixonPriceND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..586f6a3a895dc88673938abcfd376c714e4f521a
Binary files /dev/null and b/test_functions/__pycache__/DixonPriceND.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/DixonPriceND.cpython-311.pyc b/test_functions/__pycache__/DixonPriceND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4e5022b77c44c009b60e1ddcd6502e24e675c3d7
Binary files /dev/null and b/test_functions/__pycache__/DixonPriceND.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/DixonPriceND.cpython-39.pyc b/test_functions/__pycache__/DixonPriceND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..39495310240c0def36cf9ee30b14d1308adbe4d4
Binary files /dev/null and b/test_functions/__pycache__/DixonPriceND.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/DummyFixConsDim.cpython-39.pyc b/test_functions/__pycache__/DummyFixConsDim.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..52af684f87fe9f6c40b75b8aa0b29b22fb184a6b
Binary files /dev/null and b/test_functions/__pycache__/DummyFixConsDim.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Finder24.cpython-310.pyc b/test_functions/__pycache__/Finder24.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e527a0a7b92d4e8abbe47c51482d5628997a34ba
Binary files /dev/null and b/test_functions/__pycache__/Finder24.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Finder24.cpython-311.pyc b/test_functions/__pycache__/Finder24.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0bfa36d6caadccfb998746775800a123ff78d0b5
Binary files /dev/null and b/test_functions/__pycache__/Finder24.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Finder24.cpython-39.pyc b/test_functions/__pycache__/Finder24.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8ae13202cb4ee5377d3b9ae888924ad7f99dbcc2
Binary files /dev/null and b/test_functions/__pycache__/Finder24.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/GKXWC1.cpython-310.pyc b/test_functions/__pycache__/GKXWC1.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7e101b74e2e66e77d868a4a0b0e4b02266259cf8
Binary files /dev/null and b/test_functions/__pycache__/GKXWC1.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/GKXWC1.cpython-311.pyc b/test_functions/__pycache__/GKXWC1.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a9cadc30f2136af1c8cc3bfe5ee628a1b97e1c04
Binary files /dev/null and b/test_functions/__pycache__/GKXWC1.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/GKXWC1.cpython-39.pyc b/test_functions/__pycache__/GKXWC1.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7f7d1f228860840c6c93f2b2f24ad762ebac29d0
Binary files /dev/null and b/test_functions/__pycache__/GKXWC1.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/GKXWC2.cpython-310.pyc b/test_functions/__pycache__/GKXWC2.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..69d53386580ad1de7e5fd2dde3cc1a9cb618bed7
Binary files /dev/null and b/test_functions/__pycache__/GKXWC2.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/GKXWC2.cpython-311.pyc b/test_functions/__pycache__/GKXWC2.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f57c83d5bd23d4fa99f488bf2b859570cecdf5b4
Binary files /dev/null and b/test_functions/__pycache__/GKXWC2.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/GKXWC2.cpython-39.pyc b/test_functions/__pycache__/GKXWC2.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b65cf9f09c2547f00130e555dbd5ae9eb80563d0
Binary files /dev/null and b/test_functions/__pycache__/GKXWC2.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Griewank2DEmbedd.cpython-310.pyc b/test_functions/__pycache__/Griewank2DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a297b3f72898354ea2d8a7943d3396319495d540
Binary files /dev/null and b/test_functions/__pycache__/Griewank2DEmbedd.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Griewank2DEmbedd.cpython-311.pyc b/test_functions/__pycache__/Griewank2DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2d2f025c02ab16478e654c368c8bf139068df18a
Binary files /dev/null and b/test_functions/__pycache__/Griewank2DEmbedd.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Griewank2DEmbedd.cpython-39.pyc b/test_functions/__pycache__/Griewank2DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..85db9a07a0107f800a70e09adf1606c6c37c8ed3
Binary files /dev/null and b/test_functions/__pycache__/Griewank2DEmbedd.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/GriewankND.cpython-310.pyc b/test_functions/__pycache__/GriewankND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ef22a6920da256bd320bd55f45eaa06d6eba82d4
Binary files /dev/null and b/test_functions/__pycache__/GriewankND.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/GriewankND.cpython-311.pyc b/test_functions/__pycache__/GriewankND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2095e30da12bbc3436eb0eca56636a4bd7c9b9cb
Binary files /dev/null and b/test_functions/__pycache__/GriewankND.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/GriewankND.cpython-39.pyc b/test_functions/__pycache__/GriewankND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a059a496f5c000e8249f556ca6dbbedc03775532
Binary files /dev/null and b/test_functions/__pycache__/GriewankND.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Hartmann6DEmbedd.cpython-310.pyc b/test_functions/__pycache__/Hartmann6DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c6cc7194648d8a711a572f99a6fc71d54e0e74fe
Binary files /dev/null and b/test_functions/__pycache__/Hartmann6DEmbedd.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Hartmann6DEmbedd.cpython-311.pyc b/test_functions/__pycache__/Hartmann6DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..57dfa4eddc8e0280c7b8b662ba838c68af476a0f
Binary files /dev/null and b/test_functions/__pycache__/Hartmann6DEmbedd.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Hartmann6DEmbedd.cpython-39.pyc b/test_functions/__pycache__/Hartmann6DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cf04485f8642f6ad6e1aea4f02643b73f5395646
Binary files /dev/null and b/test_functions/__pycache__/Hartmann6DEmbedd.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/HeatExchanger.cpython-310.pyc b/test_functions/__pycache__/HeatExchanger.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..126cd04d58680677e2a9c66eafc4d44f68e2e390
Binary files /dev/null and b/test_functions/__pycache__/HeatExchanger.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/HeatExchanger.cpython-311.pyc b/test_functions/__pycache__/HeatExchanger.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2d9d1ccbac8975b2efeb6d4f4dced634c5c6ec0f
Binary files /dev/null and b/test_functions/__pycache__/HeatExchanger.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/HeatExchanger.cpython-39.pyc b/test_functions/__pycache__/HeatExchanger.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9bb2fd67858f60c658f8ecc2979d7ce7dc6c3c71
Binary files /dev/null and b/test_functions/__pycache__/HeatExchanger.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/JLH1.cpython-310.pyc b/test_functions/__pycache__/JLH1.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2e9e414c0d3eceb124570db025e2f357043f3c4c
Binary files /dev/null and b/test_functions/__pycache__/JLH1.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/JLH1.cpython-311.pyc b/test_functions/__pycache__/JLH1.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b81a5075281446add616777cf6181c8947e10abb
Binary files /dev/null and b/test_functions/__pycache__/JLH1.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/JLH1.cpython-39.pyc b/test_functions/__pycache__/JLH1.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bcfd134993680524aa669020b76cb119f7f266e4
Binary files /dev/null and b/test_functions/__pycache__/JLH1.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/JLH2.cpython-310.pyc b/test_functions/__pycache__/JLH2.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..81e614f9f1e374e191d3365442f80283de4b5a81
Binary files /dev/null and b/test_functions/__pycache__/JLH2.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/JLH2.cpython-311.pyc b/test_functions/__pycache__/JLH2.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0ab85797fa246a5c770e3f6233e343ca1982e058
Binary files /dev/null and b/test_functions/__pycache__/JLH2.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/JLH2.cpython-39.pyc b/test_functions/__pycache__/JLH2.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..75113ff485cc009bd163c461ba59214e2c8847fe
Binary files /dev/null and b/test_functions/__pycache__/JLH2.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/KeaneBump.cpython-310.pyc b/test_functions/__pycache__/KeaneBump.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..37353c3e5b89945e39107d539a1aeaad239d6c0d
Binary files /dev/null and b/test_functions/__pycache__/KeaneBump.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/KeaneBump.cpython-311.pyc b/test_functions/__pycache__/KeaneBump.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2db095a9dc0cc582d205edf7a1a4550970e39152
Binary files /dev/null and b/test_functions/__pycache__/KeaneBump.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/KeaneBump.cpython-39.pyc b/test_functions/__pycache__/KeaneBump.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9b132ac7c361517516c4f8e97329250c8766fe4c
Binary files /dev/null and b/test_functions/__pycache__/KeaneBump.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Levy.cpython-311.pyc b/test_functions/__pycache__/Levy.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b6f55a4256ba1af1e844f94db633cb42b5c780ec
Binary files /dev/null and b/test_functions/__pycache__/Levy.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/LevyND.cpython-310.pyc b/test_functions/__pycache__/LevyND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1bb4b5eb99c7a6f3e7e12b6eaa4fb1834707ce48
Binary files /dev/null and b/test_functions/__pycache__/LevyND.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/LevyND.cpython-311.pyc b/test_functions/__pycache__/LevyND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b4917acc0be938310e474a448cfb52e4fa045b72
Binary files /dev/null and b/test_functions/__pycache__/LevyND.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/LevyND.cpython-39.pyc b/test_functions/__pycache__/LevyND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..132b09ef70d6973cf8e8be79c08848bca93044a3
Binary files /dev/null and b/test_functions/__pycache__/LevyND.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/MOPTA08_Car.cpython-310.pyc b/test_functions/__pycache__/MOPTA08_Car.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2b570ced71a9ba919a2ddfc082ecd3bd4d02e349
Binary files /dev/null and b/test_functions/__pycache__/MOPTA08_Car.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Mazda.cpython-310.pyc b/test_functions/__pycache__/Mazda.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4ce83bf75eae1535ef66542bf83af43ecadf81dd
Binary files /dev/null and b/test_functions/__pycache__/Mazda.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/MichalewiczND.cpython-310.pyc b/test_functions/__pycache__/MichalewiczND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..65fe456760bee8c2eaace445222d5add4b24b8f1
Binary files /dev/null and b/test_functions/__pycache__/MichalewiczND.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/MichalewiczND.cpython-311.pyc b/test_functions/__pycache__/MichalewiczND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..37d916bdec013df6e18aed1f01b97261cb181216
Binary files /dev/null and b/test_functions/__pycache__/MichalewiczND.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/MichalewiczND.cpython-39.pyc b/test_functions/__pycache__/MichalewiczND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..edd94dbb5dde010f6fa12aca776cfa8db2458e72
Binary files /dev/null and b/test_functions/__pycache__/MichalewiczND.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/PressureVessel.cpython-310.pyc b/test_functions/__pycache__/PressureVessel.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ca85f9ef4ea54aa48e576f4329da7dfc9851688f
Binary files /dev/null and b/test_functions/__pycache__/PressureVessel.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/PressureVessel.cpython-311.pyc b/test_functions/__pycache__/PressureVessel.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..72afd0c05e9667c17add0c054fcf098110bcdfed
Binary files /dev/null and b/test_functions/__pycache__/PressureVessel.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/PressureVessel.cpython-39.pyc b/test_functions/__pycache__/PressureVessel.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8edfc1b685828428b3d262a891d70aabf1a6c1b6
Binary files /dev/null and b/test_functions/__pycache__/PressureVessel.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-310.pyc b/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c0b1c22014f4ca94653068e17dd9b32dac41d58c
Binary files /dev/null and b/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-311.pyc b/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ae8a261c549b4b643b8dd79c14ad914be61ce4de
Binary files /dev/null and b/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-39.pyc b/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e9b627248a13fd78e03f1e3330e5e2f3187d07b7
Binary files /dev/null and b/test_functions/__pycache__/ReinforcedConcreteBeam.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-310.pyc b/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7a5abd79f6cb01056e537f0638515a7c5b6f2329
Binary files /dev/null and b/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-311.pyc b/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9569c67ef77216ee9888c06b5ab0bc8cbe514e42
Binary files /dev/null and b/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-39.pyc b/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2fe0a405202d0ef65b2aad2be6a53e9fa643e476
Binary files /dev/null and b/test_functions/__pycache__/Rosenbrock3DEmbedd.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/RosenbrockND.cpython-310.pyc b/test_functions/__pycache__/RosenbrockND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6baf7e5b553183324429f6802f2ec835d3c3b4f5
Binary files /dev/null and b/test_functions/__pycache__/RosenbrockND.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/RosenbrockND.cpython-311.pyc b/test_functions/__pycache__/RosenbrockND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..02195df22f1275031eceeec17eeef0a76d20da4c
Binary files /dev/null and b/test_functions/__pycache__/RosenbrockND.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/RosenbrockND.cpython-39.pyc b/test_functions/__pycache__/RosenbrockND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..90c014806a559ab3cadd24818f1cbd562b44a497
Binary files /dev/null and b/test_functions/__pycache__/RosenbrockND.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/RosenbrockND2.cpython-39.pyc b/test_functions/__pycache__/RosenbrockND2.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..761d536bb62da050e991c3cd308b54d350a48fef
Binary files /dev/null and b/test_functions/__pycache__/RosenbrockND2.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/SpeedReducer.cpython-310.pyc b/test_functions/__pycache__/SpeedReducer.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7ac44436083104ba683c9584ceade7d83cbf65c1
Binary files /dev/null and b/test_functions/__pycache__/SpeedReducer.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/SpeedReducer.cpython-311.pyc b/test_functions/__pycache__/SpeedReducer.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..89af139741afec84b12a1b3d5772e4fe96cf51d6
Binary files /dev/null and b/test_functions/__pycache__/SpeedReducer.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/SpeedReducer.cpython-39.pyc b/test_functions/__pycache__/SpeedReducer.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..33f1eef604ca36a02e6db838d942ce6c70bef5ab
Binary files /dev/null and b/test_functions/__pycache__/SpeedReducer.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/ThreeTruss.cpython-310.pyc b/test_functions/__pycache__/ThreeTruss.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4529829c8facb666f42e9c472a8ff7b1b3022449
Binary files /dev/null and b/test_functions/__pycache__/ThreeTruss.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/ThreeTruss.cpython-311.pyc b/test_functions/__pycache__/ThreeTruss.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c32e7ffd8c117c108fc673241eb40b49fb70a618
Binary files /dev/null and b/test_functions/__pycache__/ThreeTruss.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/ThreeTruss.cpython-39.pyc b/test_functions/__pycache__/ThreeTruss.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..72341f2a1f9d85712d9b27eba53368bbd56dd28a
Binary files /dev/null and b/test_functions/__pycache__/ThreeTruss.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/Truss10D.cpython-311.pyc b/test_functions/__pycache__/Truss10D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f2ce9f7ae94ced99a12c7cf48bb2de18e417973a
Binary files /dev/null and b/test_functions/__pycache__/Truss10D.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/TrussSolvers.cpython-310.pyc b/test_functions/__pycache__/TrussSolvers.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..986b509ec9446fc5606c259d684c40f0f00bb829
Binary files /dev/null and b/test_functions/__pycache__/TrussSolvers.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/TrussSolvers.cpython-311.pyc b/test_functions/__pycache__/TrussSolvers.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8133676f684c3d6d6be27eedcde7dc6cb495efc7
Binary files /dev/null and b/test_functions/__pycache__/TrussSolvers.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/TrussSolvers.cpython-39.pyc b/test_functions/__pycache__/TrussSolvers.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3ba0c010acbb528ebdab2655ed0efe777078135f
Binary files /dev/null and b/test_functions/__pycache__/TrussSolvers.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/WeldedBeam.cpython-310.pyc b/test_functions/__pycache__/WeldedBeam.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..58227265f3ad3b462f71380a76fee3323d456a06
Binary files /dev/null and b/test_functions/__pycache__/WeldedBeam.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/WeldedBeam.cpython-311.pyc b/test_functions/__pycache__/WeldedBeam.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4c0effba343bddae44173e73f378f7fefbd11eab
Binary files /dev/null and b/test_functions/__pycache__/WeldedBeam.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/WeldedBeam.cpython-39.pyc b/test_functions/__pycache__/WeldedBeam.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..704e00fd46d8d1c6cf465bdcf7be39b5a5c9a3ac
Binary files /dev/null and b/test_functions/__pycache__/WeldedBeam.cpython-39.pyc differ
diff --git a/test_functions/__pycache__/__init__.cpython-310.pyc b/test_functions/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9a94dd323034667264a27ecaa80b5b1c6e19abbd
Binary files /dev/null and b/test_functions/__pycache__/__init__.cpython-310.pyc differ
diff --git a/test_functions/__pycache__/__init__.cpython-311.pyc b/test_functions/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..49576ffe7c31731698a99d4350006bbdc61aa79b
Binary files /dev/null and b/test_functions/__pycache__/__init__.cpython-311.pyc differ
diff --git a/test_functions/__pycache__/__init__.cpython-39.pyc b/test_functions/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4f8d54fd1009f40dac5ea27670b1564d9c0f85a5
Binary files /dev/null and b/test_functions/__pycache__/__init__.cpython-39.pyc differ
diff --git a/test_functions/datasets.py b/test_functions/datasets.py
new file mode 100644
index 0000000000000000000000000000000000000000..cdf7b8ec9d0f027fc2541f1bee8edd921c6e0587
--- /dev/null
+++ b/test_functions/datasets.py
@@ -0,0 +1,68 @@
+# Author: Qiuyi
+
+import torch
+import torch.nn.functional as F
+from sklearn.decomposition import PCA
+
+def cube(n_samples, dim=2):
+ return torch.rand([n_samples, dim])
+
+def sphere(n_samples, dim=1):
+ X = torch.randn([n_samples, dim+1])
+ return F.normalize(X, dim=-1)
+
+def torus(n_samples, R=2, r=1):
+ u, v = (torch.rand([n_samples, 2]) * 2 * torch.pi).chunk(2, -1)
+ x = (R + r * torch.cos(u)) * torch.cos(v)
+ y = (R + r * torch.cos(u)) * torch.sin(v)
+ z = r * torch.sin(u)
+ return torch.cat([x, y, z], dim=-1)
+
+def mobius_strip(n_samples):
+ u, v = torch.rand([n_samples, 2]).chunk(2, -1)
+ u *= 2 * torch.pi
+ x = (1 + v/2 * torch.cos(u/2)) * torch.cos(u)
+ y = (1 + v/2 * torch.cos(u/2)) * torch.sin(u)
+ z = v/2 * torch.sin(u/2)
+ return torch.cat([x, y, z], dim=-1)
+
+def klein_bottle(n_samples, R=2, P=1, e=0.1):
+ u, v = (torch.rand([n_samples, 2]) * 2 * torch.pi).chunk(2, -1)
+ x = R * (torch.cos(u/2) * torch.cos(v) - torch.sin(u/2) * torch.sin(v*2))
+ y = R * (torch.sin(u/2) * torch.cos(v) + torch.cos(u/2) * torch.sin(v*2))
+ z = P * torch.cos(u) * (1 + e * torch.sin(v))
+ w = P * torch.sin(u) * (1 + e * torch.sin(v))
+ return torch.cat([x, y, z, w], dim=-1)
+
+
+################################ Immersions ################################
+# For nonlinearly embedding datasets into high dimensional ambient spaces. #
+############################################################################
+
+def polynomial_immersion(dataset, ambient_dim, weight=(1,1,0)):
+ """
+ The graph of a continous function is homeomorphic to its domain.
+ Immersion is performed by polynomial function.
+ """
+
+ X = (dataset - dataset.mean(0)) / (dataset.std(0) * 2)
+ XX = (X.unsqueeze(1) * X.unsqueeze(2)).flatten(1)
+ XXX = (X.view(len(X), 1, 1, -1) \
+ * X.view(len(X), 1, -1, 1) \
+ * X.view(len(X), -1, 1, 1)).flatten(1)
+
+ in_dim = dataset.size(-1)
+ out_dim = ambient_dim - in_dim
+
+ # 2nd order polynomial function Y = f(X)
+ W1 = torch.randn(X.size(-1), out_dim) * weight[0]
+ W2 = torch.randn(XX.size(-1), out_dim) * weight[1]
+ W3 = torch.randn(XXX.size(-1), out_dim) * weight[2]
+ Y = X @ W1 + XX @ W2 + XXX @ W3
+
+ # rescaling
+ D = torch.cat([dataset, Y], dim=-1) # graph of polynomial f
+ D = torch.as_tensor(PCA(D.size(-1)).fit_transform(D), dtype=torch.float)
+ s = torch.rand(D.size(-1)) * (1-0.5) + 0.5
+ D = D / D.std(0).clip(3e-7) * s
+ return D
\ No newline at end of file
diff --git a/test_functions/input.txt b/test_functions/input.txt
new file mode 100644
index 0000000000000000000000000000000000000000..04b7bb99f00038b55675cf6cce701906c3a68753
--- /dev/null
+++ b/test_functions/input.txt
@@ -0,0 +1,124 @@
+0.7163974642753601
+0.9993265378225802
+0.00681085416469197
+0.49657461047172546
+0.5421959757804871
+0.07028308510780334
+0.7375115156173706
+0.23079676900863894
+0.17524531483650208
+0.4165057837963104
+0.7863314655462468
+0.9103859561629767
+0.9884545207023621
+0.49428999423980713
+0.7333322753519758
+0.3440784960247453
+0.2530369758605957
+0.4683438539505005
+0.7195425033569336
+0.4212913572074431
+0.058185406029224396
+0.06039922311902046
+0.2849200367927551
+0.11604490131139755
+0.8867061209432993
+0.5261104744926556
+0.0431898795068264
+0.3900279998779297
+0.1029452458024025
+0.20407527685165405
+0.1734655201435089
+0.19775275124324224
+0.7156706543915524
+0.04655173287253966
+0.4848773777484894
+0.30312734842300415
+0.4447859227657318
+0.6366506218910217
+0.8890612125396729
+0.7058064453653432
+0.4439832164896989
+0.9059072732925415
+0.9707982540130615
+0.19974938035011292
+0.2055460810661316
+0.2900460958480835
+0.2580410872096335
+0.09955541121486575
+0.1132098063826561
+0.24213725328445435
+0.8225266933441162
+0.42824631929397583
+0.7951440215110779
+0.6829838315960868
+0.16282251477241516
+0.3188931224570868
+0.6323996782302856
+0.6375263929367065
+0.8299118876457214
+0.052584003657102585
+0.38849183992486186
+0.4983891248703003
+0.13332130014896393
+0.556024432182312
+0.4132501184940338
+0.609487771987915
+0.9169092783257323
+0.4322524964809418
+0.366078273140641
+0.05536458277562482
+0.9767963290214539
+0.42411284168974506
+0.2329164743423462
+0.6744847893714905
+0.20683512353720418
+0.2293541160335567
+0.6657138466835022
+0.4732159972190857
+0.522901713848114
+0.11109761893749237
+0.11648011532987006
+0.3706672489643097
+0.9088611602783203
+0.7435321807861328
+0.4555647075176239
+0.03607107698917389
+0.35120466351509094
+0.28899073600769043
+0.345764785939289
+0.10496806353330612
+0.15953752398490906
+0.8993461090965778
+0.5391926443756834
+0.5935213299694775
+0.6363073587417603
+0.7447469660168282
+0.6408606171607971
+0.03914232147871405
+0.7236809310663285
+0.03898954764008522
+0.4348384141921997
+0.06559677971676071
+0.7644200989186132
+0.34992800388839107
+0.5224961802261936
+0.36969325605008013
+0.47937899827957153
+0.423367977142334
+0.11889548599720001
+0.34784603118896484
+0.493608683347702
+0.734581147879136
+0.8358172869987468
+0.784054305684064
+0.9184759259223938
+0.5115121006965637
+0.6107214132737988
+0.4500758945941925
+0.8577175394534933
+0.648746156974023
+0.20206538987318162
+0.4083820879459381
+0.6682699918746948
+0.9255886843723466
diff --git a/test_functions/models.py b/test_functions/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce5e13697e9c81b5ae70132d7aa59673c48c1783
--- /dev/null
+++ b/test_functions/models.py
@@ -0,0 +1,81 @@
+# Author: Qiuyi
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.nn.utils.parametrizations import spectral_norm
+
+
+class _Combo(nn.Module):
+ def forward(self, input):
+ return self.model(input)
+
+class LinearCombo(_Combo):
+ def __init__(self, in_features, out_features, activation=nn.LeakyReLU(0.2)):
+ super().__init__()
+ self.model = nn.Sequential(
+ nn.Linear(in_features, out_features),
+ activation
+ )
+
+class SNLinearCombo(_Combo):
+ def __init__(self, in_features, out_features, activation=nn.LeakyReLU(0.2)):
+ super().__init__()
+ self.model = nn.Sequential(
+ spectral_norm(nn.Linear(in_features, out_features)),
+ activation
+ )
+
+class MLP(nn.Module):
+ """Regular fully connected network generating features.
+
+ Args:
+ in_features: The number of input features.
+ out_feature: The number of output features.
+ layer_width: The widths of the hidden layers.
+ combo: The layer combination to be stacked up.
+
+ Shape:
+ - Input: `(N, H_in)` where H_in = in_features.
+ - Output: `(N, H_out)` where H_out = out_features.
+ """
+ def __init__(
+ self, in_features: int, out_features:int, layer_width: list,
+ combo = LinearCombo
+ ):
+ super().__init__()
+ self.in_features = in_features
+ self.out_features = out_features
+ self.layer_width = list(layer_width)
+ self.model = self._build_model(combo)
+
+ def forward(self, input):
+ return self.model(input)
+
+ def _build_model(self, combo):
+ model = nn.Sequential()
+ idx = -1
+ for idx, (in_ftr, out_ftr) in enumerate(self.layer_sizes[:-1]):
+ model.add_module(str(idx), combo(in_ftr, out_ftr))
+ model.add_module(str(idx+1), nn.Linear(*self.layer_sizes[-1])) # type:ignore
+ return model
+
+ @property
+ def layer_sizes(self):
+ return list(zip([self.in_features] + self.layer_width,
+ self.layer_width + [self.out_features]))
+
+
+class SNMLP(MLP):
+ def __init__(
+ self, in_features: int, out_features: int, layer_width: list,
+ combo=SNLinearCombo):
+ super().__init__(in_features, out_features, layer_width, combo)
+
+ def _build_model(self, combo):
+ model = nn.Sequential()
+ idx = -1
+ for idx, (in_ftr, out_ftr) in enumerate(self.layer_sizes[:-1]):
+ model.add_module(str(idx), combo(in_ftr, out_ftr))
+ model.add_module(str(idx+1), spectral_norm(nn.Linear(*self.layer_sizes[-1]))) # type:ignore
+ return model
\ No newline at end of file
diff --git a/test_functions/mopta08/mopta08_armhf.bin b/test_functions/mopta08/mopta08_armhf.bin
new file mode 100644
index 0000000000000000000000000000000000000000..cec6ee6cda97cb65dc25735c9d1332f863d64ea6
--- /dev/null
+++ b/test_functions/mopta08/mopta08_armhf.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aaffc217b6f52950fed73b22844fcb4cf1a212d30c7b34cbe8e5819b181e6865
+size 98676916
diff --git a/test_functions/mopta08/mopta08_elf32.bin b/test_functions/mopta08/mopta08_elf32.bin
new file mode 100644
index 0000000000000000000000000000000000000000..525400fb6913b8b1afda1ccb958068a054ac5c09
--- /dev/null
+++ b/test_functions/mopta08/mopta08_elf32.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:77b91231c6d4cd22301c30046f082d2ccc3feb7708c3ad8ce0e8526c6d9dd6fd
+size 41566900
diff --git a/test_functions/mopta08/mopta08_elf64.bin b/test_functions/mopta08/mopta08_elf64.bin
new file mode 100644
index 0000000000000000000000000000000000000000..7626bd6233061d500aebf92c416b5219455da259
--- /dev/null
+++ b/test_functions/mopta08/mopta08_elf64.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ad78a256980134c2a84debd4ff15a53534c812f48175577f9155cdd22d6ffb5
+size 58565259
diff --git a/test_functions/mopta08_armhf.bin b/test_functions/mopta08_armhf.bin
new file mode 100644
index 0000000000000000000000000000000000000000..cec6ee6cda97cb65dc25735c9d1332f863d64ea6
--- /dev/null
+++ b/test_functions/mopta08_armhf.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aaffc217b6f52950fed73b22844fcb4cf1a212d30c7b34cbe8e5819b181e6865
+size 98676916
diff --git a/test_functions/mopta08_elf32.bin b/test_functions/mopta08_elf32.bin
new file mode 100644
index 0000000000000000000000000000000000000000..525400fb6913b8b1afda1ccb958068a054ac5c09
--- /dev/null
+++ b/test_functions/mopta08_elf32.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:77b91231c6d4cd22301c30046f082d2ccc3feb7708c3ad8ce0e8526c6d9dd6fd
+size 41566900
diff --git a/test_functions/mopta08_elf64.bin b/test_functions/mopta08_elf64.bin
new file mode 100644
index 0000000000000000000000000000000000000000..7626bd6233061d500aebf92c416b5219455da259
--- /dev/null
+++ b/test_functions/mopta08_elf64.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ad78a256980134c2a84debd4ff15a53534c812f48175577f9155cdd22d6ffb5
+size 58565259
diff --git a/test_functions/output.txt b/test_functions/output.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ea8ebbea515e4d7cc9aa1736bdc07d4cc47c94f3
--- /dev/null
+++ b/test_functions/output.txt
@@ -0,0 +1,69 @@
+ 275.8269862960147520
+ 0.0581879368148583
+ -0.4224788876469802
+ -0.4100756001609912
+ -0.2831170848853234
+ 0.2699228951278810
+ -1.0550134317403717
+ -0.5776263839417214
+ 0.1202652926466964
+ 0.1817594688956431
+ -0.0716889385055011
+ -0.0715675971871180
+ -0.1822306559694091
+ 0.0448120443506189
+ 0.0732765928799186
+ -0.1032779716447456
+ -0.0355737650221428
+ -1.0821081604737763
+ -0.6296112281522713
+ -0.1560505513228053
+ -0.0051366243568498
+ -0.2565902686030815
+ 0.2644912201226844
+ -0.4074594692255518
+ 0.1558972751068895
+ -0.0311400644773215
+ 0.2578687828663207
+ -0.0316915328429528
+ 0.0447342648274453
+ -0.2888168826473282
+ -0.1529795285005182
+ 0.1262431217964213
+ -0.0414781325759517
+ 0.0640072115282357
+ -0.0998162893110580
+ 0.0788383110871106
+ -0.2363975385026639
+ -0.7827769477146995
+ 0.2932004681073357
+ -0.8919873927830351
+ 0.1106674271120884
+ -0.7421986510828914
+ 0.6904273371646028
+ -0.2034334096624295
+ 0.6948452509218510
+ -0.1817762251458310
+ -0.0187207101916000
+ -0.7090126160682828
+ 0.2506156381565486
+ -0.8210869189700183
+ 0.0735200231135342
+ -0.7506638170879651
+ -0.1202114602670871
+ -0.7837846044709865
+ 0.3807067050555524
+ -0.9666812979341586
+ -0.3451832671453948
+ -0.1955997453502872
+ 0.0025315276186700
+ -0.4472045013730331
+ 0.3939839637782457
+ -0.2090385167779976
+ 0.2687026674969071
+ 0.4078406265702717
+ -0.9305182911825091
+ -0.6447835100277725
+ -0.8610497420775397
+ -0.3408482065781069
+ 0.2441401812564077
diff --git a/test_functions/untitled.py b/test_functions/untitled.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions2/.ipynb_checkpoints/Ackley10D-checkpoint.py b/test_functions2/.ipynb_checkpoints/Ackley10D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..bcbdd92651d536b2ce473e5d94d9f7847109c582
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Ackley10D-checkpoint.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley10D: 10D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 10
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley10D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Ackley2D-checkpoint.py b/test_functions2/.ipynb_checkpoints/Ackley2D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed442f5037a6bebce0548f07faeb4bd5bbb5c7f1
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Ackley2D-checkpoint.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley2D: 2D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley2D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley2D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Ackley2DEmbedd-checkpoint.py b/test_functions2/.ipynb_checkpoints/Ackley2DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..09e983a179ba11e87fbaa95599132fa627e2f6c0
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Ackley2DEmbedd-checkpoint.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Ackley2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Ackley2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15-5
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Ackley500D-checkpoint.py b/test_functions2/.ipynb_checkpoints/Ackley500D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee928e3b651d44c0c2b523d1cfbc6ab5d296c93a
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Ackley500D-checkpoint.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def Ackley500D(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) - 1000 # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1) - 115 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley500D_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Ackley6D-checkpoint.py b/test_functions2/.ipynb_checkpoints/Ackley6D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c48a191cd35d9cf785c777aea245f622df5b54c
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Ackley6D-checkpoint.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley6D: 6D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley6D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 6
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley6D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/AckleyND-checkpoint.py b/test_functions2/.ipynb_checkpoints/AckleyND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..638f92e9fb5cb852545b6bae1b7d729e428f3e99
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/AckleyND-checkpoint.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def AckleyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def AckleyND_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Branin2DEmbedd-checkpoint.py b/test_functions2/.ipynb_checkpoints/Branin2DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba11caa4938034d78f3221b465c85a7efa55eb24
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Branin2DEmbedd-checkpoint.py
@@ -0,0 +1,38 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Branin
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Branin2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Branin(negate=True)
+ fun.bounds[0, 0].fill_(-5.0)
+ fun.bounds[1, 0].fill_(10.0)
+ fun.bounds[0, 1].fill_(0.0)
+ fun.bounds[1, 1].fill_(15.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Branin2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Bukin-checkpoint.py b/test_functions2/.ipynb_checkpoints/Bukin-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..562576be84619a079760227f4d009334e4151ae9
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Bukin-checkpoint.py
@@ -0,0 +1,46 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+# class Bukin(SyntheticTestFunction):
+
+# dim = 2
+# _bounds = [(-15.0, -5.0), (-3.0, 3.0)]
+# _optimal_value = 0.0
+# _optimizers = [(-10.0, 1.0)]
+# _check_grad_at_opt: bool = False
+
+
+# [docs]
+# def evaluate_true(self, X: Tensor) -> Tensor:
+# part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+# part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+# return part1 + part2
+
+
+def Bukin(X):
+
+ part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+ part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+ fx = part1 + part2
+
+ return fx
+
+def Bukin_Scaling(X):
+ X_scaled = torch.zeros(X.shape)
+
+ X_scaled[:,0] = -(X[..., 0]*10+5)
+ X_scaled[:,1] = X[..., 0]*6-3
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/CantileverBeam-checkpoint.py b/test_functions2/.ipynb_checkpoints/CantileverBeam-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0599ce7836e96aa76ce1fc59780e34f61d8e170
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/CantileverBeam-checkpoint.py
@@ -0,0 +1,193 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CantileverBeam: 10D objective, 11 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+
+
+
+
+
+def CantileverBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+
+ P = 50000
+ E = 2*107
+ L = 100
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1*x6*L + x2*x7*L + x3*x8*L + x4*x9*L + x5*x10*L )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 600 * P / (x5*x10*x10) - 14000
+ g2 = 6 * P * (L*2) / (x4*x9*x9) - 14000
+ g3 = 6 * P * (L*3) / (x3*x8*x8) - 14000
+ g4 = 6 * P * (L*4) / (x2*x7*x7) - 14000
+ g5 = 6 * P * (L*5) / (x1*x6*x6) - 14000
+ g6 = P* L**3 * (1/L + 7/L + 19/L + 37/L + 61/L) / (3*E) -2.7
+ g7 = x10/x5 - 20
+ g8 = x9/x4 - 20
+ g9 = x8/x3 - 20
+ g10 = x7/x2 - 20
+ g11 = x6/x1 - 20
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+ gx10.append( g10 )
+ gx11.append( g11 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx10 = torch.tensor(gx10)
+ gx10 = gx4.reshape((n, 1))
+
+ gx11 = torch.tensor(gx11)
+ gx11 = gx4.reshape((n, 1))
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10, gx11), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def CantileverBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ x1 = (X[:,0] * (5-1) + 1).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (5-1) + 1).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (5-1) + 1).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (5-1) + 1).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (5-1) + 1).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (65-30) + 30).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (65-30) + 30).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (65-30) + 30).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (65-30) + 30).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (65-30) + 30).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Car-checkpoint.py b/test_functions2/.ipynb_checkpoints/Car-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7193b96109cd5fc9c3f4ff3a5661bb344338e60
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Car-checkpoint.py
@@ -0,0 +1,253 @@
+import torch
+import numpy as np
+
+
+#
+#
+# Car: 11D objective, 10 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def Car(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def Car_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ x1 = (X[:,0] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (1.35-0.45) + 0.45).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (-20)).reshape(X.shape[0],1)
+ x11 = (X[:,10] * (-20)).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11), dim=1)
+ return X_scaled
+
+
+
+
+
+
+def Car_softpen(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+ cost = gx
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ fx = fx + cost
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/CompressionSpring-checkpoint.py b/test_functions2/.ipynb_checkpoints/CompressionSpring-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5443f7da043f74660ae96e1c1867f69101013d4
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/CompressionSpring-checkpoint.py
@@ -0,0 +1,100 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CompressionSpring: 8D objective, 6 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def CompressionSpring(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ d = x[0]
+ D = x[1]
+ N = x[2]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( (N+2)*D*d**2 )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 1 - ( D*D*D * N / (71785* d*d*d*d) )
+ g2 = (4*D*D - D*d) / (12566 * (D*d*d*d - d*d*d*d)) + 1/(5108*d*d) - 1
+ g3 = 1 - 140.45*d / (D*D * N)
+ g4 = (D+d)/1.5 - 1
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+
+ return gx, fx
+
+
+
+def CompressionSpring_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ d = (X[:,0] * ( 1 - 0.05 ) + 0.05 ).reshape(X.shape[0],1)
+ D = (X[:,1] * ( 1.3 - 0.25 ) + 0.25 ).reshape(X.shape[0],1)
+ N = (X[:,2] * ( 15 - 2 ) + 2 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((d, D, N), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/DixonPriceND-checkpoint.py b/test_functions2/.ipynb_checkpoints/DixonPriceND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406802fb9029db8327a08acf6601783ba9d5a51
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/DixonPriceND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DixonPriceND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = DixonPrice(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def DixonPriceND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/DummyFixConsDim-checkpoint.py b/test_functions2/.ipynb_checkpoints/DummyFixConsDim-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..de6e1b6b1ad0683d3064bc42d6a58c62c905d4ab
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/DummyFixConsDim-checkpoint.py
@@ -0,0 +1,28 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DummyFixConsDim(individuals):
+ n = individuals.size(0)
+ GX = torch.rand(n, 20)
+ Y = torch.rand(n, 1)
+
+ return GX, Y
+
+
+
+def DummyFixConsDim_Scaling(X):
+
+ X_scaled = X
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Finder24-checkpoint.py b/test_functions2/.ipynb_checkpoints/Finder24-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..9f7a4752b9e54183f145947fa4f06c51283ca754
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Finder24-checkpoint.py
@@ -0,0 +1,172 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ # START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z, n_candidate=None):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+
+ if n_candidate==None:
+ n_candidate = 2000
+
+ Z_samples = sobol.draw(n_candidate)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Finder24_no_timer-checkpoint.py b/test_functions2/.ipynb_checkpoints/Finder24_no_timer-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd3e0475a77fe66303e3dd345bc0aec41ece7fe5
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Finder24_no_timer-checkpoint.py
@@ -0,0 +1,173 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_Adam_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+ Z_samples = sobol.draw(2000)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/GKXWC1-checkpoint.py b/test_functions2/.ipynb_checkpoints/GKXWC1-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..2dfa59da9637b4c64377a6e6471c742f9f9c53f3
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/GKXWC1-checkpoint.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC1: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+
+def GKXWC1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+ for x in individuals:
+ g = np.cos(x[0])*np.cos(x[1]) - np.sin(x[0])*np.sin(x[1]) -0.5
+ fx.append( - np.cos(2*x[0])*np.cos(x[1]) - np.sin(x[0]) )
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+ return gx, fx
+
+
+def GKXWC1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/GKXWC2-checkpoint.py b/test_functions2/.ipynb_checkpoints/GKXWC2-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..5db203c32b693009590b8e9b9b79177d3cc3bba9
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/GKXWC2-checkpoint.py
@@ -0,0 +1,80 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC2: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+def GKXWC2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ g = np.sin(x[0])*np.sin(x[1]) + 0.95
+ fx.append( - np.sin(x[0]) - x[1] ) # maximize -(x1^2 +x 2^2)
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+def GKXWC2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Griewank2DEmbedd-checkpoint.py b/test_functions2/.ipynb_checkpoints/Griewank2DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e6128b1f5987182c740bab54875152b58635979
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Griewank2DEmbedd-checkpoint.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Griewank2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Griewank2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled = X_scaled * 1200 - 600
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/GriewankND-checkpoint.py b/test_functions2/.ipynb_checkpoints/GriewankND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406c4f067885c9d6c726f526688c222b89c8a3a
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/GriewankND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def GriewankND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def GriewankND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*1200-600
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Hartmann6DEmbedd-checkpoint.py b/test_functions2/.ipynb_checkpoints/Hartmann6DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..94115986eb19db5747d36fcd38d7ffc5308af125
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Hartmann6DEmbedd-checkpoint.py
@@ -0,0 +1,35 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Hartmann
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Hartmann6DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[0,1,2,3,4,5]]
+ n = X.size(0)
+ dimm = 6
+ fun = Hartmann(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(1.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Hartmann6DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/HeatExchanger-checkpoint.py b/test_functions2/.ipynb_checkpoints/HeatExchanger-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f74bb6ed047a5537a898628f467e732d71e9669
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/HeatExchanger-checkpoint.py
@@ -0,0 +1,191 @@
+import torch
+import numpy as np
+
+#
+#
+# HeatExchanger: 8D objective, 6 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+def HeatExchanger(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1+x2+x3 )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 0.0025 * (x4+x6) - 1
+ g2 = 0.0025 * (x5 + x7 - x4) - 1
+ g3 = 0.01 *(x8-x5) - 1
+ g4 = 833.33252*x4 + 100*x1 - x1*x6 - 83333.333
+ g5 = 1250*x5 + x2*x4 - x2*x7 - 125*x4
+ g6 = x3*x5 - 2500*x5 - x3*x8 + 125*10000
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6), 1)
+
+
+ return gx, fx
+
+
+
+
+
+def HeatExchanger_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ x1 = (X[:,0] * (10000-100) + 100).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1000-10) + 10).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1000-10) + 10).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1000-10) + 10).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1000-10) + 10).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (1000-10) + 10).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/JLH1-checkpoint.py b/test_functions2/.ipynb_checkpoints/JLH1-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..27b7f05394a22a18d0349cbe2632c31c471a83b7
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/JLH1-checkpoint.py
@@ -0,0 +1,57 @@
+import torch
+import numpy as np
+
+#
+# JLH1: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+def JLH1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+ test_function = (- (x[0]-0.5)**2 - (x[1]-0.5)**2 )
+ fx.append(test_function)
+ gx.append( x[0] + x[1] - 0.75 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+
+
+def JLH1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/JLH2-checkpoint.py b/test_functions2/.ipynb_checkpoints/JLH2-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ce7c5e5e65c8fbfda31d4485babc0a84bf6f1aa
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/JLH2-checkpoint.py
@@ -0,0 +1,68 @@
+import torch
+import numpy as np
+
+
+#
+# JLH2: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+
+def JLH2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( np.cos(2*x[0])*np.cos(x[1]) + np.sin(x[0]) )
+
+ fx.append(test_function)
+ gx.append( ((x[0]+5)**2)/4 + (x[1]**2)/100 -2.5 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+def JLH2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ # X = individuals
+ X1 = X[:,0].reshape(X.size(0),1)
+ X1 = X1*5-5
+ X2 = X[:,1].reshape(X.size(0),1)
+ X2 = X2*10-5
+ X_scaled = torch.tensor(np.concatenate((X1,X2), axis=1))
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/KeaneBump-checkpoint.py b/test_functions2/.ipynb_checkpoints/KeaneBump-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ff354c8c76334acb87fbbaac3baf79d1ac2fa23
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/KeaneBump-checkpoint.py
@@ -0,0 +1,88 @@
+import torch
+import numpy as np
+
+#
+#
+# KeaneBump: N-D objective (can take data of different dimention; we use 18),
+# 2 constraints
+#
+# Reference:
+# Keane A (1994) Experiences with optimizers in
+# structural design. In: Proceedings of the con-
+# ference on adaptive computing in engineering
+# design and control, pp 14–27
+#
+#
+
+
+
+def KeaneBump(X):
+
+
+
+ fx = torch.zeros(X.shape[0], 1)
+ gx1 = torch.zeros(X.shape[0], 1)
+ gx2 = torch.zeros(X.shape[0], 1)
+
+
+
+ for i in range(X.shape[0]):
+ x = X[i,:]
+
+ cos4 = 0
+ cos2 = 1
+ sq_denom = 0
+
+ pi_sum = 1
+ sigma_sum = 0
+
+ for j in range(X.shape[1]):
+ cos4 += torch.cos(x[j]) ** 4
+ cos2 *= torch.cos(x[j]) ** 2
+ sq_denom += (j+1) * (x[j])**2
+
+ pi_sum *= x[j]
+ sigma_sum += x[j]
+
+
+ # Objective
+ test_function = torch.abs( (cos4 - 2*cos2) / torch.sqrt(sq_denom) )
+ fx[i] = test_function
+
+ # Constraints
+ gx1[i] = 0.75 - pi_sum
+ gx2[i] = sigma_sum - 7.5* (X.shape[1])
+
+ gx = torch.cat((gx1, gx2), 1)
+ return gx, fx
+
+
+
+
+
+def KeaneBump_Scaling(X):
+
+ X_scaled = X*10
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/LevyND-checkpoint.py b/test_functions2/.ipynb_checkpoints/LevyND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b0c6e40d653c0b964655eb80c5d87787506ec3a
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/LevyND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Levy
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def LevyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Levy(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def LevyND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/MOPTA08_Car-checkpoint.py b/test_functions2/.ipynb_checkpoints/MOPTA08_Car-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..09894738e0c6f340e6feb5cc8119726fd81ac95c
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/MOPTA08_Car-checkpoint.py
@@ -0,0 +1,133 @@
+import os
+import subprocess
+import sys
+import tempfile
+from pathlib import Path
+from platform import machine
+
+import numpy as np
+import torch
+import stat
+
+
+def MOPTA08_Car_single(x):
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ sysarch = 64 if sys.maxsize > 2 ** 32 else 32
+ # machine = machine().lower()
+
+ # if machine == "armv7l":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_armhf.bin"
+ # elif machine == "x86_64":
+ # assert sysarch == 64, "Not supported"
+ # mopta_exectutable = "mopta08_elf64.bin"
+ # elif machine == "i386":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_elf32.bin"
+ # else:
+ # raise RuntimeError("Machine with this architecture is not supported")
+
+ machine = "x86_64"
+ mopta_exectutable = "mopta08_elf64.bin"
+
+ mopta_full_path = os.path.join(
+ "mopta08", mopta_exectutable
+ )
+ # print(mopta_full_path)
+
+ directory_file_descriptor = tempfile.TemporaryDirectory()
+ # directory_name = directory_file_descriptor.name
+ directory_name = Path(__file__).parent
+
+ ##########################################################################################
+ # Input here
+ # if x == None:
+ # x = np.random.rand(124)
+ # print(x.shape)
+ ##########################################################################################
+ with open(os.path.join(directory_name, "input.txt"), "w+") as tmp_file:
+ for _x in x:
+ tmp_file.write(f"{_x}\n")
+ popen = subprocess.Popen(
+ mopta_full_path,
+ # '#!/home/rosen/Dropbox (MIT)/Rosen_DeC0De/MOPTA_Test/mopta08/mopta08_elf64.bin',
+ stdout=subprocess.PIPE,
+ cwd=directory_name,
+ shell=True,
+ )
+ popen.wait()
+
+ with open(os.path.join(directory_name, "output.txt"), "r") as tmp_file:
+ output = (
+ tmp_file
+ .read()
+ .split("\n")
+ )
+ # print(output)
+ # print(x)
+ # print(output)
+ output = [x.strip() for x in output]
+ output = np.array([float(x) for x in output if len(x) > 0])
+ value = output[0]
+ constraints = output[1:]
+ # print(value, constraints)
+
+ return constraints, value
+
+
+
+def MOPTA08_Car(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = -fx
+
+ return GX, FX
+
+
+
+
+def MOPTA08_Car_softpen(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = fx
+
+ cost = GX
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ FX = FX + cost
+
+ return GX, -FX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Mazda-checkpoint.py b/test_functions2/.ipynb_checkpoints/Mazda-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..52f586cbf98f52df78c8d6e9ba0045535a113602
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Mazda-checkpoint.py
@@ -0,0 +1,242 @@
+import os
+import subprocess
+import stat
+import pandas as pd
+import torch
+import numpy as np
+
+
+
+def Mazda(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+def Mazda_softpen(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+
+ cost = cons_data_tensor
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ objs_data_tensor = objs_data_tensor + cost
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/MichalewiczND-checkpoint.py b/test_functions2/.ipynb_checkpoints/MichalewiczND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..55cd932393e207d7deb9ddebde8b93a408c48400
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/MichalewiczND-checkpoint.py
@@ -0,0 +1,59 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def MichalewiczND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Michalewicz(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(math.pi)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def MichalewiczND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*math.pi
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/PressureVessel-checkpoint.py b/test_functions2/.ipynb_checkpoints/PressureVessel-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..eeefcd177c3ec800e56c2a3b1b9ca4c573e79990
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/PressureVessel-checkpoint.py
@@ -0,0 +1,169 @@
+import torch
+import numpy as np
+
+#
+#
+# PressureVessel: 4D objective, 4 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def PressureVessel(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ C1 = 0.6224
+ C2 = 1.7781
+ C3 = 3.1661
+ C4 = 19.84
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ Ts = x[0]
+ Th = x[1]
+ R = x[2]
+ L = x[3]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( C1*Ts*R*L + C2*Th*R*R + C3*Ts*Ts*L + C4*Ts*Ts*R )
+ fx.append(test_function)
+
+
+ g1 = -Ts + 0.0193*R
+ g2 = -Th + 0.00954*R
+ g3 = (-1)*np.pi*R*R*L + (-1)*4/3*np.pi*R*R*R + 750*1728
+ g4 = L-240
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def PressureVessel_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ Ts = (X[:,0] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ Th = (X[:,1] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ R = (X[:,2] * (200-10) + 10).reshape(X.shape[0],1)
+ L = (X[:,3] * (200-10) ).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((Ts, Th, R, L), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/ReinforcedConcreteBeam-checkpoint.py b/test_functions2/.ipynb_checkpoints/ReinforcedConcreteBeam-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1729e66ee7ac88f8fe7fdc60b984b8ba6d784a72
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/ReinforcedConcreteBeam-checkpoint.py
@@ -0,0 +1,90 @@
+import torch
+import numpy as np
+
+#
+#
+# ReinforcedConcreteBeam: 3D objective, 9 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def ReinforcedConcreteBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ As = x[0]
+ h = x[1]
+ b = x[2]
+
+
+ test_function = - ( 29.4*As + 0.6*b*h )
+ fx.append(test_function)
+
+ g1 = h/b - 4
+ g2 = 180 + 7.35*As*As/b - As*h
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def ReinforcedConcreteBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ As = (X[:,0] * (15-0.2) + 0.2).reshape(X.shape[0],1)
+ b = (X[:,1] * (40-28) +28).reshape(X.shape[0],1)
+ h = (X[:,2] * 5 + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((As, b, h), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Rosenbrock3DEmbedd-checkpoint.py b/test_functions2/.ipynb_checkpoints/Rosenbrock3DEmbedd-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1625595859baca53628812cede1b6f68f8e7ea14
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Rosenbrock3DEmbedd-checkpoint.py
@@ -0,0 +1,40 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Rosenbrock3DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2,3]]
+ n = X.size(0)
+ dimm = 3
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-2.0)
+ fun.bounds[1, :].fill_(2.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Rosenbrock3DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+
+ X_scaled[:,1] = X_scaled[:,1]*4 - 2
+ X_scaled[:,2] = X_scaled[:,2]*4 - 2
+ X_scaled[:,3] = X_scaled[:,3]*4 - 2
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/RosenbrockND-checkpoint.py b/test_functions2/.ipynb_checkpoints/RosenbrockND-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb46001f9d022a9a9f4a73633f2a89dc882f44a3
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/RosenbrockND-checkpoint.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def RosenbrockND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/RosenbrockND2-checkpoint.py b/test_functions2/.ipynb_checkpoints/RosenbrockND2-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..635099799fbf64f4b501d187b19eecdd63c2e417
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/RosenbrockND2-checkpoint.py
@@ -0,0 +1,56 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock, Levy, DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND2(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+
+
+ Rosenbrockfun = Rosenbrock(dim=dimm, negate=True)
+ Rosenbrockfun.bounds[0, :].fill_(-3.0)
+ Rosenbrockfun.bounds[1, :].fill_(5.0)
+
+ fx = Rosenbrockfun(individuals)
+ fx = fx.reshape(individuals.shape[0],1)
+
+ Levyfun = Levy(dim=dimm, negate=False)
+ Levyfun.bounds[0, :].fill_(-3.0)
+ Levyfun.bounds[1, :].fill_(5.0)
+
+
+ DixonPricefun = DixonPrice(dim=dimm, negate=False)
+ DixonPricefun.bounds[0, :].fill_(-3.0)
+ DixonPricefun.bounds[1, :].fill_(5.0)
+
+
+ G1 = Levyfun(individuals) -1e3
+ G2 = DixonPricefun(individuals) -4e7
+
+ gx = torch.cat((G1.reshape(individuals.shape[0],1), G2.reshape(individuals.shape[0],1)), 1)
+
+
+ return gx, fx
+
+
+def RosenbrockND2_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*8-3
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/SpeedReducer-checkpoint.py b/test_functions2/.ipynb_checkpoints/SpeedReducer-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b8ec3cbabd1652d9d75361e332658fb06e7ff6b
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/SpeedReducer-checkpoint.py
@@ -0,0 +1,188 @@
+import torch
+import numpy as np
+
+#
+#
+# SpeedReducer: 7D objective, 9 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+def SpeedReducer(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ b = x[0]
+ m = x[1]
+ z = x[2]
+ L1 = x[3]
+ L2 = x[4]
+ d1 = x[5]
+ d2 = x[6]
+
+ C1 = 0.7854*b*m*m
+ C2 = 3.3333*z*z + 14.9334*z - 43.0934
+ C3 = 1.508*b*(d1*d1 + d2*d2)
+ C4 = 7.4777*(d1*d1*d1 + d2*d2*d2)
+ C5 = 0.7854*(L1*d1*d1 + L2*d2*d2)
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 0.7854*b*m*m * (3.3333*z*z + 14.9334*z - 43.0934) - 1.508*b*(d1*d1 + d2*d2) + 7.4777*(d1*d1*d1 + d2*d2*d2) + 0.7854*(L1*d1*d1 + L2*d2*d2) )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 27/(b*m*m*z) - 1
+ g2 = 397.5/(b*m*m*z*z) - 1
+
+ g3 = 1.93*L1**3 /(m*z *d1**4) - 1
+ g4 = 1.93*L2**3 /(m*z *d2**4) - 1
+
+ g5 = np.sqrt( (745*L1/(m*z))**2 + 1.69*1e6 ) / (110*d1**3) -1
+ g6 = np.sqrt( (745*L2/(m*z))**2 + 157.5*1e6 ) / (85*d2**3) -1
+ g7 = m*z/40 - 1
+ g8 = 5*m/(b) - 1
+ g9 = b/(12*m) -1
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9), 1)
+
+
+ return gx, fx
+
+
+
+def SpeedReducer_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ b = (X[:,0] * ( 3.6 - 2.6 ) + 2.6).reshape(X.shape[0],1)
+ m = (X[:,1] * ( 0.8 - 0.7 ) + 0.7).reshape(X.shape[0],1)
+ z = (X[:,2] * ( 28 - 17 ) + 17).reshape(X.shape[0],1)
+ L1 = (X[:,3] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ L2 = (X[:,4] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ d1 = (X[:,5] * ( 3.9 - 2.9 ) + 2.9).reshape(X.shape[0],1)
+ d2 = (X[:,6] * ( 5.5 - 5 ) + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((b, m, z, L1, L2, d1, d2), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/ThreeTruss-checkpoint.py b/test_functions2/.ipynb_checkpoints/ThreeTruss-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e4b3f2ef3416ea17b6626d2ea87c2dd7a9c2362
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/ThreeTruss-checkpoint.py
@@ -0,0 +1,144 @@
+import torch
+import numpy as np
+
+
+#
+#
+# ThreeTruss: 2D objective, 3 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+def ThreeTruss(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ x1 = x[0]
+ x2 = x[1]
+
+ if x1 <=1e-5:
+ x1 = 1e-5
+ if x2 <=1e-5:
+ x2 = 1e-5
+
+ L = 100
+ P = 2
+ sigma = 2
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 2*np.sqrt(2)*x1 + x2 ) * L
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = ( np.sqrt(2)*x1 + x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g2 = ( x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g3 = ( 1 ) / (x1 + np.sqrt(2)*x2) * P - sigma
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def ThreeTruss_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Truss10D-checkpoint.py b/test_functions2/.ipynb_checkpoints/Truss10D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc0ea12f999aa1d58eb4516b4fc08112f711583b
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Truss10D-checkpoint.py
@@ -0,0 +1,66 @@
+
+from TrussSolvers import *
+import torch
+import numpy as np
+
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(individuals[ii,:])
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/TrussSolvers-checkpoint.py b/test_functions2/.ipynb_checkpoints/TrussSolvers-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec6d915060eeaacae4989257c47b9212c1f3e235
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/TrussSolvers-checkpoint.py
@@ -0,0 +1,2958 @@
+import matplotlib.pyplot as plt
+import torch
+import numpy as np
+
+from slientruss3d.truss import Truss
+from slientruss3d.type import SupportType, MemberType
+from slientruss3d.plot import TrussPlotter
+
+
+
+
+
+def TestPlot(truss):
+ # -------------------- Global variables --------------------
+ # Files settings:
+ TEST_FILE_NUMBER = 25
+ TEST_LOAD_CASE = 0
+ TEST_INPUT_FILE = f"./data/bar-{TEST_FILE_NUMBER}_output_{TEST_LOAD_CASE}.json"
+ TEST_PLOT_SAVE_PATH = f"./plot/bar-{TEST_FILE_NUMBER}_plot_{TEST_LOAD_CASE}.png"
+
+ # Truss dimension setting:
+ TRUSS_DIMENSION = 3
+
+ # Figure layout settings:
+ IS_SAVE_PLOT = False # Whether to save truss figure or not.
+ IS_EQUAL_AXIS = True # Whether to use actual aspect ratio in the truss figure or not.
+ IS_PLOT_STRESS = True # If True, the color of each displaced member gives expression to [stress]. Otherwise, [force magnitude].
+ MAX_SCALED_DISPLACEMENT = 15 # Scale the max value of all dimensions of displacements.
+ MAX_SCALED_FORCE = 50 # Scale the max value of all dimensions of force arrows.
+ POINT_SIZE_SCALE_FACTOR = 1 # Scale the default size of joint point in the truss figure.
+ ARROW_SIZE_SCALE_FACTOR = 1 # Scale the default size of force arrow in the truss figure.
+ # ----------------------------------------------------------
+
+ # Truss object:
+ # truss = Truss(dim=TRUSS_DIMENSION)
+
+ # You could directly read the output .json file.
+ # truss.LoadFromJSON(TEST_INPUT_FILE, isOutputFile=True)
+
+ # Show or save the structural analysis result figure:
+ TrussPlotter(truss,
+ isEqualAxis=IS_EQUAL_AXIS,
+ isPlotStress=IS_PLOT_STRESS,
+ maxScaledDisplace=MAX_SCALED_DISPLACEMENT,
+ maxScaledForce=MAX_SCALED_FORCE,
+ pointScale=POINT_SIZE_SCALE_FACTOR,
+ arrowScale=ARROW_SIZE_SCALE_FACTOR).Plot(IS_SAVE_PLOT, TEST_PLOT_SAVE_PATH)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss10bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(0, 0),
+ (360, 0),
+ (720, 0),
+ (0, 360),
+ (360, 360),
+ (720, 360)
+ ]
+
+
+ supports = [SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ ]
+ forces = [(1, (0, -1e5)), (2, (0, -1e5))]
+
+
+ members = [(0, 1),
+ (0, 4),
+ (1, 2),
+ (1, 3),
+ (1, 4),
+ (1, 5),
+ (2, 4),
+ (2, 5),
+ (3, 4),
+ (4, 5)
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # Default: 0.1, 1e7, 1
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss25bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(62.5, 100, 200),
+ (137.5, 100, 200),
+ (62.5, 137.5, 100),
+ (137.5, 137.5, 100),
+ (137.5, 62.5, 100),
+ (62.5, 62.5, 100),
+ (0, 200, 0),
+ (200, 200, 0),
+ (200, 0, 0),
+ (0, 0, 0)
+ ]
+
+
+ supports = [SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+ forces = [(0, (1000, 20000, -5000)),
+ (1, (0, -20000, -5000)),
+ (2, (500, 0, 0)),
+ (5, (500, 0, 0)),
+ ]
+
+
+ members = [(0, 1),
+ (0, 3),
+ (1, 2),
+ (0, 4),
+ (1, 5),
+ (0, 2),
+ (0, 5),
+ (1, 3),
+ (1, 4),
+ (2, 5),
+ (3, 4),
+ (2, 3),
+ (4, 5),
+ (2, 9),
+ (5, 6),
+ (3, 8),
+ (4, 7),
+ (2, 7),
+ (3, 6),
+ (5, 8),
+ (4, 9),
+ (2, 6),
+ (3, 7),
+ (4, 8),
+ (5, 9),
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+
+ # Default: 0.1, 1e7, .1
+
+ memberType = MemberType(A[index].item(), 3e7, .283)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), .283)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 3e7, Rho[index].item())
+
+
+
+ # memberType = MemberType(A[index].item(), 1e7, .1)
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+
+def Truss47bar(A, E, Rho, version):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(-60, 0),
+ (60, 0),
+ (-60, 120),
+ (60, 120),
+ (-60, 240),
+ (60, 240),
+ (-60, 360),
+ (60, 360),
+ (-30, 420),
+ (30, 420),
+ (-30, 480),
+ (30, 480),
+ (-30, 540),
+ (30, 540),
+ (-90, 570),
+ (90, 570),
+ (-150, 600),
+ (-90, 600),
+ (-30, 600),
+ (30, 600),
+ (90, 600),
+ (150, 600)]
+
+ supports = [SupportType.PIN, SupportType.PIN,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO]
+
+
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ if version == 1:
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ elif version == 2:
+ forces = [(16, (6000, -14000))]
+
+ elif version == 3:
+ forces = [(21, (6000, -14000))]
+
+
+
+
+ members = [(0, 2), (0, 3), (1, 2), (1, 3),
+ (2, 3), (2, 4), (2, 5), (3, 4), (3, 5),
+ (4, 5), (4, 6), (4, 7), (5, 6), (5, 7),
+ (6, 7), (6, 8), (6, 9), (7, 8), (7, 9), (8, 9),
+ (8, 10), (8, 11), (9, 10), (9, 11),
+ (10, 11), (10, 12), (10, 13), (11, 12), (11, 13),
+ (12, 13), (12, 14), (12, 18), (12, 19),
+ (13, 18), (13, 19), (13, 15), (14, 16),
+ (14, 17), (14, 18), (15, 19), (15, 20),
+ (15, 21), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21)]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+
+ # Default: 0.1, 300000000.0, 0.3
+
+ memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.3)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 300000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss120bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 275.59),
+ (273.26, 0.0, 230.31),
+ (236.65010183813573, 136.62999999999997, 230.31),
+ (136.62999999999997, 236.65010183813573, 230.31),
+ (0.0, 273.26, 230.31),
+ (-136.62999999999997, 236.65010183813573, 230.31),
+ (-236.65010183813573, 136.62999999999997, 230.31),
+ (-273.26, 0.0, 230.31),
+ (-236.65010183813573, -136.62999999999997, 230.31),
+ (-136.62999999999997, -236.65010183813573, 230.31),
+ (0.0, -273.26, 230.31),
+ (136.62999999999997, -236.65010183813573, 230.31),
+ (236.65010183813573, -136.62999999999997, 230.31),
+ (492.12, 0.0, 118.11),
+ (475.3514176333763, 127.37002847585251, 118.11),
+ (426.18842171039796, 246.05999999999997, 118.11),
+ (347.9813891575237, 347.9813891575237, 118.11),
+ (246.05999999999997, 426.18842171039796, 118.11),
+ (127.37002847585251, 475.3514176333763, 118.11),
+ (0.0, 492.12, 118.11),
+ (-127.37002847585251, 475.3514176333763, 118.11),
+ (-246.05999999999997, 426.18842171039796, 118.11),
+ (-347.9813891575237, 347.9813891575237, 118.11),
+ (-426.18842171039796, 246.05999999999997, 118.11),
+ (-475.3514176333763, 127.37002847585251, 118.11),
+ (-492.12, 0.0, 118.11),
+ (-475.3514176333763, -127.37002847585251, 118.11),
+ (-426.18842171039796, -246.05999999999997, 118.11),
+ (-347.9813891575237, -347.9813891575237, 118.11),
+ (-246.05999999999997, -426.18842171039796, 118.11),
+ (-127.37002847585251, -475.3514176333763, 118.11),
+ (0.0, -492.12, 118.11),
+ (127.37002847585251, -475.3514176333763, 118.11),
+ (246.05999999999997, -426.18842171039796, 118.11),
+ (347.9813891575237, -347.9813891575237, 118.11),
+ (426.18842171039796, -246.05999999999997, 118.11),
+ (475.3514176333763, -127.37002847585251, 118.11),
+ (625.59, 0.0, 0.0),
+ (541.7768323535071, 312.79499999999996, 0.0),
+ (312.79499999999996, 541.7768323535071, 0.0),
+ (0.0, 625.59, 0.0),
+ (-312.79499999999996, 541.7768323535071, 0.0),
+ (-541.7768323535071, 312.79499999999996, 0.0),
+ (-625.59, 0.0, 0.0),
+ (-541.7768323535071, -312.79499999999996, 0.0),
+ (-312.79499999999996, -541.7768323535071, 0.0),
+ (0.0, -625.59, 0.0),
+ (312.79499999999996, -541.7768323535071, 0.0),
+ (541.7768323535071, -312.79499999999996, 0.0)
+ ]
+
+ supports = [
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+
+ # print(len(joints))
+ # print(len(supports))
+
+
+
+ forces = [
+ (0, (0.0, 0.0, -13490.0)),
+ (1, (0.0, 0.0, -6744.0)),
+ (2, (0.0, 0.0, -6744.0)),
+ (3, (0.0, 0.0, -6744.0)),
+ (4, (0.0, 0.0, -6744.0)),
+ (5, (0.0, 0.0, -6744.0)),
+ (6, (0.0, 0.0, -6744.0)),
+ (7, (0.0, 0.0, -6744.0)),
+ (8, (0.0, 0.0, -6744.0)),
+ (9, (0.0, 0.0, -6744.0)),
+ (10, (0.0, 0.0, -6744.0)),
+ (11, (0.0, 0.0, -6744.0)),
+ (12, (0.0, 0.0, -6744.0)),
+ (13, (0.0, 0.0, -6744.0)),
+ (14, (0.0, 0.0, -2248.0)),
+ (15, (0.0, 0.0, -2248.0)),
+ (16, (0.0, 0.0, -2248.0)),
+ (17, (0.0, 0.0, -2248.0)),
+ (18, (0.0, 0.0, -2248.0)),
+ (19, (0.0, 0.0, -2248.0)),
+ (20, (0.0, 0.0, -2248.0)),
+ (21, (0.0, 0.0, -2248.0)),
+ (22, (0.0, 0.0, -2248.0)),
+ (23, (0.0, 0.0, -2248.0)),
+ (24, (0.0, 0.0, -2248.0)),
+ (25, (0.0, 0.0, -2248.0)),
+ (26, (0.0, 0.0, -2248.0)),
+ (27, (0.0, 0.0, -2248.0)),
+ (28, (0.0, 0.0, -2248.0)),
+ (29, (0.0, 0.0, -2248.0)),
+ (30, (0.0, 0.0, -2248.0)),
+ (31, (0.0, 0.0, -2248.0)),
+ (32, (0.0, 0.0, -2248.0)),
+ (33, (0.0, 0.0, -2248.0)),
+ (34, (0.0, 0.0, -2248.0)),
+ (35, (0.0, 0.0, -2248.0)),
+ (36, (0.0, 0.0, -2248.0))
+ ]
+
+
+
+ members = [
+ (0, 1),
+ (0, 2),
+ (0, 3),
+ (0, 4),
+ (0, 5),
+ (0, 6),
+ (0, 7),
+ (0, 8),
+ (0, 9),
+ (0, 10),
+ (0, 11),
+ (0, 12),
+ (1, 2),
+ (2, 3),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 12),
+ (12, 1),
+ (1, 13),
+ (2, 15),
+ (3, 17),
+ (4, 19),
+ (5, 21),
+ (6, 23),
+ (7, 25),
+ (8, 27),
+ (9, 29),
+ (10, 31),
+ (11, 33),
+ (12, 35),
+ (1, 14),
+ (2, 14),
+ (2, 16),
+ (3, 16),
+ (3, 18),
+ (4, 18),
+ (4, 20),
+ (5, 20),
+ (5, 22),
+ (6, 22),
+ (6, 24),
+ (7, 24),
+ (7, 26),
+ (8, 26),
+ (8, 28),
+ (9, 28),
+ (9, 30),
+ (10, 30),
+ (10, 32),
+ (11, 32),
+ (11, 34),
+ (12, 34),
+ (12, 36),
+ (1, 36),
+ (13, 14),
+ (14, 15),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 20),
+ (20, 21),
+ (21, 22),
+ (22, 23),
+ (23, 24),
+ (24, 25),
+ (25, 26),
+ (26, 27),
+ (27, 28),
+ (28, 29),
+ (29, 30),
+ (30, 31),
+ (31, 32),
+ (32, 33),
+ (33, 34),
+ (34, 35),
+ (35, 36),
+ (36, 13),
+ (13, 37),
+ (15, 38),
+ (17, 39),
+ (19, 40),
+ (21, 41),
+ (23, 42),
+ (25, 43),
+ (27, 44),
+ (29, 45),
+ (31, 46),
+ (33, 47),
+ (35, 48),
+ (14, 37),
+ (14, 38),
+ (16, 38),
+ (16, 39),
+ (18, 39),
+ (18, 40),
+ (20, 40),
+ (20, 41),
+ (22, 41),
+ (22, 42),
+ (24, 42),
+ (24, 43),
+ (26, 43),
+ (26, 44),
+ (28, 44),
+ (28, 45),
+ (30, 45),
+ (30, 46),
+ (32, 46),
+ (32, 47),
+ (34, 47),
+ (34, 48),
+ (36, 48),
+ (36, 37)
+ ]
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 30450000, 0.288)
+ # print(A.shape)
+ memberType = MemberType(A[index].item(), 30450000, 0.288)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.288)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 30450000, Rho[index].item())
+
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_4forces(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (0.0, 0.0, -5000.0)),
+ (17, (0.0, 0.0, -5000.0)),
+ (18, (0.0, 0.0, -5000.0)),
+ (19, (0.0, 0.0, -5000.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_single(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (5000.0, 5000.0, -5000.0)),
+ (17, (0.0, 0.0, 0.0)),
+ (18, (0.0, 0.0, 0.0)),
+ (19, (0.0, 0.0, 0.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss942bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ [24.5, 24.5, 312.0],
+ [38.5, 24.5, 312.0],
+ [24.5, 38.5, 312.0],
+ [38.5, 38.5, 312.0],
+ [24.5, 24.5, 300.0],
+ [38.5, 24.5, 300.0],
+ [24.5, 38.5, 300.0],
+ [38.5, 38.5, 300.0],
+ [24.5, 24.5, 288.0],
+ [38.5, 24.5, 288.0],
+ [24.5, 38.5, 288.0],
+ [38.5, 38.5, 288.0],
+ [24.5, 24.5, 276.0],
+ [38.5, 24.5, 276.0],
+ [24.5, 38.5, 276.0],
+ [38.5, 38.5, 276.0],
+ [24.5, 24.5, 264.0],
+ [38.5, 24.5, 264.0],
+ [24.5, 38.5, 264.0],
+ [38.5, 38.5, 264.0],
+ [24.5, 24.5, 252.0],
+ [38.5, 24.5, 252.0],
+ [24.5, 38.5, 252.0],
+ [38.5, 38.5, 252.0],
+ [21.6005, 21.6005, 240.0],
+ [31.5, 17.5, 240.0],
+ [41.3995, 21.6005, 240.0],
+ [17.5, 31.5, 240.0],
+ [45.5, 31.5, 240.0],
+ [21.6005, 41.3995, 240.0],
+ [31.5, 45.5, 240.0],
+ [41.3995, 41.3995, 240.0],
+ [21.6005, 21.6005, 228.0],
+ [31.5, 17.5, 228.0],
+ [41.3995, 21.6005, 228.0],
+ [17.5, 31.5, 228.0],
+ [45.5, 31.5, 228.0],
+ [21.6005, 41.3995, 228.0],
+ [31.5, 45.5, 228.0],
+ [41.3995, 41.3995, 228.0],
+ [21.6005, 21.6005, 216.0],
+ [31.5, 17.5, 216.0],
+ [41.3995, 21.6005, 216.0],
+ [17.5, 31.5, 216.0],
+ [45.5, 31.5, 216.0],
+ [21.6005, 41.3995, 216.0],
+ [31.5, 45.5, 216.0],
+ [41.3995, 41.3995, 216.0],
+ [21.6005, 21.6005, 204.0],
+ [31.5, 17.5, 204.0],
+ [41.3995, 21.6005, 204.0],
+ [17.5, 31.5, 204.0],
+ [45.5, 31.5, 204.0],
+ [21.6005, 41.3995, 204.0],
+ [31.5, 45.5, 204.0],
+ [41.3995, 41.3995, 204.0],
+ [21.6005, 21.6005, 192.0],
+ [31.5, 17.5, 192.0],
+ [41.3995, 21.6005, 192.0],
+ [17.5, 31.5, 192.0],
+ [45.5, 31.5, 192.0],
+ [21.6005, 41.3995, 192.0],
+ [31.5, 45.5, 192.0],
+ [41.3995, 41.3995, 192.0],
+ [21.6005, 21.6005, 180.0],
+ [31.5, 17.5, 180.0],
+ [41.3995, 21.6005, 180.0],
+ [17.5, 31.5, 180.0],
+ [45.5, 31.5, 180.0],
+ [21.6005, 41.3995, 180.0],
+ [31.5, 45.5, 180.0],
+ [41.3995, 41.3995, 180.0],
+ [21.6005, 21.6005, 168.0],
+ [31.5, 17.5, 168.0],
+ [41.3995, 21.6005, 168.0],
+ [17.5, 31.5, 168.0],
+ [45.5, 31.5, 168.0],
+ [21.6005, 41.3995, 168.0],
+ [31.5, 45.5, 168.0],
+ [41.3995, 41.3995, 168.0],
+ [21.6005, 21.6005, 156.0],
+ [31.5, 17.5, 156.0],
+ [41.3995, 21.6005, 156.0],
+ [17.5, 31.5, 156.0],
+ [45.5, 31.5, 156.0],
+ [21.6005, 41.3995, 156.0],
+ [31.5, 45.5, 156.0],
+ [41.3995, 41.3995, 156.0],
+ [7.0, 24.5, 144.0],
+ [11.1199, 11.1199, 144.0],
+ [24.5, 7.0, 144.0],
+ [38.5, 7.0, 144.0],
+ [51.8801, 11.1199, 144.0],
+ [56.0, 24.5, 144.0],
+ [7.0, 38.5, 144.0],
+ [11.1199, 51.8801, 144.0],
+ [24.5, 56.0, 144.0],
+ [38.5, 56.0, 144.0],
+ [51.8801, 51.8801, 144.0],
+ [56.0, 38.5, 144.0],
+ [7.0, 24.5, 132.0],
+ [11.1199, 11.1199, 132.0],
+ [24.5, 7.0, 132.0],
+ [38.5, 7.0, 132.0],
+ [51.8801, 11.1199, 132.0],
+ [56.0, 24.5, 132.0],
+ [7.0, 38.5, 132.0],
+ [11.1199, 51.8801, 132.0],
+ [24.5, 56.0, 132.0],
+ [38.5, 56.0, 132.0],
+ [51.8801, 51.8801, 132.0],
+ [56.0, 38.5, 132.0],
+ [7.0, 24.5, 120.0],
+ [11.1199, 11.1199, 120.0],
+ [24.5, 7.0, 120.0],
+ [38.5, 7.0, 120.0],
+ [51.8801, 11.1199, 120.0],
+ [56.0, 24.5, 120.0],
+ [7.0, 38.5, 120.0],
+ [11.1199, 51.8801, 120.0],
+ [24.5, 56.0, 120.0],
+ [38.5, 56.0, 120.0],
+ [51.8801, 51.8801, 120.0],
+ [56.0, 38.5, 120.0],
+ [7.0, 24.5, 108.0],
+ [11.1199, 11.1199, 108.0],
+ [24.5, 7.0, 108.0],
+ [38.5, 7.0, 108.0],
+ [51.8801, 11.1199, 108.0],
+ [56.0, 24.5, 108.0],
+ [7.0, 38.5, 108.0],
+ [11.1199, 51.8801, 108.0],
+ [24.5, 56.0, 108.0],
+ [38.5, 56.0, 108.0],
+ [51.8801, 51.8801, 108.0],
+ [56.0, 38.5, 108.0],
+ [7.0, 24.5, 96.0],
+ [11.1199, 11.1199, 96.0],
+ [24.5, 7.0, 96.0],
+ [38.5, 7.0, 96.0],
+ [51.8801, 11.1199, 96.0],
+ [56.0, 24.5, 96.0],
+ [7.0, 38.5, 96.0],
+ [11.1199, 51.8801, 96.0],
+ [24.5, 56.0, 96.0],
+ [38.5, 56.0, 96.0],
+ [51.8801, 51.8801, 96.0],
+ [56.0, 38.5, 96.0],
+ [7.0, 24.5, 84.0],
+ [11.1199, 11.1199, 84.0],
+ [24.5, 7.0, 84.0],
+ [38.5, 7.0, 84.0],
+ [51.8801, 11.1199, 84.0],
+ [56.0, 24.5, 84.0],
+ [7.0, 38.5, 84.0],
+ [11.1199, 51.8801, 84.0],
+ [24.5, 56.0, 84.0],
+ [38.5, 56.0, 84.0],
+ [51.8801, 51.8801, 84.0],
+ [56.0, 38.5, 84.0],
+ [7.0, 24.5, 72.0],
+ [11.1199, 11.1199, 72.0],
+ [24.5, 7.0, 72.0],
+ [38.5, 7.0, 72.0],
+ [51.8801, 11.1199, 72.0],
+ [56.0, 24.5, 72.0],
+ [7.0, 38.5, 72.0],
+ [11.1199, 51.8801, 72.0],
+ [24.5, 56.0, 72.0],
+ [38.5, 56.0, 72.0],
+ [51.8801, 51.8801, 72.0],
+ [56.0, 38.5, 72.0],
+ [7.0, 24.5, 60.0],
+ [11.1199, 11.1199, 60.0],
+ [24.5, 7.0, 60.0],
+ [38.5, 7.0, 60.0],
+ [51.8801, 11.1199, 60.0],
+ [56.0, 24.5, 60.0],
+ [7.0, 38.5, 60.0],
+ [11.1199, 51.8801, 60.0],
+ [24.5, 56.0, 60.0],
+ [38.5, 56.0, 60.0],
+ [51.8801, 51.8801, 60.0],
+ [56.0, 38.5, 60.0],
+ [7.0, 24.5, 48.0],
+ [11.1199, 11.1199, 48.0],
+ [24.5, 7.0, 48.0],
+ [38.5, 7.0, 48.0],
+ [51.8801, 11.1199, 48.0],
+ [56.0, 24.5, 48.0],
+ [7.0, 38.5, 48.0],
+ [11.1199, 51.8801, 48.0],
+ [24.5, 56.0, 48.0],
+ [38.5, 56.0, 48.0],
+ [51.8801, 51.8801, 48.0],
+ [56.0, 38.5, 48.0],
+ [7.0, 24.5, 36.0],
+ [11.1199, 11.1199, 36.0],
+ [24.5, 7.0, 36.0],
+ [38.5, 7.0, 36.0],
+ [51.8801, 11.1199, 36.0],
+ [56.0, 24.5, 36.0],
+ [7.0, 38.5, 36.0],
+ [11.1199, 51.8801, 36.0],
+ [24.5, 56.0, 36.0],
+ [38.5, 56.0, 36.0],
+ [51.8801, 51.8801, 36.0],
+ [56.0, 38.5, 36.0],
+ [7.0, 24.5, 24.0],
+ [11.1199, 11.1199, 24.0],
+ [24.5, 7.0, 24.0],
+ [38.5, 7.0, 24.0],
+ [51.8801, 11.1199, 24.0],
+ [56.0, 24.5, 24.0],
+ [7.0, 38.5, 24.0],
+ [11.1199, 51.8801, 24.0],
+ [24.5, 56.0, 24.0],
+ [38.5, 56.0, 24.0],
+ [51.8801, 51.8801, 24.0],
+ [56.0, 38.5, 24.0],
+ [7.0, 24.5, 12.0],
+ [11.1199, 11.1199, 12.0],
+ [24.5, 7.0, 12.0],
+ [38.5, 7.0, 12.0],
+ [51.8801, 11.1199, 12.0],
+ [56.0, 24.5, 12.0],
+ [7.0, 38.5, 12.0],
+ [11.1199, 51.8801, 12.0],
+ [24.5, 56.0, 12.0],
+ [38.5, 56.0, 12.0],
+ [51.8801, 51.8801, 12.0],
+ [56.0, 38.5, 12.0],
+ [7.0, 24.5, 0.0],
+ [11.1199, 11.1199, 0.0],
+ [24.5, 7.0, 0.0],
+ [38.5, 7.0, 0.0],
+ [51.8801, 11.1199, 0.0],
+ [56.0, 24.5, 0.0],
+ [7.0, 38.5, 0.0],
+ [11.1199, 51.8801, 0.0],
+ [24.5, 56.0, 0.0],
+ [38.5, 56.0, 0.0],
+ [51.8801, 51.8801, 0.0],
+ [56.0, 38.5, 0.0]
+ ]
+
+
+ supports = []
+ for ii in range(244-12):
+ supports.append(SupportType.NO)
+ for ii in range(12):
+ supports.append(SupportType.PIN)
+
+
+ forces = [
+ (0, (1.5, -1.0, -3.0)),
+ (1, (-1.0, -1.0, -3.0)),
+ (2, (1.5, -1.0, -3.0)),
+ (3, (-1.0, 1.0, -3.0)),
+ (4, (1.5, -1.0, -3.0)),
+ (5, (-1.0, -1.0, -3.0)),
+ (6, (1.5, -1.0, -3.0)),
+ (7, (-1.0, 1.0, -3.0)),
+ (8, (1.5, -1.0, -3.0)),
+ (9, (-1.0, -1.0, -3.0)),
+ (10, (1.5, -1.0, -3.0)),
+ (11, (-1.0, 1.0, -3.0)),
+ (12, (1.5, -1.0, -3.0)),
+ (13, (-1.0, -1.0, -3.0)),
+ (14, (1.5, -1.0, -3.0)),
+ (15, (-1.0, 1.0, -3.0)),
+ (16, (1.5, -1.0, -3.0)),
+ (17, (-1.0, -1.0, -3.0)),
+ (18, (1.5, -1.0, -3.0)),
+ (19, (-1.0, 1.0, -3.0)),
+ (20, (1.5, -1.0, -3.0)),
+ (21, (-1.0, -1.0, -3.0)),
+ (22, (1.5, -1.0, -3.0)),
+ (23, (-1.0, 1.0, -3.0)),
+ (24, (1.5, -1.0, -3.0)),
+ (25, (0.0, -1.0, -3.0)),
+ (26, (-1.0, -1.0, -3.0)),
+ (27, (1.5, 0.0, -3.0)),
+ (28, (-1.0, 0.0, -3.0)),
+ (29, (1.5, 1.0, -3.0)),
+ (30, (0.0, 1.0, -3.0)),
+ (31, (-1.0, 1.0, -3.0)),
+ (32, (1.5, -1.0, -6.0)),
+ (33, (0.0, -1.0, -6.0)),
+ (34, (-1.0, -1.0, -6.0)),
+ (35, (1.5, 0.0, -6.0)),
+ (36, (-1.0, 0.0, -6.0)),
+ (37, (1.5, 1.0, -6.0)),
+ (38, (0.0, 1.0, -6.0)),
+ (39, (-1.0, 1.0, -6.0)),
+ (40, (1.5, -1.0, -6.0)),
+ (41, (0.0, -1.0, -6.0)),
+ (42, (-1.0, -1.0, -6.0)),
+ (43, (1.5, 0.0, -6.0)),
+ (44, (-1.0, 0.0, -6.0)),
+ (45, (1.5, 1.0, -6.0)),
+ (46, (0.0, 1.0, -6.0)),
+ (47, (-1.0, 1.0, -6.0)),
+ (48, (1.5, -1.0, -6.0)),
+ (49, (0.0, -1.0, -6.0)),
+ (50, (-1.0, -1.0, -6.0)),
+ (51, (1.5, 0.0, -6.0)),
+ (52, (-1.0, 0.0, -6.0)),
+ (53, (1.5, 1.0, -6.0)),
+ (54, (0.0, 1.0, -6.0)),
+ (55, (-1.0, 1.0, -6.0)),
+ (56, (1.5, -1.0, -6.0)),
+ (57, (0.0, -1.0, -6.0)),
+ (58, (-1.0, -1.0, -6.0)),
+ (59, (1.5, 0.0, -6.0)),
+ (60, (-1.0, 0.0, -6.0)),
+ (61, (1.5, 1.0, -6.0)),
+ (62, (0.0, 1.0, -6.0)),
+ (63, (-1.0, 1.0, -6.0)),
+ (64, (1.5, -1.0, -6.0)),
+ (65, (0.0, -1.0, -6.0)),
+ (66, (-1.0, -1.0, -6.0)),
+ (67, (1.5, 0.0, -6.0)),
+ (68, (-1.0, 0.0, -6.0)),
+ (69, (1.5, 1.0, -6.0)),
+ (70, (0.0, 1.0, -6.0)),
+ (71, (-1.0, 1.0, -6.0)),
+ (72, (1.5, -1.0, -6.0)),
+ (73, (0.0, -1.0, -6.0)),
+ (74, (-1.0, -1.0, -6.0)),
+ (75, (1.5, 0.0, -6.0)),
+ (76, (-1.0, 0.0, -6.0)),
+ (77, (1.5, 1.0, -6.0)),
+ (78, (0.0, 1.0, -6.0)),
+ (79, (-1.0, 1.0, -6.0)),
+ (80, (1.5, -1.0, -6.0)),
+ (81, (0.0, -1.0, -6.0)),
+ (82, (-1.0, -1.0, -6.0)),
+ (83, (1.5, 0.0, -6.0)),
+ (84, (-1.0, 0.0, -6.0)),
+ (85, (1.5, 1.0, -6.0)),
+ (86, (0.0, 1.0, -6.0)),
+ (87, (-1.0, 1.0, -6.0)),
+ (88, (1.5, -1.0, -6.0)),
+ (89, (1.5, -1.0, -6.0)),
+ (90, (1.5, -1.0, -6.0)),
+ (91, (-1.0, -1.0, -6.0)),
+ (92, (-1.0, -1.0, -6.0)),
+ (93, (-1.0, -1.0, -6.0)),
+ (94, (1.5, 1.0, -6.0)),
+ (95, (1.5, 1.0, -6.0)),
+ (96, (1.5, 1.0, -6.0)),
+ (97, (-1.0, 1.0, -6.0)),
+ (98, (-1.0, 1.0, -6.0)),
+ (99, (-1.0, 1.0, -6.0)),
+ (100, (1.5, -1.0, -9.0)),
+ (101, (1.5, -1.0, -9.0)),
+ (102, (1.5, -1.0, -9.0)),
+ (103, (-1.0, -1.0, -9.0)),
+ (104, (-1.0, -1.0, -9.0)),
+ (105, (-1.0, -1.0, -9.0)),
+ (106, (1.5, 1.0, -9.0)),
+ (107, (1.5, 1.0, -9.0)),
+ (108, (1.5, 1.0, -9.0)),
+ (109, (-1.0, 1.0, -9.0)),
+ (110, (-1.0, 1.0, -9.0)),
+ (111, (-1.0, 1.0, -9.0)),
+ (112, (1.5, -1.0, -9.0)),
+ (113, (1.5, -1.0, -9.0)),
+ (114, (1.5, -1.0, -9.0)),
+ (115, (-1.0, -1.0, -9.0)),
+ (116, (-1.0, -1.0, -9.0)),
+ (117, (-1.0, -1.0, -9.0)),
+ (118, (1.5, 1.0, -9.0)),
+ (119, (1.5, 1.0, -9.0)),
+ (120, (1.5, 1.0, -9.0)),
+ (121, (-1.0, 1.0, -9.0)),
+ (122, (-1.0, 1.0, -9.0)),
+ (123, (-1.0, 1.0, -9.0)),
+ (124, (1.5, -1.0, -9.0)),
+ (125, (1.5, -1.0, -9.0)),
+ (126, (1.5, -1.0, -9.0)),
+ (127, (-1.0, -1.0, -9.0)),
+ (128, (-1.0, -1.0, -9.0)),
+ (129, (-1.0, -1.0, -9.0)),
+ (130, (1.5, 1.0, -9.0)),
+ (131, (1.5, 1.0, -9.0)),
+ (132, (1.5, 1.0, -9.0)),
+ (133, (-1.0, 1.0, -9.0)),
+ (134, (-1.0, 1.0, -9.0)),
+ (135, (-1.0, 1.0, -9.0)),
+ (136, (1.5, -1.0, -9.0)),
+ (137, (1.5, -1.0, -9.0)),
+ (138, (1.5, -1.0, -9.0)),
+ (139, (-1.0, -1.0, -9.0)),
+ (140, (-1.0, -1.0, -9.0)),
+ (141, (-1.0, -1.0, -9.0)),
+ (142, (1.5, 1.0, -9.0)),
+ (143, (1.5, 1.0, -9.0)),
+ (144, (1.5, 1.0, -9.0)),
+ (145, (-1.0, 1.0, -9.0)),
+ (146, (-1.0, 1.0, -9.0)),
+ (147, (-1.0, 1.0, -9.0)),
+ (148, (1.5, -1.0, -9.0)),
+ (149, (1.5, -1.0, -9.0)),
+ (150, (1.5, -1.0, -9.0)),
+ (151, (-1.0, -1.0, -9.0)),
+ (152, (-1.0, -1.0, -9.0)),
+ (153, (-1.0, -1.0, -9.0)),
+ (154, (1.5, 1.0, -9.0)),
+ (155, (1.5, 1.0, -9.0)),
+ (156, (1.5, 1.0, -9.0)),
+ (157, (-1.0, 1.0, -9.0)),
+ (158, (-1.0, 1.0, -9.0)),
+ (159, (-1.0, 1.0, -9.0)),
+ (160, (1.5, -1.0, -9.0)),
+ (161, (1.5, -1.0, -9.0)),
+ (162, (1.5, -1.0, -9.0)),
+ (163, (-1.0, -1.0, -9.0)),
+ (164, (-1.0, -1.0, -9.0)),
+ (165, (-1.0, -1.0, -9.0)),
+ (166, (1.5, 1.0, -9.0)),
+ (167, (1.5, 1.0, -9.0)),
+ (168, (1.5, 1.0, -9.0)),
+ (169, (-1.0, 1.0, -9.0)),
+ (170, (-1.0, 1.0, -9.0)),
+ (171, (-1.0, 1.0, -9.0)),
+ (172, (1.5, -1.0, -9.0)),
+ (173, (1.5, -1.0, -9.0)),
+ (174, (1.5, -1.0, -9.0)),
+ (175, (-1.0, -1.0, -9.0)),
+ (176, (-1.0, -1.0, -9.0)),
+ (177, (-1.0, -1.0, -9.0)),
+ (178, (1.5, 1.0, -9.0)),
+ (179, (1.5, 1.0, -9.0)),
+ (180, (1.5, 1.0, -9.0)),
+ (181, (-1.0, 1.0, -9.0)),
+ (182, (-1.0, 1.0, -9.0)),
+ (183, (-1.0, 1.0, -9.0)),
+ (184, (1.5, -1.0, -9.0)),
+ (185, (1.5, -1.0, -9.0)),
+ (186, (1.5, -1.0, -9.0)),
+ (187, (-1.0, -1.0, -9.0)),
+ (188, (-1.0, -1.0, -9.0)),
+ (189, (-1.0, -1.0, -9.0)),
+ (190, (1.5, 1.0, -9.0)),
+ (191, (1.5, 1.0, -9.0)),
+ (192, (1.5, 1.0, -9.0)),
+ (193, (-1.0, 1.0, -9.0)),
+ (194, (-1.0, 1.0, -9.0)),
+ (195, (-1.0, 1.0, -9.0)),
+ (196, (1.5, -1.0, -9.0)),
+ (197, (1.5, -1.0, -9.0)),
+ (198, (1.5, -1.0, -9.0)),
+ (199, (-1.0, -1.0, -9.0)),
+ (200, (-1.0, -1.0, -9.0)),
+ (201, (-1.0, -1.0, -9.0)),
+ (202, (1.5, 1.0, -9.0)),
+ (203, (1.5, 1.0, -9.0)),
+ (204, (1.5, 1.0, -9.0)),
+ (205, (-1.0, 1.0, -9.0)),
+ (206, (-1.0, 1.0, -9.0)),
+ (207, (-1.0, 1.0, -9.0)),
+ (208, (1.5, -1.0, -9.0)),
+ (209, (1.5, -1.0, -9.0)),
+ (210, (1.5, -1.0, -9.0)),
+ (211, (-1.0, -1.0, -9.0)),
+ (212, (-1.0, -1.0, -9.0)),
+ (213, (-1.0, -1.0, -9.0)),
+ (214, (1.5, 1.0, -9.0)),
+ (215, (1.5, 1.0, -9.0)),
+ (216, (1.5, 1.0, -9.0)),
+ (217, (-1.0, 1.0, -9.0)),
+ (218, (-1.0, 1.0, -9.0)),
+ (219, (-1.0, 1.0, -9.0)),
+ (220, (1.5, -1.0, -9.0)),
+ (221, (1.5, -1.0, -9.0)),
+ (222, (1.5, -1.0, -9.0)),
+ (223, (-1.0, -1.0, -9.0)),
+ (224, (-1.0, -1.0, -9.0)),
+ (225, (-1.0, -1.0, -9.0)),
+ (226, (1.5, 1.0, -9.0)),
+ (227, (1.5, 1.0, -9.0)),
+ (228, (1.5, 1.0, -9.0)),
+ (229, (-1.0, 1.0, -9.0)),
+ (230, (-1.0, 1.0, -9.0)),
+ (231, (-1.0, 1.0, -9.0))
+ ]
+
+
+
+
+ members = [
+ (0, 3),
+ (1, 2),
+ (0, 1),
+ (2, 3),
+ (0, 2),
+ (1, 3),
+ (4, 5),
+ (6, 7),
+ (4, 6),
+ (5, 7),
+ (1, 5),
+ (0, 4),
+ (3, 7),
+ (2, 6),
+ (5, 9),
+ (4, 8),
+ (7, 11),
+ (6, 10),
+ (1, 4),
+ (0, 5),
+ (1, 7),
+ (3, 5),
+ (3, 6),
+ (2, 7),
+ (0, 6),
+ (2, 4),
+ (5, 8),
+ (4, 9),
+ (5, 11),
+ (7, 9),
+ (7, 10),
+ (6, 11),
+ (6, 8),
+ (4, 10),
+ (8, 9),
+ (10, 11),
+ (8, 10),
+ (9, 11),
+ (12, 13),
+ (14, 15),
+ (12, 14),
+ (13, 15),
+ (16, 17),
+ (18, 19),
+ (16, 18),
+ (17, 19),
+ (9, 13),
+ (8, 12),
+ (11, 15),
+ (10, 14),
+ (13, 17),
+ (12, 16),
+ (15, 19),
+ (16, 18),
+ (17, 21),
+ (16, 20),
+ (19, 23),
+ (18, 22),
+ (8, 13),
+ (9, 12),
+ (9, 15),
+ (11, 13),
+ (11, 14),
+ (10, 15),
+ (10, 12),
+ (8, 14),
+ (12, 17),
+ (13, 16),
+ (13, 19),
+ (15, 17),
+ (15, 18),
+ (14, 19),
+ (14, 16),
+ (12, 18),
+ (16, 21),
+ (17, 20),
+ (17, 23),
+ (19, 21),
+ (19, 22),
+ (18, 23),
+ (18, 20),
+ (16, 22),
+ (20, 21),
+ (22, 23),
+ (20, 22),
+ (21, 23),
+ (21, 24),
+ (20, 26),
+ (21, 31),
+ (23, 26),
+ (23, 29),
+ (22, 31),
+ (22, 24),
+ (20, 29),
+ (21, 26),
+ (20, 24),
+ (23, 31),
+ (22, 29),
+ (21, 25),
+ (20, 25),
+ (21, 28),
+ (23, 28),
+ (23, 30),
+ (22, 30),
+ (22, 27),
+ (20, 27),
+ (24, 25),
+ (25, 26),
+ (24, 27),
+ (27, 29),
+ (29, 30),
+ (30, 31),
+ (26, 28),
+ (28, 31),
+ (32, 33),
+ (33, 34),
+ (32, 35),
+ (35, 37),
+ (37, 38),
+ (38, 39),
+ (34, 36),
+ (36, 39),
+ (24, 32),
+ (26, 34),
+ (29, 37),
+ (31, 39),
+ (32, 40),
+ (34, 42),
+ (37, 45),
+ (39, 47),
+ (24, 33),
+ (25, 32),
+ (25, 34),
+ (26, 33),
+ (27, 32),
+ (24, 35),
+ (26, 36),
+ (28, 34),
+ (28, 39),
+ (31, 36),
+ (31, 38),
+ (30, 39),
+ (30, 37),
+ (29, 38),
+ (29, 35),
+ (27, 37),
+ (32, 41),
+ (33, 40),
+ (33, 42),
+ (34, 41),
+ (34, 44),
+ (36, 42),
+ (36, 47),
+ (39, 44),
+ (39, 46),
+ (38, 47),
+ (38, 45),
+ (37, 46),
+ (37, 43),
+ (35, 45),
+ (35, 40),
+ (32, 43),
+ (25, 33),
+ (27, 35),
+ (30, 38),
+ (28, 36),
+ (33, 41),
+ (35, 43),
+ (38, 46),
+ (36, 44),
+ (40, 41),
+ (41, 42),
+ (40, 43),
+ (42, 44),
+ (43, 45),
+ (45, 46),
+ (46, 47),
+ (44, 47),
+ (48, 49),
+ (49, 50),
+ (48, 51),
+ (50, 52),
+ (51, 53),
+ (53, 54),
+ (54, 55),
+ (52, 55),
+ (42, 50),
+ (40, 48),
+ (45, 53),
+ (47, 55),
+ (48, 56),
+ (50, 58),
+ (53, 61),
+ (55, 63),
+ (40, 49),
+ (41, 48),
+ (41, 50),
+ (42, 49),
+ (42, 52),
+ (44, 50),
+ (44, 55),
+ (47, 52),
+ (47, 54),
+ (46, 55),
+ (46, 53),
+ (45, 54),
+ (45, 51),
+ (43, 53),
+ (43, 48),
+ (40, 51),
+ (48, 57),
+ (49, 56),
+ (49, 58),
+ (50, 57),
+ (50, 60),
+ (52, 58),
+ (52, 63),
+ (55, 60),
+ (55, 62),
+ (54, 63),
+ (54, 61),
+ (53, 62),
+ (53, 59),
+ (51, 61),
+ (51, 56),
+ (48, 59),
+ (41, 49),
+ (43, 51),
+ (44, 52),
+ (46, 54),
+ (49, 57),
+ (51, 59),
+ (52, 60),
+ (54, 62),
+ (56, 57),
+ (57, 58),
+ (56, 59),
+ (58, 60),
+ (59, 61),
+ (60, 63),
+ (61, 62),
+ (62, 63),
+ (64, 65),
+ (65, 66),
+ (64, 67),
+ (66, 68),
+ (67, 69),
+ (68, 71),
+ (69, 70),
+ (70, 71),
+ (72, 73),
+ (73, 74),
+ (72, 75),
+ (74, 76),
+ (75, 77),
+ (76, 79),
+ (77, 78),
+ (78, 79),
+ (56, 64),
+ (58, 66),
+ (61, 69),
+ (63, 71),
+ (64, 72),
+ (66, 74),
+ (69, 77),
+ (71, 79),
+ (72, 80),
+ (74, 82),
+ (77, 85),
+ (79, 87),
+ (56, 65),
+ (57, 64),
+ (57, 66),
+ (58, 65),
+ (58, 68),
+ (60, 66),
+ (60, 71),
+ (63, 68),
+ (63, 70),
+ (62, 71),
+ (62, 69),
+ (61, 70),
+ (61, 67),
+ (59, 69),
+ (59, 64),
+ (56, 67),
+ (64, 73),
+ (65, 72),
+ (65, 74),
+ (66, 73),
+ (66, 76),
+ (68, 74),
+ (68, 79),
+ (71, 76),
+ (71, 78),
+ (70, 79),
+ (70, 77),
+ (69, 78),
+ (69, 75),
+ (67, 77),
+ (67, 72),
+ (64, 75),
+ (72, 81),
+ (73, 80),
+ (73, 82),
+ (74, 81),
+ (74, 84),
+ (76, 82),
+ (76, 87),
+ (79, 84),
+ (79, 86),
+ (78, 87),
+ (78, 85),
+ (77, 86),
+ (77, 83),
+ (75, 85),
+ (75, 80),
+ (72, 83),
+ (57, 65),
+ (59, 67),
+ (60, 68),
+ (62, 70),
+ (65, 73),
+ (67, 75),
+ (68, 76),
+ (70, 78),
+ (73, 81),
+ (75, 83),
+ (76, 84),
+ (78, 86),
+ (80, 81),
+ (81, 82),
+ (80, 83),
+ (82, 84),
+ (83, 85),
+ (84, 87),
+ (85, 86),
+ (86, 87),
+ (80, 89),
+ (82, 92),
+ (85, 95),
+ (87, 98),
+ (81, 89),
+ (81, 92),
+ (84, 92),
+ (84, 98),
+ (83, 95),
+ (83, 89),
+ (86, 95),
+ (86, 98),
+ (82, 91),
+ (80, 90),
+ (82, 93),
+ (87, 99),
+ (80, 88),
+ (85, 94),
+ (85, 96),
+ (87, 97),
+ (81, 91),
+ (81, 90),
+ (83, 88),
+ (83, 94),
+ (84, 93),
+ (84, 99),
+ (86, 96),
+ (86, 97),
+ (89, 90),
+ (91, 92),
+ (88, 89),
+ (92, 93),
+ (94, 95),
+ (95, 96),
+ (97, 98),
+ (98, 99),
+ (101, 102),
+ (103, 104),
+ (100, 101),
+ (104, 105),
+ (106, 107),
+ (107, 108),
+ (109, 110),
+ (110, 111),
+ (90, 91),
+ (88, 94),
+ (93, 99),
+ (96, 97),
+ (102, 103),
+ (100, 106),
+ (105, 111),
+ (108, 109),
+ (89, 101),
+ (92, 104),
+ (95, 107),
+ (98, 110),
+ (101, 113),
+ (104, 116),
+ (107, 119),
+ (110, 122),
+ (92, 103),
+ (91, 104),
+ (89, 102),
+ (90, 101),
+ (88, 101),
+ (89, 100),
+ (92, 105),
+ (93, 104),
+ (99, 110),
+ (98, 111),
+ (98, 109),
+ (97, 110),
+ (96, 107),
+ (95, 108),
+ (95, 106),
+ (94, 107),
+ (101, 114),
+ (102, 113),
+ (101, 112),
+ (100, 113),
+ (103, 116),
+ (104, 115),
+ (104, 117),
+ (105, 116),
+ (111, 122),
+ (110, 123),
+ (110, 121),
+ (109, 122),
+ (108, 119),
+ (107, 120),
+ (107, 118),
+ (106, 119),
+ (90, 102),
+ (91, 103),
+ (96, 108),
+ (97, 109),
+ (88, 100),
+ (94, 106),
+ (93, 105),
+ (99, 111),
+ (102, 114),
+ (103, 115),
+ (108, 120),
+ (109, 121),
+ (100, 112),
+ (106, 118),
+ (105, 117),
+ (111, 123),
+ (90, 103),
+ (91, 102),
+ (96, 109),
+ (97, 108),
+ (88, 106),
+ (94, 100),
+ (93, 111),
+ (99, 105),
+ (102, 115),
+ (103, 114),
+ (108, 121),
+ (109, 120),
+ (105, 123),
+ (111, 117),
+ (100, 118),
+ (106, 112),
+ (112, 113),
+ (113, 114),
+ (115, 116),
+ (116, 117),
+ (118, 119),
+ (119, 120),
+ (121, 122),
+ (122, 123),
+ (124, 125),
+ (125, 126),
+ (127, 128),
+ (128, 129),
+ (130, 131),
+ (131, 132),
+ (133, 134),
+ (134, 135),
+ (136, 137),
+ (137, 138),
+ (139, 140),
+ (140, 141),
+ (142, 143),
+ (143, 144),
+ (145, 146),
+ (146, 147),
+ (114, 115),
+ (120, 121),
+ (112, 118),
+ (117, 123),
+ (126, 127),
+ (132, 133),
+ (124, 130),
+ (129, 135),
+ (138, 139),
+ (144, 145),
+ (136, 142),
+ (141, 147),
+ (113, 125),
+ (116, 128),
+ (119, 131),
+ (122, 134),
+ (125, 137),
+ (128, 140),
+ (131, 143),
+ (134, 146),
+ (137, 149),
+ (140, 152),
+ (143, 155),
+ (146, 158),
+ (112, 125),
+ (113, 124),
+ (113, 126),
+ (114, 125),
+ (115, 128),
+ (116, 127),
+ (116, 129),
+ (117, 128),
+ (118, 131),
+ (119, 130),
+ (119, 132),
+ (120, 131),
+ (121, 134),
+ (122, 133),
+ (122, 135),
+ (123, 134),
+ (124, 137),
+ (125, 136),
+ (125, 138),
+ (126, 137),
+ (127, 140),
+ (128, 139),
+ (128, 141),
+ (129, 140),
+ (130, 143),
+ (131, 142),
+ (131, 144),
+ (132, 143),
+ (133, 146),
+ (134, 145),
+ (134, 147),
+ (135, 146),
+ (136, 149),
+ (137, 148),
+ (137, 150),
+ (138, 149),
+ (139, 152),
+ (140, 151),
+ (140, 153),
+ (141, 152),
+ (142, 155),
+ (143, 154),
+ (143, 156),
+ (144, 155),
+ (145, 158),
+ (146, 157),
+ (146, 159),
+ (147, 158),
+ (114, 126),
+ (115, 127),
+ (120, 132),
+ (121, 133),
+ (112, 124),
+ (118, 130),
+ (117, 129),
+ (123, 135),
+ (126, 138),
+ (127, 139),
+ (132, 144),
+ (133, 145),
+ (124, 136),
+ (130, 142),
+ (129, 141),
+ (135, 147),
+ (138, 150),
+ (139, 151),
+ (144, 156),
+ (145, 157),
+ (136, 148),
+ (142, 154),
+ (141, 153),
+ (147, 159),
+ (114, 127),
+ (115, 126),
+ (120, 133),
+ (121, 132),
+ (112, 130),
+ (118, 124),
+ (117, 135),
+ (123, 129),
+ (126, 139),
+ (127, 138),
+ (132, 145),
+ (133, 144),
+ (124, 142),
+ (130, 136),
+ (129, 147),
+ (135, 141),
+ (138, 151),
+ (139, 150),
+ (144, 157),
+ (145, 156),
+ (136, 154),
+ (142, 148),
+ (141, 153),
+ (147, 153),
+ (148, 149),
+ (149, 150),
+ (151, 152),
+ (152, 153),
+ (154, 155),
+ (155, 156),
+ (157, 158),
+ (158, 159),
+ (160, 161),
+ (161, 162),
+ (163, 164),
+ (164, 165),
+ (166, 167),
+ (167, 168),
+ (169, 170),
+ (170, 171),
+ (172, 173),
+ (173, 174),
+ (175, 176),
+ (176, 177),
+ (178, 179),
+ (179, 180),
+ (181, 182),
+ (182, 183),
+ (150, 151),
+ (156, 157),
+ (148, 154),
+ (153, 159),
+ (162, 163),
+ (168, 169),
+ (160, 166),
+ (165, 171),
+ (174, 175),
+ (180, 181),
+ (172, 178),
+ (177, 183),
+ (149, 161),
+ (152, 164),
+ (155, 167),
+ (158, 170),
+ (161, 173),
+ (164, 176),
+ (167, 179),
+ (170, 182),
+ (173, 185),
+ (176, 188),
+ (179, 191),
+ (182, 194),
+ (148, 161),
+ (149, 160),
+ (149, 162),
+ (150, 161),
+ (151, 164),
+ (152, 163),
+ (152, 165),
+ (153, 164),
+ (154, 167),
+ (155, 166),
+ (155, 168),
+ (156, 167),
+ (157, 170),
+ (158, 169),
+ (158, 171),
+ (159, 170),
+ (160, 173),
+ (161, 172),
+ (161, 174),
+ (162, 173),
+ (163, 176),
+ (164, 175),
+ (164, 177),
+ (165, 176),
+ (166, 179),
+ (167, 178),
+ (167, 180),
+ (168, 179),
+ (169, 182),
+ (170, 181),
+ (170, 183),
+ (171, 182),
+ (172, 185),
+ (173, 184),
+ (173, 186),
+ (174, 185),
+ (175, 188),
+ (176, 187),
+ (176, 189),
+ (177, 188),
+ (178, 191),
+ (179, 190),
+ (179, 192),
+ (180, 191),
+ (181, 194),
+ (182, 193),
+ (182, 195),
+ (183, 194),
+ (150, 162),
+ (151, 163),
+ (156, 168),
+ (157, 169),
+ (148, 160),
+ (154, 166),
+ (153, 165),
+ (159, 171),
+ (162, 174),
+ (163, 175),
+ (168, 180),
+ (169, 181),
+ (160, 172),
+ (166, 178),
+ (165, 177),
+ (171, 183),
+ (174, 186),
+ (175, 187),
+ (180, 192),
+ (181, 193),
+ (172, 184),
+ (178, 190),
+ (177, 189),
+ (183, 195),
+ (150, 163),
+ (151, 162),
+ (156, 169),
+ (157, 168),
+ (148, 166),
+ (154, 160),
+ (153, 171),
+ (159, 165),
+ (162, 175),
+ (163, 174),
+ (168, 181),
+ (169, 180),
+ (160, 178),
+ (166, 172),
+ (165, 183),
+ (171, 177),
+ (174, 187),
+ (175, 186),
+ (180, 193),
+ (180, 192),
+ (172, 190),
+ (178, 184),
+ (177, 195),
+ (183, 189),
+ (184, 185),
+ (185, 186),
+ (187, 188),
+ (188, 189),
+ (190, 191),
+ (191, 192),
+ (193, 194),
+ (194, 195),
+ (196, 197),
+ (197, 198),
+ (199, 200),
+ (200, 201),
+ (202, 203),
+ (203, 204),
+ (205, 206),
+ (206, 207),
+ (208, 209),
+ (209, 210),
+ (211, 212),
+ (212, 213),
+ (214, 215),
+ (215, 216),
+ (217, 218),
+ (218, 219),
+ (186, 187),
+ (192, 193),
+ (184, 190),
+ (189, 195),
+ (198, 199),
+ (204, 205),
+ (196, 202),
+ (201, 207),
+ (210, 211),
+ (216, 217),
+ (208, 214),
+ (213, 219),
+ (185, 197),
+ (188, 200),
+ (191, 203),
+ (194, 206),
+ (197, 209),
+ (200, 212),
+ (203, 215),
+ (206, 218),
+ (209, 221),
+ (212, 224),
+ (215, 227),
+ (218, 230),
+ (184, 197),
+ (185, 196),
+ (185, 198),
+ (186, 197),
+ (187, 200),
+ (188, 199),
+ (188, 201),
+ (189, 200),
+ (190, 203),
+ (191, 202),
+ (191, 204),
+ (192, 203),
+ (193, 206),
+ (194, 205),
+ (194, 207),
+ (195, 206),
+ (196, 209),
+ (197, 208),
+ (197, 210),
+ (198, 209),
+ (199, 212),
+ (200, 211),
+ (200, 213),
+ (201, 212),
+ (202, 215),
+ (203, 214),
+ (203, 216),
+ (204, 215),
+ (205, 218),
+ (206, 217),
+ (206, 219),
+ (207, 218),
+ (208, 221),
+ (209, 220),
+ (209, 222),
+ (210, 221),
+ (211, 224),
+ (212, 223),
+ (212, 225),
+ (213, 224),
+ (214, 227),
+ (215, 226),
+ (215, 228),
+ (216, 227),
+ (217, 230),
+ (218, 229),
+ (218, 231),
+ (219, 230),
+ (186, 198),
+ (187, 199),
+ (192, 204),
+ (193, 205),
+ (184, 196),
+ (190, 202),
+ (189, 201),
+ (195, 207),
+ (198, 210),
+ (199, 211),
+ (204, 216),
+ (205, 217),
+ (196, 208),
+ (202, 214),
+ (201, 213),
+ (207, 219),
+ (210, 222),
+ (211, 223),
+ (216, 228),
+ (217, 229),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (186, 199),
+ (187, 198),
+ (192, 205),
+ (193, 204),
+ (184, 202),
+ (190, 196),
+ (189, 207),
+ (195, 201),
+ (198, 211),
+ (199, 210),
+ (204, 217),
+ (205, 216),
+ (196, 214),
+ (202, 208),
+ (201, 219),
+ (207, 213),
+ (210, 223),
+ (211, 222),
+ (216, 229),
+ (217, 228),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (220, 221),
+ (221, 222),
+ (223, 224),
+ (224, 225),
+ (226, 227),
+ (227, 228),
+ (229, 230),
+ (230, 231),
+ (222, 223),
+ (228, 229),
+ (220, 226),
+ (225, 231),
+ (221, 233),
+ (224, 236),
+ (227, 239),
+ (230, 242),
+ (222, 233),
+ (220, 233),
+ (223, 236),
+ (225, 236),
+ (226, 239),
+ (228, 239),
+ (229, 242),
+ (231, 242),
+ (221, 234),
+ (221, 232),
+ (224, 235),
+ (224, 237),
+ (227, 238),
+ (227, 240),
+ (230, 241),
+ (230, 243),
+ (222, 234),
+ (223, 235),
+ (228, 240),
+ (229, 241),
+ (220, 232),
+ (226, 238),
+ (225, 237),
+ (231, 243),
+ (222, 235),
+ (223, 234),
+ (228, 241),
+ (229, 240),
+ (220, 238),
+ (226, 232),
+ (225, 243),
+ (231, 237)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+
+
+def Truss10D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ X_scaled = X * (35-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss25D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ X_scaled = X * (10-0.31) + 0.31
+
+ return X_scaled
+
+
+def Truss72D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ X_scaled = X * (10-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss120D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = X * (20-0.775) + 0.775
+
+ return X_scaled
+
+def Truss360D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = torch.zeros(X.shape)
+ X_scaled[:,:120] = X[:,:120] * (20-0.775) + 0.775
+ X_scaled[:,120:240] = X[:,120:240] * (5e4-1e3) + 1e3
+ X_scaled[:,240:360] = X[:,240:360] * (0.3-0.05) + 0.05
+
+ return X_scaled
+
+
+
+
+def Truss10D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ gx[ii,10] = max(abs(displace[1][0]), abs(displace[1][1])) - 2
+ gx[ii,11] = max(abs(displace[2][0]), abs(displace[2][1])) - 2
+ gx[ii,12] = max(abs(displace[4][0]), abs(displace[4][1])) - 2
+ gx[ii,13] = max(abs(displace[5][0]), abs(displace[5][1])) - 2
+
+ return gx, fx
+
+
+
+def Truss25D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 25 bar stress constraints, 6 displacement constraints
+ gx = torch.zeros(n,31)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 40ksi (34809)
+ for ss in range(25):
+ gx[ii,ss] = abs(stress[ss]) - 34809
+
+ # Max displacement in x and y direction less than .4 inches
+ for dd in range(6):
+ # print(displace[dd])
+ gx[ii,25+dd] = max(abs(displace[dd][0]), abs(displace[dd][1])) - 0.039
+
+
+ return gx, fx
+
+
+
+
+
+
+def Truss72D_4forces(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 72 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,76)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 25000
+ for ss in range(72):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ # Max displacement in x and y direction less than .25 inches
+ # print(displace[16], displace[17], displace[18], displace[19])
+ gx[ii,72] = max(abs(displace[16][0]), abs(displace[16][1])) - 0.25
+ gx[ii,73] = max(abs(displace[17][0]), abs(displace[17][1])) - 0.25
+ gx[ii,74] = max(abs(displace[18][0]), abs(displace[18][1])) - 0.25
+ gx[ii,75] = max(abs(displace[19][0]), abs(displace[19][1])) - 0.25
+
+
+ return gx, fx
+
+
+
+def Truss120D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss360D(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ A = X[:,:120]
+ E = X[:,120:240]
+ Rho = X[:,240:360]
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+
+ # if (E != None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ # elif (E != None) & (Rho==None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ # elif (E == None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+ # gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/Untitled-checkpoint.ipynb b/test_functions2/.ipynb_checkpoints/Untitled-checkpoint.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..363fcab7ed6e9634e198cf5555ceb88932c9a245
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/Untitled-checkpoint.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/test_functions2/.ipynb_checkpoints/WeldedBeam-checkpoint.py b/test_functions2/.ipynb_checkpoints/WeldedBeam-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1fd4d446c972834fc592de6b1484c772ea820ac
--- /dev/null
+++ b/test_functions2/.ipynb_checkpoints/WeldedBeam-checkpoint.py
@@ -0,0 +1,94 @@
+import torch
+import numpy as np
+
+#
+#
+# WeldedBeam: 4D objective, 5 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+def WeldedBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+
+ C1 = 1.10471
+ C2 = 0.04811
+ C3 = 14.0
+ fx = torch.zeros(individuals.shape[0], 1)
+ gx1 = torch.zeros(individuals.shape[0], 1)
+ gx2 = torch.zeros(individuals.shape[0], 1)
+ gx3 = torch.zeros(individuals.shape[0], 1)
+ gx4 = torch.zeros(individuals.shape[0], 1)
+ gx5 = torch.zeros(individuals.shape[0], 1)
+
+ for i in range(individuals.shape[0]):
+
+ x = individuals[i,:]
+
+ h = x[0]
+ l = x[1]
+ t = x[2]
+ b = x[3]
+
+ test_function = - ( C1*h*h*l + C2*t*b*(C3+l) )
+ fx[i] = test_function
+
+ ## Calculate constraints terms
+ tao_dx = 6000 / (np.sqrt(2)*h*l)
+
+ tao_dxx = 6000*(14+0.5*l)*np.sqrt( 0.25*(l**2 + (h+t)**2 ) ) / (2* (0.707*h*l * ( l**2 /12 + 0.25*(h+t)**2 ) ) )
+
+ tao = np.sqrt( tao_dx**2 + tao_dxx**2 + l*tao_dx*tao_dxx / np.sqrt(0.25*(l**2 + (h+t)**2)) )
+
+ sigma = 504000/ (t**2 * b)
+
+ P_c = 64746*(1-0.0282346*t)* t * b**3
+
+ delta = 2.1952/ (t**3 *b)
+
+
+ ## Calculate 5 constraints
+ g1 = (-1) * (13600- tao)
+ g2 = (-1) * (30000 - sigma)
+ g3 = (-1) * (b - h)
+ g4 = (-1) * (P_c - 6000)
+ g5 = (-1) * (0.25 - delta)
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5), 1)
+ return gx, fx
+
+
+def WeldedBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ h = (X[:,0] * (10-0.125) + 0.125 ).reshape(X.shape[0],1)
+ l = (X[:,1] * (15-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ t = (X[:,2] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ b = (X[:,3] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((h, l, t, b), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions2/.ipynb_checkpoints/__init__-checkpoint.py b/test_functions2/.ipynb_checkpoints/__init__-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions2/.ipynb_checkpoints/input-checkpoint.txt b/test_functions2/.ipynb_checkpoints/input-checkpoint.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions2/.ipynb_checkpoints/output-checkpoint.txt b/test_functions2/.ipynb_checkpoints/output-checkpoint.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions2/.ipynb_checkpoints/untitled-checkpoint.py b/test_functions2/.ipynb_checkpoints/untitled-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions2/Ackley10D.py b/test_functions2/Ackley10D.py
new file mode 100644
index 0000000000000000000000000000000000000000..bcbdd92651d536b2ce473e5d94d9f7847109c582
--- /dev/null
+++ b/test_functions2/Ackley10D.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley10D: 10D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 10
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley10D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Ackley2D.py b/test_functions2/Ackley2D.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed442f5037a6bebce0548f07faeb4bd5bbb5c7f1
--- /dev/null
+++ b/test_functions2/Ackley2D.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley2D: 2D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley2D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley2D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Ackley2DEmbedd.py b/test_functions2/Ackley2DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..09e983a179ba11e87fbaa95599132fa627e2f6c0
--- /dev/null
+++ b/test_functions2/Ackley2DEmbedd.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Ackley2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Ackley2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15-5
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/Ackley500D.py b/test_functions2/Ackley500D.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee928e3b651d44c0c2b523d1cfbc6ab5d296c93a
--- /dev/null
+++ b/test_functions2/Ackley500D.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def Ackley500D(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) - 1000 # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1) - 115 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def Ackley500D_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Ackley6D.py b/test_functions2/Ackley6D.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c48a191cd35d9cf785c777aea245f622df5b54c
--- /dev/null
+++ b/test_functions2/Ackley6D.py
@@ -0,0 +1,85 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+#
+#
+# Ackley6D: 6D objective, 2 constraints
+#
+# Reference:
+# Eriksson D, Poloczek M (2021) Scalable con-
+# strained bayesian optimization. In: Interna-
+# tional Conference on Artificial Intelligence and
+# Statistics, PMLR, pp 730–738
+#
+#
+
+def Ackley6D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = 6
+ fun = Ackley(dim=dimm, negate=True).to(dtype=dtype, device=device)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+
+def Ackley6D_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 6, "Input must be an n-by-6 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/AckleyND.py b/test_functions2/AckleyND.py
new file mode 100644
index 0000000000000000000000000000000000000000..638f92e9fb5cb852545b6bae1b7d729e428f3e99
--- /dev/null
+++ b/test_functions2/AckleyND.py
@@ -0,0 +1,75 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def AckleyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Ackley(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5)
+ fun.bounds[1, :].fill_(10)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ gx2 = gx2.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+
+ return gx, fx
+
+
+
+def AckleyND_Scaling(X):
+ # print(X.shape)
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15.0 - 5.0
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Branin2DEmbedd.py b/test_functions2/Branin2DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba11caa4938034d78f3221b465c85a7efa55eb24
--- /dev/null
+++ b/test_functions2/Branin2DEmbedd.py
@@ -0,0 +1,38 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Branin
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Branin2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Branin(negate=True)
+ fun.bounds[0, 0].fill_(-5.0)
+ fun.bounds[1, 0].fill_(10.0)
+ fun.bounds[0, 1].fill_(0.0)
+ fun.bounds[1, 1].fill_(15.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Branin2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled[:,1] = X_scaled[:,1]*15-5
+ X_scaled[:,2] = X_scaled[:,2]*15
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/Bukin.py b/test_functions2/Bukin.py
new file mode 100644
index 0000000000000000000000000000000000000000..562576be84619a079760227f4d009334e4151ae9
--- /dev/null
+++ b/test_functions2/Bukin.py
@@ -0,0 +1,46 @@
+import torch
+import numpy as np
+from botorch.test_functions import Ackley
+device = torch.device("cpu")
+dtype = torch.double
+
+# class Bukin(SyntheticTestFunction):
+
+# dim = 2
+# _bounds = [(-15.0, -5.0), (-3.0, 3.0)]
+# _optimal_value = 0.0
+# _optimizers = [(-10.0, 1.0)]
+# _check_grad_at_opt: bool = False
+
+
+# [docs]
+# def evaluate_true(self, X: Tensor) -> Tensor:
+# part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+# part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+# return part1 + part2
+
+
+def Bukin(X):
+
+ part1 = 100.0 * torch.sqrt(torch.abs(X[..., 1] - 0.01 * X[..., 0] ** 2))
+ part2 = 0.01 * torch.abs(X[..., 0] + 10.0)
+ fx = part1 + part2
+
+ return fx
+
+def Bukin_Scaling(X):
+ X_scaled = torch.zeros(X.shape)
+
+ X_scaled[:,0] = -(X[..., 0]*10+5)
+ X_scaled[:,1] = X[..., 0]*6-3
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions2/CantileverBeam.py b/test_functions2/CantileverBeam.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0599ce7836e96aa76ce1fc59780e34f61d8e170
--- /dev/null
+++ b/test_functions2/CantileverBeam.py
@@ -0,0 +1,193 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CantileverBeam: 10D objective, 11 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+
+
+
+
+
+def CantileverBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+
+ P = 50000
+ E = 2*107
+ L = 100
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1*x6*L + x2*x7*L + x3*x8*L + x4*x9*L + x5*x10*L )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 600 * P / (x5*x10*x10) - 14000
+ g2 = 6 * P * (L*2) / (x4*x9*x9) - 14000
+ g3 = 6 * P * (L*3) / (x3*x8*x8) - 14000
+ g4 = 6 * P * (L*4) / (x2*x7*x7) - 14000
+ g5 = 6 * P * (L*5) / (x1*x6*x6) - 14000
+ g6 = P* L**3 * (1/L + 7/L + 19/L + 37/L + 61/L) / (3*E) -2.7
+ g7 = x10/x5 - 20
+ g8 = x9/x4 - 20
+ g9 = x8/x3 - 20
+ g10 = x7/x2 - 20
+ g11 = x6/x1 - 20
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+ gx10.append( g10 )
+ gx11.append( g11 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx10 = torch.tensor(gx10)
+ gx10 = gx4.reshape((n, 1))
+
+ gx11 = torch.tensor(gx11)
+ gx11 = gx4.reshape((n, 1))
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10, gx11), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def CantileverBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ x1 = (X[:,0] * (5-1) + 1).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (5-1) + 1).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (5-1) + 1).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (5-1) + 1).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (5-1) + 1).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (65-30) + 30).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (65-30) + 30).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (65-30) + 30).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (65-30) + 30).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (65-30) + 30).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Car.py b/test_functions2/Car.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7193b96109cd5fc9c3f4ff3a5661bb344338e60
--- /dev/null
+++ b/test_functions2/Car.py
@@ -0,0 +1,253 @@
+import torch
+import numpy as np
+
+
+#
+#
+# Car: 11D objective, 10 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def Car(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def Car_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ x1 = (X[:,0] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (1.35-0.45) + 0.45).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1.5-0.5) + 0.5).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x9 = (X[:,8] * (0.345-0.192) + 0.192).reshape(X.shape[0],1)
+ x10 = (X[:,9] * (-20)).reshape(X.shape[0],1)
+ x11 = (X[:,10] * (-20)).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11), dim=1)
+ return X_scaled
+
+
+
+
+
+
+def Car_softpen(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 11, "Input must be an n-by-11 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros((n,1))
+ gx1 = torch.zeros((n,1))
+ gx2 = torch.zeros((n,1))
+ gx3 = torch.zeros((n,1))
+ gx4 = torch.zeros((n,1))
+ gx5 = torch.zeros((n,1))
+ gx6 = torch.zeros((n,1))
+ gx7 = torch.zeros((n,1))
+ gx8 = torch.zeros((n,1))
+ gx9 = torch.zeros((n,1))
+ gx10 = torch.zeros((n,1))
+ gx11 = torch.zeros((n,1))
+
+
+ n = individuals.size(0)
+
+ # Set function and constraints here:
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+ x9 = x[8]
+ x10 = x[9]
+ x11 = x[10]
+
+
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 1.98 + 4.90*x1 + 6.67*x2 + 6.98*x3 + 4.01*x4 + 1.78*x5 + 2.73*x7 )
+
+
+ ## Calculate constraints terms
+ g1 = 1.16 - 0.3717*x2*x4 - 0.00931*x2*x10 - 0.484*x3*x9 + 0.01343*x6*x10 -1
+
+ g2 = (0.261 - 0.0159*x1*x2 - 0.188*x1*x8
+ - 0.019*x2*x7 + 0.0144*x3*x5 + 0.0008757*x5*x10
+ + 0.08045*x6*x9 + 0.00139*x8*x11 + 0.00001575*x10*x11) -0.9
+
+ g3 = (0.214 + 0.00817*x5 - 0.131*x1*x8 - 0.0704*x1*x9 + 0.03099*x2*x6
+ -0.018*x2*x7 + 0.0208*x3*x8 + 0.121*x3*x9 - 0.00364*x5*x6
+ +0.0007715*x5*x10 - 0.0005354*x6*x10 + 0.00121*x8*x11) -0.9
+
+ g4 = 0.74 -0.061*x2 -0.163*x3*x8 +0.001232*x3*x10 -0.166*x7*x9 +0.227*x2*x2 -0.9
+
+ g5 = 28.98 +3.818*x3-4.2*x1*x2+0.0207*x5*x10+6.63*x6*x9-7.7*x7*x8+0.32*x9*x10 -32
+
+ g6 = 33.86 +2.95*x3+0.1792*x10-5.057*x1*x2-11.0*x2*x8-0.0215*x5*x10-9.98*x7*x8+22.0*x8*x9 -32
+
+ g7 = 46.36 -9.9*x2-12.9*x1*x8+0.1107*x3*x10 -32
+
+ g8 = 4.72 -0.5*x4-0.19*x2*x3-0.0122*x4*x10+0.009325*x6*x10+0.000191*x11**2 -4
+
+ g9 = 10.58 -0.674*x1*x2-1.95*x2*x8+0.02054*x3*x10-0.0198*x4*x10+0.028*x6*x10 -9.9
+
+ g10 = 16.45 -0.489*x3*x7-0.843*x5*x6+0.0432*x9*x10-0.0556*x9*x11-0.000786*x11**2 -15.7
+
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+ gx6[i] = g6
+ gx7[i] = g7
+ gx8[i] = g8
+ gx9[i] = g9
+ gx10[i] = g10
+ fx[i] = test_function
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9, gx10), 1)
+
+ cost = gx
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ fx = fx + cost
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/CompressionSpring.py b/test_functions2/CompressionSpring.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5443f7da043f74660ae96e1c1867f69101013d4
--- /dev/null
+++ b/test_functions2/CompressionSpring.py
@@ -0,0 +1,100 @@
+import torch
+import numpy as np
+
+
+#
+#
+# CompressionSpring: 8D objective, 6 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+
+def CompressionSpring(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ d = x[0]
+ D = x[1]
+ N = x[2]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( (N+2)*D*d**2 )
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 1 - ( D*D*D * N / (71785* d*d*d*d) )
+ g2 = (4*D*D - D*d) / (12566 * (D*d*d*d - d*d*d*d)) + 1/(5108*d*d) - 1
+ g3 = 1 - 140.45*d / (D*D * N)
+ g4 = (D+d)/1.5 - 1
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+
+ return gx, fx
+
+
+
+def CompressionSpring_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ d = (X[:,0] * ( 1 - 0.05 ) + 0.05 ).reshape(X.shape[0],1)
+ D = (X[:,1] * ( 1.3 - 0.25 ) + 0.25 ).reshape(X.shape[0],1)
+ N = (X[:,2] * ( 15 - 2 ) + 2 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((d, D, N), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions2/DixonPriceND.py b/test_functions2/DixonPriceND.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406802fb9029db8327a08acf6601783ba9d5a51
--- /dev/null
+++ b/test_functions2/DixonPriceND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DixonPriceND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = DixonPrice(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def DixonPriceND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/DummyFixConsDim.py b/test_functions2/DummyFixConsDim.py
new file mode 100644
index 0000000000000000000000000000000000000000..de6e1b6b1ad0683d3064bc42d6a58c62c905d4ab
--- /dev/null
+++ b/test_functions2/DummyFixConsDim.py
@@ -0,0 +1,28 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def DummyFixConsDim(individuals):
+ n = individuals.size(0)
+ GX = torch.rand(n, 20)
+ Y = torch.rand(n, 1)
+
+ return GX, Y
+
+
+
+def DummyFixConsDim_Scaling(X):
+
+ X_scaled = X
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/Finder24.py b/test_functions2/Finder24.py
new file mode 100644
index 0000000000000000000000000000000000000000..9f7a4752b9e54183f145947fa4f06c51283ca754
--- /dev/null
+++ b/test_functions2/Finder24.py
@@ -0,0 +1,172 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ # START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z, n_candidate=None):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+
+ if n_candidate==None:
+ n_candidate = 2000
+
+ Z_samples = sobol.draw(n_candidate)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions2/Finder24_no_timer.py b/test_functions2/Finder24_no_timer.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd3e0475a77fe66303e3dd345bc0aec41ece7fe5
--- /dev/null
+++ b/test_functions2/Finder24_no_timer.py
@@ -0,0 +1,173 @@
+import numpy as np
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import numpy as np
+# %matplotlib inline
+import matplotlib.pyplot as plt
+
+import plotly.graph_objects as go
+from datasets import *
+from models import MLP, SNMLP
+from torch.quasirandom import SobolEngine
+import time
+import sys
+
+def LV_embedding(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_Adam_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_AdamW(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.AdamW(list(encoder.parameters()) + list(decoder.parameters()), lr=1e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_AdamW_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def LV_embedding_5e4(X, iters):
+ X = X.clone()
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+ X = X.to(device)
+ print(device)
+ ambient_dim = X.size(-1)
+
+ width = ambient_dim * 16
+ # Note in particular the lack of the bottleneck choice below
+ encoder = MLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+ # Note also the change in the decoder to have spectral normalization
+ decoder = SNMLP(ambient_dim, ambient_dim, [width] * 4).to(device)
+
+ opt = torch.optim.Adam(list(encoder.parameters()) + list(decoder.parameters()), lr=5e-4)
+
+ η, λ = 0.01, 0.03
+
+ START_TIME = time.time()
+
+ for i in range(iters):
+ opt.zero_grad()
+ z = encoder(X)
+ rec_loss = F.mse_loss(decoder(z), X)
+ # Note below the least volume loss
+ vol_loss = torch.exp(torch.log(z.std(0) + η).mean())
+ loss = rec_loss + λ * vol_loss
+ loss.backward()
+ opt.step()
+
+ if (i+1) % 1000 == 0:
+ print('Epoch {}: rec = {}, vol = {}'.format(i, rec_loss, vol_loss))
+ END_TIME = time.time()
+ INTERVAL = END_TIME-START_TIME
+ f = open("/home/gridsan/ryu/Bank_High_DIM/LVAE_Test_July9/LV_embedding_5e4_July9.txt", "a")
+ f.write('Epoch {}: rec = {}, vol = {}, Time: {}'.format(i, rec_loss, vol_loss, INTERVAL))
+ f.write('\n')
+ f.close()
+
+ encoder.eval()
+ decoder.eval()
+
+ with torch.no_grad():
+ z = encoder(X)
+ idx = z.std(0).argsort(descending=True)
+
+ return z.to('cpu'), z.std(0).to('cpu'), idx.to('cpu'), encoder.to('cpu'), decoder.to('cpu')
+
+
+def sampling_z(z):
+ z_dim = z.shape[1]
+
+ sobol = SobolEngine(z_dim, scramble=True)
+ Z_samples = sobol.draw(2000)
+
+ for ii in range(z_dim):
+ Z_samples[:,ii] = Z_samples[:,ii] * (z[:,ii].max() - z[:,ii].min()) + z[:,ii].min()
+
+ return Z_samples
+
+
+
+
+
diff --git a/test_functions2/GKXWC1.py b/test_functions2/GKXWC1.py
new file mode 100644
index 0000000000000000000000000000000000000000..2dfa59da9637b4c64377a6e6471c742f9f9c53f3
--- /dev/null
+++ b/test_functions2/GKXWC1.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC1: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+
+def GKXWC1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+ for x in individuals:
+ g = np.cos(x[0])*np.cos(x[1]) - np.sin(x[0])*np.sin(x[1]) -0.5
+ fx.append( - np.cos(2*x[0])*np.cos(x[1]) - np.sin(x[0]) )
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+ return gx, fx
+
+
+def GKXWC1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/GKXWC2.py b/test_functions2/GKXWC2.py
new file mode 100644
index 0000000000000000000000000000000000000000..5db203c32b693009590b8e9b9b79177d3cc3bba9
--- /dev/null
+++ b/test_functions2/GKXWC2.py
@@ -0,0 +1,80 @@
+import torch
+import numpy as np
+
+#
+#
+# GKXWC2: 2D objective, 1 constraints
+#
+# Reference:
+# Gardner JR, Kusner MJ, Xu ZE, et al (2014)
+# Bayesian optimization with inequality con-
+# straints. In: ICML, pp 937–945
+#
+#
+
+def GKXWC2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ g = np.sin(x[0])*np.sin(x[1]) + 0.95
+ fx.append( - np.sin(x[0]) - x[1] ) # maximize -(x1^2 +x 2^2)
+ gx.append( g )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+def GKXWC2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ X_scaled = X*6;
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Griewank2DEmbedd.py b/test_functions2/Griewank2DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e6128b1f5987182c740bab54875152b58635979
--- /dev/null
+++ b/test_functions2/Griewank2DEmbedd.py
@@ -0,0 +1,36 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Griewank2DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2]]
+
+ n = X.size(0)
+ dimm = 2
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Griewank2DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ X_scaled = X_scaled * 1200 - 600
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/GriewankND.py b/test_functions2/GriewankND.py
new file mode 100644
index 0000000000000000000000000000000000000000..1406c4f067885c9d6c726f526688c222b89c8a3a
--- /dev/null
+++ b/test_functions2/GriewankND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Griewank
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def GriewankND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Griewank(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-600.0)
+ fun.bounds[1, :].fill_(600.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def GriewankND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*1200-600
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/Hartmann6DEmbedd.py b/test_functions2/Hartmann6DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..94115986eb19db5747d36fcd38d7ffc5308af125
--- /dev/null
+++ b/test_functions2/Hartmann6DEmbedd.py
@@ -0,0 +1,35 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Hartmann
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Hartmann6DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[0,1,2,3,4,5]]
+ n = X.size(0)
+ dimm = 6
+ fun = Hartmann(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(1.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Hartmann6DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/HeatExchanger.py b/test_functions2/HeatExchanger.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f74bb6ed047a5537a898628f467e732d71e9669
--- /dev/null
+++ b/test_functions2/HeatExchanger.py
@@ -0,0 +1,191 @@
+import torch
+import numpy as np
+
+#
+#
+# HeatExchanger: 8D objective, 6 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+
+def HeatExchanger(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ x1 = x[0]
+ x2 = x[1]
+ x3 = x[2]
+ x4 = x[3]
+ x5 = x[4]
+ x6 = x[5]
+ x7 = x[6]
+ x8 = x[7]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( x1+x2+x3 )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 0.0025 * (x4+x6) - 1
+ g2 = 0.0025 * (x5 + x7 - x4) - 1
+ g3 = 0.01 *(x8-x5) - 1
+ g4 = 833.33252*x4 + 100*x1 - x1*x6 - 83333.333
+ g5 = 1250*x5 + x2*x4 - x2*x7 - 125*x4
+ g6 = x3*x5 - 2500*x5 - x3*x8 + 125*10000
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6), 1)
+
+
+ return gx, fx
+
+
+
+
+
+def HeatExchanger_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 8, "Input must be an n-by-8 PyTorch tensor."
+
+ x1 = (X[:,0] * (10000-100) + 100).reshape(X.shape[0],1)
+ x2 = (X[:,1] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x3 = (X[:,2] * (10000-1000) + 1000).reshape(X.shape[0],1)
+ x4 = (X[:,3] * (1000-10) + 10).reshape(X.shape[0],1)
+ x5 = (X[:,4] * (1000-10) + 10).reshape(X.shape[0],1)
+ x6 = (X[:,5] * (1000-10) + 10).reshape(X.shape[0],1)
+ x7 = (X[:,6] * (1000-10) + 10).reshape(X.shape[0],1)
+ x8 = (X[:,7] * (1000-10) + 10).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((x1, x2, x3, x4, x5, x6, x7, x8), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/JLH1.py b/test_functions2/JLH1.py
new file mode 100644
index 0000000000000000000000000000000000000000..27b7f05394a22a18d0349cbe2632c31c471a83b7
--- /dev/null
+++ b/test_functions2/JLH1.py
@@ -0,0 +1,57 @@
+import torch
+import numpy as np
+
+#
+# JLH1: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+def JLH1(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+ test_function = (- (x[0]-0.5)**2 - (x[1]-0.5)**2 )
+ fx.append(test_function)
+ gx.append( x[0] + x[1] - 0.75 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+
+
+def JLH1_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/JLH2.py b/test_functions2/JLH2.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ce7c5e5e65c8fbfda31d4485babc0a84bf6f1aa
--- /dev/null
+++ b/test_functions2/JLH2.py
@@ -0,0 +1,68 @@
+import torch
+import numpy as np
+
+
+#
+# JLH2: 2D objective, 1 constraints
+#
+#
+# Reference:
+# Jetton C, Li C, Hoyle C (2023) Constrained
+# bayesian optimization methods using regres-
+# sion and classification gaussian processes as
+# constraints. In: International Design Engi-
+# neering Technical Conferences and Computers
+# and Information in Engineering Conference,
+# American Society of Mechanical Engineers, p
+# V03BT03A033
+#
+#
+
+
+def JLH2(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ fx = []
+ gx = []
+
+ for x in individuals:
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( np.cos(2*x[0])*np.cos(x[1]) + np.sin(x[0]) )
+
+ fx.append(test_function)
+ gx.append( ((x[0]+5)**2)/4 + (x[1]**2)/100 -2.5 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+ gx = torch.tensor(gx)
+ gx = torch.reshape(gx, (len(gx),1))
+
+ return gx, fx
+
+
+
+def JLH2_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ # X = individuals
+ X1 = X[:,0].reshape(X.size(0),1)
+ X1 = X1*5-5
+ X2 = X[:,1].reshape(X.size(0),1)
+ X2 = X2*10-5
+ X_scaled = torch.tensor(np.concatenate((X1,X2), axis=1))
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/KeaneBump.py b/test_functions2/KeaneBump.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ff354c8c76334acb87fbbaac3baf79d1ac2fa23
--- /dev/null
+++ b/test_functions2/KeaneBump.py
@@ -0,0 +1,88 @@
+import torch
+import numpy as np
+
+#
+#
+# KeaneBump: N-D objective (can take data of different dimention; we use 18),
+# 2 constraints
+#
+# Reference:
+# Keane A (1994) Experiences with optimizers in
+# structural design. In: Proceedings of the con-
+# ference on adaptive computing in engineering
+# design and control, pp 14–27
+#
+#
+
+
+
+def KeaneBump(X):
+
+
+
+ fx = torch.zeros(X.shape[0], 1)
+ gx1 = torch.zeros(X.shape[0], 1)
+ gx2 = torch.zeros(X.shape[0], 1)
+
+
+
+ for i in range(X.shape[0]):
+ x = X[i,:]
+
+ cos4 = 0
+ cos2 = 1
+ sq_denom = 0
+
+ pi_sum = 1
+ sigma_sum = 0
+
+ for j in range(X.shape[1]):
+ cos4 += torch.cos(x[j]) ** 4
+ cos2 *= torch.cos(x[j]) ** 2
+ sq_denom += (j+1) * (x[j])**2
+
+ pi_sum *= x[j]
+ sigma_sum += x[j]
+
+
+ # Objective
+ test_function = torch.abs( (cos4 - 2*cos2) / torch.sqrt(sq_denom) )
+ fx[i] = test_function
+
+ # Constraints
+ gx1[i] = 0.75 - pi_sum
+ gx2[i] = sigma_sum - 7.5* (X.shape[1])
+
+ gx = torch.cat((gx1, gx2), 1)
+ return gx, fx
+
+
+
+
+
+def KeaneBump_Scaling(X):
+
+ X_scaled = X*10
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/LevyND.py b/test_functions2/LevyND.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b0c6e40d653c0b964655eb80c5d87787506ec3a
--- /dev/null
+++ b/test_functions2/LevyND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Levy
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def LevyND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Levy(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-10.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def LevyND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*20-10
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/MOPTA08_Car.py b/test_functions2/MOPTA08_Car.py
new file mode 100644
index 0000000000000000000000000000000000000000..09894738e0c6f340e6feb5cc8119726fd81ac95c
--- /dev/null
+++ b/test_functions2/MOPTA08_Car.py
@@ -0,0 +1,133 @@
+import os
+import subprocess
+import sys
+import tempfile
+from pathlib import Path
+from platform import machine
+
+import numpy as np
+import torch
+import stat
+
+
+def MOPTA08_Car_single(x):
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ sysarch = 64 if sys.maxsize > 2 ** 32 else 32
+ # machine = machine().lower()
+
+ # if machine == "armv7l":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_armhf.bin"
+ # elif machine == "x86_64":
+ # assert sysarch == 64, "Not supported"
+ # mopta_exectutable = "mopta08_elf64.bin"
+ # elif machine == "i386":
+ # assert sysarch == 32, "Not supported"
+ # mopta_exectutable = "mopta08_elf32.bin"
+ # else:
+ # raise RuntimeError("Machine with this architecture is not supported")
+
+ machine = "x86_64"
+ mopta_exectutable = "mopta08_elf64.bin"
+
+ mopta_full_path = os.path.join(
+ "mopta08", mopta_exectutable
+ )
+ # print(mopta_full_path)
+
+ directory_file_descriptor = tempfile.TemporaryDirectory()
+ # directory_name = directory_file_descriptor.name
+ directory_name = Path(__file__).parent
+
+ ##########################################################################################
+ # Input here
+ # if x == None:
+ # x = np.random.rand(124)
+ # print(x.shape)
+ ##########################################################################################
+ with open(os.path.join(directory_name, "input.txt"), "w+") as tmp_file:
+ for _x in x:
+ tmp_file.write(f"{_x}\n")
+ popen = subprocess.Popen(
+ mopta_full_path,
+ # '#!/home/rosen/Dropbox (MIT)/Rosen_DeC0De/MOPTA_Test/mopta08/mopta08_elf64.bin',
+ stdout=subprocess.PIPE,
+ cwd=directory_name,
+ shell=True,
+ )
+ popen.wait()
+
+ with open(os.path.join(directory_name, "output.txt"), "r") as tmp_file:
+ output = (
+ tmp_file
+ .read()
+ .split("\n")
+ )
+ # print(output)
+ # print(x)
+ # print(output)
+ output = [x.strip() for x in output]
+ output = np.array([float(x) for x in output if len(x) > 0])
+ value = output[0]
+ constraints = output[1:]
+ # print(value, constraints)
+
+ return constraints, value
+
+
+
+def MOPTA08_Car(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = -fx
+
+ return GX, FX
+
+
+
+
+def MOPTA08_Car_softpen(X):
+ GX = torch.zeros(X.shape[0], 68)
+ FX = torch.zeros(X.shape[0], 1)
+ for ii in range(X.shape[0]):
+ input_x = X[ii,:].numpy()
+ gx, fx = MOPTA08_Car_single(input_x)
+ GX[ii,:] = torch.from_numpy(gx)
+ FX[ii,:] = fx
+
+ cost = GX
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ FX = FX + cost
+
+ return GX, -FX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Mazda.py b/test_functions2/Mazda.py
new file mode 100644
index 0000000000000000000000000000000000000000..52f586cbf98f52df78c8d6e9ba0045535a113602
--- /dev/null
+++ b/test_functions2/Mazda.py
@@ -0,0 +1,242 @@
+import os
+import subprocess
+import stat
+import pandas as pd
+import torch
+import numpy as np
+
+
+
+def Mazda(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+def Mazda_softpen(init_samples):
+ ##########################################
+ # Scaling
+ ##########################################
+
+ # Define the path to your Excel file
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/Info_Mazda_CdMOBP_edited.xlsx'
+
+ # Read the Excel file into a DataFrame
+ dataframe = pd.read_excel(file_path, sheet_name='Explain_DV_and_Const.')
+
+ # Display the DataFrame to ensure it has been read correctly
+ bounds = dataframe.values[1:, 1:3]
+ bounds_tensor = torch.tensor(bounds, dtype=torch.float32)
+ # print(bounds_tensor.shape)
+
+ range_bounds = bounds_tensor[:,1] - bounds_tensor[:,0]
+
+ scaled_samples = init_samples * range_bounds + bounds_tensor[:,0]
+ # print(scaled_samples)
+
+ # Convert the torch tensor to a numpy array
+ data_numpy_back = scaled_samples.numpy()
+
+ # Create a pandas DataFrame from the numpy array
+ dataframe_back = pd.DataFrame(data_numpy_back)
+
+ # Write the DataFrame to a text file with space-separated values
+ output_file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_vars_eval.txt'
+
+ dataframe_back.to_csv(output_file_path, sep='\t', header=False, index=False)
+ #####################
+ #####################
+
+
+ #####################
+ # Run Bash file
+ #####################
+
+ # Change the current working directory
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2')
+
+ # Get the current permissions of the file
+ current_permissions = os.stat(os.getcwd()).st_mode
+
+ # Add execute permissions for the owner, group, and others
+ new_permissions = current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+
+ # Apply the new permissions
+ os.chmod(os.getcwd(), new_permissions)
+
+ # Script name
+ script_name = 'run.sh'
+
+ # Run the bash script in the background
+ process = subprocess.Popen(['bash', script_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, start_new_session=True)
+ process.wait()
+
+ # Optional: capture the output and error messages
+ stdout, stderr = process.communicate()
+
+ os.chdir('/home/turbo/rosenyu/Bank_High_DIM/')
+ # print(os.getcwd())
+ #####################
+ #####################
+
+
+ #####################
+ # Read in objective and constraints
+ #####################
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_objs_eval.txt'
+ objs_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ objs_data_numpy = objs_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ objs_data_tensor = torch.tensor(objs_data_numpy, dtype=torch.float32)
+ objs_data_tensor = objs_data_tensor[:,0].reshape(objs_data_tensor.shape[0],1)
+
+
+
+ # Read the data from the file into a pandas DataFrame
+ file_path = '/home/turbo/rosenyu/Bank_High_DIM/Mazda_CdMOBP/Mazda_CdMOBP/rosen_sample_t2/pop_cons_eval.txt'
+ cons_dataframe = pd.read_csv(file_path, delim_whitespace=True, header=None)
+
+ # Convert the DataFrame to a numpy array
+ cons_data_numpy = cons_dataframe.values
+
+ # Convert the numpy array to a torch tensor
+ cons_data_tensor = torch.tensor(cons_data_numpy, dtype=torch.float32)
+
+
+
+ cost = cons_data_tensor
+ cost[cost<0] = 0
+ cost = cost.sum(dim=1).reshape(cost.shape[0], 1)
+ objs_data_tensor = objs_data_tensor + cost
+
+
+ # print(objs_data_tensor)
+ # print(cons_data_tensor)
+ return cons_data_tensor, -objs_data_tensor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/MichalewiczND.py b/test_functions2/MichalewiczND.py
new file mode 100644
index 0000000000000000000000000000000000000000..55cd932393e207d7deb9ddebde8b93a408c48400
--- /dev/null
+++ b/test_functions2/MichalewiczND.py
@@ -0,0 +1,59 @@
+import torch
+import numpy as np
+import math
+from botorch.test_functions.synthetic import Michalewicz
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def MichalewiczND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Michalewicz(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(0.0)
+ fun.bounds[1, :].fill_(math.pi)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def MichalewiczND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*math.pi
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/PressureVessel.py b/test_functions2/PressureVessel.py
new file mode 100644
index 0000000000000000000000000000000000000000..eeefcd177c3ec800e56c2a3b1b9ca4c573e79990
--- /dev/null
+++ b/test_functions2/PressureVessel.py
@@ -0,0 +1,169 @@
+import torch
+import numpy as np
+
+#
+#
+# PressureVessel: 4D objective, 4 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def PressureVessel(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ C1 = 0.6224
+ C2 = 1.7781
+ C3 = 3.1661
+ C4 = 19.84
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ Ts = x[0]
+ Th = x[1]
+ R = x[2]
+ L = x[3]
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( C1*Ts*R*L + C2*Th*R*R + C3*Ts*Ts*L + C4*Ts*Ts*R )
+ fx.append(test_function)
+
+
+ g1 = -Ts + 0.0193*R
+ g2 = -Th + 0.00954*R
+ g3 = (-1)*np.pi*R*R*L + (-1)*4/3*np.pi*R*R*R + 750*1728
+ g4 = L-240
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def PressureVessel_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ Ts = (X[:,0] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ Th = (X[:,1] * (98*0.0625) + 0.0625).reshape(X.shape[0],1)
+ R = (X[:,2] * (200-10) + 10).reshape(X.shape[0],1)
+ L = (X[:,3] * (200-10) ).reshape(X.shape[0],1)
+
+
+ X_scaled = torch.cat((Ts, Th, R, L), dim=1)
+
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/ReinforcedConcreteBeam.py b/test_functions2/ReinforcedConcreteBeam.py
new file mode 100644
index 0000000000000000000000000000000000000000..1729e66ee7ac88f8fe7fdc60b984b8ba6d784a72
--- /dev/null
+++ b/test_functions2/ReinforcedConcreteBeam.py
@@ -0,0 +1,90 @@
+import torch
+import numpy as np
+
+#
+#
+# ReinforcedConcreteBeam: 3D objective, 9 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+
+def ReinforcedConcreteBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+
+
+ n = individuals.size(0)
+
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+ As = x[0]
+ h = x[1]
+ b = x[2]
+
+
+ test_function = - ( 29.4*As + 0.6*b*h )
+ fx.append(test_function)
+
+ g1 = h/b - 4
+ g2 = 180 + 7.35*As*As/b - As*h
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2), 1)
+
+
+
+ return gx, fx
+
+
+
+
+def ReinforcedConcreteBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 3, "Input must be an n-by-3 PyTorch tensor."
+
+ As = (X[:,0] * (15-0.2) + 0.2).reshape(X.shape[0],1)
+ b = (X[:,1] * (40-28) +28).reshape(X.shape[0],1)
+ h = (X[:,2] * 5 + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((As, b, h), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Rosenbrock3DEmbedd.py b/test_functions2/Rosenbrock3DEmbedd.py
new file mode 100644
index 0000000000000000000000000000000000000000..1625595859baca53628812cede1b6f68f8e7ea14
--- /dev/null
+++ b/test_functions2/Rosenbrock3DEmbedd.py
@@ -0,0 +1,40 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+def Rosenbrock3DEmbedd(X_input):
+ # assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+ # Set function here:
+ X = X_input[:,[1,2,3]]
+ n = X.size(0)
+ dimm = 3
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-2.0)
+ fun.bounds[1, :].fill_(2.0)
+
+
+ dim = fun.dim
+ lb, ub = fun.bounds
+
+ fx = fun(X)
+ fx = fx.reshape((n, 1))
+ gx = 0
+ return gx, fx
+
+
+
+def Rosenbrock3DEmbedd_Scaling(X):
+ X_scaled = X.clone()
+
+ X_scaled[:,1] = X_scaled[:,1]*4 - 2
+ X_scaled[:,2] = X_scaled[:,2]*4 - 2
+ X_scaled[:,3] = X_scaled[:,3]*4 - 2
+
+ return X_scaled
+
+
+
+
diff --git a/test_functions2/RosenbrockND.py b/test_functions2/RosenbrockND.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb46001f9d022a9a9f4a73633f2a89dc882f44a3
--- /dev/null
+++ b/test_functions2/RosenbrockND.py
@@ -0,0 +1,58 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+ fun = Rosenbrock(dim=dimm, negate=True)
+ fun.bounds[0, :].fill_(-5.0)
+ fun.bounds[1, :].fill_(10.0)
+ dim = fun.dim
+ lb, ub = fun.bounds
+ #############################################################################
+ #############################################################################
+
+
+ n = individuals.size(0)
+
+ fx = fun(individuals)
+ fx = fx.reshape((n, 1))
+
+ #############################################################################
+ ## Constraints
+ # gx1 = torch.sum(individuals,1) # sigma(x) <= 0
+ # gx1 = gx1.reshape((n, 1))
+
+ # gx2 = torch.norm(individuals, p=2, dim=1)-5 # norm_2(x) -3 <= 0
+ # gx2 = gx2.reshape((n, 1))
+
+ # gx = torch.cat((gx1, gx2), 1)
+ #############################################################################
+
+ return 0, fx
+ # return gx, fx
+
+
+
+def RosenbrockND_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*15-5
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/RosenbrockND2.py b/test_functions2/RosenbrockND2.py
new file mode 100644
index 0000000000000000000000000000000000000000..635099799fbf64f4b501d187b19eecdd63c2e417
--- /dev/null
+++ b/test_functions2/RosenbrockND2.py
@@ -0,0 +1,56 @@
+import torch
+import numpy as np
+from botorch.test_functions.synthetic import Rosenbrock, Levy, DixonPrice
+device = torch.device("cpu")
+dtype = torch.double
+
+
+
+def RosenbrockND2(individuals):
+
+ # assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ #############################################################################
+ #############################################################################
+ # Set function here:
+ dimm = individuals.shape[1]
+
+
+ Rosenbrockfun = Rosenbrock(dim=dimm, negate=True)
+ Rosenbrockfun.bounds[0, :].fill_(-3.0)
+ Rosenbrockfun.bounds[1, :].fill_(5.0)
+
+ fx = Rosenbrockfun(individuals)
+ fx = fx.reshape(individuals.shape[0],1)
+
+ Levyfun = Levy(dim=dimm, negate=False)
+ Levyfun.bounds[0, :].fill_(-3.0)
+ Levyfun.bounds[1, :].fill_(5.0)
+
+
+ DixonPricefun = DixonPrice(dim=dimm, negate=False)
+ DixonPricefun.bounds[0, :].fill_(-3.0)
+ DixonPricefun.bounds[1, :].fill_(5.0)
+
+
+ G1 = Levyfun(individuals) -1e3
+ G2 = DixonPricefun(individuals) -4e7
+
+ gx = torch.cat((G1.reshape(individuals.shape[0],1), G2.reshape(individuals.shape[0],1)), 1)
+
+
+ return gx, fx
+
+
+def RosenbrockND2_Scaling(X):
+
+ # assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ X_scaled = X*8-3
+
+ return X_scaled
+
+
+
+
+
diff --git a/test_functions2/SpeedReducer.py b/test_functions2/SpeedReducer.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b8ec3cbabd1652d9d75361e332658fb06e7ff6b
--- /dev/null
+++ b/test_functions2/SpeedReducer.py
@@ -0,0 +1,188 @@
+import torch
+import numpy as np
+
+#
+#
+# SpeedReducer: 7D objective, 9 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+def SpeedReducer(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+ gx4 = []
+ gx5 = []
+ gx6 = []
+ gx7 = []
+ gx8 = []
+ gx9 = []
+ gx10 = []
+ gx11 = []
+
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+
+
+ b = x[0]
+ m = x[1]
+ z = x[2]
+ L1 = x[3]
+ L2 = x[4]
+ d1 = x[5]
+ d2 = x[6]
+
+ C1 = 0.7854*b*m*m
+ C2 = 3.3333*z*z + 14.9334*z - 43.0934
+ C3 = 1.508*b*(d1*d1 + d2*d2)
+ C4 = 7.4777*(d1*d1*d1 + d2*d2*d2)
+ C5 = 0.7854*(L1*d1*d1 + L2*d2*d2)
+
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 0.7854*b*m*m * (3.3333*z*z + 14.9334*z - 43.0934) - 1.508*b*(d1*d1 + d2*d2) + 7.4777*(d1*d1*d1 + d2*d2*d2) + 0.7854*(L1*d1*d1 + L2*d2*d2) )
+
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = 27/(b*m*m*z) - 1
+ g2 = 397.5/(b*m*m*z*z) - 1
+
+ g3 = 1.93*L1**3 /(m*z *d1**4) - 1
+ g4 = 1.93*L2**3 /(m*z *d2**4) - 1
+
+ g5 = np.sqrt( (745*L1/(m*z))**2 + 1.69*1e6 ) / (110*d1**3) -1
+ g6 = np.sqrt( (745*L2/(m*z))**2 + 157.5*1e6 ) / (85*d2**3) -1
+ g7 = m*z/40 - 1
+ g8 = 5*m/(b) - 1
+ g9 = b/(12*m) -1
+
+
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+ gx4.append( g4 )
+ gx5.append( g5 )
+ gx6.append( g6 )
+ gx7.append( g7 )
+ gx8.append( g8 )
+ gx9.append( g9 )
+
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+ gx4 = torch.tensor(gx4)
+ gx4 = gx4.reshape((n, 1))
+
+ gx5 = torch.tensor(gx5)
+ gx5 = gx1.reshape((n, 1))
+
+ gx6 = torch.tensor(gx6)
+ gx6 = gx2.reshape((n, 1))
+
+ gx7 = torch.tensor(gx7)
+ gx7 = gx3.reshape((n, 1))
+
+ gx8 = torch.tensor(gx8)
+ gx8 = gx4.reshape((n, 1))
+
+ gx9 = torch.tensor(gx9)
+ gx9 = gx4.reshape((n, 1))
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5, gx6, gx7, gx8, gx9), 1)
+
+
+ return gx, fx
+
+
+
+def SpeedReducer_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 7, "Input must be an n-by-7 PyTorch tensor."
+
+ b = (X[:,0] * ( 3.6 - 2.6 ) + 2.6).reshape(X.shape[0],1)
+ m = (X[:,1] * ( 0.8 - 0.7 ) + 0.7).reshape(X.shape[0],1)
+ z = (X[:,2] * ( 28 - 17 ) + 17).reshape(X.shape[0],1)
+ L1 = (X[:,3] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ L2 = (X[:,4] * ( 8.3 - 7.3 ) + 7.3).reshape(X.shape[0],1)
+ d1 = (X[:,5] * ( 3.9 - 2.9 ) + 2.9).reshape(X.shape[0],1)
+ d2 = (X[:,6] * ( 5.5 - 5 ) + 5).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((b, m, z, L1, L2, d1, d2), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/ThreeTruss.py b/test_functions2/ThreeTruss.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e4b3f2ef3416ea17b6626d2ea87c2dd7a9c2362
--- /dev/null
+++ b/test_functions2/ThreeTruss.py
@@ -0,0 +1,144 @@
+import torch
+import numpy as np
+
+
+#
+#
+# ThreeTruss: 2D objective, 3 constraints
+#
+# Reference:
+# Yang XS, Hossein Gandomi A (2012) Bat algo-
+# rithm: a novel approach for global engineer-
+# ing optimization. Engineering computations
+# 29(5):464–483
+#
+#
+
+
+def ThreeTruss(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+
+ fx = []
+ gx1 = []
+ gx2 = []
+ gx3 = []
+
+
+ n = individuals.size(0)
+
+ for i in range(n):
+
+ x = individuals[i,:]
+ # print(x)
+
+ x1 = x[0]
+ x2 = x[1]
+
+ if x1 <=1e-5:
+ x1 = 1e-5
+ if x2 <=1e-5:
+ x2 = 1e-5
+
+ L = 100
+ P = 2
+ sigma = 2
+
+ ## Negative sign to make it a maximization problem
+ test_function = - ( 2*np.sqrt(2)*x1 + x2 ) * L
+ fx.append(test_function)
+
+ ## Calculate constraints terms
+ g1 = ( np.sqrt(2)*x1 + x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g2 = ( x2 ) / (np.sqrt(2)*x1*x1 + 2*x1*x2) * P - sigma
+ g3 = ( 1 ) / (x1 + np.sqrt(2)*x2) * P - sigma
+
+ gx1.append( g1 )
+ gx2.append( g2 )
+ gx3.append( g3 )
+
+ fx = torch.tensor(fx)
+ fx = torch.reshape(fx, (len(fx),1))
+
+ gx1 = torch.tensor(gx1)
+ gx1 = gx1.reshape((n, 1))
+
+ gx2 = torch.tensor(gx2)
+ gx2 = gx2.reshape((n, 1))
+
+ gx3 = torch.tensor(gx3)
+ gx3 = gx3.reshape((n, 1))
+
+
+ gx = torch.cat((gx1, gx2, gx3), 1)
+
+
+ return gx, fx
+
+
+
+
+
+
+def ThreeTruss_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 2, "Input must be an n-by-2 PyTorch tensor."
+
+ return X
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Truss10D.py b/test_functions2/Truss10D.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc0ea12f999aa1d58eb4516b4fc08112f711583b
--- /dev/null
+++ b/test_functions2/Truss10D.py
@@ -0,0 +1,66 @@
+
+from TrussSolvers import *
+import torch
+import numpy as np
+
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(individuals[ii,:])
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/TrussSolvers.py b/test_functions2/TrussSolvers.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec6d915060eeaacae4989257c47b9212c1f3e235
--- /dev/null
+++ b/test_functions2/TrussSolvers.py
@@ -0,0 +1,2958 @@
+import matplotlib.pyplot as plt
+import torch
+import numpy as np
+
+from slientruss3d.truss import Truss
+from slientruss3d.type import SupportType, MemberType
+from slientruss3d.plot import TrussPlotter
+
+
+
+
+
+def TestPlot(truss):
+ # -------------------- Global variables --------------------
+ # Files settings:
+ TEST_FILE_NUMBER = 25
+ TEST_LOAD_CASE = 0
+ TEST_INPUT_FILE = f"./data/bar-{TEST_FILE_NUMBER}_output_{TEST_LOAD_CASE}.json"
+ TEST_PLOT_SAVE_PATH = f"./plot/bar-{TEST_FILE_NUMBER}_plot_{TEST_LOAD_CASE}.png"
+
+ # Truss dimension setting:
+ TRUSS_DIMENSION = 3
+
+ # Figure layout settings:
+ IS_SAVE_PLOT = False # Whether to save truss figure or not.
+ IS_EQUAL_AXIS = True # Whether to use actual aspect ratio in the truss figure or not.
+ IS_PLOT_STRESS = True # If True, the color of each displaced member gives expression to [stress]. Otherwise, [force magnitude].
+ MAX_SCALED_DISPLACEMENT = 15 # Scale the max value of all dimensions of displacements.
+ MAX_SCALED_FORCE = 50 # Scale the max value of all dimensions of force arrows.
+ POINT_SIZE_SCALE_FACTOR = 1 # Scale the default size of joint point in the truss figure.
+ ARROW_SIZE_SCALE_FACTOR = 1 # Scale the default size of force arrow in the truss figure.
+ # ----------------------------------------------------------
+
+ # Truss object:
+ # truss = Truss(dim=TRUSS_DIMENSION)
+
+ # You could directly read the output .json file.
+ # truss.LoadFromJSON(TEST_INPUT_FILE, isOutputFile=True)
+
+ # Show or save the structural analysis result figure:
+ TrussPlotter(truss,
+ isEqualAxis=IS_EQUAL_AXIS,
+ isPlotStress=IS_PLOT_STRESS,
+ maxScaledDisplace=MAX_SCALED_DISPLACEMENT,
+ maxScaledForce=MAX_SCALED_FORCE,
+ pointScale=POINT_SIZE_SCALE_FACTOR,
+ arrowScale=ARROW_SIZE_SCALE_FACTOR).Plot(IS_SAVE_PLOT, TEST_PLOT_SAVE_PATH)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss10bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(0, 0),
+ (360, 0),
+ (720, 0),
+ (0, 360),
+ (360, 360),
+ (720, 360)
+ ]
+
+
+ supports = [SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ ]
+ forces = [(1, (0, -1e5)), (2, (0, -1e5))]
+
+
+ members = [(0, 1),
+ (0, 4),
+ (1, 2),
+ (1, 3),
+ (1, 4),
+ (1, 5),
+ (2, 4),
+ (2, 5),
+ (3, 4),
+ (4, 5)
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # Default: 0.1, 1e7, 1
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss25bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(62.5, 100, 200),
+ (137.5, 100, 200),
+ (62.5, 137.5, 100),
+ (137.5, 137.5, 100),
+ (137.5, 62.5, 100),
+ (62.5, 62.5, 100),
+ (0, 200, 0),
+ (200, 200, 0),
+ (200, 0, 0),
+ (0, 0, 0)
+ ]
+
+
+ supports = [SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+ forces = [(0, (1000, 20000, -5000)),
+ (1, (0, -20000, -5000)),
+ (2, (500, 0, 0)),
+ (5, (500, 0, 0)),
+ ]
+
+
+ members = [(0, 1),
+ (0, 3),
+ (1, 2),
+ (0, 4),
+ (1, 5),
+ (0, 2),
+ (0, 5),
+ (1, 3),
+ (1, 4),
+ (2, 5),
+ (3, 4),
+ (2, 3),
+ (4, 5),
+ (2, 9),
+ (5, 6),
+ (3, 8),
+ (4, 7),
+ (2, 7),
+ (3, 6),
+ (5, 8),
+ (4, 9),
+ (2, 6),
+ (3, 7),
+ (4, 8),
+ (5, 9),
+ ]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+
+ # Default: 0.1, 1e7, .1
+
+ memberType = MemberType(A[index].item(), 3e7, .283)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), .283)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 3e7, Rho[index].item())
+
+
+
+ # memberType = MemberType(A[index].item(), 1e7, .1)
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+
+def Truss47bar(A, E, Rho, version):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 2
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [(-60, 0),
+ (60, 0),
+ (-60, 120),
+ (60, 120),
+ (-60, 240),
+ (60, 240),
+ (-60, 360),
+ (60, 360),
+ (-30, 420),
+ (30, 420),
+ (-30, 480),
+ (30, 480),
+ (-30, 540),
+ (30, 540),
+ (-90, 570),
+ (90, 570),
+ (-150, 600),
+ (-90, 600),
+ (-30, 600),
+ (30, 600),
+ (90, 600),
+ (150, 600)]
+
+ supports = [SupportType.PIN, SupportType.PIN,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO,
+ SupportType.NO, SupportType.NO]
+
+
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ if version == 1:
+ forces = [(16, (6000, -14000)),
+ (21, (6000, -14000))]
+
+ elif version == 2:
+ forces = [(16, (6000, -14000))]
+
+ elif version == 3:
+ forces = [(21, (6000, -14000))]
+
+
+
+
+ members = [(0, 2), (0, 3), (1, 2), (1, 3),
+ (2, 3), (2, 4), (2, 5), (3, 4), (3, 5),
+ (4, 5), (4, 6), (4, 7), (5, 6), (5, 7),
+ (6, 7), (6, 8), (6, 9), (7, 8), (7, 9), (8, 9),
+ (8, 10), (8, 11), (9, 10), (9, 11),
+ (10, 11), (10, 12), (10, 13), (11, 12), (11, 13),
+ (12, 13), (12, 14), (12, 18), (12, 19),
+ (13, 18), (13, 19), (13, 15), (14, 16),
+ (14, 17), (14, 18), (15, 19), (15, 20),
+ (15, 21), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21)]
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+
+ # Default: 0.1, 300000000.0, 0.3
+
+ memberType = MemberType(A[index].item(), 300000000.0, 0.3)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.3)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 300000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss120bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 275.59),
+ (273.26, 0.0, 230.31),
+ (236.65010183813573, 136.62999999999997, 230.31),
+ (136.62999999999997, 236.65010183813573, 230.31),
+ (0.0, 273.26, 230.31),
+ (-136.62999999999997, 236.65010183813573, 230.31),
+ (-236.65010183813573, 136.62999999999997, 230.31),
+ (-273.26, 0.0, 230.31),
+ (-236.65010183813573, -136.62999999999997, 230.31),
+ (-136.62999999999997, -236.65010183813573, 230.31),
+ (0.0, -273.26, 230.31),
+ (136.62999999999997, -236.65010183813573, 230.31),
+ (236.65010183813573, -136.62999999999997, 230.31),
+ (492.12, 0.0, 118.11),
+ (475.3514176333763, 127.37002847585251, 118.11),
+ (426.18842171039796, 246.05999999999997, 118.11),
+ (347.9813891575237, 347.9813891575237, 118.11),
+ (246.05999999999997, 426.18842171039796, 118.11),
+ (127.37002847585251, 475.3514176333763, 118.11),
+ (0.0, 492.12, 118.11),
+ (-127.37002847585251, 475.3514176333763, 118.11),
+ (-246.05999999999997, 426.18842171039796, 118.11),
+ (-347.9813891575237, 347.9813891575237, 118.11),
+ (-426.18842171039796, 246.05999999999997, 118.11),
+ (-475.3514176333763, 127.37002847585251, 118.11),
+ (-492.12, 0.0, 118.11),
+ (-475.3514176333763, -127.37002847585251, 118.11),
+ (-426.18842171039796, -246.05999999999997, 118.11),
+ (-347.9813891575237, -347.9813891575237, 118.11),
+ (-246.05999999999997, -426.18842171039796, 118.11),
+ (-127.37002847585251, -475.3514176333763, 118.11),
+ (0.0, -492.12, 118.11),
+ (127.37002847585251, -475.3514176333763, 118.11),
+ (246.05999999999997, -426.18842171039796, 118.11),
+ (347.9813891575237, -347.9813891575237, 118.11),
+ (426.18842171039796, -246.05999999999997, 118.11),
+ (475.3514176333763, -127.37002847585251, 118.11),
+ (625.59, 0.0, 0.0),
+ (541.7768323535071, 312.79499999999996, 0.0),
+ (312.79499999999996, 541.7768323535071, 0.0),
+ (0.0, 625.59, 0.0),
+ (-312.79499999999996, 541.7768323535071, 0.0),
+ (-541.7768323535071, 312.79499999999996, 0.0),
+ (-625.59, 0.0, 0.0),
+ (-541.7768323535071, -312.79499999999996, 0.0),
+ (-312.79499999999996, -541.7768323535071, 0.0),
+ (0.0, -625.59, 0.0),
+ (312.79499999999996, -541.7768323535071, 0.0),
+ (541.7768323535071, -312.79499999999996, 0.0)
+ ]
+
+ supports = [
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN
+ ]
+
+ # print(len(joints))
+ # print(len(supports))
+
+
+
+ forces = [
+ (0, (0.0, 0.0, -13490.0)),
+ (1, (0.0, 0.0, -6744.0)),
+ (2, (0.0, 0.0, -6744.0)),
+ (3, (0.0, 0.0, -6744.0)),
+ (4, (0.0, 0.0, -6744.0)),
+ (5, (0.0, 0.0, -6744.0)),
+ (6, (0.0, 0.0, -6744.0)),
+ (7, (0.0, 0.0, -6744.0)),
+ (8, (0.0, 0.0, -6744.0)),
+ (9, (0.0, 0.0, -6744.0)),
+ (10, (0.0, 0.0, -6744.0)),
+ (11, (0.0, 0.0, -6744.0)),
+ (12, (0.0, 0.0, -6744.0)),
+ (13, (0.0, 0.0, -6744.0)),
+ (14, (0.0, 0.0, -2248.0)),
+ (15, (0.0, 0.0, -2248.0)),
+ (16, (0.0, 0.0, -2248.0)),
+ (17, (0.0, 0.0, -2248.0)),
+ (18, (0.0, 0.0, -2248.0)),
+ (19, (0.0, 0.0, -2248.0)),
+ (20, (0.0, 0.0, -2248.0)),
+ (21, (0.0, 0.0, -2248.0)),
+ (22, (0.0, 0.0, -2248.0)),
+ (23, (0.0, 0.0, -2248.0)),
+ (24, (0.0, 0.0, -2248.0)),
+ (25, (0.0, 0.0, -2248.0)),
+ (26, (0.0, 0.0, -2248.0)),
+ (27, (0.0, 0.0, -2248.0)),
+ (28, (0.0, 0.0, -2248.0)),
+ (29, (0.0, 0.0, -2248.0)),
+ (30, (0.0, 0.0, -2248.0)),
+ (31, (0.0, 0.0, -2248.0)),
+ (32, (0.0, 0.0, -2248.0)),
+ (33, (0.0, 0.0, -2248.0)),
+ (34, (0.0, 0.0, -2248.0)),
+ (35, (0.0, 0.0, -2248.0)),
+ (36, (0.0, 0.0, -2248.0))
+ ]
+
+
+
+ members = [
+ (0, 1),
+ (0, 2),
+ (0, 3),
+ (0, 4),
+ (0, 5),
+ (0, 6),
+ (0, 7),
+ (0, 8),
+ (0, 9),
+ (0, 10),
+ (0, 11),
+ (0, 12),
+ (1, 2),
+ (2, 3),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 12),
+ (12, 1),
+ (1, 13),
+ (2, 15),
+ (3, 17),
+ (4, 19),
+ (5, 21),
+ (6, 23),
+ (7, 25),
+ (8, 27),
+ (9, 29),
+ (10, 31),
+ (11, 33),
+ (12, 35),
+ (1, 14),
+ (2, 14),
+ (2, 16),
+ (3, 16),
+ (3, 18),
+ (4, 18),
+ (4, 20),
+ (5, 20),
+ (5, 22),
+ (6, 22),
+ (6, 24),
+ (7, 24),
+ (7, 26),
+ (8, 26),
+ (8, 28),
+ (9, 28),
+ (9, 30),
+ (10, 30),
+ (10, 32),
+ (11, 32),
+ (11, 34),
+ (12, 34),
+ (12, 36),
+ (1, 36),
+ (13, 14),
+ (14, 15),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 20),
+ (20, 21),
+ (21, 22),
+ (22, 23),
+ (23, 24),
+ (24, 25),
+ (25, 26),
+ (26, 27),
+ (27, 28),
+ (28, 29),
+ (29, 30),
+ (30, 31),
+ (31, 32),
+ (32, 33),
+ (33, 34),
+ (34, 35),
+ (35, 36),
+ (36, 13),
+ (13, 37),
+ (15, 38),
+ (17, 39),
+ (19, 40),
+ (21, 41),
+ (23, 42),
+ (25, 43),
+ (27, 44),
+ (29, 45),
+ (31, 46),
+ (33, 47),
+ (35, 48),
+ (14, 37),
+ (14, 38),
+ (16, 38),
+ (16, 39),
+ (18, 39),
+ (18, 40),
+ (20, 40),
+ (20, 41),
+ (22, 41),
+ (22, 42),
+ (24, 42),
+ (24, 43),
+ (26, 43),
+ (26, 44),
+ (28, 44),
+ (28, 45),
+ (30, 45),
+ (30, 46),
+ (32, 46),
+ (32, 47),
+ (34, 47),
+ (34, 48),
+ (36, 48),
+ (36, 37)
+ ]
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 30450000, 0.288)
+ # print(A.shape)
+ memberType = MemberType(A[index].item(), 30450000, 0.288)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.288)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 30450000, Rho[index].item())
+
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_4forces(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (0.0, 0.0, -5000.0)),
+ (17, (0.0, 0.0, -5000.0)),
+ (18, (0.0, 0.0, -5000.0)),
+ (19, (0.0, 0.0, -5000.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, forces, stress, resistance = truss.GetDisplacements(), truss.GetInternalForces(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, forces, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+def Truss72bar_single(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ (0.0, 0.0, 0.0),
+ (120.0, 0.0, 0.0),
+ (120.0, 120.0, 0.0),
+ (0.0, 120.0, 0.0),
+ (0.0, 0.0, 60.0),
+ (120.0, 0.0, 60.0),
+ (120.0, 120.0, 60.0),
+ (0.0, 120.0, 60.0),
+ (0.0, 0.0, 120.0),
+ (120.0, 0.0, 120.0),
+ (120.0, 120.0, 120.0),
+ (0.0, 120.0, 120.0),
+ (0.0, 0.0, 180.0),
+ (120.0, 0.0, 180.0),
+ (120.0, 120.0, 180.0),
+ (0.0, 120.0, 180.0),
+ (0.0, 0.0, 240.0),
+ (120.0, 0.0, 240.0),
+ (120.0, 120.0, 240.0),
+ (0.0, 120.0, 240.0)
+ ]
+
+
+
+
+
+ supports = [
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.PIN,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO,
+ SupportType.NO
+ ]
+
+
+
+
+
+ forces = [
+ (0, (0.0, 0.0, 0.0)),
+ (1, (0.0, 0.0, 0.0)),
+ (2, (0.0, 0.0, 0.0)),
+ (3, (0.0, 0.0, 0.0)),
+ (4, (0.0, 0.0, 0.0)),
+ (5, (0.0, 0.0, 0.0)),
+ (6, (0.0, 0.0, 0.0)),
+ (7, (0.0, 0.0, 0.0)),
+ (8, (0.0, 0.0, 0.0)),
+ (9, (0.0, 0.0, 0.0)),
+ (10, (0.0, 0.0, 0.0)),
+ (11, (0.0, 0.0, 0.0)),
+ (12, (0.0, 0.0, 0.0)),
+ (13, (0.0, 0.0, 0.0)),
+ (14, (0.0, 0.0, 0.0)),
+ (15, (0.0, 0.0, 0.0)),
+ (16, (5000.0, 5000.0, -5000.0)),
+ (17, (0.0, 0.0, 0.0)),
+ (18, (0.0, 0.0, 0.0)),
+ (19, (0.0, 0.0, 0.0))
+ ]
+
+
+
+
+ members = [
+ (0, 4),
+ (1, 5),
+ (2, 6),
+ (3, 7),
+ (1, 4),
+ (0, 5),
+ (1, 6),
+ (2, 5),
+ (2, 7),
+ (3, 6),
+ (0, 7),
+ (3, 4),
+ (4, 5),
+ (5, 6),
+ (6, 7),
+ (7, 4),
+ (4, 6),
+ (5, 7),
+ (4, 8),
+ (5, 9),
+ (6, 10),
+ (7, 11),
+ (5, 8),
+ (4, 9),
+ (5, 10),
+ (6, 9),
+ (6, 11),
+ (7, 10),
+ (4, 11),
+ (7, 8),
+ (8, 9),
+ (9, 10),
+ (10, 11),
+ (11, 8),
+ (8, 10),
+ (9, 11),
+ (8, 12),
+ (9, 13),
+ (10, 14),
+ (11, 15),
+ (9, 12),
+ (8, 13),
+ (9, 14),
+ (10, 13),
+ (10, 15),
+ (11, 14),
+ (8, 15),
+ (11, 12),
+ (12, 13),
+ (13, 14),
+ (14, 15),
+ (15, 12),
+ (12, 14),
+ (13, 15),
+ (12, 16),
+ (13, 17),
+ (14, 18),
+ (15, 19),
+ (13, 16),
+ (12, 17),
+ (13, 18),
+ (14, 17),
+ (14, 19),
+ (15, 18),
+ (12, 19),
+ (15, 16),
+ (16, 17),
+ (17, 18),
+ (18, 19),
+ (19, 16),
+ (16, 18),
+ (17, 19)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+
+def Truss942bar(A, E, Rho):
+ # -------------------- Global variables --------------------
+ TEST_OUTPUT_FILE = f"./test_output.json"
+ TRUSS_DIMENSION = 3
+ # ----------------------------------------------------------
+
+ # Truss object:
+ truss = Truss(dim=TRUSS_DIMENSION)
+
+ init_truss = truss
+
+ # Truss settings:
+ joints = [
+ [24.5, 24.5, 312.0],
+ [38.5, 24.5, 312.0],
+ [24.5, 38.5, 312.0],
+ [38.5, 38.5, 312.0],
+ [24.5, 24.5, 300.0],
+ [38.5, 24.5, 300.0],
+ [24.5, 38.5, 300.0],
+ [38.5, 38.5, 300.0],
+ [24.5, 24.5, 288.0],
+ [38.5, 24.5, 288.0],
+ [24.5, 38.5, 288.0],
+ [38.5, 38.5, 288.0],
+ [24.5, 24.5, 276.0],
+ [38.5, 24.5, 276.0],
+ [24.5, 38.5, 276.0],
+ [38.5, 38.5, 276.0],
+ [24.5, 24.5, 264.0],
+ [38.5, 24.5, 264.0],
+ [24.5, 38.5, 264.0],
+ [38.5, 38.5, 264.0],
+ [24.5, 24.5, 252.0],
+ [38.5, 24.5, 252.0],
+ [24.5, 38.5, 252.0],
+ [38.5, 38.5, 252.0],
+ [21.6005, 21.6005, 240.0],
+ [31.5, 17.5, 240.0],
+ [41.3995, 21.6005, 240.0],
+ [17.5, 31.5, 240.0],
+ [45.5, 31.5, 240.0],
+ [21.6005, 41.3995, 240.0],
+ [31.5, 45.5, 240.0],
+ [41.3995, 41.3995, 240.0],
+ [21.6005, 21.6005, 228.0],
+ [31.5, 17.5, 228.0],
+ [41.3995, 21.6005, 228.0],
+ [17.5, 31.5, 228.0],
+ [45.5, 31.5, 228.0],
+ [21.6005, 41.3995, 228.0],
+ [31.5, 45.5, 228.0],
+ [41.3995, 41.3995, 228.0],
+ [21.6005, 21.6005, 216.0],
+ [31.5, 17.5, 216.0],
+ [41.3995, 21.6005, 216.0],
+ [17.5, 31.5, 216.0],
+ [45.5, 31.5, 216.0],
+ [21.6005, 41.3995, 216.0],
+ [31.5, 45.5, 216.0],
+ [41.3995, 41.3995, 216.0],
+ [21.6005, 21.6005, 204.0],
+ [31.5, 17.5, 204.0],
+ [41.3995, 21.6005, 204.0],
+ [17.5, 31.5, 204.0],
+ [45.5, 31.5, 204.0],
+ [21.6005, 41.3995, 204.0],
+ [31.5, 45.5, 204.0],
+ [41.3995, 41.3995, 204.0],
+ [21.6005, 21.6005, 192.0],
+ [31.5, 17.5, 192.0],
+ [41.3995, 21.6005, 192.0],
+ [17.5, 31.5, 192.0],
+ [45.5, 31.5, 192.0],
+ [21.6005, 41.3995, 192.0],
+ [31.5, 45.5, 192.0],
+ [41.3995, 41.3995, 192.0],
+ [21.6005, 21.6005, 180.0],
+ [31.5, 17.5, 180.0],
+ [41.3995, 21.6005, 180.0],
+ [17.5, 31.5, 180.0],
+ [45.5, 31.5, 180.0],
+ [21.6005, 41.3995, 180.0],
+ [31.5, 45.5, 180.0],
+ [41.3995, 41.3995, 180.0],
+ [21.6005, 21.6005, 168.0],
+ [31.5, 17.5, 168.0],
+ [41.3995, 21.6005, 168.0],
+ [17.5, 31.5, 168.0],
+ [45.5, 31.5, 168.0],
+ [21.6005, 41.3995, 168.0],
+ [31.5, 45.5, 168.0],
+ [41.3995, 41.3995, 168.0],
+ [21.6005, 21.6005, 156.0],
+ [31.5, 17.5, 156.0],
+ [41.3995, 21.6005, 156.0],
+ [17.5, 31.5, 156.0],
+ [45.5, 31.5, 156.0],
+ [21.6005, 41.3995, 156.0],
+ [31.5, 45.5, 156.0],
+ [41.3995, 41.3995, 156.0],
+ [7.0, 24.5, 144.0],
+ [11.1199, 11.1199, 144.0],
+ [24.5, 7.0, 144.0],
+ [38.5, 7.0, 144.0],
+ [51.8801, 11.1199, 144.0],
+ [56.0, 24.5, 144.0],
+ [7.0, 38.5, 144.0],
+ [11.1199, 51.8801, 144.0],
+ [24.5, 56.0, 144.0],
+ [38.5, 56.0, 144.0],
+ [51.8801, 51.8801, 144.0],
+ [56.0, 38.5, 144.0],
+ [7.0, 24.5, 132.0],
+ [11.1199, 11.1199, 132.0],
+ [24.5, 7.0, 132.0],
+ [38.5, 7.0, 132.0],
+ [51.8801, 11.1199, 132.0],
+ [56.0, 24.5, 132.0],
+ [7.0, 38.5, 132.0],
+ [11.1199, 51.8801, 132.0],
+ [24.5, 56.0, 132.0],
+ [38.5, 56.0, 132.0],
+ [51.8801, 51.8801, 132.0],
+ [56.0, 38.5, 132.0],
+ [7.0, 24.5, 120.0],
+ [11.1199, 11.1199, 120.0],
+ [24.5, 7.0, 120.0],
+ [38.5, 7.0, 120.0],
+ [51.8801, 11.1199, 120.0],
+ [56.0, 24.5, 120.0],
+ [7.0, 38.5, 120.0],
+ [11.1199, 51.8801, 120.0],
+ [24.5, 56.0, 120.0],
+ [38.5, 56.0, 120.0],
+ [51.8801, 51.8801, 120.0],
+ [56.0, 38.5, 120.0],
+ [7.0, 24.5, 108.0],
+ [11.1199, 11.1199, 108.0],
+ [24.5, 7.0, 108.0],
+ [38.5, 7.0, 108.0],
+ [51.8801, 11.1199, 108.0],
+ [56.0, 24.5, 108.0],
+ [7.0, 38.5, 108.0],
+ [11.1199, 51.8801, 108.0],
+ [24.5, 56.0, 108.0],
+ [38.5, 56.0, 108.0],
+ [51.8801, 51.8801, 108.0],
+ [56.0, 38.5, 108.0],
+ [7.0, 24.5, 96.0],
+ [11.1199, 11.1199, 96.0],
+ [24.5, 7.0, 96.0],
+ [38.5, 7.0, 96.0],
+ [51.8801, 11.1199, 96.0],
+ [56.0, 24.5, 96.0],
+ [7.0, 38.5, 96.0],
+ [11.1199, 51.8801, 96.0],
+ [24.5, 56.0, 96.0],
+ [38.5, 56.0, 96.0],
+ [51.8801, 51.8801, 96.0],
+ [56.0, 38.5, 96.0],
+ [7.0, 24.5, 84.0],
+ [11.1199, 11.1199, 84.0],
+ [24.5, 7.0, 84.0],
+ [38.5, 7.0, 84.0],
+ [51.8801, 11.1199, 84.0],
+ [56.0, 24.5, 84.0],
+ [7.0, 38.5, 84.0],
+ [11.1199, 51.8801, 84.0],
+ [24.5, 56.0, 84.0],
+ [38.5, 56.0, 84.0],
+ [51.8801, 51.8801, 84.0],
+ [56.0, 38.5, 84.0],
+ [7.0, 24.5, 72.0],
+ [11.1199, 11.1199, 72.0],
+ [24.5, 7.0, 72.0],
+ [38.5, 7.0, 72.0],
+ [51.8801, 11.1199, 72.0],
+ [56.0, 24.5, 72.0],
+ [7.0, 38.5, 72.0],
+ [11.1199, 51.8801, 72.0],
+ [24.5, 56.0, 72.0],
+ [38.5, 56.0, 72.0],
+ [51.8801, 51.8801, 72.0],
+ [56.0, 38.5, 72.0],
+ [7.0, 24.5, 60.0],
+ [11.1199, 11.1199, 60.0],
+ [24.5, 7.0, 60.0],
+ [38.5, 7.0, 60.0],
+ [51.8801, 11.1199, 60.0],
+ [56.0, 24.5, 60.0],
+ [7.0, 38.5, 60.0],
+ [11.1199, 51.8801, 60.0],
+ [24.5, 56.0, 60.0],
+ [38.5, 56.0, 60.0],
+ [51.8801, 51.8801, 60.0],
+ [56.0, 38.5, 60.0],
+ [7.0, 24.5, 48.0],
+ [11.1199, 11.1199, 48.0],
+ [24.5, 7.0, 48.0],
+ [38.5, 7.0, 48.0],
+ [51.8801, 11.1199, 48.0],
+ [56.0, 24.5, 48.0],
+ [7.0, 38.5, 48.0],
+ [11.1199, 51.8801, 48.0],
+ [24.5, 56.0, 48.0],
+ [38.5, 56.0, 48.0],
+ [51.8801, 51.8801, 48.0],
+ [56.0, 38.5, 48.0],
+ [7.0, 24.5, 36.0],
+ [11.1199, 11.1199, 36.0],
+ [24.5, 7.0, 36.0],
+ [38.5, 7.0, 36.0],
+ [51.8801, 11.1199, 36.0],
+ [56.0, 24.5, 36.0],
+ [7.0, 38.5, 36.0],
+ [11.1199, 51.8801, 36.0],
+ [24.5, 56.0, 36.0],
+ [38.5, 56.0, 36.0],
+ [51.8801, 51.8801, 36.0],
+ [56.0, 38.5, 36.0],
+ [7.0, 24.5, 24.0],
+ [11.1199, 11.1199, 24.0],
+ [24.5, 7.0, 24.0],
+ [38.5, 7.0, 24.0],
+ [51.8801, 11.1199, 24.0],
+ [56.0, 24.5, 24.0],
+ [7.0, 38.5, 24.0],
+ [11.1199, 51.8801, 24.0],
+ [24.5, 56.0, 24.0],
+ [38.5, 56.0, 24.0],
+ [51.8801, 51.8801, 24.0],
+ [56.0, 38.5, 24.0],
+ [7.0, 24.5, 12.0],
+ [11.1199, 11.1199, 12.0],
+ [24.5, 7.0, 12.0],
+ [38.5, 7.0, 12.0],
+ [51.8801, 11.1199, 12.0],
+ [56.0, 24.5, 12.0],
+ [7.0, 38.5, 12.0],
+ [11.1199, 51.8801, 12.0],
+ [24.5, 56.0, 12.0],
+ [38.5, 56.0, 12.0],
+ [51.8801, 51.8801, 12.0],
+ [56.0, 38.5, 12.0],
+ [7.0, 24.5, 0.0],
+ [11.1199, 11.1199, 0.0],
+ [24.5, 7.0, 0.0],
+ [38.5, 7.0, 0.0],
+ [51.8801, 11.1199, 0.0],
+ [56.0, 24.5, 0.0],
+ [7.0, 38.5, 0.0],
+ [11.1199, 51.8801, 0.0],
+ [24.5, 56.0, 0.0],
+ [38.5, 56.0, 0.0],
+ [51.8801, 51.8801, 0.0],
+ [56.0, 38.5, 0.0]
+ ]
+
+
+ supports = []
+ for ii in range(244-12):
+ supports.append(SupportType.NO)
+ for ii in range(12):
+ supports.append(SupportType.PIN)
+
+
+ forces = [
+ (0, (1.5, -1.0, -3.0)),
+ (1, (-1.0, -1.0, -3.0)),
+ (2, (1.5, -1.0, -3.0)),
+ (3, (-1.0, 1.0, -3.0)),
+ (4, (1.5, -1.0, -3.0)),
+ (5, (-1.0, -1.0, -3.0)),
+ (6, (1.5, -1.0, -3.0)),
+ (7, (-1.0, 1.0, -3.0)),
+ (8, (1.5, -1.0, -3.0)),
+ (9, (-1.0, -1.0, -3.0)),
+ (10, (1.5, -1.0, -3.0)),
+ (11, (-1.0, 1.0, -3.0)),
+ (12, (1.5, -1.0, -3.0)),
+ (13, (-1.0, -1.0, -3.0)),
+ (14, (1.5, -1.0, -3.0)),
+ (15, (-1.0, 1.0, -3.0)),
+ (16, (1.5, -1.0, -3.0)),
+ (17, (-1.0, -1.0, -3.0)),
+ (18, (1.5, -1.0, -3.0)),
+ (19, (-1.0, 1.0, -3.0)),
+ (20, (1.5, -1.0, -3.0)),
+ (21, (-1.0, -1.0, -3.0)),
+ (22, (1.5, -1.0, -3.0)),
+ (23, (-1.0, 1.0, -3.0)),
+ (24, (1.5, -1.0, -3.0)),
+ (25, (0.0, -1.0, -3.0)),
+ (26, (-1.0, -1.0, -3.0)),
+ (27, (1.5, 0.0, -3.0)),
+ (28, (-1.0, 0.0, -3.0)),
+ (29, (1.5, 1.0, -3.0)),
+ (30, (0.0, 1.0, -3.0)),
+ (31, (-1.0, 1.0, -3.0)),
+ (32, (1.5, -1.0, -6.0)),
+ (33, (0.0, -1.0, -6.0)),
+ (34, (-1.0, -1.0, -6.0)),
+ (35, (1.5, 0.0, -6.0)),
+ (36, (-1.0, 0.0, -6.0)),
+ (37, (1.5, 1.0, -6.0)),
+ (38, (0.0, 1.0, -6.0)),
+ (39, (-1.0, 1.0, -6.0)),
+ (40, (1.5, -1.0, -6.0)),
+ (41, (0.0, -1.0, -6.0)),
+ (42, (-1.0, -1.0, -6.0)),
+ (43, (1.5, 0.0, -6.0)),
+ (44, (-1.0, 0.0, -6.0)),
+ (45, (1.5, 1.0, -6.0)),
+ (46, (0.0, 1.0, -6.0)),
+ (47, (-1.0, 1.0, -6.0)),
+ (48, (1.5, -1.0, -6.0)),
+ (49, (0.0, -1.0, -6.0)),
+ (50, (-1.0, -1.0, -6.0)),
+ (51, (1.5, 0.0, -6.0)),
+ (52, (-1.0, 0.0, -6.0)),
+ (53, (1.5, 1.0, -6.0)),
+ (54, (0.0, 1.0, -6.0)),
+ (55, (-1.0, 1.0, -6.0)),
+ (56, (1.5, -1.0, -6.0)),
+ (57, (0.0, -1.0, -6.0)),
+ (58, (-1.0, -1.0, -6.0)),
+ (59, (1.5, 0.0, -6.0)),
+ (60, (-1.0, 0.0, -6.0)),
+ (61, (1.5, 1.0, -6.0)),
+ (62, (0.0, 1.0, -6.0)),
+ (63, (-1.0, 1.0, -6.0)),
+ (64, (1.5, -1.0, -6.0)),
+ (65, (0.0, -1.0, -6.0)),
+ (66, (-1.0, -1.0, -6.0)),
+ (67, (1.5, 0.0, -6.0)),
+ (68, (-1.0, 0.0, -6.0)),
+ (69, (1.5, 1.0, -6.0)),
+ (70, (0.0, 1.0, -6.0)),
+ (71, (-1.0, 1.0, -6.0)),
+ (72, (1.5, -1.0, -6.0)),
+ (73, (0.0, -1.0, -6.0)),
+ (74, (-1.0, -1.0, -6.0)),
+ (75, (1.5, 0.0, -6.0)),
+ (76, (-1.0, 0.0, -6.0)),
+ (77, (1.5, 1.0, -6.0)),
+ (78, (0.0, 1.0, -6.0)),
+ (79, (-1.0, 1.0, -6.0)),
+ (80, (1.5, -1.0, -6.0)),
+ (81, (0.0, -1.0, -6.0)),
+ (82, (-1.0, -1.0, -6.0)),
+ (83, (1.5, 0.0, -6.0)),
+ (84, (-1.0, 0.0, -6.0)),
+ (85, (1.5, 1.0, -6.0)),
+ (86, (0.0, 1.0, -6.0)),
+ (87, (-1.0, 1.0, -6.0)),
+ (88, (1.5, -1.0, -6.0)),
+ (89, (1.5, -1.0, -6.0)),
+ (90, (1.5, -1.0, -6.0)),
+ (91, (-1.0, -1.0, -6.0)),
+ (92, (-1.0, -1.0, -6.0)),
+ (93, (-1.0, -1.0, -6.0)),
+ (94, (1.5, 1.0, -6.0)),
+ (95, (1.5, 1.0, -6.0)),
+ (96, (1.5, 1.0, -6.0)),
+ (97, (-1.0, 1.0, -6.0)),
+ (98, (-1.0, 1.0, -6.0)),
+ (99, (-1.0, 1.0, -6.0)),
+ (100, (1.5, -1.0, -9.0)),
+ (101, (1.5, -1.0, -9.0)),
+ (102, (1.5, -1.0, -9.0)),
+ (103, (-1.0, -1.0, -9.0)),
+ (104, (-1.0, -1.0, -9.0)),
+ (105, (-1.0, -1.0, -9.0)),
+ (106, (1.5, 1.0, -9.0)),
+ (107, (1.5, 1.0, -9.0)),
+ (108, (1.5, 1.0, -9.0)),
+ (109, (-1.0, 1.0, -9.0)),
+ (110, (-1.0, 1.0, -9.0)),
+ (111, (-1.0, 1.0, -9.0)),
+ (112, (1.5, -1.0, -9.0)),
+ (113, (1.5, -1.0, -9.0)),
+ (114, (1.5, -1.0, -9.0)),
+ (115, (-1.0, -1.0, -9.0)),
+ (116, (-1.0, -1.0, -9.0)),
+ (117, (-1.0, -1.0, -9.0)),
+ (118, (1.5, 1.0, -9.0)),
+ (119, (1.5, 1.0, -9.0)),
+ (120, (1.5, 1.0, -9.0)),
+ (121, (-1.0, 1.0, -9.0)),
+ (122, (-1.0, 1.0, -9.0)),
+ (123, (-1.0, 1.0, -9.0)),
+ (124, (1.5, -1.0, -9.0)),
+ (125, (1.5, -1.0, -9.0)),
+ (126, (1.5, -1.0, -9.0)),
+ (127, (-1.0, -1.0, -9.0)),
+ (128, (-1.0, -1.0, -9.0)),
+ (129, (-1.0, -1.0, -9.0)),
+ (130, (1.5, 1.0, -9.0)),
+ (131, (1.5, 1.0, -9.0)),
+ (132, (1.5, 1.0, -9.0)),
+ (133, (-1.0, 1.0, -9.0)),
+ (134, (-1.0, 1.0, -9.0)),
+ (135, (-1.0, 1.0, -9.0)),
+ (136, (1.5, -1.0, -9.0)),
+ (137, (1.5, -1.0, -9.0)),
+ (138, (1.5, -1.0, -9.0)),
+ (139, (-1.0, -1.0, -9.0)),
+ (140, (-1.0, -1.0, -9.0)),
+ (141, (-1.0, -1.0, -9.0)),
+ (142, (1.5, 1.0, -9.0)),
+ (143, (1.5, 1.0, -9.0)),
+ (144, (1.5, 1.0, -9.0)),
+ (145, (-1.0, 1.0, -9.0)),
+ (146, (-1.0, 1.0, -9.0)),
+ (147, (-1.0, 1.0, -9.0)),
+ (148, (1.5, -1.0, -9.0)),
+ (149, (1.5, -1.0, -9.0)),
+ (150, (1.5, -1.0, -9.0)),
+ (151, (-1.0, -1.0, -9.0)),
+ (152, (-1.0, -1.0, -9.0)),
+ (153, (-1.0, -1.0, -9.0)),
+ (154, (1.5, 1.0, -9.0)),
+ (155, (1.5, 1.0, -9.0)),
+ (156, (1.5, 1.0, -9.0)),
+ (157, (-1.0, 1.0, -9.0)),
+ (158, (-1.0, 1.0, -9.0)),
+ (159, (-1.0, 1.0, -9.0)),
+ (160, (1.5, -1.0, -9.0)),
+ (161, (1.5, -1.0, -9.0)),
+ (162, (1.5, -1.0, -9.0)),
+ (163, (-1.0, -1.0, -9.0)),
+ (164, (-1.0, -1.0, -9.0)),
+ (165, (-1.0, -1.0, -9.0)),
+ (166, (1.5, 1.0, -9.0)),
+ (167, (1.5, 1.0, -9.0)),
+ (168, (1.5, 1.0, -9.0)),
+ (169, (-1.0, 1.0, -9.0)),
+ (170, (-1.0, 1.0, -9.0)),
+ (171, (-1.0, 1.0, -9.0)),
+ (172, (1.5, -1.0, -9.0)),
+ (173, (1.5, -1.0, -9.0)),
+ (174, (1.5, -1.0, -9.0)),
+ (175, (-1.0, -1.0, -9.0)),
+ (176, (-1.0, -1.0, -9.0)),
+ (177, (-1.0, -1.0, -9.0)),
+ (178, (1.5, 1.0, -9.0)),
+ (179, (1.5, 1.0, -9.0)),
+ (180, (1.5, 1.0, -9.0)),
+ (181, (-1.0, 1.0, -9.0)),
+ (182, (-1.0, 1.0, -9.0)),
+ (183, (-1.0, 1.0, -9.0)),
+ (184, (1.5, -1.0, -9.0)),
+ (185, (1.5, -1.0, -9.0)),
+ (186, (1.5, -1.0, -9.0)),
+ (187, (-1.0, -1.0, -9.0)),
+ (188, (-1.0, -1.0, -9.0)),
+ (189, (-1.0, -1.0, -9.0)),
+ (190, (1.5, 1.0, -9.0)),
+ (191, (1.5, 1.0, -9.0)),
+ (192, (1.5, 1.0, -9.0)),
+ (193, (-1.0, 1.0, -9.0)),
+ (194, (-1.0, 1.0, -9.0)),
+ (195, (-1.0, 1.0, -9.0)),
+ (196, (1.5, -1.0, -9.0)),
+ (197, (1.5, -1.0, -9.0)),
+ (198, (1.5, -1.0, -9.0)),
+ (199, (-1.0, -1.0, -9.0)),
+ (200, (-1.0, -1.0, -9.0)),
+ (201, (-1.0, -1.0, -9.0)),
+ (202, (1.5, 1.0, -9.0)),
+ (203, (1.5, 1.0, -9.0)),
+ (204, (1.5, 1.0, -9.0)),
+ (205, (-1.0, 1.0, -9.0)),
+ (206, (-1.0, 1.0, -9.0)),
+ (207, (-1.0, 1.0, -9.0)),
+ (208, (1.5, -1.0, -9.0)),
+ (209, (1.5, -1.0, -9.0)),
+ (210, (1.5, -1.0, -9.0)),
+ (211, (-1.0, -1.0, -9.0)),
+ (212, (-1.0, -1.0, -9.0)),
+ (213, (-1.0, -1.0, -9.0)),
+ (214, (1.5, 1.0, -9.0)),
+ (215, (1.5, 1.0, -9.0)),
+ (216, (1.5, 1.0, -9.0)),
+ (217, (-1.0, 1.0, -9.0)),
+ (218, (-1.0, 1.0, -9.0)),
+ (219, (-1.0, 1.0, -9.0)),
+ (220, (1.5, -1.0, -9.0)),
+ (221, (1.5, -1.0, -9.0)),
+ (222, (1.5, -1.0, -9.0)),
+ (223, (-1.0, -1.0, -9.0)),
+ (224, (-1.0, -1.0, -9.0)),
+ (225, (-1.0, -1.0, -9.0)),
+ (226, (1.5, 1.0, -9.0)),
+ (227, (1.5, 1.0, -9.0)),
+ (228, (1.5, 1.0, -9.0)),
+ (229, (-1.0, 1.0, -9.0)),
+ (230, (-1.0, 1.0, -9.0)),
+ (231, (-1.0, 1.0, -9.0))
+ ]
+
+
+
+
+ members = [
+ (0, 3),
+ (1, 2),
+ (0, 1),
+ (2, 3),
+ (0, 2),
+ (1, 3),
+ (4, 5),
+ (6, 7),
+ (4, 6),
+ (5, 7),
+ (1, 5),
+ (0, 4),
+ (3, 7),
+ (2, 6),
+ (5, 9),
+ (4, 8),
+ (7, 11),
+ (6, 10),
+ (1, 4),
+ (0, 5),
+ (1, 7),
+ (3, 5),
+ (3, 6),
+ (2, 7),
+ (0, 6),
+ (2, 4),
+ (5, 8),
+ (4, 9),
+ (5, 11),
+ (7, 9),
+ (7, 10),
+ (6, 11),
+ (6, 8),
+ (4, 10),
+ (8, 9),
+ (10, 11),
+ (8, 10),
+ (9, 11),
+ (12, 13),
+ (14, 15),
+ (12, 14),
+ (13, 15),
+ (16, 17),
+ (18, 19),
+ (16, 18),
+ (17, 19),
+ (9, 13),
+ (8, 12),
+ (11, 15),
+ (10, 14),
+ (13, 17),
+ (12, 16),
+ (15, 19),
+ (16, 18),
+ (17, 21),
+ (16, 20),
+ (19, 23),
+ (18, 22),
+ (8, 13),
+ (9, 12),
+ (9, 15),
+ (11, 13),
+ (11, 14),
+ (10, 15),
+ (10, 12),
+ (8, 14),
+ (12, 17),
+ (13, 16),
+ (13, 19),
+ (15, 17),
+ (15, 18),
+ (14, 19),
+ (14, 16),
+ (12, 18),
+ (16, 21),
+ (17, 20),
+ (17, 23),
+ (19, 21),
+ (19, 22),
+ (18, 23),
+ (18, 20),
+ (16, 22),
+ (20, 21),
+ (22, 23),
+ (20, 22),
+ (21, 23),
+ (21, 24),
+ (20, 26),
+ (21, 31),
+ (23, 26),
+ (23, 29),
+ (22, 31),
+ (22, 24),
+ (20, 29),
+ (21, 26),
+ (20, 24),
+ (23, 31),
+ (22, 29),
+ (21, 25),
+ (20, 25),
+ (21, 28),
+ (23, 28),
+ (23, 30),
+ (22, 30),
+ (22, 27),
+ (20, 27),
+ (24, 25),
+ (25, 26),
+ (24, 27),
+ (27, 29),
+ (29, 30),
+ (30, 31),
+ (26, 28),
+ (28, 31),
+ (32, 33),
+ (33, 34),
+ (32, 35),
+ (35, 37),
+ (37, 38),
+ (38, 39),
+ (34, 36),
+ (36, 39),
+ (24, 32),
+ (26, 34),
+ (29, 37),
+ (31, 39),
+ (32, 40),
+ (34, 42),
+ (37, 45),
+ (39, 47),
+ (24, 33),
+ (25, 32),
+ (25, 34),
+ (26, 33),
+ (27, 32),
+ (24, 35),
+ (26, 36),
+ (28, 34),
+ (28, 39),
+ (31, 36),
+ (31, 38),
+ (30, 39),
+ (30, 37),
+ (29, 38),
+ (29, 35),
+ (27, 37),
+ (32, 41),
+ (33, 40),
+ (33, 42),
+ (34, 41),
+ (34, 44),
+ (36, 42),
+ (36, 47),
+ (39, 44),
+ (39, 46),
+ (38, 47),
+ (38, 45),
+ (37, 46),
+ (37, 43),
+ (35, 45),
+ (35, 40),
+ (32, 43),
+ (25, 33),
+ (27, 35),
+ (30, 38),
+ (28, 36),
+ (33, 41),
+ (35, 43),
+ (38, 46),
+ (36, 44),
+ (40, 41),
+ (41, 42),
+ (40, 43),
+ (42, 44),
+ (43, 45),
+ (45, 46),
+ (46, 47),
+ (44, 47),
+ (48, 49),
+ (49, 50),
+ (48, 51),
+ (50, 52),
+ (51, 53),
+ (53, 54),
+ (54, 55),
+ (52, 55),
+ (42, 50),
+ (40, 48),
+ (45, 53),
+ (47, 55),
+ (48, 56),
+ (50, 58),
+ (53, 61),
+ (55, 63),
+ (40, 49),
+ (41, 48),
+ (41, 50),
+ (42, 49),
+ (42, 52),
+ (44, 50),
+ (44, 55),
+ (47, 52),
+ (47, 54),
+ (46, 55),
+ (46, 53),
+ (45, 54),
+ (45, 51),
+ (43, 53),
+ (43, 48),
+ (40, 51),
+ (48, 57),
+ (49, 56),
+ (49, 58),
+ (50, 57),
+ (50, 60),
+ (52, 58),
+ (52, 63),
+ (55, 60),
+ (55, 62),
+ (54, 63),
+ (54, 61),
+ (53, 62),
+ (53, 59),
+ (51, 61),
+ (51, 56),
+ (48, 59),
+ (41, 49),
+ (43, 51),
+ (44, 52),
+ (46, 54),
+ (49, 57),
+ (51, 59),
+ (52, 60),
+ (54, 62),
+ (56, 57),
+ (57, 58),
+ (56, 59),
+ (58, 60),
+ (59, 61),
+ (60, 63),
+ (61, 62),
+ (62, 63),
+ (64, 65),
+ (65, 66),
+ (64, 67),
+ (66, 68),
+ (67, 69),
+ (68, 71),
+ (69, 70),
+ (70, 71),
+ (72, 73),
+ (73, 74),
+ (72, 75),
+ (74, 76),
+ (75, 77),
+ (76, 79),
+ (77, 78),
+ (78, 79),
+ (56, 64),
+ (58, 66),
+ (61, 69),
+ (63, 71),
+ (64, 72),
+ (66, 74),
+ (69, 77),
+ (71, 79),
+ (72, 80),
+ (74, 82),
+ (77, 85),
+ (79, 87),
+ (56, 65),
+ (57, 64),
+ (57, 66),
+ (58, 65),
+ (58, 68),
+ (60, 66),
+ (60, 71),
+ (63, 68),
+ (63, 70),
+ (62, 71),
+ (62, 69),
+ (61, 70),
+ (61, 67),
+ (59, 69),
+ (59, 64),
+ (56, 67),
+ (64, 73),
+ (65, 72),
+ (65, 74),
+ (66, 73),
+ (66, 76),
+ (68, 74),
+ (68, 79),
+ (71, 76),
+ (71, 78),
+ (70, 79),
+ (70, 77),
+ (69, 78),
+ (69, 75),
+ (67, 77),
+ (67, 72),
+ (64, 75),
+ (72, 81),
+ (73, 80),
+ (73, 82),
+ (74, 81),
+ (74, 84),
+ (76, 82),
+ (76, 87),
+ (79, 84),
+ (79, 86),
+ (78, 87),
+ (78, 85),
+ (77, 86),
+ (77, 83),
+ (75, 85),
+ (75, 80),
+ (72, 83),
+ (57, 65),
+ (59, 67),
+ (60, 68),
+ (62, 70),
+ (65, 73),
+ (67, 75),
+ (68, 76),
+ (70, 78),
+ (73, 81),
+ (75, 83),
+ (76, 84),
+ (78, 86),
+ (80, 81),
+ (81, 82),
+ (80, 83),
+ (82, 84),
+ (83, 85),
+ (84, 87),
+ (85, 86),
+ (86, 87),
+ (80, 89),
+ (82, 92),
+ (85, 95),
+ (87, 98),
+ (81, 89),
+ (81, 92),
+ (84, 92),
+ (84, 98),
+ (83, 95),
+ (83, 89),
+ (86, 95),
+ (86, 98),
+ (82, 91),
+ (80, 90),
+ (82, 93),
+ (87, 99),
+ (80, 88),
+ (85, 94),
+ (85, 96),
+ (87, 97),
+ (81, 91),
+ (81, 90),
+ (83, 88),
+ (83, 94),
+ (84, 93),
+ (84, 99),
+ (86, 96),
+ (86, 97),
+ (89, 90),
+ (91, 92),
+ (88, 89),
+ (92, 93),
+ (94, 95),
+ (95, 96),
+ (97, 98),
+ (98, 99),
+ (101, 102),
+ (103, 104),
+ (100, 101),
+ (104, 105),
+ (106, 107),
+ (107, 108),
+ (109, 110),
+ (110, 111),
+ (90, 91),
+ (88, 94),
+ (93, 99),
+ (96, 97),
+ (102, 103),
+ (100, 106),
+ (105, 111),
+ (108, 109),
+ (89, 101),
+ (92, 104),
+ (95, 107),
+ (98, 110),
+ (101, 113),
+ (104, 116),
+ (107, 119),
+ (110, 122),
+ (92, 103),
+ (91, 104),
+ (89, 102),
+ (90, 101),
+ (88, 101),
+ (89, 100),
+ (92, 105),
+ (93, 104),
+ (99, 110),
+ (98, 111),
+ (98, 109),
+ (97, 110),
+ (96, 107),
+ (95, 108),
+ (95, 106),
+ (94, 107),
+ (101, 114),
+ (102, 113),
+ (101, 112),
+ (100, 113),
+ (103, 116),
+ (104, 115),
+ (104, 117),
+ (105, 116),
+ (111, 122),
+ (110, 123),
+ (110, 121),
+ (109, 122),
+ (108, 119),
+ (107, 120),
+ (107, 118),
+ (106, 119),
+ (90, 102),
+ (91, 103),
+ (96, 108),
+ (97, 109),
+ (88, 100),
+ (94, 106),
+ (93, 105),
+ (99, 111),
+ (102, 114),
+ (103, 115),
+ (108, 120),
+ (109, 121),
+ (100, 112),
+ (106, 118),
+ (105, 117),
+ (111, 123),
+ (90, 103),
+ (91, 102),
+ (96, 109),
+ (97, 108),
+ (88, 106),
+ (94, 100),
+ (93, 111),
+ (99, 105),
+ (102, 115),
+ (103, 114),
+ (108, 121),
+ (109, 120),
+ (105, 123),
+ (111, 117),
+ (100, 118),
+ (106, 112),
+ (112, 113),
+ (113, 114),
+ (115, 116),
+ (116, 117),
+ (118, 119),
+ (119, 120),
+ (121, 122),
+ (122, 123),
+ (124, 125),
+ (125, 126),
+ (127, 128),
+ (128, 129),
+ (130, 131),
+ (131, 132),
+ (133, 134),
+ (134, 135),
+ (136, 137),
+ (137, 138),
+ (139, 140),
+ (140, 141),
+ (142, 143),
+ (143, 144),
+ (145, 146),
+ (146, 147),
+ (114, 115),
+ (120, 121),
+ (112, 118),
+ (117, 123),
+ (126, 127),
+ (132, 133),
+ (124, 130),
+ (129, 135),
+ (138, 139),
+ (144, 145),
+ (136, 142),
+ (141, 147),
+ (113, 125),
+ (116, 128),
+ (119, 131),
+ (122, 134),
+ (125, 137),
+ (128, 140),
+ (131, 143),
+ (134, 146),
+ (137, 149),
+ (140, 152),
+ (143, 155),
+ (146, 158),
+ (112, 125),
+ (113, 124),
+ (113, 126),
+ (114, 125),
+ (115, 128),
+ (116, 127),
+ (116, 129),
+ (117, 128),
+ (118, 131),
+ (119, 130),
+ (119, 132),
+ (120, 131),
+ (121, 134),
+ (122, 133),
+ (122, 135),
+ (123, 134),
+ (124, 137),
+ (125, 136),
+ (125, 138),
+ (126, 137),
+ (127, 140),
+ (128, 139),
+ (128, 141),
+ (129, 140),
+ (130, 143),
+ (131, 142),
+ (131, 144),
+ (132, 143),
+ (133, 146),
+ (134, 145),
+ (134, 147),
+ (135, 146),
+ (136, 149),
+ (137, 148),
+ (137, 150),
+ (138, 149),
+ (139, 152),
+ (140, 151),
+ (140, 153),
+ (141, 152),
+ (142, 155),
+ (143, 154),
+ (143, 156),
+ (144, 155),
+ (145, 158),
+ (146, 157),
+ (146, 159),
+ (147, 158),
+ (114, 126),
+ (115, 127),
+ (120, 132),
+ (121, 133),
+ (112, 124),
+ (118, 130),
+ (117, 129),
+ (123, 135),
+ (126, 138),
+ (127, 139),
+ (132, 144),
+ (133, 145),
+ (124, 136),
+ (130, 142),
+ (129, 141),
+ (135, 147),
+ (138, 150),
+ (139, 151),
+ (144, 156),
+ (145, 157),
+ (136, 148),
+ (142, 154),
+ (141, 153),
+ (147, 159),
+ (114, 127),
+ (115, 126),
+ (120, 133),
+ (121, 132),
+ (112, 130),
+ (118, 124),
+ (117, 135),
+ (123, 129),
+ (126, 139),
+ (127, 138),
+ (132, 145),
+ (133, 144),
+ (124, 142),
+ (130, 136),
+ (129, 147),
+ (135, 141),
+ (138, 151),
+ (139, 150),
+ (144, 157),
+ (145, 156),
+ (136, 154),
+ (142, 148),
+ (141, 153),
+ (147, 153),
+ (148, 149),
+ (149, 150),
+ (151, 152),
+ (152, 153),
+ (154, 155),
+ (155, 156),
+ (157, 158),
+ (158, 159),
+ (160, 161),
+ (161, 162),
+ (163, 164),
+ (164, 165),
+ (166, 167),
+ (167, 168),
+ (169, 170),
+ (170, 171),
+ (172, 173),
+ (173, 174),
+ (175, 176),
+ (176, 177),
+ (178, 179),
+ (179, 180),
+ (181, 182),
+ (182, 183),
+ (150, 151),
+ (156, 157),
+ (148, 154),
+ (153, 159),
+ (162, 163),
+ (168, 169),
+ (160, 166),
+ (165, 171),
+ (174, 175),
+ (180, 181),
+ (172, 178),
+ (177, 183),
+ (149, 161),
+ (152, 164),
+ (155, 167),
+ (158, 170),
+ (161, 173),
+ (164, 176),
+ (167, 179),
+ (170, 182),
+ (173, 185),
+ (176, 188),
+ (179, 191),
+ (182, 194),
+ (148, 161),
+ (149, 160),
+ (149, 162),
+ (150, 161),
+ (151, 164),
+ (152, 163),
+ (152, 165),
+ (153, 164),
+ (154, 167),
+ (155, 166),
+ (155, 168),
+ (156, 167),
+ (157, 170),
+ (158, 169),
+ (158, 171),
+ (159, 170),
+ (160, 173),
+ (161, 172),
+ (161, 174),
+ (162, 173),
+ (163, 176),
+ (164, 175),
+ (164, 177),
+ (165, 176),
+ (166, 179),
+ (167, 178),
+ (167, 180),
+ (168, 179),
+ (169, 182),
+ (170, 181),
+ (170, 183),
+ (171, 182),
+ (172, 185),
+ (173, 184),
+ (173, 186),
+ (174, 185),
+ (175, 188),
+ (176, 187),
+ (176, 189),
+ (177, 188),
+ (178, 191),
+ (179, 190),
+ (179, 192),
+ (180, 191),
+ (181, 194),
+ (182, 193),
+ (182, 195),
+ (183, 194),
+ (150, 162),
+ (151, 163),
+ (156, 168),
+ (157, 169),
+ (148, 160),
+ (154, 166),
+ (153, 165),
+ (159, 171),
+ (162, 174),
+ (163, 175),
+ (168, 180),
+ (169, 181),
+ (160, 172),
+ (166, 178),
+ (165, 177),
+ (171, 183),
+ (174, 186),
+ (175, 187),
+ (180, 192),
+ (181, 193),
+ (172, 184),
+ (178, 190),
+ (177, 189),
+ (183, 195),
+ (150, 163),
+ (151, 162),
+ (156, 169),
+ (157, 168),
+ (148, 166),
+ (154, 160),
+ (153, 171),
+ (159, 165),
+ (162, 175),
+ (163, 174),
+ (168, 181),
+ (169, 180),
+ (160, 178),
+ (166, 172),
+ (165, 183),
+ (171, 177),
+ (174, 187),
+ (175, 186),
+ (180, 193),
+ (180, 192),
+ (172, 190),
+ (178, 184),
+ (177, 195),
+ (183, 189),
+ (184, 185),
+ (185, 186),
+ (187, 188),
+ (188, 189),
+ (190, 191),
+ (191, 192),
+ (193, 194),
+ (194, 195),
+ (196, 197),
+ (197, 198),
+ (199, 200),
+ (200, 201),
+ (202, 203),
+ (203, 204),
+ (205, 206),
+ (206, 207),
+ (208, 209),
+ (209, 210),
+ (211, 212),
+ (212, 213),
+ (214, 215),
+ (215, 216),
+ (217, 218),
+ (218, 219),
+ (186, 187),
+ (192, 193),
+ (184, 190),
+ (189, 195),
+ (198, 199),
+ (204, 205),
+ (196, 202),
+ (201, 207),
+ (210, 211),
+ (216, 217),
+ (208, 214),
+ (213, 219),
+ (185, 197),
+ (188, 200),
+ (191, 203),
+ (194, 206),
+ (197, 209),
+ (200, 212),
+ (203, 215),
+ (206, 218),
+ (209, 221),
+ (212, 224),
+ (215, 227),
+ (218, 230),
+ (184, 197),
+ (185, 196),
+ (185, 198),
+ (186, 197),
+ (187, 200),
+ (188, 199),
+ (188, 201),
+ (189, 200),
+ (190, 203),
+ (191, 202),
+ (191, 204),
+ (192, 203),
+ (193, 206),
+ (194, 205),
+ (194, 207),
+ (195, 206),
+ (196, 209),
+ (197, 208),
+ (197, 210),
+ (198, 209),
+ (199, 212),
+ (200, 211),
+ (200, 213),
+ (201, 212),
+ (202, 215),
+ (203, 214),
+ (203, 216),
+ (204, 215),
+ (205, 218),
+ (206, 217),
+ (206, 219),
+ (207, 218),
+ (208, 221),
+ (209, 220),
+ (209, 222),
+ (210, 221),
+ (211, 224),
+ (212, 223),
+ (212, 225),
+ (213, 224),
+ (214, 227),
+ (215, 226),
+ (215, 228),
+ (216, 227),
+ (217, 230),
+ (218, 229),
+ (218, 231),
+ (219, 230),
+ (186, 198),
+ (187, 199),
+ (192, 204),
+ (193, 205),
+ (184, 196),
+ (190, 202),
+ (189, 201),
+ (195, 207),
+ (198, 210),
+ (199, 211),
+ (204, 216),
+ (205, 217),
+ (196, 208),
+ (202, 214),
+ (201, 213),
+ (207, 219),
+ (210, 222),
+ (211, 223),
+ (216, 228),
+ (217, 229),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (186, 199),
+ (187, 198),
+ (192, 205),
+ (193, 204),
+ (184, 202),
+ (190, 196),
+ (189, 207),
+ (195, 201),
+ (198, 211),
+ (199, 210),
+ (204, 217),
+ (205, 216),
+ (196, 214),
+ (202, 208),
+ (201, 219),
+ (207, 213),
+ (210, 223),
+ (211, 222),
+ (216, 229),
+ (217, 228),
+ (208, 220),
+ (214, 226),
+ (213, 225),
+ (219, 231),
+ (220, 221),
+ (221, 222),
+ (223, 224),
+ (224, 225),
+ (226, 227),
+ (227, 228),
+ (229, 230),
+ (230, 231),
+ (222, 223),
+ (228, 229),
+ (220, 226),
+ (225, 231),
+ (221, 233),
+ (224, 236),
+ (227, 239),
+ (230, 242),
+ (222, 233),
+ (220, 233),
+ (223, 236),
+ (225, 236),
+ (226, 239),
+ (228, 239),
+ (229, 242),
+ (231, 242),
+ (221, 234),
+ (221, 232),
+ (224, 235),
+ (224, 237),
+ (227, 238),
+ (227, 240),
+ (230, 241),
+ (230, 243),
+ (222, 234),
+ (223, 235),
+ (228, 240),
+ (229, 241),
+ (220, 232),
+ (226, 238),
+ (225, 237),
+ (231, 243),
+ (222, 235),
+ (223, 234),
+ (228, 241),
+ (229, 240),
+ (220, 238),
+ (226, 232),
+ (225, 243),
+ (231, 237)
+ ]
+
+
+
+
+ # memberType : Member type which contain the information about
+ # 1) cross-sectional area,
+ # 2) Young's modulus,
+ # 3) density of this member.
+
+
+ # Read data in this [.py]:
+ for joint, support in zip(joints, supports):
+ truss.AddNewJoint(joint, support)
+
+ for jointID, force in forces:
+ truss.AddExternalForce(jointID, force)
+
+ index = 0
+ for jointID0, jointID1 in members:
+ # memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ memberType = MemberType(A[index].item(), 10000.0, 0.1)
+
+ if (E != None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), E[index].item(), Rho[index].item())
+ elif (E != None) & (Rho==None):
+ memberType = MemberType(A[index].item(), E[index].item(), 0.1)
+ elif (E == None) & (Rho!=None):
+ memberType = MemberType(A[index].item(), 10000.0, Rho[index].item())
+
+ truss.AddNewMember(jointID0, jointID1, memberType)
+ index += 1
+
+ # Do direct stiffness method:
+ truss.Solve()
+
+ # Dump all the structural analysis results into a .json file:
+ # truss.DumpIntoJSON(TEST_OUTPUT_FILE)
+
+ # Get result of structural analysis:
+ displace, stress, resistance = truss.GetDisplacements(), truss.GetInternalStresses(), truss.GetResistances()
+ return displace, stress, resistance, truss, truss.weight
+
+
+
+
+
+
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+##########################################################################################
+
+
+def Truss10D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ X_scaled = X * (35-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss25D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ X_scaled = X * (10-0.31) + 0.31
+
+ return X_scaled
+
+
+def Truss72D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ X_scaled = X * (10-0.1) + 0.1
+
+ return X_scaled
+
+
+def Truss120D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = X * (20-0.775) + 0.775
+
+ return X_scaled
+
+def Truss360D_Scaling(X):
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ X_scaled = torch.zeros(X.shape)
+ X_scaled[:,:120] = X[:,:120] * (20-0.775) + 0.775
+ X_scaled[:,120:240] = X[:,120:240] * (5e4-1e3) + 1e3
+ X_scaled[:,240:360] = X[:,240:360] * (0.3-0.05) + 0.05
+
+ return X_scaled
+
+
+
+
+def Truss10D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss10bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ gx[ii,10] = max(abs(displace[1][0]), abs(displace[1][1])) - 2
+ gx[ii,11] = max(abs(displace[2][0]), abs(displace[2][1])) - 2
+ gx[ii,12] = max(abs(displace[4][0]), abs(displace[4][1])) - 2
+ gx[ii,13] = max(abs(displace[5][0]), abs(displace[5][1])) - 2
+
+ return gx, fx
+
+
+
+def Truss25D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 25, "Input must be an n-by-25 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 25 bar stress constraints, 6 displacement constraints
+ gx = torch.zeros(n,31)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss25bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 40ksi (34809)
+ for ss in range(25):
+ gx[ii,ss] = abs(stress[ss]) - 34809
+
+ # Max displacement in x and y direction less than .4 inches
+ for dd in range(6):
+ # print(displace[dd])
+ gx[ii,25+dd] = max(abs(displace[dd][0]), abs(displace[dd][1])) - 0.039
+
+
+ return gx, fx
+
+
+
+
+
+
+def Truss72D_4forces(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 72, "Input must be an n-by-72 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 72 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,76)
+
+ for ii in range(n):
+
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss72bar_4forces(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 25000
+ for ss in range(72):
+ gx[ii,ss] = abs(stress[ss]) - 25000
+
+ # Max displacement in x and y direction less than .25 inches
+ # print(displace[16], displace[17], displace[18], displace[19])
+ gx[ii,72] = max(abs(displace[16][0]), abs(displace[16][1])) - 0.25
+ gx[ii,73] = max(abs(displace[17][0]), abs(displace[17][1])) - 0.25
+ gx[ii,74] = max(abs(displace[18][0]), abs(displace[18][1])) - 0.25
+ gx[ii,75] = max(abs(displace[19][0]), abs(displace[19][1])) - 0.25
+
+
+ return gx, fx
+
+
+
+def Truss120D(A):
+
+ assert torch.is_tensor(A) and A.size(1) == 120, "Input must be an n-by-120 PyTorch tensor."
+ E = None
+ Rho = None
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, None)
+
+ if (E != None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ elif (E != None) & (Rho==None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ elif (E == None) & (Rho!=None):
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+def Truss360D(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 360, "Input must be an n-by-120 PyTorch tensor."
+ A = X[:,:120]
+ E = X[:,120:240]
+ Rho = X[:,240:360]
+
+ n = A.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 120 bar stress constraints, 1 displacement constraints
+ gx = torch.zeros(n,121)
+
+ for ii in range(n):
+ # print(ii)
+ # print(A[ii,:].shape)
+ displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+
+ # if (E != None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], Rho[ii,:])
+ # elif (E != None) & (Rho==None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], E[ii,:], None)
+ # elif (E == None) & (Rho!=None):
+ # displace, _, stress, _, _, weights = Truss120bar(A[ii,:], None, Rho[ii,:])
+
+ fx[ii,0] = -weights # Negate for maximizing optimization
+
+ # Max stress less than 34800
+ for ss in range(120):
+ gx[ii,ss] = abs(stress[ss]) - 34800
+ # gx[ii,ss] = abs(stress[ss]) - 34800
+
+ # Max displacement in x and y direction less than
+ MAX_DIST = 0
+ for dd in range(len(displace)):
+ if max(displace[dd]) > MAX_DIST:
+ MAX_DIST = max(abs(displace[dd]))
+ gx[ii,120] = MAX_DIST - 0.1969
+
+
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Trusses/.ipynb_checkpoints/Truss10D-checkpoint.py b/test_functions2/Trusses/.ipynb_checkpoints/Truss10D-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c56f09cfc2d258e92feb09e0c0bf19477e45acd
--- /dev/null
+++ b/test_functions2/Trusses/.ipynb_checkpoints/Truss10D-checkpoint.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+from .. import TrussSolvers
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(A)
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Trusses/Truss10D.py b/test_functions2/Trusses/Truss10D.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c56f09cfc2d258e92feb09e0c0bf19477e45acd
--- /dev/null
+++ b/test_functions2/Trusses/Truss10D.py
@@ -0,0 +1,64 @@
+import torch
+import numpy as np
+from .. import TrussSolvers
+
+
+
+
+def Truss10D(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 10, "Input must be an n-by-10 PyTorch tensor."
+
+ n = individuals.size(0)
+
+ fx = torch.zeros(n,1)
+
+ # 10 bar stress constraints, 4 displacement constraints
+ gx = torch.zeros(n,14)
+
+ for ii in range(n):
+ displace, stress, _, _, weights = Truss10bar(A)
+ fx[ii,0] = weights
+
+ for ss in range(10):
+ gx[ii,ss] = abs(stress[ss])
+
+ gx[ii,10] = displace[1][1]
+ gx[ii,11] = displace[2][1]
+ gx[ii,12] = displace[4][1]
+ gx[ii,13] = displace[5][1]
+
+ return gx, fx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test_functions2/Trusses/__pycache__/Truss10D.cpython-311.pyc b/test_functions2/Trusses/__pycache__/Truss10D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7805bcb57aaaeb456de17c80a26c30380821b4ef
Binary files /dev/null and b/test_functions2/Trusses/__pycache__/Truss10D.cpython-311.pyc differ
diff --git a/test_functions2/Untitled.ipynb b/test_functions2/Untitled.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..363fcab7ed6e9634e198cf5555ceb88932c9a245
--- /dev/null
+++ b/test_functions2/Untitled.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/test_functions2/WeldedBeam.py b/test_functions2/WeldedBeam.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1fd4d446c972834fc592de6b1484c772ea820ac
--- /dev/null
+++ b/test_functions2/WeldedBeam.py
@@ -0,0 +1,94 @@
+import torch
+import numpy as np
+
+#
+#
+# WeldedBeam: 4D objective, 5 constraints
+#
+# Reference:
+# Gandomi AH, Yang XS, Alavi AH (2011) Mixed
+# variable structural optimization using firefly
+# algorithm. Computers & Structures 89(23-
+# 24):2325–2336
+#
+#
+
+def WeldedBeam(individuals):
+
+ assert torch.is_tensor(individuals) and individuals.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+
+ C1 = 1.10471
+ C2 = 0.04811
+ C3 = 14.0
+ fx = torch.zeros(individuals.shape[0], 1)
+ gx1 = torch.zeros(individuals.shape[0], 1)
+ gx2 = torch.zeros(individuals.shape[0], 1)
+ gx3 = torch.zeros(individuals.shape[0], 1)
+ gx4 = torch.zeros(individuals.shape[0], 1)
+ gx5 = torch.zeros(individuals.shape[0], 1)
+
+ for i in range(individuals.shape[0]):
+
+ x = individuals[i,:]
+
+ h = x[0]
+ l = x[1]
+ t = x[2]
+ b = x[3]
+
+ test_function = - ( C1*h*h*l + C2*t*b*(C3+l) )
+ fx[i] = test_function
+
+ ## Calculate constraints terms
+ tao_dx = 6000 / (np.sqrt(2)*h*l)
+
+ tao_dxx = 6000*(14+0.5*l)*np.sqrt( 0.25*(l**2 + (h+t)**2 ) ) / (2* (0.707*h*l * ( l**2 /12 + 0.25*(h+t)**2 ) ) )
+
+ tao = np.sqrt( tao_dx**2 + tao_dxx**2 + l*tao_dx*tao_dxx / np.sqrt(0.25*(l**2 + (h+t)**2)) )
+
+ sigma = 504000/ (t**2 * b)
+
+ P_c = 64746*(1-0.0282346*t)* t * b**3
+
+ delta = 2.1952/ (t**3 *b)
+
+
+ ## Calculate 5 constraints
+ g1 = (-1) * (13600- tao)
+ g2 = (-1) * (30000 - sigma)
+ g3 = (-1) * (b - h)
+ g4 = (-1) * (P_c - 6000)
+ g5 = (-1) * (0.25 - delta)
+
+ gx1[i] = g1
+ gx2[i] = g2
+ gx3[i] = g3
+ gx4[i] = g4
+ gx5[i] = g5
+
+
+
+ gx = torch.cat((gx1, gx2, gx3, gx4, gx5), 1)
+ return gx, fx
+
+
+def WeldedBeam_Scaling(X):
+
+ assert torch.is_tensor(X) and X.size(1) == 4, "Input must be an n-by-4 PyTorch tensor."
+
+ h = (X[:,0] * (10-0.125) + 0.125 ).reshape(X.shape[0],1)
+ l = (X[:,1] * (15-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ t = (X[:,2] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+ b = (X[:,3] * (10-0.1 ) + 0.1 ).reshape(X.shape[0],1)
+
+ X_scaled = torch.cat((h, l, t, b), dim=1)
+ return X_scaled
+
+
+
+
+
+
+
+
diff --git a/test_functions2/__init__.py b/test_functions2/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test_functions2/__pycache__/Ackley10D.cpython-310.pyc b/test_functions2/__pycache__/Ackley10D.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..939c395963562b5e43943dd937217c9a0c158cf8
Binary files /dev/null and b/test_functions2/__pycache__/Ackley10D.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Ackley10D.cpython-311.pyc b/test_functions2/__pycache__/Ackley10D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3ae42be16174f26a558ce50a3d06697772a3c25c
Binary files /dev/null and b/test_functions2/__pycache__/Ackley10D.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Ackley10D.cpython-38.pyc b/test_functions2/__pycache__/Ackley10D.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a4a46205bee4741268a6e0b43afa9fe2d9b48852
Binary files /dev/null and b/test_functions2/__pycache__/Ackley10D.cpython-38.pyc differ
diff --git a/test_functions2/__pycache__/Ackley10D.cpython-39.pyc b/test_functions2/__pycache__/Ackley10D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..95c62aee32e19b75ca36f1d3855d77a0dd26f867
Binary files /dev/null and b/test_functions2/__pycache__/Ackley10D.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Ackley2D.cpython-310.pyc b/test_functions2/__pycache__/Ackley2D.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..48696fe053334a107153dfa86c7e8051e6b36e5a
Binary files /dev/null and b/test_functions2/__pycache__/Ackley2D.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Ackley2D.cpython-311.pyc b/test_functions2/__pycache__/Ackley2D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..644ddef1084f73e8f24a285fdfd4d40e543cc0a7
Binary files /dev/null and b/test_functions2/__pycache__/Ackley2D.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Ackley2D.cpython-39.pyc b/test_functions2/__pycache__/Ackley2D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..418e674ed5473813101c3a684262d0490bfb69a8
Binary files /dev/null and b/test_functions2/__pycache__/Ackley2D.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Ackley2DEmbedd.cpython-310.pyc b/test_functions2/__pycache__/Ackley2DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..210499996825793de72e934a965a5c1c826be6e7
Binary files /dev/null and b/test_functions2/__pycache__/Ackley2DEmbedd.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Ackley2DEmbedd.cpython-311.pyc b/test_functions2/__pycache__/Ackley2DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9f12c863e2981114aee51e6abdc371456332922e
Binary files /dev/null and b/test_functions2/__pycache__/Ackley2DEmbedd.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Ackley2DEmbedd.cpython-39.pyc b/test_functions2/__pycache__/Ackley2DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f2db2bc5155d6638d45022e1093a1b9a0c706c75
Binary files /dev/null and b/test_functions2/__pycache__/Ackley2DEmbedd.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Ackley500D.cpython-39.pyc b/test_functions2/__pycache__/Ackley500D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..76e58d8dbc301bd9c89b75b519fcfc701c8a80e8
Binary files /dev/null and b/test_functions2/__pycache__/Ackley500D.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Ackley6D.cpython-310.pyc b/test_functions2/__pycache__/Ackley6D.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..83f4ad1b94ca40b3deadf33f7db8640ff67f23f0
Binary files /dev/null and b/test_functions2/__pycache__/Ackley6D.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Ackley6D.cpython-311.pyc b/test_functions2/__pycache__/Ackley6D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..14dd6827d006a8a622706304d0a401635a1df4e5
Binary files /dev/null and b/test_functions2/__pycache__/Ackley6D.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Ackley6D.cpython-39.pyc b/test_functions2/__pycache__/Ackley6D.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3d7de45bbdb14792369732daa1507fcdfddfc60e
Binary files /dev/null and b/test_functions2/__pycache__/Ackley6D.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/AckleyND.cpython-310.pyc b/test_functions2/__pycache__/AckleyND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b7c064f93d72f66938ab3bbdbf21103959ff1baf
Binary files /dev/null and b/test_functions2/__pycache__/AckleyND.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/AckleyND.cpython-311.pyc b/test_functions2/__pycache__/AckleyND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..850434077b1be71540506552b318c1c19fb97693
Binary files /dev/null and b/test_functions2/__pycache__/AckleyND.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/AckleyND.cpython-39.pyc b/test_functions2/__pycache__/AckleyND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d4dbd31eb1085de872602aefcc7d904a0cf3bdbe
Binary files /dev/null and b/test_functions2/__pycache__/AckleyND.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Branin2DEmbedd.cpython-310.pyc b/test_functions2/__pycache__/Branin2DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d8b60958c0e8c5b973c3c069570095b9e99f927c
Binary files /dev/null and b/test_functions2/__pycache__/Branin2DEmbedd.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Branin2DEmbedd.cpython-311.pyc b/test_functions2/__pycache__/Branin2DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d86f86c1c005fd6b715fe5c0dec94dcb14d0f998
Binary files /dev/null and b/test_functions2/__pycache__/Branin2DEmbedd.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Branin2DEmbedd.cpython-39.pyc b/test_functions2/__pycache__/Branin2DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..77ece24a0ac413c34f6e99d5ddf29ce447adbe19
Binary files /dev/null and b/test_functions2/__pycache__/Branin2DEmbedd.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Bukin.cpython-311.pyc b/test_functions2/__pycache__/Bukin.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e3618d32603e6ac6c6a8bd8268c498d094cb0d3e
Binary files /dev/null and b/test_functions2/__pycache__/Bukin.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/CantileverBeam.cpython-310.pyc b/test_functions2/__pycache__/CantileverBeam.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e93b09863eae39b244c652aa7f2361a422ff6f5a
Binary files /dev/null and b/test_functions2/__pycache__/CantileverBeam.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/CantileverBeam.cpython-311.pyc b/test_functions2/__pycache__/CantileverBeam.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fa557da6eba8d0edeea57a272a070679a12f9809
Binary files /dev/null and b/test_functions2/__pycache__/CantileverBeam.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/CantileverBeam.cpython-39.pyc b/test_functions2/__pycache__/CantileverBeam.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6541fb6552f858709d8186ad8973ee674add5b59
Binary files /dev/null and b/test_functions2/__pycache__/CantileverBeam.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Car.cpython-310.pyc b/test_functions2/__pycache__/Car.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d41b5d3dcd430f72285141dffb6e7962d59c2e61
Binary files /dev/null and b/test_functions2/__pycache__/Car.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Car.cpython-311.pyc b/test_functions2/__pycache__/Car.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d6f0598a927366f93a45cf2dd53787c988e6129f
Binary files /dev/null and b/test_functions2/__pycache__/Car.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Car.cpython-39.pyc b/test_functions2/__pycache__/Car.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c043c7d33f164255c35e974ffb54e8e86329b3dd
Binary files /dev/null and b/test_functions2/__pycache__/Car.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/CompressionSpring.cpython-310.pyc b/test_functions2/__pycache__/CompressionSpring.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ab754c07b5beba79947d9d402bea5c9420aa6630
Binary files /dev/null and b/test_functions2/__pycache__/CompressionSpring.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/CompressionSpring.cpython-311.pyc b/test_functions2/__pycache__/CompressionSpring.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f5f3b7dd6129e869e1cc16a723d160b57ffad9ed
Binary files /dev/null and b/test_functions2/__pycache__/CompressionSpring.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/CompressionSpring.cpython-39.pyc b/test_functions2/__pycache__/CompressionSpring.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8c8ba9bb4c1e04c9e5f7bd1b5e98d39c0924fb82
Binary files /dev/null and b/test_functions2/__pycache__/CompressionSpring.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/DixonPriceND.cpython-310.pyc b/test_functions2/__pycache__/DixonPriceND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..586f6a3a895dc88673938abcfd376c714e4f521a
Binary files /dev/null and b/test_functions2/__pycache__/DixonPriceND.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/DixonPriceND.cpython-311.pyc b/test_functions2/__pycache__/DixonPriceND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4e5022b77c44c009b60e1ddcd6502e24e675c3d7
Binary files /dev/null and b/test_functions2/__pycache__/DixonPriceND.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/DixonPriceND.cpython-39.pyc b/test_functions2/__pycache__/DixonPriceND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..39495310240c0def36cf9ee30b14d1308adbe4d4
Binary files /dev/null and b/test_functions2/__pycache__/DixonPriceND.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/DummyFixConsDim.cpython-39.pyc b/test_functions2/__pycache__/DummyFixConsDim.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..52af684f87fe9f6c40b75b8aa0b29b22fb184a6b
Binary files /dev/null and b/test_functions2/__pycache__/DummyFixConsDim.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Finder24.cpython-310.pyc b/test_functions2/__pycache__/Finder24.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e527a0a7b92d4e8abbe47c51482d5628997a34ba
Binary files /dev/null and b/test_functions2/__pycache__/Finder24.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Finder24.cpython-311.pyc b/test_functions2/__pycache__/Finder24.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0bfa36d6caadccfb998746775800a123ff78d0b5
Binary files /dev/null and b/test_functions2/__pycache__/Finder24.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Finder24.cpython-39.pyc b/test_functions2/__pycache__/Finder24.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8ae13202cb4ee5377d3b9ae888924ad7f99dbcc2
Binary files /dev/null and b/test_functions2/__pycache__/Finder24.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/GKXWC1.cpython-310.pyc b/test_functions2/__pycache__/GKXWC1.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7e101b74e2e66e77d868a4a0b0e4b02266259cf8
Binary files /dev/null and b/test_functions2/__pycache__/GKXWC1.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/GKXWC1.cpython-311.pyc b/test_functions2/__pycache__/GKXWC1.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a9cadc30f2136af1c8cc3bfe5ee628a1b97e1c04
Binary files /dev/null and b/test_functions2/__pycache__/GKXWC1.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/GKXWC1.cpython-39.pyc b/test_functions2/__pycache__/GKXWC1.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7f7d1f228860840c6c93f2b2f24ad762ebac29d0
Binary files /dev/null and b/test_functions2/__pycache__/GKXWC1.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/GKXWC2.cpython-310.pyc b/test_functions2/__pycache__/GKXWC2.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..69d53386580ad1de7e5fd2dde3cc1a9cb618bed7
Binary files /dev/null and b/test_functions2/__pycache__/GKXWC2.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/GKXWC2.cpython-311.pyc b/test_functions2/__pycache__/GKXWC2.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f57c83d5bd23d4fa99f488bf2b859570cecdf5b4
Binary files /dev/null and b/test_functions2/__pycache__/GKXWC2.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/GKXWC2.cpython-39.pyc b/test_functions2/__pycache__/GKXWC2.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b65cf9f09c2547f00130e555dbd5ae9eb80563d0
Binary files /dev/null and b/test_functions2/__pycache__/GKXWC2.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Griewank2DEmbedd.cpython-310.pyc b/test_functions2/__pycache__/Griewank2DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a297b3f72898354ea2d8a7943d3396319495d540
Binary files /dev/null and b/test_functions2/__pycache__/Griewank2DEmbedd.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Griewank2DEmbedd.cpython-311.pyc b/test_functions2/__pycache__/Griewank2DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2d2f025c02ab16478e654c368c8bf139068df18a
Binary files /dev/null and b/test_functions2/__pycache__/Griewank2DEmbedd.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Griewank2DEmbedd.cpython-39.pyc b/test_functions2/__pycache__/Griewank2DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..85db9a07a0107f800a70e09adf1606c6c37c8ed3
Binary files /dev/null and b/test_functions2/__pycache__/Griewank2DEmbedd.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/GriewankND.cpython-310.pyc b/test_functions2/__pycache__/GriewankND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ef22a6920da256bd320bd55f45eaa06d6eba82d4
Binary files /dev/null and b/test_functions2/__pycache__/GriewankND.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/GriewankND.cpython-311.pyc b/test_functions2/__pycache__/GriewankND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2095e30da12bbc3436eb0eca56636a4bd7c9b9cb
Binary files /dev/null and b/test_functions2/__pycache__/GriewankND.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/GriewankND.cpython-39.pyc b/test_functions2/__pycache__/GriewankND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a059a496f5c000e8249f556ca6dbbedc03775532
Binary files /dev/null and b/test_functions2/__pycache__/GriewankND.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-310.pyc b/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c6cc7194648d8a711a572f99a6fc71d54e0e74fe
Binary files /dev/null and b/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-311.pyc b/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..57dfa4eddc8e0280c7b8b662ba838c68af476a0f
Binary files /dev/null and b/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-39.pyc b/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cf04485f8642f6ad6e1aea4f02643b73f5395646
Binary files /dev/null and b/test_functions2/__pycache__/Hartmann6DEmbedd.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/HeatExchanger.cpython-310.pyc b/test_functions2/__pycache__/HeatExchanger.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..126cd04d58680677e2a9c66eafc4d44f68e2e390
Binary files /dev/null and b/test_functions2/__pycache__/HeatExchanger.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/HeatExchanger.cpython-311.pyc b/test_functions2/__pycache__/HeatExchanger.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2d9d1ccbac8975b2efeb6d4f4dced634c5c6ec0f
Binary files /dev/null and b/test_functions2/__pycache__/HeatExchanger.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/HeatExchanger.cpython-39.pyc b/test_functions2/__pycache__/HeatExchanger.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9bb2fd67858f60c658f8ecc2979d7ce7dc6c3c71
Binary files /dev/null and b/test_functions2/__pycache__/HeatExchanger.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/JLH1.cpython-310.pyc b/test_functions2/__pycache__/JLH1.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2e9e414c0d3eceb124570db025e2f357043f3c4c
Binary files /dev/null and b/test_functions2/__pycache__/JLH1.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/JLH1.cpython-311.pyc b/test_functions2/__pycache__/JLH1.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b81a5075281446add616777cf6181c8947e10abb
Binary files /dev/null and b/test_functions2/__pycache__/JLH1.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/JLH1.cpython-39.pyc b/test_functions2/__pycache__/JLH1.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bcfd134993680524aa669020b76cb119f7f266e4
Binary files /dev/null and b/test_functions2/__pycache__/JLH1.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/JLH2.cpython-310.pyc b/test_functions2/__pycache__/JLH2.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..81e614f9f1e374e191d3365442f80283de4b5a81
Binary files /dev/null and b/test_functions2/__pycache__/JLH2.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/JLH2.cpython-311.pyc b/test_functions2/__pycache__/JLH2.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0ab85797fa246a5c770e3f6233e343ca1982e058
Binary files /dev/null and b/test_functions2/__pycache__/JLH2.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/JLH2.cpython-39.pyc b/test_functions2/__pycache__/JLH2.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..75113ff485cc009bd163c461ba59214e2c8847fe
Binary files /dev/null and b/test_functions2/__pycache__/JLH2.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/KeaneBump.cpython-310.pyc b/test_functions2/__pycache__/KeaneBump.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..37353c3e5b89945e39107d539a1aeaad239d6c0d
Binary files /dev/null and b/test_functions2/__pycache__/KeaneBump.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/KeaneBump.cpython-311.pyc b/test_functions2/__pycache__/KeaneBump.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2db095a9dc0cc582d205edf7a1a4550970e39152
Binary files /dev/null and b/test_functions2/__pycache__/KeaneBump.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/KeaneBump.cpython-39.pyc b/test_functions2/__pycache__/KeaneBump.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9b132ac7c361517516c4f8e97329250c8766fe4c
Binary files /dev/null and b/test_functions2/__pycache__/KeaneBump.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Levy.cpython-311.pyc b/test_functions2/__pycache__/Levy.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b6f55a4256ba1af1e844f94db633cb42b5c780ec
Binary files /dev/null and b/test_functions2/__pycache__/Levy.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/LevyND.cpython-310.pyc b/test_functions2/__pycache__/LevyND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1bb4b5eb99c7a6f3e7e12b6eaa4fb1834707ce48
Binary files /dev/null and b/test_functions2/__pycache__/LevyND.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/LevyND.cpython-311.pyc b/test_functions2/__pycache__/LevyND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b4917acc0be938310e474a448cfb52e4fa045b72
Binary files /dev/null and b/test_functions2/__pycache__/LevyND.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/LevyND.cpython-39.pyc b/test_functions2/__pycache__/LevyND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..132b09ef70d6973cf8e8be79c08848bca93044a3
Binary files /dev/null and b/test_functions2/__pycache__/LevyND.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/MOPTA08_Car.cpython-310.pyc b/test_functions2/__pycache__/MOPTA08_Car.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2b570ced71a9ba919a2ddfc082ecd3bd4d02e349
Binary files /dev/null and b/test_functions2/__pycache__/MOPTA08_Car.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Mazda.cpython-310.pyc b/test_functions2/__pycache__/Mazda.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4ce83bf75eae1535ef66542bf83af43ecadf81dd
Binary files /dev/null and b/test_functions2/__pycache__/Mazda.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/MichalewiczND.cpython-310.pyc b/test_functions2/__pycache__/MichalewiczND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..65fe456760bee8c2eaace445222d5add4b24b8f1
Binary files /dev/null and b/test_functions2/__pycache__/MichalewiczND.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/MichalewiczND.cpython-311.pyc b/test_functions2/__pycache__/MichalewiczND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..37d916bdec013df6e18aed1f01b97261cb181216
Binary files /dev/null and b/test_functions2/__pycache__/MichalewiczND.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/MichalewiczND.cpython-39.pyc b/test_functions2/__pycache__/MichalewiczND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..edd94dbb5dde010f6fa12aca776cfa8db2458e72
Binary files /dev/null and b/test_functions2/__pycache__/MichalewiczND.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/PressureVessel.cpython-310.pyc b/test_functions2/__pycache__/PressureVessel.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ca85f9ef4ea54aa48e576f4329da7dfc9851688f
Binary files /dev/null and b/test_functions2/__pycache__/PressureVessel.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/PressureVessel.cpython-311.pyc b/test_functions2/__pycache__/PressureVessel.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..72afd0c05e9667c17add0c054fcf098110bcdfed
Binary files /dev/null and b/test_functions2/__pycache__/PressureVessel.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/PressureVessel.cpython-39.pyc b/test_functions2/__pycache__/PressureVessel.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8edfc1b685828428b3d262a891d70aabf1a6c1b6
Binary files /dev/null and b/test_functions2/__pycache__/PressureVessel.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-310.pyc b/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c0b1c22014f4ca94653068e17dd9b32dac41d58c
Binary files /dev/null and b/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-311.pyc b/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ae8a261c549b4b643b8dd79c14ad914be61ce4de
Binary files /dev/null and b/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-39.pyc b/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e9b627248a13fd78e03f1e3330e5e2f3187d07b7
Binary files /dev/null and b/test_functions2/__pycache__/ReinforcedConcreteBeam.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-310.pyc b/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7a5abd79f6cb01056e537f0638515a7c5b6f2329
Binary files /dev/null and b/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-311.pyc b/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9569c67ef77216ee9888c06b5ab0bc8cbe514e42
Binary files /dev/null and b/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-39.pyc b/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2fe0a405202d0ef65b2aad2be6a53e9fa643e476
Binary files /dev/null and b/test_functions2/__pycache__/Rosenbrock3DEmbedd.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/RosenbrockND.cpython-310.pyc b/test_functions2/__pycache__/RosenbrockND.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6baf7e5b553183324429f6802f2ec835d3c3b4f5
Binary files /dev/null and b/test_functions2/__pycache__/RosenbrockND.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/RosenbrockND.cpython-311.pyc b/test_functions2/__pycache__/RosenbrockND.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..02195df22f1275031eceeec17eeef0a76d20da4c
Binary files /dev/null and b/test_functions2/__pycache__/RosenbrockND.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/RosenbrockND.cpython-39.pyc b/test_functions2/__pycache__/RosenbrockND.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..90c014806a559ab3cadd24818f1cbd562b44a497
Binary files /dev/null and b/test_functions2/__pycache__/RosenbrockND.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/RosenbrockND2.cpython-39.pyc b/test_functions2/__pycache__/RosenbrockND2.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..761d536bb62da050e991c3cd308b54d350a48fef
Binary files /dev/null and b/test_functions2/__pycache__/RosenbrockND2.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/SpeedReducer.cpython-310.pyc b/test_functions2/__pycache__/SpeedReducer.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7ac44436083104ba683c9584ceade7d83cbf65c1
Binary files /dev/null and b/test_functions2/__pycache__/SpeedReducer.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/SpeedReducer.cpython-311.pyc b/test_functions2/__pycache__/SpeedReducer.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..89af139741afec84b12a1b3d5772e4fe96cf51d6
Binary files /dev/null and b/test_functions2/__pycache__/SpeedReducer.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/SpeedReducer.cpython-39.pyc b/test_functions2/__pycache__/SpeedReducer.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..33f1eef604ca36a02e6db838d942ce6c70bef5ab
Binary files /dev/null and b/test_functions2/__pycache__/SpeedReducer.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/ThreeTruss.cpython-310.pyc b/test_functions2/__pycache__/ThreeTruss.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4529829c8facb666f42e9c472a8ff7b1b3022449
Binary files /dev/null and b/test_functions2/__pycache__/ThreeTruss.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/ThreeTruss.cpython-311.pyc b/test_functions2/__pycache__/ThreeTruss.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c32e7ffd8c117c108fc673241eb40b49fb70a618
Binary files /dev/null and b/test_functions2/__pycache__/ThreeTruss.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/ThreeTruss.cpython-39.pyc b/test_functions2/__pycache__/ThreeTruss.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..72341f2a1f9d85712d9b27eba53368bbd56dd28a
Binary files /dev/null and b/test_functions2/__pycache__/ThreeTruss.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/Truss10D.cpython-311.pyc b/test_functions2/__pycache__/Truss10D.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f2ce9f7ae94ced99a12c7cf48bb2de18e417973a
Binary files /dev/null and b/test_functions2/__pycache__/Truss10D.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/TrussSolvers.cpython-310.pyc b/test_functions2/__pycache__/TrussSolvers.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..986b509ec9446fc5606c259d684c40f0f00bb829
Binary files /dev/null and b/test_functions2/__pycache__/TrussSolvers.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/TrussSolvers.cpython-311.pyc b/test_functions2/__pycache__/TrussSolvers.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8133676f684c3d6d6be27eedcde7dc6cb495efc7
Binary files /dev/null and b/test_functions2/__pycache__/TrussSolvers.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/TrussSolvers.cpython-39.pyc b/test_functions2/__pycache__/TrussSolvers.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3ba0c010acbb528ebdab2655ed0efe777078135f
Binary files /dev/null and b/test_functions2/__pycache__/TrussSolvers.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/WeldedBeam.cpython-310.pyc b/test_functions2/__pycache__/WeldedBeam.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..58227265f3ad3b462f71380a76fee3323d456a06
Binary files /dev/null and b/test_functions2/__pycache__/WeldedBeam.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/WeldedBeam.cpython-311.pyc b/test_functions2/__pycache__/WeldedBeam.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4c0effba343bddae44173e73f378f7fefbd11eab
Binary files /dev/null and b/test_functions2/__pycache__/WeldedBeam.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/WeldedBeam.cpython-39.pyc b/test_functions2/__pycache__/WeldedBeam.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..704e00fd46d8d1c6cf465bdcf7be39b5a5c9a3ac
Binary files /dev/null and b/test_functions2/__pycache__/WeldedBeam.cpython-39.pyc differ
diff --git a/test_functions2/__pycache__/__init__.cpython-310.pyc b/test_functions2/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9a94dd323034667264a27ecaa80b5b1c6e19abbd
Binary files /dev/null and b/test_functions2/__pycache__/__init__.cpython-310.pyc differ
diff --git a/test_functions2/__pycache__/__init__.cpython-311.pyc b/test_functions2/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..49576ffe7c31731698a99d4350006bbdc61aa79b
Binary files /dev/null and b/test_functions2/__pycache__/__init__.cpython-311.pyc differ
diff --git a/test_functions2/__pycache__/__init__.cpython-39.pyc b/test_functions2/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4f8d54fd1009f40dac5ea27670b1564d9c0f85a5
Binary files /dev/null and b/test_functions2/__pycache__/__init__.cpython-39.pyc differ
diff --git a/test_functions2/datasets.py b/test_functions2/datasets.py
new file mode 100644
index 0000000000000000000000000000000000000000..cdf7b8ec9d0f027fc2541f1bee8edd921c6e0587
--- /dev/null
+++ b/test_functions2/datasets.py
@@ -0,0 +1,68 @@
+# Author: Qiuyi
+
+import torch
+import torch.nn.functional as F
+from sklearn.decomposition import PCA
+
+def cube(n_samples, dim=2):
+ return torch.rand([n_samples, dim])
+
+def sphere(n_samples, dim=1):
+ X = torch.randn([n_samples, dim+1])
+ return F.normalize(X, dim=-1)
+
+def torus(n_samples, R=2, r=1):
+ u, v = (torch.rand([n_samples, 2]) * 2 * torch.pi).chunk(2, -1)
+ x = (R + r * torch.cos(u)) * torch.cos(v)
+ y = (R + r * torch.cos(u)) * torch.sin(v)
+ z = r * torch.sin(u)
+ return torch.cat([x, y, z], dim=-1)
+
+def mobius_strip(n_samples):
+ u, v = torch.rand([n_samples, 2]).chunk(2, -1)
+ u *= 2 * torch.pi
+ x = (1 + v/2 * torch.cos(u/2)) * torch.cos(u)
+ y = (1 + v/2 * torch.cos(u/2)) * torch.sin(u)
+ z = v/2 * torch.sin(u/2)
+ return torch.cat([x, y, z], dim=-1)
+
+def klein_bottle(n_samples, R=2, P=1, e=0.1):
+ u, v = (torch.rand([n_samples, 2]) * 2 * torch.pi).chunk(2, -1)
+ x = R * (torch.cos(u/2) * torch.cos(v) - torch.sin(u/2) * torch.sin(v*2))
+ y = R * (torch.sin(u/2) * torch.cos(v) + torch.cos(u/2) * torch.sin(v*2))
+ z = P * torch.cos(u) * (1 + e * torch.sin(v))
+ w = P * torch.sin(u) * (1 + e * torch.sin(v))
+ return torch.cat([x, y, z, w], dim=-1)
+
+
+################################ Immersions ################################
+# For nonlinearly embedding datasets into high dimensional ambient spaces. #
+############################################################################
+
+def polynomial_immersion(dataset, ambient_dim, weight=(1,1,0)):
+ """
+ The graph of a continous function is homeomorphic to its domain.
+ Immersion is performed by polynomial function.
+ """
+
+ X = (dataset - dataset.mean(0)) / (dataset.std(0) * 2)
+ XX = (X.unsqueeze(1) * X.unsqueeze(2)).flatten(1)
+ XXX = (X.view(len(X), 1, 1, -1) \
+ * X.view(len(X), 1, -1, 1) \
+ * X.view(len(X), -1, 1, 1)).flatten(1)
+
+ in_dim = dataset.size(-1)
+ out_dim = ambient_dim - in_dim
+
+ # 2nd order polynomial function Y = f(X)
+ W1 = torch.randn(X.size(-1), out_dim) * weight[0]
+ W2 = torch.randn(XX.size(-1), out_dim) * weight[1]
+ W3 = torch.randn(XXX.size(-1), out_dim) * weight[2]
+ Y = X @ W1 + XX @ W2 + XXX @ W3
+
+ # rescaling
+ D = torch.cat([dataset, Y], dim=-1) # graph of polynomial f
+ D = torch.as_tensor(PCA(D.size(-1)).fit_transform(D), dtype=torch.float)
+ s = torch.rand(D.size(-1)) * (1-0.5) + 0.5
+ D = D / D.std(0).clip(3e-7) * s
+ return D
\ No newline at end of file
diff --git a/test_functions2/input.txt b/test_functions2/input.txt
new file mode 100644
index 0000000000000000000000000000000000000000..04b7bb99f00038b55675cf6cce701906c3a68753
--- /dev/null
+++ b/test_functions2/input.txt
@@ -0,0 +1,124 @@
+0.7163974642753601
+0.9993265378225802
+0.00681085416469197
+0.49657461047172546
+0.5421959757804871
+0.07028308510780334
+0.7375115156173706
+0.23079676900863894
+0.17524531483650208
+0.4165057837963104
+0.7863314655462468
+0.9103859561629767
+0.9884545207023621
+0.49428999423980713
+0.7333322753519758
+0.3440784960247453
+0.2530369758605957
+0.4683438539505005
+0.7195425033569336
+0.4212913572074431
+0.058185406029224396
+0.06039922311902046
+0.2849200367927551
+0.11604490131139755
+0.8867061209432993
+0.5261104744926556
+0.0431898795068264
+0.3900279998779297
+0.1029452458024025
+0.20407527685165405
+0.1734655201435089
+0.19775275124324224
+0.7156706543915524
+0.04655173287253966
+0.4848773777484894
+0.30312734842300415
+0.4447859227657318
+0.6366506218910217
+0.8890612125396729
+0.7058064453653432
+0.4439832164896989
+0.9059072732925415
+0.9707982540130615
+0.19974938035011292
+0.2055460810661316
+0.2900460958480835
+0.2580410872096335
+0.09955541121486575
+0.1132098063826561
+0.24213725328445435
+0.8225266933441162
+0.42824631929397583
+0.7951440215110779
+0.6829838315960868
+0.16282251477241516
+0.3188931224570868
+0.6323996782302856
+0.6375263929367065
+0.8299118876457214
+0.052584003657102585
+0.38849183992486186
+0.4983891248703003
+0.13332130014896393
+0.556024432182312
+0.4132501184940338
+0.609487771987915
+0.9169092783257323
+0.4322524964809418
+0.366078273140641
+0.05536458277562482
+0.9767963290214539
+0.42411284168974506
+0.2329164743423462
+0.6744847893714905
+0.20683512353720418
+0.2293541160335567
+0.6657138466835022
+0.4732159972190857
+0.522901713848114
+0.11109761893749237
+0.11648011532987006
+0.3706672489643097
+0.9088611602783203
+0.7435321807861328
+0.4555647075176239
+0.03607107698917389
+0.35120466351509094
+0.28899073600769043
+0.345764785939289
+0.10496806353330612
+0.15953752398490906
+0.8993461090965778
+0.5391926443756834
+0.5935213299694775
+0.6363073587417603
+0.7447469660168282
+0.6408606171607971
+0.03914232147871405
+0.7236809310663285
+0.03898954764008522
+0.4348384141921997
+0.06559677971676071
+0.7644200989186132
+0.34992800388839107
+0.5224961802261936
+0.36969325605008013
+0.47937899827957153
+0.423367977142334
+0.11889548599720001
+0.34784603118896484
+0.493608683347702
+0.734581147879136
+0.8358172869987468
+0.784054305684064
+0.9184759259223938
+0.5115121006965637
+0.6107214132737988
+0.4500758945941925
+0.8577175394534933
+0.648746156974023
+0.20206538987318162
+0.4083820879459381
+0.6682699918746948
+0.9255886843723466
diff --git a/test_functions2/models.py b/test_functions2/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce5e13697e9c81b5ae70132d7aa59673c48c1783
--- /dev/null
+++ b/test_functions2/models.py
@@ -0,0 +1,81 @@
+# Author: Qiuyi
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.nn.utils.parametrizations import spectral_norm
+
+
+class _Combo(nn.Module):
+ def forward(self, input):
+ return self.model(input)
+
+class LinearCombo(_Combo):
+ def __init__(self, in_features, out_features, activation=nn.LeakyReLU(0.2)):
+ super().__init__()
+ self.model = nn.Sequential(
+ nn.Linear(in_features, out_features),
+ activation
+ )
+
+class SNLinearCombo(_Combo):
+ def __init__(self, in_features, out_features, activation=nn.LeakyReLU(0.2)):
+ super().__init__()
+ self.model = nn.Sequential(
+ spectral_norm(nn.Linear(in_features, out_features)),
+ activation
+ )
+
+class MLP(nn.Module):
+ """Regular fully connected network generating features.
+
+ Args:
+ in_features: The number of input features.
+ out_feature: The number of output features.
+ layer_width: The widths of the hidden layers.
+ combo: The layer combination to be stacked up.
+
+ Shape:
+ - Input: `(N, H_in)` where H_in = in_features.
+ - Output: `(N, H_out)` where H_out = out_features.
+ """
+ def __init__(
+ self, in_features: int, out_features:int, layer_width: list,
+ combo = LinearCombo
+ ):
+ super().__init__()
+ self.in_features = in_features
+ self.out_features = out_features
+ self.layer_width = list(layer_width)
+ self.model = self._build_model(combo)
+
+ def forward(self, input):
+ return self.model(input)
+
+ def _build_model(self, combo):
+ model = nn.Sequential()
+ idx = -1
+ for idx, (in_ftr, out_ftr) in enumerate(self.layer_sizes[:-1]):
+ model.add_module(str(idx), combo(in_ftr, out_ftr))
+ model.add_module(str(idx+1), nn.Linear(*self.layer_sizes[-1])) # type:ignore
+ return model
+
+ @property
+ def layer_sizes(self):
+ return list(zip([self.in_features] + self.layer_width,
+ self.layer_width + [self.out_features]))
+
+
+class SNMLP(MLP):
+ def __init__(
+ self, in_features: int, out_features: int, layer_width: list,
+ combo=SNLinearCombo):
+ super().__init__(in_features, out_features, layer_width, combo)
+
+ def _build_model(self, combo):
+ model = nn.Sequential()
+ idx = -1
+ for idx, (in_ftr, out_ftr) in enumerate(self.layer_sizes[:-1]):
+ model.add_module(str(idx), combo(in_ftr, out_ftr))
+ model.add_module(str(idx+1), spectral_norm(nn.Linear(*self.layer_sizes[-1]))) # type:ignore
+ return model
\ No newline at end of file
diff --git a/test_functions2/mopta08/mopta08_armhf.bin b/test_functions2/mopta08/mopta08_armhf.bin
new file mode 100644
index 0000000000000000000000000000000000000000..cec6ee6cda97cb65dc25735c9d1332f863d64ea6
--- /dev/null
+++ b/test_functions2/mopta08/mopta08_armhf.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aaffc217b6f52950fed73b22844fcb4cf1a212d30c7b34cbe8e5819b181e6865
+size 98676916
diff --git a/test_functions2/mopta08/mopta08_elf32.bin b/test_functions2/mopta08/mopta08_elf32.bin
new file mode 100644
index 0000000000000000000000000000000000000000..525400fb6913b8b1afda1ccb958068a054ac5c09
--- /dev/null
+++ b/test_functions2/mopta08/mopta08_elf32.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:77b91231c6d4cd22301c30046f082d2ccc3feb7708c3ad8ce0e8526c6d9dd6fd
+size 41566900
diff --git a/test_functions2/mopta08/mopta08_elf64.bin b/test_functions2/mopta08/mopta08_elf64.bin
new file mode 100644
index 0000000000000000000000000000000000000000..7626bd6233061d500aebf92c416b5219455da259
--- /dev/null
+++ b/test_functions2/mopta08/mopta08_elf64.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ad78a256980134c2a84debd4ff15a53534c812f48175577f9155cdd22d6ffb5
+size 58565259
diff --git a/test_functions2/mopta08_armhf.bin b/test_functions2/mopta08_armhf.bin
new file mode 100644
index 0000000000000000000000000000000000000000..cec6ee6cda97cb65dc25735c9d1332f863d64ea6
--- /dev/null
+++ b/test_functions2/mopta08_armhf.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:aaffc217b6f52950fed73b22844fcb4cf1a212d30c7b34cbe8e5819b181e6865
+size 98676916
diff --git a/test_functions2/mopta08_elf32.bin b/test_functions2/mopta08_elf32.bin
new file mode 100644
index 0000000000000000000000000000000000000000..525400fb6913b8b1afda1ccb958068a054ac5c09
--- /dev/null
+++ b/test_functions2/mopta08_elf32.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:77b91231c6d4cd22301c30046f082d2ccc3feb7708c3ad8ce0e8526c6d9dd6fd
+size 41566900
diff --git a/test_functions2/mopta08_elf64.bin b/test_functions2/mopta08_elf64.bin
new file mode 100644
index 0000000000000000000000000000000000000000..7626bd6233061d500aebf92c416b5219455da259
--- /dev/null
+++ b/test_functions2/mopta08_elf64.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ad78a256980134c2a84debd4ff15a53534c812f48175577f9155cdd22d6ffb5
+size 58565259
diff --git a/test_functions2/output.txt b/test_functions2/output.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ea8ebbea515e4d7cc9aa1736bdc07d4cc47c94f3
--- /dev/null
+++ b/test_functions2/output.txt
@@ -0,0 +1,69 @@
+ 275.8269862960147520
+ 0.0581879368148583
+ -0.4224788876469802
+ -0.4100756001609912
+ -0.2831170848853234
+ 0.2699228951278810
+ -1.0550134317403717
+ -0.5776263839417214
+ 0.1202652926466964
+ 0.1817594688956431
+ -0.0716889385055011
+ -0.0715675971871180
+ -0.1822306559694091
+ 0.0448120443506189
+ 0.0732765928799186
+ -0.1032779716447456
+ -0.0355737650221428
+ -1.0821081604737763
+ -0.6296112281522713
+ -0.1560505513228053
+ -0.0051366243568498
+ -0.2565902686030815
+ 0.2644912201226844
+ -0.4074594692255518
+ 0.1558972751068895
+ -0.0311400644773215
+ 0.2578687828663207
+ -0.0316915328429528
+ 0.0447342648274453
+ -0.2888168826473282
+ -0.1529795285005182
+ 0.1262431217964213
+ -0.0414781325759517
+ 0.0640072115282357
+ -0.0998162893110580
+ 0.0788383110871106
+ -0.2363975385026639
+ -0.7827769477146995
+ 0.2932004681073357
+ -0.8919873927830351
+ 0.1106674271120884
+ -0.7421986510828914
+ 0.6904273371646028
+ -0.2034334096624295
+ 0.6948452509218510
+ -0.1817762251458310
+ -0.0187207101916000
+ -0.7090126160682828
+ 0.2506156381565486
+ -0.8210869189700183
+ 0.0735200231135342
+ -0.7506638170879651
+ -0.1202114602670871
+ -0.7837846044709865
+ 0.3807067050555524
+ -0.9666812979341586
+ -0.3451832671453948
+ -0.1955997453502872
+ 0.0025315276186700
+ -0.4472045013730331
+ 0.3939839637782457
+ -0.2090385167779976
+ 0.2687026674969071
+ 0.4078406265702717
+ -0.9305182911825091
+ -0.6447835100277725
+ -0.8610497420775397
+ -0.3408482065781069
+ 0.2441401812564077
diff --git a/test_functions2/untitled.py b/test_functions2/untitled.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391