Polynomial multiplication in M2(R)? - algorithm

I was trying to implement a FFT-based multiplication algorithm in M2(R). Basically an algorithm that gets as an input two polynoms with elements given as matrices, and builds the product polynom. However, even though the algorithm should work, as it looks exactly identical to a version I wrote earlier on regular number, it doesn't. The coefficients are always off by a little.
I have not found any articles on the roots of unity in M2(C), but I have found(on paper) that choosing eps = ((cos(2PI/n) , i sin(2PI/n)) , ( i sin(2PI/n) , cos(2PI/n))), I get a nice cycle.
Is there something wrong in my approach?
Here is the code:
struct FFT {
PolyC To, Aux[17][2], Res[17][2], AC, BC, ResC, ResD, ArgA, ArgB;
void fft(PolyC V, var depth, var n, PolyC To, MatC step) {
if(n == 1) {
To[0] = V[0];
} else {
MatC eps = matCHelper.I2;
//We "split" the poly in 2
for(var i=0; i<n; i++)
Aux[depth+1][i&1][i>>1] = V[i];
//We recursively apply FFT to the components
fft(Aux[depth+1][0], depth+1, n/2, Res[depth+1][0], step*step);
fft(Aux[depth+1][1], depth+1, n/2, Res[depth+1][1], step*step);
//We compute the result for the n roots
for(var i=0; i<n/2; i++) {
To[i] = Res[depth+1][0][i] + eps * Res[depth+1][1][i];
To[n/2+i] = Res[depth+1][0][i] - eps * Res[depth+1][1][i];
eps = eps * step;
}
}
}
void FFTMultiply(Poly Res, Poly A, Poly B, var n1, var n2) {
var M;
for(M = 1; M <= 2*n1 || M <= 2*n2; M <<= 1);
for(var i=0; i<n1; i++) ArgA[i] = A[i];
for(var i=n1; i<M; i++) ArgA[i] = matCHelper.O2;
for(var i=0; i<n2; i++) ArgB[i] = B[i];
for(var i=n2; i<M; i++) ArgB[i] = matCHelper.O2;
MatC step( Complex(cos(2*PI/M), 0) , Complex(0, sin(2*PI/M)),
Complex(0, sin(2*PI/M)) , Complex(cos(2*PI/M), 0) );
fft(ArgA, 0, M, AC, step);
fft(ArgB, 0, M, BC, step);
for(var i=0; i<M; i++) {
RezC[i] = AC[i] * BC[i];
}
step.b = -step.b;
step.c = -step.c;
fft(RezC, 0, M, RezD, step);
for(var i=0; i<M; i++) {
// Now I divided everything by M and copied every element of ResD to Res modulo some number
}
}
};

You can not expect this method to work if your coefficient matrices do not commute with your matrix step. To get it working correctly, use the diagonal matrix corresponding to multiplication with the scalar exp(i*2*PI/M).

Related

2-dimensional cutting rod algorithm?

