Create an increasing integer alternating sequence in MATLAB / Octave - matlab

I'm trying to find a way to create a number pattern like the one below
0,1,-2,3,-4,5....
Please note: it needs to go to 200000, but I will be splitting them up into groups of 2000.
I found a formula that looks like it would work on http://oeis.org/A181983, but when I create the formula in MATLAB / Octave, the numbers don't match up:
f_num= #(x) x / (1 + x)^2;
numval = f_num(1)
numval = 0.25000
Is there another way I should be doing this?

Method #1 - Using (-1)^x
Just use a linear increment operator to go from 0 to 200000 and multiply the sequence by (-1)^(x+1) to allow the sign of the sequence to alternate:
x = 0:200000;
y = ((-1).^(x+1)) .* x;
The addition of the +1 is important so that the even positions get a positive sign while the odd positions get a negative sign.
Method #2 - Using indexing
Alternatively, you can declare the same array from 0 to 200000, index into every even position and negate the sign:
x = 0:200000;
x(2:2:end) = -x(2:2:end);
Method #3 - Using trigonometry and integers
One more to throw into the mix. You know that for cos(x*pi), the output is -1 when x is odd and the output is 1 when x is even. We need to flip this for your case and ultimately use this alternating sequence to multiply with the same array going from 0 to 200000, and therefore:
x = 0:200000;
y = (-cos(x*pi)).*x;
Aside
Interestingly enough, (-1)^x is also equal to exp(i*pi*x) for all values of x that are integer. We can verify this by using Euler's formula where: exp(i*pi*x) = cos(pi*x) + i*sin(pi*x). Since i*sin(pi*x) = 0 for all x belonging to an integer, we really get exp(i*pi*x) = cos(pi*x). Substituting even numbers of x will give us 1 while odd numbers of x will give us -1, and hence exp(i*pi*x) = cos(pi*x) = (-1)^x for all x belonging to integers.
Also, (-1)^(x+1) = -(-1)^x = -cos(x*pi) for all x belonging to integers and so the first method is really equal to the third method anyway!

try
f_num= #(x) x * (-1)^(x+1);

Related

MatLab :: Assume and find different possible unknown variables of inequalities ,

I have inequalities with two unknown variables. So how could I assume one variable with different values and get the others?
For instance: -15<10*x+2*y<20.
How could I assume x=2, 3, and so on, and then find answer of (y) depending on the value of (x)?
I have been trying to apply the assume and find commands, but unfortunately, I could not. So I hope anyone could help me, please.
Looking forward to hearing from you.
I am new to Matlab, so I have been trying to apply solve, assume, and find commands
clear all;
clc;
syms x y real;
z=solve(-15<10*x+2*y,[x y])
b=solve(10*x+2*y<20,[x y])
yinterval = [ z,b]
I expect the output: to assume x=different numbers and then y= be a list of possible results depending on the value of x
Thanks,
For each value of x, technically there are infinite values of y that satisfy those equations, so for my solution, I assumed x and y were integer values. As well, it appears that you want to give the program a set of x values and have it calculate y values for each x value. Instead of using the solve command, we can simply use a couple of loops to find all satisfactory integer values of y for each value of x.
To start, we need to make a results matrix to store each x,y pair that satisfies the equations you've given. This is called pre-allocation, as we're pre-allocating the space needed to store our answers. Using the equations, we can deduce that there will be 17 satisfactory y values per x. So, our first two lines of code will be initializing the desired x-values and the results matrix:
xVec = 1:5; %x-vector, change this to whatever x-values you want to test
results = zeros(length(xVec)*14, 2); %results matrix
Note: If you decide to iterate x or y by a value different than +1 (more on that later), you'll need to come up with a different method of creating this results matrix. You could also just not pre-allocate the results matrix, but your code will run slower as the size of the results matrix will be changing on each loop.
Next are the loops. Admittedly, this is not the most elegant solution, but it'll get the job done. First, we need an index to keep up with where we are in our results matrix. This is pretty easy, we'll just call it index and start at 1 (since MATLAB indexes from 1 in matrices. Remember that!):
index = 1; %index for results matrix
Next, we need to loop through each value in our x-vector. Simply use a for loop:
for x = xVec
...
For each value of x, there is a minimum value of y. This value can be solved for in
-15 < 10*x + 2*y --> -14 = 10*x + 2*y_min
So, simply solving for y gives us our next line of code:
y = -7 - 5*x; %solving for y
Note: each time we iterate x in our for loop, a new starting value of y will be calculated.
Finally, we need to loop through values of y that still satisfy the inequalities given. This is performed through use of a while loop:
while 10*x + 2*y > -15 && 10*x + 2*y < 20
...
Note: && is the 'and' statement while using loops. You can't use a single equation for this (i.e. you can't say something like -15 < x < 20, you have to split them up using &&).
Since we solved for the first value of y, we can go ahead and record the current x and y values in our results matrix:
results(index, :) = [x, y]; %storing current x- and y-values
Then, we need to iterate y, as otherwise we'd be stuck in this while-loop forever.
y = y + 1;
Note: You can iterate this y-value with whatever amount you want. I chose to iterate by 1 each time, as I assumed you wanted to find integer values. Just change the +1 to whatever value you want.
Finally, we iterate our index, so that the next pair of x,y values that satisfy our equations don't overwrite our previous solutions.
index = index + 1;
All that's left is to close our loops and run! As I said, this isn't the most efficient solution, so I wouldn't use this for large amounts of x- and y-values. As well, like with iterating the y-values, the x-values can have any 'step-size' you want. As it's coded currently, it jumps +1 between each x, but changing the xVec input to any vector will still work (ex. xVec = 1:0.1:5; iterates the x-value by +0.1 each step instead of +1).
Here's the code all together, sans comments (since I wrote the comments while making the above code snippets):
xVec = 1:5;
results = zeros(length(xVec)*14, 2);
index = 1;
for x = xVec
y = -7 - 5*x;
while 10*x + 2*y > -15 && 10*x + 2*y < 20
results(index, :) = [x, y];
y = y + 1;
index = index + 1;
end
end
Let me know if you have any questions!

