Work log: A journal-style record of the work on the final project throughout the semester

04-04-2011 - A proposal for my term project for the class, which will have something to do with structural optimization

04-25-2011 - I now have an implementation of the Nelder-Mead algorithm up and running in C#. The code is in this folder (easiest to just open the .sln file in the IDE, but you can also compile the C# class files, which are in here), and is most easily run using Microsoft's Visual Studio IDE. Most of the work I have done this semester is in Python, so I want to return to my old familiar C# to see if I'm missing anything. I'm much more comfortable with the object oriented stuff in C#, which I don't really know how to do. That makes its appealing for the final project, where I will be piecing together different modular pieces.

That said, going back to C# has given me a real appreciation of how easy Python makes writing algorithms. You really do need a lot of code to do numerical stuff in C# or Java. The takeaway is that I need to learn how to make use of object oriented features in Python, so that I can progress beyond self-contained scripts towards modular programs. It will be well worth the effort.

I have modified the Nelder Mead algorithm to allow for upper and lower bounds to be placed on variables. I have tried it out on a very simple test function (the sum of the square of the variables, obviously minimized by setting all variables to zero) and found that convergence gets pretty slow around n = 40

04-26-2011 - Added constraints to the Nelder Mead algorithm with an adaptive linear penalty function. Every time the algorithm generates a point that violates a constraint, the multiplier for that constraint gets increased, making violations of that constraint by all future points more costly. It seems to work pretty well, although I haven't tested it on anything too tough yet. Things get noticeably slower with all that constraint checking going on.

05-09-2011 - After last week, I decided to rewrite in Python. Writing the Optimization algorithms for last week's homework really showed me how much easier it is to write scientific code in Python than in C#. The project goals for me now include learning to write a fully object-oriented program in Python, making use of all the usual OO features. All my Python code will be placed here

I extended the Finite Element code from week 6 to model two-dimensional frame structures. Each node has three degrees of freedom - two displacements and one slope. I connected the Nelder Mead algorithm to the structure and attempted to search for the minimum internal strain energy structure by varying nodal coordinates in an example. I am returning negative strain energies, which is a bug to be fixed. I have started work on connecting the GA to the structure, and intend to use the Nelder Mead algorithm as a move generator in place of random mutation. The Nelder Mead algorithm needs to be modified to include constraints (penalty term) and bounds like the C# version I wrote

I need to give some thought to what variables the optimization algorithm can modify

05-11-2011 - On Neil's advice, I have begun experimenting with a very simple structure (two connected beams with a single movable node). I bounded the variables in the python implementation of the Nelder Mead algorithm. Everything is now is classes, and I write a main method that instantiates a structure object and an optimization object. The structure object is passed as an argument to the optimization object, which modifies the structure's geometry in pursuit of the minimum strain energy structure. Upper and lower bounds can be set on the geometric variables, which is useful in forcing the structure to remain within a reasonable design space. However, the algorithm appears to often "stick" to the boundary in cases where I know that the optimum solution lies away form the boundary.

05-12-2011 - I extended the algorithm's design variables to modify cross sectional areas and moments of inertia, instead of just the nodal coordinates. The orders of magnitude between nodal coordinates and member properties differ by 1 or 2m, and I observed poor performance on the simple test task. After consulting some optimization textbooks, I scaled the variables before running the optimization routine so that they all were of the same order of magnitude. Performance was greatly improved.

Implemented a second objective function for the structure - its volume. The goal of the optimization routine is now to find the minimum volume truss capable of sustaining the applied load. Naturally, the algorithm simply reduced the size of the structural elements as much as possible, always hitting the lower bound I set for element sizes. It also moves the nodal location so that the beams form a straight line. Both of these factors cause the displacements to then get very large. A limitation in our FE model is that it assumes material linearity. The displacements of the structure designed by the optimization algorithm are far in excess of those that would cause the structure's material to yield. The unconstrained, bounded Nelder Mead algorithm is not very useful now. This motivates the addition of a constraint in displacements. I followed the approach of (reference to Luersen paper here) and simply introduced a penalty term in the objective function, with an adaptive linear penalty multiplier. Initial results on the simple test problem are encouraging. It reaches a solution which respects the constraints but still decreases the objective function more or less monotonically to a solution (which is at least locally optimum)

I have also begun work on the gradient formulation. This requires taking the gradient of the inverse of the structure's stiffness matrix with respect to all the variables that the algorithm is allowed to modify - not an entirely trivial task!

05-12-2011 until 05-16-2011 - A lot of work during this time, and I have been a little less thorough in maintaining the log. I found a better way to do get gradients of the structure, using a trick from RL Fox's Engineering Optimization book. You can express the gradient of the displacements in terms of the gradient of the stiffness matrix. You still need to do a matrix inversion, but only of the original stiffness matrix. Details are on the main page. I spent a good deal of time debugging and refining the code. Some things I thought were working fine turned out to have issues which materialized when I tried to optimize a more complex structure. Most of these issues centered around the penalty formulation for dealing with constraints. Now works reasonably well for more complex structure. I did the background work for the gradient formulation, but it looks like I won't have time to implement it, given that I now need to spend some time writing up the project for the class site. Given that I most likely do some more research work in this area while at MIT, I intend to finish the implementation of the gradient method to get a sense of how much better the search will perform compared to Nelder Mead.