Cannot find why Stack Overflow error appears - stack-overflow

I am trying to make an octree for randomly distributed set of particles. I have been trying to find where Stack Overflow Error appears whole day, but it was in vain. Could you please help me? The problem should be somewhere in (c == [0]) && (a > 0) part, however, I have no idea where. Thank you in advance!
type particle
R::Vector{Float64} # coordinates of the particle
m::Float64 # mass of the particle
a_tree::Float64 # acceleration of particle calculated from tree
a_exact::Float64 # acceleration of particle calculated by exact summation
end
type node
parent::Int64 # node's parent number
children::Vector{Int64} # set of childrens' numbers
l::Float64 # size of the node
R::Vector{Float64} # radius of geometric center
m::Float64 # total mass of the node
ptcl::Int64 # pointer to the particle in it
end
function problem3_2(N::Int64)
particles = Vector{particle}(N) # Basically, our system
tree = Vector{node}(1) # Initial tree (root)
tree[1] = node(0,[0],1.0,[0.0,0.0,0.0],0.0,0)
for i in eachindex(particles)
particles[i] = particle([rand() - 1/2, rand() - 1/2, rand() - 1/2], 1.0, 0.0, 0.0)
tree = InsertParticle(i,1,tree,particles)
end
return tree
end
function InsertParticle(i::Int64,k::Int64,tree,particles)
c = tree[k].children
a = tree[k].ptcl
if (c == [0]) && (a == 0)
tree[k].ptcl = i
elseif (c == [0]) && (a > 0)
j_1 = length(tree) + DetermOctant(particles[tree[k].ptcl],tree[k])
j_2 = length(tree) + DetermOctant(particles[i],tree[k])
tree[k].children = [x for x in length(tree)+1:length(tree)+8]
for p = 1:8
push!(tree,node(k,[0],tree[k].l/2,[0.0,0.0,0.0],0.0,0))
if (p == 1) || (p == 4) || (p == 5) || (p == 8)
tree[k+p].R[1] = tree[k].R[1] + tree[k+p].l/2
else
tree[k+p].R[1] = tree[k].R[1] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 5) || (p == 6)
tree[k+p].R[2] = tree[k].R[2] + tree[k+p].l/2
else
tree[k+p].R[2] = tree[k].R[2] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 3) || (p == 4)
tree[k+p].R[3] = tree[k].R[3] + tree[k+p].l/2
else
tree[k+p].R[3] = tree[k].R[3] - tree[k+p].l/2
end
end
InsertParticle(tree[k].ptcl,j_1,tree,particles)
InsertParticle(i,j_2,tree,particles)
tree[k].ptcl = 0
elseif (c != [0])
j = DetermOctant(particles[i],tree[k])
InsertParticle(i,tree[k].children[j],tree,particles)
end
return tree
end
function DetermOctant(x::particle,y::node)
c1 = y.R[1]; c2 = y.R[2]; c3 = y.R[3]
x1 = sign(x.R[1] - c1); x2 = sign(x.R[2] - c2); x3 = sign(x.R[3] - c3)
if (x1 > 0) && (x2 > 0) && (x3 > 0)
n = 1
elseif (x1 < 0) && (x2 > 0) && (x3 > 0)
n = 2
elseif (x1 < 0) && (x2 < 0) && (x3 > 0)
n = 3
elseif (x1 > 0) && (x2 < 0) && (x3 > 0)
n = 4
elseif (x1 > 0) && (x2 > 0) && (x3 < 0)
n = 5
elseif (x1 < 0) && (x2 > 0) && (x3 < 0)
n = 6
elseif (x1 < 0) && (x2 < 0) && (x3 < 0)
n = 7
else
n = 8
end
return n
end
Basically, I do know that the error should be somewhere here:
function InsertParticle(i::Int64,k::Int64,tree,particles)
c = tree[k].children
a = tree[k].ptcl
if (c == [0]) && (a == 0)
tree[k].ptcl = i
elseif (c == [0]) && (a > 0)
j_1 = length(tree) + DetermOctant(particles[tree[k].ptcl],tree[k])
j_2 = length(tree) + DetermOctant(particles[i],tree[k])
tree[k].children = [x for x in length(tree)+1:length(tree)+8]
for p = 1:8
push!(tree,node(k,[0],tree[k].l/2,[0.0,0.0,0.0],0.0,0))
if (p == 1) || (p == 4) || (p == 5) || (p == 8)
tree[k+p].R[1] = tree[k].R[1] + tree[k+p].l/2
else
tree[k+p].R[1] = tree[k].R[1] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 5) || (p == 6)
tree[k+p].R[2] = tree[k].R[2] + tree[k+p].l/2
else
tree[k+p].R[2] = tree[k].R[2] - tree[k+p].l/2
end
if (p == 1) || (p == 2) || (p == 3) || (p == 4)
tree[k+p].R[3] = tree[k].R[3] + tree[k+p].l/2
else
tree[k+p].R[3] = tree[k].R[3] - tree[k+p].l/2
end
end
InsertParticle(tree[k].ptcl,j_1,tree,particles)
InsertParticle(i,j_2,tree,particles)
tree[k].ptcl = 0
elseif (c != [0])
j = DetermOctant(particles[i],tree[k])
InsertParticle(i,tree[k].children[j],tree,particles)
end
return tree
end
However, I cannot see where the infinite loop appears. Sorry for bringing these all here in a such form, I just want to avoid XY-problem.
Thank you in advance!

Related

Can You Use a For Loop(s) to Optimize This Code?

