How to: Use Python to Solve Optimization Problems

As I mentioned a few weeks ago, some ZIA readers may interested in learning how to use Python, and various supporting packages, to solve mathematics problems frequently encountered by social scientists. Depending on the level of interest, I will make more of these tutorials to tackle other problems.

Optimization problems are a class frequently encountered by social scientists, and therefore this is where I will begin. Optimization techniques can answer questions such as, “if we spend x on schools, y on hospitals and z on infrastructure in a attempt gain confidence from some population P, what is the optimal amount to spend in each to gain maximum confidence?” In a step-by-step fashion, this tutorial will explain how to use Python and SymPy to solve these types of problems.

  1. If you have not already, you will need to download and install the Python IDLE and SymPy compatible with your operating system. Each of these software packages has their own installation instructions, review them carefully before installing. Also, if you are totally new to Python, I recommend the Dive Into Python tutorial. Once you have the software up and running we are ready to begin!
  2. Problem: Find the critical points for the function below, then classify these critical points as either local maximum, local minimum, saddle point, or neither.

    f(x,y)=x^{4}+x^{2}-6xy+3y^{2}

    First, we must find the first-order conditions of this function by setting up the gradient. To do this using Python, we must first import SymPy into the IDLE and then add the appropriate variables to memory.

  3. Open the Python IDLE and type the following commands (all Python commands will be in block-quotes):

    >>> import sympy as S
    >>> x,y=S.symbols(‘xy’)

    The first line loads the entire SymPy package into the variable S, while the second line adds the variables x and y into memory using SymPy’s symbolic format so they can be manipulated.

  4. The gradient of this function will be the partial derivatives of both variables, x and y.
    bigtriangledown f = frac{partial f}{partial x}, frac{partial f}{partial y}

    To solve this with Python, we will first store the function as a variable, then use SymPy’s diff function to perform partial differentiation on f.
  5. We store the function in a variable to prevent ourselves from having to repeatedly enter the function into IDLE.

    >>> f=x**4+x**2-6*x*y+3*y**2
    >>> f
    -6*x*y + x**2 + 3*y**2 + x**4

    You will notice two things; first, the ** is Python’s is exponent operator, that is, if you are calculating 42 you would type 4**2 into the interpreter; second, SymPy has rearranged the function. This rearranging occurs because SymPy automatically reorders variables from most negative to most positive rank. Now we perform the partial differentiation.

    >>> a=S.diff(f,x)
    >>> S.pprint(a)
    -6*y + 2*x + 4*x3
    >>> b=S.diff(f,y)
    >>> S.pprint(b)
    -6*x + 6*y

    SymPy’s S.diff command will differentiate a function with respect to all or some of its variables. In our example, S.diff(f,x) is differentiating f with respect to x and likewise S.diff(f,y) is differentiating f with respect to y. To find the full derivative; however, simply execute S.diff(f,[x,y]). Another very useful command in SymPy is S.pprint or “pretty print”. This command will take SymPy’s symbolic representation of a function and output it in a more readable manner. To see the difference, inspect our new variables a or b without using S.pprint. With the gradient now stored in memory, we can use these variables to solve the system of equations and find the critical points.

  6. To do this, we can use SymPy’s built-in equations solver.

    >>> S.solve_system([a,b],[x,y])
    [(-1, -1), (0, 0), (1, 1)]

    Our critical points are (-1,-1), (0,0) and (1,1). We now use the second-order conditions to find if they are local maximum/minimum, saddle points or neither. To do so, we must find the Hessian matrix of f and find out the “definiteness” of this matrix for all of our critical points.

  7. SymPy has commands that will easily allow us to calculate the Hessian, as well as the principal minors of those matrices, which will tell us the definiteness.

    >>> H=S.hessian(f,[x,y])

    The translation from Python matrix form to HTML is ugly, so for clarity, we find the Hessian of f is equal to the equation below.

    D^{2}f(x,y)=left| begin{array}{lr} 12x^{2}+2&-6 \ -6&6end{array} right|

    Given that the Hessian has only one element containing a variable (12x2+2), we will only have to plug in the x-values of our critical points to be able to classify them; however, in order to find the definiteness of these matrices we will have to store three matrices in memory for SymPy to operate on.
  8. To do so, we use SymPy’s internal matrix package, S.Matrix, to store these matrices.

    >>> M1=S.Matrix([14,-6],[-6,6])
    >>> M2=S.Matrix([2,-6],[-6,6])

    Note, since 2+12*(+/-1)2 are equivalent, M1 represents both critical points (-1,-1) and (1,1) and M2 represents (0,0). Our final step is to find the principal minors of these matrices to determine their definiteness.

  9. SymPy has a built in function that will return all N principal minors of an NxN matrix, so we need only to check the sign of the results of this command to get our answers.

    >>> S.Matrix.berkowitz_minors(M1)
    (14, 48)
    >>> S.Matrix.berkowitz_minors(M2)
    (2, -24)

    M1 is positive definite because all principal minors are &ge 0, therefore (-1,-1) and (1,1) are both local minimum. Conversely, because the principal minors of M2 flip sign from positive to negative it is indefinite, therefore (0,0) is a saddle-point.

I hope you have found this tutorial useful, and you will be able to take these tools and apply them to your own problems. As always, if you have any questions please enter a comment, or send me an e-mail.


Automatically Generated Related posts:

  1. UPDATED: Must-Have Python Packages for Social Scientists
  2. How to: Perform Multivariate Regression with Python
  3. How to: Use Python and Social Network Analysis to Find New Twitter Friends
  4. On the Disutility of Network Analysis and the Top 5 Problems
  5. How to: Use Python to Collect Data from the Web – Part 2: Saving the Data