I have an assignment to solve using dynamic programming the following problem:
There is a rectangular sheet and a set of rectangular elements of given dimensions and value. The task is to divide the sheet into elements of given dimensions, so that the sum of values of the elements is maximum. Find this sum and a tree of consequent cuts.
There are following conditions:
It is NOT possible to rotate the given elements.
It is possible to cut out unlimited number of certain types of
elements.
It is possible that some parts of the sheet will remain unused.
The only possible way to cut the sheet is by a straight
line, so that you again obtain two smaller rectangles.
The problem is solved. Solution can be found below.
==========================================================================
I understand the problem for one dimension, which comes to the rod cutting problem. You divide the rod into the smallest possible pieces, take the first one and check if you can build it with the given segments. Remember the weight you'll get with building the part this way and move on to a bigger part containing the previous one. You go back by the length of the segment you're trying at the moment and check if using this segment plus the weight of the previously build part will make up to better sum of the weight for the current part.
Supposedly, the cutting wood problem is no different, but you add the 2-dimension, additional loop somewhere in the middle. Unfortunately, I can't imagine how to store the values and how to go back for the 2-dimensions.
I've tried doing like:
1. Loop on one dimension
2. Loop on second dimension
3. Loop on all the segments you can use
4. Check if you can fit the current segment depending on 1. and 2.
5. If yes, go back the length of the segment to see if weight of the segment + what's stored there gives you a greater result; do the same for the width
6. Store the result in the cell you're currently on
7. Go through the array and find the greatest result
Here is the code I produced after many debugging tries:
public int Cut((int length, int width) sheet, (int length, int width, int price)[] elements, out Cut cuts)
{
int[,] tmpSheetArr = new int[sheet.length + 1, sheet.width + 1];
for (int i = 1; i < tmpSheetArr.GetLength(0); i++)
{
for (int j = 1; j < tmpSheetArr.GetLength(1); j++)
{
tmpSheetArr[i, j] = Int32.MinValue;
}
}
for (int i = 1; i < tmpSheetArr.GetLength(0); i++) //columns
{
for (int j = 1; j < tmpSheetArr.GetLength(1); j++) //rows
{
for (int e = 0; e < elements.Length; e++)
{
(int length, int width, int price) elem = elements[e];
if (i >= elem.length && j >= elem.width)
{
int tmpJ, tmpI, tmpVal;
tmpJ = j - elem.width;
tmpI = i;
while (0 < tmpI)
{
if(tmpI > i - elem.length && tmpI <= i && tmpJ > j - elem.width && tmpJ <= j)
{
tmpJ -= 1;
if (-1 == tmpJ)
{
tmpJ = tmpSheetArr.GetLength(1) - 1;
tmpI -= 1;
}
continue;
}
tmpVal = tmpSheetArr[tmpI, tmpJ] == Int32.MinValue ? 0 : tmpSheetArr[tmpI, tmpJ];
if (tmpSheetArr[i, j] < elem.price + tmpVal)
{
tmpSheetArr[i, j] = elem.price + tmpVal;
}
tmpJ -= 1;
if(-1 == tmpJ)
{
tmpJ = tmpSheetArr.GetLength(1) - 1;
tmpI -= 1;
}
}
}
}
}
}
int tmpMax = 0;
for (int i = 1; i < tmpSheetArr.GetLength(0); i++)
{
for (int j = 1; j < tmpSheetArr.GetLength(1); j++)
{
if (tmpMax < tmpSheetArr[i, j])
tmpMax = tmpSheetArr[i, j];
}
}
cuts = null;
return tmpMax;
}
It doesn't work, gives too big results in some cases and gets stuck on bigger problems. I think the main problem is about going back - with only the weight stored I don't know what size of the block was used and if it will overlap with the current one.
I decided to write it from the beginning, but really can't find another approach. I have a code for the 1D problem:
int cutRod(int[] price, int n)
{
int[] val = new int[n + 1];
val[0] = 0;
int i, j;
// Build the table val[] and return the last entry
// from the table
for (i = 1; i <= n; i++)
{
int max_val = Int32.MinValue;
for (j = 0; j < i; j++)
max_val = Math.Max(max_val, price[j] + val[i - j - 1]);
val[i] = max_val;
}
return val[n];
}
How do I change it so it works for 2D problem?
I tried to explain my limited understanding and way of thinking the best I could. I would appreciate any help on this matter.
Make your dynamic state at x be a dictionary mapping a particular "skyline" of what blocks placed before x look like after x. You start with a flat skyline (no blocks so far, clean edge), and you're looking for a flat skyline at the other end (didn't go off the edge of the sheet).
As you advance you "lower" your skyline by 1, start looking at ways to cut out new blocks, and get new possible skylines.
The number of possible skylines will grow exponentially with the width of the rectangle.
The solution:
Build an array of maximum values that can be obtained from given piece of dimensions 1x1 up to the size of the board. Maximum value for given piece is stored under index of [(length of the piece) - 1, (width of the piece) - 1]. To find the maximum value, check how the current piece can be formed with previous pieces and cuts.
To construct the tree of cuts, build a second array of the best cuts for the current piece. Root of the cuts tree for the current piece is stored under index of [(length of the piece) - 1, (width of the piece) - 1].
Cuts class:
public class Cut
{
public int length; // vertical dimension (before cut)
public int width; // horizontal dimension (before cut)
public int price; // sum of the values of the two elements resulting from the cut
public bool vertical; // true for vertical cut, false otherwise
public int n; // distance from left side (for vertical cut) or top (for horizontal cut) of the current piece
// price 0 means there was no cut, topleft and bottomright are null,
public Cut topleft; // top/left resulting piece after cut
public Cut bottomright; // bottom/right resulting piece after cut
public Cut(int length, int width, int price, bool vertical=true, int n=0, Cut topleft=null, Cut bottomright=null)
{
this.length = length;
this.width = width;
this.price = price;
this.vertical = vertical;
this.n = n;
this.topleft = topleft;
this.bottomright = bottomright;
}
}
Function finding the maximum value and a tree of cuts:
public int Cut((int length, int width) sheet, (int length, int width, int price)[] elements, out Cut cuts)
{
int[,] sheetArr = new int[sheet.length, sheet.width]; //contains best values of current pieces that can be formed
Cut[,] cutsArr = new Cut[sheet.length, sheet.width]; //contains references for cuts used to form pieces of the best value,
for (int l = 0; l < sheet.length; l++) //loop on length
{
for (int w = 0; w < sheet.width; w++) //loop on width
{
foreach ((int length, int width, int price) elem in elements) //loop on elements
{
if (elem.length == l + 1 && elem.width == w + 1) //check if current piece can be build with one of the given elements
{
sheetArr[l, w] = elem.price;
cutsArr[l, w] = new Cut(elem.length, elem.width, elem.price); //piece is exactly one of the elements (no cut)
break; //no 2 elements of the same size in the given elements
}
cutsArr[l, w] = new Cut(l + 1, w + 1, 0); //piece can not be formed from given elements, price = 0 (no cut)
}
for (int i = 1; i < Math.Floor((decimal)(l + 1) / 2) + 1; i++) //go back on length
{
if (sheetArr[i - 1, w] + sheetArr[l - i, w] > sheetArr[l, w])
{
sheetArr[l, w] = sheetArr[i - 1, w] + sheetArr[l - i, w];
cutsArr[l, w] = new Cut(l + 1, w + 1, sheetArr[l, w], false, i, cutsArr[i - 1, w], cutsArr[l - i, w]);
}
}
for (int i = 1; i < Math.Floor((decimal)(w + 1) / 2) + 1; i++) //go back on width
{
if (sheetArr[l, i - 1] + sheetArr[l, w - i] > sheetArr[l, w])
{
sheetArr[l, w] = sheetArr[l, i - 1] + sheetArr[l, w - i];
cutsArr[l, w] = new Cut(l + 1, w + 1, sheetArr[l, w], true, i, cutsArr[l, i - 1], cutsArr[l, w - i]);
}
}
}
}
cuts = cutsArr[sheet.length - 1, sheet.width - 1];
return sheetArr[sheet.length - 1, sheet.width - 1];
}

