diff --git a/Ackley10D_CEI_Avg_Obj.pt b/Ackley10D_CEI_Avg_Obj.pt new file mode 100644 index 0000000000000000000000000000000000000000..66e52cba89689b52cd0c3ae123cf83adb45cc433 --- /dev/null +++ b/Ackley10D_CEI_Avg_Obj.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef078fab3310090b39fa175558b54f1a6819ea07cb0b9e19f38b39bd4c27c12b +size 2968 diff --git a/Ackley10D_CEI_Avg_Time.pt b/Ackley10D_CEI_Avg_Time.pt new file mode 100644 index 0000000000000000000000000000000000000000..73dd05b0e0e6d8e9ced0403c6000059b5ff970a6 --- /dev/null +++ b/Ackley10D_CEI_Avg_Time.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e43f57c340f37f7e912b2143872910e14e797a16f1c16c1b3088cf3d550c64a +size 3484 diff --git a/CantileverBeam.png b/CantileverBeam.png new file mode 100644 index 0000000000000000000000000000000000000000..0f67b720d03df6c9081b09d929dacc8382119a0f Binary files /dev/null and b/CantileverBeam.png differ diff --git a/Car.png b/Car.png new file mode 100644 index 0000000000000000000000000000000000000000..2d520db4732e5cee826f1330f68c103ca8b91bf7 Binary files /dev/null and b/Car.png differ diff --git a/Car_CEI_Avg_Obj.pt b/Car_CEI_Avg_Obj.pt new file mode 100644 index 0000000000000000000000000000000000000000..a354b10fae0c0fb41912d08db8d54ba96e3e77b5 --- /dev/null +++ b/Car_CEI_Avg_Obj.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2703f7d2083dfc5a340b082b9b16406467443a82ced26ac7202f7440f68c9854 +size 3008 diff --git a/Car_CEI_Avg_Time.pt b/Car_CEI_Avg_Time.pt new file mode 100644 index 0000000000000000000000000000000000000000..f074ba51abac37cb7cd26a958e52cae443101584 --- /dev/null +++ b/Car_CEI_Avg_Time.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:acaa29100dfafb78d40a7391feae3d042716159955ec46772eb2f0c017830d1a +size 3396 diff --git a/CompressionSpring.png b/CompressionSpring.png new file mode 100644 index 0000000000000000000000000000000000000000..7698c220381953d93306aa5ee39cdf56343bfd6d Binary files /dev/null and b/CompressionSpring.png differ diff --git a/Formulation_default.png b/Formulation_default.png new file mode 100644 index 0000000000000000000000000000000000000000..cdca1112b2d4c35ae547e2c791abbc6207cbf167 Binary files /dev/null and b/Formulation_default.png differ diff --git a/Gradio_important.ipynb b/Gradio_important.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..200cd6cdb97f3f3eb1b7bada3037c2dd6e71dc40 --- /dev/null +++ b/Gradio_important.ipynb @@ -0,0 +1,588 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "0823043e-8451-4dc8-968c-ca066003f4a7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running on local URL: http://127.0.0.1:7958\n", + "\n", + "To create a public link, set `share=True` in `launch()`.\n" + ] + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import gradio as gr\n", + "import torch\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from test_functions.Ackley10D import *\n", + "from test_functions.Ackley2D import *\n", + "from test_functions.Ackley6D import *\n", + "from test_functions.HeatExchanger import *\n", + "from test_functions.CantileverBeam import *\n", + "from test_functions.Car import *\n", + "from test_functions.CompressionSpring import *\n", + "from test_functions.GKXWC1 import *\n", + "from test_functions.GKXWC2 import *\n", + "from test_functions.HeatExchanger import *\n", + "from test_functions.JLH1 import *\n", + "from test_functions.JLH2 import *\n", + "from test_functions.KeaneBump import *\n", + "from test_functions.GKXWC1 import *\n", + "from test_functions.GKXWC2 import *\n", + "from test_functions.PressureVessel import *\n", + "from test_functions.ReinforcedConcreteBeam import *\n", + "from test_functions.SpeedReducer import *\n", + "from test_functions.ThreeTruss import *\n", + "from test_functions.WeldedBeam import *\n", + "# Import other objective functions as needed\n", + "import time\n", + "\n", + "from Rosen_PFN4BO import *\n", + "from PIL import Image\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "def s(input_string):\n", + " return input_string\n", + "\n", + "\n", + "\n", + "\n", + "def optimize(objective_function, iteration_input, progress=gr.Progress()):\n", + "\n", + " print(objective_function)\n", + "\n", + " # Variable setup\n", + " Current_BEST = torch.tensor( -1e10 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -1e10 )\n", + "\n", + " if objective_function==\"CantileverBeam.png\":\n", + " Current_BEST = torch.tensor( -82500 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -82500 )\n", + " elif objective_function==\"CompressionSpring.png\":\n", + " Current_BEST = torch.tensor( -8 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -8 )\n", + " elif objective_function==\"HeatExchanger.png\":\n", + " Current_BEST = torch.tensor( -30000 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -30000 )\n", + " elif objective_function==\"ThreeTruss.png\":\n", + " Current_BEST = torch.tensor( -300 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -300 )\n", + " elif objective_function==\"Reinforcement.png\":\n", + " Current_BEST = torch.tensor( -440 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -440 )\n", + " elif objective_function==\"PressureVessel.png\":\n", + " Current_BEST = torch.tensor( -40000 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -40000 ) \n", + " elif objective_function==\"SpeedReducer.png\":\n", + " Current_BEST = torch.tensor( -3200 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -3200 ) \n", + " elif objective_function==\"WeldedBeam.png\":\n", + " Current_BEST = torch.tensor( -35 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -35 )\n", + " elif objective_function==\"Car.png\":\n", + " Current_BEST = torch.tensor( -35 ) # Some arbitrary very small number\n", + " Prev_BEST = torch.tensor( -35 )\n", + "\n", + " # Initial random samples\n", + " # print(objective_functions)\n", + " trained_X = torch.rand(20, objective_functions[objective_function]['dim'])\n", + "\n", + " # Scale it to the domain of interest using the selected function\n", + " # print(objective_function)\n", + " X_Scaled = objective_functions[objective_function]['scaling'](trained_X)\n", + "\n", + " # Get the constraints and objective\n", + " trained_gx, trained_Y = objective_functions[objective_function]['function'](X_Scaled)\n", + "\n", + " # Convergence list to store best values\n", + " convergence = []\n", + " time_conv = []\n", + "\n", + " START_TIME = time.time()\n", + "\n", + "\n", + "# with gr.Progress(track_tqdm=True) as progress:\n", + "\n", + "\n", + " # Optimization Loop\n", + " for ii in progress.tqdm(range(iteration_input)): # Example with 100 iterations\n", + "\n", + " # (0) Get the updated data for this iteration\n", + " X_scaled = objective_functions[objective_function]['scaling'](trained_X)\n", + " trained_gx, trained_Y = objective_functions[objective_function]['function'](X_scaled)\n", + "\n", + " # (1) Randomly sample Xpen \n", + " X_pen = torch.rand(1000,trained_X.shape[1])\n", + "\n", + " # (2) PFN inference phase with EI\n", + " default_model = 'final_models/model_hebo_morebudget_9_unused_features_3.pt'\n", + " \n", + " ei, p_feas = Rosen_PFN_Parallel(default_model,\n", + " trained_X, \n", + " trained_Y, \n", + " trained_gx,\n", + " X_pen,\n", + " 'power',\n", + " 'ei'\n", + " )\n", + "\n", + " # Calculating CEI\n", + " CEI = ei\n", + " for jj in range(p_feas.shape[1]):\n", + " CEI = CEI*p_feas[:,jj]\n", + "\n", + " # (4) Get the next search value\n", + " rec_idx = torch.argmax(CEI)\n", + " best_candidate = X_pen[rec_idx,:].unsqueeze(0)\n", + "\n", + " # (5) Append the next search point\n", + " trained_X = torch.cat([trained_X, best_candidate])\n", + "\n", + "\n", + " ################################################################################\n", + " # This is just for visualizing the best value. \n", + " # This section can be remove for pure optimization purpose\n", + " Current_X = objective_functions[objective_function]['scaling'](trained_X)\n", + " Current_GX, Current_Y = objective_functions[objective_function]['function'](Current_X)\n", + " if ((Current_GX<=0).all(dim=1)).any():\n", + " Current_BEST = torch.max(Current_Y[(Current_GX<=0).all(dim=1)])\n", + " else:\n", + " Current_BEST = Prev_BEST\n", + " ################################################################################\n", + " \n", + " # (ii) Convergence tracking (assuming the best Y is to be maximized)\n", + " # if Current_BEST != -1e10:\n", + " print(Current_BEST)\n", + " print(convergence)\n", + " convergence.append(Current_BEST.abs())\n", + " time_conv.append(time.time() - START_TIME)\n", + "\n", + " # Timing\n", + " END_TIME = time.time()\n", + " TOTAL_TIME = END_TIME - START_TIME\n", + " \n", + " # Website visualization\n", + " # (i) Radar chart for trained_X\n", + " radar_chart = None\n", + " # radar_chart = create_radar_chart(X_scaled)\n", + " # (ii) Convergence tracking (assuming the best Y is to be maximized)\n", + " convergence_plot = create_convergence_plot(objective_function, iteration_input, \n", + " time_conv, \n", + " convergence, TOTAL_TIME)\n", + "\n", + "\n", + " return convergence_plot\n", + " # return radar_chart, convergence_plot\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "def create_radar_chart(X_scaled):\n", + " fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))\n", + " labels = [f'x{i+1}' for i in range(X_scaled.shape[1])]\n", + " values = X_scaled.mean(dim=0).numpy()\n", + " \n", + " num_vars = len(labels)\n", + " angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()\n", + " values = np.concatenate((values, [values[0]]))\n", + " angles += angles[:1]\n", + "\n", + " ax.fill(angles, values, color='green', alpha=0.25)\n", + " ax.plot(angles, values, color='green', linewidth=2)\n", + " ax.set_yticklabels([])\n", + " ax.set_xticks(angles[:-1])\n", + " # ax.set_xticklabels(labels)\n", + " ax.set_xticklabels([f'{label}\\n({value:.2f})' for label, value in zip(labels, values[:-1])]) # Show values\n", + " ax.set_title(\"Selected Design\", size=15, color='black', y=1.1)\n", + " \n", + " plt.close(fig)\n", + " return fig\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "def create_convergence_plot(objective_function, iteration_input, time_conv, convergence, TOTAL_TIME):\n", + " fig, ax = plt.subplots()\n", + " \n", + " # Realtime optimization data\n", + " ax.plot(time_conv, convergence, '^-', label='PFN-CBO (Realtime)' )\n", + "\n", + " # Stored GP data\n", + " if objective_function==\"CantileverBeam.png\":\n", + " GP_TIME = torch.load('CantileverBeam_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('CantileverBeam_CEI_Avg_Obj.pt')\n", + " \n", + " elif objective_function==\"CompressionSpring.png\":\n", + " GP_TIME = torch.load('CompressionSpring_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('CompressionSpring_CEI_Avg_Obj.pt')\n", + "\n", + " elif objective_function==\"HeatExchanger.png\":\n", + " GP_TIME = torch.load('HeatExchanger_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('HeatExchanger_CEI_Avg_Obj.pt')\n", + " \n", + " elif objective_function==\"ThreeTruss.png\":\n", + " GP_TIME = torch.load('ThreeTruss_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('ThreeTruss_CEI_Avg_Obj.pt')\n", + " \n", + " elif objective_function==\"Reinforcement.png\":\n", + " GP_TIME = torch.load('ReinforcedConcreteBeam_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('ReinforcedConcreteBeam_CEI_Avg_Obj.pt')\n", + " \n", + " elif objective_function==\"PressureVessel.png\":\n", + " GP_TIME = torch.load('PressureVessel_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('PressureVessel_CEI_Avg_Obj.pt')\n", + " \n", + " elif objective_function==\"SpeedReducer.png\":\n", + " GP_TIME = torch.load('SpeedReducer_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('SpeedReducer_CEI_Avg_Obj.pt')\n", + " \n", + " elif objective_function==\"WeldedBeam.png\":\n", + " GP_TIME = torch.load('WeldedBeam_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('WeldedBeam_CEI_Avg_Obj.pt') \n", + "\n", + " elif objective_function==\"Car.png\":\n", + " GP_TIME = torch.load('Car_CEI_Avg_Time.pt')\n", + " GP_OBJ = torch.load('Car_CEI_Avg_Obj.pt') \n", + " \n", + " # Plot GP data \n", + " ax.plot(GP_TIME[:iteration_input], GP_OBJ[:iteration_input], '^-', label='GP-CBO (Data)' )\n", + "\n", + " \n", + " ax.set_xlabel('Time (seconds)')\n", + " ax.set_ylabel('Objective Value')\n", + " ax.set_title('Convergence Plot for {t} iterations'.format(t=iteration_input))\n", + " # ax.legend()\n", + "\n", + " if objective_function==\"CantileverBeam.png\":\n", + " ax.axhline(y=50000, color='red', linestyle='--', label='Optimal Value')\n", + "\n", + " elif objective_function==\"CompressionSpring.png\":\n", + " ax.axhline(y=0, color='red', linestyle='--', label='Optimal Value')\n", + "\n", + " elif objective_function==\"HeatExchanger.png\":\n", + " ax.axhline(y=4700, color='red', linestyle='--', label='Optimal Value')\n", + " \n", + " elif objective_function==\"ThreeTruss.png\":\n", + " ax.axhline(y=262, color='red', linestyle='--', label='Optimal Value')\n", + " \n", + " elif objective_function==\"Reinforcement.png\":\n", + " ax.axhline(y=355, color='red', linestyle='--', label='Optimal Value')\n", + " \n", + " elif objective_function==\"PressureVessel.png\":\n", + " ax.axhline(y=5000, color='red', linestyle='--', label='Optimal Value')\n", + " \n", + " elif objective_function==\"SpeedReducer.png\":\n", + " ax.axhline(y=2650, color='red', linestyle='--', label='Optimal Value')\n", + " \n", + " elif objective_function==\"WeldedBeam.png\":\n", + " ax.axhline(y=6, color='red', linestyle='--', label='Optimal Value') \n", + "\n", + " elif objective_function==\"Car.png\":\n", + " ax.axhline(y=25, color='red', linestyle='--', label='Optimal Value') \n", + "\n", + " \n", + " ax.legend(loc='best')\n", + " # ax.legend(loc='lower left')\n", + " \n", + "\n", + " # Add text to the top right corner of the plot\n", + " if len(convergence) == 0:\n", + " ax.text(0.5, 0.5, 'No Feasible Design Found', transform=ax.transAxes, fontsize=12,\n", + " verticalalignment='top', horizontalalignment='right')\n", + " \n", + " \n", + " plt.close(fig)\n", + " return fig\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "# Define available objective functions\n", + "objective_functions = {\n", + " # \"ThreeTruss.png\": {\"image\": \"ThreeTruss.png\", \n", + " # \"function\": ThreeTruss, \n", + " # \"scaling\": ThreeTruss_Scaling, \n", + " # \"dim\": 2},\n", + " \"CompressionSpring.png\": {\"image\": \"CompressionSpring.png\", \n", + " \"function\": CompressionSpring, \n", + " \"scaling\": CompressionSpring_Scaling, \n", + " \"dim\": 3},\n", + " \"Reinforcement.png\": {\"image\": \"Reinforcement.png\", \"function\": ReinforcedConcreteBeam, \"scaling\": ReinforcedConcreteBeam_Scaling, \"dim\": 3},\n", + " \"PressureVessel.png\": {\"image\": \"PressureVessel.png\", \"function\": PressureVessel, \"scaling\": PressureVessel_Scaling, \"dim\": 4},\n", + " \"SpeedReducer.png\": {\"image\": \"SpeedReducer.png\", \"function\": SpeedReducer, \"scaling\": SpeedReducer_Scaling, \"dim\": 7},\n", + " \"WeldedBeam.png\": {\"image\": \"WeldedBeam.png\", \"function\": WeldedBeam, \"scaling\": WeldedBeam_Scaling, \"dim\": 4},\n", + " \"HeatExchanger.png\": {\"image\": \"HeatExchanger.png\", \"function\": HeatExchanger, \"scaling\": HeatExchanger_Scaling, \"dim\": 8},\n", + " \"CantileverBeam.png\": {\"image\": \"CantileverBeam.png\", \"function\": CantileverBeam, \"scaling\": CantileverBeam_Scaling, \"dim\": 10},\n", + " \"Car.png\": {\"image\": \"Car.png\", \"function\": Car, \"scaling\": Car_Scaling, \"dim\": 11},\n", + "}\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "# Extract just the image paths for the gallery\n", + "image_paths = [key for key in objective_functions]\n", + "\n", + "\n", + "def submit_action(objective_function_choices, iteration_input):\n", + " # print(iteration_input)\n", + " # print(len(objective_function_choices))\n", + " # print(objective_functions[objective_function_choices]['function'])\n", + " if len(objective_function_choices)>0:\n", + " selected_function = objective_functions[objective_function_choices]['function']\n", + " return optimize(objective_function_choices, iteration_input)\n", + " return None\n", + "\n", + "# Function to clear the output\n", + "def clear_output():\n", + " # print(gallery.selected_index)\n", + " \n", + " return gr.update(value=[], selected=None), None, 15, gr.Markdown(\"\"), 'Test_formulation_default.png'\n", + "\n", + "def reset_gallery():\n", + " return gr.update(value=image_paths)\n", + "\n", + "\n", + "with gr.Blocks() as demo:\n", + " # Centered Title and Description using gr.HTML\n", + " gr.HTML(\n", + " \"\"\"\n", + "
\n", + "

