2
* This file is part of TISEAN
4
* Copyright (c) 1998-2007 Rainer Hegger, Holger Kantz, Thomas Schreiber
6
* TISEAN is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* TISEAN is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with TISEAN; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
/* Author: Rainer Hegger
21
* Modified: Piotr Held <pjheld@gmail.com> (2015).
22
* This function is based on polynom of TISEAN 3.0.1
23
* https://github.com/heggus/Tisean"
26
#define HELPTEXT "Part of tisean package\n\
27
No argument checking\n\
28
FOR INTERNAL USE ONLY"
30
#include <octave/oct.h>
31
#include "routines_c/tsa.h"
33
double polynom(double *series, octave_idx_type DELAY, octave_idx_type N,
34
octave_idx_type act,octave_idx_type dim,long cur,long fac)
38
octave_idx_type n = cur/fac;
39
octave_idx_type hi = act-(dim-1)*DELAY;
40
for (octave_idx_type j=1;j<=n;j++)
43
ret *= polynom(series, DELAY, N,act,dim-1,cur-n*fac,fac/(N+1));
48
octave_idx_type number_pars(octave_idx_type DIM, octave_idx_type ord,
49
octave_idx_type start)
52
octave_idx_type ret=0;
55
for (octave_idx_type i=start;i<=DIM;i++)
58
for (octave_idx_type i=start;i<=DIM;i++)
59
ret += number_pars(DIM, ord-1,i);
64
void make_coding(std::vector <octave_idx_type> &coding_vec, octave_idx_type N,
65
octave_idx_type ord, octave_idx_type d,
66
octave_idx_type fac, octave_idx_type cur)
69
coding_vec.push_back (cur);
71
for (octave_idx_type j=0;j<=ord;j++)
72
make_coding(coding_vec, N, ord-j,d-1,fac*(N+1),cur+j*fac);
75
void make_fit(double *series, octave_idx_type *coding, double *results,
76
octave_idx_type INSAMPLE, octave_idx_type N,
77
octave_idx_type DIM, octave_idx_type DELAY,
78
long maxencode, octave_idx_type pars)
81
Matrix mat_b (pars,1);
82
double *b = mat_b.fortran_vec ();
84
Matrix mat (pars,pars);
85
OCTAVE_LOCAL_BUFFER (double *, mat_arr, pars);
87
for (octave_idx_type i=0;i<pars;i++)
88
mat_arr[i]=mat.fortran_vec () + i * pars;
90
for (octave_idx_type i=0;i<pars;i++) {
92
for (octave_idx_type j=0;j<pars;j++)
96
for (octave_idx_type i=0;i<pars;i++)
97
for (octave_idx_type j=i;j<pars;j++)
98
for (octave_idx_type k=(DIM-1)*DELAY;k<INSAMPLE-1;k++)
99
mat_arr[i][j] += polynom(series,DELAY,N,k,DIM,coding[i],maxencode)*
100
polynom(series,DELAY,N,k,DIM,coding[j],maxencode);
101
for (octave_idx_type i=0;i<pars;i++)
102
for (octave_idx_type j=i;j<pars;j++)
103
mat_arr[j][i]=(mat_arr[i][j] /= (INSAMPLE-1-(DIM-1)*DELAY));
105
for (octave_idx_type i=0;i<pars;i++) {
106
for (octave_idx_type j=(DIM-1)*DELAY;j<INSAMPLE-1;j++)
107
b[i] += series[j+1]*polynom(series,DELAY,N,j,DIM,coding[i],maxencode);
108
b[i] /= (INSAMPLE-1-(DIM-1)*DELAY);
111
// old solvele(mat_arr,b,pars);
112
Matrix solved_vec = mat.solve (mat_b);
113
double *solved_ptr = solved_vec.fortran_vec ();
115
for (octave_idx_type i=0;i<pars;i++)
116
results[i]=solved_ptr[i];
120
void decode(octave_idx_type N,octave_idx_type *out,int dim,long cur,long fac)
123
octave_idx_type n=cur/fac;
126
decode(N,out,dim-1,cur-(long)n*fac,fac/(N+1));
129
double make_error(double *series, octave_idx_type *coding, double *results,
130
octave_idx_type N, octave_idx_type DIM,
131
octave_idx_type DELAY, long maxencode, octave_idx_type pars,
132
octave_idx_type i0, octave_idx_type i1)
136
for (octave_idx_type j=i0+(DIM-1)*DELAY;j<(long)i1-1;j++) {
138
for (octave_idx_type k=0;k<pars;k++)
139
h += results[k]*polynom(series,DELAY,N,j,DIM,coding[k],maxencode);
140
err += (series[j+1]-h)*(series[j+1]-h);
142
return err /= (double)(i1-i0-(DIM-1)*DELAY);
145
void make_cast (NDArray &forecast, double *series, octave_idx_type *coding,
146
double * results, octave_idx_type LENGTH,
147
octave_idx_type CLENGTH, octave_idx_type N,
148
octave_idx_type DIM, octave_idx_type DELAY, long maxencode,
149
octave_idx_type pars,
153
for (octave_idx_type i=0;i<=(DIM-1)*DELAY;i++)
154
series[i]=series[LENGTH-(DIM-1)*DELAY-1+i];
156
octave_idx_type hi=(DIM-1)*DELAY;
157
forecast.resize (dim_vector (CLENGTH,1));
158
for (octave_idx_type i=1;i<=CLENGTH;i++)
161
for (octave_idx_type k=0;k<pars;k++)
162
casted += results[k]*polynom(series,DELAY,N,(DIM-1)*DELAY,DIM,
163
coding[k],maxencode);
165
// old fprintf(fcast,"%e\n",casted*std_dev);
166
forecast(i-1) = casted*std_dev;
167
for (octave_idx_type j=0;j<(DIM-1)*DELAY;j++)
168
series[j]=series[j+1];
173
DEFUN_DLD (__polynom__, args, nargout, HELPTEXT)
176
int nargin = args.length ();
177
octave_value_list retval;
179
if (nargin != 6 || nargout != 5)
187
NDArray input = args(0).array_value ();
188
octave_idx_type DIM = args(1).idx_type_value ();
189
octave_idx_type DELAY = args(2).idx_type_value ();
190
octave_idx_type N = args(3).idx_type_value ();
191
octave_idx_type INSAMPLE = args(4).idx_type_value ();
192
octave_idx_type CLENGTH = args(5).idx_type_value ();
194
octave_idx_type LENGTH = input.numel ();
195
double *series = input.fortran_vec ();
199
variance(input,LENGTH,&av,&std_dev);
202
for (octave_idx_type i=0;i<LENGTH;i++)
203
series[i] /= std_dev;
205
// Create help values for the fit
207
for (octave_idx_type i=1;i<DIM;i++)
210
octave_idx_type pars = 1;
211
for (octave_idx_type i=1;i<=N;i++) {
212
pars += number_pars(DIM, i,1);
216
OCTAVE_LOCAL_BUFFER (double, results, pars);
217
OCTAVE_LOCAL_BUFFER (octave_idx_type, opar, DIM);
220
std::vector <octave_idx_type> coding_vec;
221
coding_vec.reserve (pars);
222
make_coding(coding_vec,N,N,DIM-1,1,0);
223
octave_idx_type *coding = coding_vec.data();
227
// Promote warnings connected with singular matrixes to errors
228
set_warning_state ("Octave:nearly-singular-matrix","error");
229
set_warning_state ("Octave:singular-matrix","error");
232
make_fit (series, coding, results, INSAMPLE, N, DIM, DELAY,
235
// If error encountered during the fit there is no sense to continue
243
// Create output that contains the number of free parameters
244
// old fprintf(file,"#number of free parameters= %d\n\n",pars);
245
octave_idx_type free_par = pars;
247
// Create output that contains the norm used for the fit
248
// old fprintf(file,"#used norm for the fit= %e\n",std_dev);
249
double fit_norm = std_dev;
251
// Create coefficients output
252
Matrix coeffs (pars, DIM + 1);
253
for (octave_idx_type j=0;j<pars;j++)
255
decode(N,opar,DIM-1,coding[j],maxencode);
256
octave_idx_type sumpar=0;
257
for (octave_idx_type k=0;k<DIM;k++)
260
// old fprintf(file,"%d ",opar[k]);
261
coeffs(j, k) = opar[k];
263
// old fprintf(file,"%e\n",results[j]
264
// /pow(std_dev,(double)(sumpar-1)));
265
coeffs(j,DIM) = results[j]/pow(std_dev,(double)(sumpar-1));
269
// Create sample error
270
// 1st element of sample_error is the insample error
271
// 2nd element of sample_error is the out of sample error (if exists)
272
NDArray sample_err (dim_vector (1,1));
274
// old in_error = make_error((unsigned long)0,INSAMPLE)
275
// fprintf(file,"#average insample error= %e\n",
276
// sqrt(in_error)*std_dev);
277
sample_err(0) = sqrt(make_error(series, coding, results, N, DIM,
278
DELAY, maxencode, pars,
282
if (INSAMPLE < LENGTH)
284
// old out_error=make_error(INSAMPLE,LENGTH);
285
// fprintf(file,"#average out of sample error= %e\n",
286
// sqrt(out_error)*std_dev);
287
sample_err.resize (dim_vector (2,1));
288
sample_err(1) = sqrt (make_error (series, coding, results, N,
289
DIM, DELAY, maxencode, pars,
295
NDArray forecast (dim_vector (0,0));
297
make_cast(forecast, series, coding, results, LENGTH, CLENGTH, N,
298
DIM, DELAY, maxencode, pars, std_dev);
301
retval(0) = free_par;
302
retval(1) = fit_norm;
304
retval(3) = sample_err;
305
retval(4) = forecast;