evaluate dynamically created formula on large (in memory) flat table - c#

I am currently using this code:
using System;
using NCalc;
namespace SandboxConsoleApp
{
class Program
{
static void Main(string[] args)
{
double[,] data = new double[100, 10];
Random random = new Random();
var numberOfRows = data.GetLength(0);
var numberOfColumns = data.GetLength(1);
for (int row = 0; row < numberOfRows; row++)
{
for (int col = 0; col < numberOfColumns; col++)
{
data[row, col] = random.Next();
}
}
// in the case of 10 columns the expression looks like: [x0] + [x1] + [x2] + [x3] + [x4] + [x5] + [x6] + [x7] + [x8] + [x9]
var stringExpression = "";
for (int col = 0; col < numberOfColumns - 1; col++)
{
stringExpression += string.Format("[x{0}] + ", col);
}
stringExpression += string.Format("[x{0}]", (numberOfColumns - 1));
var exp = new Expression(stringExpression);
var total = 0.0;
for (int row = 0; row < numberOfRows; row++)
{
for (int col = 0; col < numberOfColumns; col++)
{
exp.Parameters[string.Format("x{0}", col)] = data[row, col];
}
if (row % 100000 == 0)
{
Console.WriteLine(row);
}
if (!exp.HasErrors())
{
total += (double)exp.Evaluate();
}
}
}
}
}
Here the fake 'dynamic' expression/formula:
[x0] + [x1] + [x2] + [x3] + [x4] + [x5] + [x6] + [x7] + [x8] + [x9]
adds 10 columns of a 10000000 row 'flat file'. The execution is not very fast and I hit limits, if I have lets say 100 million rows. Is there anything I can do to execute the above faster or should I use some other technologies to execute dynamically created formulas like this? Not sure how fast MySql would be - here I would generate the formula as SQL to the db via (e.g. Dapper).

Related

The sum for every column and raw in a 2D array with N columns

