Accord.Net Multiclass SVM DynamicTimeWarping Exception - c#

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

Related

How to solve application responsivness issue in C#

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.

How does ACCORDs Deep neural learning work?

I get an error when I try to run DeepNeuralLearning from ACCORDs toolbox. It works when I run it as:
var inputs = new double[3][];
inputs[0] = new double[] {1, 2, 3};
inputs[1] = new double[] {1, 2, 3};
inputs[2] = new double[] {1, 2, 3};
var classes = new[] {0, 1, 2};
var outputs = Tools.Expand(classes, -1, 1);
var network = new DeepBeliefNetwork(3, 4, 3, 2);
var teacher = new DeepNeuralNetworkLearning(network)
{
Algorithm = (ann, i) => new ParallelResilientBackpropagationLearning(ann),
LayerIndex = network.Layers.Length - 1
};
var error = teacher.RunEpoch(inputs, outputs);
However, when I tweak the code to accept a 21 x 30,000 matrix for inputs and a 5 x 30000 matrix for outputs, it gives me an index was out of bounds exception. This is very strange as alll I did was change the matrix size. I tried changing the numbers for hidden layers but to no resolve. Anyone have any ideas what I am doing wrong?
double[][] inputs;
int[] classes;
var outputsList = Outputs(out inputs, out classes);
GetPerformanceOfStock(outputsList, inputs, classes);
//reclassify as 0 -4
for (var i = 0; i < classes.Length; i++)
{
classes[i] = classes[i] - 1;
}
//mean subtract
for (var i = 0; i < inputs.Length; i++)
{
var avg = inputs[i].Average();
for (var j = 0; j < inputs[i].Length; j++)
{
inputs[i][j] = inputs[i][j] - avg;
}
}
var outputs = Tools.Expand(classes, -1, 1);
//SPLIT INTO TEST AND TRAINIG DATA
var trainingIndex = (int) Math.Floor(.1*inputs.Length);
var fullsize = inputs.Length;
var trainingInputs = new double[trainingIndex][];
var trainingOutputs = new double[trainingIndex][];
for (var i = 0; i < trainingIndex; i++)
{
trainingInputs[i] = inputs[i];
trainingOutputs[i] = outputs[i];
}
var testingInputs = new double[fullsize - trainingIndex][];
var testingOutputs = new double[fullsize - trainingIndex][];
var counter = 0;
for (var i = fullsize - 1; i >= trainingIndex; i--)
{
testingInputs[counter] = inputs[i];
testingOutputs[counter] = outputs[i];
counter++;
}
//Inmitialize network
var network = new DeepBeliefNetwork(inputs.Length, 400, 3, 2);
//var network = new DeepBeliefNetwork(new BernoulliFunction(), trainingInputs.Length, 50, 25, 10);
var teacher = new DeepNeuralNetworkLearning(network)
{
Algorithm = (ann, i) => new ParallelResilientBackpropagationLearning(ann),
LayerIndex = network.Layers.Length - 1
};
teacher.RunEpoch(inputs, outputs);

C# console application that can find every combination of some numbers but only writes if they can divide by 3

