I am trying to implement a genetic algorithm in c#. The genetic has crossover method and mutation method. The population size is 5 chromosomes where each chromosome is a 2d array of integers (matrix 10x10) The genetic should loop 50 times and call crossover and mutation each loop as follows:
DateTime startTiming = DateTime.Now;
TimeSpan startGenetic;
// Make a population for each layer - as we have 4 layers, thus 4 population arrays after the intial eavaluation for the intial population and have differernt values in the aterations > 1
static List<int[,]> populationLayer1 = new List<int[,]>();
static List<int[,]> populationLayer2 = new List<int[,]>();
static List<int[,]> populationLayer3 = new List<int[,]>();
static List<int[,]> populationLayer4 = new List<int[,]>();
// 4 layers - we need 4 arrays
double[,] FitnessValLayer1 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)
double[,] FitnessValLayer2 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)
double[,] FitnessValLayer3 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)
double[,] FitnessValLayer4 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)
// 4 RouletteWeel values because of the 4 layers
int[] RouletteWheelLayer1 = new int[10];
int[] RouletteWheelLayer2 = new int[10];
int[] RouletteWheelLayer3 = new int[10];
int[] RouletteWheelLayer4 = new int[10];
public async Task Genetic_Algorithm(List<int[,]> population)
{
cancelSource = new CancellationTokenSource();
//In this step just duplicate the initial population
populationLayer1 = population.ToList();
populationLayer2 = population.ToList();
populationLayer3 = population.ToList();
populationLayer4 = population.ToList();
int round = 0;
for (geneticIteration = 0; geneticIteration < minIteration; geneticIteration++)
{
round = geneticIteration;
//----------------------//
//Calculate Fitness
try
{
// Calculate the fitness Function and the Fitness Ratio
await FitnessFunctionAsync(populationLayer1, populationLayer2, populationLayer3, populationLayer4, cancelSource.Token); // Fitness Function
}
catch (Exception ex)
{
// Write output to the file.
Trace.Write("when calling (FitnessFunctionAsync)..." + ex.Message);
Trace.Flush();
}
//----------------------//
// To Do :
//get 4 arrays for the fitness for each layer
//----------------------//
// Note : Each layer has different values for fitness so the changes on the population will not be the same in the 4 layers
//---------------------//
//RouletteWeel
RouletteWheelLayer1 = RouletteWheel_Selection(FitnessValLayer1);
RouletteWheelLayer2 = RouletteWheel_Selection(FitnessValLayer2);
RouletteWheelLayer3 = RouletteWheel_Selection(FitnessValLayer3);
RouletteWheelLayer4 = RouletteWheel_Selection(FitnessValLayer4);
//Crossover
// populationLayer1 = CrosssOver(RouletteWheelLayer1, populationLayer1);
//populationLayer2 = CrosssOver(RouletteWheelLayer2, populationLayer2);
// populationLayer3 = CrosssOver(RouletteWheelLayer3, populationLayer3);
//populationLayer4 = CrosssOver(RouletteWheelLayer4, populationLayer4);
//Mutation
//populationLayer1 = Mutation(RouletteWheelLayer1, populationLayer1);
// populationLayer2 = Mutation(RouletteWheelLayer2, populationLayer2);
// populationLayer3 = Mutation(RouletteWheelLayer3, populationLayer3);
//populationLayer4 = Mutation(RouletteWheelLayer4, populationLayer4);
// 4 layers - re-intialize
FitnessValLayer1 = new double[5, 2];
FitnessValLayer2 = new double[5, 2];
FitnessValLayer3 = new double[5, 2];
FitnessValLayer4 = new double[5, 2];
// 4 RouletteWeel - re-intialize
RouletteWheelLayer1 = new int[10];
RouletteWheelLayer2 = new int[10];
RouletteWheelLayer3 = new int[10];
RouletteWheelLayer4 = new int[10];
}
InvokeUpdateControls();
}
Unfortunately, I got my application not response when implement the crossover or mutation i.e. when the probabilities are satisfied. The following are the two methods:
public List<int[,]> CrosssOver(int[] RouletteWheel, List<int[,]> population)
{
double rndNumber1 = 0.0;
int rndNumber2 = 0;
Random rnd = new Random();
int chrom1 = 0;
int chrom2 = 0;
for (int i = 0; i < population.Count; i++) // For all Chromosomes
{
rndNumber1 = rnd.Next(0, 11) / 10.00; // generate a random number to check the probability for crossover
chrom1 = RouletteWheel[rnd.Next(0, 10)];
chrom2 = RouletteWheel[rnd.Next(0, 10)];
if (rndNumber1 <= Pc) /* check if we will do Crossover */
{
rndNumber2 = rnd.Next(0, rows - 1); // determine the crossover point randomly by generating number between 0 and rows-1
for (int j = 0; j < rows; j++)
{
for (int v = 0; v < columns; v++)
{
if (j == rndNumber2) /* copy from same chromosome */
{
try
{
population[chrom1][j, v] = population[chrom2][j, v];
}
catch (Exception ex)
{
// Write output to the file.
Trace.Write("crossover..." + ex.Message);
Trace.Flush();
return population;
}
}
}
}
}
}
return population;
} // end-cross-over
The mutation method:
public List<int[,]> Mutation(int[] RouletteWheel, List<int[,]> population)
{
double rndNumber1 = 0.0;
int chrom1 = 0;
int rndNumber2 = 0;
Random rnd = new Random();
for (int i = 0; i < population.Count; i++) // For all Chromosomes
{
rndNumber1 = rnd.Next(0, 11) / 100.00; // generate a random number between 0 and 10 and divide result by 100
chrom1 = RouletteWheel[rnd.Next(0, 10)];
if (rndNumber1 <= Pm) /* check if we will do Crossover */
{
rndNumber2 = rnd.Next(0, rows); // determine the crossover point randomly by generating number between 0 and rows -1
for (int j = 0; j < rows; j++)
{
for (int v = 0; v < columns; v++)
{
if (j == rndNumber2) /* Mutate the cell that is equal to 1 */
{
try
{
if (population[chrom1][j, v] == 0)
{
population[chrom1][j, v] = 1;
}
}
catch (Exception ex)
{
// Write output to the file.
Trace.Write("mutation..." + ex.Message);
Trace.Flush();
return population;
}
}
}
}
}
}
return population;
}
My app is stuck because of these methods...
I need to move to the next iteration if the mutation and crossover are successfully completed.
Unfortunately, the only real answer in a case like this is to move the offending code into a separate thread so the main thread remains available to pump the message queue.
Make sure it can't be triggered twice, make sure nothing else can write the data while it's running and be very wary of even reading any of the data (for example, to display intermediate results) in any other thread.
Related
I can't fill it with numbers to 0 - 15 then shuffle the array, so that's not the solution
I used this code in C but now in c# it doesn't work, for some reason this code let some numbers pass the do while.
Random r = new Random();
bool unique;
int rand_num;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
do
{
unique = true;
rand_num = r.Next(16);
for (int k = 0; k < 4; k++)
{
for (int l = 0; l < 4; l++)
{
if (numbers[k, j] == rand_num)
{
unique = false;
}
}
}
} while (!unique);
numbers[i, j] = rand_num;
}
}
}
If the list of possible numbers is small, as in this case, just create the full list and randomise it first, then take the items in the order they appear. In your case, you can put the randomised numbers into a queue, then dequeue as required.
var r = new Random();
var numberQueue = new Queue<int>(Enumerable.Range(0, 16).OrderBy(n => r.NextDouble()));
var numbers = new int[4, 4];
for (var i = 0; i <= numbers.GetUpperBound(0); i++)
{
for (var j = 0; j <= numbers.GetUpperBound(1); j++)
{
numbers[i, j] = numberQueue.Dequeue();
}
}
I suggest you to use the Fisher-Yates algorithm to generate your non-repeatable sequence of random numbers.
It would be very straight-forward to implement a code to fill in a 2d array with those numbers, then.
List<int> seq = Enumerable.Range(0,16).ToList();
int[,] numbers = new int[4,4];
Random r = new();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int n = r.Next(0, seq.Count);
numbers[i,j] = seq[n];
seq.RemoveAt(n);
}
}
The approach you have taken may end up in continuous looping and take lot of time to complete.
Also checking for value in 2D using nested for loop is not efficient.
You can use HashSet to keep track of unique value. Searching in HashSet is fast.
following is the code approach I suggest.
var hashSet = new HashSet<int>();
var r = new Random();
var arr = new int[4, 4];
for(var i = 0;i<4;i++)
{
for(var j = 0;j<4;j++)
{
// Generate random value between 0 and 16.
var v = r.Next(0, 16);
// Check if the hashSet has the newly generated random value.
while(hashSet.Contains(v))
{
// generate new random value if the hashSet has the earlier generated value.
v = r.Next(0, 16);
}
//Add value to the hashSet.
hashSet.Add(v);
// add value to the 2D array.
arr[i, j] = v;
}
}
I hope this will help solving your issue.
The problem with your current approach is that as you get closer to the end of the array, you have to work harder and harder to get the next random value.
Imagine you roll a die, and each time you want to get a unique value. The first time you roll, any result will be unique. The next time, you have a 1/6 chance of getting a number that has already been obtained. And then a 2/6 chance, etc. and in the end most of your rolls will be non-unique.
In your example, you have 16 places that you want to fill with numbers 0 to 15. This is not a case of randomly generating numbers, but randomly placing them. How do we do this with a deck of cards? We shufle them!
My proposal is that you fill the array with unique sequential values and then shuffle them:
Random random = new Random();
int dim1 = array.GetLength(0);
int dim2 = array.GetLength(1);
int length = dim1 * dim2;
for (int i = 0; i < length; ++i)
{
int x = i / dim1;
int y = i % dim1;
array[x, y] = i; // set the initial values for each cell
}
// shuffle the values randomly
for (int i = 0; i < length; ++i)
{
int x1 = i / dim1;
int y1 = i % dim1;
int randPos = random.Next(i, length);
int x2 = randPos / dim1;
int y2 = randPos % dim1;
int tmp = array[x1, y1];
array[x1, y1] = array[x2, y2];
array[x2, y2] = tmp;
}
The shuffle in this code is based on the shuffle found here
int[,] numbers = new int[4, 4];
Random r = new Random();
bool unique;
int rand_num;
List<int> listRandom = new List<int> { };
for ( int i = 0; i < 4; i++ )
{
for ( int j = 0; j < 4; j++ )
{
do
{
unique = false;
if (!listRandom.Contains( rand_num = r.Next( 0, 16 )))
{
listRandom.Add( rand_num );
numbers[i, j] = rand_num;
unique = true;
}
} while ( !unique );
}
}
Basically I'm creating a program to randomly generate 6 unique lottery numbers so there is no duplicates in the same line, here is the code I have so far...
//Generate 6 random numbers using the randomiser object
int randomNumber1 = random.Next(1, 49);
int randomNumber2 = random.Next(1, 49);
int randomNumber3 = random.Next(1, 49);
int randomNumber4 = random.Next(1, 49);
int randomNumber5 = random.Next(1, 49);
int randomNumber6 = random.Next(1, 49);
textBox1.Text = randomNumber1.ToString();
textBox2.Text = randomNumber2.ToString();
textBox3.Text = randomNumber3.ToString();
textBox4.Text = randomNumber4.ToString();
textBox5.Text = randomNumber5.ToString();
textBox6.Text = randomNumber6.ToString();
}
I'm getting random numbers but sometimes there is the same number on the same line, how do I make each number unique????
Thanks in advance
You need to store them in a collection and each time you pick a new number you need to make sure it's not present already, otherwise you need to generate a new number until you find a unique number.
Instead of this, I would generate a sequence between 1 and 49, shuffle them and pick 6 number out of the sequence, for example:
var rnd = new Random();
var randomNumbers = Enumerable.Range(1,49).OrderBy(x => rnd.Next()).Take(6).ToList();
You can't. You've only specified that each number be a random number from 1 to 49, not that it shouldn't match any duplicates.
Since you've got a relatively small set of numbers, your best bet is probably to draw the random numbers, put them into a HashSet, then if you need more, pull more. Something like this:
HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < 6) {
numbers.Add(random.Next(1, 49));
}
Here you're taking advantage of the HashSet's elimination of duplicates. This won't work with a List or other collection.
Returning repeat values is a necessity in order for a generator to satisfy a necessary statistical property of randomness: the probability of drawing a number is not dependent on the previous numbers drawn.
You could shuffle the integers in the range 1 to 49 and return the first 6 elements. See http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle for more details on such a shuffler.
However, I think you get a slight statistical bias by doing this.
The best way is probably to use random.Next(1, 49); and reject any repeat. That will be free from statistical bias and the fact that you're only wanting 6 from 49 possibilities, the number of collisions will not slow the algorithm appreciably.
Using this extension method for reservoir sampling:
public static IList<T> TakeRandom<T>(
this IEnumerable<T> source, int count, Random random)
{
var list = new List<T>(count);
int n = 1;
foreach (var item in source)
{
if (list.Count < count)
{
list.Add(item);
}
else
{
int j = random.Next(n);
if (j < count)
{
list[j] = item;
}
}
n++;
}
return list;
}
You can sample your collection like this:
var random = new Random();
var numbers = Enumerable.Range(1, 49).TakeRandom(6, random);
numbers.Shuffle(random);
Note the returned numbers will be uniformly sampled out of all (49 choose 6) possibilities for a set of 6 numbers out of {1, 2, ..., 49}, but they will neither remain in order nor be uniformly shuffled. If you want to have the order randomized as well, you can easily do a standard Fisher-Yates shuffle afterwards.
public static void Shuffle<T>(this IList<T> list, Random random)
{
for (int i = 0; i < list.Count; i++)
{
int j = random.Next(i, list.Count);
T temp = list[j];
list[j] = list[i];
list[i] = temp;
}
}
Note a more heavily optimized version of Fisher-Yates shuffle can be found in this answer: Randomize a List<T>
List<int> aux = new List<int>();
while(aux.Count < 6)
{
int rnd = random.Next(1,49);
if(!aux.Contains(rnd))aux.add(rnd);
}
if you put all Texbox in the same panel you can do that
int j = 0;
foreach(Control x in MyPanel.Controls)
{
if(x is TexBox)
{
x.Text = aux[j].toString();
j++;
}
}
It's my solution: generate array of number
/// <summary>
/// auto generate a array with number element and max value is max
/// </summary>
/// <param name="number">number element of array</param>
/// <param name="max">max value of array</param>
/// <returns>array of number</returns>
public static int[] createRandomArray(int number, int max)
{
List<int> ValueNumber = new List<int>();
for (int i = 0; i < max; i++)
ValueNumber.Add(i);
int[] arr = new int[number];
int count = 0;
while (count < number)
{
Random rd = new Random();
int index = rd.Next(0,ValueNumber.Count -1);
int auto = ValueNumber[index];
arr[count] = auto;
ValueNumber.RemoveAt(index);
count += 1;
}
return arr;
}
It's too late but I use a Method named M_Randomizer created by me. It may look as too much work, but it's technique is different from traditional which is based on generating a random number and checking the previously generated list for uniqueness. This code while generating a new random number, never looks for the previously generated. And if we talk about touching all combinations, I have tested this method till 9 factorial, maybe little bias for some but it touches all.
using System;
class Randomizer
{
public int[] M_Randomizer(int x)
{
bool b = false;
if (x < -1)
{
b = true;
x = -1 * x;
}
if(x == -1)
x = 0;
if (x < 2)
return new int[x];
int[] site;
int k = new Random(Guid.NewGuid().GetHashCode()).Next() % 2;
if (x == 2)
{
site = new int[2];
site[0] = k;
site[1] = 1 - site[0];
return site;
}
else if (x == 3)
{
site = new int[3];
site[0] = new Random(Guid.NewGuid().GetHashCode()).Next(0, 3);
site[1] = (site[0] + k + 1) % 3;
site[2] = 3 - (site[0] + site[1]);
return site;
}
site = new int[x];
int a = 0, m = 0, n = 0, tmp = 0;
int[] p = M_Randomizer(3);
int[] q;
if (x % 3 == 0)
q = M_Randomizer(x / 3);
else
q = M_Randomizer((x / 3) + 1);
if (k == 0)
{
for (m = 0; m < q.Length; m++)
{
for (n = 0; n < p.Length && a < x; n++)
{
tmp = (q[m] * 3) + p[n];
if (tmp < x)
{
site[a] = tmp;
a++;
}
}
}
}
else
{
while (n < p.Length)
{
while (a < x)
{
tmp = (q[m] * 3) + p[n];
if (tmp < x)
{
site[a] = tmp;
a++;
}
m = m + k;
if (m >= q.Length)
break;
}
m = m % q.Length;
n++;
}
}
a = (new Random(Guid.NewGuid().GetHashCode()).Next() % 2) + 1;
k = new Random(Guid.NewGuid().GetHashCode()).Next() % 10;
if (k > 5)
for (int i = a; i < k; i++)
while (a < site.Length)
{
if (k % (a + 1) == 0)
{
tmp = site[a - 1];
site[a - 1] = site[a];
site[a] = tmp;
}
a = a + 2;
}
k = new Random(Guid.NewGuid().GetHashCode()).Next() % 10;
if (k > 5)
{
n = x / 2;
k = 0;
if (x % 2 != 0)
k = (new Random(Guid.NewGuid().GetHashCode()).Next() % 2);
p = new int[n + k];
m = (x - n) - k;
for (a = 0; m < x; a++, m++)
p[a] = site[m];
m = n + k;
for (a = (x - m) - 1; a >= 0; a--, m++)
site[m] = site[a];
for (a = 0; a < p.Length; a++)
site[a] = p[a];
}
int[] site2;
int[] site3 = new int[x];
if (b)
return site;
else
site2 = M_Randomizer(-1 * x);
for (a = 0; a < site.Length; a++)
site3[site2[a]] = site[a];
return site3;
}
public int[] M_Randomizer(int x, int start)
{
int[] dm = M_Randomizer(x);
for(int a = 0; a < x; a++)
dm[a] = dm[a] + start;
return dm;
}
}
Look at using an array to hold your 6 numbers.
Each time you generate one, loop through the array to make sure it is not already there. If it is, then generate another & loop again until you have a non-match.
It's so easy with array and OOP (Object Oriented Programming). Before you start you have to add Linq (using System.Linq) library to your project.
Random random = new Random();
int[] array = new int[6];
int number;
for (int i = 0; i < 6; i++)
{
number = random.Next(1, 50);
if (!array.Contains(number)) //If it's not contains, add number to array;
array[i] = number;
else //If it contains, restart random process
i--;
}
for (int i = 1; i < 7; i++)
{
foreach (Control c in this.Controls) //Add random numbers to all Textboxes
{
if (c is TextBox && c.Name.EndsWith(i.ToString()))
{
c.Text = array[i - 1].ToString();
}
}
}
A functional approach could be to generate an infinite sequence of random numbers, filter out non-unique numbers and take the number of unique numbers you need.
For example:
private IEnumerable<int> RandomDigitStream(int seed)
{
Random random = new Random(seed);
while (true)
{
yield return random.Next(DIGIT_MIN, DIGIT_MAX);
}
}
private List<int> GenerateUniqueRandomNumbers(int seed, int count)
{
// Assert that DIGIT_MAX - DIGIT_MIN > count to ensure
// algorithm can finish
return RandomDigitStream(seed)
.Distinct()
.Take(count)
.ToList();
}
The efficiency of this algorithm is mainly dependent on how Distinct is implemented by the .NET team. Its memory usage would grow with the number of digits you require and the range of digits produced by the random function. It also has an unpredictable running time as it depends on the probability distribution of the random function. In fact it is possible for this algorithm to get stuck in an infinite loop if the range of digits produced by the random algorithm is less than the number of digits you require.
Looking at it practically however, it should be fine for a small amount of digits but if you are looking at a large number (100 +) you might want to look at other methods.
It would be more efficient to craft a random algorithm that only produces unique numbers in the first place if that is even possible without using a lookup table.
Here is a small program using recursion to generate number lines, and also uses recursion to randomize and get unique numbers.
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static Random random;
public static List<int> lottoNumbers = Enumerable.Range(1, 49).ToList();
public static void Main()
{
random = new Random((int)DateTime.Now.Ticks);
var LinesToGenerate = 10;
GenerateNumbers(LinesToGenerate);
}
public static void GenerateNumbers(int LineCount)
{
int[] SelectedNumbers = new int[6];
for (var i = 0; i < 6; i++)
{
var number = GetRandomNumber(lottoNumbers.ToArray());
while (SelectedNumbers.Contains(number))
number = GetRandomNumber(lottoNumbers.ToArray());
SelectedNumbers[i] = number;
}
var numbersOrdered = SelectedNumbers.OrderBy(n => n).Select(n => n.ToString().PadLeft(2, '0'));
Console.WriteLine(string.Join(" ", numbersOrdered));
if (LineCount > 1)
GenerateNumbers(--LineCount);
}
//Recursively and randomly removes numbers from the array until only one is left, and returns it
public static int GetRandomNumber(int[] arr)
{
if (arr.Length > 1)
{
//Remove random number from array
var r = random.Next(0, arr.Length);
var list = arr.ToList();
list.RemoveAt(r);
return GetRandomNumber(list.ToArray());
}
return arr[0];
}
}
Yes. Use array.
Loop how many times you want:
Generate a random number,
Loop through array and compare all with the generated number.
If there's a match then loop again till there's no match.
Then store it.
Done:)
After running my program I noticed that all values of my array are equal to one and after running the debugger I noticed that my for loops that should have populated the array are simply skipped over but I have absolutly no idea as to why. Could someone please tell me what I've done wrong?
The program reaches this line:
for (a = a; a >= 1000; a++) // Adds all prime numbers 1 through 1000 to primeA[];
and then jumps to:
for (int k = 0; k < primeA.Length; k++)
Complete code:
class calcPrime
{
/* #Method: isPrimeSET
* #param: int a, int b
* #return: true / false
* # Builds a list of primes and sorts them into a multi dimensional array.
*/
public int[,] isPrimeSet(int a, int b)
{
int[,] primeNumArray = new int[999, 999]; // Prime Multi Array 1000 slots in each array
int[] primeA = new int[999]; // All prime numbers a 1 to 1000
int[] primeB = new int[999]; // All prime numbers b 1 to 1000
ArrayList dumpArrayA = new ArrayList(); // None prime numbers
ArrayList dumpArrayB = new ArrayList(); // None prime numbers
for (a = a; a >= 1000; a++) // Adds all prime numbers 1 through 1000 to primA[];
{
if (isPrime(a) == true)
{
int i = 0; // Index of primeA
primeA[i] = a; // Add primes to a
i++;
}
else // Stores none prime numbers
{
int m = 0;
dumpArrayA.Add(m);
m++;
}
for (b = b; b >= 1000; b++) // Adds all prime number 1 through 1000 to primeB[];
{
if (isPrime(b) == true)
{
int j = 0; // Index of primeB
primeB[j] = b; // Add primes to b
j++;
}
else
{
int n = 0;
dumpArrayB.Add(n);
n++;
}
}
}
// Merge primesA[] and primesB[];
for (int k = 0; k < primeA.Length; k++)
{
primeNumArray[k, 0] = primeA[k];
primeNumArray[k, 1] = primeB[k];
}
// Print Contents of PrimeNumArray
for (int l = 0; l >= primeNumArray.Length; l++) {
Console.WriteLine(primeNumArray[l, l]);
}
return primeNumArray;
}
Else statements and dump arrays added in vain attempt at making the program work. Also I know I assigned a variable to the same variable in the for loops, I wanted the value to be set wherever the user chooses when the method is called.
There are many mistake there !!
I managed to correct your code
here is your corrected code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Prime_number
{
class Program
{
static void Main(string[] args)
{
int[,] k = isPrimeSet(1, 1);
Console.Read();
}
public static int[,] isPrimeSet(int a, int b)
{
int[,] primeNumArray; // Prime Multi Array 1000 slots in each array
ArrayList primeA = new ArrayList(); // All prime numbers a 1 to 1000
ArrayList primeB = new ArrayList(); // All prime numbers b 1 to 1000
ArrayList dumpArrayA = new ArrayList(); // None prime numbers
ArrayList dumpArrayB = new ArrayList(); // None prime numbers
int i = 0;
int m = 0;
int j = 0; // Index of primeB
int n = 0;
for (a = 1; a <= 1000; a++) // Adds all prime numbers 1 through 1000 to primA[];
{
if (isPrime(a) == true)
{
// Index of primeA
primeA.Add( a); // Add primes to a
i++;
}
else // Stores none prime numbers
{
dumpArrayA.Add(m);
m++;
}
}
for (b = 1; b <= 1000; b++) // Adds all prime number 1 through 1000 to primeB[];
{
if (isPrime(b) == true)
{
primeB.Add(b); // Add primes to b
j++;
}
else
{
dumpArrayB.Add(n);
n++;
}
}
primeNumArray= new int[primeA.Count,2];
// Merge primesA[] and primesB[];
for (int k = 0; k < primeA.Count; k++)
{
primeNumArray[k, 0] = (int)primeA[k];
primeNumArray[k, 1] = (int)primeB[k];
}
// Print Contents of PrimeNumArray
for (int l = 0; l <= primeNumArray.GetLength(0)-1; l++)
{
Console.WriteLine(primeNumArray[l, 0] + " " + primeNumArray[l, 1]);
}
return primeNumArray;
}
static bool isPrime(int num)
{
bool bPrime = true;
int factor = num / 2;
int i = 0;
for (i = 2; i <= factor; i++)
{
if ((num % i) == 0)
bPrime = false;
}
return bPrime;
}
}
}
Give it a try :) ! Thanks
I think index of array seems incorrect,
if (isPrime(a) == true)
{
int i = 0; // Index of primeA
primeA[i] = a; // Add primes to a
i++;
}
Isn't that changing only primeA[0] value? And for primeB array
int j = 0; // Index of primeB
primeB[j] = b; // Add primes to b
j++;
Maybe you should define i and j out of loop.
I want to combine dynamic time warping and svm to use as a classifier. I use Accord .net, but there is something wrong with my code,here is my code:
double[][] inputs = new double[100][];
for(int i = 0; i < linesX.Length; i++)
{
inputs[i] = Array.ConvertAll(linesX[i].Split(','), Double.Parse);
}
int[] outputs = Array.ConvertAll(linesY, s => int.Parse(s));
// Create the Sequential Minimal Optimization learning algorithm
var smo = new MulticlassSupportVectorLearning<DynamicTimeWarping>()
{
// Set the parameters of the kernel
Kernel = new DynamicTimeWarping(alpha: 1, degree: 1)
};
// And use it to learn a machine!
var svm = smo.Learn(inputs, outputs);
// Now we can compute predicted values
int[] predicted = svm.Decide(inputs);
// And check how far we are from the expected values
double error = new ZeroOneLoss(outputs).Loss(predicted);
My inputs are (100,800), outputs are (100,1), there will be an exception at this line:var svm = smo.Learn(inputs, outputs);The exception is “System.AggregateException” happens in Accord.MachineLearning.dllWhat's wrong with my code
Please refer to the correct setup HERE. You're not assigning the Learner property.
Here's your modified code with some random input data:
static void Main(string[] args)
{
Random r = new Random();
double[][] inputs = new double[10][];
int[] outputs = new int[10];
for (int i = 0; i < 10; i++)
{
inputs[i] = new double[8];
for (int j = 0; j < 8; j++)
{
inputs[i][j] = r.Next(1, 100);
}
outputs[i] = r.Next(1, 6);
}
var smo = new MulticlassSupportVectorLearning<DynamicTimeWarping>()
{
Learner = (param) => new SequentialMinimalOptimization<DynamicTimeWarping>()
{
Kernel = new DynamicTimeWarping(alpha: 1, degree: 1),
}
};
var svm = smo.Learn(inputs, outputs);
int[] predicted = svm.Decide(inputs);
double error = new ZeroOneLoss(outputs).Loss(predicted);
Console.WriteLine();
Console.WriteLine("output = \n{0}", Matrix.ToString(outputs));
Console.WriteLine();
Console.WriteLine("predicted = \n{0}", Matrix.ToString(predicted));
Console.WriteLine();
Console.WriteLine("error = {0}", error);
Console.ReadLine();
}
Which will produce something like this:
output =
2 3 1 2 1 2 2 3 5 1
predicted =
2 1 1 2 1 2 2 2 2 1
error = 0.3
I have a multidimensional array, which I want to initialize in a simple and fast way:
double[,,] arr = new double[4,5,6];
// doesn't work by design
foreach(double d in arr)
d = ... ; // my initialization value
This obviously doesn't works. But I would like to have a generic function for setting all array values to a choosen default. With own classes, I could write a special constructor, but with value types I've no real idea. With C++, I could access all items in a linear way with one for loop, but in C# I think I've to use as much for loops as I have dimensions. I've no better solution at the moment ( or I'm using unsafe code and pointer arithmetics, which would probably work.).
Is there a more elegant way for doing this ?
Not quite sure if it's what you want, but the following extension method will allow you to initialise every value in an array, regardless of the number of dimensions.
public static class ArrayExtensions
{
public static void Set<T>(this Array array, T defaultValue)
{
int[] indicies = new int[array.Rank];
SetDimension<T>(array, indicies, 0, defaultValue);
}
private static void SetDimension<T>(Array array, int[] indicies, int dimension, T defaultValue)
{
for (int i = 0; i <= array.GetUpperBound(dimension); i++)
{
indicies[dimension] = i;
if (dimension < array.Rank - 1)
SetDimension<T>(array, indicies, dimension + 1, defaultValue);
else
array.SetValue(defaultValue, indicies);
}
}
}
Use like so:
int[, ,] test1 = new int[3, 4, 5];
test1.Set(1);
int[,] test2 = new int[3, 4];
test2.Set(1);
int[] test3 = new int[3];
test3.Set(1);
I would strongly recommend using a 1D array, and map the values sequentially. You will need to convert from indeces i, j, k, ... into the proper array index, which is done with the Que() function below, part of a generic array class SeqArray<T>.
// Test code first
class Program
{
static void Main(string[] args)
{
/* 3 pages, of a 4x2 matrix
*
* |16 17|
* | 8 9|19|
* | 0 1|11|21|
* | 2 3|13|23|
* | 4 5|15|
* | 6 7|
*
* shown above are the sequential indeces for a rank 3 array
*/
SeqArray<double> arr = new SeqArray<double>(3, 4, 2);
// Initialize values to squential index "num"
int num = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 2; k++)
{
arr[i, j, k] = num++;
}
}
}
// Check that the array values correspond to the index sequence
num = 0;
for (int i = 0; i < 3 * 4 * 2; i++)
{
Trace.Assert(arr.InnerArray[i] == num++);
}
// Initialize with value=π
arr = new SeqArray<double>(Math.PI, 4, 5, 6);
}
}
public class SeqArray<T>
{
T[] values;
int[] lengths;
public SeqArray(params int[] lengths)
{
this.lengths = lengths;
int N = 1;
for (int i = 0; i < lengths.Length; i++)
{
N *= lengths[i];
}
values = new T[N];
}
public SeqArray(T value, params int[] lengths) : this(lengths)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = value;
}
}
public int[] Lengths { get { return lengths; } }
public int Size { get { return values.Length; } }
internal T[] InnerArray { get { return values; } }
public int Que(params int[] indeces)
{
// Check if indeces are omited like arr[4] instead of arr[4,0,0]
if (indeces.Length < lengths.Length)
{
// Make a new index array padded with zeros
int[] temp = new int[lengths.Length];
indeces.CopyTo(temp, 0);
indeces = temp;
}
// Count the elements for indeces
int k = 0;
for (int i = 0; i < indeces.Length; i++)
{
k = lengths[i] * k + indeces[i];
}
return k;
}
public T this[params int[] indeces]
{
get { return values[Que(indeces)]; }
set { values[Que(indeces)] = value; }
}
}
Here is a non-recursive version alternative to that posted by Andy Holt above:
public static void SetAll<T>(this Array array, T value)
{
var sizes = new int[array.Rank];
sizes[array.Rank - 1] = 1;
for (var d = array.Rank - 2; d >= 0; d--)
{
sizes[d] = array.GetLength(d + 1)*sizes[d + 1];
}
for (var i = 0; i < array.Length; i++)
{
var remainder = i;
var index = new int[array.Rank];
for (var d = 0; d < array.Rank && remainder > 0; d++)
{
index[d] = remainder / sizes[d];
remainder -= index[d]*sizes[d];
}
array.SetValue(value, index);
}
}