Related
I'm trying to solve a non square linear system with Math.net.
But I get an error Matrix dimensions must agree: 3x7.
Here is some example code:
using MathNet.Numerics.LinearAlgebra;
var mBuilder = Matrix<double>.Build;
var vBuilder = Vector<double>.Build;
var A = mBuilder.DenseOfArray(new double[,]
{
{ 3, 2, 1, 5, -1, 0, 0 },
{ 2, 1, 1, 2, 0, -1, 0 },
{ 5, 1, 3, 4, 0, 0, -1 }
});
var b = vBuilder.DenseOfArray(new double[] { -3, -5, -2 });
Vector<double> x;
x = A.Solve(b);
Cleary the system has a solution (e.g. X = {0, 0, 0, 0, 3, 5, 2}).
How can I solve such a system with Math.Net?
You can not use the Matrix.Solve function with a non-square matrix because there is no inverse and no unique solutions for a rectangular matrix. Google "inverse of rectangular matrix" for explanations galore. You can use pseudoinverse however, as shown below.
var mBuilder = Matrix<double>.Build;
var A = mBuilder.DenseOfArray(new double[,]
{
{ 3, 2, 1, 5, -1, 0, 0 },
{ 2, 1, 1, 2, 0, -1, 0 },
{ 5, 1, 3, 4, 0, 0, -1 }
});
Matrix<double> b = Matrix<double>.Build.Dense(3, 1);
b[0, 0] = -3.0;
b[1, 0] = -5.0;
b[2, 0] = -2.0;
var p = A.PseudoInverse();
var x = p * b;
// verify
var o = A * x;
Let's say I have an Array:
arr[3]={0,1,2};
and I am generating a Random value:
int r = Random.Range(0,4);
And in my code just after that I want to use:
print(arr[r-1]+arr[r]+arr[r+1]);
In this case it will only work if arr[r] is 1, because if r=0 then r-1 will be -1 , what can I do so if I increment the last index, it goes back to a certain point?
So that if r=2, so arr[r]=2, arr[r+1]=0 , and arr[r+4] is also 0 because it did an extra loop.
I know I could use ifs, if r=0 then r-1=3 but it's less than ideal.
Thanks
Here's something that I think you can work with:
var random = new Random();
var arr = new [] { 0, 1, 2 };
for (var i = 0; i < 20; i++)
{
int r = random.Next(1, 1 + arr.Length);
Console.WriteLine(String.Join(", ", (r - 1) % 3, r % 3, (r + 1) % 3));
}
That produces:
1, 2, 0
2, 0, 1
2, 0, 1
1, 2, 0
2, 0, 1
2, 0, 1
1, 2, 0
1, 2, 0
2, 0, 1
1, 2, 0
1, 2, 0
1, 2, 0
2, 0, 1
1, 2, 0
1, 2, 0
1, 2, 0
0, 1, 2
1, 2, 0
1, 2, 0
0, 1, 2
You can try modulus %. I'm not too sure if the operation will always return a positive value, but you can always do r = random.range(3,7);, and then use r-1 % 3 etc.
I am trying to create a two dimensional array of random 1 and 0. These will be used to switch on or off I/O lines on an Arduino. The number of arrays (height) to create will come from a textbox on the UI as will the number of items (width) in each array.
This means I do not know how many arrays I will have so what I want to do is have a loop in which I name each array e.g. a0 then a1 then a2 etc.
I have tried to name them but as you can see below have not been able to get it right. What do I need to do?
private int[][] build_data(int height, int width)
{
Random randNum = new Random();
int Min = 0, Max = 2;
var array_name = "a";
rch_txtbx.AppendText(height.ToString() + "\r");
rch_txtbx.AppendText(width.ToString() + "\r");
for (int j = 0; j <= height; j++) //create a0 to ax
{
array_name = "a" + j; //this creates the name I want
int[] a = new int[width]; //need to initialise each array in turn but how?
for (int i = 0; i <= width; i++) //create number of items in each array
{
a[i] = randNum.Next(Min, Max);
}
}
/* This is what I am trying to create arayys of random 0 and 1
int[] a1 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] a2 = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
int[] a3 = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0 };
int[] a4 = { 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0 };
int[] a5 = { 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0 };
int[] a6 = { 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0 };
int[] a7 = { 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0 };
int[] a8 = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
int[] a9 = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0 };
int[] a10 = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0 };
int[] a11 = { 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0 };
int[] a12 = { 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0 };
int[] a13 = { 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0 };
int[] a14 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
*/
//get data ready to send back
int[][] arr = { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 };
return arr;
}
Instead of trying to dynamically create variables and then add them into the array just at the end of each outer loop iteration set the value of that array:
int[][] array = new int[height][];
for (int i = 0; i < height; i++)
{
int[] innerArray = new int[width];
for (int j = 0; j < width; j++)
innerArray[j] = r.Next(min, max);
array[i] = innerArray;
}
You can also replace the above for loops with Linq:
// Creates an enumerable with N
var array = Enumerable.Repeat(0, height) items
// For each item create an enumerable with M items
.Select(i => Enumerable.Repeat(0, width)
// Set the value of each inner item to a
// random number
.Select(j => r.Next(min,max))
// Convert to an array
.ToArray())
.ToArray();
You can use a multidimensional array:
int[,] random2dArray = new int[width, height];
for (int j = 0; j <= random2dArray.GetLength(0); j++)
{
for (int i = 0; i <= random2dArray.GetLength(1); i++)
{
random2dArray[j, i] = randNum.Next(Min, Max);
}
}
For more info you can look at MSDN.
According to the signature
private int[][] build_data(int height, int width)
you actually want to create an array of array int[][] (aka jagged array). You can do it quite direct:
// Simplest, but not thread-safe
private static Random s_Gen = new Random();
// static: there's no need in "this"
private static int[][] build_data(int height, int width) {
int[][] result = new int[height][];
for (int i = 0; i < result.Length; ++i) {
int[] line = new int[width];
for (int j = 0; j < line.Length; ++j)
line[j] = s_Gen.Next(2);
result[i] = line;
}
return result;
}
In case you want to have a collection of named arrays, I suggest using Dictionary<string, int[]> as a returned type:
private static Dictionary<string, int[]> build_named_data(int height, int width) {
Dictionary<string, int[]> result = new Dictionary<string, int[]>();
for (int i = 1; i <= height; ++i) {
int[] line = new int[width];
for (int j = 0; j < line.Length; ++j)
line[j] = s_Gen.Next(2);
result.Add($"a{i}", line);
}
return result;
}
....
var myData = build_named_data(15, 20);
int[] array = build_named_data["a3"];
This is what i have decided to start with a winForm & 1 button called btnCreate and I have 2 images 35px X 35px floor.bmp and wall.bmp
public partial class Form1 : Form
{
int x;
int y;
int[] Row0 = new int[10] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
int[] Row1 = new int[10] { 1, 1, 1, 1, 0, 0, 1, 1, 0, 1 };
int[] Row2 = new int[10] { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 };
int[] Row3 = new int[10] { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1 };
int[] Row4 = new int[10] { 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 };
int[] Row5 = new int[10] { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 };
int[] Row6 = new int[10] { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 };
int[] Row7 = new int[10] { 1, 1, 1, 1, 0, 0, 1, 1, 0, 1 };
int[] Row8 = new int[10] { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 };
int[] Row9 = new int[10] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
int[,] LevelA = new int[10,10];
private void Form1_Load(object sender, EventArgs e)
{
for (x = 0; x < 10; x++)
{
//load all arrays
LevelA[0, x] = Row0[x];
LevelA[1, x] = Row1[x];
LevelA[2, x] = Row2[x];
LevelA[3, x] = Row3[x];
LevelA[4, x] = Row4[x];
LevelA[5, x] = Row5[x];
LevelA[6, x] = Row6[x];
LevelA[7, x] = Row7[x];
LevelA[8, x] = Row8[x];
LevelA[9, x] = Row9[x];
}
}
private void btnCreate_Click(object sender, EventArgs e)
{
for (int X = 0; X < 10; X++)
{
for (int Y = 0; Y < 10; Y++)
{
//the following is the idea of what I would like to accomplish
//if (LevelA[Y,X] == 0)
//{
//Bitmap myBmp = new Bitmap(Image.FromFile(#"C:\My Documents\floor2.bmp"));
//myBmp.Top == Y * 35;
//myBmp.left == X * 35;
//}
}
}
}
}
Would the CODE above work as I intend it too >? or would the end of the for-loop only display the last tile as it would keep replacing(destroying) the previous one with a new one? In witch case I would need to have 100 myBmp's for a 10 by 10 grid?
You can get the bitmap of an image file by creating a Bitmap object.
Bitmap bmp = new Bitmap(Image.FromFile(#"D:\MyImageFile.bmp"));
You can place that or draw that anywhere as long as you get hold of a Graphics instance.
You can find asimple example here about that.
I have a nested loop "structure" in my code. Sometimes, I get the below message.
Collection was modified; enumeration operation may not execute.
I have a collection I am looping through, like below. Coll is a List<string>
foreach (string[] s1 in obj.Coll
{
foreach (string s in s1) { }
}
For each string in the array, I need to work with it (read as read the value, not write).
All I do with it is get directories (this value is a path) and split this string into an array.
How can this be resolved?
The obj.Coll is changed while you are enumerating it. If it is not changed by the current thread, it may be changed by some other thread. If the collection is changed by the current thread, there are basically two ways to solve the problem: You can create a copy of the collection and enumerate the copy or you can postpone the changes until you have enumerated the collection.
However, if the collection is changed by another thread, you should access the collection in a thread-safe manner (not just here but everywhere).
EDIT for Kieren Johnstone:
I wrote a short code to demonstrate that List<T>.ToArray() is not thread-safe.
var list = new List<int>();
Task.Factory.StartNew(() => {
for (int i = 0; i < 1000000; ++i) {
list.Clear();
// Add values from 1 to 9
for (int j = 1; j < 10; ++j) {
list.Add(j);
}
}
Console.WriteLine("Thread Exit: list.Add()");
});
Task.Factory.StartNew(() => {
for (int i = 0; i < 100; ++i) {
var array = list.ToArray();
if (array.Length > 0) {
Console.WriteLine("ToArray(): {0}", string.Join(", ", array));
}
}
Console.WriteLine("Thread Exit: list.ToArray()");
});
And below is a snippet of the output. I guess that it proves my claim. The snippet contains 15 lines and nine of them contain bad data.
ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 6, 7, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 0, 0, 0, 4, 5, 6, 7
ToArray(): 1, 2, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3
ToArray(): 1, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2
ToArray(): 1, 2, 3
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 6, 7, 8
There would be more variations if we had used list.Insert(0, j) instead of list.Add(j).
You can try:
foreach (string[] s1 in obj.Coll.ToArray())
{
That will take a copy before starting iteration!