What is the best way to build a path with equal distance between nodes?

I have a path in 2D space. But distances between noded are not equal.
I'm looking for an algorithm that adds nodes to the source path so that the distance between nodes will be equal.
What is the best practice?
Example picture:
It is geometrically impossible for you to generate equidistant points for more than one arbitrary path segment - only possible if their lengths share a common divisor.
However, you can generate the closest matching set of points using the following method:
You need to first set the maximum number of points N you want on a path segment. This is to stop the algorithm from infinitely looping - because in the general case only an infinite number of divisions would give us the exact answer, and that is not what we want.
However before this can be applied, we need to check that N + 1 is not less than the ratio of the longest path to the shortest. If it is then we need to adjust it.
For each path segment iterate to the maximum number of points N, calculating the division length L for each number. For each iterated value we shall define a Cost variable as the sum of the total difference between the computed solution and the ideal.
Then iterate through every other path segment. Divide its length M by L to give a ratio R:
If R is an integer, then for this segment an exact solution has been found. Add zero to Cost
Otherwise take A = floor(R), B = ceil(R). Compute the two separate costs cost_A = abs(M - L * A) and similarly for B.
If cost_A < cost_B, take C = A as the optimal division count for this segment, and vice versa. Record C.
Take min(cost_A, cost_B) and add to Cost. Continue.
Remember to keep track of a list of optimal values for C for each path segment, and also the "working list" which records the current computation. Also keep track of a min_Cost variable.
If at the end of a main loop for each segment Cost < min_Cost, then update min_Cost and the optimal list.
The above description may seem a little vague. Here is some C# code - apologies as I'm not familiar with the details of C# Mono / Unity, so you may have to replace a few type names / function names here or there, but the gist of the algorithm is hopefully what you want.
public static int[] calculateOptimalSplitNumbers(Point[] path, int N)
{
int no_segs = path.Length - 1;
if (no_segs <= 1) return null;
double[] lengths = new double[no_segs];
for (int i = 0; i < no_segs; i++)
lengths[i] = Vector.LengthOf(path[i + 1] - path[i]); // replace with the correct unity function?
int max_ratio = Math.Floor(Math.Max(lengths) / Math.Min(lengths)) - 1;
if (N < max_ratio)
N = max_ratio;
double min_Cost = double.MaxValue;
int[] min_List = new int[no_segs];
int[] cur_List = new int[no_segs];
for (int i = 0; i < no_segs; i++)
{
double cost = 0.0;
for (int j = 0; j < N; j++)
{
double L = lengths[i] / (j + 2);
cur_list[i] = j + 1;
for (int k = 0; k < no_segs; k++)
{
if (k == i) continue;
double M = lengths[k],
R = M / L;
// path is too short - put no points
if (R < 1.0) {
cur_list[k] = 0;
cost += M - L;
}
int A = Math.Floor(R),
B = Math.Ceiling(R);
double cost_A = Math.Abs(M - L * A),
cost_B = Math.Abs(M - L * B);
if (cost_A < cost_B) {
cur_list[k] = A;
cost += cost_A;
}
else {
cur_list[k] = B;
cost += cost_B;
}
}
}
if (cost < min_Cost) {
min_Cost = cost;
System.Array.Copy(cur_List, min_List, no_segs);
}
}
return min_List;
}
The code takes an array of path points and returns the number of points to put on each path segment. If you need any more explanation of the code just let me know and I will edit with some more comments.
I have decided to share path normalizer utility (according to #meowgoesthedog approach) for using it in Unity3D:
using System; using System.Collections.Generic; using UnityEngine;
/// <summary>
/// Represents helper that normalizes the path in a way
/// that distance between all nodes become almost equal.
/// </summary>
public static class PathNormalizer
{
/// <summary>
/// Normalizes the specified vector path.
/// </summary>
/// <param name="vectorPath">The vector path.</param>
/// <param name="minSplitsBySegment">The minimum splits by segment.</param>
public static Vector3[] Normalize(Vector3[] vectorPath, int minSplitsBySegment)
{
if (vectorPath.Length < 3)
{
return vectorPath;
}
var segmentsSplits = CalculateOptimalSplitNumbers(vectorPath, minSplitsBySegment);
if (segmentsSplits == null)
{
Debug.LogWarning("Can't normalize path");
return vectorPath;
}
List<Vector3> newPath = new List<Vector3>();
for (int i = 1; i < vectorPath.Length; i++)
{
var split = segmentsSplits[i - 1];
for (int j = 0; j < split; j++)
{
var newNode = Vector3.Lerp(vectorPath[i - 1], vectorPath[i], (float)j / split);
newPath.Add(newNode);
}
}
newPath.Add(vectorPath[vectorPath.Length - 1]);
return newPath.ToArray();
}
private static int[] CalculateOptimalSplitNumbers(Vector3[] path, int minSplitsBySegment)
{
int noSegs = path.Length - 1;
if (noSegs <= 1) return null;
float[] lengths = new float[noSegs];
for (int i = 0; i < noSegs; i++)
lengths[i] = Vector3.Distance(path[i + 1], path[i]);
float minLenght = float.MaxValue;
float maxLenght = 0;
foreach (var length in lengths)
{
if (length < minLenght)
{
minLenght = length;
}
if (length > maxLenght)
{
maxLenght = length;
}
}
int maxRatio = (int)Math.Floor(maxLenght / minLenght) - 1;
if (minSplitsBySegment < maxRatio)
minSplitsBySegment = maxRatio;
double minCost = double.MaxValue;
int[] minList = new int[noSegs];
int[] curList = new int[noSegs];
for (int i = 0; i < noSegs; i++)
{
double cost = 0.0;
for (int j = 0; j < minSplitsBySegment; j++)
{
double l = lengths[i] / (j + 2);
curList[i] = j + 1;
for (int k = 0; k < noSegs; k++)
{
if (k == i) continue;
double m = lengths[k],
r = m / l;
// path is too short - put no points
if (r < 1.0)
{
curList[k] = 0;
cost += m - l;
}
int a = (int)Math.Floor(r),
b = (int)Math.Ceiling(r);
double costA = Math.Abs(m - l * a),
costB = Math.Abs(m - l * b);
if (costA < costB)
{
curList[k] = a;
cost += costA;
}
else
{
curList[k] = b;
cost += costB;
}
}
}
if (cost < minCost)
{
minCost = cost;
Array.Copy(curList, minList, noSegs);
}
}
return minList;
}
}

Image rotation algorithm for a square pixel grid

I'm currently working on my own little online pixel editor.
Now I'm trying to add a rotation function.
But I can't quite figure out how to realize it.
Here is the basic query for my pixel grid:
for (var y = 0;y < pixelAmount;y++) {
for (var x = 0;x < pixelAmount;x++) {
var name = y + "x" + x;
newY = ?? ;
newX = ?? ;
if ($(newY + "x" + newX).style.backgroundColor != "rgb(255, 255, 255)")
{ $(name).style.backgroundColor = $(newY + "x" + newX).style.backgroundColor; }
}
}
How do I calculate newY and newX?
How do you rotate a two dimensional array?
from this^ post I got this method (in c#):
int a[4][4];
int n=4;
int tmp;
for (int i=0; i<n/2; i++){
for (int j=i; j<n-i-1; j++){
tmp=a[i][j];
a[i][j]=a[j][n-i-1];
a[j][n-i-1]=a[n-i-1][n-j-1];
a[n-i-1][n-j-1]=a[n-j-1][i];
a[n-j-1][i]=tmp;
}
}
or this one:
int[,] array = new int[4,4] {
{ 1,2,3,4 },
{ 5,6,7,8 },
{ 9,0,1,2 },
{ 3,4,5,6 }
};
int[,] rotated = RotateMatrix(array, 4);
static int[,] RotateMatrix(int[,] matrix, int n) {
int[,] ret = new int[n, n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
ret[i, j] = matrix[n - j - 1, i];
}
}
return ret;
}
the first method doesn't use a second array (/matrix) to save memory..
Take a look at this doc (Section 3: Rotating a bitmap with an angle of any value). It walks you through how to do the math and gives you some sample code (C++, but it should be good enough for what you need).
If very quick performance is not of huge importance (which is the case by default), you can consider rotating the picture clockwise by flipping it against the main diagonal and then horizontally. To rotate counterclockwise, flip horizontally, then against the main diagonal. The code is much simpler.
For diagonal flip you exchange the values of image[x,y] with image[y,x] in a loop like this
for( var x = 0; x < pixelAmount; ++x )
for( var y = x + 1; y < pixelAmount; ++y )
swap(image[x,y],image[y,x]);
For horizontal flip you do something like
for( var y = 0; y < pixelAmount; ++y )
{
i = 0; j = pixelAmount - 1;
while( i < j ) {
swap( image[i,y], image[j,y] );
++i; --j;
}
}

find the largest sub- matrix full of ones in linear time

Given an n by n matrix with zeros and ones, find the largest sub-
matrix full of ones in linear time. I was told that a solution with
O(n) time complexity exists. If there are n^2 elements in a n X n
matrix how does a linear solution exist?
Unless you have a non-standard definition of submatrix this problem is NP-hard by reduction from maximum clique.
You can't search a n x n matrix in n time. Counterexample: a matrix of zeros with a single element set to one. You have to check every element to find where that one is, so time must be at least O(n^2).
Now if you say that the matrix has N = n^2 entries, and you only consider submatrices that form a contiguous block, then you should be able to find the largest submatrix by walking diagonally across the matrix, keeping track of every rectangle of ones as you go. You could in general have up to O(sqrt(N)) rectangles active simultaneously, and you would need to search in them to figure out which rectangle was the largest, so you ought to be able to do this in O(N^(3/2) * log(N)) time.
If you can pick arbitrary rows and columns to form your submatrix, then I don't see any obvious polynomial time algorithm.
The solution is linear in the number of entries, not in the number of rows or columns.
public static int biggestSubMatrix(int[][] matrix) {
int[][] newMatrix = new int[matrix.length][matrix[0].length];
for (int i = 0; i < matrix.length; i++) {
int sum = 0;
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j] == 1) {
sum++;
newMatrix[i][j] = sum;
} else {
sum = 0;
newMatrix[i][j] = 0;
}
}
}
int maxDimention = 0;
int maxSubMatrix = 0;
for (int i = 0; i < newMatrix[0].length; i++) {
//find dimention for each column
maxDimention = calcHighestDimentionBySmallestItem(newMatrix, i);
if(maxSubMatrix < maxDimention ){
maxSubMatrix = maxDimention ;
}
}
return maxSubMatrix;
}
private static int calcHighestDimentionBySmallestItem(int[][] matrix, int col) {
int totalMaxDimention =0;
for (int j = 0; j < matrix.length; j++) {
int maxDimention = matrix[j][col];
int numItems = 0;
int min = matrix[j][col];
int dimention = 0;
for (int i = j; i < matrix.length; i++) {
int val = matrix[i][col];
if (val != 0) {
if (val < min) {
min = val;
}
numItems++;
dimention = numItems*min;
if(dimention>maxDimention){
maxDimention = dimention;
}
} else { //case val == 0
numItems = 0;
min = 0;
}
}
if(totalMaxDimention < maxDimention){
totalMaxDimention = maxDimention;
}
}
return totalMaxDimention;
}