I am hoping there is a cleaner way to write this code. What I have below works exactly as intended, however, I will have to do this for multiple different sections, so before I do that I am looking to see if there is a way potentially using for loops or something that would shorten this code and help it to run faster.
The user can enter a number of images from as few as 1 to as many as 4. Depending on the number they select, a new line is created for each image to be placed. This therefore pushes lines at the bottom of the spreadsheet that many lines lower, so this needs to be accounted for to ensure the information still gets inserted in the correct location regardless of how many images the user chooses. This is written in Google Apps Scripts within Google Sheets. If the value of the variables below is anything greater than 2, the user wants an image there, less than 3 they do not want an image and no new line will be created.
var graphic1_loc = 'A62';
var graphic2_loc = 'A63';
var graphic3_loc = 'A64';
var graphic4_loc = 'A65';
var graphic5_loc = 'A66';
var graphic1 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic1_loc).getValue();
var graphic2 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic2_loc).getValue();
var graphic3 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic3_loc).getValue();
var graphic4 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic4_loc).getValue();
var graphic5 = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+graphic5_loc).getValue();
var website_loc = 'D2';
var website_placement = 'B47';
var website_placement2 = 'B48';
var website_placement3 = 'B49';
var website_placement4 = 'B50';
var website_placement5 = 'B51';
if (graphic2.length < 3 && graphic3.length < 3 && graphic4.length < 3 && graphic5.length < 3) {
var website = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+website_loc).getValue()
SpreadsheetApp.getActiveSheet().getRange('Briefing!'+website_placement).setValue('For the latest forecast updates, visit ' + website+'.');
}
else if (((graphic2.length > 2) && (graphic3.length < 3) && (graphic4.length < 3) && (graphic5.length < 3)) ||
+((graphic2.length < 3) && (graphic3.length > 2) && (graphic4.length < 3) && (graphic5.length < 3)) ||
+((graphic2.length < 3) && (graphic3.length < 3) && (graphic4.length > 2) && (graphic5.length < 3)) ||
+((graphic2.length < 3) && (graphic3.length < 3) && (graphic4.length < 3) && (graphic5.length > 2))) {
var website = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+website_loc).getValue()
SpreadsheetApp.getActiveSheet().getRange('Briefing!'+website_placement2).setValue('For the latest forecast updates, visit ' + website+'.');
}
else if ((graphic2.length > 2 && graphic3.length > 2 && graphic4.length < 3 && graphic5.length < 3) ||
+(graphic2.length > 2 && graphic3.length < 3 && graphic4.length > 2 && graphic5.length < 3) ||
+(graphic2.length > 2 && graphic3.length < 3 && graphic4.length < 3 && graphic5.length > 2) ||
+(graphic2.length < 3 && graphic3.length > 2 && graphic4.length > 2 && graphic5.length < 3) ||
+(graphic2.length < 3 && graphic3.length > 2 && graphic4.length < 3 && graphic5.length > 2) ||
+(graphic2.length < 3 && graphic3.length < 3 && graphic4.length > 2 && graphic5.length > 2)) {
var website = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+website_loc).getValue()
SpreadsheetApp.getActiveSheet().getRange('Briefing!'+website_placement3).setValue('For the latest forecast updates, visit ' + website+'.');
}
else if (((graphic2.length > 2) && (graphic3.length > 2) && (graphic4.length > 2) && (graphic5.length < 3)) ||
+((graphic2.length > 2) && (graphic3.length > 2) && (graphic4.length < 3) && (graphic5.length > 2)) ||
+((graphic2.length > 2) && (graphic3.length < 3) && (graphic4.length > 2) && (graphic5.length > 2)) ||
+((graphic2.length < 3) && (graphic3.length > 2) && (graphic4.length > 2) && (graphic5.length > 2))) {
var website = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+website_loc).getValue()
SpreadsheetApp.getActiveSheet().getRange('Briefing!'+website_placement4).setValue('For the latest forecast updates, visit ' + website+'.');
}
else if ((graphic2.length > 2) && (graphic3.length > 2) && (graphic4.length > 2) && (graphic5.length > 2)) {
var website = SpreadsheetApp.getActiveSheet().getRange('main_gen!'+website_loc).getValue()
SpreadsheetApp.getActiveSheet().getRange('Briefing!'+website_placement5).setValue('For the latest forecast updates, visit ' + website+'.');
}
I believe you are talking about code factorization. It really depends on how the < or > are aligned in your if statement, if there is not common pattern, you might just leave as what it is.
If it does, my very first attempt is probably refactor out the common if statement into a function, for example (your first else if),
else if (((graphic2.length > 2) && (graphic3.length < 3) && (graphic4.length < 3) && (graphic5.length < 3)) ||...)
generalize it to a function, since graphic2,3,4,5 are used all the time,
create a array before the comparison
var graphic_arr = [graphic2.length, graphic3.length, graphic4.length, graphic5.length]
then create a condition function;
function condOne(arr1,arr2) {
return arr1[0] > arr2[0] && arr1[1] > arr2[1] && arr1[2] > arr2[2] && arr1[3] > arr2[3]
}
then your original condition can become
else if (condOne(graphic_arr, [2,3,3,3]) ||...)
if there are really some common pattern everywhere and you can create and reuse others like condTwo() etc, you can end up something like
note: each condition function has different < and > in comparison
if (condOne(graphic_arr, [ 4 digits])) || condTwo(graphic_arr, [ 4 digits])) || .....)
elseif (condThree(graphic_arr, [ new 4 digits]) || condTwo(graphic_arr, [another 4 digits]))
.....
The running speed depends on the amount of data you are consuming just based on your current code, the condition checking wouldn't matter a lot as long as it does your intent correctly.