I have to perform a task. pls help me. İ want a c sharp console application that can find every combination of some numbers but only writes if they can divide by 3.
We have 15 card in a bag. we will take 3 cards randomly(without replacement) . After that we will add them(card1+card2+card3) and if their result can divide by 3 then we will write them to console.[(card1+card2+card3)/3]=0
Not sure where to begin with this. Any help is greatly appreciated!
You can get some idea from this I think.
public List<int[]> getCombinations(int[] inArray)
{
List<int[]> outList = new List<int[]>();
for (int i = 0; i < inArray.Length; i++)
for (int j = i + 1; j < inArray.Length; j++)
for (int k = j + 1; k < inArray.Length; k++)
{
int[] outCombination = new int[] { inArray[i], inArray[j], inArray[k] };
outList.Add(outCombination);
}
return outList;
}
static void Main(string[] args)
{
int[] inArray = new int[] { 0, 1, 2, 3, 4, 5 };
// Returned list of combinations...
Program ns = new Program();
List<int[]> Combinations = ns.getCombinations(inArray);
// example: Displaying the results...
foreach (int[] outArray in Combinations)
{
Console.Write(outArray[0] + "," + outArray[1] + "," + outArray[2]);
}
}
Given 3 numbers, you can tell if they are divisible by 3 using the modulus operator:
List<int> numbers = new List<int> {4, 8, 11}; // Represents three random cards
// This will be set to true if the sum of the numbers is evenly divisible by 3
bool numbersAreDivisibleByThree = numbers.Sum() % 3 == 0;
Here is an example of how this could be used:
private static void Main()
{
var cardBag = new List<int>();
var drawnCards = new List<int>();
// Add 15 numbers to the cardBag
for (int i = 1; i <= 15; i++)
{
cardBag.Add(i);
}
// Draw 3 cards at random
var rnd = new Random();
while (drawnCards.Count < 3)
{
var candidateCard = cardBag[rnd.Next(15)];
// In this implementation, we only add unique cards
if (!drawnCards.Contains(candidateCard))
drawnCards.Add(candidateCard);
}
// This will be set to true if the sum of the numbers is evenly divisible by 3
bool numbersAreDivisibleByThree = drawnCards.Sum() % 3 == 0;
// Output results to console
Console.WriteLine("The three random cards drawn from the deck are: {0}",
string.Join(", ", drawnCards));
Console.WriteLine("The sum of the cards is: {0}", drawnCards.Sum());
Console.WriteLine("Is the sum of the cards evenly divisible by three? {0}.",
numbersAreDivisibleByThree);
}
Since you seem like a noob, here is an easy way of looking at it (although not the most efficient and least costly):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RandomGeneratorPractice
{
class Program
{
static void Main(string[] args)
{
Random random = new Random();
int randomNumber1 = random.Next(1, 15);
int randomNumber2 = random.Next(1, 15);
int randomNumber3 = random.Next(1, 15);
bool bln = true;
while(bln)
{
if (randomNumber1 == randomNumber2)
{
randomNumber2 = random.Next(1, 15);
bln = true;
}
else if (randomNumber2 == randomNumber3 || randomNumber1==randomNumber3)
{
randomNumber3 = random.Next(1,15);
bln = true;
}
else if ((randomNumber1 != randomNumber2) && (randomNumber1 != randomNumber3) && (randomNumber2 != randomNumber3))
{
bln = false;
}
}
int dividend = randomNumber1 + randomNumber2 + randomNumber3;
double divisor = 3;
double quotient = (randomNumber1 + randomNumber2 + randomNumber3) / 3;
Console.WriteLine("(" + randomNumber1 + "+" + randomNumber2 + "+" + randomNumber3 + ") / 3 = " + (dividend / divisor));
if (dividend % divisor == 0)
{
Console.WriteLine("You CAN divide by 3 evenly");
}
else
{
Console.WriteLine("You CANNOT divide by 3 evenly");
}
Console.WriteLine("Press ENTER to exit...");
Console.Read();
}
}
}

Encog 3.3 library for c#: I get a 0.79 error on my network but does not improve

