Minimization of convex stochastic values - matlab

I have a variable of equidistant values (suppose values=0:1e-3:1). I want to get the value and its correspondent index from values which is closest to a uniformly random value (suppose x=rand).
I could do [value,vIdx]=min(abs(values-x)), which would be the simplest minimization I could do. Unfortunately the min function won't take advantage from one property from the data, that is to be convex. I don't need to search all indexes, because as soon as find an index that is no more lesser than the previous I've found the global minimum. Said that, I don't want to substitute the matlab min function for a loop that would be slower depending on how distant it is from the value I will start. There are many methods that could be used, as the golden section, but I am not sure if using matlab fmincon would be faster than the min method.
Does anyone have any hints/ideas how to get the required value faster than using the described min method? I'll check the time performance when I have time, but if someone knows a good answer a priori, please let me know.
Possible Application: Snap to nearest graphic data

Since your points are equidistant you can use the value x to find the index:
vIdx = 1+round(x*(numel(values)-1));
The idea is that you are dividing the interval [0, 1] into numel(values)-1 equally sized intervals. Now by multiplying x by that number you map the interval to [0, numel(values)-1] where your points are mapped to integer values. Now using round you get the closest one and by adding 1 you get the one-based index that MATLAB requires.

Related

min/max of a function without built in operators nor for/while/if?

