Parallel.For with raster image processing - c#

I want to speed my code up. I'd like that snippet to work faster. I tried to create my own Parallel.For implementation of the loop, but I failed. No errors, but tifDS seems to be empty:/ Could any1 help me? Thanks in advance!
Original loops:
for (int iY = 0; iY < srcDS.RasterYSize; iY++)
{
byte[] srcData = new byte[srcDS.RasterXSize * 1];
srcBand.ReadRaster(0, iY, srcDS.RasterXSize, 1, srcData, srcDS.RasterXSize, 1, 0, 0);
for (int iBand = 0; iBand < _outBands; iBand++)
{
int[] bandLookup = lookup[iBand];
int[] dstData = new int[srcData.Count()];
for (int index = 0; index < srcData.Count(); index++)
{
byte b = srcData[index];
dstData[index] = bandLookup[b];
}
tifDS.GetRasterBand(iBand + 1).WriteRaster(0, iY, srcDS.RasterXSize, 1, dstData,
srcDS.RasterXSize, 1, 0, 0);
}
}
My tries:
for (int iY = 0; iY < srcDS.RasterYSize; iY++)
{
byte[] srcData = new byte[srcDS.RasterXSize * 1];
srcBand.ReadRaster(0, iY, srcDS.RasterXSize, 1, srcData, srcDS.RasterXSize, 1, 0, 0);
Parallel.For<object>((long) 0, _outBands, () => 0,
(iBand, state, subtotal) =>
{
int[] bandLookup = lookup[iBand];
int[] dstData = new int[srcData.Count()];
for (int index = 0; index < srcData.Count(); index++)
{
byte b = srcData[index];
dstData[index] = bandLookup[b];
}
return new object[] {iBand, dstData};
},
o =>
{
int iBand = (int) (o as object[])[0];
int[] dstData = (o as object[])[1] as int[];
lock (_getRasterBandLock)
{
tifDS.GetRasterBand(iBand + 1).WriteRaster(0, iY, srcDS.RasterXSize, 1, dstData,
srcDS.RasterXSize, 1, 0, 0);
}
});
}

Related

Wrong output of Dijkstra algorithm using C#

I tried to implement dijkstra algorithm in c# but the output is wrong and it can not calculate right distance from source node.
I use an array called distance to update and store shortest path from source node.
Vertex list is declared to save intermediate nodes that construct shortest path.
Here is my code :
namespace Dijkstra
{
public class Program
{
static void Main(string[] args)
{
int[][] graph = {
new int []{ 0, 1, 7, 0, 0 },
new int [] { 0, 0, 4,4, 1},
new int []{ 0, 0, 0, 3, 2 },
new int []{ 0, 0, 0, 0, 5 },
new int []{ 0, 0, 0, 0, 0 } };
ShortestPath(graph, 0);
}
static void ShortestPath(int[][]graph,int source)
{
int nodes = graph.GetLength(0);
int[] distance = new int[nodes];
List<int> vertex = new List<int>();
List<int> edge = new List<int>();
int nearvertex = 0;
int min = int.MaxValue;
for(int i = 0; i< graph.GetLength(0); i++)
{
distance[i] = graph[source][i];
if (distance[i] == 0 && i != source)
distance[i] = int.MaxValue;
}
while(nodes-1 > 0)
{
min = int.MaxValue;
for (int j = 0; j < graph.GetLength(0); j++)
{
if (distance[j] <= min && 0 < distance[j] && !vertex.Contains(j))
{
min = distance[j];
nearvertex = j;
}
}
edge.Add(min);
for (int i = 0; i < graph.GetLength(0); i++)
{
if (distance[nearvertex] + graph[nearvertex][i] < distance[i] &&!vertex.Contains(i))
{
distance[i] = distance[nearvertex] + graph[nearvertex][i];
vertex.Add(nearvertex);
}
}
distance[nearvertex] = -1;
nodes--;
}
foreach(var i in edge)
Console.WriteLine(i);
}
}
}
Is there any problem with comparisons in for loops?
How can i fix it?
There are few things wrong on your code. I'll point them for you.
See below code and comments.
static void ShortestPath(int[][] graph, int source)
{
int nodes = graph.GetLength(0);
int[] distance = new int[nodes];
List<int> vertex = new List<int>();
int nearvertex = 0;
int min = int.MaxValue;
for (int i = 0; i < distance.Length; i++)
{
// Distance array should be initialized to max except source vertex.
distance[i] = int.MaxValue;
}
distance[source] = 0;
while (nodes - 1 > 0)
{
min = int.MaxValue;
for (int j = 0; j < graph.GetLength(0); j++)
{
// 0 < distance[j] --> 0 <= distance[j] : starting point distance is 0, so should be <=
if (distance[j] <= min && 0 <= distance[j] && !vertex.Contains(j))
{
min = distance[j];
nearvertex = j;
}
}
//edge.Add(min); edge array is unnecessary.
for (int i = 0; i < graph.GetLength(0); i++)
{
// you are using 0 as un-reachable distance value in your graph array, so you should check it.
if (distance[nearvertex] + graph[nearvertex][i] < distance[i] && graph[nearvertex][i] > 0 && !vertex.Contains(i))
{
distance[i] = distance[nearvertex] + graph[nearvertex][i];
vertex.Add(nearvertex);
}
}
//distance[nearvertex] = -1; No change required after refreshing distance array.
nodes--;
}
// shortest path from source ( 0 ) will be restored in distance array.
foreach (var i in distance)
Console.WriteLine(i);
}
Sample Result
// 0, 1, 7, 0, 0
// 0, 0, 4, 4, 1
// 0, 0, 0, 3, 2
// 0, 0, 0, 0, 5
// 0, 0, 0, 0, 0
0 // source vertex
1 // 0 -> 1
5 // 0 -> 1 -> 2
5 // 0 -> 1 -> 3
2 // 0 -> 1 -> 4

