Find index which has minimum value in sublist C# - c#

I want to find index in which that index has minimum value for a sublist.
I have a class name Subproblem like this:
public class Subproblem
{
public double[,] x { get; set; }
public double ReducedCost { get; set; }
}
then I want to find the index of subproblem which has the minimum value of reduced cost.
var sub = new List<Subproblem>();
Subproblem s = new Subproblem();
s.x = new double[DC1, DC1];
for (int m = 0; m < M; ++m)
{
s.ReducedCost = model.ObjVal;
for (int i = 0; i < DC1; ++i)
{
for (int j = 0; j < DC1; ++j)
{
s.x[i, j] = x[i, j].X;
}
}
sub.Add(s);
}
double minRC = sub.Min(a => a.ReducedCost);
int minRCIndex = sub.IndexOf(minRC);
The last line is still error but i dont know how to solve it.

You get this error because minRC has type double but in your case IndexOf() expects parameter type Subproblem.
You should use FindIndex():
int minRCIndex = sub.FindIndex((i) => i.ReducedCost == minRC);
Also, you can change these two lines:
double minRC = sub.Min(a => a.ReducedCost);
int minRCIndex = sub.IndexOf(minRC);
to only one:
int minRCIndex = sub.FindIndex(i => i.ReducedCost == sub.Min(a => a.ReducedCost));

Related

'Schema mismatch for input column 'Features': expected scalar or vector of String, got VarVector<Single> (Parameter 'inputSchema')'

I'm want to implement the k-means clustering algorithm to clusterize a list of text files loaded from disk, and also using the silhouette method to determine the number of clusters.
The error I'm getting is System.ArgumentOutOfRangeException: 'Schema mismatch for input column 'Features': expected scalar or vector of String, got VarVector<Single> (Parameter 'inputSchema')'
How can I solve the problem?
Code
static void Main(string[] args)
{
// Load text files from disk
string[] filePaths = Directory.GetFiles("C:\\ExportedEmails\\", "*.txt");
string[] textFiles = filePaths.Select(File.ReadAllText).ToArray();
// Extract features from text files
var textData = textFiles.Select((text, index) =>
{
int startIndex = text.IndexOf("Description: ") + "Description: ".Length;
string description = text.Substring(startIndex);
return new TextData { Text = description, Index = index };
}).ToArray();
// Initialize the MLContext
var context = new MLContext();
// Convert data to IDataView
var data = context.Data.LoadFromEnumerable(textData);
// Initialize the variables to store the silhouette scores
var silhouetteScores = new double[10];
// Iter
for (int k = 2; k <= 10; k++)
{
// Create a new KMeansTrainer
var pipeline = context.Transforms.Text.FeaturizeText("Text", "Features")
.Append(context.Clustering.Trainers.KMeans(featureColumnName: "Features", numberOfClusters: k));
var model = pipeline.Fit(data);
var transformedData = model.Transform(data);
// Compute the silhouette score
var clusterAssignments = transformedData.GetColumn<uint>("PredictedLabel").ToArray();
var clusterCenters = transformedData.GetColumn<float[]>("Centroid").ToArray();
var features = transformedData.GetColumn<float[]>("Features").ToArray();
var silhouetteScore = ComputeSilhouetteScore(features, clusterAssignments, clusterCenters);
silhouetteScores[k - 2] = silhouetteScore;
}
// Find the number of clusters that maximizes the average silhouette score
int optimalClusters = 0;
double maxScore = double.MinValue;
for (int i = 0; i < silhouetteScores.Length; i++)
{
if (silhouetteScores[i] > maxScore)
{
maxScore = silhouetteScores[i];
optimalClusters = i + 2;
}
}
Console.WriteLine($"The optimal number of clusters is {optimalClusters}.");
}
private static double ComputeSilhouetteScore(float[][] features, uint[] clusterAssignments, float[][] clusterCenters)
{
double silhouetteScore = 0;
for (int i = 0; i < features.Length; i++)
{
var a = ComputeAverageDistance(features[i], clusterAssignments[i], features, clusterAssignments);
var b = ComputeMinimumDistance(features[i], clusterAssignments[i], clusterCenters);
silhouetteScore += (b - a) / Math.Max(a, b);
}
return silhouetteScore / features.Length;
}
private static double ComputeAverageDistance(float[] feature, uint clusterAssignment, float[][] features, uint[] clusterAssignments)
{
double distance = 0;
int count = 0;
for (int i = 0; i < features.Length; i++)
{
if (clusterAssignments[i] == clusterAssignment)
{
distance += Distance(feature, features[i]);
count++;
}
}
return distance / count;
}
private static double ComputeMinimumDistance(float[] feature, uint clusterAssignment, float[][] clusterCenters)
{
double minDistance = double.MaxValue;
for (int i = 0; i < clusterCenters.Length; i++)
{
if (i != clusterAssignment)
{
minDistance = Math.Min(minDistance, Distance(feature, clusterCenters[i]));
}
}
return minDistance;
}
private static double Distance(float[] feature1, float[] feature2)
{
double distance = 0;
for (int i = 0; i < feature1.Length; i++)
{
distance += Math.Pow(feature1[i] - feature2[i], 2);
}
return Math.Sqrt(distance);
}
class TextData
{
public string? Text { get; set; }
public float[] Features { get; set; }
public int Index { get; set; }
}
I believe the reason you're getting this error is you set the output column name to Text and input column name as Features in the FeaturizeText transform. I suspect you want the opposite. Take the Text column as input and generate a feature vector called Features which you can do by swapping the values in FeaturizeText or you can explicitly add parameter names (FeaturizeText(outputColumnName: "Features", inputColumnName:"Text")).
Check out the FeaturizeText documentation for more details.

