The world’s leading publication for data science, AI, and ML professionals.

Unit 5 Application) Optimizing Constrained Non-Linear Pressure Vessel Design Problem

We will apply Evolutionary Programming to find the Best Solution to the Pressure Vessel Design Problem

Image by Author

Evolutionary Computation Course

Hello and Welcome back to this full course on Evolutionary Computation! In this post we will wrap up Unit 5 of the course by apply what we’ve learned about Evolutionary Programming to optimize the design of a constrained non-linear Pressure Vessel! Because this post will only deal with the application of the concepts, please check out the previous post where I explained Evolutionary Programming in detail. You can find it here:

Unit 5) Evolutionary Programming

In that previous post we discussed the Classical Evolutionary Programming algorithm, to which we will implement here from scratch to solve our problem!

Table of Contents

  • Problem Statement
  • Help from Literature Paper
  • Designing our Algorithm
  • Evolutionary Programming Algorithm
  • Results
  • Code
  • Conclusion
  • References

Problem Statement

Our problem is designing a pressure vessel, whose purpose is to hold liquids or gases. The goal is to minimize the cost of the material by optimizing the design variables of the vessel. However, we cannot achieve absolute minimization as we need to meet some constraints to uphold the safety, efficacy, and physics of the vessel. There are four variables of interest:

  • Inner Radius – R
  • Length of Cylindrical Section – L
  • Thickness of the Body – T_s
  • Thickness of the Cap – T_h

There are four constraints on our problem, one of them being non-linear. Here is the function we want to minimize along with the constraints:

The domain set of the problem is both continuous and discrete. The Radius (R) and Length (L) are continuous values ranging from 10 to 200 inches, while the thickness of the head (T_h) and body (T_s) are discrete from 0.0625 to 6.1875 inches with step size of 0.0625 inches.

As we can see, we have the ultimate constrained problem, a domain of variables that is a mix of both continuous and discrete, and four constraints, one being non linear (G_3). This is will a perfect problem to test the efficiency of our Classic Evolutionary Programming Algorithm. If you want a review on optimization theory and constrained problems, check out my previous post here:

Unit 1) Optimization Theory

Help from Literature Paper

Constrained Optimization problems can be extremely difficult to handle as we need a way for our algorithm to focus on only the feasible domain space and steer away from infeasible solutions. As a review from Unit 1, Optimization Theory, there are two main ways to handle constraints: adjust our algorithm to only produce feasible solutions (which can be difficult with many constraints) or introduce a penalty term that penalizes the fitness value of infeasible solutions.

In a literature paper called "A Constraint Handling Technique for Genetic Algorithms using a Violation Factor" by Adam Chehouri, et al, in 2016, the authors actually dove into this same exact problem on how to handle infeasible solutions for solving constrained optimization problems using genetic algorithms [1]. They proposed two different algorithms, where the main idea in both was to split the good, feasible solutions, from the bad, infeasible solutions. After this split, they sorted the good solutions by fitness value and bad solutions by how ‘bad’ they were, which they determined by how many constraints were broken. For selection for reproduction, they performed a tournament style selection between two individuals from the pooled bad and good solutions. If two good solutions were paired to fight, the solution with the best fitness was chosen to survive. If two bad solutions were paired to fight, the solution with the least amount of constraints broken won. If a bad and good solution was paired to fight, the good solution was always chosen to survive.

Now this is a brief overview of their algorithm as they included many different intricate components and tested them on many other optimization problems, so if you’re wanting to know more about their violation factor and algorithm please check out their paper. For our purposes, we are going to use a modification of their algorithm for our problem.

Designing our Algorithm

For our problem, we are going to be using the Classical Evolutionary Programming Algorithm discussed in the previous post. This algorithm works by using Gaussian Mutation, log-normal self-adaptation of the strategy parameter, the standard deviation in our instance, and elitism to choose the best half from the pooled collection of parents and offspring while using relative fitness through tournaments.

In inspiration from the literature paper discussed earlier, we will sort the good solutions by fitness and bad solutions NOT by how many constraints they have broken but by the sum of the z-scores of their differences. For example, using the algorithm given in the paper above, if a solution has broken all four constraints only by 1% then it would be rejected in favor of a solution has broken only one constraint by 20%. In my eyes, the first solution should be accepted over the later even though it has broken more constraints, as the degree of broken constraints is much greater than the latter. One might implement this by simply summing up the differences in the cases of a broken constraint and compare using that sum. However, because the domain is different for each variable, a 1% difference in the domain could result in a different sum. For example, a 1% difference for X1 and X2 in our example is 0.06125, while it is 9 for X3 and 19 for X4. Therefore, if we were to sum the differences, an individual with only a 1% difference in X4 would be equivalent to an individual with a 311% difference for X1. To get around this, we need to scale our differences by using z-scores. Z-scores are a measurement of indicating how far away a point is away from its central mean, where values greater than 3 in value mean that it is an outlier as it is greater than 3 standard deviations from the mean. We do not need to worry about values with -3 value in z-score as that indicates that the individual’s difference is extremely small compared to rest. We want to penalize individuals with large differences, therefore that this is why we do not take the absolute value. After sorting the good and bad, we combine the two in order and select the best half for survival. We will also utilize relative fitness by use of random tournaments.