Pre-trained Transformer for Constrained Bayesian Optimization

\n", + "

Paper: \n", + " Fast and Accurate Bayesian Optimization with Pre-trained Transformers for Constrained Engineering Problems \n", + "

\n", + "\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", + " )\n", + "\n", + " \n", + " with gr.Row():\n", + " \n", + " \n", + " with gr.Column(variant='compact'):\n", + " # gr.Markdown(\"# Inputs: \")\n", + " \n", + " with gr.Row():\n", + " gr.Markdown(\"## Select a problem (objective): \")\n", + " img_key = gr.Markdown(value=\"\", visible=False)\n", + " \n", + " gallery = gr.Gallery(value=image_paths, label=\"Objective Functions\", \n", + " # height = 450, \n", + " object_fit='contain',\n", + " columns=3, rows=3, elem_id=\"gallery\")\n", + " \n", + " gr.Markdown(\"## Enter iteration Number: \")\n", + " iteration_input = gr.Slider(label=\"Iterations:\", minimum=15, maximum=50, step=1, value=15)\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", + " with gr.Column():\n", + " # gr.Markdown(\"# Outputs: \")\n", + " gr.Markdown(\"## Problem Formulation: \")\n", + " formulation = gr.Image(value='Formulation_default.png', height=150)\n", + " gr.Markdown(\"## Results: \")\n", + " gr.Markdown(\"The graph will plot the best observed data v.s. the time for the algorithm to run up until the iteration. The PFN-CBO shows the result of the realtime optimization running in the backend while the GP-CBO shows the stored data from our previous experiments since running GP-CBO will take longer time.\")\n", + " convergence_plot = gr.Plot(label=\"Convergence Plot\")\n", + "\n", + "\n", + "\n", + " def handle_select(evt: gr.SelectData):\n", + " selected_image = evt.value\n", + " key = evt.value['image']['orig_name']\n", + " formulation = 'Test_formulation.png'\n", + " print('here')\n", + " print(key)\n", + "\n", + " return key, formulation\n", + " \n", + " gallery.select(fn=handle_select, inputs=None, outputs=[img_key, formulation])\n", + "\n", + "\n", + " \n", + " submit_button.click(\n", + " submit_action,\n", + " inputs=[img_key, iteration_input],\n", + " # outputs= [radar_plot, convergence_plot],\n", + " outputs= convergence_plot,\n", + " \n", + " # progress=True # Enable progress tracking\n", + " \n", + " )\n", + "\n", + " clear_button.click(\n", + " clear_output,\n", + " inputs=None,\n", + " outputs=[gallery, convergence_plot, iteration_input, img_key, formulation]\n", + " ).then(\n", + " # Step 2: Reset the gallery to the original list\n", + " reset_gallery,\n", + " inputs=None,\n", + " outputs=gallery\n", + " )\n", + "\n", + " \n", + "\n", + "demo.launch()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "776c7ab2-96a1-4e22-9b4b-daf69960e3c4", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d2c7c58-43b1-4e5b-9135-17683dac1788", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d33a24c-818c-4023-bbbd-495f992a9d1a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "764d0258-ec88-41d5-b5b5-e0bcb39ff313", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2c35245-543c-4b82-8d12-04f3dda1468b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3663adc-3e95-418b-bf50-0a372615cdd6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30886262-bd87-4760-a585-7872e071663f", + "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/Gradio_test.ipynb b/Gradio_test.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..74e386929798d14fd4ba31a2105e2b9336de3138 --- /dev/null +++ b/Gradio_test.ipynb @@ -0,0 +1,569 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "4453c5ad-ec87-42e0-a6d5-e3fd3593aec2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running on local URL: http://127.0.0.1:7891\n", + "Running on public URL: https://f714b6f956fb581264.gradio.live\n", + "\n", + "This share link expires in 72 hours. For free permanent hosting and GPU upgrades, run `gradio deploy` from Terminal to deploy to Spaces (https://huggingface.co/spaces)\n" + ] + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import gradio as gr\n", + "import torch\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from test_functions.Ackley10D import *\n", + "from test_functions.Ackley2D import *\n", + "from test_functions.Ackley6D import *\n", + "from test_functions.HeatExchanger import *\n", + "from test_functions.CantileverBeam import *\n", + "from test_functions.Car import *\n", + "from test_functions.CompressionSpring import *\n", + "from test_functions.GKXWC1 import *\n", + "from test_functions.GKXWC2 import *\n", + "from test_functions.HeatExchanger import *\n", + "from test_functions.JLH1 import *\n", + "from test_functions.JLH2 import *\n", + "from test_functions.KeaneBump import *\n", + "from test_functions.GKXWC1 import *\n", + "from test_functions.GKXWC2 import *\n", + "from test_functions.PressureVessel import *\n", + "from test_functions.ReinforcedConcreteBeam import *\n", + "from test_functions.SpeedReducer import *\n", + "from test_functions.ThreeTruss import *\n", + "from test_functions.WeldedBeam import *\n", + "# Import other objective functions as needed\n", + "import time\n", + "\n", + "from Rosen_PFN4BO import *\n", + "\n", + "def optimize(objective_function, iteration_input):\n", + "\n", + " # Variable setup\n", + " Current_BEST = -1e10 # Some arbitrary very small number\n", + " Prev_BEST = -1e10\n", + "\n", + " # Initial random samples\n", + " # print(objective_functions)\n", + " trained_X = torch.rand(20, objective_functions[objective_function]['dim'])\n", + "\n", + " # Scale it to the domain of interest using the selected function\n", + " # print(objective_function)\n", + " X_Scaled = objective_functions[objective_function]['scaling'](trained_X)\n", + "\n", + " # Get the constraints and objective\n", + " trained_gx, trained_Y = objective_functions[objective_function]['function'](X_Scaled)\n", + "\n", + " # Convergence list to store best values\n", + " convergence = []\n", + "\n", + " START_TIME = time.time()\n", + "\n", + " # Optimization Loop\n", + " for ii in range(iteration_input): # Example with 100 iterations\n", + "\n", + " # (0) Get the updated data for this iteration\n", + " X_scaled = objective_functions[objective_function]['scaling'](trained_X)\n", + " trained_gx, trained_Y = objective_functions[objective_function]['function'](X_scaled)\n", + "\n", + " # (1) Randomly sample Xpen \n", + " X_pen = torch.rand(1000,trained_X.shape[1])\n", + "\n", + " # (2) PFN inference phase with EI\n", + " default_model = 'final_models/Cyril_500features_800epoch_cpu.pt'\n", + " \n", + " ei, p_feas = Rosen_PFN_Parallel(default_model,\n", + " trained_X, \n", + " trained_Y, \n", + " trained_gx,\n", + " X_pen,\n", + " 'power',\n", + " 'ei'\n", + " )\n", + "\n", + " # Calculating CEI\n", + " CEI = ei\n", + " for jj in range(p_feas.shape[1]):\n", + " CEI = CEI*p_feas[:,jj]\n", + "\n", + " # (4) Get the next search value\n", + " rec_idx = torch.argmax(CEI)\n", + " best_candidate = X_pen[rec_idx,:].unsqueeze(0)\n", + "\n", + " # (5) Append the next search point\n", + " trained_X = torch.cat([trained_X, best_candidate])\n", + "\n", + "\n", + " ################################################################################\n", + " # This is just for visualizing the best value. \n", + " # This section can be remove for pure optimization purpose\n", + " Current_X = objective_functions[objective_function]['scaling'](trained_X)\n", + " Current_GX, Current_Y = objective_functions[objective_function]['function'](Current_X)\n", + " if ((Current_GX<=0).all(dim=1)).any():\n", + " Current_BEST = torch.max(Current_Y[(Current_GX<=0).all(dim=1)])\n", + " else:\n", + " Current_BEST = Prev_BEST\n", + " ################################################################################\n", + " \n", + " # (ii) Convergence tracking (assuming the best Y is to be maximized)\n", + " if Current_BEST != -1e10:\n", + " convergence.append(Current_BEST.abs())\n", + "\n", + " # Timing\n", + " END_TIME = time.time()\n", + " TOTAL_TIME = END_TIME - START_TIME\n", + " \n", + " # Website visualization\n", + " # (i) Radar chart for trained_X\n", + " radar_chart = create_radar_chart(X_scaled)\n", + " # (ii) Convergence tracking (assuming the best Y is to be maximized)\n", + " convergence_plot = create_convergence_plot(convergence, TOTAL_TIME)\n", + " \n", + " return radar_chart, convergence_plot\n", + "\n", + "def create_radar_chart(X_scaled):\n", + " fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))\n", + " labels = [f'x{i+1}' for i in range(X_scaled.shape[1])]\n", + " values = X_scaled.mean(dim=0).numpy()\n", + " \n", + " num_vars = len(labels)\n", + " angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()\n", + " values = np.concatenate((values, [values[0]]))\n", + " angles += angles[:1]\n", + "\n", + " ax.fill(angles, values, color='green', alpha=0.25)\n", + " ax.plot(angles, values, color='green', linewidth=2)\n", + " ax.set_yticklabels([])\n", + " ax.set_xticks(angles[:-1])\n", + " # ax.set_xticklabels(labels)\n", + " ax.set_xticklabels([f'{label}\\n({value:.2f})' for label, value in zip(labels, values[:-1])]) # Show values\n", + " ax.set_title(\"Selected Design\", size=15, color='black', y=1.1)\n", + " \n", + " plt.close(fig)\n", + " return fig\n", + "\n", + "def create_convergence_plot(convergence, TOTAL_TIME):\n", + " fig, ax = plt.subplots()\n", + " # print(len(convergence))\n", + " ax.plot(convergence, label='Best Objective Value')\n", + " ax.set_xlabel('Iteration')\n", + " ax.set_ylabel('Objective Value')\n", + " ax.set_title('Convergence Plot (Opt Runtime: {t} sec)'.format(t=round(TOTAL_TIME, 2)))\n", + " ax.legend()\n", + "\n", + " # Add text to the top right corner of the plot\n", + " if len(convergence) == 0:\n", + " ax.text(0.5, 0.5, 'No Feasible Design Found', transform=ax.transAxes, fontsize=12,\n", + " verticalalignment='top', horizontalalignment='right')\n", + " \n", + " plt.close(fig)\n", + " return fig\n", + "\n", + "# Define available objective functions\n", + "objective_functions = {\n", + " \"Ackley2D\": {\"function\": Ackley2D, \"scaling\": Ackley2D_Scaling, \"dim\": 2},\n", + " \"Ackley6D\": {\"function\": Ackley6D, \"scaling\": Ackley6D_Scaling, \"dim\": 6},\n", + " \"Ackley10D\": {\"function\": Ackley10D, \"scaling\": Ackley10D_Scaling, \"dim\": 10},\n", + " \"GKXWC1\": {\"function\": GKXWC1, \"scaling\": GKXWC1_Scaling, \"dim\": 2},\n", + " \"GKXWC2\": {\"function\": GKXWC2, \"scaling\": GKXWC2_Scaling, \"dim\": 2},\n", + " \"JLH1\": {\"function\": JLH1, \"scaling\": JLH1_Scaling, \"dim\": 2},\n", + " \"JLH2\": {\"function\": JLH2, \"scaling\": JLH2_Scaling, \"dim\": 2},\n", + " \"Keane Bump\": {\"function\": KeaneBump, \"scaling\": KeaneBump_Scaling, \"dim\": 18},\n", + " \"Three Truss\": {\"function\": ThreeTruss, \"scaling\": ThreeTruss_Scaling, \"dim\": 2},\n", + " \"Compression Spring\": {\"function\": CompressionSpring, \"scaling\": CompressionSpring_Scaling, \"dim\": 3},\n", + " \"Reinforced Concrete Beam\": {\"function\": ReinforcedConcreteBeam, \"scaling\": ReinforcedConcreteBeam_Scaling, \"dim\": 3},\n", + " \"Pressure Vessel\": {\"function\": PressureVessel, \"scaling\": PressureVessel_Scaling, \"dim\": 4},\n", + " \"Speed Reducer\": {\"function\": SpeedReducer, \"scaling\": SpeedReducer_Scaling, \"dim\": 4},\n", + " \"Welded Beam\": {\"function\": WeldedBeam, \"scaling\": WeldedBeam_Scaling, \"dim\": 4},\n", + " \"Heat Exchanger\": {\"function\": HeatExchanger, \"scaling\": HeatExchanger_Scaling, \"dim\": 8},\n", + " \"Cantilever Beam\": {\"function\": CantileverBeam, \"scaling\": CantileverBeam_Scaling, \"dim\": 10},\n", + " \"Car\": {\"function\": Car, \"scaling\": Car_Scaling, \"dim\": 11},\n", + " \n", + " # Add more functions here\n", + "}\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "with gr.Blocks(theme=gr.themes.Default()) as demo:\n", + " # Centered Title and Description using gr.HTML\n", + " gr.HTML(\n", + " \"\"\"\n", + "
\n", + "

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", + " \"Example\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