Double sqrt solution in Matlab? - matlab

I would like to know how can I get both the positive and the negative solution from a sqrt in Matlab.
For example if I have:
sin(a) = sqrt(1-cos(a)^2);

The docs don't say anything specific about always only providing the positive square root but it does seem like a fair assumption in which case you can get the negative square pretty easily like this:
p = sqrt(1-cos(a)^2);
n = -sqrt(1-cos(a)^2);
btw assigning to sin(a) like that is going to create a variable called sin which will hide the sin function leading to many possible errors, so I would highly recommend choosing a different variable name.

MATLAB (and every other programming language that I know of) only returns the principal square root of x when calling sqrt(x) or equivalent.
How you'd write the square root of x mathematically, is
s = ±√x
which is just a shorthand for writing the whole solution set
s = {+√x -√x}
In MATLAB, you'd write it the same as this last case, but with slightly different syntax,
s = [+sqrt(x) -sqrt(x)]
which can be computed more efficiently if you "factor out" the sqrt:
s = sqrt(x) * [1 -1]
So, for your case,
s = sqrt(1-cos(a)^2) * [1 -1]
or, if you so desire,
s = sin(acos(a)) * [1 -1]
which is a tad slower, but perhaps more readable (and actually a bit more accurate as well).
Now of course, if you can somehow find the components whose quotient results in the value of your cosine, then you wouldn't have to deal with all this messy business of course....

sqrt does not solve equations, only gives numerical output. You will need to formulate your equation as you need it, and then you can use sqrt(...) -1*sqrt(...) to give your positive and negative outputs.

Related

Non-element-wise vector division in Matlab returns a scalar! What is it?

I spent over an hour chasing a bug in my code which was leading to a precision error. It turned out that in one of my equations, I had forgotten to divide two vectors element-wise; I had written / instead of ./. Usually Matlab gives an error in these cases, e.g. if you try to multiply two vectors with * instead of .*. But in this case it's happily returning a scalar value! Is this supposed to happen, and does this value have any meaning?
For example,
x = 0 : 0.01 : 1;
y = x/exp(x);
sets y=0.3132.
Yes, this is supposed to happen. You used the matrix right division operator /, and in this particular case it found a scalar value of y that solved the following system of equations in a least-squares sense:
y*exp(x) = x;

What is this code doing? Machine Learning

I'm just learning matlab and I have a snippet of code which I don't understand the syntax of. The x is an n x 1 vector.
Code is below
p = (min(x):(max(x)/300):max(x))';
The p vector is used a few lines later to plot the function
plot(p,pp*model,'r');
It generates an arithmetic progression.
An arithmetic progression is a sequence of numbers where the next number is equal to the previous number plus a constant. In an arithmetic progression, this constant must stay the same value.
In your code,
min(x) is the initial value of the sequence
max(x) / 300 is the increment amount
max(x) is the stopping criteria. When the result of incrementation exceeds this stopping criteria, no more items are generated for the sequence.
I cannot comment on this particular choice of initial value and increment amount, without seeing the surrounding code where it was used.
However, from a naive perspective, MATLAB has a linspace command which does something similar, but not exactly the same.
Certainly looks to me like an odd thing to be doing. Basically, it's creating a vector of values p that range from the smallest to the largest values of x, which is fine, but it's using steps between successive values of max(x)/300.
If min(x)=300 and max(x)=300.5 then this would only give 1 point for p.
On the other hand, if min(x)=-1000 and max(x)=0.3 then p would have thousands of elements.
In fact, it's even worse. If max(x) is negative, then you would get an error as p would start from min(x), some negative number below max(x), and then each element would be smaller than the last.
I think p must be used to create pp or model somehow as well so that the plot works, and without knowing how I can't suggest how to fix this, but I can't think of a good reason why it would be done like this. using linspace(min(x),max(x),300) or setting the step to (max(x)-min(x))/299 would make more sense to me.
This code examines an array named x, and finds its minimum value min(x) and its maximum value max(x). It takes the maximum value and divides it by the constant 300.
It doesn't explicitly name any variable, setting it equal to max(x)/300, but for the sake of explanation, I'm naming it "incr", short for increment.
And, it creates a vector named p. p looks something like this:
p = [min(x), min(x) + incr, min(x) + 2*incr, ..., min(x) + 299*incr, max(x)];

How to generate random matlab vector with these constraints