Generating all ordered samples with replacement

I would like to generate an array which contains all ordered samples of length k taken from a set of n elements {a_1,...,a_n}, that is all the k-tuples (x_1,...,x_k) where each x_j can be any of the a_i (repetition of elements is allowed), and whose total number is n^k.
Is there a built-in function in Matlab to obtain it?
I have tried to write a code that iteratively uses the datasample function, but I couldn't get what desired so far.
An alternative way to get all the tuples is based on k-base integer representation.
If you take the k-base representation of all integers from 0 to n^k - 1, it gives you all possible set of k indexes, knowing that these indexes start at 0.
Now, implementing this idea is quite straightforward. You can use dec2base if k is lower than 10:
X = A(dec2base(0:(n^k-1), k)-'0'+1));
For k between 10 and 36, you can still use dec2base but you must take care of letters as there is a gap in ordinal codes between '9' and 'A':
X = A(dec2base(0:(n^k-1), k)-'0'+1));
X(X>=17) = X(X>=17)-7;
Above 36, you must use a custom made code for retrieving the representation of the integer, like this one. But IMO you may not need this as 2^36 is quite huge.
What you are looking for is ndgrid: it generates the grid elements in any dimension.
In the case k is fixed at the moment of coding, get all indexes of all elements a this way:
[X_1, ..., X_k] = ndgrid(1:n);
Then build the matrix X from vector A:
X = [A(X_1(:)), ..., A(X_k(:))];
If k is a parameter, my advice would be to look at the code of ndgrid and adapt it in a new function so that the output is a matrix of values instead of storing them in varargout.
What about this solution, I don't know if it's as fast as yours, but do you think is correct?
function Y = ordsampwithrep(X,K)
%ordsampwithrep Ordered samples with replacement
% Generates an array Y containing in its rows all ordered samples with
% replacement of length K with elements of vector X
X = X(:);
nX = length(X);
Y = zeros(nX^K,K);
Y(1,:) = datasample(X,K)';
k = 2;
while k < nX^K +1
temprow = datasample(X,K)';
%checknew = find (temprow == Y(1:k-1,:));
if not(ismember(temprow,Y(1:k-1,:),'rows'))
Y(k,:) = temprow;
k = k+1;
end
end
end

how to define an array with fractional index number

