I want to solve a binary Linear Problem in C# using Microsoft Solver Foundation. I don't know why I get wrong answer. The Objective Value should be 41.1 but I get 213. The value of 5 variables should be 1 and the other ones should be 0. But I get many many variables with wrong values.
The sum of each row of the matrix should be <= 1. That are my constraints, and as you see in Constraint_arr I get the right constraints.
Thanks for any help.
Define decision variables:
SolverContext context = SolverContext.GetContext();
Model model = context.CreateModel();
Decision[,] x = new Decision[name_column.Length, 7];
for (int i = 0; i < name_column.Length; i++)
{
for (int j = 0; j < 7; j++)
{
x[i, j] = new Decision(Domain.IntegerRange(0,1), "x" + i + j);
}
}
for (int i = 0; i < name_column.Length; i++)
{
for (int j = 0; j < 7; j++)
{
model.AddDecisions(x[i, j]);
}
}
Create Constraint and add it to model:
Term[] Constraint_arr = new Term[name_column.Length];
Term tempC;
int jj;
for (int i = 0; i < name_column.Length; i++)
{
tempC = 0;
for (jj= 0; jj < 7; jj++)
{
if(vars_Matrix[i,jj] == 1)
{
tempC += x[i,jj];
}
}
Constraint_arr[i] = tempC;
model.AddConstraints("constraint" + i, Constraint_arr[i] <= 1);
}
Create Objective Function:
Term objective_Func = 0;
Term tempZ;
for (int i = 0; i < name_column.Length; i++)
{
tempZ = 0;
for (int j = 0; j < 7; j++)
{
tempZ += x[i, j] * ratio[i];
}
objective_Func+= tempZ;
}
model.AddGoal("Goal", GoalKind.Maximize, objective_Func);
print the answer:
Solution solution = context.Solve(new SimplexDirective());
Report report = solution.GetReport();
for (int i = 0; i < name_column.Length; i++)
{
for (int j = 0; j < 7; j++)
{
Console.Write(x[i, j]);
}
Console.WriteLine();
}
Console.Write("{0}", report);
Console.ReadLine();
The following MiniZinc model arrives at 14 as maximum value for the objective:
set of int: rows = 1..5;
set of int: cols = 1..7;
array[rows, cols] of 0..1: vars_Matrix = [|0, 0, 1, 0, 1, 1, 1
|0, 0, 1, 1, 0, 1, 1
|0, 0, 1, 0, 0, 0, 0
|0, 0, 1, 1, 0, 1, 1
|0, 0, 0, 0, 1, 0, 0|];
array[cols] of var 0..1: c;
var int: obj;
% constraint
% obj = sum(i in rows)(
% sum(j in cols) (
% c[i] * vars_Matrix[i, j]
% )
% );
constraint
obj = sum([ sum([ c[i] * vars_Matrix[i, j] | j in cols ]) | i in rows ]);
solve maximize(obj);
Output
c = array1d(1..7, [1, 1, 1, 1, 1, 1, 1]);
obj = 14;
The same result is obtained from the following Z3py model:
from z3 import *
s = Optimize()
Rows = range(5);
Cols = range(7);
vars_Matrix = [[0, 0, 1, 0, 1, 1, 1],
[0, 0, 1, 1, 0, 1, 1],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 1],
[0, 0, 0, 0, 1, 0, 0]]
c = [Int("c" + str(i+1)) for i in Rows]
obj = Int("obj")
for i in Rows:
s.add(c[i] >= 0, c[i] <= 1)
s.add(obj == Sum( [ Sum( [ c[i] * vars_Matrix[i][j] for j in Cols ] ) for i in Rows ] ))
s.maximize(obj)
if sat == s.check():
print(s.model())
else:
print("No solution. Sorry!")
Related
int[,] cells = new int[,]
{
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0},
{0, 0, 3, 0, 2, 0, 0},
{0, 0, 0, 4, 6, 0, 0},
{0, 0, 0, 6, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0}
};
Hello, i have this 2D array of intergers, i want to crop out the the values to a new 2D array.
What i should end up with is:
1 0 0
3 0 2
0 4 6
0 6 0
What I have is the following, It works if the 2D array is surrounded by 1 row and 1 column. But stops working of the rows and columns increase.
public static int[,] Trim2DArray(int[,] fArray, int n)
{
List<int> rangeX = new List<int>();
List<int> rangeY = new List<int>();
int[,] corrArray = new int[,]{};
if(n == 0)
{
return fArray;
}
else
{
for(int y = 0; y < fArray.GetLength(0); y++)
{
for(int x = 0; x < fArray.GetLength(1); x++)
{
if(fArray[y,x] > 0)
{
rangeX.Add(x);
rangeY.Add(y);
}
}
}
int xm = rangeX.Min();
int ym = rangeY.Min();
int xM = rangeX.Max();
int yM = rangeY.Max();
corrArray = new int[xM,yM];
for(int col = 0; col <= corrArray.GetLength(0)-yM; col++)
{
for(int row = 0; row <= corrArray.GetLength(1)-xM; row++)
{
corrArray[col, row] = fArray[col + xm, row + ym];
}
}
}
return corrArray;
}
You made few mistakes.
Firstly corrArray starts at 0 and ends at xM and yM, so it is too big by xm - 1 and ym - 1 respectively. The -1 is neccessay in case xm==xM or ym==yM - this might happen if only a single row or column has positive numbers. This is the correct way:
corrArray = new int[xM + 1- xm, yM + 1 - ym];
Secondly, you loop indexing wrong.
for (int col = 0; col < corrArray.GetLength(0); col++)
{
for (int row = 0; row < corrArray.GetLength(1); row++)
{
corrArray[col, row] = fArray[col + xm, row + ym];
}
}
You might also consider abandoning list usage, as it's completely unnecessary:
private static int[,] Trim2DArray(int[,] fArray)
{
var startY = -1;
var startX = -1;
var endY = -1;
var endX = -1;
for (int x = 0; x < fArray.GetLength(0); x++)
{
for (int y = 0; y < fArray.GetLength(1); y++)
{
if (fArray[x, y] != 0)
{
if (startX == -1) startX = x;
if (startY == -1) startY = y;
if (x > endX) endX = x;
if (y > endY) endY = y;
}
}
}
if (startX == -1)
{
return new int[0,0];
}
var crop = new int[endX - startX + 1, endY - startY + 1];
for (int x = 0; x < crop.GetLength(0); x++)
{
for (int y = 0; y < crop.GetLength(1); y++)
{
crop[x, y] = fArray[x + startX, y + startY];
}
}
return crop;
}
You have the right idea but you only need to track the four corners rather than building a list of all cells with data.
Here's an example which works for any number of rows and columns.
private static int[,] Trim2DArray(int[,] fArray)
{
var startY = -1;
var startX = -1;
var endY = -1;
var endX = -1;
for (int x = 0; x < fArray.GetLength(0); x++)
{
for (int y = 0; y < fArray.GetLength(1); y++)
{
if (fArray[x, y] != 0)
{
if (startX == -1) startX = x;
if (startY == -1) startY = y;
if (x > endX) endX = x;
if (y > endY) endY = y;
}
}
}
if (startX == -1)
{
return new int[0,0];
}
var crop = new int[endX - startX + 1, endY - startY + 1];
for (int x = 0; x < crop.GetLength(0); x++)
{
for (int y = 0; y < crop.GetLength(1); y++)
{
crop[x, y] = fArray[x + startX, y + startY];
}
}
return crop;
}
The following picture is retrieved from Wikipedia:
I haven't understood this part:
I have two questions here:
Where did they obtain [8,4,1,2] from and what did they want to tell us by that?
Take a look at cell [0, 0] whose value is 13. If I go clockwise along with its contouring values, I obtain the binary string 0010 which is 2. How does the 1st cell-value become 13?
.
enum What
{
lines, surface, both
}
class Program
{
public static void Print(int[,] data, int xn, int yn)
{
for (int j = 0; j < yn; j++)
{
for (int i = 0; i < xn; i++)
{
Console.Write(data[i,j] + ", ");
}
Console.WriteLine();
}
}
public static int[,] normalize(int[,] data, int xn, int yn)
{
for (int j = 0; j < yn; j++)
{
for (int i = 0; i < xn; i++)
{
if (data[i, j] > 1)
{
data[i, j] = 0;
}
else
{
data[i, j] = 1;
}
}
}
return data;
}
public static int[,] marching_square(int x, int y, int[,] data, int isovalue, What what)
{
int xn = x;
int yn = y;
data = normalize(data, xn, yn);
int[,] bitMask = new int[xn - 1, yn - 1];
for (int j = 0; j < yn - 1; j++)
{
for (int i = 0; i < xn - 1; i++)
{
StringBuilder sb = new StringBuilder();
sb.Append(data[i, j]);
sb.Append(data[i, j + 1]);
sb.Append(data[i + 1, j]);
sb.Append(data[i + 1, j + 1]);
bitMask[i, j] = Convert.ToInt32(sb.ToString(), 2);
}
}
return bitMask;
}
static void Main(string[] args)
{
int[,] data = new int[,] {
{ 1,1,1,1,1 },
{ 1,2,3,2,1 },
{ 1,3,3,3,1 },
{ 1,2,3,2,1 },
{ 1,1,1,1,1 }
};
Print(data, 5,5);
int[,] bitMask = marching_square(5,5,data, 0, What.lines);
Print(bitMask, 4, 4);
}
}
Output:
1, 1, 1, 1, 1,
1, 2, 3, 2, 1,
1, 3, 3, 3, 1,
1, 2, 3, 2, 1,
1, 1, 1, 1, 1,
14, 10, 10, 11,
12, 0, 0, 3,
12, 0, 0, 3,
13, 5, 5, 7,
I inverted the bits. But, the output looks different.
Im having trouble with code, I get
System.IndexOutOfRangeException
in the first loop in the find() method. Could you guys help me? I cant figure out whats wrong.
I've found this code for java and changed a little bit for C#. In java code there was int[][] A, Ive changed it to int[,]. P.S on java, code works.
class Program
{
static void Main(string[] args)
{
int[,] A = { { 1, 7, 9, 2 }, { 8, 6, 3, 2 }, { 1, 6, 7, 8 },
{ 2, 9, 8, 2 } };
Console.WriteLine("{0}", find(A));
}
public static int find(int[,] A)
{
int[,] solution = new int[A.Length + 1, A.Length + 1];
solution[0, 0] = A[0, 0];
for(int i = 1; i < A.Length; i++)
{
solution[0, i] = A[0, i] + solution[0, i - 1]; //IndexOutOfRangeException
}
for(int i = 1; i < A.Length; i++)
{
solution[i, 0] = A[i, 0] + solution[i - 1, 0];
}
for(int i = 1; i < A.Length; i++)
{
for(int j = 1; j < A.Length; j++)
{
solution[i, j] = A[i, j]
+ Math.Min(solution[i - 1, j], solution[i, j - 1]);
}
}
return solution[A.Length - 1, A.Length - 1];
}
}
The problem is that in a jagged array ([,]) the property Length will give you the overall amount of elements, in your case A.Length == 16 but you want only one dimension. The solution would be to use GetLength.
for (int i = 1; i < A.GetLength(1); i++)
you need to use 0 for the X-Dimension and 1 for the Y-Dimenstion ( [X,Y]) see the documenation for details.
This is how your method should look like:
public static int find(int[,] A)
{
int[,] solution = new int[A.GetLength(0) + 1, A.GetLength(1)+ 1];
solution[0, 0] = A[0, 0];
for (int i = 1; i < A.GetLength(1); i++)
{
solution[0, i] = A[0, i] + solution[0, i - 1];
}
for (int i = 1; i < A.GetLength(0); i++)
{
solution[i, 0] = A[i, 0] + solution[i - 1, 0];
}
for (int i = 1; i < A.GetLength(0); i++)
{
for (int j = 1; j < A.GetLength(1); j++)
{
solution[i, j] = A[i, j]
+ Math.Min(solution[i - 1, j], solution[i, j - 1]);
}
}
return solution[A.GetLength(0) - 1, A.GetLength(1) - 1];
}
I want to sort this row:
5, 1, 6, 2, 4, 3
Here is my code:
int[] a = new int[] { 5, 1, 6, 2, 4, 3 };
int i, j, key;
for (i = 1; i < 6; i++)
{
key = a[i];
j = i - 1;
while (j >= 0 && key < a[j])
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = key;
}
var result = string.Empty;
for (i = 0; i < 6; i++)
{
Console.WriteLine(string.Join(",",a[i]));
//Console.WriteLine(string.Concat(a[i], ","));
}
Console.ReadKey();
I want to print the comma separated output value like below
1,2,3,4,5,6
Can anyone help me out?
You were almost there in getting your output the way you want it.
The String.Join method takes as a second parameter an array, so you can directly pass it your a without the for loop:
Console.WriteLine(string.Join(",", a));
try,
int[] a = new int[] { 5, 1, 6, 2, 4, 3 };
int i, j, key;
var result = string.Empty;
for (i = 0; i < 6; i++)
{
for (j = i+1; j < 6; j++)
{
if (a[i] > a[j])
{
key = a[i];
a[i] = a[j];
a[j] = key;
}
}
result += a[i].ToString() + ((i == 5) ? "" : ",");
}
Console.WriteLine( result);
Console.ReadKey();
You also can try this way:
for (i = 0; i < 6; i++)
{
Console.Write(a[i].ToString());
if(i < 5)
Console.Write(",");
else
Console.WriteLine();
}
I have a 2D array as follows:
long[,] arr = new long[4, 4] {{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 }};
I want to print the values of this array in matrix format like:
0 0 0 0
1 1 1 1
0 0 0 0
1 1 1 1
How can I do this?
You can do it like this (with a slightly modified array to show it works for non-square arrays):
long[,] arr = new long[5, 4] { { 1, 2, 3, 4 }, { 1, 1, 1, 1 }, { 2, 2, 2, 2 }, { 3, 3, 3, 3 }, { 4, 4, 4, 4 } };
int rowLength = arr.GetLength(0);
int colLength = arr.GetLength(1);
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Console.Write(string.Format("{0} ", arr[i, j]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
Console.ReadLine();
like so:
long[,] arr = new long[4, 4] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
var rowCount = arr.GetLength(0);
var colCount = arr.GetLength(1);
for (int row = 0; row < rowCount; row++)
{
for (int col = 0; col < colCount; col++)
Console.Write(String.Format("{0}\t", arr[row,col]));
Console.WriteLine();
}
I wrote extension method
public static string ToMatrixString<T>(this T[,] matrix, string delimiter = "\t")
{
var s = new StringBuilder();
for (var i = 0; i < matrix.GetLength(0); i++)
{
for (var j = 0; j < matrix.GetLength(1); j++)
{
s.Append(matrix[i, j]).Append(delimiter);
}
s.AppendLine();
}
return s.ToString();
}
To use just call the method
results.ToMatrixString();
Here is how to do it in Unity:
(Modified answer from #markmuetz so be sure to upvote his answer)
int[,] rawNodes = new int[,]
{
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 }
};
private void Start()
{
int rowLength = rawNodes.GetLength(0);
int colLength = rawNodes.GetLength(1);
string arrayString = "";
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
arrayString += string.Format("{0} ", rawNodes[i, j]);
}
arrayString += System.Environment.NewLine + System.Environment.NewLine;
}
Debug.Log(arrayString);
}
Your can do it like this in short hands.
int[,] values=new int[2,3]{{2,4,5},{4,5,2}};
for (int i = 0; i < values.GetLength(0); i++)
{
for (int k = 0; k < values.GetLength(1); k++) {
Console.Write(values[i,k]);
}
Console.WriteLine();
}
you can do like this also
long[,] arr = new long[4, 4] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 }};
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
Console.Write(arr[i,j]+" ");
}
Console.WriteLine();
}
If using a square matrix:
int[,] mat = new int[,]{{ 1, 0, 0 },{ 0, 1, 0},{ 0, 0, 1}};
int i=1;
foreach(int e in mat){
Console.Write(i%Math.Sqrt(mat.Length)==0? $"{e}\n" : e);
i+=1;
}