Algorithm - Given a set of pixels with coordinates, how to find all the contiguous lines in an efficient way?

I am working on an extrusion function to create a mesh given a 2D texture and the thickness of it.
Example:
I have achieved finding the outline of the texture by simply looking for the pixels either near the edge or near transparent ones. It works great even for concave (donut-shaped) shapes but now I am left with an array of outline pixels.
Here is the result:
The problem is that the values, by being ordered from top-left to bottom-right, they are not suitable for building an actual 3D outline.
My current idea is the following:
Step 1.
From index [0], look at the right-hand side for the nearest contiguous point different from the starting point.
If found, move it into another array.
If nothing, look at the bottom. Continue until the starting point has been reached.
Step2.
Pick another pixel, if any, from the pixels remained in the array.
Repeat from Step1.
This, in my head, would work but it seems quite inefficient. Researching, I found about the Moore-Neighbor tracing algorithm but I couldn't find anywhere an example where it worked with convex shapes.
Any thoughts?
At the end, I managed to find my own answer, so here I want to share it:
After finding the outline of a given image (using the alpha value of each pixel), the pixels will be ordered in rows, good for drawing them but bad for constructing a mesh.
So, the next step is to find contiguous lines. This is done by checking first if there are any neighbors to the found pixel giving priority to the ones top/left/right/bottom (otherwise it will skip the corners).
Keep going until no pixels are left in the original array.
Here is the actual implementation (for Babylon.js but the idea works with any other engine):
Playground: https://www.babylonjs-playground.com/#9GPMUY#11
var GetTextureOutline = function (data, keepOutline, keepOtherPixels) {
var not_outline = [];
var pixels_list = [];
for (var j = 0; j < data.length; j = j + 4) {
var alpha = data[j + 3];
var current_alpha_index = j + 3;
// Not Invisible
if (alpha != 0) {
var top_alpha = data[current_alpha_index - (canvasWidth * 4)];
var bottom_alpha = data[current_alpha_index + (canvasWidth * 4)];
var left_alpha = data[current_alpha_index - 4];
var right_alpha = data[current_alpha_index + 4];
if ((top_alpha === undefined || top_alpha == 0) ||
(bottom_alpha === undefined || bottom_alpha == 0) ||
(left_alpha === undefined || left_alpha == 0) ||
(right_alpha === undefined || right_alpha == 0)) {
pixels_list.push({
x: (j / 4) % canvasWidth,
y: parseInt((j / 4) / canvasWidth),
color: new BABYLON.Color3(data[j] / 255, data[j + 1] / 255, data[j + 2] / 255),
alpha: data[j + 3] / 255
});
if (!keepOutline) {
data[j] = 255;
data[j + 1] = 0;
data[j + 2] = 255;
}
} else if (!keepOtherPixels) {
not_outline.push(j);
}
}
}
// Remove not-outline pixels
for (var i = 0; i < not_outline.length; i++) {
if (!keepOtherPixels) {
data[not_outline[i]] = 0;
data[not_outline[i] + 1] = 0;
data[not_outline[i] + 2] = 0;
data[not_outline[i] + 3] = 0;
}
}
return pixels_list;
}
var ExtractLinesFromPixelsList = function (pixelsList, sortPixels) {
if (sortPixels) {
// Sort pixelsList
function sortY(a, b) {
if (a.y == b.y) return a.x - b.x;
return a.y - b.y;
}
pixelsList.sort(sortY);
}
var lines = [];
var line = [];
var pixelAdded = true;
var skipDiagonals = true;
line.push(pixelsList[0]);
pixelsList.splice(0, 1);
var countPixels = 0;
while (pixelsList.length != 0) {
if (!pixelAdded && !skipDiagonals) {
lines.push(line);
line = [];
line.push(pixelsList[0]);
pixelsList.splice(0, 1);
} else if (!pixelAdded) {
skipDiagonals = false;
}
pixelAdded = false;
for (var i = 0; i < pixelsList.length; i++) {
if ((skipDiagonals && (
line[line.length - 1].x + 1 == pixelsList[i].x && line[line.length - 1].y == pixelsList[i].y ||
line[line.length - 1].x - 1 == pixelsList[i].x && line[line.length - 1].y == pixelsList[i].y ||
line[line.length - 1].x == pixelsList[i].x && line[line.length - 1].y + 1 == pixelsList[i].y ||
line[line.length - 1].x == pixelsList[i].x && line[line.length - 1].y - 1 == pixelsList[i].y)) || (!skipDiagonals && (
line[line.length - 1].x + 1 == pixelsList[i].x && line[line.length - 1].y + 1 == pixelsList[i].y ||
line[line.length - 1].x + 1 == pixelsList[i].x && line[line.length - 1].y - 1 == pixelsList[i].y ||
line[line.length - 1].x - 1 == pixelsList[i].x && line[line.length - 1].y + 1 == pixelsList[i].y ||
line[line.length - 1].x - 1 == pixelsList[i].x && line[line.length - 1].y - 1 == pixelsList[i].y
))) {
line.push(pixelsList[i]);
pixelsList.splice(i, 1);
i--;
pixelAdded = true;
skipDiagonals = true;
}
}
}
lines.push(line);
return lines;
}
Algorithm Looping over pixels, we only check each pixel once, skipping empty cells, and store it in a list as there won't be duplicates.
isEmpty implementation depends on how transparency works in your case, if a certain color is considered transparent, below is a case where we have an alpha channel.
threshold is the alpha level that represent the least-visibility for a cell to be considered non-empty.
isBorder will check if any of Moore neighbors is empty, in that case it is a border cell, otherwise it's not because it is surrounded by filled cells.
isEmpty(x,y): image[x,y].alpha <= threshold
isBorder(x,y)
: if isEmpty(x , y-1): return true
: if isEmpty(x , y+1): return true
: if isEmpty(x-1, y ): return true
: if isEmpty(x+1, y ): return true
: if isEmpty(x-1, y-1): return true
: if isEmpty(x-1, y+1): return true
: if isEmpty(x+1, y-1): return true
: if isEmpty(x+1, y+1): return true
: otherwise: return false
getBorderCellList()
: l = empty-list
: for x in 0..image.width
: : for y in 0..image.height
: : : if !isEmpty(x,y)
: : : : if isBorder(x,y)
: : : : : l.add(x,y)
: return l
Optimization You could optimize this by having a pre-computed boolean e[image.width][image.height] where e[x,y] = 1 if image[x,y]is not-empty, then use it directly to check, like isBorder(x,y): e[x-1,y] | e[x+1,y] | .. | e[x+1,y+1].
init()
: for x in 0..image.width
: : for y in 0..image.height
: : : e[x,y] = isEmpty(x,y)
isEmpty(x,y): image[x,y].alpha <= threshold
isBorder(x,y): e[x-1,y] | e[x+1,y] | .. | e[x+1,y+1]
getBorderCellList()
: l = empty-list
: for x in 0..image.width
: : for y in 0..image.height
: : : if not e[x,y]
: : : : if isBorder(x,y)
: : : : : l.add(x,y)
: return l

