Gnuplot:在拟合曲线中使用数组作为参数不起作用

Gnuplot: Using arrays as parameters in fit curve doesn't work

似乎单个数组值在 gnuplot 中的工作方式与普通变量不同。

我试过下面给出的代码。

# Following code doesn't work.
reset

# Parameters and fitting curve
n = 3
array p[n]
p[1] = 1.3 ; p[2] = 0.2 ; p[3] = 0.7
f(x) = p[1] * sin( p[2] + p[3] * x )

set fit
fit f(x) 'datafile.txt' using 1:2 via p[1], p[2], p[3]
unset fit

我收到以下错误:line 11: unknown type in real()

请注意,如果我将数组 p[1], p[2], p[3] 更改为 a, b, c,则代码有效。

# Following works.
reset

a = 1.3 ; b = 0.2 ; c = 0.7
f(x) = a * sin( b + c * x )

set fit
fit f(x) 'datafile.txt' using 1:2 via a, b, c
unset fit

为了完整起见,下面给出了部分数据(应另存为'datafile.txt'):

# x y
0  0.0222457
0.1  0.113168 
0.2  0.252268  
0.3  0.378091  
0.4  0.397219  
0.5  0.577536  
0.6  0.621418  
0.7  0.695817  
0.8  0.741057  
0.9  0.849566  
1  0.864276  

所以我的问题是:

  1. gnuplot 数组与普通变量的工作方式不同,我的假设是否正确?
  2. 有没有办法让数组的行为方式与普通变量相同?

正如@Karl 在评论中提到的,您必须来回分配变量和数组。 以下解决方案似乎以自动方式工作,但我不确定这是否真的是一种简化。 如果您想从 p 更改为 q,或者从 3 个变量更改为 7 个变量,也许这会让生活变得更轻松。 它使用了一些不太明显的“技巧”,检查 help arrayshelp macroshelp evaluatehelp keyentryhelp sumhelp sprintf、.. .

代码:

### workaround for fitting using array values
reset session

$Data <<EOD
# x y
0  0.0222457
0.1  0.113168 
0.2  0.252268  
0.3  0.378091  
0.4  0.397219  
0.5  0.577536  
0.6  0.621418  
0.7  0.695817  
0.8  0.741057  
0.9  0.849566  
1  0.864276  
EOD

# parameters and fitting curve
N = 3
array p[N]
p[1] = 1.3 ; p[2] = 0.2 ; p[3] = 0.7
myVar = 'p'   # define your variable
myColX = 1
myColY = 2

f(x) = p1 * sin( p2 + p3 * x )    # fitting function, defined with p1, p2, p3, ..., pN

#=======
# from here on "everything" goes automatic with variables and arrays
print "Initial array values: ", @myVar

# defining procedures for assigning variables and/arrays back and forth
myArrToVar(var) = sprintf("do for [i=1:|%s|] { eval(sprintf('%s%s = %s[%s]',i,i)) }",var,var,'%d',var,'%d')
myVarToArr(var) = sprintf("do for [i=1:|%s|] { eval(sprintf('%s[%s] = %s%s',i,i)) }",var,var,'%d',var,'%d')

# values from array --> variables
ArrToVar = myArrToVar(myVar)
@ArrToVar

# create the via, e.g p1,p2,p3,...
myViaStr(var) = (_tmp = '', (sum[_i=1:N] (_tmp = _tmp.sprintf('%s%d%s',var,_i,_i==N?'':', '),1)), _tmp)
viaStr = myViaStr(myVar)

# actual fitting
set fit quiet nolog
fit f(x) $Data using myColX:myColY via @viaStr

# values from variables --> array
VarToArr = myVarToArr(myVar)
@VarToArr

print "Final array values:  ", @myVar
set key top left

plot $Data u myColX:myColY w p pt 7 ti "Data", \
     f(x) w l lc "red", \
     for [i=1:N] keyentry ti sprintf('%s[%d]=%.4f',myVar,i,@myVar[i])
### end of code

结果:

Initial array values: [1.3,0.2,0.7]

Final array values:  [0.9215500294371,0.0231339564404058,1.20450770853891]