How do I initialize a list<> with two dimensional arrays? - c#

List<int[,]> table = new List<int[,]> { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
This isn't right, but I'm stumped on how to do it.
Basically in the end I want to say table[0] and get back the first tuple, table[2] and get back the second tuple, and so on.
What is the correct format (if I have the right data model) or the correct data structure for what I want to do?
I have a pretty hefty list of tuples in the above format, And I like to stay with the format if at all possible.

Related

multidimensional array definition in c# (difference and applications)

What is the difference between these two:
string[,] array1;
and
string[][] array2;
Could someone please explain me about these two in terms of applications and functionality, memory management etc... how do you called them, which one is better to use? how to initialize them?
array1 is called a reference to a multidimensional array; array2 is a reference to a jagged array.
The first one is designed to store rectangular data which is not sparse and the number of elements in the dimensions are almost the same. You can initialize it like:
// Two-dimensional array.
int[,] array1= new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
In the latter case which is also called array of array the elements can be of different dimensions and sizes. Some times it is memory optimized to store sparse 2d data in the RAM. You can initialize it like:
int[][] array2= new int[][]
{
new int[] { 1, 3, 5, 7, 9 },
new int[] { 0, 2, 4, 6 },
new int[] { 11, 22 }
};
Absolutely the usage is depends on you requirements and purposes. You can review these 1, 2.

C# - How to add values to a 3D array?

I'm building an interactive map using Mapbox and would like to draw a polygon over a specific area like is shown here. For this I need to dynamically fill a 3D array with the X,Y and Z coordinates from a database. The array structure I want to achieve is:
[
[
[
[xCoordinate1, yCoordinate1, zCoordinate1],
[xCoordinate2, yCoordinate2, zCoordinate2],
[xCoordinate3, yCoordinate3, zCoordinate3]
]
]
]
I have been trying to accomplish this with C#. In my application I initialized a 3D list, like so:
List<List<List<List<double>>>> coordinates = new List<List<List<List<double>>>>();
Next I iterated over the coordinates that are coming from the database so they would be added to the array:
foreach (var coordinate in Coordinates) {
coordinates.Add({ coordinate.X, coordinate.Y, coordinate.Z })
}
However this doesn't add the values at the disired position and throws an IndexOutOfBounds exception. I have also tried to initialize the array, like so:
double[, , ,] coordinates = {
{
{
{ coordinate.X, coordinate.Y, coordinate.Z },
{ coordinate.X, coordinate.Y, coordinate.Z },
{ coordinate.X, coordinate.Y, coordinate.Z }
}
}
};
With this approach i was also unable to format my array the way it should be formatted. Can someone show me how to work with a complex 3D array so that it gets the structure I'm looking for?
To sum up:
int[,,,] array3D = new int[,,,] {
{
{
{ 1, 2, 3 },
{ 4, 5, 6 }
//How can I add more here dynamically?
}
}
};
array3D[0, 0, 0, 3] = { 7, 8, 8 }; //This doesn't do the trick :(
You cannot change the size of a multidimensional array, but that is ok because your JSON really represents an array of arrays of sorts.
Start with the (expandable) list of coordinates
var coords = new List<double[]>
{
new double[] { 1,2,3 },
new double[] { 4,5,6 },
};
// later
coords.Add(new double[] { 7, 8, 9 });
Then convert to the JSON structure for export. You showed an array of array of array of coordinates (array).
var json = new double[][][][] {
new double[][][] {
coords.ToArray()
}
};
This is how you recover the coordinates
foreach (var item in json[0][0])
{
Debug.WriteLine($"Point=({item[0]}, {item[1]}, {item[2]})");
}
In the output window, you see
// Point=(1, 2, 3)
// Point=(4, 5, 6)
// Point=(7, 8, 9)
If I understand correctly, you can get away with just 2D list, where the first list contains sets of coordinates (i.e. (x,y,z)) and the second list simply contains a bunch of first lists, like so:
List<List<double>> coords = new List<List<double>>();
coords.Add(new List<double> { 24, 54, 46 });
coords.Add(new List<double> { 32, 45, 48 });
Console.WriteLine(coords[1][1]);
//Outputs 45.
//Note: xCoord = 24, yCoord = 54, zCoord = 46 in the first list entry
You can make it a separate method or an extension method where the coordinates are passed in as an arguments. It's also possible to loop through the lists to get particular x,y or z coordinate (if you need to search through them in your code).

Multi Label Support Vector Machine in Accord.NET

I am trying to make a Multi Label Support Vector Machine using Accord.NET framework (MultilabelSupportVectorMachine Class) but based on the example it's difficult to understand the encoding e.g.:
// Sample input data
double[][] inputs =
{
new double[] { 0 },
new double[] { 3 },
new double[] { 1 },
new double[] { 2 },
};
// Outputs for each of the inputs
int[][] outputs =
{
new[] { -1, 1, -1 },
new[] { -1, -1, 1 },
new[] { 1, 1, -1 },
new[] { -1, -1, -1 },
};
What if my output is a matrix which contains integer values not within the -1 and +1 range, what encoding should we use to convert the data into this format?
This is the format of the output the MultiLabelSupportVectorMachine would return if you compute something with it. MultiClassSupportVectorMachine returns a single int because it is used when you are sure that an example matches only a single class whereas MultiLabelSupportVectorMachine returns an array which shows which classes does the example match and is used when an example can match more classes.
It works like this:
The output array length is between 0(inclusive) and the number of classes. So if you have 4 classes you'll have an output array like this:
{ -1, -1, 1, -1 }
This means that the output class is 2, because the index of 1 is 2.
I hope that now you know how the output of this class works and that this gives you directions how to format your example output.
Additional info: If you want to use MultiLabelSupportVectorMachine, but you want to get only one output class you can just take the first index of 1 in the output array. I recommend this only if you are certain that One-Vs-All serves you better than One-Vs-One.

C# HMM Gesture Recognition usng Kinect

I'm working on a solution to do gesture recognition using the Kinect sensor.
Now I'm using Accord .NET to train the HMM.
I have a dataset with saved gestures. This dataset has 11 gestures and each one has 32 frames with 18 points saved.
So I have a (double [12] [32,18]) input dataset and a (int[12]) output dataset, but when i do:
double error = teacher.Run(inputSequences, output), it gives me this : "Specified argument was out of the range of valid values."
Does anyone knows how to solve this? Should treat the dataset before using it o on the hmm teacher or the dataset is ok like this?
I have used Accord.NET in the past and its really one of the best implementations for a HMM engine. However, when I trained my HMM, I passed the HMM parameters (namely PI, A and B) to the Baum Welch Teacher with the input data set supplied using an organized excel sheet. (similar to what Accord's author himself has used in his project). I somehow feel that since you are storing your data set as a multi-dimensional array and directly supplying it to the teacher, its unable to process it properly. Maybe you could supply one gesture record at a time or change the storage structure of your data set altogether. I advice going through the entire example of Accord if you haven't already because it worked just fine for me.
The problem might have been that the teaching algorithm expects the training sequences to be in the form double[12][32][18], rather than double[12][32,18]. The training data should be a collection of sequences of multivariate points. It should also be necessary to note that, if you have 11 possible classes of gestures, the integer labels given in the int[12] array should be comprised of values between 0 and 10 only.
Thus if you have 12 gesture samples, each containing 32 frames, and each frame is a vector of 18 points, you should be feeding the teacher with a double[12][32][18] array containing the observations and a int[12] array containing the expected class labels.
The example below, extracted from the HiddenMarkovClassifierLearning documentation page should help to give an idea how the vectors should be organized!
// Create a Continuous density Hidden Markov Model Sequence Classifier
// to detect a multivariate sequence and the same sequence backwards.
double[][][] sequences = new double[][][]
{
new double[][]
{
// This is the first sequence with label = 0
new double[] { 0, 1 },
new double[] { 1, 2 },
new double[] { 2, 3 },
new double[] { 3, 4 },
new double[] { 4, 5 },
},
new double[][]
{
// This is the second sequence with label = 1
new double[] { 4, 3 },
new double[] { 3, 2 },
new double[] { 2, 1 },
new double[] { 1, 0 },
new double[] { 0, -1 },
}
};
// Labels for the sequences
int[] labels = { 0, 1 };
In the above code, we have set the problem for 2 sequences of observations, where each sequence containing 5 observations, and in which each observations is comprised of 2 values. As you can see, this is a double[2][5][2] array. The array of class labels is given by a int[2], containing only values ranging from 0 to 1.
Now, to make the example more complete, we can continue creating and training the model using the following code:
var initialDensity = new MultivariateNormalDistribution(2);
// Creates a sequence classifier containing 2 hidden Markov Models with 2 states
// and an underlying multivariate mixture of Normal distributions as density.
var classifier = new HiddenMarkovClassifier<MultivariateNormalDistribution>(
classes: 2, topology: new Forward(2), initial: initialDensity);
// Configure the learning algorithms to train the sequence classifier
var teacher = new HiddenMarkovClassifierLearning<MultivariateNormalDistribution>(
classifier,
// Train each model until the log-likelihood changes less than 0.0001
modelIndex => new BaumWelchLearning<MultivariateNormalDistribution>(
classifier.Models[modelIndex])
{
Tolerance = 0.0001,
Iterations = 0,
FittingOptions = new NormalOptions()
{
Diagonal = true, // only diagonal covariance matrices
Regularization = 1e-5 // avoid non-positive definite errors
}
}
);
// Train the sequence classifier using the algorithm
double logLikelihood = teacher.Run(sequences, labels);
And now we can test the model, asserting that the output class label indeed matches what we are expecting:
// Calculate the probability that the given
// sequences originated from the model
double likelihood, likelihood2;
// Try to classify the 1st sequence (output should be 0)
int c1 = classifier.Compute(sequences[0], out likelihood);
// Try to classify the 2nd sequence (output should be 1)
int c2 = classifier.Compute(sequences[1], out likelihood2);

Retrieving values from multidimensional arrays

I have an array something like this:
int[,] multiDimensionalArray2 = { { 1, 2 }, { 4, 5 } };
if I want to retrieve 1 and 2 and feed them into this:
int a;
int b;
How do I do it?
Is it something like this:
multiDimensionalArray2[0,0]
What if I wanted to put more numbers in the same form e.g. { { 2, 1 }, { 4, 1 } };, in the same form as above. Would it be something like this:
int[,] multiDimensionalArray2 = { { 1, 2 }, { 4, 5 } },{ { 2, 1 }, { 4, 1 } };
To retrieve the second set would I do this, multiDimensionalArray2[1,1]
You´re close, to retrieve the first numbers try this
var a = multiDimensionalArray2[0, 0]; // x == 1
var b = multiDimensionalArray2[0, 1]; // x == 2
Did you give it a try and it didn´t work? You´ll notice that SO users will encourage you to try-and-error first. Come back when you hit a wall :)
Double dimention arrays are stored like this (picture it in your mind) as per your example
Row0 Row1
1 2
4 5
2 1
4 1
Now follow what Dominik suggested.
If you have a multi dimensional array like the one you gave,
int[,] multiDimensionalArray2 = { { 1, 2 }, { 4, 5 }, { 2, 1 }, { 4, 1 } };
We want to get the index of the number 5. To do this we need two indexes, [a,b]
Index a is the index of the "group of numbers" that you want to get.
First look at which group it is in. The first group (index 0) contains 1 and 2, the second group (index 1) contains 4 and 5.
Therefore a = 1.
Index b is the index of the "position within the group" that you want to get.
In the group {4, 5}, the number 5 is the first item (index 0). Therfore b = 0.
This means that the number 5 can be found at multiDimensionalArray2[1,0]
Chao, I search documents in MSDN site for you, you should give it a try if you want.
Here is how I see on MSDN
List< > >
Dictionary<>
I guess it works for your problem too, it can dynamically grow longer or shorter. they say using generic classes might be better, I am not sure about whether it ought to be faster or not though.

Categories