How to solve this: two functions x = sin(x)/a - c

I tried to solve this equation in different ways but no luck:
Find the number of points of two functions.
f(x) = sin(x)
y = a
at a given a. In this case lets say a = 0.15
sin(x) = ax
= 0.15x
x = sin(x)/0.15
???
Can any one help with this question?
this is the question in the exact words:
Write a C program that would read in the value a and write out all the solutions (i.e. roots) of the equation sin(x) = a*x
NOTE: This equation has for sure one solution: x = 0. However, for low values of a, the line representing the equation y = a*x is sufficiently close to horizontal line to cross the sine wave several times. Your program should calculate and print the number of roots and their values.
HINT: Suppose you are to solve an equation f(x) = 0, where f(x) is a continuous function. Suppose further that you can find two values xlow and xhigh such that f(xlow) < 0 and f(xhigh) > 0 and the function f(x) crosses the x-axis only once somewhere between these values. You could proceed using the so called "binary search" technique, as follows:
Estimate the solution x as x = (xlow + xhigh) / 2.0
If |f(x)| < epsilon then print x as solution and exit; else
If f(x) < 0 then substitute xlow = x else substitute xhigh = x
Go to (1)
Use epsilon = 0.001

You could proceed using the so called "binary search" technique
This is the key to the solution. Actually it is the solution. Let me draw two functions:
f(x) g(x)
/ --
/ --
/ --
/ --
/--
-*
--/
-- /
-- /
^ ^
| |
xlow xhigh
You have xlow and xhigh as an estimate of where f(x) crosses g(x). In your question, f(x) = ax and g(x) = sin(x).
First, let's see why xlow and xhigh make a good estimate. If you notice, at xlow, we have f(x) < g(x) and at xhigh we have f(x) > g(x). Since the functions are continuous, then there is some point somewhere in between where f(x) == g(x).
Now let's look at the middle-point between xlow and xhigh:
f(x) g(x)
/ --
/ --
/ --
/ --
/--
-*
--/
-- /
-- /
^ ^ ^
| | |
xlow xmid xhigh
Now at xmid, we have f(x) > g(x) (in this example). So:
f(xhigh) > g(xhigh)
f(xmid) > g(xmid)
f(xlow) < g(xlow)
Since between xmid and xlow, the functions change bigger-ness-ship (in other words, f(x) - g(x) changes its sign), then the answer is for sure between xlow and xmid (note that there could still be an even number of solutions between xmid and xhigh, but we can't really tell at this point).
So, if we assign xhigh = xmid, we would have:
f(x) g(x)
/--
-*
--/
-- /
-- /
^ ^
| |
xlow xhigh
But this is the same problem as before! Except that we shrank the possible location of the solution by half. Repeating we have:
f(x) g(x)
/--
-*
--/
-- /
-- /
^ ^ ^
| | |
xlow xmid xhigh
f(xhigh) < g(xhigh)
f(xmid) > g(xmid)
f(xlow) > g(xlow)
This time, the sign of f(x) - g(x) changes between xmid and xhigh, so we would do xlow = xmid to cut away the first half of the range which we are not interested in. We get:
f(x) g(x)
/--
-*
--/
^ ^
| |
xlow xhigh
Again, the same problem, except we shrank the range where the solution could possibly be by half.
Repeating this in a while loop, there would be some point where |f(xmid) - g(xmid)| becomes almost zero (say smaller than 0.000001 (or 1e-6) (also note that absolute value)). In that case, we stop searching and we say that that particular xmid is the answer. (See here for why we don't check for equality, but closeness).
There is still one problem. With your particular functions, there could be many cross-sections. How do we find xlow and xhigh? Well, we want the range [xlow, xhigh] to contain only one solution. So we can incrementally find those ranges and find the cross-section in between them.
Assuming a > 0 (and solutions for x > 0), this is how the graph would look like:
----- f(x) = ax
_ _ __*__ _ g(x) = sin(x)
/ \ /_*___----- / \ /
/ *____---*- \ / \ /
|---- | | | | | |
| | | | | |
\ / \ / \ /
\_/ \_/ \_/
So let's see where the solutions can be. For sure, it's not where sin(x) < 0. Then on [2kπ, 2kπ + π/2] and [2kπ + π/2, 2kπ + π] there could be one solution each. The initial [0, π / 2] may or may not have a solution depending on a. So the safest way is to enumerate all such ranges, calculate f(x) - g(x) for both xlow and xhigh and look at their signs. If the sign doesn't change, there is no solution and we can move on. If it does change, we perform the binary search above.
When does the algorithm end? We know that g(x) = sin(x) <= 1 and we know that for a > 0, f(x) = ax is always increasing. So when you have f(xlow) > 1, then for sure there are no more solutions.
The algorithm would thus be:
Main Algorithm:
for k = 0,1,...
xlow = 2kπ
xhigh = 2kπ + π/2
binary_search(xlow, xhigh)
xlow = 2kπ + π/2
xhigh = 2kπ + π
binary_search(xlow, xhigh)
binary_search:
if axlow-sin(xlow) and axhigh-sin(xhigh) have the same sign
return no result in this range
do
xmid = (xhigh + xlow) / 2
diff = axmid - sin(axmid)
if diff and axlow-sin(xlow) have the same sign
xlow = xmid
else
xhigh = xmid
while abs(diff) > epsilon
return xmid
For the cases where a < 0, the solution is similar (except the ranges change to the other half of the sin cycle). By the way, for each x that you find above, -x is also a solution!

Obviously, there can only be solutions for
-1 <= ax <= 1
The monotonicity of the difference function h(x)=sin(x)-ax is the same on all intervals between the roots of the derivative h'(x)=cos(x)-a, and they are also the local maxima and minima of this function. So use the points
arccos(a), 2*pi-arccos(a), 2*pi+arccos(a), 4*pi-arccos(a), 4*pi+arccos(a), ...
as long as they are smaller than 1/abs(a) to define the search intervals. Use inside each of them, as per the answer of Shahbaz, the bisection method, or better the Illinois variant of the regula falsi method.

A brutefore approach without any optimization (therefore a naive approach) would to run a for loop on x, x running from 0 to 2*PI, PI = 22.0/7.0, and loop increment by say 0.001, if you get abs(sin(x) - a*x) < epsilon, where epsilon say equals to some kow value like 0.001 (depends on your granularity), you get it! This would solve your equation sin(x) = a*x

Related

Variable elimination in Bayes Net on a node with single child

If we have a node X, that has a child Y in a Bayes net, why is it correct to express P(Y) as P(Y|X)P(X)? Does it then follow that X is a necessary condition for Y?
Bayes Networks
An edge in a Bayes Network means the variable is conditionally dependent. If nodes are not connected by any path, they are conditionally independent.
Having a node X with a child Y means you need to learn:
Given X is True, what is the probability of Y being True?
Given X is False, what is the probability of Y being True?
More generally: If X can have n values and Y can have m values, then you have to learn n * (m - 1) values. The - 1 is there because the probabilities need to sum up to 1.
Example
Let's stick with the simple case that both variables are binary and use the following from Wikipedia:
Say X is RAIN and Y is SPRINKLER. You want to express Y (SPRINKLER) in terms of X (RAIN).
The Bayes theorem states:
P(Y|X) = P(X|Y) * P(Y) / P(X)
<=> P(Y) = P(Y | X) * P(X) / P(X | Y)
Now we apply the Law of total probability for X. This means, for X we simply go through all possible values:
P(Y) = P(Y | X = true) * P(X = true) +
P(Y | X = false) * P(X = false)
I guess this is what you refer to. P(X=true | Y) = 1, because the X=true means we already know that X=true happened. It doesn't matter what Y is.
To continue our case, we now look up the values in the tables (X is RAIN, Y is SPRINKLER):
P(Y) = 0.01 * 0.2 + 0.4 * 0.8
= 0.322

How to find out the intersection of two coplanar lines in C

I have two 3D lines which lie on the same plane. line1 is defined by a point (x1, y1, z1) and its direction vector (a1, b1, c1) while line2 is defined by a point (x2, y2, z2) and its direction vector (a2, b2, c2). Then the parametric equations for both lines are
x = x1 + a1*t; x = x2 + a2*s;
y = y1 + b1*t; y = y2 + b2*s;
z = z1 + c1*t; z = z2 + c2*s;
If both direction vectors are nonzeros, we can find out the location of intersection node easily by equating the right-hand-side of the equations above and solving t and s from either two of the three. However, it's possible that a1 b1 c1 a2 b2 c2 are not all nonzero so that I can't solve those equations in the same way. My current thought is to deal with this issue case by case, like
case1: a1 = 0, others are nonzero
case2: a2 = 0, others are nonzero
case3: b1 = 0, others are nonzero
...
However, there are so many cases in total and the implementation would become messy. Is there any good ways to tackle this problem? Any reference? Thanks a lot!
It is much more practical to see this as a vector equation. A dot . is a scalar product and A,n,B,m are vectors describing the lines. Point A is on the first line of direction n. Directions are normalized : n.n=1 and m.m=1. The point of intersection C is such that :
C=A+nt=B+ms
where t and s are scalar parameters to be computed.
Therefore (.n) :
A.n+ t=B.n+m.n s
t= (B-A).n+m.n s
And (.m):
A.m+n.m t=B.m+ s
A.m+n.m (B-A).n+(m.n)^2 s=B.m+ s
n.m(B-A).n+(A-B).m=(1-(m.n)^2).s
Since n.n=m.m=1 and n and m are not aligned, (m.n)^2<1 :
s=[n.m(B-A).n+(A-B).m]/[1-(m.n)^2]
t= (B-A).n+m.n s
You can solve this as a linear system:
| 1 0 0 -a1 0 | | x | | x1 |
| 0 1 0 -b1 0 | | y | | y1 |
| 0 0 1 -c1 0 | | z | = | z1 |
| 1 0 0 0 -a2 | | s | | x2 |
| 0 1 0 0 -b2 | | t | | y2 |
| 0 0 1 0 -c2 | | z2 |
x y z is the intersection point, and s t are the coefficients of the vectors. This solves the same equation that #francis wrote, with the advantage that it also obtains the solution that minimizes the error in case your data are not perfect.
This equation is usually expressed as Ax=b, and can be solved by doing x = A^(-1) * b, where A^(-1) is the pseudo-inverse of A. All the linear algebra libraries implement some function to solve systems like this, so don't worry.
It might be vital to remember that calculations are never exact, and small deviations in your constants and calculations can make your lines not exactly intersect.
Therefore, let's solve a more general problem - find the values of t and s for which the distance between the corresponding points in the lines is minimal. This is clearly a task for calculus, and it's easy (because linear functions are the easiest ones in calculus).
So the points are
[xyz1]+[abc1]*t
and
[xyz2]+[abc2]*s
(here [xyz1] is a 3-vector [x1, y1, z1] and so on)
The (square of) the distance between them:
([abc1]*t - [abc2]*s + [xyz1]-[xyz2])^2
(here ^2 is a scalar product of a 3-vector with itself)
Let's find a derivative of this with respect to t:
[abc1] * ([abc1]*t - [abc2]*s + [xyz1]-[xyz2]) (multiplied by 2, but this doesn't matter)
(here the first * is a scalar product, and the other *s are regular multiplications between a vector and a number)
The derivative should be equal to zero at the minimum point:
[abc1] * ([abc1]*t - [abc2]*s + [xyz1]-[xyz2]) = 0
Let's use the derivative with respect to s too - we want it to be zero too.
[abc1]*[abc1]*t - [abc1]*[abc2]*s = -[abc1]*([xyz1]-[xyz2])
-[abc2]*[abc1]*t + [abc2]*[abc2]*s = [abc2]*([xyz1]-[xyz2])
From here, let's find t and s.
Then, let's find the two points that correspond to these t and s. If all calculations were ideal, these points would coincide. However, at this point you are practically guaranteed to get some small deviations, so take and of these points as your result (intersection of the two lines).
It might be better to take the average of these points, to make the result symmetrical.

How to generate a multiplicative space vector in Matlab?

I am trying to generate "automatically" a vector 0.01, 0.03, 0.1, 0.3, 1, 3, 10, 30 (in multiplicative space).
I know linspace and logspace functions, but I couldn't find any similar function for multiplicative space.
Is there any? Otherwise, how to generate a vector like the one I need?
An easy way with bsxfun, also considering multiplication to smaller spaces:
x = [0.01,0.03,0.05] % initial vector, works for various lengths
n = 12; % times it should get multiplied in rising direction
m = 3; % times it should get multiplied in falling direction
Z = bsxfun( #times, x(:), 10.^(-m:n) )
Z = Z(:)
% if preferred, bulky one-liner:
% Z = reshape( bsxfun( #times, x(:), 10.^(-m:n) ) , 1 , [])
I assumed a multiplication with the multiplication vector, e.g.:
10.^(0:n) = 1 10 100 1000 10000 100000 ....
But custom vectors Y are also possible:
Z = bsxfun( #times, x(:), Y(:)' ) Z = Z(:)
A function that might help you achieving this in a very easy and compact way is the Kronecker tensor product kron.
You can use it to rewrite thewaywewalk's answer as:
v = [0.01;0.03;0.05]; % initial vector
emin = -3; % minimal exponent
emax = 12; % maximal exponent
Z = kron(10.^(emin:emax)',v(:))
which should give you the exact same result.
not very efficient but this will generate what you want. inputvec is your initial vector [0.01 0.03] in this case, multiplier is 10. length of the required string n is 8. n should be a multiple of nn (length of the input vector)
function newvec=multispace(n,inputvec,multiplier)
nn=length(inputvec);
newvec=zeros(1,n);
newvec(1:nn)=inputvec;
for i=1:n/nn-1
newvec(i*nn+1:(i+1)*nn)=(newvec((i-1)*nn+1:(i)*nn)).*multiplier;
end
end

Fastest computation of sum x^5 + x^4 + x^3...+x^0 (Bitwise possible ?) with x=16

For a tree layout that takes benefit of cache line prefetching (reading _next_ cacheline is cheap), I need to solve the address calculation in a really fast way. I was able to boil down the problem to:
newIndex = nowIndex + 1 + (localChildIndex*X)
x would be for example: X = 45 + 44 + 43 + 42 +40.
Note: 4 is the branching factor. In reality it will be 16, so a power of 2. This should be useful to use bitwise stuff?
It would be very bad if it would need a loop to calculate X (performancewise) and stuff like division/multiplication. This appeals to be an interesting problem which I wasn’t able to come up with some nice way of computing it.
Since its part of a tree traversal, 2 modes would be possible: absolute calculation, independent of prior calculations AND incremental calculation which starts with a high X being kept in a variable and then some minimal stuff done to it with every deeper level of the tree.
I hope I was able to make clear what the math should do. Not sure if there is a way to do this fast & without loop - but maybe somebody can come up with a really smart solution. I would like to thank everybody for their help - StackOverflow have been a great teacher to me in the past and I hope to be able to give back more in the future, as my knowledge increases.
I'll answer this in increasing complexity and generality.
If x is fixed to 16 then just use a constant value 1118481. Hooray! (Name it, using magical numbers is bad practice)
If you have a few cases known at compile time use a few constants or even defines, for example:
#define X_2 63
#define X_4 1365
#define X_8 37449
#define X_16 1118481
...
If you have several cases known at execution time initialize and use a lookup table indexed with the exponent.
int _X[MAX_EXPONENT]; // note: give it a more meaningful name :)
Initialize it and then just access with the known exponent of 2^exp at execution time.
newIndex = nowIndex + 1 + (localChildIndex*_X[exp]);
How are these values precalculated, or how to calculate them efficiently on the fly:
The sum X = x^n + x^(n - 1) + ... + x^1 + x^0 is a geometric serie and its finite sum is:
X = x^n + x^(n - 1) + ... + x^1 + x^0 = (1-x^(n + 1))/(1-x)
About the bitwise operations, as Oli Charlesworth has stated if x is a power of 2 (in binary 0..010..0) x^n is also a power of 2, and the sum of different powers of two is equivalent to the OR operation. Thus we could make an expression like:
Let exp be the exponent so that x = 2^exp. (For 16, exp = 4). Then,
X = x^5 + ... + x^1 + x^0
X = (2^exp)^5 + ... + (2^exp)^1 + 1
X = 2^(exp*5) + ... + 2^(exp*1) + 1
now using bitwise, 2^n = 1<<n
X = 1<<(exp*5) | ... | 1<<exp | 1
In C:
int X;
int exp = 4; //for x == 16
X = 1 << (exp*5) | 1 << (exp*4) | 1 << (exp*3) | 1 << (exp*2) | 1 << (exp*1) | 1;
And finally, I can't resist to say: if your expression were more complex and you had to evaluate an arbitrary polynomial a_n*x^n + ... + a_1*x^1 + a_0 in x, instead of implementing the obvious loop, a faster way to evaluate the polynomial is using the Horner's rule.

Fast Hypotenuse Algorithm for Embedded Processor?

Is there a clever/efficient algorithm for determining the hypotenuse of an angle (i.e. sqrt(a² + b²)), using fixed point math on an embedded processor without hardware multiply?
If the result doesn't have to be particularly accurate, you can get a crude
approximation quite simply:
Take absolute values of a and b, and swap if necessary so that you have a <= b. Then:
h = ((sqrt(2) - 1) * a) + b
To see intuitively how this works, consider the way that a shallow angled line is plotted on a pixel display (e.g. using Bresenham's algorithm). It looks something like this:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | |*|*|*| ^
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | | | | | | | | | | | |*|*|*|*| | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | | | | | | | |*|*|*|*| | | | | | | | a pixels
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | | | |*|*|*|*| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|*|*|*|*| | | | | | | | | | | | | | | | v
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
<-------------- b pixels ----------->
For each step in the b direction, the next pixel to be plotted is either immediately to the right, or one pixel up and to the right.
The ideal line from one end to the other can be approximated by the path which joins the centre of each pixel to the centre of the adjacent one. This is a series of a segments of length sqrt(2), and b-a segments of length 1 (taking a pixel to be the unit of measurement). Hence the above formula.
This clearly gives an accurate answer for a == 0 and a == b; but gives an over-estimate for values in between.
The error depends on the ratio b/a; the maximum error occurs when b = (1 + sqrt(2)) * a and turns out to be 2/sqrt(2+sqrt(2)), or about 8.24% over the true value. That's not great, but if it's good enough for your application, this method has the advantage of being simple and fast. (The multiplication by a constant can be written as a sequence of shifts and adds.)
For the record, here are a few more approximations, listed in roughly
increasing order of complexity and accuracy. All these assume 0 ≤ a ≤ b.
h = b + 0.337 * a // max error ≈ 5.5 %
h = max(b, 0.918 * (b + (a>>1))) // max error ≈ 2.6 %
h = b + 0.428 * a * a / b // max error ≈ 1.04 %
Edit: to answer Ecir Hana's question, here is how I derived these
approximations.
First step. Approximating a function of two variables can be a
complex problem. Thus I first transformed this into the problem of
approximating a function of one variable. This can be done by choosing
the longest side as a “scale” factor, as follows:
h = √(b2 + a2)
= b √(1 + (a/b)2)
= b f(a/b) where f(x) = √(1+x2)
Adding the constraint 0 ≤ a ≤ b means we are only concerned with
approximating f(x) in the interval [0, 1].
Below is the plot of f(x) in the relevant interval, together with the
approximation given by Matthew Slattery (namely (√2−1)x + 1).
Second step. Next step is to stare at this plot, while asking
yourself the question “how can I approximate this function cheaply?”.
Since the curve looks roughly parabolic, my first idea was to use a
quadratic function (third approximation). But since this is still
relatively expensive, I also looked at linear and piecewise linear
approximations. Here are my three solutions:
The numerical constants (0.337, 0.918 and 0.428) were initially free
parameters. The particular values were chosen in order to minimize the
maximum absolute error of the approximations. The minimization could
certainly be done by some algorithm, but I just did it “by hand”,
plotting the absolute error and tuning the constant until it is
minimized. In practice this works quite fast. Writing the code to
automate this would have taken longer.
Third step is to come back to the initial problem of approximating a
function of two variables:
h ≈ b (1 + 0.337 (a/b)) = b + 0.337 a
h ≈ b max(1, 0.918 (1 + (a/b)/2)) = max(b, 0.918 (b + a/2))
h ≈ b (1 + 0.428 (a/b)2) = b + 0.428 a2/b
Consider using CORDIC methods. Dr. Dobb's has an article and associated library source here. Square-root, multiply and divide are dealt with at the end of the article.
One possibility looks like this:
#include <math.h>
/* Iterations Accuracy
* 2 6.5 digits
* 3 20 digits
* 4 62 digits
* assuming a numeric type able to maintain that degree of accuracy in
* the individual operations.
*/
#define ITER 3
double dist(double P, double Q) {
/* A reasonably robust method of calculating `sqrt(P*P + Q*Q)'
*
* Transliterated from _More Programming Pearls, Confessions of a Coder_
* by Jon Bentley, pg. 156.
*/
double R;
int i;
P = fabs(P);
Q = fabs(Q);
if (P<Q) {
R = P;
P = Q;
Q = R;
}
/* The book has this as:
* if P = 0.0 return Q; # in AWK
* However, this makes no sense to me - we've just insured that P>=Q, so
* P==0 only if Q==0; OTOH, if Q==0, then distance == P...
*/
if ( Q == 0.0 )
return P;
for (i=0;i<ITER;i++) {
R = Q / P;
R = R * R;
R = R / (4.0 + R);
P = P + 2.0 * R * P;
Q = Q * R;
}
return P;
}
This still does a couple of divides and four multiples per iteration, but you rarely need more than three iterations (and two is often adequate) per input. At least with most processors I've seen, that'll generally be faster than the sqrt would be on its own.
For the moment it's written for doubles, but assuming you've implemented the basic operations, converting it to work with fixed point shouldn't be terribly difficult.
Some doubts have been raised by the comment about "reasonably robust". At least as originally written, this was basically a rather backhanded way of saying that "it may not be perfect, but it's still at least quite a bit better than a direct implementation of the Pythagorean theorem."
In particular, when you square each input, you need roughly twice as many bits to represent the squared result as you did to represent the input value. After you add (which needs only one extra bit) you take the square root, which gets you back to needing roughly the same number of bits as the inputs. Unless you have a type with substantially greater precision than the inputs, it's easy for this to produce really poor results.
This algorithm doesn't square either input directly. It is still possible for an intermediate result to underflow, but it's designed so that when it does so, the result still comes out as well as the format in use supports. Basically, the situation in which it happens is that you have an extremely acute triangle (e.g., something like 90 degrees, 0.000001 degrees, and 89.99999 degrees). If it's close enough to 90, 0, 90, we may not be able to represent the difference between the two longer sides, so it'll compute the hypotenuse as being the same length as the other long side.
By contrast, when the Pythagorean theorem fails, the result will often be a NaN (i.e., tells us nothing) or, depending on the floating point format in use, quite possibly something that looks like a reasonable answer, but is actually wildly incorrect.
You can start by reevaluating if you need the sqrt at all. Many times you are calculating the hypotenuse just to compare it to another value - if you square the value you're comparing against you can eliminate the square root altogether.
Unless you're doing this at >1kHz, multiply even on a MCU without hardware MUL isn't terrible. What's much worse is the sqrt. I would try to modify my application so it doesn't need to calculate it at all.
Standard libraries would probably be best if you actually need it, but you could look at using Newton's method as a possible alternative. It would require several multiply/divide cycles to perform, however.
AVR resources
Atmel App note AVR200: Multiply and Divide Routines (pdf)
This sqrt function on AVR Freaks forum
Another AVR Freaks post
Maybe you could use some of Elm Chans Assembler Libraries and adapt the ihypot-function to your ATtiny. You would need to replace the MUL and maybe (i haven't checked) some other instructions.

Resources