Im new at programming, and I am trying to learn Encog 3.3 Library. I worked on making my first network. I was able to write and understand the Code; However, My error rate does not go below 0.79, I used TANH activation function. My network is suppose to return 1 of three values -1,0,1 based on a set of variables I input it. Has anyone Have this same Problem?
this is the Code:
static void Main(string[] args)
{
// creating the neural net : network
var network = new BasicNetwork();
network.AddLayer(new BasicLayer(null, true,21));
network.AddLayer(new BasicLayer( new ActivationTANH(), true,15));
network.AddLayer(new BasicLayer(new ActivationTANH(), true, 15));
network.AddLayer(new BasicLayer(new ActivationTANH(), true,1));
network.Structure.FinalizeStructure();
network.Reset();
// creating the training Data
string Path = "";
var listArray = GetFile(Path);
int amountNumbersY = GetYSize(listArray);
int amountNumbers = GetXSize(listArray[1]);
string[,] matrixString = new string[listArray.Length, amountNumbers]; matrixString = splitter(listArray, amountNumbers);
double[][] allData = new double[amountNumbers][];
for (int i = 0; i < allData.Length; i++)
allData[i] = new double[amountNumbersY];
allData = ConvertToDouble(matrixString, amountNumbers);
// creating the inpuit and output
double[][] XOR_INPUT = new double[amountNumbersY][];
for (int i = 0; i < amountNumbersY; i++)
{
XOR_INPUT[i] = new double[amountNumbers - 1];
}
double[][] XOR_IDEAL = new double[amountNumbersY][];
for (int i = 0; i < amountNumbersY; i++)
{
XOR_IDEAL[i] = new double[1];
}
XOR_INPUT = GetInput(allData, amountNumbers, amountNumbersY, 1);
XOR_IDEAL = GetIdealOutPut(allData, amountNumbers, amountNumbersY, 1);
// normalizing the Arrays
double[][] temp_Input = new double[amountNumbersY-1][];
for (int i = 0; i < amountNumbersY-1; i++) // initializing the x axis
{
temp_Input[i] = new double[amountNumbers - 1];
}
double[][] temp_Ideal = new double[amountNumbersY-1][]; // same as above for output matrix
for (int i = 0; i < amountNumbersY-1; i++)
{
temp_Ideal[i] = new double[1];
}
double[][] closedLoop_temp_Input = new double[amountNumbersY-1][];
for (int i = 0; i < amountNumbersY-1; i++) // initializing the x axis
{
closedLoop_temp_Input[i] = new double[amountNumbers - 1];
}
double[][] closedLoop_temp_Ideal = new double[amountNumbersY-1][];
for (int i = 0; i < amountNumbersY-1; i++)
{
closedLoop_temp_Ideal[i] = new double[1];
}
var hi = 1;
var lo = -1;
var norm = new NormalizeArray { NormalizedHigh = hi, NormalizedLow = lo };
for (int i = 0; i < amountNumbersY-1; i++)
{
temp_Input[i] = norm.Process( XOR_INPUT[i]);
}
closedLoop_temp_Input = EngineArray.ArrayCopy(temp_Input);
var Ideal_Stats = new NormalizedField(NormalizationAction.Normalize,"Temp_Ideal",1,-1,-1,1);
for (int i = 0; i < amountNumbersY - 1; i++)
{
temp_Ideal[i][0] = Ideal_Stats.Normalize(XOR_IDEAL[i][0]);
}
closedLoop_temp_Ideal = EngineArray.ArrayCopy(temp_Ideal);
IMLDataSet trainingSet = new BasicMLDataSet(closedLoop_temp_Input, closedLoop_temp_Ideal);
// training the network
IMLTrain train = new ResilientPropagation( network, trainingSet);
ICalculateScore score = new TrainingSetScore(trainingSet);
IMLTrain annealing = new NeuralSimulatedAnnealing(network,score,10,2,10);
int epoch = 1;
do
{
if (epoch == 50)
{
int i = 0;
do
{
annealing.Iteration();
Console.WriteLine("Annealing: " + i +", Error: " + annealing.Error);
i++;
} while (i < 5);
}
train.Iteration();
Console.WriteLine(#" Epoch: "+epoch+ #", Error: "+train.Error+"...");
epoch ++;
} while ( train.Error<0.01 || epoch < 1000);
// testing the network
}
}
}
The training rate not falling is one of the most common problems in machine learning. Often it is because the data given to the model simply does not support a prediction. You are training a neural network to predict an output given the input. Consider if you were to train on the following inputs and expected outputs. The data might be noisy or it might be contradictory.
A few suggestions. First, dump your training data to a file and have a look at it. Is it what you expect? Are all of the values between -1 and 1. You have quite a bit of code happening before the training. There could be something going wrong there.
You also have a somewhat hybrid training approach going on, with RPROP and annealing. Perhaps just stick to RPROP and see what happens.

How can I emulate Microsoft Excel's Solver functionality (GRG Nonlinear) in C#?

