I got the following codes:
Boo[,,] boos = new Boo[8, 8, 8];
Boo GetMe(int i, int j, int k)
{
return boos[i, j, k];
}
The code above is inefficient so i convert it to one dimensional array:
Boo[] boosone;
Boo[,,] boos = new Boo[8, 8, 8];
Boo GetMe(int i, int j, int k)
{
if (boosone == null)
{
boosone = new Boo[8 * 8 * 8];
int num = 0;
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
for (int z = 0; z < 8; z++)
{
boosone[num] = boos[x, y, z];
num++;
}
}
}
}
return boosone[?];
}
How can I get the Boo (from the same position like in multidimensional array j k l) from the one dimensional array boosone?
int index = (8 * 8 * i) + (8 * j) + k;
return boosone[index];
Not really sure why you're saying that the first 3D array is not efficient (I mean, have you actually noticed a particularly heavy slowdown when using it?), but you can do that with some simple offset calculations.
First of all, if you target the latest C# version, you can replace the whole copy function with just two lines, and your code would then look like this:
using System;
using System.Runtime.InteropServices;
Boo[] boosone;
Boo[,,] boos = new Boo[8, 8, 8];
Boo GetMe(int i, int j, int k)
{
if (boosone == null)
{
boosone = new Boo[boos.Length];
MemoryMarshal.CreateSpan(ref boos[0, 0, 0], boosone.Length).CopyTo(boosone);
}
return boosone[boos.GetLength(1) * boos.GetLength(2) * i + boos.GetLength(2) * j + k];
}
If you don't want to use the MemoryMarshal class for some reason, you could also use LINQ to flatten your 3D array, although this approach is much less efficient:
boosone = boos.Cast<Boo>().ToArray();
Accessing a multi dimensional array isn't any slower then accessing a single dimension array, in fact they are both stored in memory exactly the same way. It's not what you are doing, it's how you are doing it.
If you want to wrap either array in a trivial method, give the compiler a hint that it can be inline
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Boo GetMe(int i, int j, int k)
{
return boos[i, j, k];
}
On saying that, this method does absolutely nothing and has no advantage then just using the array indexer.
If you want to work with segments of an array with out the overhead of reallocation, consider using Span<T> or Memory<T> or ArraySegment
At about this point I would write example code, however as I have no idea what you are doing, it's hard to guess what you need.
What I suggest, is download BenchmarkDotNet, and start profiling your code to work out what is the most efficient and performant way to do what you desire, don't guess...
Why don't you look at jagged arrays which provide better performance? I did a test (under RELEASE configuration) which showed that you wrapper is twice faster than the d3 array, but jagged is 3 times faster than the d3 array.
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
namespace ArrayWrapper
{
class ArrayPerformanceTest
{
int xSize = 2;
int ySize = 3;
int zSize = 4;
int count = 100000000;
int delay = 500;
static void Main(string[] args)
{
new ArrayPerformanceTest().Run();
}
private void Run()
{
var d3Array = CreateD3Array();
var wrapped = GetD1Adapter(d3Array);
var jagged = GetJaggedArray(d3Array);
Thread.Sleep(delay);
TestD3Array(d3Array);
Thread.Sleep(delay);
TestWrappedArray(wrapped);
Thread.Sleep(delay);
TestJaggeddArray(jagged);
Thread.Sleep(delay);
}
private int[,,] CreateD3Array()
{
var rectangular = new int[xSize, ySize, zSize];
int i = 7;
for (var x = 0; x < xSize; x++)
for (var y = 0; y < ySize; y++)
for (var z = 0; z < zSize; z++)
rectangular[x, y, z] = ++i;
return rectangular;
}
private int[] GetD1Adapter(int[,,] d3Array)
{
return d3Array.Cast<int>().ToArray();
}
private int[][][] GetJaggedArray(int[,,] d3Array)
{
var xSize = d3Array.GetUpperBound(0) + 1;
var ySize = d3Array.GetUpperBound(1) + 1;
var zSize = d3Array.GetUpperBound(2) + 1;
var jagged = new int[xSize].Select(j => new int[ySize].Select(k => new int[zSize].ToArray()).ToArray()).ToArray();
for (var x = 0; x < xSize; x++)
for (var y = 0; y < ySize; y++)
for (var z = 0; z < zSize; z++)
jagged[x][y][z] = d3Array[x, y, z];
return jagged;
}
private void TestD3Array(int[,,] d3Array)
{
int i;
var sw = new Stopwatch();
sw.Start();
for (var c = 0; c < count; c++)
for (var x = 0; x < xSize; x++)
for (var y = 0; y < ySize; y++)
for (var z = 0; z < zSize; z++)
i = d3Array[x, y, z];
sw.Stop();
Console.WriteLine($"{nameof(d3Array),7} {sw.ElapsedTicks,10}");
}
private void TestWrappedArray(int[] wrapped)
{
int i;
var sw = new Stopwatch();
sw.Start();
for (var c = 0; c < count; c++)
for (var x = 0; x < xSize; x++)
for (var y = 0; y < ySize; y++)
for (var z = 0; z < zSize; z++)
i = wrapped[x * ySize * zSize + y * zSize + z];
sw.Stop();
Console.WriteLine($"{nameof(wrapped),7} {sw.ElapsedTicks,10}");
}
private void TestJaggeddArray(int[][][] jagged)
{
int i;
var sw = new Stopwatch();
sw.Start();
for (var c = 0; c < count; c++)
for (var x = 0; x < xSize; x++)
for (var y = 0; y < ySize; y++)
for (var z = 0; z < zSize; z++)
i = jagged[x][y][z];
sw.Stop();
Console.WriteLine($"{nameof(jagged),7} {sw.ElapsedTicks,10}");
}
}
}
Output:
d3Array 15541709
wrapped 8213316
jagged 5322008
I also analysed CPU usage.
It is of the same rate for all 3 approaches.
Related
Using unity to create a procedural map I'm getting the Error "Cs0161: not all code paths return a value" , I'm still pretty new to coding and I may have made some mistake.
I've tried google but the answers don't even make sense to me
yet
MapData GenerateMapData()
{
float[,] noiseMap = Noise.GenerateNoiseMap(mapChunkSize, mapChunkSize, seed, noiseScale, octaves, lacunarity, persistance, offset);
Color[] colourMap = new Color[mapChunkSize * mapChunkSize];
for (int y = 0; y < mapChunkSize; y++)
{
for (int x = 0; x < mapChunkSize; x++)
{
float currentHeight = noiseMap[x, y];
for (int i = 0; i < regions.Length; i++)
{
if (currentHeight <= regions[i].height)
{
colourMap[y * mapChunkSize + x] = regions[i].colour;
break;
}
}
}
return new MapData(noiseMap, colourMap);
}
}
Error CS0161 'MapGenerator.GenerateMapData()': not all code paths return a value Assembly-CSharp
After the for loops you should also return a value. See the code below and the comment at the bottom of the method:
MapData GenerateMapData()
{
float[,] noiseMap = Noise.GenerateNoiseMap(mapChunkSize, mapChunkSize, seed, noiseScale, octaves, lacunarity, persistance, offset);
Color[] colourMap = new Color[mapChunkSize * mapChunkSize];
for (int y = 0; y < mapChunkSize; y++)
{
for (int x = 0; x < mapChunkSize; x++)
{
float currentHeight = noiseMap[x, y];
for (int i = 0; i < regions.Length; i++)
{
if (currentHeight <= regions[i].height)
{
colourMap[y * mapChunkSize + x] = regions[i].colour;
break;
}
}
}
return new MapData(noiseMap, colourMap);
}
// You should also return something here
}
It is theoretically possible that mapChunkSize can have a value of 0 (zero) and it will not enter the first for loop at all. That's why you need a return statement at the bottom as well.
The reason why you are receiving that error is because your return statement is inside the for loops. More specifically, it can happen that neither of the loops execute (e.g. mapChunkSize == 0. Then 0 isn't less than 0 and the program doesn't enter the for loops) and that thus nothing gets returned. So either move the return outside the loops or add another return outside the loops.
MapData GenerateMapData()
{
float[,] noiseMap = Noise.GenerateNoiseMap(mapChunkSize, mapChunkSize, seed, noiseScale, octaves, lacunarity, persistance, offset);
Color[] colourMap = new Color[mapChunkSize * mapChunkSize];
for (int y = 0; y < mapChunkSize; y++)
{
for (int x = 0; x < mapChunkSize; x++)
{
float currentHeight = noiseMap[x, y];
for (int i = 0; i < regions.Length; i++)
{
if (currentHeight <= regions[i].height)
{
colourMap[y * mapChunkSize + x] = regions[i].colour;
break;
}
}
}
/*return new MapData(noiseMap, colourMap); //uncommenting this might still leave you with the functionality you want */
}
return new MapData(noiseMap, colourMap);
}
you are not returning any thing outside the first loop, try to evaluate values inside the loops and then return from outside the loop.
for (int y = 0; y < mapChunkSize; y++)
{
for (int x = 0; x < mapChunkSize; x++)
{
float currentHeight = noiseMap[x, y];
for (int i = 0; i < regions.Length; i++)
{
if (currentHeight <= regions[i].height)
{
colourMap[y * mapChunkSize + x] = regions[i].colour;
break;
}
}
}
return new MapData(noiseMap, colourMap);
}
add return statement here
UPDATE: The span issues that were mentioned previously were fixed in the .net core 2.1 release (which is currently in preview.) These actually made the Span Vector *faster* than the array Vector...
NB: Testing this on a "Intel Xeon E5-1660 v4" which CPU-Z tells me has Instructions for "MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES, AVX, AVX2, FMA3, RSX" so it should be OK...
Off the back of answering a Vector based question, I thought I would try to implement some BLAS functions. I found that ones that were reading/summing such as dot product were pretty good, but were I was writing back to an array were bad - better than non-SIMD, but barely.
So am I doing something wrong, or is there more work in the JIT required?
The example (assuming x.Length = y.Length, not null etc. blah, blah):
public static void daxpy(double alpha, double[] x, double[] y)
{
for (var i = 0; i < x.Length; ++i)
y[i] = y[i] + x[i] * alpha;
}
In Vector form becomes:
public static void daxpy(double alpha, double[] x, double[] y)
{
var i = 0;
if (Vector.IsHardwareAccelerated)
{
var length = x.Length + 1 - Vector<double>.Count;
for (; i < length; i += Vector<double>.Count)
{
var valpha = new Vector<double>(alpha);
var vx = new Vector<double>(x, i);
var vy = new Vector<double>(y, i);
(vy + vx * valpha).CopyTo(y, i);
}
}
for (; i < x.Length; ++i)
y[i] = y[i] + x[i] * alpha;
}
And, playing around in .NET Core 2.0, I though I would try Span, both naive and Vector form:
public static void daxpy(double alpha, Span<double> x, Span<double> y)
{
for (var i = 0; i < x.Length; ++i)
y[i] += x[i] * alpha;
}
And Vector
public static void daxpy(double alpha, Span<double> x, Span<double> y)
{
if (Vector.IsHardwareAccelerated)
{
var vx = x.NonPortableCast<double, Vector<double>>();
var vy = y.NonPortableCast<double, Vector<double>>();
var valpha = new Vector<double>(alpha);
for (var i = 0; i < vx.Length; ++i)
vy[i] += vx[i] * valpha;
x = x.Slice(Vector<double>.Count * vx.Length);
y = y.Slice(Vector<double>.Count * vy.Length);
}
for (var i = 0; i < x.Length; ++i)
y[i] += x[i] * alpha;
}
So the relative timings on all these are:
Naive 1.0
Vector 0.8
Span Naive 2.5 ==> Update: Span Naive 1.1
Span Vector 0.9 ==> Update: Span Vector 0.6
So am I doing something wrong? I could hardly think of a simpler example, so I don't think so?
You probably want to test with 2.1 more than 2.0;
on my laptop (which has poor SIMD compared to my desktop), I get:
daxpy_naive x10000: 144ms
daxpy_arr_vector x10000: 77ms
daxpy_span x10000: 173ms
daxpy_vector x10000: 67ms
daxpy_vector_no_slice x10000: 67ms
using code:
using System;
using System.Diagnostics;
using System.Numerics;
class Program
{
static void Main(string[] args)
{
double alpha = 0.5;
double[] x = new double[16 * 1024], y = new double[x.Length];
var rand = new Random(12345);
for (int i = 0; i < x.Length; i++)
x[i] = rand.NextDouble();
RunAll(alpha, x, y, 1, false);
RunAll(alpha, x, y, 10000, true);
}
private static void RunAll(double alpha, double[] x, double[] y, int loop, bool log)
{
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
var watch = Stopwatch.StartNew();
for(int i = 0; i < loop; i++)
{
daxpy_naive(alpha, x, y);
}
watch.Stop();
if (log) Console.WriteLine($"{nameof(daxpy_naive)} x{loop}: {watch.ElapsedMilliseconds}ms");
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
{
daxpy_arr_vector(alpha, x, y);
}
watch.Stop();
if (log) Console.WriteLine($"{nameof(daxpy_arr_vector)} x{loop}: {watch.ElapsedMilliseconds}ms");
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
{
daxpy_span(alpha, x, y);
}
watch.Stop();
if (log) Console.WriteLine($"{nameof(daxpy_span)} x{loop}: {watch.ElapsedMilliseconds}ms");
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
{
daxpy_vector(alpha, x, y);
}
watch.Stop();
if (log) Console.WriteLine($"{nameof(daxpy_vector)} x{loop}: {watch.ElapsedMilliseconds}ms");
watch = Stopwatch.StartNew();
for (int i = 0; i < loop; i++)
{
daxpy_vector_no_slice(alpha, x, y);
}
watch.Stop();
if (log) Console.WriteLine($"{nameof(daxpy_vector_no_slice)} x{loop}: {watch.ElapsedMilliseconds}ms");
}
public static void daxpy_naive(double alpha, double[] x, double[] y)
{
for (var i = 0; i < x.Length; ++i)
y[i] = y[i] + x[i] * alpha;
}
public static void daxpy_arr_vector(double alpha, double[] x, double[] y)
{
var i = 0;
if (Vector.IsHardwareAccelerated)
{
var length = x.Length + 1 - Vector<double>.Count;
for (; i < length; i += Vector<double>.Count)
{
var valpha = new Vector<double>(alpha);
var vx = new Vector<double>(x, i);
var vy = new Vector<double>(y, i);
(vy + vx * valpha).CopyTo(y, i);
}
}
for (; i < x.Length; ++i)
y[i] = y[i] + x[i] * alpha;
}
public static void daxpy_span(double alpha, Span<double> x, Span<double> y)
{
for (var i = 0; i < x.Length; ++i)
y[i] += x[i] * alpha;
}
public static void daxpy_vector(double alpha, Span<double> x, Span<double> y)
{
if (Vector.IsHardwareAccelerated)
{
var vx = x.NonPortableCast<double, Vector<double>>();
var vy = y.NonPortableCast<double, Vector<double>>();
var valpha = new Vector<double>(alpha);
for (var i = 0; i < vx.Length; ++i)
vy[i] += vx[i] * valpha;
x = x.Slice(Vector<double>.Count * vx.Length);
y = y.Slice(Vector<double>.Count * vy.Length);
}
for (var i = 0; i < x.Length; ++i)
y[i] += x[i] * alpha;
}
public static void daxpy_vector_no_slice(double alpha, Span<double> x, Span<double> y)
{
int i = 0;
if (Vector.IsHardwareAccelerated)
{
var vx = x.NonPortableCast<double, Vector<double>>();
var vy = y.NonPortableCast<double, Vector<double>>();
var valpha = new Vector<double>(alpha);
for (i = 0; i < vx.Length; ++i)
vy[i] += vx[i] * valpha;
i = Vector<double>.Count * vx.Length;
}
for (; i < x.Length; ++i)
y[i] += x[i] * alpha;
}
}
which is using dotnet build -c Release and dotnet run -c Release, with dotnet --version reporting "2.2.0-preview1-008000" (a "daily" from a little while ago).
On my desktop, I would expect the difference to be even better.
I've run into a stall trying to put together some code to average out 10x10 subarrays of a 2D multidimensional array.
Given a multidimensional array
var myArray = new byte[100, 100];
How should I go about creating 100 subarrays of 100 bytes (10x10) each.
Here are some examples of the value indexes the subarrays from the multidimensional would contain.
[x1,y1,x2,y2]
Subarray1[0,0][9,9]
Subarray2[10,10][19,19]
Subarray3[20,20][29,29]
Given these subarrays, I would then need to average the subarray values to create a byte[10,10] from the original byte[100,100].
I realize this is not unbelievably difficult, but after spending 4 days debugging very low-level code and now getting stuck on this would appreciate some fresh eyes.
Use this as a reference. I used ints just for ease of use. Code is untested. but the idea is there.
var rowSize = 100;
var colSize = 100;
var arr = new int[rowSize, colSize];
var r = new Random();
for (int i = 0; i < rowSize; i++)
for (int j = 0; j < colSize; j++)
arr[i, j] = r.Next(20);
for (var subcol = 0; subcol < colSize / 10; subcol++)
{
for (var subrow = 0; subrow < colSize/10; subrow++)
{
var startX = subcol*10;
var startY = subrow*10;
var avg = 0;
for (var x=0; x<10; x++)
for (var y = 0; y < 10; y++)
avg += arr[startX + x, startY + y];
avg /= 10*10;
Console.WriteLine(avg);
}
}
It looks like you're new to SO. Next time try to post your attempt at the problem; it's better to fix your code.
The only challenge is figuring out the function, that given the subarray index we're trying to populate, would give you the correct row and column indexes in your original 100x100 array; the rest would just be a matter of copying the values:
// psuedocode
// given a subarrayIndex of 0 to 99, these will calculate the correct indices
rowIndexIn100x100Array = (subarrayIndex / 10) * 10 + subArrayRowIndexToPopulate;
colIndexIn100x100Array = (subarrayIndex % 10) * 10 + subArrayColIndexToPopulate;
I'll leave it as an exercise to you to deduce why the above functions correctly calculate the indices.
With the above, we can easily map the values:
var subArrays = new List<byte[,]>();
for (int subarrayIndex = 0; subarrayIndex < 100; subarrayIndex++)
{
var subarray = new byte[10, 10];
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
{
int rowIndexIn100x100Array = (subarrayIndex / 10) * 10 + i;
int colIndexIn100x100Array = (subarrayIndex % 10) * 10 + j;
subarray[i, j] = originalArray[rowIndexIn100x100Array, colIndexIn100x100Array];
}
subArrays.Add(subarray);
}
Once we have the 10x10 arrays, calculating the average would be trivial using LINQ:
var averages = new byte[10, 10];
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
{
averages[i, j] = (byte)subArrays[(i * 10) + j].Cast<byte>().Average(b => b);
}
Fiddle.
Below is the code I wrote for clustering using genetic algorithm. Points are from a picturebox, generated randomly (X,Y) before calling this class. However, the result of this algorithm is much worse than k-means or lbg I'm comparing it to. Can someone take a look for any errors in the algorithm, maybe I omitted something. Thanks.
I did this using arrays, the 2 other I did using lists, but I don't think that should have any impact on result.
public class geneticAlgorithm
{
static int pom = 0;
static PictureBox pb1;
public geneticAlgorithm(PictureBox pb)
{
pb1 = pb;
}
public static void doGA(PointCollection points, int clusterCounter)
//points is a list of points,
//those point have (X,Y) coordinates generated randomly from pictureBox
//coordinates. clusterCounter is how many clusters I want to divide the points into
{
//this part converts list of points into array testtab,
//where each array field hold X,Y of a point
Point[] test = new Point[points.Count];
test = points.ToArray();
double[][] testtab = new double[test.Length][];
for (int i = 0; i < testtab.GetLength(0); i++)
{
testtab[i] = new double[2];
testtab[i][0] = test[i].X;
testtab[i][1] = test[i].Y;
}
//end of converting
int n = testtab.GetLength(0);
int k = clusterCounter;
int chromosomeCount = 500;
int dimensions = 2;
double[][] testClusters = new double[k][];
for (int i = 0; i < k; i++)
{
testClusters[i] = new double[dimensions];
}
double[][] testChromosomes = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
testChromosomes[i] = new double[2 * k];
}
int[][] testChromosomesInt = new int[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
testChromosomesInt[i] = new int[2 * k];
}
double[] partner = new double[chromosomeCount];
double[][] roulette = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
roulette[i] = new double[1];
}
double[][] errors = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
errors[i] = new double[1];
}
double crossingPossibility = 0.01;
double mutationPossibility = 0.0001;
int maxIterations = 10000;
//here I create chromosomes and initial clusters
for (int j = 0; j < chromosomeCount; j++)
{
for (int i = 0; i < k; i++)
{
Random rnd = new Random();
int r = rnd.Next(n);
for (int q = 0; q < dimensions; q++)
{
testClusters[i][q] = testtab[r][q];
}
}
int help = 0;
for (int i = 0; i < k; i++)
for (int l = 0; l < dimensions; l++) // here is creation of chromosome
{
testChromosomes[j][help] = testClusters[i][l];
help++;
}
//end
//here I call accomodation function to see which of them are good
errors[j][0] = accomodationFunction(testClusters, testtab, n, k);
//end
//cleaning of the cluster table
testClusters = new double[k][];
for (int i = 0; i < k; i++)
{
testClusters[i] = new double[dimensions];
}
}
//end
for (int counter = 0; counter < maxIterations; counter++)
{
//start of the roulette
double s = 0.0;
for (int i = 0; i < chromosomeCount; i++)
s += errors[i][0];
for (int i = 0; i < chromosomeCount; i++)
errors[i][0] = chromosomeCount * errors[i][0] / s;
int idx = 0;
for (int i = 0; i < chromosomeCount; i++)
for (int j = 0; i < errors[i][0] && idx < chromosomeCount; j++)
{
roulette[idx++][0] = i;
}
double[][] newTab = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
newTab[i] = new double[2 * k];
}
Random rnd = new Random();
for (int i = 0; i < chromosomeCount; i++)
{
int q = rnd.Next(chromosomeCount);
newTab[i] = testChromosomes[(int)roulette[q][0]];
}
testChromosomes = newTab;
//end of roulette
//start of crossing chromosomes
for (int i = 0; i < chromosomeCount; i++)
partner[i] = (rnd.NextDouble() < crossingPossibility + 1) ? rnd.Next(chromosomeCount) : -1;
for (int i = 0; i < chromosomeCount; i++)
if (partner[i] != -1)
testChromosomes[i] = crossing(testChromosomes[i], testChromosomes[(int)partner[i]], rnd.Next(2 * k), k);
//end of crossing
//converting double to int
for (int i = 0; i < chromosomeCount; i++)
for (int j = 0; j < 2 * k; j++)
testChromosomes[i][j] = (int)Math.Round(testChromosomes[i][j]);
//end of conversion
//start of mutation
for (int i = 0; i < chromosomeCount; i++)
if (rnd.NextDouble() < mutationPossibility + 1)
testChromosomesInt[i] = mutation(testChromosomesInt[i], rnd.Next(k * 2), rnd.Next(10));
//end of mutation
}
//painting of the found centre on the picture box
int centrum = max(errors, chromosomeCount);
Graphics g = pb1.CreateGraphics();
SolidBrush brush = new SolidBrush(Color.Red);
for (int i = 0; i < 2 * k - 1; i += 2)
{
g.FillRectangle(brush, testChromosomesInt[centrum][i], testChromosomesInt[centrum][i + 1], 20, 20);
}
return;
}
//end of painting
public static int max(double[][] tab, int chromosomeCount)
{
double max = 0;
int k = 0;
for (int i = 0; i < chromosomeCount; i++)
{
if (max < tab[i][0])
{
max = tab[i][0];
k = i;
}
}
return k;
}
public static int[] mutation(int[] tab, int elem, int bit)
{
int mask = 1;
mask <<= bit;
tab[elem] = tab[elem] ^ mask;
return tab;
}
public static double[] crossing(double[] tab, double[] tab2, int p, int k)
{
double[] hold = new double[2 * k];
for (int i = 0; i < p; i++)
hold[i] = tab[i];
for (int i = p; i < 2 * k; i++)
hold[i] = tab2[i];
return hold;
}
//accomodation function, checks to which centre which point belongs based on distance
private static double accomodationFunction(double[][] klastry, double[][] testtab, int n, int k)
{
double Error = 0;
for (int i = 0; i < n; i++)
{
double min = 0;
int ktory = 0;
for (int j = 0; j < k; j++)
{
double dist = distance(klastry[j], testtab[i]);
if (j == 0)
{
min = dist;
}
if (min > dist)
{
min = dist;
ktory = j;
}
}
Error += min;
}
pom++;
return 1 / Error;
}
public static double distance(double[] tab, double[] tab2)
{
double dist = 0.0;
for (int i = 0; i < tab.GetLength(0); i++)
dist += Math.Pow(tab[i] - tab2[i], 2);
return dist;
}
}
The algorithm should work like so: (excuse me if not the best english)
1. Get random points (let's say 100)
2. Check into how many clusters we want to split them (the same thing I would do using k-means for example
3. Get starting population of chromosomes
4. Throu cutting on the roulette, crossing and mutation pick the best x centres, where x is the amount of clusters we want
5. Paint them.
Here are some results, and why I think it's wrong: (it's using 100 points, 5 clusters)
k-means:
lbg:
genetic(without colors now):
I hope this clarifies a bit.
I have a 3d-array double[,,] numbers = new double[x,y,z]; and now if one imagines the 3d-array to look like a cube with numbers I need to find the smallest and biggest value of every slice along all three directions.
It is of course easy to do by simply looping over it, but does C# have any functions to find the smallest and biggest value in a slice?
To explain it a bit further, maybe this "unreal" code will help:
int i;
double[] xmin = new double[x];
double[] xmax = new double[x];
double[] ymin = new double[y];
double[] ymax = new double[y];
double[] zmin = new double[z];
double[] zmax = new double[z];
for(i = 0; i < x; i++)
{
MinOf(numbers[i, y, z]) = xmin[i];
MaxOf(numbers[i, y, z]) = xmax[i];
}
for(i = 0; i < y; i++)
{
MinOf(numbers[x, i, z]) = ymin[i];
MaxOf(numbers[x, i, z]) = ymax[i];
}
for(i = 0; i < z; i++)
{
MinOf(numbers[x, y, i]) = zmin[i];
MaxOf(numbers[x, y, i]) = zmax[i];
}
Hopefully someone can help me with that.
Cheers, Phil13131
You can make methods for enumerating the slices. This is for one dimension, you would need another two, but I think you can manage that:
public static IEnumerable<T> SliceX<T>(T[,,] data, int x) {
for (int y = 0; y < data.GetLength(1); y++) {
for (int z = 0; z < data.GetLength(2); z++) {
yield return data[x, y, z];
}
}
}
Then you can just use the Min and Max methods, but that will of course loop through the data twice:
double min = SliceX(numbers, x).Min();
double max = SliceX(numbers, x).Max();
You can make an extension method that gets both min and max in one iteration:
public static class IEnumerableExtensions {
public static void GetMinMax<T>(this IEnumerable<T> data, out T min, out T max) where T : IComparable<T> {
bool first = true;
min = max = default(T);
foreach (T value in data) {
if (first) {
min = max = value;
first = false;
} else {
if (value.CompareTo(min) < 0) min = value;
if (value.CompareTo(max) > 0) max = value;
}
}
}
}
Usage:
double min, max;
SliceX(numbers, 0).GetMinMax(out min, out max);
Are you looking for something like this?
double[, ,] numbers = new double[2, 2, 2];
numbers[0, 0, 0] = 0;
numbers[0, 0, 1] = 1;
numbers[0, 1, 0] = 2;
numbers[0, 1, 1] = 3;
numbers[1, 0, 0] = 4;
numbers[1, 0, 1] = 5;
numbers[1, 1, 0] = 6;
numbers[1, 1, 1] = 7;
double[] xmax = new double[numbers.GetLength(0)];
double[] ymax = new double[numbers.GetLength(1)];
double[] zmax = new double[numbers.GetLength(2)];
for (int x = 0; x < xmax.Length; x++) xmax[x] = int.MinValue;
for (int y = 0; y < ymax.Length; y++) ymax[y] = int.MinValue;
for (int z = 0; z < zmax.Length; z++) zmax[z] = int.MinValue;
for (int x = 0; x < xmax.Length; x++)
for (int y = 0; y < ymax.Length; y++)
for (int z = 0; z < zmax.Length; z++)
{
xmax[x] = Math.Max(xmax[x], numbers[x, y, z]);
ymax[y] = Math.Max(ymax[y], numbers[x, y, z]);
zmax[z] = Math.Max(zmax[z], numbers[x, y, z]);
}
// xmax == { 3, 7 }
// ymax == { 5, 7 }
// zmax == { 6, 7 }