optimization of an equation parameters using genetic sharp genetic algorithm - c#

i have some data for example:
x=1, 2, 3, 4, 5
y=5, 4, 3, 2, 1
z=1, 2, 1, 1, 3
t=9, 12, 9, 9, 15.
i know that t=ax+by+c*z. here i know a=1,b=1 and c=3 and i need to find them by genetic algorithm by Genetic Sharp. i wrote the below code but i get the boundary values all times of -100,-100,-100.
can you help me on it?
NOTE that i need the GA to search on a large boundary for example here i selected -100 to 100 for each of a,b and c. in real case i need to bound it to -100000 to 10000 for example. also i need the at least 10 fraction digits also.
double[] x = new double[] { 1, 2, 3, 4, 5 };
double[] y = new double[] { 5, 4, 3, 2, 1 };
double[] z = new double[] { 1, 2, 1, 1, 3 };
double[] t = new double[] { 9, 12, 9, 9, 15 };
var selection = new EliteSelection();
var crossover = new UniformCrossover();
var mutation = new FlipBitMutation();
var fitness = new FuncFitness((c) =>
{
var vals = (c as FloatingPointChromosome).ToFloatingPoints();
double err = 0;
for (int i = 0; i < x.Count(); i++)
{
err += Math.Pow((t[i] - (vals[0] * x[i] + vals[1] * y[i] + vals[2] * z[i])), 2);
}
return err;
});
var chromosome = new FloatingPointChromosome(
new double[] { -100, -100, -100 },
new double[] { 100, 100, 100 },
new int[] { 64, 64, 64 },
new int[] { 10, 10, 10 });
var population = new Population(100, 100, chromosome);
var ga = new GeneticAlgorithm(population, fitness, selection, crossover, mutation);
ga.Termination = new GenerationNumberTermination(300);
Console.WriteLine("GA running...");
ga.Start();

I think that is because the algorith wants to maximize the Fitness Function and in the way that you wrote it, the algo will find the worst possible values for your variables.
I changed the error calculation in the Fitness Function to
err -= Math.Pow((t[i] - (vals[0] * x[i] + vals[1] * y[i] + vals[2] * z[i])), 2);
so now the maximum possible value for err is zero and the algorith will try to find the variable values for it.
Got very close results running this code, although couldn't get the exact ones.

In this problem, by changing the fitness function and mutation the correct answer could be achieved using GeneticSharp. the modified code is as follows:
// x = 1, 2, 3, 4, 5
// y = 5, 4, 3, 2, 1
// z = 1, 2, 1, 1, 3
// t = 9, 12, 9, 9, 15.
// t = a*x + b*y + c*z
// a,b,c =???
double[] x = new double[] { 1, 2, 3, 4, 5 };
double[] y = new double[] { 5, 4, 3, 2, 1 };
double[] z = new double[] { 1, 2, 1, 1, 3 };
double[] t = new double[] { 9, 12, 9, 9, 15 };
var chromosome = new FloatingPointChromosome(
new double[] { -10, -10, -10 },
new double[] { 10.0, 10.0, 10.0 },
new int[] { 64, 64, 64 },
new int[] { 0, 0, 0 });
var fitness = new FuncFitness((c) =>
{
var fc = c as FloatingPointChromosome;
double err = 0;
var values = fc.ToFloatingPoints();
var pa = values[0];
var pb = values[1];
var pc = values[2];
var fitness_e = 0.0;
for (int i = 0; i < x.Count(); i++)
{
try
{
var expected_result = t[i];
var equations = (pa * x[i] + pb * y[i] + pc * z[i]);
var diff = Math.Abs(equations - expected_result);
fitness_e += diff;
}
catch (Exception)
{
return double.MinValue;
}
}
return fitness_e * -1;
});
var population = new Population(100, 500, chromosome);
var selection = new EliteSelection();
var crossover = new ThreeParentCrossover();
var mutation = new UniformMutation(true);
var ga = new GeneticAlgorithm(population, fitness, selection, crossover, mutation);
ga.Termination = new OrTermination(
new GenerationNumberTermination(5000),
new FitnessStagnationTermination(2000));
ga.CrossoverProbability = 0.1f;
ga.MutationProbability = 0.4f;
ga.Reinsertion = new ElitistReinsertion();
Console.WriteLine("GA running...");
var latestFitness = 0.0;
ga.GenerationRan += (sender1, e1) =>
{
var bestChromosome = ga.BestChromosome as FloatingPointChromosome;
var bestFitness = bestChromosome.Fitness.Value;
if (bestFitness != latestFitness)
{
latestFitness = bestFitness;
var phenotype = bestChromosome.ToFloatingPoints();
Console.WriteLine(
"Generation {0}: {1},{2},{3} fitness: {4}",
ga.GenerationsNumber,
phenotype[0],
phenotype[1],
phenotype[2],
bestFitness
);
}
};
ga.Start();
Console.WriteLine("GA End");