I have a non-linear optimization problem with constraints. It can be solved in Microsoft Excel with the Solver add-in, but I am having trouble replicating that in C#.
My problem is shown in the following spreadsheet. I am solving the classic A x = b problem but with the caveat that all components of x must be non-negative. So instead of using standard linear algebra I use Solver with the non-negative constraint, minimizing the sum of the squared differences, and get a reasonable solution. I have tried to replicate this in C# using either Microsoft Solver Foundation or Solver SDK. However I can't seem to get anywhere with them because with MSF I can't figure out how to define the goal and with Solver SDK I always get back status "optimal" and a solution of all 0s which is definitely not even a local minimum.
Here is my code for Solver SDK:
static double[][] A = new double[][] { new double[] { 1, 0, 0, 0, 0 }, new double[] { 0.760652602, 1, 0, 0, 0 }, new double[] { 0.373419404, 0.760537565, 1, 0, 0 }, new double[] { 0.136996731, 0.373331934, 0.760422587, 1, 0 }, new double[] { 0.040625222, 0.136953801, 0.373244464, 0.76030755, 1 } };
static double[][] b = new double[][] { new double[] { 2017159 }, new double[] { 1609660 }, new double[] { 837732.8125 }, new double[] { 330977.3125 }, new double[] { 87528.38281 } };
static void Main(string[] args)
{
using(Problem problem = new Problem(Solver_Type.Minimize, 5, 0))
{
problem.VarDecision.LowerBound.Array = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0 };
problem.VarDecision.UpperBound.Array = new double[] { Constants.PINF, Constants.PINF, Constants.PINF, Constants.PINF, Constants.PINF };
problem.Evaluators[Eval_Type.Function].OnEvaluate += new EvaluateEventHandler(SumOfSquaredErrors);
problem.ProblemType = Problem_Type.OptNLP;
problem.Solver.Optimize();
Optimize_Status status = problem.Solver.OptimizeStatus;
Console.WriteLine(status.ToString());
foreach(double x in problem.VarDecision.FinalValue.Array)
{
Console.WriteLine(x);
}
}
}
static Engine_Action SumOfSquaredErrors(Evaluator evaluator)
{
double[][] x = new double[evaluator.Problem.Variables[0].Value.Array.Length][];
for(int i = 0; i < x.Length; i++)
{
x[i] = new double[1] { evaluator.Problem.Variables[0].Value.Array[i] };
}
double[][] b_calculated = MatrixMultiply(A, x);
double sum_sq = 0.0;
for(int i = 0; i < b_calculated.Length; i++)
{
sum_sq += Math.Pow(b_calculated[i][0] - b[i][0], 2);
}
evaluator.Problem.FcnObjective.Value[0] = sum_sq;
return Engine_Action.Continue;
}
static double[][] MatrixMultiply(double[][] left, double[][] right)
{
if(left[0].Length != right.Length)
{
throw new ArgumentException();
}
double[][] sum = new double[left.Length][];
for(int i = sum.GetLowerBound(0); i <= sum.GetUpperBound(0); i++)
{
sum[i] = new double[right[i].Length];
}
for(int i = 0; i < sum.Length; i++)
{
for(int j = 0; j < sum[0].Length; j++)
{
for(int k = 0; k < right.Length; k++)
{
sum[i][j] += left[i][k] * right[k][j];
}
}
}
return sum;
}
I don't have any code for Microsoft Solver Foundation because I don't think the goal function can be written in a single line and it doesn't allow for delegates like Solver SDK does.
One alternative would be to formulate this as an LP problem:
minimize sum of the elements in x
subject to Ax >= b
This should be fairly simple to formulate using Solver Foundation, based on one of the LP samples.
UPDATE JULY 5
The above approach also looks overly complex, but maybe this is due to the Frontline Solver API. Using Microsoft Solver Foundation, and minimizing the sum of squared differences, the following program:
private static void Main(string[] args)
{
var solver = SolverContext.GetContext();
var model = solver.CreateModel();
var A = new[,]
{
{ 1, 0, 0, 0, 0 },
{ 0.760652602, 1, 0, 0, 0 },
{ 0.373419404, 0.760537565, 1, 0, 0 },
{ 0.136996731, 0.373331934, 0.760422587, 1, 0 },
{ 0.040625222, 0.136953801, 0.373244464, 0.76030755, 1 }
};
var b = new[] { 2017159, 1609660, 837732.8125, 330977.3125, 87528.38281 };
var n = A.GetLength(1);
var x = new Decision[n];
for (var i = 0; i < n; ++i)
model.AddDecision(x[i] = new Decision(Domain.RealNonnegative, null));
// START NLP SECTION
var m = A.GetLength(0);
Term goal = 0.0;
for (var j = 0; j < m; ++j)
{
Term Ax = 0.0;
for (var i = 0; i < n; ++i) Ax += A[j, i] * x[i];
goal += Model.Power(Ax - b[j], 2.0);
}
model.AddGoal(null, GoalKind.Minimize, goal);
// END NLP SECTION
var solution = solver.Solve();
Console.WriteLine("f = {0}", solution.Goals.First().ToDouble());
for (var i = 0; i < n; ++i) Console.WriteLine("x[{0}] = {1}", i, x[i].GetDouble());
}
generates the following solution, which should be in line with the solution from the linked Excel sheet:
f = 254184688.179922
x[0] = 2017027.31820845
x[1] = 76226.6063397686
x[2] = 26007.3375581303
x[3] = 1.00650383558278E-07
x[4] = 4.18546775823669E-09
If I am not mistaken, unlike GRG, Solver Foundation cannot support general non-linear constraints out-of-the-box, I believe you will need additional plug-ins to handle these. For your problem, this is of course not an issue.
For completeness, to formulate the LP problem instead, exchange the code between START NLP SECTION and END NLP SECTION with the following code:
var m = A.GetLength(0);
var constraints = new Term[m];
for (var j = 0; j < m; ++j)
{
Term Ax = 0.0;
for (var i = 0; i < n; ++i) Ax += A[j, i] * x[i];
model.AddConstraint(null, constraints[j] = Model.GreaterEqual(Ax, b[j]));
}
model.AddGoal(null, GoalKind.Minimize, Model.Sum(x));
which will yield the following output (note that objective functions are different in the two cases, hence the large differences in f):
f = 2125502.27815564
x[0] = 2017159
x[1] = 75302.7580022821
x[2] = 27215.9247379241
x[3] = 5824.5954154355
x[4] = 0

Categories