We have to determine the min/max values of a 1x6000 array without using the operators mentionned in the title. We have to use algorithms learned in class, but I don't see how that would translate to matlab, as I will need to do a certain number of iterations before I get the right answer.
We learned the bisection method, muller method, newton method, fixed point method, etc.
Please don't write the code, as this is my homework, and I'm trying to learn something, but if you could guide me in the right direction...
Thank you.
Disclaimer
I'm a bit confused on why you can't use a for or while loop because Newton's method, the bisection method or any fixed point method is an iterative algorithm which requires loops. As such, this answer assumes that other than using these methods that are using loops, no other loops are allowed.
Since you're allowed to use Newton's method or the bisection method, remember that these methods find the root of a function or where the function output is equal to 0. Also remember that when you find the derivative and see where the values are equal to 0, this tells you what critical points (min and max) are part of the function. Therefore, if you ran Newton's or the bisection method on the derivative of your function, you would then be able to determine the critical points and hence where the min or max are. However, these don't tell if you the points are at a minimum or a maximum. Therefore, you'd have to take a look at the second derivative and examine the sign at these points. If the sign is positive, it is a minimum and if the sign is negative, it is a maximum.
Because you only have an array of points and not the actual function itself, have a look at diff which computes the discrete approximation to the derivative (i.e. a finite difference) for an array. Also when you are specifying points in the array that don't belong to an integer values as it will be inevitable with Newton's or the bisection, have a look at interp1 to interpolate and find the approximate value in between integer points.
I'll do only the case for Newton's method. You can derive a similar set of rules for the bisection method. Recall that Newton's method is defined such that:
(source: mit.edu)
x_i is the current guess of the root while x_{i+1} is the next guess of the root. f(x_i) is the function evaluated at x_i while f'(x_i) is the derivative of the function. Since you want to find the critical points where the derivative is equal to 0 and not the original function, f(x_i) is now f'(x_i) and its derivative is simply the second derivative or f''(x_i).
Given that X is the array of points you have, the pseudocode could look something like this:
Use dx = diff(X, 1) to compute the first derivative and dx2 = diff(X, 2) to compute the second derivative.
Specify an initial guess of the root, xp, of the derivative, or where you think the minimum or maximum point is. Starting at the halfway point where xp = floor(numel(X)/2); may be a good place to start.
Run Newton's method N amount of times or when the difference between successive guesses of the root is less than some threshold on diff(X, 1) using xp as the initial guess and updating xp to be used for future guesses. For each guess of the root, use interp1 to determine the approximate value of the derivative at this point. Therefore, the Newton's update rule would look something like:
i1 = interp1(1:numel(dx), dx, xp, 'linear');
i2 = interp1(1:numel(dx2), dx2, xp, 'linear');
xp = xp - (i1 / i2);
i1 is the derivative evaluated at the current guess xp while i2 is the second derivative evaluated at the current guess xp. We then do the update.
xp will now contain the location of where the critical point is. However, you will probably have floating point precision here so using this to index into your original array X to get the minimum or maximum is not valid. One thing that I can suggest as a heuristic would be to perhaps round xp which makes sense because for the decimal floating part of the final root to be < 0.5 would suggest that you lean towards the left of the value where as going >= 0.5 would suggest that you lean towards the right.
Once Newton's method converges, you need to check if the value is a minimum or maximum. Since you can't use if, a trick here would be to have your function output a two element array where both values are initialized to NaN. Depending on what the sign of the second derivative of this is at xp, you can manually create the right index to populate only one element of this array while leaving the other element as NaN. The position that is not NaN should tell you if it's a minimum or maximum. I'll stick with the convention where the first element is a minimum and the second element is a maximum. You can concretely determine this logic by:
minmax = [NaN NaN];
ind = interp1(1:numel(dx2), dx2, xp, 'linear') > 0 + 1;
minmax(ind) = X(round(xp));
The second statement calculates the index of where we need to populate the value in this array. It states that if the sign is positive, the value should be equal to 1 and if it isn't, the value should be equal to 0. Adding an offset of 1 will now mean that the index will either be 1 or 2 where 1 is the minimum value and 2 is the maximum.
What if you have more than one minimum or maximum?
It is possible where you could have more than one minimum or maximum that has the same value over the entire array, or you want to find both the minimum and maximum. In that case, you'd have to do this recursively where you first run Newton's method to find the minimum and maximum point. Then you'd have to split up your array into two halves where the first half is the first point in X up to this minimum/maximum point and the second half is the minimum/maximum point up to the end. You'd also have to make the initial guesses the middle of each array to ensure that you're not just going to return the maximum or minimum values possibly being located at the extremities of the array. If you want to achieve this without a loop, you will have to use recursion. If you think about it, this is almost the same as using merge sort. I wouldn't be surprised if you could use merge sort's logic in a way that would help you define the minimum and maximum values or specifically use recursion. However since you stated you can only used fixed-point methods, I didn't suggest to use recursion to begin with.
I've given some code hints, but as you said you don't want full code so this should hopefully get you started. Be advised that there may be some numerical inaccuracies due to diff and this is algorithm I haven't tried or tested. It's an idea that I thought of while reading your question.
Good luck!

Optimization algorithm in Matlab

I want to calculate maximum of the function CROSS-IN-TRAY which is
shown here:
So I have made this function in Matlab:
function f = CrossInTray2(x)
%the CrossInTray2 objective function
%
f = 0.0001 *(( abs(sin(x(:,1)).* sin(x(:,2)).*exp(abs(100 - sqrt(x(:,1).^2 + x(:,2).^2)/3.14159 )) )+1 ).^0.1);
end
I multiplied the whole formula by (-1) so the function is inverted so when I will be looking for the minimum of the inverted formula it will be actually the maximum of original one.
Then when I go to optimization tools and select the GA algorithm and define lower and upper bounds as -3 and 3 it shows me the result after about 60 iterations which is about 0.13 and the final point is something like [0, 9.34].
And how is this possible that the final point is not in the range defined by the bounds? And what is the actual maximum of this function?
The maximum is (0,0) (actually, when either input is 0, and periodically at multiples of pi). After you negate, you're looking for a minimum of a positive quantity. Just looking at the outer absolute value, it obviously can't get lower than 0. That trivially occurs when either value of sin(x) is 0.
Plugging in, you have f_min = f(0,0) = .0001(0 + 1)^0.1 = 1e-4
This expression is trivial to evaluate and plot over a 2d grid. Do that until you figure out what you're looking at, and what the approximate answer should be, and only then invoke an actual optimizer. GA does not sound like a good candidate for a relatively smooth expression like this. The reason you're getting strange answers is the fact that only one of the input parameters has to be 0. Once the optimizer finds one of those, the other input could be anything.