16 comments to How to: Use Python to Solve Optimization Problems

  • Lindsey Cormack

    This is a good thing

    [Reply]

  • Hello.
    I am interested in using Python for numerical optimization tasks, not only by using existing packages, but also by implementing my own algorithms, as a part of my PhD Thesis work.
    I am glad to read this clear example that speaks about the way to deal with optimization basic tasks within Python.
    I would like to ask the author and the readers about any package or module related to Optimization.
    As far as I know, there is COIN-OR, OpenOpt, cvsopt, as well as other non-free solutions (for example, MOSEK Python API).
    Do you know any other interesting proposal (frameworks for optimization, whatever)??
    Thank you in advance.
    [sorry for my English mistakes]

    [Reply]

  • Vincent, you may want to look into Sage, which uses the same packages (sympy, etc) to evaluate symbolic math, but with a nice UI wrapped around it. Good luck!

    [Reply]

  • somebody can help me??

    someone can help me??
    I never program before,
    is it possible to create a simple script
    that ask the function and tell us the answer??
    I try this but it doesn’t work:
    when I run hessiana.py:
    3
    -6*y + 2*x + 4*x
    -6*x + 6*y
    Traceback (most recent call last):
    File “C:\Documents and Settings\Proprietario\Desktop\hessiana.py”, line 8, in
    S.solve_system([a,b],[x,y])
    AttributeError: ‘module’ object has no attribute ‘solve_system’
    this is my hessiana.py:
    import sympy as S
    x,y=S.symbols(‘xy’)
    f=x**4+x**2-6*x*y+3*y**2
    a=S.diff(f,x)
    S.pprint(a)
    b=S.diff(f,y)
    S.pprint(b)
    S.solve_system([a,b],[x,y])
    H=S.hessian(f,[x,y])
    M1=S.Matrix([14,-6],[-6,6])
    M2=S.Matrix([2,-6],[-6,6])
    S.Matrix.berkowitz_minors(M2)
    S.Matrix.berkowitz_minors(M1)

    [Reply]

  • Seeking help,
    I cannot duplicate your error, when I run your code I get the following:
    >>> S.Matrix.berkowitz_minors(M2)
    (2, -24)
    >>> S.Matrix.berkowitz_minors(M1)
    (14, 48)

    [Reply]

  • rocco

    thank you for the answer!!
    the error is still here… :-( (
    is it possible to make the script more interactive:
    for example:
    - you open “hessiana.py”,
    - it ask for the function,
    - you enter the function,
    - then appear the answer
    thanks a lot!!

    [Reply]

  • roccolo

    thanks for fast reply!!!
    but i can’t solve the error!!!

    [Reply]

  • roccolo

    ok I found the error!!!
    instead of “solve_system”
    I put “solve” and now it work!!!
    but how can I make a script with “raw_input”??
    thank ou

    [Reply]

  • It would be a bit problematic to use raw_input with this setup because you have to setup the symbolic representation of variables in sympy.
    You could use a regular expression to try to extract out those variables, but I don’t think there would ever be a perfect interactive solution.

    [Reply]

  • roccolo

    ok now it works!!
    but how I can automate the last passage from hessian to matrix???:
    import sympy
    x = sympy.Symbol(‘x’)
    y = sympy.Symbol(‘y’)
    f = input(“function :”)
    print “you input this: “, f
    a = sympy.diff(f, x)
    print “f’ x:”
    sympy.pprint(a)
    b = sympy.diff(f, y)
    print “f’ y:”
    sympy.pprint(b)
    print “critical points are: ”
    print sympy.solve([a, b], [x, y])
    H = sympy.hessian(f, [x,y])
    M1 = sympy.Matrix([14,-6], [-6,6])
    M2 = sympy.Matrix([2,-6], [-6,6])
    sympy.Matrix.berkowitz_minors(M2)
    sympy.Matrix.berkowitz_minors(M1)

    [Reply]

  • roccolo

    sorry,
    how can I pass the critical point to hessian matrix??

    [Reply]

  • anuraf

    hello
    i need a help that,i am doin a project named source analyser in python.for that purpose i want to know what is the regular expression to list the variables used in a particular source code.i find out the headerfiles,function used in a source code by using fffindgrep function,but i can’t use that to search the variables.i think the regular expression that i gave is not correct.when i gave the regular expression like ['\w+','='].it returns not only the variables but also all the things that is followed by = and ==.so pls suggest the regular expresssion to list the variables.
    reply soon……

    [Reply]

  • Anuraf:
    Unfortunately, I am not an expert in regular expression, and generally just refer to the online manual anytime I need to use them.
    Here is what I use: http://docs.python.org/dev/howto/regex.html
    Good luck!

    [Reply]

  • Hi folks. I know this post is a little old, but I wanted to note that there is no need to use regular expressions to convert input into a SymPy expression. SymPy has a built-in function sympify() that converts strings into SymPy expressions:
    >>> from sympy import *
    >>> sympify(“x**2″)
    x**2

    [Reply]

  • oscar

    I know it is a bit old this post, but for all of you who are python lovers in the applied math/optimization world, here it is a python package worth using it:
    https://software.sandia.gov/trac/coopr/wiki/Pyomo

    Which is part of a bigger framework/package: https://software.sandia.gov/trac/coopr/

    Enjoy it!

    [Reply]

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Technorati Profile