Breakwater blocks#

Click –> Live Code to activate live coding on this page!

Problem#

It is desired to design the cheapest breakwater block (box-shaped). The price of the brick will depend only on the amount of used material. It is required that each face has a minimum surface of \(0.8\) \(\text{m}^2\). Also, for stability reasons, the block weight has to be larger than \(3000\) \(\text{kg}\). Let’s assume concrete density of \(2500\) \(\text{kg}/{m}^2\).

../_images/blocks.png

Fig. 3.1 Breakwater blocks#

Model#

We need to define our model in the form of a nonlinear constrained optimization model (3.1) to apply scipy.optimize.minimize.

We’ll define the model as follows:

  • Design variables: width, height and depth of a block

  • Objective function: minimum volume of the block

  • Inequality constraint functions: minimum surface area of each face of \(0.8\) \(\text{m}^2\) and maximum weight of \(3000\) \(\text{kg}\)

  • Equality constraint functions: none

  • Bounds: positive dimensions

Design variables#

Let’s start with our design variables. In this case a logical choice could be the width, height and depth of our block

(3.2)#\[\begin{split}x=\left[ \begin{matrix} {{x}_{width}} \\ {{x}_{depth}} \\ {{x}_{height}} \\ \end{matrix} \right]=\left[ \begin{matrix} {{x}_{1}} \\ {{x}_{2}} \\ {{x}_{3}} \\ \end{matrix} \right]\end{split}\]

Objective function#

Now we can define the objective function as the product of the dimension to represent \(\mathop {\min }\limits_x f\left(x\right) \) in (3.1):

(3.3)#\[{\min }\limits_x f\left(x\right) = x_1 \cdot x_2 \cdot x_3\]

Inequality constraints#

Let’s continue with the inequality constraints, which should deal with the required positive dimensions, minimum surface area of each face of \(0.8\) \(\text{m}^2\) and maximum weight of \(3000\) \(\text{kg}\). These can be defined in the form \({{g}}\left(x_{ij}\right) \le 0\) as:

(3.4)#\[\begin{split}g_1\left(x\right) = -x_{1} \cdot x_2 + 0.8 \\ g_2\left(x\right) = -x_{2} \cdot x_3 + 0.8 \\ g_3\left(x\right) = -x_{1} \cdot x_3 + 0.8 \\ g_4\left(x\right) = -x_{1} \cdot x_2 \cdot x_3 \cdot 2500 + 3000 \\\end{split}\]
Test yourself

Bounds#

The dimensions of the block cannot be negative. Therefore, the bounds can be defined as:

(3.5)#\[0<{{x}_{i}}\text{ } i=1,2,3\]

Find best solution manually#

Test yourself

Try and adjust the values for \(x_1\), \(x_2\) and \(x_3\). Can you find the optimal solution?

Method#

Now let’s solve this problem using an optimization method.

Import libraries#

import scipy as sp
import numpy as np
import scipy as sp 
import numpy as np

Define variables#

As before, we don’t need to specify our variable \(x\) itself as defined in (3.2). However, this optimization method requires an initial guess. An arbitrary value is chosen here:

x0 = np.array([5,0,1])

Define objective function#

The objective function was defined in (3.3), which gives:

def func(x):
    vol = x[0]*x[1]*x[2]
    return vol

Define constrain functions#

The constraint functions were defined in (3.4). We had no equality constraints. Unlike before with the method to solve linear constrained problem, we need an object which defines the upper and lower bounds. As this problem has only an upper bound of \(0\), the lower bound is set to \(\infty\) which is np.inf in python. Note that a single constraint object can include multiple constraints.

def nonlinconfun(x):
    c1 = 0.8 - x[0]*x[1]
    c2 = 0.8 - x[0]*x[2]
    c3 = 0.8 - x[1]*x[2]
    c4 = 3000 - 2500 * x[0] * x[1] * x[2]
    return np.array([c1,c2,c3,c4])

cons = sp.optimize.NonlinearConstraint(nonlinconfun, np.array([-np.inf,-np.inf,-np.inf,-np.inf]), np.array([0,0,0,0]))

Define bounds#

The bounds were defined in (3.5) and result in:

bounds = [[0, None],
          [0, None],
          [0, None]]

Solve the problem#

Now let’s solve the problem. The cons object can be added directly, in the case of equality constraints as well you can define a list of constrainer objects as an input.

result = sp.optimize.minimize(fun = func,x0 = x0,bounds = bounds,constraints=cons)
print(result)
 message: Optimization terminated successfully
 success: True
  status: 0
     fun: 1.2000000000024624
       x: [ 1.353e+00  1.488e+00  5.962e-01]
     nit: 10
     jac: [ 8.871e-01  8.065e-01  2.013e+00]
    nfev: 41
    njev: 10

Exercise#

Test yourself

Click –> Live Code to activate live coding on this page.

Questions, discussions and comments#