C# Changing values between 2 arrays

I'm trying to change values between two arrays, but im not getting get that right.
This is what I've done so far
I cant show the total of the first array and i cant make any swap at the second array
public static void exe4()
{
int[,] matriz1 = new int[,] { { -2, 3, 4, 11, -8 }, { -1, 0, -12, -6, 9 }, { 23, 4, 6, 8, -3 } };
int[,] matriz2 = new int[,] { { 2, 3, 8 }, { -2, -4, -5 }, { 0, 8, -14 }, { 3, 5, 6 }, { -9, -8, -1 } };
int troca1 = 0;
int troca2 = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
troca1 = matriz1[i, j];
matriz1[1, 0] = matriz2[0, 2];
matriz1[1, 1] = matriz2[1, 2];
matriz1[1, 4] = matriz2[4, 1];
}
Console.WriteLine();
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
troca2 = matriz2[i, j];
matriz2[0, 2] = matriz1[1, 0];
matriz2[1, 2] = matriz1[1, 1];
matriz2[4, 2] = matriz1[1, 4];
}
Console.WriteLine();
}
Console.WriteLine("\nApĆ³s a troca dos valores:\n");
Console.WriteLine("Matriz1:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write("{0}\t", matriz1[i, j]);
}
Console.WriteLine();
}
Console.WriteLine("\nMatriz2:\n");
Console.WriteLine();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write("{0}\t", matriz2[i, j]);
}
Console.WriteLine();
}
That's how it's supposed to be:
Analyzing your solution
It sounds like you're only interested in swapping very few and specific values in those matrices, so for-loops seem unnecessary as you already know the positions in the matrices you want to swap.
Apart from that I noticed that your for-loops only goes from 0 to 2 (for (int i = 0; i < 3; i++)) but your matrices have a length of 4 in one dimension, so the loops never reach the ends.
An alternative solution
If you just want to swap those specific values, you could do it like this:
int[,] matriz1 = new int[,]
{
{ -2, 3, 4, 11, -8 },
{ -1, 0, -12, -6, 9 },
{ 23, 4, 6, 8, -3 }
};
int[,] matriz2 = new int[,]
{
{ 2, 3, 8 },
{ -2, -4, -5 },
{ 0, 8, -14 },
{ 3, 5, 6 },
{ -9, -8, -1 }
};
int temporary;
// Swap A[1,0] with B[0,2]
temporary = matriz1[1,0];
matriz1[1,0] = matriz2[0,2];
matriz2[0,2] = temporary;
// Swap A[1,1] with B[1,2]
temporary = matriz1[1,0];
matriz1[1,1] = matriz2[1,2];
matriz2[1,2] = temporary;
// Swap A[1,4] with B[4,2]
temporary = matriz1[1,0];
matriz1[1,4] = matriz2[4,2];
matriz2[4,2] = temporary;
... or with a little helper function:
void Swap(int[,] matrixA, int row1, int col1, int[,] matrixB, int row2, int col2)
{
var temp = matrixA[row1, col1];
matrixA[row1, col1] = matrixB[row2, col2];
matrixB[row2, col2] = temp;
}
// ...
Swap(matriz1, 1, 0, matriz2, 0, 2);
Swap(matriz1, 1, 1, matriz2, 1, 2);
Swap(matriz1, 1, 4, matriz2, 4, 2);