Related

How do I remove each N item in List until List.Count more than target value?

There is a list of short. The values of it doesn't matter like:
List<short> resultTemp = new List<short>{1,2,3,4,5,6,7,8,9...};
This code should reduse the result list count by removing each Nth item from it.
Example 1:
List<short>{1,2,3,4,5,6,7,8,9,10}.Count == 10;
var targetItemsCount = 5;
result should be {1,3,5,7,9} and result.Count should be == 5
Example 2:
List<short>{1,2,3,4,5,6,7,8,9}.Count == 9;
var targetItemsCo:nt = 3;
result should be {1,4,7} and result.Count should be == 3
But it should stop to remove it, somewhere for make result count equal targetItemsCount (42 in this code, but its value else doesn't matter).
The code is:
var currentItemsCount = resultTemp.Count;
var result = new List<short>();
var targetItemsCount = 42;
var counter = 0;
var counterResettable = 0;
if (targetItemsCount < currentItemsCount)
{
var reduceIndex = (double)currentItemsCount / targetItemsCount;
foreach (var item in resultTemp)
{
if (counterResettable < reduceIndex ||
result.Count + 1 == currentItemsCount - counter)
{
result.Add(item);
counterResettable++;
}
else
{
counterResettable = 0;
}
counter++;
}
}
And the resault.Count in this example equals 41, but should be == targetItemsCount == 42;
Ho do I remove each N item in List untill List.Count more then target value with C#?
If my understanding is correct:
public static void run()
{
var inputs =
new List<Input>{
new Input{
Value = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },`
TargetCount = 5, ExpectedOutput= new List<int>{1,3,5,7,9}
},
new Input{
Value = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
TargetCount = 3, ExpectedOutput= new List<int>{1,4,7}
},
};
foreach (var testInput in inputs)
{
Console.WriteLine($"# Input = [{string.Join(", ", testInput.Value)}]");
var result = Reduce(testInput.Value, testInput.TargetCount);
Console.WriteLine($"# Computed Result = [{string.Join(", ", result)} ]\n");
}
}
static List<int> Reduce(List<int> input, int targetItemsCount)
{
while (input.Count() > targetItemsCount)
{
var nIndex = input.Count() / targetItemsCount;
input = input.Where((x, i) => i % nIndex == 0).ToList();
}
return input;
}
class Input
{
public List<int> ExpectedOutput;
public List<int> Value;
public int TargetCount;
}
Result :
Input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Computed Result = [1, 3, 5, 7, 9 ]
Input = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Computed Result = [1, 4, 7 ]
To guarantee you get the expected number of selected items:
double increment = Convert.ToDouble(resultTemp.Count) / targetItemsCount;
List<short> result = Enumerable.Range(0, targetItemsCount).
Select(x => resultTemp[(int)(x * increment)]).
ToList();
Note that in the following case
List<short>{1,2,3,4,5,6,7,8,9}.Count == 9;
var targetItemsCount = 6;
The result will be [1, 2, 4, 5, 7, 8], i.e. rounding the index down when needed
Also, you'll need to add validation (targetItemsCount > 0, targetItemsCount < resultTemp.Count...)
Link to Fiddle
Give this a try:
var resultTemp = Enumerable.Range(1, 9).ToList();
var targetItemsCount = 3;
var roundingError = resultTemp.Count % targetItemsCount;
var reduceIndex = (resultTemp.Count - roundingError) / targetItemsCount;
List<int> result;
if (reduceIndex <= 1)
result = resultTemp.Take(targetItemsCount).ToList();
else
result = resultTemp.Where((a, index) => index % reduceIndex == 0).Take(targetItemsCount).ToList();
Tried it with your given example, also gave 42 a spin with a list of 1 to 100 it will remove every 2nd item till it reaches 42, so the last entry in the list would be 83.
As I said, give it a try and let me know if it fits your requirement.

C# parallelize loop

I have the following c# code:
int[] ns = new int[4] { 100, 500, 1000, 5000 };
int[] ks = new int[5] { 5, 10, 15, 80, 160 };
int[] rs = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for(int n = 0; n<ns.Length; n++)
{
for(int k = 0; k < ks.Length; k++)
{
for (int r = 0; r < rs.Length; r++)
{
RunProg(ns[n], ks[k], rs[r]);
}
}
}
where RunProg takes a relatively substantial amount of time. I would like to parallelize this code. What is the most straight forward way to parallelize this in C#?
I have not tried any method yet. I was trying to decide between the different functionalities available in C#
A simple way to parallelize this is to produce a sequence representing all combinations of inputs, then transforming this sequence to a sequence of thread pool tasks representing the result. This final sequence can simply be passed to Task.WhenAll to await the completion of all tasks.
class Program
{
static void Main(string[] args)
{
int[] ns = new int[4] { 100, 500, 1000, 5000 };
int[] ks = new int[5] { 5, 10, 15, 80, 160 };
int[] rs = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var inputs = ns
.SelectMany(n => ks.Select(k => new { n, k }))
.SelectMany(x => rs.Select(r => new { x.n, x.k, r }));
var tasks = inputs.Select(x => Task.Run(() => RunProg(x.n, x.k, x.r)));
var results = Task.WhenAll(tasks).Result;
}
static int RunProg(int n, int k, int r)
{
Thread.Sleep(1000);
return n + k + r;
}
}
You can also Parallel.ForEach over the inputs collection, as mentioned in the other answers.
Parallel.ForEach(inputs, x => RunProg(x.n, x.k, x.r));
There is a Parallel.For method:
int[] ns = new int[4] { 100, 500, 1000, 5000 };
int[] ks = new int[5] { 5, 10, 15, 80, 160 };
int[] rs = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Parallel.For(0, ns.Length, n =>
{
Parallel.For(0, ks.Length, k =>
{
Parallel.For(0, rs.Length, r =>
{
RunProg(ns[n], ks[k], rs[r]);
});
});
});
This should work provided that the order in which the RunProg method is called is not important, and that the method itself is thread-safe.
Use Parallel.For() for the loops: https://msdn.microsoft.com/de-de/library/dd460713(v=vs.110).aspx
This works if the iterations are not dependent on each other.

LINQ to get two integers in an array whose sum is closest to zero

Given an array of integers (with +ve and -ve numbers which are unordered),
what is the LINQ statement to find those two numbers whose sum is closest to 0
E.g int[] a = new int[]{2, 56, -11, 15, 12, 10, 43, -59, -13}
In the above set of integers {-11,10} and {12,-13} are the two set of two integers which is closest to 0
I could not get much, except the following basic query of LINQ as i was not sure how to proceed,
var res = from x in a
WHERE //i am stuck in the logic what to write here
select x
If it can be any two values in the set then you can do this...
var set = new int[] { 2, 56, -11, 15, 12, 10, 43, -59, -13 };
var ret = (from a in set
from b in set
orderby Math.Abs(a + b)
select new
{
a,
b
}).First();
Console.WriteLine(ret); // {a: -11, b:12 }
If you want slightly better performance for large sets (and can assume there are negative and positive values mixed) you can do this.
var set = new int[] { 2, 56, -11, 15, 12, 10, 43, -59, -13 };
var ret = (from a in set.Where(x => x >= 0)
from b in set.Where(y => y < 0)
orderby Math.Abs(a + b)
select new
{
a,
b
}).First();
Console.WriteLine(ret); // { a= 12, b= -11}
And since you now want the entire set of matches excluding matching to one's self...
var set = new int[] { 2, 56, -11, 15, 12, 10, 43, -59, -13 };
var ret = from a in set
from b in set
where a != b
let c = new { a, b }
group c by Math.Abs(c.a + c.b);
var minset = ret.First(i => i.Key == ret.Min(j => j.Key))
.Select(s=>s);
Console.WriteLine(minset.Aggregate(new StringBuilder(),
(sb,v)=>sb.Append(v)
.AppendLine()
));
/*
{ a = -11, b = 12 }
{ a = -11, b = 10 }
{ a = 12, b = -11 }
{ a = 12, b = -13 }
{ a = 10, b = -11 }
{ a = -13, b = 12 }
*/
And to dedup....
var set = new[] { 2, 56, -11, 15, 12, 10, 43, -59, -13 };
var ret = from a in set
from b in set
where a != b
let c = new { a, b }
group c by Math.Abs(c.a + c.b);
var minset = ret.First(i => i.Key == ret.Min(j => j.Key))
.Select(s => new { a = Math.Min(s.a, s.b), b = Math.Max(s.a, s.b) })
.Distinct();
Console.WriteLine(minset.Aggregate(new StringBuilder(),
(sb, v) => sb.Append(v)
.AppendLine()));
/*
{ a = -11, b = 12 }
{ a = -11, b = 10 }
{ a = -13, b = 12 }
*/
var data = new [] { 2, 56, -11, 15, 12, 10, 43, -59, -13 };
// TODO : assert data.Length >= 2
var query = from i in Enumerable.Range (0, data.Length - 2)
from j in Enumerable.Range (i + 1, data.Length - 1 - i)
let x = data[i] let y = data[j]
group new { x, y } by Math.Abs (x + y) into g
orderby g.Key select g;
Console.WriteLine (string.Join ("\n", query.First ()));
{ x = -11, y = 12 }
{ x = -11, y = 10 }
{ x = 12, y = -13 }

Randomly pick from a list of numbers until specific limit

Let's say I have a list of predefined numbers, and a list of predefined max limits.
When a user picks a limit, I need to randomly pick a certain amount of numbers from the first list, up until their totals match (As close to, but never over) the user selected total.
What I've tried so far:
void Main()
{
List<int> num = new List<int>(){ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19, 20 };
int maxNum = 17;
List<int> curNum = new List<int>();
int curTotal = 0;
foreach(int sel in num.Where(x => x < maxNum)){
curTotal += sel;
if(curTotal <= maxNum){
curNum.Add(sel);
}
}
}
There needs to be x amount of numbers picked. In this case, 5 numbers picked, +- 20 numbers to be randomly picked from, and 1 max values.
So the end list should look like this:
1, 2, 3, 4, 7 (17)
1, 2, 3, 5, 6 (17)
1, 2, 3, 4, 6 (16) <- This will be fine if there isn't a solution to the max value.
Building upon #AlexiLevenkov's answer:
class Program
{
static void Main(string[] args)
{
int limit = 17;
int listSize = 5;
List<int> a = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
a.Shuffle();
List<int> genList = new List<int>();
int stoppedCount = 0;
for (int i = 0; i < a.Count(); i++)
{
if (i < listSize)
{
genList.Add(a[i]);
stoppedCount = i;
}
else
{
break;
}
}
while (genList.Sum() > limit)
{
genList.Remove(genList.Max());
stoppedCount++;
genList.Add(a[stoppedCount]);
}
}
}
static class ThisClass
{
public static void Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
I think shuffle + "take while sum < limit" may be what you are looking for.
Something like following:
var shuffledList = num.ToList();
shuffledList.Shuffle();
var sum = 0;
var count = 0;
while (shuffledList[count] + sum < max)
{
sum += shuffledList[count++];
}
return shuffledList.Take(count);

How to fill a three dimensional array

I want to fill a three dimensional array with the following arrays:
double[] y11 = new double[7] { 24, 13.3, 12.2, 14, 22.2, 16.1, 27.9 };
double[] y12 = new double[7] { 3.5, 3.5, 4, 4, 3.6, 4.3, 5.2 };
double[] y21 = new double[7] { 7.4, 13.2, 8.5, 10.1, 9.3, 8.5, 4.3 };
double[] y22 = new double[7] { 3.5, 3, 3, 3, 2, 2.5, 1.5 };
double[] y31 = new double[5] { 16.4, 24, 53, 32.7, 42.8 };
double[] y32 = new double[5] { 3.2, 2.5, 1.5, 2.6, 2 };
double[] y41 = new double[2] { 25.1, 5.9 };
double[] y42 = new double[2] { 2.7, 2.3 };
for instance y12 means the array in group 1 , column number 2 and so on. so i have 4 groups ,each group has 2 columns.
public class Matrix
{
double[, ,] matrix;
public void Initial(int groupSize, int columnSize, int valueSize)
{
matrix = new double[groupSize, columnSize, valueSize];
}
}
I need a simple flexible Add method for the matrix, rather than assigning each value like matrix[1][2][3] = value;
I've tried this, but couldn't get it work
public void Add(double[] columnArray, int groupIndex, int columnIndex)
{
matrix[i, y] = columnArray;
}
According to #Henk Holterman 's Comment (thank you), I've managed to solve the problem
public class Matrix
{
double[,][] matrix;
public Matrix(int groupSize, int columnSize)
{
matrix = new double[groupSize, columnSize][];
}
public void Add(double[] arr, int groupIndex, int columnIndex)
{
matrix[groupIndex, columnIndex] = arr;
}
public void Print()
{
int columnIndex = 0;
int groupIndex = 0;
int groupSize = matrix.GetLength(0);
int columnSize = matrix.GetLength(1);
while (groupIndex < groupSize)
{
for (int k = 0; k < matrix[groupIndex, columnIndex].Length; k++)
{
Console.Write(groupIndex + 1);
while (columnIndex < columnSize)
{
Console.Write(" {0}", matrix[groupIndex, columnIndex][k]);
columnIndex++;
}
Console.WriteLine();
columnIndex = 0;
}
groupIndex++;
}
}
}
Main Class
static Matrix m;
static void SetDataSet()
{
double[] y11 = new double[7] { 24, 13.3, 12.2, 14, 22.2, 16.1, 27.9 };
double[] y12 = new double[7] { 3.5, 3.5, 4, 4, 3.6, 4.3, 5.2 };
double[] y21 = new double[7] { 7.4, 13.2, 8.5, 10.1, 9.3, 8.5, 4.3 };
double[] y22 = new double[7] { 3.5, 3, 3, 3, 2, 2.5, 1.5 };
double[] y31 = new double[5] { 16.4, 24, 53, 32.7, 42.8 };
double[] y32 = new double[5] { 3.2, 2.5, 1.5, 2.6, 2 };
double[] y41 = new double[2] { 25.1, 5.9 };
double[] y42 = new double[2] { 2.7, 2.3 };
m.Add(y11, 0, 0);
m.Add(y12, 0, 1);
m.Add(y21, 1, 0);
m.Add(y22, 1, 1);
m.Add(y31, 2, 0);
m.Add(y32, 2, 1);
m.Add(y41, 3, 0);
m.Add(y42, 3, 1);
}
static void Main(string[] args)
{
m = new Matrix(4,2);
SetDataSet();
m.Print();
Console.ReadLine();
}
}

Categories

Resources