I have a 2D Array in C# with user input to fill the Array. I need help to find the sum for every column and row.
var input = Console.ReadLine();
var n = int.Parse(input);
int[,] intArr = new int[n, 3];
for (int i = 0; i < n; i++)
{
input = Console.ReadLine();
var parts = input.Split(' ');
for (int j = 0; j < 3; j++)
{
intArr[i, j] = int.Parse(parts[j]);
}
}
if (n == 1)
{
Console.WriteLine("Sum of column " + Convert.ToString(n) + ": " + (intArr[n - 1, 0] + intArr[n - 1, 1] + intArr[n - 1, 2]));
Console.WriteLine("Row1: " + (intArr[n - 1, 0]));
Console.WriteLine("Row2: " + (intArr[n - 1, 1]));
Console.WriteLine("Row3: " + (intArr[n - 1, 2]));
}
if (n == 2)
{
Console.WriteLine("Sum of column " + Convert.ToString(n - 1) + ": " + (intArr[n - 2, 0] + intArr[n - 2, 1] + intArr[n - 2, 2]));
Console.WriteLine("Sum of column " + Convert.ToString(n) + ": " + (intArr[n - 1, 0] + intArr[n - 1, 1] + intArr[n - 1, 2]));
Console.WriteLine("Row 1: " + (intArr[n - 2, 0] + intArr[n - 1, 0]));
Console.WriteLine("Row 2: " + (intArr[n - 2, 1] + intArr[n - 1, 1]));
Console.WriteLine("Row 3: " + (intArr[n - 1, 2] + intArr[n - 1, 1]));
}
}
User input:
2
1 2 3
4 5 6
The output:
Sum of column 1: 6
Sum of column 2: 15
Row 1: 5
Row 2: 7
Row 3: 11
I want this output for N columns enter by user, but I am stuck!
Thank you!
Not sure, is your problem that you get an undesired result or that you have a model with a fixed number of elements? An array is a fixed size data container, so if you want any number of columns the architecture perhaps is where you want to change away from array.
Anyway, problem 1 is that you let user chose how many rows they want, but now how many column, so presuming there will be 3 conflicts with you data. So you have on array the .getUpperBound() for that which takes a range parameter and this way we can use a dynamic strucure
//From:
for (int i = 0; i < n; i++)
{
input = Console.ReadLine();
var parts = input.Split(' ');
for (int j = 0; j < 3; j++)
{
intArr[i, j] = int.Parse(parts[j]);
}
}
//TO:
var rows = new List<int[]>();
for (int i = 0; i < n; i++)
{
input = Console.ReadLine();
var parts = input.Split(' ');
var listOf = new List<int>();
for (int j = 0; j < parts.GetUpperBound(0); j++)
{
listOf.Add(int.Parse(parts[j]));
}
rows.Add(listOf.ToArray());
}
from https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.aggregate?view=net-5.0 You get the aggregation capability
[Fact]
public void SumExerciseTest()
{
/*
The output:
Sum of column 1: 6
Sum of column 2: 15
Row 1: 5
Row 2: 7
Row 3: 11 => 9
*/
var testData = new[] { "1 2 3", "4 5 6" };
var input = "2"; // Console.ReadLine();
var n = int.Parse(input);
var rows = new List<int[]>(n);
for (int i = 0; i < n; i++)
{
input = testData[i];
var parts = input.Split(' ');
var listOf = new List<int>();
for (int j = 0; j <= parts.GetUpperBound(0); j++)
{
listOf.Add(int.Parse(parts[j]));
}
rows.Add(listOf.ToArray());
}
var rowSums = new List<int>(n);
foreach (int[] row in rows)
{
rowSums.Add(row.Aggregate((result, item) => result + item));
}
int maxLength = 0;
var rowLengths = new List<int>(n);
foreach (int[] row in rows)
{
rowLengths.Add(row.Length);
}
maxLength = rowLengths.Max();
int[] columnSums = new int[maxLength];
for (int idx = 0; idx < columnSums.Length; idx++){
foreach (var row in rows)
{
if (row.GetUpperBound(0) >= idx)
{
columnSums[idx] += row[idx];
}
}
}
int counter = 0;
//Outputting:
foreach(var sum in rowSums)
{
counter += 1;
System.Diagnostics.Debug.WriteLine($"Row {counter}: {sum}");
}
counter = 0;
foreach(var sum in columnSums)
{
counter += 1;
System.Diagnostics.Debug.WriteLine($"Column {counter}: {sum}");
}
Well, let's implement (extract) methods for summing arbitrary column and row:
private static int SumColumn(int[,] array, int column) {
if (array == null)
throw new ArgumentNullException(nameof(array));
if (column < 0 || column >= array.GetLength(1))
throw new ArgumentOutOfRangeException(nameof(column));
int result = 0;
for (int r = 0; r < array.GetLength(0); ++r)
result += array[r, column];
return result;
}
private static int SumRow(int[,] array, int row) {
if (array == null)
throw new ArgumentNullException(nameof(array));
if (row < 0 || row >= array.GetLength(0))
throw new ArgumentOutOfRangeException(nameof(row));
int result = 0;
for (int c = 0; c < array.GetLength(1); ++c)
result += array[row, c];
return result;
}
then you can put
for (int c = 0; c < intArr.GetLength(1); ++c)
Console.WriteLine($" Sum of column {c + 1}: {SumColumn(intArr, c)}");
for (int r = 0; r < intArr.GetLength(0); ++r)
Console.WriteLine($" Sum of row {r + 1}: {SumRow(intArr, r)}");

Get the specific whole (0) dimension in multidimensional array (C# UNITY)

How can I possibly count only the specific whole column I want in a multidimensional array
I do the counting of my whole column and row like this
//COLUMN
for(int col = 0; col < table.GetLength(0); col++)
{
int sum = 0;
//ROW
for (int row = 0; row < table.GetLength(1); row++)
{
if (table[col,row] != null)
{
sum++;
}
}
Debug.Log("table column: " + col + " has " + sum + " data");
}
What I want is just to get the specific whole Column then move to another Column just like that. I need to do this because i need to compare it with the last column value to the next one.
For example : I want to check how many data are there in the 2nd column then compare it with the 1st column.
You´re almost there. All you have to do is store the sum of the current column into a list:
var List<int> sums = new List<int>();
//COLUMN
for(int col = 0; col < table.GetLength(0); col++)
{
int sum = 0;
//ROW
for (int row = 0; row < table.GetLength(1); row++)
{
if (table[col,row] != null)
{
sum++;
}
}
Debug.Log("table column: " + col + " has " + sum + " data");
sums.Add(sum);
}
Now you can easily compare the number of rows in colum 1 and that of column 2:
bool areEqual = sums[0] == sums[1];
Got a solution :)
//generic function
public static int CountRow<T>(T[,] table, int col)
{
if (table == null || col < 0 || col >= table.GetLength(1))
{
//handle error
return -1;
}
//this is the same as the block of the outer for loop
int sum = 0;
for (int row = 0; row < table.GetLength(1); row++)
{
if(table[col,row] != null)
{
sum++;
}
}
return sum;
}
then used it like this
int prevSum = -1;
for (int col = 0; col < table.GetLength(0); ++col)
{
int sum = CountRow(table, col);
Debug.Log("table column :" + col + " has " + sum + " data");
if (sum == prevSum)
{
//comparison happens
}
}

Checking all the Checkboxes in a certain row by giving the row number in C#

I have Created Checkboxes like this:
but now i want to be able to check all the Checkboxes in one Row after giving the Row number
private void button4_Click(object sender, EventArgs e)
{
CheckBox[,] c = new CheckBox[10, 5];
for (i = 1; i < c.GetLength(0); i++)
{
for ( j = 1; j < c.GetLength(1); j++)
{
c[i, j] = new CheckBox();
c[i, j].Location = new Point(i * 50, j * 50);
c[i, j].AutoSize = true;
c[i, j].Name = i + "-" + j.ToString();
c[i, j].Text = i + "-" + j.ToString();
this.Controls.Add(c[i, j]);
}
}
You already use name:
for (i = 1; i < c.GetLength(0); i++)
{
for ( j = 1; j < c.GetLength(1); j++)
{
...
c[i, j].Name = i + "-" + j.ToString();
this.Controls.Add(c[i, j]);
}
}
So you could create a method to search against that:
private CheckBox Find(int row, int col)
{
foreach(var control in this.Controls)
{
if (control is CheckBox && control.Name == $"{row}-{col}")
return control as CheckBox;
}
}
So then just loop the rows and/or columns you want. This should check every even row:
for(var i = 1; i <= rowCount; i++)
{
if (i % 2 == 0)
{
for(var j = 1; i <= colCount; i++)
{
var checkBox = Find(i, j);
if (checkBox != null)
checkBox.Checked = true;
}
}
}
It's not the most efficient as each Find call is essentially looping over the controls so you'd be iterating multiple times but should work for a reasonable grid.
A shorter solution would use a jagged array instead, but with 2D array you can do the following:
You should change your check box array initialisation to this:
for (int i = 0; i < c.GetLength(0); i++)
{
for (int j = 0; j < c.GetLength(1); j++)
{
c[i, j] = new CheckBox
{
Location = new Point(i * 50, j * 50),
AutoSize = true,
Name = i + "-" + j.ToString(),
Text = i + "-" + j.ToString()
};
Controls.Add(c[i, j]);
}
}
If you still want their location to not be the upper left corner you can add 1 to the index like this:
Location = new Point((i + 1) * 50, (j + 1) * 50)
Than you can later obtain a row like this:
private CheckBox[] GetCheckBoxsByRow(int row, CheckBox[,] checkboxs)
{
CheckBox[] selectedRowCheckboxs = new CheckBox[checkboxs.GetLength(0)];
for (int x = 0; x < checkboxs.GetLength(0); x++)
{
selectedRowCheckboxs[x] = checkboxs[x, row - 1];
}
return selectedRowCheckboxs;
}
Example usage:
var firstRow = GetCheckBoxsByRow(1, c);

How to get average of columns in a 2d array

I have just started using 2D arrays, but can't seem to figure out how to get the average of each column. I am using a for loop to have the user enter the data( a students grade), then a for loop to display the information user entered. But after the information is displayed, I want to display the average of each column. What should I do get the average of each column?
This is the code I have so far
static void Main(string[] args)
{
double[,] grades = new double[2, 3];
double result;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write("Enter Grade " + (j + 1) + " For Group" + (i + 1) + ": ==>> ");
if (double.TryParse(Console.ReadLine(), out result)) grades[i, j] = result;
else
{
Console.WriteLine("*** INVALID GRADE ENTERED. PLEASE REENTER.");
}
}
}
for (int row = 0; row < 1; row++)
{
Console.WriteLine();
Console.Write(" Group " + (row + 1) + ": ");
Console.WriteLine(" Group " + (row + 2) + ": ");
Console.Write("=========== ===========");
for (int col = 0; col < 3; col++)
{
//String.Format("{0,-10} | {1,-10} | {2,5}",
//make pring for execise 2 Console.Write(string.Format("{0,-5}", grades[row, col]));
Console.WriteLine();
Console.Write(string.Format("{0,-9}", ""));
Console.Write(string.Format("{0,-20}",grades[0, col]));
Console.Write(grades[1,col]);
}
Console.WriteLine();
Console.WriteLine("=========== ===========");
}
Console.WriteLine("\n\npress any key to exit...");
Console.ReadKey();
//print it for exercise 1 myArr[o, column]; myArr[ , column]
}`
If you are looking for a special command that will do it for you, you're out of luck! You'll just have to write the code to do it, the same way you would normally average a series of numbers. Hint: The number of elements in the 'y' dimension of a 2D array is given by e.g. grades.GetLength(1).
To get Average per columns you need to traverse columns for a fixed row and add their values like this:
int columnTotal, average;
for (int row = 0; row < 2; row++)
{
columnTotal = 0;
for (int col = 0; col < 2; col++)
{
columnTotal += grades[row, col];
}
average = columnTotal/2;
Console.WriteLine("Average: {0}", average);
}

Microsoft Solver Foundation doesn't solve what is solved by Excel solver

I have a non-linear optimization problem with constraints. I solved it with Excel Solver (GRG)
but when I tried to translate it to C# with Microsoft Solver Foundation it gets solution.Quality = SolverQuality.Unknown.
The problem is this: I have some decisions and limit constraints (upper and lower) for every one of them. And two other constraints (this ones are the problematic constraints):
the sum of the Decision need to be 1 (100%)
(MMULT(TRANSPOSE(Decision-Array),MMULT(Tabel-with-values,Decision-Array)))^0.5 needs to be equal to another value
The goal is sum(Decision * value). I write it by Microsoft Solver Foundation like this:
SolverContext solverData = SolverContext.GetContext();
context.ClearModel();
model = context.CreateModel();
for (i=0 ; i< decisionCount; i++)
{
var decision = new Decision(SolverDomain.RealNonnegative, "decisions_" + i);
model.AddDecision(decision);
model.AddConstraint("limits_of_" + i, downConstraint(i) <= decision <= upConstraint(i));
}
var fdecision = new Decision(SolverDomain.RealNonnegative, "formula");
//mymatrix is double[,]
model.AddConstraint("f_constraint_1", fdecision == matMult(transpose(model.Decisions.ToList()),
matMult(matrix(mymatrix), transpose(model.Decisions.ToList()))[0, 0]);
//myAalue is double = givvenValue^2
solverData.model.AddConstraint("f_constraint_2", fdecision == myAalue);
var udecision = new Decision(SolverDomain.RealNonnegative, "upto100");
model.AddConstraint("upto1_constraint_1", udecision == UpTo100Precent(model.Decisions.ToList()));
model.AddConstraint("upto1_constraint_2", udecision == 1);
solverData.model.AddGoal("goal", GoalKind.Maximize, CalcGoal(model.Decisions.ToList()));
model.AddDecision(udecision);
model.AddDecision(fdecision);
Solution solution = context.Solve(new HybridLocalSearchDirective() { TimeLimit = 60000 });
//add here I get solution.Quality == SolverQuality.Unknown
These are the functions I use in above code:
private Term[,] matrix(Double[,] m)
{
int rows = m.GetLength(0);
int cols = m.GetLength(1);
Term[,] r = new Term[rows, cols];
for (int row = 0; row < rows; row++)
for (int col = 0; col < cols; col++)
r[row, col] = m[row, col];
return r;
}
private Term[,] matMult(Term[,] a, Term[,] b)
{
int rows = a.GetLength(0);
int cols = b.GetLength(1);
Term[,] r = new Term[rows, cols];
for (int row = 0; row < rows; row++)
for (int col = 0; col < cols; col++)
{
r[row, col] = 0;
for (int k = 0; k < a.GetLength(1); k++)
{
r[row, col] += a[row, k] * b[k, col];
}
}
return r;
}
private Term[,] transpose(Term[,] m)
{
int rows = m.GetLength(0);
int cols = m.GetLength(1);
Term[,] r = new Term[cols, rows];
for (int row = 0; row < rows; row++)
for (int col = 0; col < cols; col++)
{
r[col, row] = m[row, col];
}
return r;
}
private Term UpTo100Precent(List<Decision> decisions)
{
Term to100 = 0;
foreach (var decision in decisions)
{
to100 += decision;
}
return to100;
}
private Term CalcGoal(List<Decision> decisions)
{
Term x = 0;
//A is double[]
for (i = 0; i < decisions.Count ; i++)
{
x += decisions[i] * A[1]
}
return x;
}
Does someone have a solution?

Categories

Resources