Why is my code miscalculating the order of operations? [duplicate] - ruby

This question already has answers here:
Why is division in Ruby returning an integer instead of decimal value?
(7 answers)
Closed 6 years ago.
I've been trying to code a Point of Intersection calculator for myself. For some reason my calculator has either been coded completely wrong or the intended order of operations are not working. Allow me to elaborate.
def point_of_intersection (m1, b1, m2, b2)
if m1 == m2 || m1 - m2 == 0
puts "No Solution"
elsif m1 == m2 || b1 == b2
puts "Infinite Solutions"
end
x = -1 * (b1 - b2) / (m1 - m2)
y = (m1 * x) + b1
puts "The Point Of Intersection is: (#{x}, #{y})"
end
As you can see, the method point_of_intersection takes four parameters:
The slope of the first linear equation (m1) and its y-intercept (b1)
and the slope of the second linear equation (m2) and its y-intercept (b2)
This calculator has worked correctly for me for some cases but for some others it seems to output the wrong numbers. Here are the results of some of my tests
point_of_intersection(1, 4, 2, 6) #Gives (-2,2) which is correct
point_of_intersection(0,5,2,0) #Gives (2,5) when it should be (2.5, 5)
point_of_intersection(1,2,5,3) #Gives (-1, 1) when it should be (-0.25, 1.75)
I know some people may be quick to question whether or not the formula that -1 times the difference in y-intercept divided by the difference in the value of the slopes is right or not. I can guarantee that for every test I performed on the text editor, I also used the exact same formula on paper and got different results.
My best guess is that my computer is somehow performing the order of operations for
x = -1 * (b1 - b2) / (m1 - m2)
however I am not experienced enough to identify how the computer could screw up the operation.
I would appreciate all of your help thank you.

You need to work with floats:
x = (-1 * (b1 - b2) / (m1 - m2)).to_f
y = ((m1 * x) + b1).to_f

Convert your arguments to floats:
def point_of_intersection (m1, b1, m2, b2)
m1 = m1.to_f
b1 = b1.to_f
m2 = m2.to_f
b2 = b2.to_f
if m1 == m2 || m1 - m2 == 0
puts "No Solution"
elsif m1 == m2 || b1 == b2
puts "Infinite Solutions"
end
x = -1 * (b1 - b2) / (m1 - m2)
y = (m1 * x) + b1
puts "The Point Of Intersection is: (#{x}, #{y})"
end
Examples:
point_of_intersection(1, 4, 2, 6)
#The Point Of Intersection is: (-2.0, 2.0)
point_of_intersection(0, 5, 2, 0)
#The Point Of Intersection is: (2.5, 5.0)
point_of_intersection(1, 2, 5, 3)
#The Point Of Intersection is: (-0.25, 1.75)

Related

Invariant induction over horn-clauses with Z3py