What should be the recurrence relation?

I am trying to solve this problem using dynamic programming but getting wrong answer. I think the recurrence i am using is incorrect. What should be the recurrence relation for the problem and what information should the dp state hold? At present, i am using a 2-dimensional array where dp[i][j] denotes the maximum number of scoops for rectangle of size (i x j), So answer will be dp[n - 1][n - 1].-> Problem Statement
My Code:
1) s[n][n] is the grid that is given in the problem.
2) end[i][j].first is 1 if s[i][j] is used in the solution for (i x j) rectangle and 0 otherwise.
3) end[i][j].second is 1 if s[i][j] is joined with upper-# and 2 if left-# and 0 if s[i][j] is not used.
int dp[n][n];
pair<int, int> end[n][n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
// w is the answer for (i x j) without using s[i][j]
w = (i - 1 >= 0 ? dp[i - 1][j] : 0) + (j - 1 >= 0 ? dp[i][j - 1] : 0) - (i - 1 >= 0 && j - 1 >= 0 ? dp[i - 1][j - 1] : 0);
if (i - 1 >= 0 && j - 1 >= 0 && end[i - 1][j].first == 1 && end[i - 1][j].second == 2 && end[i][j - 1].first == 1 && end[i][j - 1].second == 1) w--;
x = y = 0;
if (s[i][j] == '#') {
if (i > 0) {
// using the upper # if present
if (s[i - 1][j] == '#') x = 1 + (i - 2 >= 0 ? dp[i - 2][j] : 0) + (j - 1 >= 0 ? dp[i][j - 1] : 0) - (i - 2 >= 0 && j - 1 >= 0 ? dp[i - 2][j - 1] : 0);
if (i - 2 >= 0 && j - 1 >= 0 && end[i - 1][j - 1].first == 1 && end[i - 1][j - 1].second == 1 && end[i - 2][j].first == 1 && end[i - 2][j].second == 2) x--;
if (x <= w) x = 0;
}
if (j > 0) {
//using the left # if present
if (s[i][j - 1] == '#') y = 1 + (i - 1 >= 0 ? dp[i - 1][j] : 0) + (j - 2 >= 0 ? dp[i][j - 2] : 0) - (i - 1 >= 0 && j - 2 >= 0 ? dp[i - 1][j - 2] : 0);
if (i - 1 >= 0 && j - 2 >= 0 && end[i - 1][j - 1].first == 1 && end[i - 1][j - 1].second == 2 && end[i][j - 2].first == 1 && end[i][j - 2].second == 1) y--;
if (y <= w) y = 0;
}
}
// choosing the maximum of the three and accordingly assigning end[i][j]
if (w >= x && w >= y) {
dp[i][j] = w;
end[i][j] = make_pair(0, 0);
} else if (x > w && x > y) {
dp[i][j] = x;
end[i][j] = make_pair(1, 1);
} else {
dp[i][j] = y;
end[i][j] = make_pair(1, 2);
}
}
}
This problem is not about dynamic programming. It's about the maximum matching. Let's paint the grid with black and white colors(like a chess board). Now we have a bipartite graph(black cells are in the first part and white cells are in the second one). We should add edges between adjacent cells if both of them contain oil. The answer is the size of the maximum matching in this graph.

Index Exceeds Matrix Dimensions - Canny Edge Detection