For the overall design of our algorithm we will follow the pseudocode above. First, we initialize our population, then we mutate all the individuals of the population to create the offspring. Next, we pool the parents with the offspring and calculate the relative fitness using tournament style selection. Then, we sort and pool together the good and bad solutions, choosing the best half for survival.

Evolutionary Programming Algorithm

To begin, we first need to specify our fitness function, which would be the optimization problem itself, along with the constraints. In the ‘constraints’ function we will calculate how many times each individual has broken a constraint; and if broken, by how much. Because X1 and X2 are discrete, we simply round those variable values for each individual to the nearest step size of 0.0625:

Next, we are going to specify our initial population. Remember, each individual is not only going to contain their variable values but the strategy parameters for each variable as well. Because we are using Gaussian Mutation, our strategy parameter will be the standard deviation parameter. Initializing our generation variables is easy, just sample uniformly from the domain. However, how can we initialize our strategy parameters? Well, this is up to the designer; as a smaller standard deviation would result in exploitation and a larger standard deviation would result in exploration. For this application, I tried to make the standard deviation cover around between 1 and 20% of the total domain size.

Because Evolutionary Programming is interested in evolving the behavior of individuals, mutation is the only mechanism used to create offspring, no crossover. We create the offspring from updating the parent variable values and strategy parameters using log-normal self-adaptation, while leaving the original parent values alone.

Next, we need to calculate the relative fitness. We do this by looping over each individual and counting up how many times its raw fitness value is better than those in the tournament:

Now, it is time to tackle our main algorithm. I’m going to break it down into a few simple steps. First, because this is a constrained environment, we need to make sure each one of our individuals adheres to the bounds of the domain. If an individual has variable values greater or smaller than the bounds then we need to reduce the strategy parameter by 10% to decrease the mutation bound for that variable:

Now it is time to compute the relative fitness. We combine the parents with the offspring and calculate the relative fitness through tournament selection ONLY for the good solutions, solutions with zero broken constraints:

Now we need to sort the bad solutions by how ‘bad’ they are, which in our implementation will be the sum of the z scores of the differences in broken constraints:

Lastly, we combine our sorted good and sorted bad solutions together and then use elitism to take the best half from the pooled population:

Results

Now it is time to run our algorithm. Because this is such a well known tested problem in literature, we need a basis to compare our algorithm against. In the literature paper, "Solving Structural Engineering Design Optimization Problems Using an Artificial Bee Colony Algorithm" by Harish Garg [2], he details that his Artificial Bee Colony had the following results after 50 independent runs and an average of 80,000 function evaluations per run, where function evaluations is the number of times the fitness function was calculated:

Now that we know the results from a standard algorithm, it is time for us to run our algorithm. To keep things simple, we are going to run our algorithm for 100,000 function evaluations per run, which results in an initial population of 1000 and maximum iterations of 100. Here are our results after 100 independent runs:

We can see that our algorithm ended with a best fitness of 5805.339. For comparison, our algorithm did find a best solution almost equivalent to the Artificial Bee Colony Algorithm, except our algorithm had a higher median, higher mean, higher worst value, and higher standard deviation. It appears that our algorithm has the ability to find a near optimal solution but is unreliable in reproducing results. Here is the final best individual:

To see the range of fitness values over the 100 runs, here below is a boxplot of the best fitness value per run:

For graphics, below we have the mean and best fitness of the run that yielded the global best solution from all runs:

Because we are evolving the behavior of individuals through self-adaptive strategy parameters for mutation, we can see the evolution of the strategy parameters themselves. Here below we have the mean of the standard deviation used for mutating the fourth variable. We can see that the standard deviation increased from a mean around 25 up to almost 50 and slowly decreased for convergence. Note the second peak, showing the power of self-adaptive strategy parameters as it adjusts by increasing when decreasing during that period yielded poor results.

Code Implementation

As will all my implementations, you can find the full code on my GitHub page below:

OUStudent/EvolutionaryComputationCourse

Conclusion

In conclusion, we applied our Classical Evolutionary Programming algorithm to find an optimal solution for a real-world engineering, non-linear, constrained optimization problem. After comparing our algorithm to an Artificial Bee Colony Algorithm found in literature [2], our algorithm produced reputable results for finding a near optimal solution after many independent runs; however, the best solution from each run varied greatly in terms of fitness within the independent runs, indicating that our algorithm is unreliable in creating results in only a handful of runs and needs to be ran for many iterations to yield a near optimal solution.

This wraps up Unit 5) Evolutionary Programming, stay tuned for the next post where we will start and finish Unit 6) Evolutionary Strategies, a cousin of Evolutionary Programming with the incorporation of a crossover mechanism!

References

[1] Chehouri, Adam & Younes, Rafic & Perron, Jean & Ilinca, Adrian. (2016). A constraint-handling technique for genetic algorithms using a violation factor. 12. 350–362. 10.3844/jcssp.2016.350–362.

[2] Solving structural engineering design optimization problems using an artificial bee colony algorithm, Journal of Industrial & Management Optimization,10,3,777,794,2013–11–1,Harish Garg,1547–5816_2014_3_777,Artificial bee colony, structural design optimization, nonlinear constraint., constraints handling,


Related Articles