I am currently using Z3py to to deduce some invariants which are encoded as a conjunction of horn-clauses whilst also providing a template for the invariant. I'm starting with a simple example first if you see the code snippet below.
x = 0;
while(x < 5){
x += 1
}
assert(x == 5)
This translates into the horn clauses
x = 0 => Inv(x)
x < 5 /\ Inv(x) => Inv(x +1)
Not( x < 5) /\ Inv(x) => x = 5
The invariant here is x <= 5.
I have provided a template for the invariant of the form a*x + b <= c
so that all the solver has to do is guess a set of values for a,b and c that can reduce to x <= 5.
However when I encode it up I keep getting unsat. If try to assert Not (x==5) I get a=2 , b = 1/8 and c = 2 which makes little sense to me as a counterexample.
I provide my code below and would be grateful for any help on correcting my encoding.
x = Real('x')
x_2 = Real('x_2')
a = Real('a')
b = Real('b')
c = Real('c')
s = Solver()
s.add(ForAll([x],And(
Implies(x == 0 , a*x + b <= c),
Implies(And(x_2 == x + 1, x < 5, a*x + b <= c), a*x_2 + b <= c),
Implies(And(a*x + b <= c, Not(x < 5)), x==5)
)))
if (s.check() == sat):
print(s.model())
Edit: it gets stranger for me. If I remove the x_2 definition and just replace x_2 with (x + 1) in the second horn clause as well as delete the x_2 = x_2 + 1, I get unsat whether I write Not( x==5) or x==5 in the final horn clause.
There were two things preventing your original encoding from working:
1) It's not possible to satisfy x_2 == x + 1 for all x for a single value of x_2. Thus, if you're going to write x_2 == x + 1, both x and x_2 need to be universally quantified.
2) Somewhat surprisingly, this problem is satisfiable in the integers but not in the reals. You can see the problem with the clause x < 5 /\ Inv(x) => Inv(x + 1). If x is an integer, then this is satisfied by x <= 5. However, if x is allowed to be any real value, then you could have x == 4.5, which satisfies both x < 5 and x <= 5, but not x + 1 <= 5, so Inv(x) = (x <= 5) does not satisfy this problem in the reals.
Also, you might find it helpful to define Inv(x), it cleans up the code quite a bit. Here is the encoding of your problem with those changes:
from z3 import *
# Changing these from 'Int' to 'Real' changes the problem from sat to unsat.
x = Int('x')
x_2 = Int('x_2')
a = Int('a')
b = Int('b')
c = Int('c')
def Inv(x):
return a*x + b <= c
s = Solver()
# I think this is the simplest encoding for your problem.
clause1 = Implies(x == 0 , Inv(x))
clause2 = Implies(And(x < 5, Inv(x)), Inv(x + 1))
clause3 = Implies(And(Inv(x), Not(x < 5)), x == 5)
s.add(ForAll([x], And(clause1, clause2, clause3)))
# Alternatively, if clause2 is specified with x_2, then x_2 needs to be
# universally quantified. Note the ForAll([x, x_2]...
#clause2 = Implies(And(x_2 == x + 1, x < 5, Inv(x)), Inv(x_2))
#s.add(ForAll([x, x_2], And(clause1, clause2, clause3)))
# Print result all the time, to avoid confusing unknown with unsat.
result = s.check()
print result
if (result == sat):
print(s.model())
One more thing: it's a bit strange to me to write a*x + b <= c as a template, because this is the same as a*x <= d for some integer d.

How can I ask Wolfram Alpha to rearrange an equation?

I have an equation (parentheses are used because of VBA code)
Y=(P/(12E((bt^3)/12))*A
and i know every variables but not "b". Is there any way how to ask Wolfram Alpha to "redefine" (not solve) equation so I can see something like following: I tried to do it manually (but result is not OK)
b=((P/EY)*12A))/t^3
I wish to see how right equation will look.
Original equation is on picture below
where
equation in [,] I simplified by A
I'm not sure if there's a way to tell Wolfram|Alpha to rearrange for a particular variable; in general it will usually try to rearrange for x or y.
If I substitute b for x in your equation and use the following query:
solve Y - (P/(12E((xt^3)/12))*A) = 0
then Wolfram Alpha returns the result you're looking for: x (b) expressed in terms of the other variables. Specifically:
x = A P / (E t^3 Y) for tY != 0 and AP != 0
I know that your question was about Wolfram Alpha, that you do not want to "solve", but here is one way you could do it in Mathematica using your real question. I renamed I into J because I is a reserved symbol in Mathematica for the imaginary unit.
J = b t^3/12;
expr = (P / (12 E J) ) (4 L1^3 + 3 R ( 2 Pi L1^2 + Pi R^2 + 8 L1 R ) + 12 L2 (L1 + R)^2)
Solve[ Y == expr , b]
Result
{{b -> (P (4 L1^3 + 12 L1^2 L2 + 24 L1 L2 R + 6 L1^2 \[Pi] R + 24 L1 R^2 + 12 L2 R^2 + 3 \[Pi] R^3))/(E t^3 Y)}}

What is an algorithm to find intersection of two linear equations?