I am using the following lines of code for edge detection using canny edge detector :
I=imread('bradd.tif');
figure,imshow(I);
IDtemp = im2double(I);
[r c]=size(I);
ID(r,c) = 0;
IDx(r,c) = 0;
IDfil(r,c) = 0;
IDxx(r,c) = 0;
IDy(r,c) = 0;
IDyy(r,c) = 0;
mod(r,c) = 0;
for i= 1 : r+4
for j = 1:c+4
if(i<=2 || j<=2 || i>=r+3 || j>=c+3)
ID(i,j) = 0;
else
ID(i,j) = IDtemp(i-2,j-2);
end;
end
end
%figure,imshow(ID);
filter=[2 4 5 4 2;4 9 12 9 4;5 12 15 12 5;4 9 12 9 4;2 4 5 4 2];
for i=1:5
for j=1:5
filter(i,j)=filter(i,j)/159;
end
end
%figure,imshow(filter);
for v = 3 : r
for u = 3 : c
sum = 0;
for i = -2 : 2
for j = -2 : 2
sum = sum + (ID(u+i, v+j) * filter(i+3, j+3));
end
end
IDx(u,v) = sum;
end
end
%figure,imshow(IDx);
IDxtemp = IDx;
for i= 1 : r+2
for j = 1:c+2
if(i<=1 || j<=1 || i>=r || j>=c)
IDfil(i,j) = 0;
else
IDfil(i,j) = IDxtemp(i-1,j-1);
end;
end
end
%figure,imshow(IDfil);
Mx = [-1 0 1; -2 0 2; -1 0 1]; % Sobel Mask in X-Direction
My = [-1 -2 -1; 0 0 0; 1 2 1]; % Sobel Mask in Y-Direction
for u = 2:r
for v = 2:c
sum1 = 0;
for i=-1:1
for j=-1:1
sum1 = sum1 + IDfil(u + i, v + j)* Mx(i + 2,j + 2);
end
end
IDxx(u,v) = sum1;
end;
end
%figure,imshow(IDxx);
for u = 2:r
for v = 2:c
sum2 = 0;
for i=-1:1
for j=-1:1
sum2 = sum2 + IDfil(u + i, v + j)* My(i + 2,j + 2);
end
end
IDyy(u,v) = sum2;
end
end
%figure,imshow(IDyy);
for u = 1:r
for v = 1:c
mod(u,v) = sqrt(IDxx(u,v)^2 + IDyy(u,v)^2) ;
%mod(u,v) = sqrt(IDxx(u,v)^2 + IDyy(u,v)^2);
end
end
%figure,imshow(mod);
modtemp = mod;
for i= 1 : r+2
for j = 1:c+2
if(i<=1 || j<=1 || i>=r || j>=c)
mod(i,j) = 0;
else
mod(i,j) = modtemp(i-1,j-1);
end;
end
end
%figure,imshow(mod);
theta(u,v) = 0;
supimg(u,v) = 0;
ntheta(u,v) = 0;
for u = 2 : r
for v = 2 : c
theta(u,v) = atand(IDyy(u,v)/IDxx(u,v));
if ((theta(u,v) > 0 ) && (theta(u,v) < 22.5) || (theta(u,v) > 157.5) && (theta(u,v) < -157.5))
ntheta(u,v) = 0;
end
if ((theta(u,v) > 22.5) && (theta(u,v) < 67.5) || (theta(u,v) < -112.5) && (theta(u,v) > -157.5))
ntheta(u,v) = 45;
end
if ((theta(u,v) > 67.5 && theta(u,v) < 112.5) || (theta(u,v) < -67.5 && theta(u,v) > 112.5))
ntheta(u,v) = 90;
end
if ((theta(u,v) > 112.5 && theta(u,v) <= 157.5) || (theta(u,v) < -22.5 && theta(u,v) > -67.5))
ntheta(u,v) = 135;
end
if (ntheta(u,v) == 0)
if (mod(u, v) > mod(u, v-1) && mod(u, v) > mod(u, v+1))
supimg(u,v) = mod(u,v);
else supimg(u,v) = 0;
end
end
if (ntheta(u,v) == 45)
if (mod(u, v) > mod(u+1, v-1) && mod(u, v) > mod(u-1, v+1))
supimg(u,v) = mod(u,v);
else supimg(u,v) = 0;
end
end
if (ntheta(u,v) == 90)
if (mod(u, v) > mod(u-1, v) && mod(u, v) > mod(u+1, v))
supimg(u,v) = mod(u,v);
else supimg(u,v) = 0;
end
end
if (ntheta(u,v) == 135)
if (mod(u, v) > mod(u-1, v-1) && mod(u, v) > mod(u+1, v+1))
supimg(u,v) = mod(u,v);
else supimg(u,v) = 0;
end
end
end
end
%figure,imshow(ntheta);
th = 0.2;
tl = 0.1;
resimg(u,v)= 0;
for u = 2 : r-1
for v = 2 : c-1
if(supimg(u,v) > th)
resimg(u,v) = 1;
else
if(supimg(u,v) >= tl && supimg(u,v) <= th )
resimg(u,v) = 1;
else
if (supimg(u,v) < tl)
resimg(u,v) = 0;
end
end
end
if (supimg(u-1,v-1) > th || supimg(u,v-1) > th || supimg(u+1,v-1) > th || supimg(u+1,v) > th || supimg(u+1,v+1) > th || supimg(u,v+1) > th || supimg(u-1,v+1) > th || supimg(u-1,v) > th)
resimg(u,v) = 1;
else
resimg(u,v) = 0;
end
end
end
figure,imshow(supimg);
figure,imshow(resimg);
However, for some of the images it is working fine, while for others it is showing the following error :
Index exceeds matrix dimensions.
Error in canny_edge (line 45)
sum = sum + (ID(u+i, v+j) * filter(i+3, j+3));
Can someone help me sort out this problem ??
Thanks and Regards.
Your loop ranges are in the wrong order leading to the error. If you modify your loop ranges to this
for u = 3 : r
for v = 3 : c
sum = 0;
for i = -2 : 2
for j = -2 : 2
sum = sum + (ID(u+i, v+j) * filter(i+3, j+3));
end
end
IDx(u,v) = sum;
end
end
the problem is solved.
My guess is that the code worked only for square images with c==r.
Note you are not making use of Matlab's vectorization capability, which allows you to shorten the first steps to:
ID = [zeros(2,c+4) ; [zeros(r,2) IDtemp zeros(r,2)]; zeros(2,c+4)];
filter=[2 4 5 4 2;4 9 12 9 4;5 12 15 12 5;4 9 12 9 4;2 4 5 4 2];
filter=filter/159;
for u = 1 : r
for v = 1 : c
IDx(u,v) = sum(reshape(ID(u+[0:4], v+[0:4]).* filter,25,1));
end
end
and this last loop can also be collapsed further but that might make readability an issue.
(edit) The loop can (for instance) be replaced with
IDx = conv2(ID, filter,'same');

