Just thought I'd update:
I've had a decent amount of success using sympy to solve large systems of
equations!
This is making school much easier in my opinion!
I have added a function to my solver that iterates through and replace any
symbols that have an obvious numeric answer, and another that iterates
through and substitutes symbols from equations where there are only two
variables.
This seemed to tame the large system we had put together for my machine
design class.
I will re-upload if anyone is interested. This is one of my first python
modules; I want to learn to code them correctly. I think this could have a
lot of utility.
Still learning how to manipulate data...
The "Wheel_Chair_Solver.py" takes the data from P-Lift.txt and generates
solutions for S-Lift.txt
solver.py is my imported module
Anyway, I had one more question.
I wanted to create a symbolic solution set for one variable in a system of
equations.
If you solved each equation for each variable in that system it seems like
you'd be poised to generate a large number of solutions for that variable -
via substitution.
It seems to me that a symbolic system of equations has a finite solution
set as long you don't start substituting an equation back into into
themselves. Is this seem correct?
I realize this would take a lot of processing power, so i started looking
in PyOpenCL as means of generate large amounts of parallel processes.
However, it seems that GPU programming is really only capable of numerical
analysis, and that it would be impossible to pass sympy functions/variables
to a GPU kernel?
^^I tried doing this with multiprocessing at the bottom of my solver.py
file. The functions have been commented out.
Anybody know if this is possible, or where to start looking??
Best regards,
Brett
On Friday, June 12, 2015 at 12:40:20 PM UTC-7, Brett Smith wrote:
>
> Yes, sympy automatically equates these equations to zero.
> You really are not supposed to write the equations this way when
> programming with Sympy, but for this application I wanted to be able to
> type equations in a little easier.
> I prefer:
> x^2 + y = 15
> to:
> Eq(x**2 + y, 15)
>
> I have a large amount of equations to get through in a large amount of
> problem sets :P
> I believe the syntax above is a little more familiar. The following
> function in the solver.py makes it understandable to sympy:
>
> def parse_input(_file): #Converts file into array of Sympy Functions
> _functions = []
> original_functions = []
> lines = []
> with open(_file,'r+') as f:
> lines = f.readlines()
> for line in lines:
> line = line[:-1]
> comment = line[0] == '#'
> if not comment:
> if "#" in line: #remove comments
> split = string.find(line,"#")
> line = line[0:split]
>
> original_functions.append(line) #Store original syntax
>
> line = string.replace(line," ","") #remove white space
> line = string.replace(line," ","")
>
> if "^" in line: #Convert conventional equation syntax in sympy syntax
> line = string.replace(line,"^","**")
>
> if "=" in line:
> split = string.find(line,'=')
> line = "Eq(" + line[0:split] + "," + line[split + 1:len(line)] + ")"
> temp = parse_expr(line)
> _functions.append(temp)
> return _functions, original_functions
>
>
> If its two cases for each of the four, is that not 8? I am afraid I don't
> understand.
> Do i need to solve for each term? i.e:
> > Sa = + sqrt(3)*T14
> > Sa = - sqrt(3)*T14
> > T14 = Sa/sqrt(3)
> > T14 = -Sa/sqrt(3)
>
> On Friday, June 12, 2015 at 10:44:48 AM UTC-7, Ondřej Čertík wrote:
>>
>> On Fri, Jun 12, 2015 at 2:53 AM, Brett Smith <[email protected]> wrote:
>> > This system of equations calculates the reaction forces internal to a
>> > machine structure (in this case, vise grip pliers). Then uses the
>> reaction
>> > forces to solve for stress, and eventually, the factor of safety on
>> each
>> > pin connection.
>> >
>> > I have made the changes you have suggested and I still don't get a
>> solution.
>> > I was thinking that by assigning each variable twice might over define
>> the
>> > system:
>> >
>> > Sa = - sqrt(3) * T14 AND Sa = + sqrt(3) * T14
>> >
>> > Will sympy know to solve this as a pair?
>>
>> No, you have to plug them there separately. As I said, there is 16 such
>> options.
>>
>> There seem to be other non-linearities, like:
>>
>> F12x + F32x
>> F32y + F12y + P
>> R32x*F32y - R32y*F32x + R12x*F12y - R12y*F12x + Rp*P
>> F43x + F23x
>> F43y + F23y + Fh
>> R43x*F43y - R43y*F43x + R23x*F23y - R23y*F23x + Rh*Fh
>> F14x + F34x
>> F14y + F34y
>> R14x*F14y - R14y*F14x + R34x*F34y - R34y*F34x
>>
>> aren't these missing an equal sign (=)? Or are these equal to 0? I
>> don't understand yet.
>>
>>
>>
>> > Even if I comment out all the negative assignments, I still do not get
>> a
>> > result...
>> >
>> > A numerical result is necessary, but in addition I'd like to play with
>> and
>> > vary the parameters, and perhaps solve large systems for variables I
>> choose
>> > to isolate.
>>
>> You should start by numerical solution of the system. Then if you find
>> one, we can try to find a symbolic solution. At least we'll know that
>> there is one.
>>
>> Ondrej
>>
>> > Looks Grobner basis might be a good place to start looking. I wanted to
>> get
>> > all of this functionality working this weekend so I could use it for a
>> class
>> > project....... buuuuut I might have been overly optimistic with my
>> timeline
>> > haha. Looks like I could learn a lot from studying these kind of
>> numerical
>> > analysis methods.
>> >
>> > For my sympy.solve() call I set the flat "Manual=true", does this
>> change the
>> > method Sympy uses to solve the system? I like the idea of the computer
>> > solving equations the same way I do, but perhaps eventually it is
>> simply not
>> > practical or even possible.
>> > It seems like for most solvers with non-linear systems, you must give
>> the
>> > solver some kind of starting value for it to begin its work.
>> >
>> > I have never actually had any of the code I've wrote make it into an
>> > official distributable package, so that would be really awesome!
>> > Looks like you have done a lot of work for this module! Open source
>> projects
>> > like these are primarily responsible for any success I've had both
>> > professionally and academically :P
>> >
>> > On Thursday, June 11, 2015 at 8:38:14 PM UTC-7, Ondřej Čertík wrote:
>> >>
>> >> On Thu, Jun 11, 2015 at 9:35 PM, Ondřej Čertík <[email protected]>
>> >> wrote:
>> >> > Hi Brett,
>> >> >
>> >> > On Thu, Jun 11, 2015 at 5:37 PM, Brett Smith <[email protected]>
>> wrote:
>> >> >> Thank you for getting back to me so quickly!
>> >> >> I am actually excited about this program, but it seems like I will
>> need
>> >> >> to
>> >> >> learn a thing or two about numerical analysis.
>> >> >> Our class is supposed to use TK Solver, and it seems to work OK.
>> >> >> However, I
>> >> >
>> >> > Interesting, it looks like TK Solver
>> >> > (http://en.wikipedia.org/wiki/TK_Solver) was invented by Miloš
>> >> > Konopásek (http://en.wikipedia.org/wiki/Milos_Konopasek), born in
>> the
>> >> > same country as I was.
>> >> >
>> >> >> really didn't understand how it worked, or why I was getting the
>> bugs I
>> >> >> had.
>> >> >> In addition, TK is only a numerical solver. As far as I can tell it
>> >> >> will NOT
>> >> >> present an answer as a function of other variables.
>> >> >>
>> >> >> I feel like in the long the run, developing and building my own
>> suite
>> >> >> (and
>> >> >> hopefully sharing) of functions would save me a lot of time in the
>> >> >> future,
>> >> >> especially if I plan on doing engineering design work.
>> >> >>
>> >> >> I attached a revised version of the solver.py file, and the input
>> file.
>> >> >> Everything works perfectly. I have 32 linear functions, 4
>> non-linear
>> >> >> functions and 36 unknown variables. It takes my program about 1.1s
>> to
>> >> >> run
>> >> >> and solve.
>> >> >>
>> >> >> I would like to add the following equations to the file
>> >> >> "P5-9-Reactions.txt":
>> >> >>
>> >> >> Na = Sy/Sa
>> >> >> Nb = Sy/Sb
>> >> >> Nc = Sy/Sc
>> >> >> Nd = Sy/Sd
>> >> >> Sy = 400*10^6
>> >> >> Sa^2 = 3*T14^2
>> >> >> Sb^2 = 3*T12^2
>> >> >> Sc^2 = 3*T43^2
>> >> >> Sd^2 = 3*T32^2
>> >> >> T14 = F14/A
>> >> >> T12 = F12/A
>> >> >> T43 = F43/A
>> >> >> T32 = F32/A
>> >> >> A = pi*d^2/4
>> >> >> d = .008
>> >> >>
>> >> >>
>> >> >> It seems to me that system is still determinant, with 51 unknowns
>> and
>> >> >> 51
>> >> >> equations.
>> >> >> However, as far as I can tell, the system hangs/runs indefinitely.
>> >> >> Because sympy is capable of delivering symbolic answers, I don't
>> mind a
>> >> >> long
>> >> >> execution time, as long as it is actually converging onto a
>> solution,
>> >> >> not
>> >> >> just running off to infinity...
>> >> >> That being said, I do not understand the underpinnings of a
>> numerical
>> >> >> solver, much less a symbolic run. In a class I am taking online we
>> have
>> >> >> gone
>> >> >> over linear gradient descent and thats about all I know about the
>> >> >> subject -
>> >> >> besides just doing symbolic analysis by hand.
>> >> >>
>> >> >> Any ideas on how I can get this to solve? I have grown attached to
>> >> >> sympy,
>> >> >> numpy, and matplotlib. I think they are very powerful, and I would
>> like
>> >> >> to
>> >> >> see more tools become free and open source :P
>> >> >
>> >> > I think this would be a welcome addition. We need to learn about the
>> >> > algorithms and state of the art to solve these kinds of problems. If
>> >> > it is a polynomial system of equations, then Gröbner basis is one
>> such
>> >> > method and SymPy has such capability. But I am not an expert in
>> that.
>> >> > It looks like you are after a numerical solution, so that's what I
>> >> > would recommend at first. It might be much easier to implement. You
>> >> > should open source it. Depending on which language you'll use to
>> >> > implement it, it can go to SciPy or a separate library. I like that
>> >> > you are trying to find or implement an open source solution. I am
>> the
>> >> > same way, thus SymPy was born.
>> >> >
>> >> > Can you describe the symbolic structure of those equations --- what
>> >> > kind of non-linearity is allowed? Because perhaps you can tell SymPy
>> >> > to first eliminate the linear system, which SymPy should be able to
>> >> > do, and then we just need to handle the nonlinear part. One way is
>> to
>> >> > take one equation and substitute into the rest, and so on. This only
>> >> > works for some non-linear systems. If it is more non-linear, it
>> might
>> >> > not be easy to eliminate a variable from an equation, then you need
>> >> > something more advanced.
>> >> >
>> >> > E.g. these are a bit tricky:
>> >> >
>> >> >> Sa^2 = 3*T14^2
>> >> >> Sb^2 = 3*T12^2
>> >> >> Sc^2 = 3*T43^2
>> >> >> Sd^2 = 3*T32^2
>> >> >
>> >> > But you can help it by solving two cases, first:
>> >> >
>> >> > Sa = + sqrt(3) * T14
>> >> > ...
>> >> >
>> >> > and the second:
>> >> >
>> >> > Sa = - sqrt(3) * T14
>> >>
>> >> Actually, you have 2 cases per each of the 4 equations, thus 2^4 = 16
>> >> cases total, you need to do all possible combinations.
>> >>
>> >> >
>> >> > And you'll have two solutions. It might be that the whole system
>> >> > doesn't have a solution for one of the cases, so then you end up
>> with
>> >> > just one solution overall.
>> >> >
>> >> > What is the application of such systems?
>> >> >
>> >> > Ondrej
>> >> >
>> >> >
>> >> >>
>> >> >> On Thursday, June 11, 2015 at 12:05:11 PM UTC-7, Ondřej Čertík
>> wrote:
>> >> >>>
>> >> >>> Hi Brett,
>> >> >>>
>> >> >>> On Thu, Jun 11, 2015 at 12:26 PM, Brett Smith <[email protected]>
>> >> >>> wrote:
>> >> >>> > Hello All,
>> >> >>> > New to the forum, but I have used Sympy on a few projects in the
>> >> >>> > past.
>> >> >>> > I am currently enrolled in a machine design course, and often
>> times
>> >> >>> > we
>> >> >>> > have
>> >> >>> > to solve large systems of equations.
>> >> >>> > I do not really like how any of the solver we use in class work,
>> so
>> >> >>> > I
>> >> >>> > thought I'd right my own.
>> >> >>> > If it works well enough Id like to add a GUI front end and
>> >> >>> > incorporate
>> >> >>> > commonly used engineering functions.
>> >> >>> > I have had success compiling systems of linear equations up to
>> about
>> >> >>> > 40
>> >> >>> > equations & 40 unknowns.
>> >> >>> > However adding any non-linear equations seems to break its
>> back...
>> >> >>>
>> >> >>> Can you post the file P5-9-FOS.txt, so that we can run solver.py?
>> >> >>>
>> >> >>> Is anything else needed to run it?
>> >> >>>
>> >> >>> What kind of equations are those? It seems these are numerical
>> >> >>> equations, but they are non linear, is that right? What solvers do
>> you
>> >> >>> use in class?
>> >> >>>
>> >> >>> Ondrej
>> >> >>>
>> >> >>> >
>> >> >>> > I was wondering if anybody here had a better way of going about
>> this
>> >> >>> > project.
>> >> >>> > Right now it just reads a text file full of equations, parses
>> the
>> >> >>> > strings
>> >> >>> > into sympy Functions, and then runs sympy.solve, and prints the
>> >> >>> > solution
>> >> >>> > to
>> >> >>> > a new file.
>> >> >>> >
>> >> >>> > So currently operations looks like:
>> >> >>> >
>> >> >>> > import solver
>> >> >>> > eqn = [] #holds all functions in file
>> >> >>> > symb = [] #holds unique symbols
>> >> >>> > sln = [] #holds all solution sets
>> >> >>> > og = [] #holds original, unparsed functions for printing to
>> output
>> >> >>> > file
>> >> >>> > in_file = "problem_file.txt"
>> >> >>> > out_file = "solution_file.txt"
>> >> >>> >
>> >> >>> > eqn , og = solver.parse_input(in_file)
>> >> >>> > symb = solver.sort_symbols(eqn)
>> >> >>> > sln = solver.solver(eqn)
>> >> >>> > print_output(out_file,sln,og)
>> >> >>> >
>> >> >>> > Ill post the code below for easy reading, but I'll also attach a
>> few
>> >> >>> > demo
>> >> >>> > files.
>> >> >>> > Any ideas on how to make this more powerful (i.e. more
>> equations, or
>> >> >>> > more
>> >> >>> > non-linear equations)???
>> >> >>> > Running this in my sublime editor a couple times also slows my
>> whole
>> >> >>> > system
>> >> >>> > WAY down from time to time (Ubuntu 14.04)
>> >> >>> > Thanks Gang!!
>> >> >>> >
>> >> >>> >
>> >> >>> >
>> >> >>> > from sympy import *
>> >> >>> > from sympy.parsing.sympy_parser import parse_expr
>> >> >>> > from IPython.display import display_pretty
>> >> >>> > import string
>> >> >>> > import time
>> >> >>> > import os
>> >> >>> >
>> >> >>> > init_printing(use_latex = True)
>> >> >>> >
>> >> >>> > #Vars
>> >> >>> > sig_figs = 6
>> >> >>> >
>> >> >>> >
>> >> >>> > def sort_symbols(_functions): #Returns unique Sympy sybols from
>> >> >>> > array of
>> >> >>> > functions
>> >> >>> > _symbols = []
>> >> >>> > temp = []
>> >> >>> > symbol_str = []
>> >> >>> > symbols_sorted = []
>> >> >>> >
>> >> >>> > for i in _functions:
>> >> >>> > _symbols.append(i.atoms(Symbol))
>> >> >>> >
>> >> >>> > for i in _symbols: #Puts all occurences of all symbols in 1 list
>> >> >>> > temp += (set.union(i))
>> >> >>> >
>> >> >>> > temp = list(set(temp)) #Eliminate duplicates
>> >> >>> >
>> >> >>> > for i in temp: #Convert to string so symbols may be sorted
>> >> >>> > symbol_str.append(str(i))
>> >> >>> >
>> >> >>> > symbol_str = sorted(symbol_str)
>> >> >>> >
>> >> >>> > for i in symbol_str: #Convert string back to sympy symbols
>> >> >>> > symbols_sorted.append(parse_expr(i))
>> >> >>> >
>> >> >>> > return symbols_sorted
>> >> >>> >
>> >> >>> > def parse_input(_file): #Converts file into array of Sympy
>> Functions
>> >> >>> > _functions = []
>> >> >>> > original_functions = []
>> >> >>> > lines = []
>> >> >>> > with open(_file,'r+') as f:
>> >> >>> > lines = f.readlines()
>> >> >>> > for line in lines:
>> >> >>> > line = line[:-1]
>> >> >>> > comment = line[0] == '#'
>> >> >>> > if not comment:
>> >> >>> > if "#" in line: #remove comments
>> >> >>> > split = string.find(line,"#")
>> >> >>> > line = line[0:split]
>> >> >>> >
>> >> >>> > original_functions.append(line) #Store original syntax
>> >> >>> >
>> >> >>> > line = string.replace(line," ","") #remove white space
>> >> >>> > line = string.replace(line," ","")
>> >> >>> >
>> >> >>> > if "^" in line: #Convert conventional equation syntax in sympy
>> >> >>> > syntax
>> >> >>> > line = string.replace(line,"^","**")
>> >> >>> >
>> >> >>> > if "=" in line:
>> >> >>> > split = string.find(line,'=')
>> >> >>> > line = "Eq(" + line[0:split] + "," + line[split + 1:len(line)] +
>> ")"
>> >> >>> > temp = parse_expr(line)
>> >> >>> > _functions.append(temp)
>> >> >>> > return _functions, original_functions
>> >> >>> >
>> >> >>> >
>> >> >>> > def solver(_functions):
>> >> >>> > _solution = solve(_functions[0:len(_functions)],manual=True)
>> >> >>> > #Pass
>> >> >>> > functions to solver #,symbols[0:len(symbols)] #passes symbols
>> >> >>> > print _solution
>> >> >>> > return _solution
>> >> >>> >
>> >> >>> > def print_output(_solutions):
>> >> >>> >
>> >> >>> > print "The submitted functions:"
>> >> >>> > for i in original_functions:
>> >> >>> > pretty_print(i)
>> >> >>> >
>> >> >>> > print "Have the following unique variables"
>> >> >>> > for i in sort_symbols():
>> >> >>> > pretty_print(i)
>> >> >>> >
>> >> >>> > print "And have solutions set(s):"
>> >> >>> > for i in _solutions:
>> >> >>> > for u in i:
>> >> >>> > print str(u) + " = " + str(Float(i[u],sig_figs))
>> >> >>> >
>> >> >>> > def print_to_file(f,_solutions,_functions):
>> >> >>> > ##Print File Header
>> >> >>> > _file = open(f,'w+')
>> >> >>> > header = "Brett's Sympy Solver!\nSolution Created : " +
>> >> >>> > time.strftime("%d/%m/%Y") + "\n"
>> >> >>> > _file.write(header)
>> >> >>> > header = "Equation File : " + os.getcwd() + "/" + in_file +
>> "\n\n"
>> >> >>> > _file.write(header)
>> >> >>> >
>> >> >>> > ##Some nice underscoring
>> >> >>> > max_length = 0
>> >> >>> >
>> >> >>> > for i in _solutions:
>> >> >>> > for u in i:
>> >> >>> > length = len(str(Float(i[u],sig_figs))+" = "+ str(u)) #find
>> longest
>> >> >>> > equation
>> >> >>> > if length > max_length:
>> >> >>> > max_length = length
>> >> >>> >
>> >> >>> > for i in _functions:
>> >> >>> > length = len(str(i))
>> >> >>> > if length > max_length:
>> >> >>> > max_length = length
>> >> >>> >
>> >> >>> > underscore = "_"
>> >> >>> > for i in range (0,(max_length-20)/2):
>> >> >>> > underscore += "_"
>> >> >>> >
>> >> >>> > _file.write(underscore +"SOLUTIONS"+ underscore +"\n")
>> >> >>> > for i in _solutions:
>> >> >>> > for u in i:
>> >> >>> > _file.write(str(u) + " = " + str(Float(i[u],sig_figs))+"\n")
>> >> >>> >
>> >> >>> > _file.write("\n" + underscore +"EQUATIONS"+ underscore +"\n")
>> >> >>> > #_file.write("Compiler Assumes All Equations = 0 Unless
>> >> >>> > specified\n")
>> >> >>> > print len(_functions)
>> >> >>> > for i in _functions:
>> >> >>> > _file.write(str(i)+"\n")
>> >> >>> > _file.write("\n\n\n\n")
>> >> >>> >
>> >> >>> > --
>> >> >>> > You received this message because you are subscribed to the
>> Google
>> >> >>> > Groups
>> >> >>> > "sympy" group.
>> >> >>> > To unsubscribe from this group and stop receiving emails from
>> it,
>> >> >>> > send
>> >> >>> > an
>> >> >>> > email to [email protected].
>> >> >>> > To post to this group, send email to [email protected].
>> >> >>> > Visit this group at http://groups.google.com/group/sympy.
>> >> >>> > To view this discussion on the web visit
>> >> >>> >
>> >> >>> >
>> >> >>> >
>> https://groups.google.com/d/msgid/sympy/89416b65-b1b1-40e4-b608-1d4a93be9a1f%40googlegroups.com.
>>
>>
>> >> >>> > For more options, visit https://groups.google.com/d/optout.
>> >> >>
>> >> >> --
>> >> >> You received this message because you are subscribed to the Google
>> >> >> Groups
>> >> >> "sympy" group.
>> >> >> To unsubscribe from this group and stop receiving emails from it,
>> send
>> >> >> an
>> >> >> email to [email protected].
>> >> >> To post to this group, send email to [email protected].
>> >> >> Visit this group at http://groups.google.com/group/sympy.
>> >> >> To view this discussion on the web visit
>> >> >>
>> >> >>
>> https://groups.google.com/d/msgid/sympy/0ca6f806-1316-4903-8cc2-99732b6b9e07%40googlegroups.com.
>>
>>
>> >> >>
>> >> >> For more options, visit https://groups.google.com/d/optout.
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> Groups
>> > "sympy" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> an
>> > email to [email protected].
>> > To post to this group, send email to [email protected].
>> > Visit this group at http://groups.google.com/group/sympy.
>> > To view this discussion on the web visit
>> >
>> https://groups.google.com/d/msgid/sympy/db23d376-edff-4bc7-8cab-dce9d2538ed7%40googlegroups.com.
>>
>>
>> >
>> > For more options, visit https://groups.google.com/d/optout.
>>
>
--
You received this message because you are subscribed to the Google Groups
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy.
To view this discussion on the web visit
https://groups.google.com/d/msgid/sympy/05f4c367-924c-4b89-b2a4-36656ddf2c99%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
S-Lift:
Total Equations: 78
Total Variables: 78
Total Solutions: 77
(F12x, 1123.17272085573)
(F12y, 1123.17272085573)
(F13x, -7053.57560949123)
(F13y, 2134.18569799642)
(F14x, -3897.35841885215)
(F14y, -3897.35841885215)
(F21x, -1123.17272085573)
(F21y, -1123.17272085573)
(F26x, 1123.17272085573)
(F26y, 1123.17272085573)
(F31x, 7053.57560949123)
(F31y, -2134.18569799642)
(F36x, -7053.57560949123)
(F36y, 2134.18569799642)
(F41x, 3897.35841885215)
(F41y, 3897.35841885215)
(F46x, -3897.35841885215)
(F46y, -3897.35841885215)
(F62x, -1123.17272085573)
(F62y, -1123.17272085573)
(F63x, 7053.57560949123)
(F63y, -2134.18569799642)
(F64x, 3897.35841885215)
(F64y, 3897.35841885215)
(F67x, -237347.761307488)
(F67y, 0)
(F68x, 227520.000000000)
(F68y, -640)
(F76x, 237347.761307488)
(F76y, 0.0)
(F78x, -227520.000000000)
(F78y, 0)
(F86x, -227520.000000000)
(F86y, 640)
(F87x, 227520.000000000)
(F87y, 0)
(Frx, 9827.76130748765)
(Fry, 640.000000000000)
(Load, -600)
(R12x, 0)
(R12y, 8.75000000000000)
(R13x, 0)
(R13y, -8.75000000000000)
(R14x, 0)
(R14y, -8.75000000000000)
(R21x, 6.72000000000000)
(R21y, 6.72000000000000)
(R26x, -6.72000000000000)
(R26y, -6.72000000000000)
(R31x, 6.71750000000000)
(R31y, -2.03250000000000)
(R36x, -6.71750000000000)
(R36y, 2.03250000000000)
(R41x, 6.72000000000000)
(R41y, 6.72000000000000)
(R46x, -6.72000000000000)
(R46y, -6.72000000000000)
(R62x, 0)
(R62y, 19)
(R63x, 0)
(R63y, 19)
(R64x, 0)
(R64y, -1)
(R67x, 2.50000000000000)
(R67y, -18)
(R68x, -2)
(R68y, -19.2500000000000)
(R76x, 0.500000000000000)
(R78x, -0.500000000000000)
(R86x, 21)
(R86y, -0.125000000000000)
(R87y, 0)
(Rload, -25)
(Rrx, 0)
(Rry, -10.7500000000000)
(Rweight, 0)
(Weight, -40)
### Bus Tower, Component 1
F12x + F13x + F14x + Frx = 0
F12y + F13y + F14y + Fry= 0
R12x*F12y - R12y*F12x + R13x*F13y - R13y*F13x + R14x*F14y - R14y*F14x + Rrx*Fry
- Rry*Frx = 0
### Upper Link, Component 2
F21x + F26x = 0
F21y + F26y = 0
R21x*F21y - R21x*F21y + R26x*F26y - R26y*F26x = 0
### Lower-Link, Component 4
F41x + F46x = 0 ## Lower Cylinder Not Included :F45x
F41y + F46y = 0 ## Lower Cylinder Not Included :F45y
R41x*F41y - R41y*F41x + R46x*F46y - R46y*F46x = 0 ## Missing R45xF45
### Upper Cylinder, Component 3
F36x + F31x = 0
F36y + F31y = 0
R36x*F36y - R36y*F36x + R31x*F31y - R31y*F31x = 0
### Chair Tower, Component 6
F62x + F63x + F64x + F67x + F68x = 0
F62y + F63y + F64y + F67y + F68y = 0
R62x*F62y - R62y*F62x + R63x*F63y - R63y*F63x + R64x*F64y - R64y*F64x +
R67x*F67y - R67y*F67x + R68x*F68y - R68y*F68x = 0
### Base Plate, Component 8
F86x + F87x = 0 ## No F85x
F86y + F87y + Load + Weight = 0 ## No F85y
R86x*F86y - R86y*F86x + R87x*F87y - R87y*F87x + Rload*Load + Rweight*Weight = 0
# No R85 x F85
Weight = -40
Load = - 600
F87y = 0
### Lower Cylinder, Component 5
#F54x + F58x = 0
#F54y + F58y = 0
#R54x*F54y - R54y*F54x + R58x*F58y - R58y*F58x = 0
### Platform Stop, Component 7
## No forces in x direction
F76y + F78y = 0
R76x*F76y + R78x*F78y = 0
### Third Law Components
F12x = -F21x
F12y = -F21y
F13x = -F31x
F13y = -F31y
F14x = -F41x
F14y = -F41y
F26x = -F62x
F26y = -F62y
##F45x = -F54x
##F45y = -F54y
F46x = -F64x
F46y = -F64y
F36x = -F63x
F36y = -F63y
##F58x = -F85x
##F58y = -F85y
F67x = -F76x
F67y = -F76y
F68x = -F86x
F68y = -F86y
F87x = -F78x
F87y = -F78y
### Geometry, For moment equations
#Bus Tower
R12y = 8.75
R13y = -8.75
R14y = -8.75
R12x = 0
R13x = 0
R14x = 0
Rrx = 0
Rry = -10.75 #Assuming 2 inches
### Upper Link
R21y = 6.72 #in (cos(theta)*li/2)
R26y = -6.72
R21x = 6.72
R26x = -6.72
### Lower Link
R41y = 6.72
R41x = 6.72
R46x = -6.72
R46y = -6.72
##R45x = -5.303 ### air cylinder 2 inches from other link
##R45y = -5.303
### Chair Tower
R62y = 19
R62x = 0
R63y = 19
R63x = 0
R64y = -1
R64x = 0
R68y = -19.25
R68x = -2
R67y = -18
R67x = 2.5
### Baseplate
Rload = -25
Rweight = 0
R86x = 21
R86y = -.125
##R85x = 24 ### 3 inches from hinge
##R85y = 0
### Platform Stopper
R76x = .5
R78x = -0.5
R87y = 0
R87x = 25
### Upper Air Cylinder
R36x = -6.7175
R36y = 2.0325
R31x = 6.7175
R31y = -2.0325
from solver import *
import sympy as sym
in_file = 'P-Lift'
out_file = 'S-Lift'
equations = problem_file(in_file)
solutions = solution_file(out_file)
"""
equations.solve(_numeric = 1)
print len(equations.sympy_symbols)
print len(equations.sorted_solutions)
for i in equations.sorted_solutions:
print i
for i in equations.sympy_symbols:
if i not in equations.solutions:
print i
"""
equations.max_reduction(_numeric = 1)
reduced_unknowns = len(equations.get_sympy_symbols(equations.reduction_functions[-1]))
reduced_knowns = len(equations.reduction_functions[-1])
"""Sort Reduction Solutions into List"""
redux = {}
srtd_redux = []
for i in equations.reduction_solutions:
redux.update(i)
srtd_redux = equations.dict_to_sorted_list(redux)
"""Run Solver and put into list"""
slvr = {}
srtd_slvr = []
slvr = sym.solve(equations.reduction_functions[-1])
srtd_slvr = equations.dict_to_sorted_list(slvr)
"""Append Both Solution Sets and Sort"""
slns = []
slns_dict = {}
for i in srtd_redux:
slns.append(i)
for i in srtd_slvr:
slns.append(i)
str_slns = []
for i in slns:
str_slns.append(str(i))
srtd_slns = sorted(str_slns)
"""Build Dictionary of Solutions"""
slns_dict.update(redux)
slns_dict.update(slvr)
""" Print Sorted Solutions"""
print "Total Equations: "+str(len(equations.sympy_functions))
print "Total Variables: " + str(len(equations.sympy_symbols))
print ("Total Solutions: " + str(len(slns)))
#print len(slns)
for i in srtd_slns:
print i
"""Find Missing Solutions"""
print
print "Missing Solutions: "
for i in equations.sympy_symbols:
if i not in slns_dict:
print i
#print(sym.solve(equations.reduction_functions[-1]))
#equations.solve()
"""
equations.max_reduction()
for i in equations.reduction_solutions:
print i
print
for i in equations.reduction_functions:
print i
"""import sympy as sym
from sympy.parsing.sympy_parser import parse_expr
from IPython.display import display_pretty
from progressbar import ProgressBar
import multiprocessing as mp
import string
import time
import os
sym.init_printing(use_latex = True)
sig_figs = 10
pbar = ProgressBar()
class problem_file(object):
solutions = {} # Dictionary holds master list of numeric solutions
sorted_solutions = []
solver_solutions = {} # Dictionary holds solutions from sym.solve()
reduction_solutions = [] # Holds solutions from direct substitution
reduction_functions = [] # Holds reduced functions from direct substitution
reduction_count = []
#symbolic_count = []
#function_singularities = []
def __init__(self, in_file):
self.in_file = in_file + '.txt'
self.sympy_functions = self.get_sympy_functions()
self.sympy_symbols = self.get_sympy_symbols()
self.original_functions = self.get_original_functions()
self.knowns = len(self.sympy_functions)
self.unknowns = len(self.sympy_symbols)
def get_sympy_functions(self): #Converts file into array of Sympy Functions
_functions = []
_lines = []
with open(self.in_file,'r+') as f:
_lines = f.readlines()
for line in _lines:
line = line[:-1] #remove newline character
comment = line[0] == '#'
if not comment:
if "#" in line: #remove comments
split = string.find(line,"#")
line = line[0:split]
line = string.replace(line," ","") #remove white space
line = string.replace(line," ","")
if "^" in line: #Convert conventional equation syntax in sympy syntax
line = string.replace(line,"^","**")
if "=" in line:
split = string.find(line,'=')
line = "Eq(" + line[0:split] + "," + line[split + 1:len(line)] + ")"
else:
line = "Eq(" + line +",0)" #Convert all funcs to relational equality
line = parse_expr(line) #Convert string to sympy function
_functions.append(line)
return _functions
def get_sympy_symbols(self,_functions = 0): #Returns unique Sympy sybols from array of functions
_symbols = []
_temp = []
_symbol_str = []
_symbols_sorted = []
if not _functions:
_functions = self.sympy_functions
for i in _functions:
_symbols.append(i.atoms(sym.Symbol))
for i in _symbols: #Puts all occurences of all symbols in 1 list
_temp += (set.union(i))
_temp = list(set(_temp)) #Eliminate duplicates
for i in _temp: #Convert to string so symbols may be sorted
_symbol_str.append(str(i))
_symbol_str = sorted(_symbol_str)
for i in _symbol_str: #Convert string back to sympy symbols
_symbols_sorted.append(parse_expr(i))
return _symbols_sorted
def get_original_functions(self):
_functions = []
_lines = []
with open(self.in_file,'r+') as f:
_lines = f.readlines()
for line in _lines:
line = line[:-1]
comment = line[0] == '#'
if not comment:
if "#" in line: #remove comments
split = string.find(line,"#")
line = line[0:split]
_functions.append(line) #Store original syntax
return _functions
def max_reduction(self, _functions = 0, _numeric = 0):
if not _functions:
self.substitution_reduction(_numeric = _numeric)
while(self.reduction_count[-1] > 0):
self.substitution_reduction(_numeric = _numeric)
return
else:
_functions, count = self.substituion_reduction(_functions, _numeric = _num)
while(count > 0):
_functions, count = self.substitution_reduction(_functions, _numeric = _num)
return _functions
def set_to_list(self,_set, _reversed = 0):
_list = []
for i in _set:
_list.append(i)
if not _reversed:
return (_list)
else:
return list(reversed(_list))
def substitution_reduction(self,_functions = 0,_numeric = 0):
_symbols = []
_solutions = []
_temp_solutions = []
_out_functions = []
_dict_solutions = {}
_dict1 = {}
_list_solutions = []
_list_substituions = []
if not _numeric:
x = 2
else :
x = 1
"""Check which functions to use"""
if not _functions:
_self = 0
if not self.reduction_functions:
_functions = self.sympy_functions
else:
_functions = self.reduction_functions[-1]
"""Look for solvable functions"""
for i in _functions:
_sym = i.atoms(sym.Symbol)
"""Only 2 symbols allowed for symbolic substitution,
1 variable allowed for numeric equivalence """
if (len(_sym) <= x):
_sym = self.set_to_list(_sym, _reversed = 1) ## must reverse because set.pop() is reversed
_symbols.append(_sym[0])
_temp_solutions = sym.solve(i,_sym[0]) ## Because result is a list, return to list and then dereference
if _temp_solutions:
#print (i,sym.N(_temp_solutions[0]))
_solutions.append(_temp_solutions[-1]) ## Result should be list of len 1
_list_substituions = list(zip(_symbols,_solutions))
"""Substitute new solutions into old functions"""
for i in _functions:
temp = i.subs(_list_substituions)
if type(temp) != bool:
_out_functions.append(temp)
total_reduced = len(_functions) - len(_out_functions)
"""Update values to class/self"""
if not _self:
for i in _list_substituions:
_set = i[1].atoms(sym.Symbol)
if len(_set) == 0: ### If the len set == 0, there is only numerical solution
_list_solutions.append(i)
_dict1 = {i[0]:i[1]}
_dict_solutions.update(_dict1)
self.reduction_solutions.append(_dict_solutions)
self.reduction_functions.append(_out_functions)
self.reduction_count.append(total_reduced)
return _out_functions, total_reduced
def dict_to_sorted_list(self,_dict):
_keys = []
_sorted_keys = []
_sort = []
_vals = []
for i in list(_dict):
_keys.append(str(i))
_keys = sorted(_keys)
for i in _keys:
_sorted_keys.append(sym.Symbol(i))
_vals.append(_dict[sym.Symbol(i)])
_sort = list(zip(_sorted_keys,_vals))
return _sort
def solve(self, _functions = 0,_numeric = 0):
"""First Reduce Numerically"""
self.max_reduction(_numeric = _numeric )
if self.reduction_functions:
temp = sym.solve(self.reduction_functions[-1])
#print temp
"""Combine reduction solutions and solver solutions"""
self.solutions.update(self.solver_solutions)
for i in self.reduction_solutions:
self.solutions.update(i)
"""Generate list of sorted solutions"""
self.sorted_solutions = self.dict_to_sorted_list(self.solutions)
class solution_file(object):
def __init__(self,out_file,in_file = 0):
self.out_file = out_file
self.in_file = in_file
def write(self,_solutions, _equations = [],_iterations = []):
header = ["Brett's Sympy Solver!\nSolution Created : " + time.strftime("%d/%m/%Y") + "\n"]
if self.in_file :
header.append("Equation File : " + os.getcwd() + "/" + self.in_file + ".txt" "\n\n")
_file = open(self.out_file + '.txt',"w+")
for i in header:
_file.write(i)
_file.write("_______SOLUTIONS_______\n")
for i in _solutions:
_file.write(str(i) + "\n" )
if _equations:
_file.write("\n_______EQUATIONS_______\n")
for i in _equations:
_file.write(str(i)+"\n")
if _iterations:
_file.write("\n_______SOLUTION ITERATIONS_______\n")
for u,i in enumerate(_iterations):
_file.write("ITERATION " + str(u) + ":\n")
for x in i:
_file.write(str(x)+"\n")
def string_to_sympy_function(line):
line = string.replace(line," ","") #remove white space
line = string.replace(line," ","")
if "^" in line: #Convert conventional equation syntax in sympy syntax
line = string.replace(line,"^","**")
if "=" in line:
split = string.find(line,'=')
line = "Eq(" + line[0:split] + "," + line[split + 1:len(line)] + ")"
line = parse_expr(line)
return line
def run(in_file, out_file):
#in_file = 'Chair-Lift-Equations'
#out_file = 'Chair-Lift-Equations'
equations = problem_file(in_file)
solutions = solution_file(out_file)
unknowns = len(equations.sympy_symbols)
knowns = len(equations.sympy_functions)
print ("Unkowns : " + str(unknowns))
print ("Knowns : " + str(knowns))
equations.max_reduction()
for i in equations.reduction_count:
print i
for i in equations.reduction_functions[-1]:
print i
print len(equations.reduction_functions[-1])
print len ( equations.get_sympy_symbols( equations.reduction_functions[-1] ) )
if __name__ == '__main__':
in_file = '/home/waymond91/Documents/School/Wheel_Chair_Lift/blah'
out_file = 'Chair-Lift-Reactions'
run (in_file,out_file)
"""
def worker_solver(self,_sympy_function,data):
name = mp.current_process().name
_soln = []
_symb = []
_set = []
for i in _sympy_function.atoms(sym.Symbol):
_soln.append(sym.solve(_sympy_function,i))
_symb.append(i)
data.append(dict(zip(_symb,_soln)))
return
def solve_all_symbols(self,_equations = 0):
_solvers = []
dct = {}
count = 0
manager = mp.Manager()
solution_data = manager.list()
if _equations:
_functions = _equations
else:
_functions = self.sympy_functions
for count,u in enumerate((_functions)):
_solvers.append(mp.Process(target=self.worker_solver,args=(u,solution_data)))
for worker in _solvers:
worker.start()
for workers in (_solvers):
workers.join()
for workers in (_solvers):
workers.terminate()
if _equations:
return solution_data
self.function_singularities = list(solution_data)
#print len(self.function_singularities)
"""
"""
def numerical_reduction(self, _functions=0):
_solutions=[]
_symbols = []
_out_functions = []
dct = {}
lst = []
if not _functions:
_self = 0
if len(self.reduction_functions) == 0:
_functions = self.sympy_functions
else:
_functions = self.reduction_functions[-1] #get last element
for i in _functions:
if len(i.atoms(sym.Symbol)) == 1:
atom = i.atoms(sym.Symbol)
_symbols.append(atom.pop())
temp = (sym.solve(i))
_solutions.append(temp[0])
lst = list(zip(_symbols,_solutions))
dct = dict(zip(_symbols,_solutions))
for i in _functions:
temp = i.subs(lst)
if type(temp) != bool:
temp = sym.N(temp,sig_figs)
_out_functions.append(temp)
total_reduced = len(_functions) - len(_out_functions)
if not _self:
self.reduction_solutions.append(dct)
self.reduction_functions.append(_out_functions)
self.numeric_count.append(total_reduced)
return _out_functions, total_reduced
"""