I'm struggling to figure out an algorithm to find the intersection of two linear equations like:
f(x)=2x+4
g(x)=x+2
I'd like to use the method where you set f (x)=g (x) and solve x, and I'd like to stay away from cross product.
Does anyone have any suggestion to how an algorithm like that would look like?
If your input lines are in slope-intercept form, an algorithm is an over-kill as there is a direct formula to calculate their point of intersection. It's given on a Wikipedia page and you can understand it as explained below.
Given the equations of the lines: The x and y coordinates of the
point of intersection of two non-vertical lines can easily be found
using the following substitutions and rearrangements.
Suppose that two lines have the equations y = ax + c and y = bx + d where a
and b are the slopes (gradients) of the lines and where c and d are
the y-intercepts of the lines. At the point where the two lines
intersect (if they do), both y coordinates will be the same, hence the
following equality:
ax + c = bx + d.
We can rearrange this expression in order to extract the
value of x,
ax - bx = d - c, and so,
x = (d-c)/(a-b).
To find the y coordinate, all we need to do is substitute the value of x into > either one of the two line equations. For example, into the first:
y=(a*(d-c)/(a-b))+c.
Hence, the Point of Intersection is {(d-c)/(a-b), (a*(d-c)/(a-b))+c}
Note: If a = b then the two lines are parallel. If c ≠ d as well, the lines
are different and there is no intersection, otherwise the two lines are
identical.
Given:
ax + b = cx + d
ax = cx + d - b
ax - cx = d - b
x(a - c) = d - b
Therefore, x = (d - b) / (a - c)
In your example, let a = 2, b = 4, c = 1 d = 2
x = (2 - 4) / (2 - 1)
x = -2 / 1
x = -2
General solution. Let
f(x) = a1x + b1 ....... g(x) = a2x + b2
Special cases:
a1 == a2 and b1 == b2 : lines coincide
a1 == a2 and b1 != b2 : lines are parallel, no intersection
General case: a1 != a2
X = (b2 - b1) / (a1 - a2) ....and... Y = (a1b2 - a2b1) / (a1 - a2)
I don't remember what cross products are in the context of equations.
One way to solve these is to set them equal to each other, solve for x, then use that value to solve for y:
2x + 4 = x + 2
2x + 2 = x
x = -2
y = f(x)
= g(x)
= x + 2
= -2 + 2
= 0
Solution: (-2, 0)

Algorithm: Triangle with two constraints, each corner on a given line

