PDA

View Full Version : Physics Parser

jverkoey
10-19-2004, 09:55 PM
I've just finished developing my Physics Solver application for my high school computer science special project. I'm not posting this as merely a project (or I'd put it in the projects section), but also posting it to say that I'm releasing the source, if anyone's interested in checking it out.

I've been working on the solver from scratch (minus the math parser, which used some base code from OST2) since Sept. 23, and have just finished the help file and adding the license stuff to all the source files.

So, let's get on to the good stuff.
You can get the binaries of the solver here:
http://thejefffiles.com/downloadfile.php?fileID=downloads/PSolverInstall.exe

The source can be gotten here:
http://thejefffiles.com/downloadfile.php?fileID=downloads/Physics%20Solver%20source.zip

And the original idea can be found here:
http://thejefffiles.com/articles/compsciproj.doc

So, if you'd like to get the source, check it out, give any feedback you feel is necessary, I'd be thankful. I'm looking for feedback on both the program itself and the source (any suggestions for better layouts or organization?)

And for people who don't feel like looking at the solver itself, basically the purpose of it is to solve physics problems with the only known values being the input. For example, say you only knew the mass and acceleration of an object, with the solver, you could do this:

m=10
a=20

slv F

and it will solve for F automatically. This is a very simple example, but the solver uses a recursive algorithm to find equations to solve with, so it can get quite complex.

Note to mods: Before I get flamed in case this doesn't belong in gd, feel free to move it if it shouldn't be here.

Sang-drax
10-20-2004, 12:57 AM
Interesting project.
I tested it with the formula for acceleration in circular movement and it worked. a=v^2/r

I don't like the parser though -- this gives errors:

a = 5
v = 5
slv r

If you remove the spaces around the '=' it works. I don't like space-sensitive parsers.

I'll test it some more now.

Sang-drax
10-20-2004, 01:24 AM
Wouldn't there be lots of ambiguity issues in this kind of program?

F=2
a=2
v=2
slv E

In this example, you could calculate the mass using the force and acceleration and calculate the energy using E=mc2, or you could calculate it with E = v^2 / 2
Which would be correct?

EDIT:
I don't think it'd be hard to change the program so you don't have to type:

v=d/t
d=v*t
t=d/v

in the definitions file. The program should convert every equation of the form A=B to the standard form A-B=0 and if it knows every variable but one in an equation solve it using Newton-Raphson.

okinrus
10-20-2004, 02:17 AM
Another idea of solving these kind of problems is to use a constraint graph. Iif you have an equation f := m * a, you would create nodes in your graph with edges from f to m and from f to a. (You would probably not have to actually construct the graph in your implementation, because the connection is implicit from the callbacks.) When nodes m and a have valid values, then f can be solved.

An implementation of this idea would have node f register modify callbacks for nodes a and m, so that when nodes a or m are modified node f is notified. Although m could be notified and a could be undertermined, f would then check to see if both m and a were notified. Only when both m and a are determined will f calculate its value, thereby f would become determined. Node f could also have nodes that depend upon its value, and when f becomes determined, it would also notify the nodes that depend on it.

There is a catch, however, because when f is known and m is known its possible to solve for a. But this problem is easily solved. Simply have node m register notifications for nodes f and a, and have node a register for nodes m and f. Notifications could, then, be handed accordingly.

jverkoey
10-20-2004, 07:53 AM
sang-drax:
Fixed the space sensitivity error (that was a fault on my part, forgetting to shave whitespace from the correct white spaces)
I inserted line 91 of PhysicsParserCommands.cpp to shave the leading and trailing whitespace off of the variable name before shaving inner whitespace (to see if the name's length didn't change, meaning there's no whitespace between the letters, causing an error). The source and the release have both been updated.

okinrus:
I'm not sure, as I hadn't thought of solving things exactly the same way you described, but I think my system kind of works similarly that way....
What it does is searches for functions that solve for that particular variable, and then tries to parse the equation. The math solver will return a flag that says whether or not it compiled the math string correctly or not, and if it didn't, it returns a list of the undefined variables. The solver then proceeds to recursively call the solve function until it can solve for that equation. In essence doing that I think you just explained.

Sang-drax again (on the note of figuring out the different equations):
I'm not sure what the Newton-Rhapson method is (the last math I took was precalc last year, or the grade 12 equivalent, I'm taking calc next semester). But I will research it and see if that will allow me to do that or not.
As far as the A=B A-B=0 method, I wonder if there's any way I could use my existing stack parser to do this easily? As when you are moving around values in equations, you tend to have to follow order of operations (for the most part) and my math parser follows order of ops perfectly...

In this example, you could calculate the mass using the force and acceleration and calculate the energy using E=mc2, or you could calculate it with E = v^2 / 2
Which would be correct?

Yah, that's one problem with the solver is ambiguous cases such as these. I was thinking of making it so if there was more than one possible solution (and they yielded different results) that you could have the option of selecting which equation to use, maybe via a menu that pops up. I didn't implement this as one of my goals was to keep the interface simple and easy to use, and adding more menus would only complicate things. However, this is something that probably wouldn't add *too* much complication, yet wield more accurate results, which is definitely worth it.

Thanks for the feedback

Sang-drax
10-20-2004, 09:39 AM
I'm not sure what the Newton-Rhapson method is (the last math I took was precalc last year, or the grade 12 equivalent, I'm taking calc next semester). But I will research it and see if that will allow me to do that or not.
As far as the A=B A-B=0 method, I wonder if there's any way I could use my existing stack parser to do this easily?
I haven't looked at your source.
That being said, I'll try to explain what I mean:

Look at this case:
I write in the config file:

F = m*a
The computer parses this and converts it to

(F) - (m*a)Which it knows equals zero.
When I input this into the program:

F = 3
m = 2
slv a
It searches the available equations (with whatever algorithm you've implemented) and finds an equation

3 - 2*a == 0

i.e. somehow ends up with only one unknown.

Equations of the form
f(x) == 0
has a good chance of being solvable with a numerical method (for example Newton-Rhapson)

You already have a parser, and I can help you with a numerical equation solver (or you can use google), so I think this is quite feasible to implement.

Govtcheez
10-20-2004, 09:46 AM
> Note to mods: Before I get flamed in case this doesn't belong in gd, feel free to move it if it shouldn't be here.

Looks fine to me. It's nice to see stuff like this in here.

okinrus
10-20-2004, 02:42 PM
I'm not sure, as I hadn't thought of solving things exactly the same way you described, but I think my system kind of works similarly that way....
What it does is searches for functions that solve for that particular variable, and then tries to parse the equation. The math solver will return a flag that says whether or not it compiled the math string correctly or not, and if it didn't, it returns a list of the undefined variables. The solver then proceeds to recursively call the solve function until it can solve for that equation. In essence doing that I think you just explained.

Looks like the same general idea. Having the nodes notified when their dependents change might be easier to program and faster. But you should be to have the same result using your idea. Then, as soon as you solve for one own, say x, you would search through the lists of undifined variables, updating each undefined x to be defined. Once an equation has only one undefined variable, then it could be solved.

If you haven't yet done so, you ought to parse the equations once into some sort of intermediate form. Newton's Raphson's method will require that you be able to numerically find the derivative of a function. You would, in effect, need to be able to evaluate the function at a given point.

Sang-drax
10-20-2004, 06:08 PM
Newton's Raphson's method will require that you be able to numerically find the derivative of a function
Perhaps this will do:

float func(float x)
{
return <unknown function>
}

float derive( float(*f)(float) , float x)
{
float h = x/1e6;
return (f(x+h) - f(x)) / h;
}

Then one root of the function f(x)=0 can be found using this method:

float findRoot( float(*f)(float) , float guess)
{
float x = guess;
//Iterate a few times
for (int n=0;n<aFew;++n)
x = x - f(x)/derive(f,x);
return x;
}

Checks need to be added to make sure a proper root is returned.