cvDilate/cvErode: How to avoid connection between separated objects?

I would like to separate objects in OpenCv like the following image it shows:
But if I am using cvDilate or cvErode the objects grow together... how to do that with OpenCv?
It looks like you will need to write your own dilate function and then add xor functionality yourself.
Per the opencv documentation, here is the rule that cvdilate uses:
dst=dilate(src,element): dst(x,y)=max((x',y') in element))src(x+x',y+y')
Here is pseudocode for a starting point (this does not include xor code):
void my_dilate(img) {
for(i = 0; i < img.height; i++) {
for(j = 0; j < img.width; j++) {
max_pixel = get_max_pixel_in_window(img, i, j);
img.pixel(i,j) = max_pixel;
}
}
}
int get_max_pixel_in_window(img, center_row, center_col) {
int window_size = 3;
int cur_max = 0;
for(i = -window_size; i <= window_size; i++) {
for(j = -window_size; j <= window_size; j++) {
int cur_col = center_col + i;
int cur_row = center_row + j;
if(out_of_bounds(img, cur_col, cur_row)) {
continue;
}
int cur_pix = img.pixel(center_row + i, center_col + j);
if(cur_pix > cur_max) {
cur_max = cur_pix;
}
}
}
return cur_max;
}
// returns true if the x, y coordinate is outside of the image
int out_of_bounds(img, x, y) {
if(x >= img.width || x < 0 || y >= img.height || y <= 0) {
return 1;
}
return 0;
}
As far as I know OpenCV does not have "dilation with XOR" (although that would be very nice to have).
To get similar results you might try eroding (as in 'd'), and using the eroded centers as seeds for a Voronoi segmentation which you could then AND with the original image.
after erosion and dilate try thresholding the image to eliminate weak elements. Only strong regions should remain and thus improve the object separation. By the way could you be a little more clear about your problem with cvDilate or cvErode.

Resources