I am trying to make a program in MATLAB in which we have to find the maxima.
The algorithm which I am using is compare the given point with two adjacent points.
If the next point is greater than the present , iterate in positive direction.
If the next point is smaller than the present, iterate in the negative direction.
If the previous point and the next point are less than the present, maxima reached.
I have made a while loop with flag variable.But it is not able to detect the maxima.
I intialize x to some number intially (say x = 0)
The function 'f(x) = -x^2 -3;'
The variable 'xint ' is the interval which is set to say 0.1.
The variable 'i' is just to keep a count.
clc
clear all
syms x
f(x) = -x^2+3;
max = 0;
x = 0;
xint = 0.1;
flag =1;
while(flag ==1)
fprintf('\ninside while\n')
if(f(x+xint)> f(x))
x = x + xint;
fprintf('inside first: Value of x is set to = %f, where function value is %f', x, f(x));
elseif(f(x+xint) < f(x))
x = x-xint;
fprintf('inside second: Value of x is set to = %f, where function value is %f', x, f(x));
else if(f(x-xint)<f(x) & f(x+xint) < f(x))
disp('Max detected')
max = x;
flag =0;
end
i = i+1;
end
Any help will be of use to me.
Thank You very much.
Anupam
Input :
f(x) = -x^2 +3;
Output:
The program does not enter into the third else if statement.And thus while loop keeps running.
You can't have a condition for the else clause. Additionally, if you were to make the else into an elseif it was be unreachable as the condition you wrote there can I be true when the condition you have for the previous elseif is true, but in a if-elseif statements only one clause gets executed every time.
Change the condition of the elseif and get to of the condition for the else:
elseif(f(x-xint) > f(x))
x = x-xint;
fprintf('inside second: Value of x is set to = %f, where function value is %f', x, f(x));
else
disp('Max detected')
max = x;
flag =0;
end
I am assuming xint is a positive value and your function is second degree polinomial with negative constant (i.e. y = a*x^2+b where a < 0), then:
if f(x+xint) > f(x) % go to right.
x1 = x+xint;
else % go to left
x1 = x
xint = -xint;
end
while f(x1) > f(x1+xint)
x1 = x1+xint;
end
Here x1 is maxima or something very close to it.
Related
I'm very new in MATLAB (this is my first script).
I wonder how may I speed up this loop, I don't know any toolbox or 'tricks' as I'm a newbie on it. I tried to code it with instinct, it works, but it is really long.
All are variables get with fread or integer manually entered, so this is basically simple math, but I have no clue on why is it so long (maybe nested loops ?) and how to improve, as I am more familiar with Python and for example multiprocess.
Thanks a lot
X = 0;
Points = [0,0,0];
for i=1:nbLines
for j=1:nbPositions-1
if lDate(i)>posDate(j) && lDate(i)<=posDate(j+1)
weight = (lDate(i) - posDate(j)) / (posDate(j+1)- posDate(j));
X = posX(j)*(1-weight) + posX(j+1) * weight;
end
end
if X ~= 0
for j=1:nbScans
Y = - distance(i,j) / tan(angle(i,j));
Points = [Points;X, Y, distance(i,j)];
end
end
end
X = 0;
Points = cell([],1) ;
Points{1} = [0,0,0];
count = 1 ;
for i=1:nbLines
id = find(lDate(i)>posDate & lDate(i)<=posDate) ;
if length(id) > 1
weight = (lDate(i) - posDate(id(1))) / (posDate(id(end))- posDate(id(1)));
X = posX(id(1))*(1-weight) + posX(id(end)) * weight;
end
if X ~= 0
j=1:nbScans ;
count = count+1 ;
Y = - distance(i,j)./tan(angle(i,j));
Points{count} = [repelem(X,size(Y,2),size(Y),1), Y, distance(i,j)'];
end
end
You have one issue with the given code. The blow line:
Points = [Points; X, Y, distance(i,j)];
This will definitely slow up your code. You need to initialize this array to store the numbers. If you initialize it, you will find good difference in speed.
X = 0;
Points = zeros([],3) ;
Points(1,:) = [0,0,0];
count = 1 ;
for i=1:nbLines
for j=1:nbPositions-1
if lDate(i)>posDate(j) && lDate(i)<=posDate(j+1)
weight = (lDate(i) - posDate(j)) / (posDate(j+1)- posDate(j));
X = posX(j)*(1-weight) + posX(j+1) * weight;
end
end
if X ~= 0
for j=1:nbScans
count = count+1 ;
Y = - distance(i,j) / tan(angle(i,j));
Points(count,:) = [X, Y, distance(i,j)];
end
end
end
Note that, you code only saves the last value of X, is this what you want?
try using parallelization- "parfor" instead of "for" that uses all available processors.
parfor i=1:nbLines
rest of code here
end
While using Matlab for image processing (exactly improving img by Fuzzy Logic) I found a really strange thing. My fuzzy function is correct, I tested it on random values and they are basically simple linear functions.
function f = Udark(z)
if z < 50
f = 1;
elseif z > 125
f = 0;
elseif (z >= 50) && (z <= 125)
f = -z/75 + 125/75;
end
end
where z is a value of a pixel (in grayscale). Now there is a really strange thing going on.
f = -z/75 + 125/75;, where a is an image. However, it is giving really different results if used as an input. I.e. if I use a variable p = 99, the output of the function is 0.3467 as it should be, when if I use A(i,j) it is giving me result f=2. Since it is clearly impossible, I do not know where is the problem. I thought that maybe there is a case with the type of the variable but if I change it to uint8 it stays the same... If you know what's going on, please, let me know :)
1.Changed line:
f = (125/75) - (z/75);
After editing the third condition the resultant/transformed image has no pixel values of 2. Not sure if you intend to work with decimals. If decimals are necessary using the im2double() function to convert the image and scaling it up by a factor of 255 might suffice your needs. See heading 3 for rounding details.
2.Reading in Image and Testing:
%Reading in the image and applying the function%
Image = imread("RGB_Image.png");
Greyscale_Image = rgb2gray(Image);
[Image_Height,Image_Width] = size(Greyscale_Image);
Transformed_Image = zeros(Image_Height,Image_Width);
for Row = 1: +1: Image_Height
for Column = 1: +1: Image_Width
Pixel_Value = Greyscale_Image(Row,Column);
[Transformed_Pixel_Value] = Udark(Pixel_Value);
Transformed_Image(Row,Column) = Transformed_Pixel_Value;
end
end
subplot(1,2,1); imshow(Greyscale_Image);
subplot(1,2,2); imshow(Transformed_Image);
%Checking that no transformed pixels falls in this impossible range%
Check = (Transformed_Image > (125/75)) & (Transformed_Image ~= 1);
Check_Flag = any(Check,'all');
%Function to transform pixel values%
function f = Udark(z)
if z < 50
f = 1;
elseif z > 125
f = 0;
elseif (z >= 50) && (z <= 125)
f = (125/75) - (z/75);
end
end
3.Evaluating the Specifics of the Third Condition
Working with integers (uint8) will force the values to be rounded to the nearest integer. Any number that falls between the range (50,125] will evaluate to 1 or 0.
f = -z/75 + 125/75;
If z = 50.1,
-50.1/75 + 125/75 = 74.9/75 ≈ 0.9987 → rounds to 1
Using MATLAB version: R2019b
I am having a problem in really simple program. My problem is that i lose value (y = 50 or 100 or 150) because at that time first condition is not valid. so how can i repeat loop for let say y = 50. (i don't want to use '=' e.g y< = (50+increment) because this is just a dummy program.
thanks
increment = 0
b = 1
var = 0
for y in range(1,1000):
if y>= increment and y< (50+increment):
print(f'{y} in List {b}')
else:
var = y
increment += 50
b+=1
Let's say I have two sets of coordinates. Set A is the ground truth coordinates and set B is the newly generated coordinates.
I am classifying the following way:
True positives if the coordinate in set A is at least within 5 pixels of a coordinate in B.
False negative for all the coordinates in set A that do not find matches with any coordinates in set B.
False positive for all the coordinates in set B that do find matches with any coordinates in set A.
The sets do not correspond. By that I mean, the first coordinate in set A doesn't have any relevance with the first coordinate in set B.
Here is my code:
clear;
w = warning ('off','all');
coordA = dir('./GT*.txt');
coordB = dir('./O*.txt');
for i =1:length(coordA)
TP = [];
FP = [];
FN = [];
%read coordinate files
fir = fopen(coordA(i).name, 'r');
disp(coordA(i).name);
A = textscan(fir, '%d %d\n');
fclose(fir);
disp(coordB(i).name);
sec = fopen(coordB(i).name, 'r');
B = textscan(fir, '%d, %d\n');
fclose(sec);
A_x = A{1};
A_y = A{2};
B_x = B{1};
B_y = B{2};
for j = 1:length(A_x)
flag = 1; %this flag indicates false negatives
for k = 1:length(B_x)
X = [A_x(j), A_y(j); B_x(k), B_y(k)];
d = pdist(X);
if(d <= 5)
flag = 0; %Ax and Ay
%the problem is here---------
TP = [TP [B_x(k) B_y(k)]];
B_x(k) = 0;
B_y(k) = 0;
end
end
if(flag)
FN = [FN [A_x(j) A_y(j)]];
end
end
for b = find(B_x)
FP = [FP [B_x(b) B_y(b)]];
end
end
The problem(please note the comments in the code and example below) I am facing is the following. Let's say there are two coordinates in set A that are really close to each other. When I go to check for TPs in set B and I find a coordinate that's within 5 pixels, I mark it as true positive then remove that coordinate from set B. However, let's say I'm trying to check for the other nearby coordinate from set A. Well, it will be marked as a false negative since I removed a close by coordinate in set B when checking for a different coordinate.
I thought of not removing coordinates in set B even when I find a true positive, but then how would I find false positives?
I did this in Matlab, but any language is fine with me.
Example coordinates:
A:
250 500
251 500
B:
250 501
The second coordinate should also be considered as true positive, but its being considered as false negative.
By altering your code, I believe the following part should do what you are looking for. Basically, instead of removing entries, you can just use logical indexing:
clear;
w = warning ('off','all');
coordA = dir('./GT*.txt');
coordB = dir('./O*.txt');
radius = 5;
for i =1:length(coordA)
% read coordinate files
fir = fopen(coordA(i).name, 'r');
disp(coordA(i).name);
A = textscan(fir, '%d %d\n');
fclose(fir);
disp(coordB(i).name);
sec = fopen(coordB(i).name, 'r');
B = textscan(fir, '%d, %d\n');
fclose(sec);
A_x = A{1};
A_y = A{2};
B_x = B{1};
B_y = B{2};
% Initialize logical arrays to reflect the
% Status of each entry
TP = zeros(length(A_x),1); % no entry of A is considered true positive
FN = ones(length(A_x),1); % all entries of A are considered false negative
FP = ones(length(B_x),1); % all entries of B are considered false positive
for ij = 1:length(A_x)
for ijk = 1:length(B_x)
X = [A_x(ij), A_y(ij); B_x(ijk), B_y(ijk)];
d = pdist(X)
if (d <= radius)
TP(ij) = 1; % just found a true positive
FP(ijk) = 0;% no more a false positive
end
end
end
% Obtain the lists containing the appropriate values
% For true positive, just use logical indexing and TP array
True_Pos = [A_x(logical(TP))', A_y(logical(TP))'];
% For false negative, remove TP from FN
False_Neg = [A_x(logical(FN-TP))', A_y(logical(FN-TP))'];
% For false positive, whatever remained switched on in FP
False_Pos = [B_x(logical(FP))', B_y(logical(FP))'];
end
There are other approaches if you do need to remove entries (see my comment above). Moreover, there is a more clean way to code it but I tried to be explicit and follow your implementation.
Problem: We have x checkboxes and we want to check y of them evenly.
Example 1: select 50 checkboxes of 100 total.
[-]
[x]
[-]
[x]
...
Example 2: select 33 checkboxes of 100 total.
[-]
[-]
[x]
[-]
[-]
[x]
...
Example 3: select 66 checkboxes of 100 total:
[-]
[x]
[x]
[-]
[x]
[x]
...
But we're having trouble to come up with a formula to check them in code, especially once you go 11/111 or something similar. Anyone has an idea?
Let's first assume y is divisible by x. Then we denote p = y/x and the solution is simple. Go through the list, every p elements, mark 1 of them.
Now, let's say r = y%x is non zero. Still p = y/x where / is integer devision. So, you need to:
In the first p-r elements, mark 1 elements
In the last r elements, mark 2 elements
Note: This depends on how you define evenly distributed. You might want to spread the r sections withx+1 elements in between p-r sections with x elements, which indeed is again the same problem and could be solved recursively.
Alright so it wasn't actually correct. I think this would do though:
Regardless of divisibility:
if y > 2*x, then mark 1 element every p = y/x elements, x times.
if y < 2*x, then mark all, and do the previous step unmarking y-x out of y checkboxes (so like in the previous case, but x is replaced by y-x)
Note: This depends on how you define evenly distributed. You might want to change between p and p+1 elements for example to distribute them better.
Here's a straightforward solution using integer arithmetic:
void check(char boxes[], int total_count, int check_count)
{
int i;
for (i = 0; i < total_count; i++)
boxes[i] = '-';
for (i = 0; i < check_count; i++)
boxes[i * total_count / check_count] = 'x';
}
total_count is the total number of boxes, and check_count is the number of boxes to check.
First, it sets every box to unchecked. Then, it checks check_count boxes, scaling the counter to the number of boxes.
Caveat: this is left-biased rather than right-biased like in your examples. That is, it prints x--x-- rather than --x--x. You can turn it around by replacing
boxes[i * total_count / check_count] = 'x';
with:
boxes[total_count - (i * total_count / check_count) - 1] = 'x';
Correctness
Assuming 0 <= check_count <= total_count, and that boxes has space for at least total_count items, we can prove that:
No check marks will overlap. i * total_count / check_count increments by at least one on every iteration, because total_count >= check_count.
This will not overflow the buffer. The subscript i * total_count / check_count
Will be >= 0. i, total_count, and check_count will all be >= 0.
Will be < total_count. When n > 0 and d > 0:
(n * d - 1) / d < n
In other words, if we take n * d / d, and nudge the numerator down, the quotient will go down, too.
Therefore, (check_count - 1) * total_count / check_count will be less than total_count, with the assumptions made above. A division by zero won't happen because if check_count is 0, the loop in question will have zero iterations.
Say number of checkboxes is C and the number of Xes is N.
You example states that having C=111 and N=11 is your most troublesome case.
Try this: divide C/N. Call it D. Have index in the array as double number I. Have another variable as counter, M.
double D = (double)C / (double)N;
double I = 0.0;
int M = N;
while (M > 0) {
if (checkboxes[Round(I)].Checked) { // if we selected it, skip to next
I += 1.0;
continue;
}
checkboxes[Round(I)].Checked = true;
M --;
I += D;
if (Round(I) >= C) { // wrap around the end
I -= C;
}
}
Please note that Round(x) should return nearest integer value for x.
This one could work for you.
I think the key is to keep count of how many boxes you expect to have per check.
Say you want 33 checks in 100 boxes. 100 / 33 = 3.030303..., so you expect to have one check every 3.030303... boxes. That means every 3.030303... boxes, you need to add a check. 66 checks in 100 boxes would mean one check every 1.51515... boxes, 11 checks in 111 boxes would mean one check every 10.090909... boxes, and so on.
double count = 0;
for (int i = 0; i < boxes; i++) {
count += 1;
if (count >= boxes/checks) {
checkboxes[i] = true;
count -= count.truncate(); // so 1.6 becomes 0.6 - resetting the count but keeping the decimal part to keep track of "partial boxes" so far
}
}
You might rather use decimal as opposed to double for count, or there's a slight chance the last box will get skipped due to rounding errors.
Bresenham-like algorithm is suitable to distribute checkboxes evenly. Output of 'x' corresponds to Y-coordinate change. It is possible to choose initial err as random value in range [0..places) to avoid biasing.
def Distribute(places, stars):
err = places // 2
res = ''
for i in range(0, places):
err = err - stars
if err < 0 :
res = res + 'x'
err = err + places
else:
res = res + '-'
print(res)
Distribute(24,17)
Distribute(24,12)
Distribute(24,5)
output:
x-xxx-xx-xx-xxx-xx-xxx-x
-x-x-x-x-x-x-x-x-x-x-x-x
--x----x----x---x----x--
Quick html/javascript solution:
<html>
<body>
<div id='container'></div>
<script>
var cbCount = 111;
var cbCheckCount = 11;
var cbRatio = cbCount / cbCheckCount;
var buildCheckCount = 0;
var c = document.getElementById('container');
for (var i=1; i <= cbCount; i++) {
// make a checkbox
var cb = document.createElement('input');
cb.type = 'checkbox';
test = i / cbRatio - buildCheckCount;
if (test >= 1) {
// check the checkbox we just made
cb.checked = 'checked';
buildCheckCount++;
}
c.appendChild(cb);
c.appendChild(document.createElement('br'));
}
</script>
</body></html>
Adapt code from one question's answer or another answer from earlier this month. Set N = x = number of checkboxes and M = y = number to be checked and apply formula (N*i+N)/M - (N*i)/M for section sizes. (Also see Joey Adams' answer.)
In python, the adapted code is:
N=100; M=33; p=0;
for i in range(M):
k = (N+N*i)/M
for j in range(p,k-1): print "-",
print "x",
p=k
which produces
- - x - - x - - x - - x - - [...] x - - x - - - x where [...] represents 25 --x repetitions.
With M=66 the code gives
x - x x - x x - x x - x x - [...] x x - x x - x - x where [...] represents mostly xx- repetitions, with one x- in the middle.
Note, in C or java: Substitute for (i=0; i<M; ++i) in place of for i in range(M):. Substitute for (j=p; j<k-1; ++j) in place of for j in range(p,k-1):.
Correctness: Note that M = x boxes get checked because print "x", is executed M times.
What about using Fisher–Yates shuffle ?
Make array, shuffle and pick first n elements. You do not need to shuffle all of them, just first n of array. Shuffling can be find in most language libraries.