Search code examples
gnuplotdata-fitting

I want to fit a function with integer parameters


I want to fit a function with GNUPLOT that is like a Fourier expansion. I have 3 terms with many parameters that should be integer and real.

I don't know how to set some variables to fit as integer numbers

I have something like that, where n1,n2,n3 should be integer, and the other parameters real:

g(x)=(A1*(1+cos(n1*x-b1))+A2*(1+cos(n2*x-b2))+A3*(1+cos(n3*x-b3)))/2

fit g(x) file u ($1+4):(f($2,E_min)) via A1,A2,A3,b1,b2,b3,n1,n2,n3

Solution

  • Maybe this could be an oversimplification to your problem, but I hope to help you. Suppose you have a file like this:

    # data.dat
      0.000    4.313
     10.417    4.868
     20.833    5.115
     31.250    4.858
     41.667    3.942
     52.083    3.213
     62.500    2.153
     72.917    1.403
     83.333    0.967
     93.750    1.130
    104.167    1.439
    114.583    2.175
    125.000    2.699
    135.417    3.319
    145.833    3.448
    156.250    3.319
    166.667    2.884
    177.083    2.352
    187.500    1.933
    197.917    1.530
    208.333    1.611
    218.750    2.046
    229.167    2.375
    239.583    2.826
    250.000    3.213
    

    You can perform a first fit to find parameters values and then write a file with such values within and pass it for a second fit command.

    # Function
    g(x) = (A1*(1+cos(n1*x-b1))+A2*(1+cos(n2*x-b2))+A3*(1+cos(n3*x-b3)))/2
    
    # Initial values
    A1 = 1.0; n1 = 1.0; b1 = 1.0
    A2 = 1.5; n2 = 2.0; b2 = 2.0
    A3 = 2.0; n3 = 3.0; b3 = 3.0
    
    set fit prescale
    
    # First fit command
    fit g(x) "data.dat" u 1:2 via A1,A2,A3, b1,b2,b3, n1,n2,n3
    

    The trick is round the values with you want.

    # File to second fit command
    set print "parameters.dat"
        print sprintf("A1 = %g", A1)
        print sprintf("A2 = %g", A2)
        print sprintf("A3 = %g", A3)
        print sprintf("b1 = %g", b1)
        print sprintf("b2 = %g", b2)
        print sprintf("b3 = %g", b3)
        print sprintf("n1 = %.0f # FIXED", n1)
        print sprintf("n2 = %.0f # FIXED", n2)
        print sprintf("n3 = %.0f # FIXED", n3)
    unset print
    

    The parameters.dat file look like this:

    A1 = 1.15639
    A2 = 1.61595
    A3 = 2.45079
    b1 = 46.054
    b2 = 12.2914
    b3 = 65.8431
    n1 = 1 # FIXED
    n2 = 2 # FIXED
    n3 = 3 # FIXED
    

    Now the second fit command and the final graph:

    # Second fit command
    fit g(x) "data.dat" u 1:2 via "parameters.dat"
    
    plot "data.dat" u 1:2 w p ls -1 pt 7, g(x) w l lc "red" lw 2
    

    Of course the parameters now are little bit different.

    A1 = 0.901065
    A2 = 1.59511 
    A3 = 2.63525 
    b1 = 29.8406 
    b2 = 34.2084 
    b3 = 60.7824  
    

    The result: Result

    I hope to help you.