Initialize array of a class with fixed length and dynamically add values in C#

I want to have a two-dimensional game board, and every field is a custom class with information about this field, with properties. The size of the game board is known on instantiation, the values of the properties are not. After instantiation, I want to randomly set them for each field. My initial idea was to create an array, not a list, because the size of the game board is always fixed.
public class GameBoard
{
private int _xValue;
private int _yValue;
private int _bombs;
private int _fields;
public Field[][] gameBoard;
public GameBoard(int x, int y)
{
_xValue = x;
_yValue = y;
_fields = _xValue * _yValue;
gameBoard = new[] { new Field[_xValue], new Field[_yValue] };
//Here I have to initialize every Field
for (int i = 0; i < _xValue; i++)
{
for (int j = 0; j < _yValue; j++)
{
//Set properties of Field
//For example: gameBoard[i][j].IsBomb = RandomBoolean;
//Here I get NullReferenceExceptions
}
}
}
}
I do understand why this does not work. I tried lists, two-dimensional arrays or, like at the moment, a jagged array, what I would prefer. How can I solve this problem in a readable, clean way?
EDIT
The Field class:
public class Field
{
public bool IsBomb { get; set; }
public bool IsFlagged { get; set; }
}
I tried to add gameBoard[i][j] = new Field(); inside the nested forloop. This leads to an IndexOutOfRangeException.
Here is your array-property:
public Field[,] gameBoard;
And here is initialization:
public GameBoard(int x, int y)
{
_xValue = x;
_yValue = y;
_fields = _xValue * _yValue;
gameBoard = new Field[_xValue, _yValue];
for (int i = 0; i < _xValue; i++)
{
for (int j = 0; j < _yValue; j++)
{
gameBoard[i, j] = new Field();
}
}
}
Lots of confusion in here on how to work with jagged arrays. If you want to work with jagged arrays, you have to setup in such a way
//Declare jagged array, I want _xValue arrays
Field[][] gameBoard = new Field[_xValue][];
for (int i = 0; i < _xValue; i++)
{
gameBoard[i] = new Field[_yValue];
for (int j = 0; j < _yValue; j++)
{
gameBoard[i][j] = new Field(){ IsBomb = RandomBoolean};
}
}
The equivalent in a multi-dimensional array would be
//Declare multi-dimensional array of size _xValue x _yValue
Field[,] gameBoard2 = new Field[_xValue, _yValue];
for(int i = 0; i < _xValue; i++)
{
for(int j = 0; j < _yValue; j++)
{
// Instantiate the Field object at x,y
gameBoard2[i, j] = new Field { IsBomb = RandomBoolean };
}
}

Show sublist value from index C#

My problem is I have M subproblem. Each subproblem include x (double array) and reduced cost which has different value for each iteration m. I want to show x which has the minimum reduced cost among all subproblems. here is my class:
public class Subproblem
{
public double[,] x { get; set; }
public double ReducedCost { get; set; }
}
So far, I already can get the minimum Reduced Cost and index of it. Now I want to show x value (double array) which on that index. I've code like this:
var sub = new List<Subproblem>();
for (int m = 0; m < M; ++m)
{
Subproblem s = new Subproblem();
s.x = new double[DC1, DC1];
s.ReducedCost = model.ObjVal;
for (int i = 0; i < DC1; ++i)
{
for (int j = 0; j < DC1; ++j)
{
s.x[i, j] = x[i, j].X;
}
}
sub.Add(s);
}
double minRC = sub.Min(a => a.ReducedCost);
int minRCIndex = sub.FindIndex((i) => i.ReducedCost == minRC);
Console.WriteLine(sub.x(minRCIndex));
the last line (Console.WriteLine(sub.x(minRCIndex));) still got red underline, I don't know how to write it
If you are only trying to get the minimum Reduced Costed subproblem you should be doing:
Subproblem minimumReducedCostedSubproblem = sub[minRCIndex];
And you can print the matrix down like this:
for (int i = 0; i < DC1; ++i)
{
for (int j = 0; j < DC1; ++j)
{
Console.Write(minimumReducedCostedSubproblem.x[i, j] + "\t");
}
Console.Write("\n");
}
But you seem a little confused. You are pushing a Subproblem into your sub list with the same object for M times. Because model.ObjVal doesn't change along the first for loop. There is something wierd going on there too.
It should be
var objWithMinReduceCost = sub[minRCIndex];
//Now you have the object of Subproblem derived from your logic.
//You can access x property of it have further logic to process it.
for (int i = 0; i < DC1; ++i)
{
for (int j = 0; j < DC1; ++j)
{
Console.WriteLine(objWithMinReduceCost.x[i, j]);
}
}
If you are interested in obtaining the double array, you could just do this:
double[,] result = sub.First(i => i.ReducedCost == minRC).x;
Although as Tolga mentioned, all your elements will have the same ReducedCost with your current code.

