4

I'm new here and I hope that perhaps the experts outthere can help me: I want to fit the sinus function f(x) = a *sin(b* (x+c))+d via the library "math.net numerics" in C#.

At the beginning I tried the following example code:

// data points: we compute y perfectly but then add strong random noise to it
var rnd = new Random(1);
var omega = 1.0d
var xdata = new double[] { -1, 0, 0.1, 0.2, 0.3, 0.4, 0.65, 1.0, 1.2, 2.1, 4.5, 5.0, 6.0 };
var ydata = xdata.Select(x => 5 + 2 * Math.Sin(omega*x + 0.2) + 2*(rnd.NextDouble()-0.5)).ToArray();

// build matrices
var X = DenseMatrix.OfColumns(new[] {
new DenseVector(1),
new DenseVector(xdata.Select(t => Math.Sin(omega*t)).ToArray()),
new DenseVector(xdata.Select(t => Math.Cos(omega*t)).ToArray())});
var y = new DenseVector(ydata);

// solve
var p = X.QR().Solve(y);
var a = p[0];
var b = SpecialFunctions.Hypotenuse(p[1], p[2]);
var c = Math.Atan2(p[2], p[1]); 

But the result was, that the program returned the following error:

"Matrix dimensions must agree: 1x3".

Could you give me a hint what I can do to solve the problem ?

Grant Winney
  • 65,241
  • 13
  • 115
  • 165
Biläl
  • 43
  • 4

1 Answers1

2

You are adding 3 columns to the matrix (X) that have different lengths.

The first vector has length 1, while the second and third vectors have lengths of xdata.Length.

If you intend for the first vector to have the length of xdata.Length but to be filled with 1s then do the following:

var X = DenseMatrix.OfColumns(new[]
{
    new DenseVector(Enumerable.Repeat(1d , xdata.Length).ToArray()),
    new DenseVector(xdata.Select(t => Math.Sin(omega*t)).ToArray()),
    new DenseVector(xdata.Select(t => Math.Cos(omega*t)).ToArray())
});
Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
  • Thanks Yacoub you saved my life – Biläl Jan 15 '16 at 15:03
  • Additional question: The code above was for the function f(x) = a + b*sin(c+omega*x). What do I have to change in the code, so it is for the function f(x) = a *sin(b* (x+c))+d ? – Biläl Jan 15 '16 at 15:28
  • @Biläl, It would be better if you post this as another question with details. This way, we have more context to answer the question. – Yacoub Massad Jan 15 '16 at 15:36