views:

312

answers:

3

Are there any libraries or techniques that simplify computing equations ?

Take the following two examples:

  • F = B * { [ a * b * sumOf (A / B ''' for all i ''' ) ] / [ sumOf(c * d * j) ] }

    where:

    F = cost from i to j

    B, a, b, c, d, j are all vectors in the format [ [zone_i, zone_j, cost_of_i_to_j], [..]]

    This should produce a vector F [ [1,2, F_1_2], ..., [i,j, F_i_j] ]

  • T_ij = [ P_i * A_i * F_i_j] / [ SumOf [ Aj * F_i_j ] // j = 1 to j = n ]

    where:

    n is the number of zones

    T = vector [ [1, 2, A_1_2, P_1_2], ..., [i, j, A_i_j, P_i_j] ]

    F = vector [1, 2, F_1_2], ..., [i, j, F_i_j]

    so P_i would be the sum of all P_i_j for all j and Aj would be sum of all P_j for all i

I'm not sure what I'm looking for, but perhaps a parser for these equations or methods to deal with multiple multiplications and products between vectors?

To calculate some of the factors, for example A_j, this is what i use

from collections import defaultdict

A_j_dict = defaultdict(float)
for A_item in TG: A_j_dict[A_item[1]] += A_item[3]

Although this works fine, I really feel that it is a brute force / hacking method and unmaintainable in the case we want to add more variables or parameters. Are there any math equation parsers you'd recommend?

Side Note: These equations are used to model travel. Currently I use excel to solve a lot of these equations; and I find that process to be daunting. I'd rather move to python where it pulls the data directly from our database (postgres) and outputs the results into the database. All that is figured out. I'm just struggling with evaluating the equations themselves.

Thanks :)

A: 

Did you check SAGE?

Sage is a free open-source mathematics software system licensed under the GPL. It combines the power of many existing open-source packages into a common Python-based interface.

Sage is built out of nearly 100 open-source packages (including Numpy and Scipy) and features a unified interface. Sage can be used to study elementary and advanced, pure and applied mathematics. This includes a huge range of mathematics, including basic algebra, calculus, elementary to very advanced number theory, cryptography, numerical computation, commutative algebra, group theory, combinatorics, graph theory, exact linear algebra and much more. It combines various software packages and seamlessly integrates their functionality into a common experience. It is well-suited for education and research.

joaquin
Will thank any comment on why the downvote.
joaquin
It seems that Sage is pretty monolithic, where this guy sounds as though he's looking to make it as self-contained as possible (hence the move away from Excel). Installing nearly a gigabyte of software might be counterproductive. :)
dwf
+3  A: 

The common solution to this kind of task is NumPy.

Your equations seem close enough to vector and matrix equations that NumPy's arrays and matrices should be very helpful.

Here is an example based on what you want:

T_ij = [ P_i * A_i * F_i_j] / [ SumOf [ Aj * F_i_j ] // j = 1 to j = n ]

where: n is the number of zones

T = vector [ [1, 2, A_1_2, P_1_2], ..., [i, j, A_i_j, P_i_j] ]

F = vector [1, 2, F_1_2], ..., [i, j, F_i_j]

so P_i would be the sum of all P_i_j for all j and Aj would be sum of all P_j for all i

This can be calculated for instance with:

import numpy as np
A = np.array([…]); P = np.array(…)  # Vectors (1D arrays)
F = np.array([[…], […],…])  # 2D array
T = (P*A*F.T).T/np.dot(F, A)

You see that the final result is expressed in a quite compact form, thanks to NumPy. NumPy array calculations are also very fast.

What you are trying to achieve is really an ideal job for NumPy. If you are ready to learn this tool, I would suggest that you go through the Numpy tutorial.

EOL
Can you give a simplified example of how to calculate A_1,2 = P_1 / [sumOF (A_j * F_1,2) ]. I've looked into numpy before, and I couldn't figure out how to do this type of calcs
dassouki
+4  A: 

To do an elementwise multiply of two NumPy arrays with the same dimension is simply 'A * B'.

In [1]: a = arange(50)

In [2]: b = ones(50) * 2

In [3]: a
Out[3]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
       34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49])

In [4]: b
Out[4]: 
array([ 2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,
        2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,
        2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,
        2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.])

In [5]: a * b
Out[5]: 
array([  0.,   2.,   4.,   6.,   8.,  10.,  12.,  14.,  16.,  18.,  20.,
        22.,  24.,  26.,  28.,  30.,  32.,  34.,  36.,  38.,  40.,  42.,
        44.,  46.,  48.,  50.,  52.,  54.,  56.,  58.,  60.,  62.,  64.,
        66.,  68.,  70.,  72.,  74.,  76.,  78.,  80.,  82.,  84.,  86.,
        88.,  90.,  92.,  94.,  96.,  98.])

In [6]: (a * b).sum()
Out[6]: 2450.0

If you can write things in terms of matrix multiplies, you can use dot():

In [7]: A = arange(25).reshape((5,5))

In [8]: X = arange(5)

In [9]: A
Out[9]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

In [12]: dot(A, X) # Sum_j A[i,j] * X[j] for all i
Out[12]: array([ 30,  80, 130, 180, 230])

That should get you started.

dwf