Determine the position and value of peak

I have a graph with five major peaks. I'd like to find the position and value of the first peak (the one furthest to the right). I have more than 100 different plots of this and the peak grows and shrinks in size in the various plots, and will need to use a for loop. I'm just stuck on determining the x and y values to a large number of significant figures using Matlab code.
Here's one of the many plots:
If you know for sure you're always gonna have 5 peaks I think the FileExchange function extrema will be very helpful, see here.
This will return you the maxima (and minima if needed) in descending order, so the first elements of output zmax and imax are respectively the maximal value and its index, their second elements are the second maximum value and its index and so on.
In the case if the peak you need is always the smallest of the five you'll just need zmax(5) and imax(5) to determine the 5th biggest maximum.
If you have access to Signal Processing Toolbox, findpeaks is the function you are looking for. It can be invoked using different options including number of peaks, which can be helpful when that information is available.

Controlled random number/dataset generation in MATLAB

Say, I have a cube of dimensions 1x1x1 spanning between coordinates (0,0,0) and (1,1,1). I want to generate a random set of points (assume 10 points) within this cube which are somewhat uniformly distributed (i.e. within certain minimum and maximum distance from each other and also not too close to the boundaries). How do I go about this without using loops? If this is not possible using vector/matrix operations then the solution with loops will also do.
Let me provide some more background details about my problem (This will help in terms of what I exactly need and why). I want to integrate a function, F(x,y,z), inside a polyhedron. I want to do it numerically as follows:
$F(x,y,z) = \sum_{i} F(x_i,y_i,z_i) \times V_i(x_i,y_i,z_i)$
Here, $F(x_i,y_i,z_i)$ is the value of function at point $(x_i,y_i,z_i)$ and $V_i$ is the weight. So to calculate the integral accurately, I need to identify set of random points which are not too close to each other or not too far from each other (Sorry but I myself don't know what this range is. I will be able to figure this out using parametric study only after I have a working code). Also, I need to do this for a 3D mesh which has multiple polyhedrons, hence I want to avoid loops to speed things out.
Check out this nice random vectors generator with fixed sum FEX file.
The code "generates m random n-element column vectors of values, [x1;x2;...;xn], each with a fixed sum, s, and subject to a restriction a<=xi<=b. The vectors are randomly and uniformly distributed in the n-1 dimensional space of solutions. This is accomplished by decomposing that space into a number of different types of simplexes (the many-dimensional generalizations of line segments, triangles, and tetrahedra.) The 'rand' function is used to distribute vectors within each simplex uniformly, and further calls on 'rand' serve to select different types of simplexes with probabilities proportional to their respective n-1 dimensional volumes. This algorithm does not perform any rejection of solutions - all are generated so as to already fit within the prescribed hypercube."
Use i=rand(3,10) where each column corresponds to one point, and each row corresponds to the coordinate in one axis (x,y,z)

How do I interpolate between points without going beyond them?

I have data of variable lengths (reaching movements recorded in 2D) and want to create a function that will resample this data to a uniform length (500 samples).
However, I want matlab to only resample between the maximum and minimum values given, without adding any additional distance. For instance, if I resample the matrix [1:1:10], the resampled matrix should have a minimum value of 1 and a maximum value of 10.
So far I've tried the following:
x = [1:1:10];
interp(x, 500 / length(x));
This, however, gives values above my maximum specified value of 10.
Is there any way I can get matlab to resample/interpolate solely between two points, without extending beyond them?
If I understood you correctly, you need to:
x=(1:1:10);
n=500;
xi=interp1(1:length(x),x,linspace(min(x),max(x),n));