Can you simplify this expression?

One for the mathematicians. This has gone around the office and we want to see who can come up with a better optimised version.
(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) &&
((b - (a + p) == 0) || (b - (a + p) > 1))
Edit: all data is positive int's
Edit: Better == simpler
(a + p <= b) && (a != 1) && (b - a - p != 1);
If the formula works and come from your business rules there is no real need to simplify it. The compiler probably knows better than us how to optimizing the formula.
The only thing you should do is use better variables names which reflect the business logic.
Beware of applying any of the proposed solution before unit testing them.
Refactor for simplicity by introducing more local variables which indicate the meaning of each expression. This is hard for us to do with no idea of what a, b and p mean.
b >= p && b != p+1
EDIT: Ok, that didn't work, but this one does:
a != 1 && b >= a+p && b-a-p != 1
(a!=1) && ((b==a+p) || (b>1+a+p))
It may not the simplest, but should be the one of most readable.
I wouldnt do all math in that expression. Such as b - ( a + p ) is evaluated twice. If possible, split them into variables instead.
Also, writing a polish notiation tree might help you optimize it, everything that you see twice, can be re-used.
Since they are all positive ints a lot of the repetition can be removed:
So as a first step,
(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) || (b - (a + p) > 1))
becomes
((a+p) <= b) && (a != 1) && (b >= p)) && ((b - (a + p) != 1)
For clarity, this is just replacing the (foo == 0 || foo > 1) pattern with foo != 1
That pattern appears twice above, once with foo = a, and once with foo = (b - (a+p))
Since the ints are unsigned, (a==0 || a>1) can be substituted for (a !=1).
With a first pass, you can reduce it to this:
uint sum = a + p;
return ((sum <= b) && (a != 1) && (b >= p)) && (b - sum != 1);
Also, it would be much more readable if you were able to give more meaningful names to the variables. For instance, if a and p were pressures, then a+p could be substitued as PressureSum.
s = a + p
b >= s && a != 1 && b - s - 1 > 0
Checked, returns the same boolean value as the question.
Program that I have used to check: (had fun writing it)
#include <iostream>
using namespace std;
typedef unsigned int uint;
bool condition(uint a, uint b, uint p)
{
uint s = a + p;
return uint( b >= s && a != 1 && b - s - 1 > 0 )
== uint( (((a+p) <= b) && (a == 0 || a > 1) && (b >= p))
&& ((b - (a + p) == 0) || (b - (a + p) > 1)) );
}
void main()
{
uint i = 0;
uint j = 0;
uint k = 0;
const uint max = 50;
for (uint i = 0; i <= max; ++i)
for (uint j = 0; j <= max; ++j)
for (uint k = 0; k <= max; ++k)
if (condition(i, j, k) == false)
{
cout << "Fails on a = " << i << ", b = " << j;
cout << ", p = " << k << endl;
int wait = 0;
cin >> wait;
}
}
bap = b - (a + p)
bap >= 0 && bap != 1 && a != 1
EDIT: Now I've got -2 for an honest attempt at helping out and also for what seems to me to be a valid answer. For you who can use Python, here are two functions, one with the question and one with my answer:
def question(a, b, p):
return (((a+p) <= b) and (a == 0 or a > 1) and (b >= p)) or ((b - (a + p) == 0) or (b - (a + p) > 1))
def answer(a, b, p):
bap = b - (a + p)
return bap >= 0 and bap != 1 and a != 1
Tested with a,b,p from 0 to 10000:
a != 1 && a != (b-p-1) && a <= (b-p);
I think it can be simplified even more.
This is as simple as I could get it.
def calc(a, b, p):
if (a != 1):
temp = a - b + p
if temp == 0 or temp < -1:
return True
return False
It could also be written as:
def calc(a, b, p):
temp = a - b + p
return a != 1 and (temp == 0 or temp < -1)
Or as:
def calc(a, b, p):
temp = a - b + p
return a != 1 and temp <= 0 and temp != -1
// In one line:
return (a != 1) && ((b-a-p == 0) || (b-a-p > 1))
// Expanded for the compiler:
if(a == 1)
return false;
int bap = b - a - p;
return (bap == 0) || (bap > 1);
If you post the processor you are using, I can optimize for assembly. =]
jjngy up here has it right. Here's a proof that his simplified formula is equivalent to the original using the Coq Proof Assistant.
Require Import Arith.
Require Import Omega.
Lemma eq : forall (a b p:nat),
(((a+p) <= b) /\ ((a = 0) \/ (a > 1)) /\ (b >= p)) /\
((b - (a + p) = 0) \/ (b - (a + p) > 1)) <->
((a + p <= b) /\ ~ (a= 1) /\ ~ (b - a - p = 1)).
Proof. intros; omega. Qed.
my apologies for the mistake in the original derivation. This is what happens when you don't bother to unit test after refactoring!
the corrected derivation follows, in the form of a test program.
The short answer is:
((a > 1) && (skeet == 0)) || ((a > 1) && (jon > 0) && (skeet < -1));
where
jon = (b - p)
skeet = (a - jon);
class Program
{
static void Main(string[] args)
{
bool ok = true;
for (int a = 1; a < 100; a++)
{
Console.Write(a.ToString());
Console.Write("...");
for (int b = 1; b < 100; b++)
{
for (int p = 1; p < 100; p++)
{
bool[] results = testFunctions(a, b, p);
if (!allSame(results))
{
Console.WriteLine(string.Format(
"Fails for {0},{1},{2}", a, b, p));
for (int i = 1; i <= results.Length; i++)
{
Console.WriteLine(i.ToString() + ": " +
results[i-1].ToString());
}
ok = false;
break;
}
}
if (!ok) { break; }
}
if (!ok) { break; }
}
if (ok) { Console.WriteLine("Success"); }
else { Console.WriteLine("Failed!"); }
Console.ReadKey();
}
public static bool allSame(bool[] vals)
{
bool firstValue = vals[0];
for (int i = 1; i < vals.Length; i++)
{
if (vals[i] != firstValue)
{
return false;
}
}
return true;
}
public static bool[] testFunctions(int a, int b, int p)
{
bool [] results = new bool[16];
//given: all values are positive integers
if (a<=0 || b<=0 || p<=0)
{
throw new Exception("All inputs must be positive integers!");
}
//[1] original expression
results[0] = (((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) &&
((b - (a + p) == 0) || (b - (a + p) > 1));
//[2] a==0 cannot be true since a is a positive integer
results[1] = (((a+p) <= b) && (a > 1) && (b >= p)) &&
((b - (a + p) == 0) || (b - (a + p) > 1));
//[3] rewrite (b >= p) && ((a+p) <= b)
results[2] = (b >= p) && (b >= (a+p)) && (a > 1) &&
((b - (a + p) == 0) || (b - (a + p) > 1));
//[4] since a is positive, (b>=p) guarantees (b>=(p+a)) so we
//can drop the latter term
results[3] = (b >= p) && (a > 1) &&
((b - (a + p) == 0) || (b - (a + p) > 1));
//[5] separate the two cases b>=p and b=p
results[4] = ((b==p) && (a > 1) && ((b - (a + p) == 0) ||
(b - (a + p) > 1))) || ((b > p) && (a > 1) &&
((b - (a + p) == 0) || (b - (a + p) > 1)));
//[6] rewrite the first case to eliminate p (since b=p
//in that case)
results[5] = ((b==p) && (a > 1) && ((-a == 0) ||
(-a > 1))) || ((b > p) && (a > 1) &&
(((b - a - p) == 0) || ((b - a - p) > 1)));
//[7] since a>0, neither (-a=0) nor (-a>1) can be true,
//so the case when b=p is always false
results[6] = (b > p) && (a > 1) && (((b - a - p) == 0) ||
((b - a - p) > 1));
//[8] rewrite (b>p) as ((b-p)>0) and reorder the subtractions
results[7] = ((b - p) > 0) && (a > 1) && (((b - p - a) == 0) ||
((b - p - a) > 1));
//[9] define (b - p) as N temporarily
int N = (b - p);
results[8] = (N > 0) && (a > 1) && (((N - a) == 0) || ((N - a) > 1));
//[10] rewrite the disjunction to isolate a
results[9] = (N > 0) && (a > 1) && ((a == N) || (a < (N - 1)));
//[11] expand the disjunction
results[10] = ((N > 0) && (a > 1) && (a == N)) ||
((N > 0) && (a > 1) && (a < (N - 1)));
//[12] since (a = N) in the first subexpression we can simplify to
results[11] = ((a == N) && (a > 1)) ||
((N > 0) && (a > 1) && (a < (N - 1)));
//[13] extract common term (a > 1) and replace N with (b - p)
results[12] = (a > 1) && ((a == (b - p)) ||
(((b - p) > 0) && (a < (b - p - 1))));
//[14] extract common term (a > 1) and replace N with (b - p)
results[13] = (a > 1) && (((a - b + p) == 0) ||
(((b - p) > 0) && ((a - b + p) < -1)));
//[15] replace redundant subterms with intermediate
//variables (to make Jon Skeet happy)
int jon = (b - p);
int skeet = (a - jon); //(a - b + p) = (a - (b - p))
results[14] = (a > 1) && ((skeet == 0) ||
((jon > 0) && (skeet < -1)));
//[16] rewrite in disjunctive normal form
results[15] = ((a > 1) && (skeet == 0)) ||
((a > 1) && (jon > 0) && (skeet < -1));
return results;
}
}
Well
((b - (a + p) == 0) || (b - (a + p) > 1))
Would be better writen as:
(b - (a + p) >= 0)
Applying this to the whole string you get:
((a+p) <= b) && (a > 1) && (b >= p)) && (b - (a + p) >= 0)
(a + p) <= b is the same thing as b - (a + p) >= 0
So you can get rid of that leaving:
((a+p) <= b) && (a > 1) && (b >= p))
I added this as a comment to nickf's answer but thought I'd offer it up as an answer on it's own. The good answers all seem to be a variation of his, including mine. But since we're not depending on the compiler for optimization (if the OP were, we wouldn't even be doing this) then boiling this down from 3 ANDs to the following means that there will be values where only 2 of the 3 portions will need to be evaluated. And if this is being done in a script, it would make a difference as opposed to compiled code.
(a != 1) && ((b > (a + p + 1)) || (b == (a + p))))
Based on a comment, I'm going to add this wrt this being better than the AND version:
I guess it depends on whether your true results data set is larger than 50 percent of the input sets. The more often the input is true, the better my variation will be. So, with this equation, it looks like the AND style will be better (at least for my input data set of 0-500).
If a, b and p are positive integers (assuming that the positive range include the 0 value) then the expression (((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) || (b - (a + p) > 1))
can be reduced to ((a+p)<=b) && (a!=1) && ((b-(a+p))!=1)
Let me demonstrate it:
In the first part of the expression there is a condition, ((a+p)<=b),
that if valuated true render true the second part:
((b - (a + p) == 0) || (b - (a + p) > 1)). If it is true that (b >=(a+p)) then (b - (a+p)) have to be greater or equal to 0, we need to assure that (b-(a+p))!=1.
Put this term aside for awhile and go on.
Now we can concentrate our efforts on the the first part
(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b-(a+p))!=1)
If a is positive then it is always >=0 and so we can drop the test (a == 0 || a > 1) if favor of (a!=1) and reduce first part of the expression to (((a+p) <= b) && (b >= p) && (a!=1)).
For the next step of the reduction you can consider that if b >= (a+p) then, obviously b>=p (a is positive) and the expression can be reduced to
((a+p)<=b) && (a!=1) && ((b-(a+p))!=1)
how is about the following logic, please comment it:
((a == 0 || a > 1) && ((b-p) > 1) )
(((a+p) <= b) && (a == 0 || a > 1) &&
(b >= p)) && ((b - (a + p) == 0)
|| (b - (a + p) > 1))
1) (a == 0 || a > 1) is (a != 1)
2) (b >= p) is (b - p >= 0)
(a + p <= b) is (b - p >= a), which is stronger than (b - p >= 0).
First condition reduced to (a != 1) && (b - p >= a).
3) (b - (a + p) == 0) is (b - a - p == 0) is (b - p == a).
(b - (a + p) > 1) is (b - a - p > 1) is (b - p > 1 + a).
Since we had (b - p >= a) and we're using && operation, we may say that (b - p >= a) covers (b - p == a && b - p > 1 + a).
Hence, the whole condition will be reduced to
(a != 1 && (b - p >= a))
There's a tempation to reduce it further to (b >= p), but this reduction won't cover prohibition of b = p + 1, therefore (a != 1 && (b - p >= a)) is the condition.
This question has been pretty comfortably answered already in practice, but there is one point I mention below which I have not seen anyone else raise yet.
Since we were told to assume a >= 0, and the first condition assures that b - (a + p) >= 0, the bracketed || tests can be turned into tests against inequality with 1:
(a + p <= b) && (a != 1) && (b >= p) && (b - a - p != 1)
It is tempting to remove the check (b >= p), which would give nickf's expression. And this is almost certainly the correct practical solution. Unfortunately, we need to know more about the problem domain before being able to say if it is safe to do that.
For instance, if using C and 32-bit unsigned ints for the types of a, b, and p, consider the case where a = 2^31 + 7, p = 2^31 + 5, b = 13. We have a > 0, (a + p) = 12 < b, but b < p. (I'm using '^' to indicate exponentiation, not C bitwise xor.)
Probably your values will not approach the kind of ranges where this sort of overflow is an issue, but you should check this assumption. And if it turns out to be a possibility, add a comment with that expression explaining this so that some zealous future optimiser does not carelessly remove the (b >= p) test.
I feel (a != 1) && (a + p <= b) && (a + p != b - 1) is slightly more clear.
Another option is:
int t = b-p;
(a != 1 && a <= t && a != t-1)
Basically a is either 0, t, or lies between 2 and t-2 inclusive.
First iteration:
bool bool1 = ((a+p) <= b) && (a == 0 || a > 1) && (b >= p);
bool bool2 = (b - (a + p) == 0) || (b - (a + p) > 1);
return bool1 && bool2;
Second iteration:
int value1 = b - (a + p);
bool bool1 = (value1 >= 0) && (a == 0 || a > 1) && (b >= p);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
Third iteration (all positives)
int value1 = b - (a + p);
bool bool1 = (value1 >= 0) && (a != 1) && (b >= p);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
4th iteration (all positives)
int value2 = b - p;
int value1 = value2 - a;
bool bool1 = (value1 >= 0) && (a != 1) && (b - p >= 0);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
5th iteration:
int value2 = b - p;
int value1 = value2 - a;
bool bool1 = (value1 >= 0) && (a != 1) && (value2 >= 0);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
b >= (a+p) && a>=1
even b >= p is redundant as this will always be the case for a >= 1
Alright, I'm hoping that I did my math right here, but if I'm right, then this simplifies quite a bit. Granted it doesn't look the same in the end, but the core logic should be the same.
// Initial equation
(((a + p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) || (b - (a + p) > 1))
// ((a + p) <= b) iif a = 0 && p = b; therefore, b = p and a = 0 for this to work
(b == p) && ((b - (a + p) == 0) || (b - (a + p) > 1))
// Simplification, assuming that b = p and a = 0
(b == p) && (a == 0)
However, if we are operating under the assumption that zero is neither positive or negative then that implies that any value for a provided to the equation is going to be greater than or equal to one. This in turn means that the equation will always evaluate to false due to the fact that the following:
(a == 0 || a > 1)
Would only evaluate to true when a >= 2; however, if the following is also true:
(b >= p)
Then that means that p is at least equal to b, thus:
((a + p) <= b)
By substitution becomes:
((2 + b) <= b)
Which can clearly never evaluate to true.
a!=1 && ((b == a + p) || (b - p > a + 1))
(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) || (b - (a + p) > 1))
since a >=0 (positive integers), the term (a == 0 || a > 1) is always true
if ((a+p) <= b) then (b >= p) is true when a,b,p are >=0
therefore ((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) reduces to
b>=(a+p)
(b - (a + p) == 0) || (b - (a + p) > 1) is equivalent to b>=(a+p)
therefore the whole equation reduces to
**b>= (a+p)**

Resources