Some time ago I asked a question on math.stackexchange and got an answer. I have difficulties deriving an algorithm from that answer because my background is in design and hope some of you can help me.
The original question with visual sketch and possible answer are here:
https://math.stackexchange.com/questions/667432/triangle-with-two-constraints-each-corner-on-a-given-line
The question was: Given 3 3-dimensional lines (a, b and c) that coincide in a common point S and a given Point B on b, I'm looking for a point A on a and a point C on c where AB and BC have the same length and the angle ABC is 90 degrees.
I will have to implement this algorithm in an imperative language, any code in C++, Java, imperative pseudo-code or similar is fine.
Also, different approaches to this problem are equally welcome. Plus: Thanks for any hints, if the complete solution is indeed too time-consuming!
The two key formulas are
(I've replied the derivation for the formulas in the mathematics stack exchange site)
Substituting the first in the second gives in the end a 4th degree equation that is quite annoying to solve with a closed form. I've therefore used instead a trivial numerical solver in Python:
# function to solve (we look for t such that f(t)=0)
def f(t):
s = (t*cB - B2) / (t*ac - aB)
return s*s - 2*s*aB - t*t + 2*t*cB
# given f and an interval to search generates all solutions in the range
def solutions(f, x0, x1, n=100, eps=1E-10):
X = [x0 + i*(x1 - x0)/(n - 1) for i in xrange(n)]
Y = map(f, X)
for i in xrange(n-1):
if (Y[i]<0 and Y[i+1]>=0 or Y[i+1]<0 and Y[i]>=0):
xa, xb = X[i], X[i+1]
ya, yb = Y[i], Y[i+1]
if (xb - xa) < eps:
# Linear interpolation
# 0 = ya + (x - xa)*(yb - ya)/(xb - xa)
yield xa - ya * (xb - xa) / (yb - ya)
else:
for x in solutions(f, xa, xb, n, eps):
yield x
The search algorithm samples the function in the interval and when it finds two adjacent samples that are crossing the f=0 line repeats the search recursively between those two samples (unless the interval size is below a specified limit, approximating the function with a line and computing the crossing point in that case).
I've tested the algorithm generating random problems and solving them with
from random import random as rnd
for test in xrange(1000):
a = normalize((rnd()-0.5, rnd()-0.5, rnd()-0.5))
b = normalize((rnd()-0.5, rnd()-0.5, rnd()-0.5))
c = normalize((rnd()-0.5, rnd()-0.5, rnd()-0.5))
L = rnd() * 100
B = tuple(x*L for x in b)
aB = dot(a, B)
cB = dot(c, B)
B2 = dot(B, B)
ac = dot(a, c)
sols = list(solutions(f, -1000., 1000.))
And there are cases in which the solutions are 0, 1, 2, 3 or 4. For example the problem
a = (-0.5900900304960981, 0.4717596600172049, 0.6551614908475357)
b = (-0.9831451620384042, -0.10306322574446096, 0.15100848274062748)
c = (-0.6250439408232388, 0.49902426033920616, -0.6002456660677057)
B = (-33.62793897729328, -3.5252208930692497, 5.165162011403056)
has four distinct solutions:
s = 57.3895941365 , t = -16.6969433689
A = (-33.865027354189415, 27.07409541837935, 37.59945205363035)
C = (10.436323283003153, -8.332179814593692, 10.022267893763457)
|A - B| = 44.5910029061
|C - B| = 44.5910029061
(A - B)·(C - B) = 1.70530256582e-13
s = 43.619078237 , t = 32.9673082734
A = (-25.739183207076163, 20.5777215193455, 28.577540327140607)
C = (-20.606016281518986, 16.45148662649085, -19.78848391300571)
|A - B| = 34.5155582156
|C - B| = 34.5155582156
(A - B)·(C - B) = 1.13686837722e-13
s = -47.5886624358 , t = 83.8222109697
A = (28.08159526800866, -22.450411211385674, -31.17825902887765)
C = (-52.39256507303229, 41.82931682916268, -50.313918854788845)
|A - B| = 74.0747844969
|C - B| = 74.0747844969
(A - B)·(C - B) = 4.54747350886e-13
s = 142.883074325 , t = 136.634726869
A = (-84.31387768560096, 67.4064705656035, 93.61148799140805)
C = (-85.40270813540043, 68.1840435123674, -82.01440263735996)
|A - B| = 124.189861967
|C - B| = 124.189861967
(A - B)·(C - B) = -9.09494701773e-13
Write two quadratic equations for lambda, mu unknowns (just above matrix forms).
Solve this system with paper, pen and head, or with any mathematical software like Maple, Mathematica, Matlab, Derive etc. You will have 4th order equation. It has closed-form solution - apply Ferrari or Kardano method and get real roots, find mu, lambda, then point coordinates.

How to reflect a line over another line

For a collision algorithm I am developing, I need to find out how to reflect a line over another.
Line 1:
y=ax+b
Line 2:
y=cx+d
Line 3:
(a result of reflecting line 1 over line 2) y=ex+f
Is there any algebraic way to determine e and f in terms of a, b, c, and d?
I have run over this exact same problem before. Stay with me here...
This problem involves two parts:
1. Find the point at which they intersect
to find where two lines intersect, we use the two equations of the lines:
y = M1x + B1
y = M2x + B2
Using substitution:
M1x + B1 = M2x + B2
M1x - M2x = B2 - B1
x(M1 - M2) = B2 - B1
x = (B2 - B1) / (M1 - M2)
To find the y value, just plug it in:
y = M1x + B1
2. Find the slope of the line from the other two slopes.
The second is far trickier. Using trigonometry, it is not impossible.
Let L1 be the "base line." (With a slope of M1)
Let L2 be the line that is to be reflected over the "base line." (With a slope of M2)
Let L3 be our resulting line. (With a slope of M3)
The equation I used is as follows:
double M3 = ((2 * M1) + (M2 * pow(M1, 2)) - M2) / (2 * M1 * M2 - pow(M1, 2) + 1);
Straight from my C code.
It is important to note that both slopes should be defined. You can use L'Hopital's rule to get an equation when one of the slopes is approaching infinity.
ONWARD WITH THE EXPLANATION!
Here is a crude drawing of three lines.
L2 is reflected over L1, resulting in L3. Drawing is not exact.
The angle between L1 and L2, as well as L2 and L3, is labelled as R.\
Here are the facts:
M1 = tan(A1)
M2 = tan(A2)
M3 = tan(A3)
This comes from the definition of tangent.
A3 = R + A1
This is a little trickier to see, but if you draw a horizontal line at the point of intersection it becomes obvious.
Thus, our goal is to find tan(A3). To accomplish this, we need to find R. As we can see, R can be found in a triangle with A2 and the supplement of A1 as the other angles. Thus, we know:
R + (180 - A1) + A2 = 180
R - A1 + A2 = 0
R = A1 - A2
Let's take the tangent of both sides:
tan(R) = tan(A1 - A2)
From trigonometry, we know:
tan(R) = (tan(A1) - tan(A2)) / (1 + tan(A1)tan(A2))
R = arctan((tan(A1) - tan(A2) / (1 + tan(A1)tan(A2))
Arctan being inverse tangent. From our earlier formula, A3 = R + A1, we get:
A3 = arctan((tan(A1) - tan(A2) / (1 + tan(A1)tan(A2)) + A1
A3 = arctan((M1 - M2) / (1 + M1*M2)) + A1
But we don't want A3. We want tan(A3). So again, we take the tangent of both sides.
tan(A3) = M3 = tan(arctan((M1 - M2) / (1 + M1*M2)) + A1)
M3 = tan(arctan((M1 - M2) / (1 + M1*M2))) + tan(A1) / (1 - tan(arctan((M1 - M2) / (1 + M1*M2))) * tan(A1))
Unfortunately, that's disgustingly hideous. Replacing tangents with slopes and simplifying, we get
M3 = ((M1 - M2) / (1 + M1*M2)) + M1 / (1 - ((M1 - M2)/(1 + M1*M2)) * M1)
M3 = (M1 - M2 + M1*(1 + M1*M2)) / (1 + M1*M2 - M1*M1 + M1*M2)
M3 = (M1^2 * M2 + 2*M1 - M2) / (1 + 2*M1*M2 - M1^2)
Which is the exact same as the formula above. Sorry about all the ugly math. When M2 is completely vertical, you can use L'Hopital's rule to get
M3 = (M1^2 - 1) / 2*M1
If anyone is so inclined, check my math. But I'm tired right about now.
Assuming the two lines are not parallel to each other
Step 1:
First find the intersection of the line y = ax + b with line y = cx + d , that is by solving comes out to be
m = (d - b) / (c - a)
Step 2:
The final line has point of the form (x , ex + f) , so wjat we know is the line joining the point and the corresponding image is perpendicular to the mirror line AND the the midpoint of the first point and its image lies on the mirror line. Solving for first requirement ....
(Slope of line joining point and its image) * (Slope of the mirror line) = -1
we get ...
c * (e*pt + f - a*n - b)/( pt - n ) = -1 -----> The first equation .
Then the midpoint of the point and its image lie on the central line , i.e.
Y coordinate of the midpoint - ( c* x coordinate of midpoint + d) = 0
y coordinate of midpoint = (a*n + e*pt) / 2 and x coordinate = ( pt + n) / 2
putting it above we get...
(a*n + e*pt)c - c( pt + n) - 2d =0 ----> second equation
3.
now the point and its image make equal angles from the intersection point .... a simple way of saying that angle between mirror line , point line and image line , point line being equal ... therefore ... the tangent of angle between lines mI and mM is equal to that of mM and mP
equating we get
( mM + mP ) / ( 1 + mp*mM) =( mI - mM )/ (1 + mI*mM)
where mM = c , mI = e, and mP = a -----> third equation
put it in their respective
places you get three equations in three unknowns , pt , e and f and solve ... just x in place of n earlier and there you have your e , f in terms of a , b , c , d.
Solve it yourselves ....
However if they are parallel its simple , you have two equations in two variables use the midpoint method
Yet another method:
Matrix of affine transformation for reflection relatively to line y=ax+b (works for non-vertical lines!).
Let's pa = 1+a^2, ma = 1-a^2, then matrix is (from Nikulin's Computer Geometry book)
ma/pa 2a/pa 0
2a/pa -ma/pa 0
-2ab/pa 2b/pa 1
So we can get two arbitrary points at second line, apply this transform, and calculate new line equation

Resources