Like suppose that I need to create a function named pressure denoted by p (a 2-D matrix) which depends on 2 variables r and z.
u, v, w are linear matrices which also depend on 2 variables r and z.
r and z are linear matrix defined below take i={1,2,3,4,5,6,7,8,9,10}
r(i)=i/10
z(i)=i/10
u(i) = 2*r(i) + 3*z(i)
v(i) = 8*r(i) + 4*z(i)
w(i) = 3*r(i) + 2*z(i)
p = p(r,z) %, which is given as,
p(r(i),z(j)) = 2*v(i) - 4*u(i) + w(j)
Now suppose the value of p at a given location (r,z) say (0.4,0.8) is needed, I want that if I give the input p(0.4,0.8), I get the result.
In your case the easiest way is to convert the fractional numbers to integers by multiplying by 10.
This way the location (r,z) = (0.4, 0.8) will become (4,8).
If you don't want to remember every time to provide the locations multiplied by 10, just create a function that will do it for you, so you can call the function with the fractional location.
If your matrices are linear, you will always find a multiplying factor to get rid of the fractional coordinates.
Not entirely sure what you mean here, but if your matrix is only defined in the indices you give (i.e. you only want to draw values from the fixed set of indices you defined), then this should do it:
% the query indices
r_i = 0.4;
z_i = 0.8;
value = p(r_i*10,z_i*10);
if you want to look at values between the ones you defined, you need to look at interpolation:
% the query indices
r_i = 0.46;
z_i = 0.84;
value = interp2(r,z, p, r_i, z_i);
(I may have gotten r and z in that last function in the wrong order, try it out).

Using find on non-integer MATLAB array values

I've got a huge array of values, all or which are much smaller than 1, so using a round up/down function is useless. Is there anyway I can use/make the 'find' function on these non-integer values?
e.g.
ind=find(x,9.5201e-007)
FWIW all the values are in acceding sequential order in the array.
Much appreciated!
The syntax you're using isn't correct.
find(X,k)
returns k non-zero values, which is why k must be an integer. You want
find(x==9.5021e-007);
%# ______________<-- logical index: ones where condition is true, else zeros
%# the single-argument of find returns all non-zero elements, which happens
%# at the locations of your value of interest.
Note that this needs to be an exact representation of the floating point number, otherwise it will fail. If you need tolerance, try the following example:
tol = 1e-9; %# or some other value
val = 9.5021e-007;
find(abs(x-val)<tol);
When I want to find real numbers in some range of tolerance, I usually round them all to that level of toleranace and then do my finding, sorting, whatever.
If x is my real numbers, I do something like
xr = 0.01 * round(x/0.01);
then xr are all multiples of .01, i.e., rounded to the nearest .01. I can then do
t = find(xr=9.22)
and then x(t) will be every value of x between 9.2144444444449 and 9.225.
It sounds from your comments what you want is
`[b,m,n] = unique(x,'first');
then b will be a sorted version of the elements in x with no repeats, and
x = b(n);
So if there are 4 '1's in n, it means the value b(1) shows up in x 4 times, and its locations in x are at find(n==1).

Set all nonzero matrix elements to 1 (while keeping the others 0)

I have a mesh grid defined as
[X, Y, Z] = meshgrid(-100:100, -100:100, 25); % z will have more values later
and two shapes (ovals, in this case):
x_offset_1 = 40;
x_offset_2 = -x_offset_1;
o1 = ((X-x_offset_1).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
o2 = ((X-x_offset_2).^2./(2*Z).^2+Y.^2./Z.^2 <= 1);
Now, I want to find all points that are nonzero in either oval. I tried
union = o1+o2;
but since I simply add them, the overlapping region will have a value of 2 instead of the desired 1.
How can I set all nonzero entries in the matrix to 1, regardless of their previous value?
(I tried normalized_union = union./union;, but then I end up with NaN in all 0 elements because I'm dividing by zero...)
Simplest solution: A=A~=0;, where A is your matrix.
This just performs a logical operation that checks if each element is zero. So it returns 1 if the element is non-zero and 0 if it is zero.
First suggestion: don't use union as a variable name, since that will shadow the built-in function union. I'd suggest using the variable name inEitherOval instead since it's more descriptive...
Now, one option you have is to do something like what abcd suggests in which you add your matrices o1 and o2 and use the relational not equal to operator:
inEitherOval = (o1+o2) ~= 0;
A couple of other possibilities in the same vein use the logical not operator or the function logical:
inEitherOval = ~~(o1+o2); % Double negation
inEitherOval = logical(o1+o2); % Convert to logical type
However, the most succinct solution is to apply the logical or operator directly to o1 and o2:
inEitherOval = o1|o2;
Which will result in a value of 1 where either matrix is non-zero and zero otherwise.
There is another simple solution, A=logical(A)