Square with Maximum Sum

I am learning C#, and I am doing Multidimensional Arrays at the moment. I want to write a program that reads a matrix and then finds the biggest sum of 2x2 submatrix and prints it.
int[] dimensions = Console.ReadLine()
.Split(", ", StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
int rows = dimensions[0];
int columns = dimensions[1];
int[,] matrix = new int[rows,columns];
for (int i = 0; i < rows; i++)
{
int[] numbers = Console.ReadLine()
.Split(", ", StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
for (int j = 0; j < columns; j++)
{
matrix[i, j] = numbers[j];
}
}
int maxSum = int.MinValue;
int selectedRow = -1;
int selectedCol = -1;
for (int row = 0; row < matrix.GetLength(0) - 1; row++)
{
for (int col = 0; col < matrix.GetLength(1) - 1; col++)
{
int currentSum = matrix[row, col] + matrix[row, col + 1] + matrix[row + 1, col] + matrix[row + 1, col + 1];
if (currentSum > maxSum)
{
maxSum = currentSum;
selectedRow = row;
selectedCol = col;
}
}
}
Console.WriteLine($"{matrix[selectedRow, selectedCol]} {matrix[selectedRow, selectedCol + 1]}");
Console.WriteLine($"{matrix[selectedRow + 1, selectedCol]} {matrix[selectedRow + 1, selectedCol + 1]}");
Console.WriteLine(maxSum);
So, I read the matrix, but I am not sure how to start finding the submatrices and compare their sums. I would be very grateful if you could give me some hints.
You need to check values only current, under positions of your i and current, right positions of your j.
I mean it will check like this:
[7,1] [1,3] [3,3]
[1,3] [3,9] [9,8]
And so on.
After every compare, calculate sum of this 2x2 matrix and save it to dictionary.
For return, you just need to find the max value of key and get value of it key.
public class MatrixTest
{
public static IEnumerable<object[]> TestData =>
new List<object[]>
{
new object[]
{
new int[,]
{
{7, 1, 3, 3, 2, 1},
{1, 3, 9, 8, 5, 6},
{4, 6, 7, 9, 1, 0}
},
new int[,]
{
{9, 8},
{7, 9}
},
33
},
new object[]
{
new int[,]
{
{10, 11, 12, 13},
{14, 15, 16, 17}
},
new int[,]
{
{12, 13},
{16, 17}
},
58
}
};
[Theory]
[MemberData(nameof(TestData))]
public void Test(int[,] input, int[,] expectedArray, int expectedSum)
{
MatrixHandler m = new MatrixHandler();
var resp = m.GetMax2x2Matrix(input);
resp.Item1.Should().Be(expectedSum);
resp.Item2.Should().BeEquivalentTo(expectedArray);
}
}
public class MatrixHandler
{
public (int, int[,]) GetMax2x2Matrix(int[,] source)
{
var sumsPlusTempArrays = new Dictionary<int, int[,]>();
int[,] temp;
int sum = 0;
for (int i = 0, n0 = source.GetLength(0) - 1; i <= n0; i++)
{
for (int j = 0, n1 = source.GetLength(1) - 1; j <= n1; j++)
{
if (i + 1 <= n0 && j + 1 <= n1)
{
temp = new int[2,2];
temp[0, 0] = source[i, j];
temp[0, 1] = source[i, j + 1];
temp[1, 0] = source[i + 1, j];
temp[1, 1] = source[i + 1, j + 1];
sum = CalculateSum(temp);
sumsPlusTempArrays.TryAdd(sum, temp);
}
}
}
var key = sumsPlusTempArrays.Select(x => x.Key).Max();
var value = sumsPlusTempArrays[key];
return (key, value);
}
private int CalculateSum(int[,] source)
{
int sum = 0;
for (int i = 0, n0 = source.GetLength(0); i < n0; i++)
{
for (int j = 0, n1 = source.GetLength(1); j < n1; j++)
{
sum += source[i, j];
}
}
return sum;
}
}

Write 3 arrays to 1

I have 3 arrays: x, y and z. How can I write all three to one in one-after-one mode?
For example: I have X=1,2 Y=3,4 Z=5,6
I need an array W = X[1],Y[1],Z[1],X[2],Y[2],Z[2] ... X[n],Y[n],Z[n]
float[] posX = new float[rmv2.lod[0].VerticesCount[0]];
float[] posY = new float[rmv2.lod[0].VerticesCount[0]];
float[] posZ = new float[rmv2.lod[0].VerticesCount[0]];
for (int i = 0; i < 1; i += 3)
{
posX[i] = rmv2.lod[0].Mesh[0].Vertex[i].X;
posY[i + 1] = rmv2.lod[0].Mesh[0].Vertex[i].Y;
posZ[i + 2] = rmv2.lod[0].Mesh[0].Vertex[i].Z;
}
I don't see the w array you're trying to write the output to. Are you looking for something like this?
int n = rmv2.lod[0].VerticesCount[0];
float[] posX = new float[n];
float[] posY = new float[n];
float[] posZ = new float[n];
float[] w = new float[n * 3];
for (int i = 0; i < n; i++)
{
posX[i] = rmv2.lod[0].Mesh[0].Vertex[i].X;
posY[i] = rmv2.lod[0].Mesh[0].Vertex[i].Y;
posZ[i] = rmv2.lod[0].Mesh[0].Vertex[i].Z;
w[i * 3 + 0] = rmv2.lod[0].Mesh[0].Vertex[i].X;
w[i * 3 + 1] = rmv2.lod[0].Mesh[0].Vertex[i].Y;
w[i * 3 + 2] = rmv2.lod[0].Mesh[0].Vertex[i].Z;
}
Perhaps you should look at jagged arrays...
https://msdn.microsoft.com/en-us/library/2s05feca.aspx
Try this:
float[] x = new float[] { 1, 2, 9 };
float[] y = new float[] { 3, 4 };
float[] z = new float[] { 5, 6 };
int max = Math.Max(x.Length, Math.Max(y.Length, z.Length));
List<float> combined = new List<float>();
for (int i = 0; i < max; i++)
{
if (x.Length > i) combined.Add(x[i]);
if (y.Length > i) combined.Add(y[i]);
if (z.Length > i) combined.Add(z[i]);
}
Produces a list with the combined arrays, regardless of their original lengths.
1, 3, 5, 2, 4, 6, 9
If I right understand you, try this solution. With this method arrays can have different length
static T[] ConcatOneAfterOne<T>(params T[][] arrays)
{
int outputArrayLength = 0;
for (int i = 0; i < arrays.Length; i++)
{
outputArrayLength += arrays[i].Length;
}
T[] output = new T[outputArrayLength];
int outputIndex = 0;
int sourceIndex = 0;
while (outputIndex != outputArrayLength)
{
for (int arrayIndex = 0; arrayIndex < arrays.Length; arrayIndex++)
{
if (sourceIndex < arrays[arrayIndex].Length)
{
output[outputIndex++] = arrays[arrayIndex][sourceIndex];
}
}
sourceIndex++;
}
return output;
}
[Test]
static void ConcatOneAfterOneTest()
{
int[] result = ConcatOneAfterOne(new[] { 1, 2 }, new[] { 3, 4 }, new[] { 5, 6 });
CollectionAssert.AreEqual(new int[] { 1, 3, 5, 2, 4, 6 }, result);
}

How to Get Adjacency matrix from a matrix in c#

supposing I have a matrix like
0 -1 0 0
0 0 -1 0
0 0 0 0
0 0 -1 -1
so in this case The matrix represents:
0's are conected and -1 are not
How can I get Adjacency matrix from it?
I know
h[i][j] = 0, if there is no direct link from i to j
(i and j are not neighbors)
h[i][j] = 1, if there is a direct link from i to j
(i and j are neighbors)
so I am doing something like:
Int32[,] original = new int[4, 4]
{
{0, -1, 0, 0},
{0, 0, -1, 0},
{0, 0, 0, 0},
{0, 0, -1, -1}
}
Int32[,] adjacent;
for (int i = 0; i < original.GetLength(0); i++){
for (int j = 0; j < original.GetLength(1); j++) {
//How to know if there is direct link from i to j
//if(){
// adjacent[i,j]=0;
//}else{
// adjacent[i,j]=1;
//}
}
}
The original code has a problem - the matrixes adjacent and original are not usually the same size.
But it's close, in a way.
Code not tested:
int size = original.GetLength(0) * original.GetLength(1);
int[,] adjacent = new int[size, size];
for (int i = 0; i < original.GetLength(0); i++) {
for (int j = 0; j < original.GetLength(1); j++) {
if (original[i, j] == 0) {
// up/down
if (j > 0 && original[i, j - 1] == 0) {
adjacent[remap(i, j), remap(i, j - 1)] = 1;
adjacent[remap(i, j - 1), remap(i, j)] = 1;
}
// left/right
if (i > 0 && original[i - 1, j] == 0) {
adjacent[remap(i, j), remap(i - 1, j)] = 1;
adjacent[remap(i - 1, j), remap(i, j)] = 1;
}
}
}
}
remap maps a 2D point to a "node index". It may need more arguments. It could be something like:
int remap(int i, int j, int width)
{
return width * i + j;
}
There are other possibilities, but this is the simplest.
The adjacency matrix is an n by n matrix for a graph with n nodes (see an example here), as #harold has stated already. So you need to map between the physical (i,j) coordinates of the node in your grid, and the node number which is between 0 and n-1.
Here is some code that is along the right lines. I have looked at the output in the debugger and checking the first couple of rows it looked ok.
class Program
{
static void AddToAdjacencyMatrix(Int32[,] adjacency, Int32[,] original,
Dictionary<Tuple<int, int>, int> coordinate2NodeNum,
Tuple<int, int> fromCoord, int deltaX, int deltaY)
{
Tuple<int, int> toCoord = new Tuple<int, int>(
fromCoord.Item1 + deltaX, fromCoord.Item2 + deltaY);
try { // quick and dirty way of catching out of range coordinates
if (original[toCoord.Item1,toCoord.Item2] == 0) {
int fromNodeNum = coordinate2NodeNum[fromCoord];
int toNodeNum = coordinate2NodeNum[toCoord];
adjacency[fromNodeNum, toNodeNum] = 1;
adjacency[toNodeNum, fromNodeNum] = 1;
}
}
catch {
}
}
static void Main(string[] args)
{
Int32[,] original = new int[4, 4]
{
{0, -1, 0, 0},
{0, 0, -1, 0},
{0, 0, 0, 0},
{0, 0, -1, -1}
};
// Adjacency matrix has column and row headings for each node in graph
// Therefore we need to map between the node number in the adjacency matrix
// (i.e. the column or row heading) and the physical grid coordinates
Dictionary<int, Tuple<int, int>> nodeNum2Coordinate = new Dictionary<int, Tuple<int, int>>();
Dictionary<Tuple<int, int>, int> coordinate2NodeNum = new Dictionary<Tuple<int, int>, int>();
int nodeCount = 0;
for (int i = 0; i < original.GetLength(0); i++){
for (int j = 0; j < original.GetLength(1); j++) {
if (original[i, j] == 0) {
Tuple<int, int> coord = new Tuple<int, int>(i,j);
nodeNum2Coordinate.Add(nodeCount, coord);
coordinate2NodeNum.Add(coord, nodeCount);
nodeCount++;
}
}
}
// Now create the adacency matrix
Int32[,] adjacency = new int[nodeCount, nodeCount];
for (int i = 0; i < original.GetLength(0); i++){
for (int j = 0; j < original.GetLength(1); j++) {
if (original[i, j] == 0) {
Tuple<int, int> fromCoord = new Tuple<int, int>(i,j);
// Check connections
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
-1, 0); // UP
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
+1, 0); // DOWN
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
0, -1); // LEFT
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
0, +1); // UP
}
}
}
Console.ReadLine();
}
}

Categories