Comparing two variable in a structure C#

What I want to do is compare two of the same variable in a structure.
For example I have a structure like so:
struct player
{
public string name;
public int number;
}
static player[] players = new player[3];
and what I want to do is compare the numbers, so that if two players have the same number, something will happen.
This is what I tried, however it would always say two numbers were the same because it would compare two of the same
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
if (players[i].number == players[j].number)
{
Console.WriteLine("Same");
Console.ReadLine();
}
else
{
Console.WriteLine("Not");
Console.ReadLine();
}
}
Hopefully you understand what I mean.
Any help would be really appreciated!
Thanks
Problem is in your loop variables i and j starting both at index zero. Then you are comparing element zero to element zero and therefore the condition is true.
Update this line:
for (int j = 0; j < length; j++)
to this:
for (int j = i + 1; j < length; j++)
Edit
To be more precise. The condition evaluates to true not only for the first element, but for each element when i and j are the same. This solution bars both control variables from having the same value in any iteration.
Simple, just add a check to make sure you aren't comparing the same index, because this is the same object:
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
if (i == j) continue;
if (players[i].number == players[j].number)
{
Console.WriteLine("Same");
Console.ReadLine();
}
else
{
Console.WriteLine("Not");
Console.ReadLine();
}
}
Use a Class, and do it using Linq:
public class Player
{
public string Name { get; set; }
public int Number { get; set; }
}
Then in the other class have this method to cross-check
private void Match()
{
var players = new Player[3].ToList();
foreach (var found in players.ToList().Select(player => players.FirstOrDefault(p => p.Number == player.Number)))
{
if (found != null)
{
Console.WriteLine("Same");
Console.ReadLine();
}
else
{
Console.WriteLine("Not");
Console.ReadLine();
}
}
}

Matrix of objects class

I have written 3 classes: KompresorSilnik, KompresorObiekt and Mrowka.
I want to create a matrix of objects of class KompresorObiekt ( it's a GrafObiektow method ). In the constructor of KompresorObiekt, I create 4 instances of KompresorSilnik. I have a method, zwrocListe() which returns a list of int[] from 0000 to 2222.
The question is: was that correct or not implementation?
public class KompresorSilnik
{
public double minFlow;
public double maxFlow;
public bool typ;
public int stan;
public KompresorSilnik()
{
}
public KompresorSilnik(double minFlow, double maxFlow, bool typ, int stan)
{
this.minFlow = minFlow;
this.maxFlow = maxFlow;
this.typ = typ;
this.stan = stan;
}
}
This is my second class KompresorObiekt
public class KompresorObiekt
{
public KompresorObiekt() { }
public KompresorObiekt( List<int[]> list, int x, int y)
{
double k1Max = 3000000.0;
double k1Min = 10000.0;
double k2Max = 200000.0;
double k2Min = 5000.0;
double K3Max = 100000000.0;
double k3Min = 800.0;
double k4Max = 10000.0;
double k4Min = 2000.0;
KompresorSilnik komp1 = new KompresorSilnik(k1Min, k1Max, false, list[x][y]);
KompresorSilnik komp2 = new KompresorSilnik(k2Min, k2Max, true, list[x][y+1]);
KompresorSilnik komp3 = new KompresorSilnik(k3Min, K3Max, false, list[x][y+2]);
KompresorSilnik komp4 = new KompresorSilnik(k4Min, k4Max, true, list[x][y+3]);
}
}
and the last one Mrowka
public class Mrowka
{
List<int[]> zwrocListe()
{
List<int[]> arrList = new List<int[]>();
int[] ArrayOfInts = new int[4];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
for (int m = 0; m < 3; m++)
{
ArrayOfInts[0] = i;
ArrayOfInts[1] = j;
ArrayOfInts[2] = k;
ArrayOfInts[3] = m;
int[] arc = (int[])ArrayOfInts.Clone();
arrList.Add(arc);
}
}
}
}
return arrList;
}
KompresorObiekt[][] GrafObiektow(int time)
{
KompresorObiekt[][] graf = new KompresorObiekt[time][];
int numNodes = zwrocListe().Count;
for (int i = 0; i < graf.Length; ++i)
graf[i] = new KompresorObiekt[numNodes];
for (int i = 0; i < time; ++i)
for (int j = 0; j < numNodes; ++j)
{
graf[i][j] = new KompresorObiekt(zwrocListe(), j, 0);
}
return graf;
}
}

Categories

Resources