I'm having trouble creating a random vector V in Matlab subject to the following set of constraints: (given parameters N,D, L, and theta)
The vector V must be N units long
The elements must have an average of theta
No 2 successive elements may differ by more than +/-10
D == sum(L*cosd(V-theta))
I'm having the most problems with the last one. Any ideas?
Edit
Solutions in other languages or equation form are equally acceptable. Matlab is just a convenient prototyping tool for me, but the final algorithm will be in java.
Edit
From the comments and initial answers I want to add some clarifications and initial thoughts.
I am not seeking a 'truly random' solution from any standard distribution. I want a pseudo randomly generated sequence of values that satisfy the constraints given a parameter set.
The system I'm trying to approximate is a chain of N links of link length L where the end of the chain is D away from the other end in the direction of theta.
My initial insight here is that theta can be removed from consideration until the end, since (2) in essence adds theta to every element of a 0 mean vector V (shifting the mean to theta) and (4) simply removes that mean again. So, if you can find a solution for theta=0, the problem is solved for all theta.
As requested, here is a reasonable range of parameters (not hard constraints, but typical values):
5<N<200
3<D<150
L==1
0 < theta < 360
I would start by creating a "valid" vector. That should be possible - say calculate it for every entry to have the same value.
Once you got that vector I would apply some transformations to "shuffle" it. "Rejection sampling" is the keyword - if the shuffle would violate one of your rules you just don't do it.
As transformations I come up with:
switch two entries
modify the value of one entry and modify a second one to keep the 4th condition (Theoretically you could just shuffle two till the condition is fulfilled - but the chance that happens is quite low)
But maybe you can find some more.
Do this reasonable often and you get a "valid" random vector. Theoretically you should be able to get all valid vectors - practically you could try to construct several "start" vectors so it won't take that long.
Here's a way of doing it. It is clear that not all combinations of theta, N, L and D are valid. It is also clear that you're trying to simulate random objects that are quite complex. You will probably have a hard time showing anything useful with respect to these vectors.
The series you're trying to simulate seems similar to the Wiener process. So I started with that, you can start with anything that is random yet reasonable. I then use that as a starting point for an optimization that tries to satisfy 2,3 and 4. The closer your initial value to a valid vector (satisfying all your conditions) the better the convergence.
function series = generate_series(D, L, N,theta)
s(1) = theta;
for i=2:N,
s(i) = s(i-1) + randn(1,1);
end
f = #(x)objective(x,D,L,N,theta)
q = optimset('Display','iter','TolFun',1e-10,'MaxFunEvals',Inf,'MaxIter',Inf)
[sf,val] = fminunc(f,s,q);
val
series = sf;
function value= objective(s,D,L,N,theta)
a = abs(mean(s)-theta);
b = abs(D-sum(L*cos(s-theta)));
c = 0;
for i=2:N,
u =abs(s(i)-s(i-1)) ;
if u>10,
c = c + u;
end
end
value = a^2 + b^2+ c^2;
It seems like you're trying to simulate something very complex/strange (a path of a given curvature?), see questions by other commenters. Still you will have to use your domain knowledge to connect D and L with a reasonable mu and sigma for the Wiener to act as initialization.
So based on your new requirements, it seems like what you're actually looking for is an ordered list of random angles, with a maximum change in angle of 10 degrees (which I first convert to radians), such that the distance and direction from start to end and link length and number of links are specified?
Simulate an initial guess. It will not hold with the D and theta constraints (i.e. specified D and specified theta)
angles = zeros(N, 1)
for link = 2:N
angles (link) = theta(link - 1) + (rand() - 0.5)*(10*pi/180)
end
Use genetic algorithm (or another optimization) to adjust the angles based on the following cost function:
dx = sum(L*cos(angle));
dy = sum(L*sin(angle));
D = sqrt(dx^2 + dy^2);
theta = atan2(dy/dx);
the cost is now just the difference between the vector given by my D and theta above and the vector given by the specified D and theta (i.e. the inputs).
You will still have to enforce the max change of 10 degrees rule, perhaps that should just make the cost function enormous if it is violated? Perhaps there is a cleaner way to specify sequence constraints in optimization algorithms (I don't know how).
I feel like if you can find the right optimization with the right parameters this should be able to simulate your problem.
You don't give us a lot of detail to work with, so I'll assume the following:
random numbers are to be drawn from [-127+theta +127-theta]
all random numbers will be drawn from a uniform distribution
all random numbers will be of type int8
Then, for the first 3 requirements, you can use this:
N = 1e4;
theta = 40;
diffVal = 10;
g = #() randi([intmin('int8')+theta intmax('int8')-theta], 'int8') + theta;
V = [g(); zeros(N-1,1, 'int8')];
for ii = 2:N
V(ii) = g();
while abs(V(ii)-V(ii-1)) >= diffVal
V(ii) = g();
end
end
inline the anonymous function for more speed.
Now, the last requirement,
D == sum(L*cos(V-theta))
is a bit of a strange one...cos(V-theta) is a specific way to re-scale the data to the [-1 +1] interval, which the multiplication with L will then scale to [-L +L]. On first sight, you'd expect the sum to average out to 0.
However, the expected value of cos(x) when x is a random variable from a uniform distribution in [0 2*pi] is 2/pi (see here for example). Ignoring for the moment the fact that our limits are different from [0 2*pi], the expected value of sum(L*cos(V-theta)) would simply reduce to the constant value of 2*N*L/pi.
How you can force this to equal some other constant D is beyond me...can you perhaps elaborate on that a bit more?

Matlab problem with writing equations

i am having problem with writing equations.
r = 25, k= 2, R = 50:25:600, DR = 0.5:0.5:4.0
h= r*[1-cos(asin((sqrt(2*R*DR+DR^2))+r*sin(acos(r-k)/r)/r))]-k
but as a resault i get this: h = 1.9118e+001 +1.7545e+002i.
I just start with Matlab. Thanks
What I get from what you've written is actually
??? Error using ==> mtimes
Inner matrix dimensions must agree.
which is correct because you're trying to multiply two row vectors by one another. Could you please show us the actual code you used?
Anyway, supposing that's dealt with somehow, it looks to me as if you're feeding something to asin that's much bigger than 1. That'll give you complex results. Is the thing you're passing to asin perhaps meant to be divided by R^2 or DR^2 or something of the kind? You have a similar issue a bit later with the argument to acos.
I also suspect that some of your * and ^ and / operators should actually be elementwise ones .*, .^, ./.
If you're trying to do as you said:
so in first equation i used R= 50, DR
= 0.5, r= 25, k=2 and i need to get h. In second equation i used R=75,
DR=1.0, r=25, k=2...for a last
equation i used
R=600,DR=4.0,r=25,k=2.
DR and R need to be the same length... so if R goes between 50 and 600 in increments of 25, DR should go from 0.5 to 12.5 in increments of 0.5, or 0.5 to 4.0 in increments of 0.1522...
once you figure that out, be sure the add a period before every matrix multiplication operation (e.g. * or ^)
EDIT: formula adjusted slightly (bracketing) to reflect success in comment.
When you say you want a table, I guess it is to be an R by DR table (since you have to vectors of different length). To do that you need to use R as a column vector (R' below) and multiply with * (not .*). When R doesn't appear in a term multiply by ones(size(R)) (or use repmat) to get DR into the right shape. To square DR by element, you need DR.^2. There seems to be a misplaced bracket for the acos, surely you divide by r before taking the acos. There must be a division by something like r in the asin (not r^2 because you've taken the sqrt). Finally, the last division by r is redundant as written, since you multiply by r at the same level just before. Anyway, if I do the following:
h= r*(1-cos(asin((sqrt(2*R'*DR+ones(size(R))'*DR.^2)/r)+sin(acos((r-k)/r)))))-k
I get an R by DR table. Results for small R,DR are real; higher R,DR are complex due to the argument of the first asin being >1. The first entry in the table is 4.56, as you require.

Calculating the maximum distance between elements of vector in MATLAB

Let's assume that we have a vector like
x = -1:0.05:1;
ids = randperm(length(x));
x = x(ids(1:20));
I would like to calculate the maximum distance between the elements of x in some idiomatic way. It would be easy to just iterate over all possible combinations of x's elements but I feel like there could be a way to do it with MATLAB's built-in functions in some crazy but idiomatic way.
What about
max_dist = max(x) - min(x)
?
Do you mean the difference between the largest and smallest elements in your vector ? If you do, then something like this will work:
max(x) - min(x)
If you don't, then I've misunderstood the question.
This is an interpoint distance computation, although a simple one, since you are working in one dimension. Really that point which falls at a maximum distance in one dimension is always one of two possible points. So all you need do is grab the minimum value and the maximum value from the list, and see which is farther away from the point in question. So assuming that the numbers in x are real numbers, this will work:
xmin = min(x);
xmax = max(x);
maxdistance = max(x - xmin,xmax - x);
As an alternative, some time ago I put a general interpoint distance computation tool up on the file exchange (IPDM). It is smart enough to special case simple problems like the 1-d farthest point problem. This call would do it for you:
D = ipdm(x,'subset','farthest','result','struct');
Of course, it will not be as efficient as the simple code I wrote above, since it is a fully general tool.
Uhh... would love to have a MATLAB at my hands and its still early in the morning, but what about something like:
max_dist = max(x(2:end) - x(1:end-1));
I don't know if this is what You are looking for.