STK++ 0.9.13
STK_BSplineCoefficients.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------*/
2/* Copyright (C) 2004-2016 Serge Iovleff, Université Lille 1, Inria
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the
16 Free Software Foundation, Inc.,
17 59 Temple Place,
18 Suite 330,
19 Boston, MA 02111-1307
20 USA
21
22 Contact : S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
23 */
24
25/*
26 * Project: stkpp::Regress
27 * created on: 25 juin 2010
28 * Purpose: Compute the coefficient of a B-spline curves.
29 * Author: iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
30 **/
31
36#ifndef STK_BSPLINECOEFFICIENTS_H
37#define STK_BSPLINECOEFFICIENTS_H
38
39#include "STK_IBasis.h"
40
43
44#ifdef STK_REGRESS_VERBOSE
46#endif
47
48namespace STK
49{
61template<class Data>
62class BSplineCoefficients: public IBasis<Data, ArrayXX>
63{
64 public:
66 using Base::p_data_;
68 using Base::dim_;
69 using Base::msg_error_;
70 using Base::hasRun_;
71 using Base::minValue_;
72 using Base::maxValue_;
73
85 BSplineCoefficients( Data const* p_data =0
86 , int nbControlPoints =1
87 , int degree = 3
89 , bool useDataValues = true
90 );
100 BSplineCoefficients( Data const& data
101 , int nbControlPoints
102 , int degree = 3
104 , bool useDataValues = true
105 );
113 BSplineCoefficients* clone() const { return new BSplineCoefficients(*this);}
115 virtual bool run();
116 // getters
118 inline int degree() const { return degree_;}
120 inline int nbKnots() const { return nbKnots_;}
122 inline int nbControlPoints() const { return dim_;}
124 inline VectorX const& knots() const { return knots_;}
125 // setters
133 inline void setDim( int dim) { setNbControlPoints(dim);}
137 void setDegree( int degree = 3);
148 void setParameters( Data const& data
149 , int nbControlPoints
150 , int degree = 3
152 );
153
160 void setData( Data const& data
161 , int nbControlPoints
162 , int degree = 3
164 );
165
169 template<class OtherVector>
171
172 protected:
185
190
191 private:
204 void computeCoefficientsRow(int irow, Real const& value);
205};
206
207/* constructor */
208template<class Data>
210 , int nbControlPoints
211 , int degree
213 , bool useDataValues
214 )
215 : Base(p_data, nbControlPoints, useDataValues)
216 , degree_(degree)
217 , position_(position)
218 , nbKnots_(nbControlPoints + degree + 1)
219 , lastControlPoint_(dim_-1)
220 , knots_( Range(0, nbKnots_) )
221{ }
222
223/* constructor */
224template<class Data>
226 , int nbControlPoints
227 , int degree
229 , bool useDataValues
230 )
231 : Base(data, nbControlPoints, useDataValues)
232 , degree_(degree)
233 , position_(position)
234 , nbKnots_(nbControlPoints + degree +1)
235 , lastControlPoint_(dim_-1)
236 , knots_( Range(0, nbKnots_) )
237{}
238/* copy constructor.
239 * @param coefs the coefficients to copy
240 **/
241template<class Data>
243 : Base(coefs)
244 , degree_(coefs.degree_)
245 , position_(coefs.position_)
246 , nbKnots_(coefs.nbKnots_)
247 , lastControlPoint_(coefs.lastControlPoint_)
248 , knots_(coefs.knots_)
249{}
250
251
252
253/* run the computations for the given value.
254 * @param p_data the input data values
255 **/
256template<class Data>
258 , int nbControlPoints
259 , int degree
261 )
262{ // set data
263 p_data_ = &data;
264 dim_ = nbControlPoints;
265 degree_ = degree;
266 position_ = position;
267 nbKnots_ = dim_ + degree_ +1;
268 lastControlPoint_ = dim_-1;
269 Base::update();
270}
271
272/* run the computations for the given value.
273 * @param p_data the input data values
274 **/
275template<class Data>
277 , int nbControlPoints
278 , int degree
280 )
281{ // set data
282 p_data_ = &data;
283 dim_ = nbControlPoints;
284 degree_ = degree;
285 position_ = position;
286 nbKnots_ = dim_ + degree_ +1;
287 lastControlPoint_ = dim_-1;
288 knots_.resize( Range(0, nbKnots_) );
289 Base::update();
290}
291
292/* run the computations for the given value.
293 * @param p_data the input data values
294 **/
295template<class Data>
297{
298 dim_ = nbControlPoints;
299 nbKnots_ = dim_ + degree_ +1;
300 lastControlPoint_ = dim_-1;
301 knots_.resize( Range(0, nbKnots_) );
302 Base::update();
303}
304
305/* Set the degree of the BSpline basis
306 * @param degree degree of the B-spline curves (default is 3)
307 **/
308template<class Data>
310{
311 degree_ = degree;
312 nbKnots_ = dim_ + degree_ +1;
313 lastControlPoint_ = dim_-1;
314 knots_.resize( Range(0, nbKnots_) );
315 Base::update();
316}
317
318/* Set the kind of position to use for the knots
319 * @param position method to use for positioning the knots (default is uniform)
320 **/
321template<class Data>
327
328
329/* run the computations. */
330template<class Data>
332{
333 // check if data exists
334 if (!p_data_)
335 {
337 return false;
338 }
339 if (!this->initializeStep()) return false;
340 knots_ = minValue_;
341 // compute the knots and coefficients
342 if (computeKnots()) { computeCoefficients();}
343 else { return false;}
344 this->hasRun_ = true;
345 return true;
346}
347
348/* Extrapolate the matrix of coefficients for a given set of x-values.
349 * @param x the values to extrapolate
350 * @param coefs the matrix of coefficients for each values.
351 **/
352template<class Data>
353template<class OtherVector>
355{
356 // check if knots exists
357 if (!this->hasRun_)
359 // resize coeficients
360 ArrayXX coefs(x.range(), Range(0, lastControlPoint_, 0), 0.0);
361 // check if the original data set was not reduced to a single point
362 if (minValue_ == maxValue_) return coefs;
363 // compute the coefficients
364 for (int irow=x.begin(); irow< x.end(); irow++)
365 {
366 const Real value = x[irow];
367 // value outside the range of the knots case
368 if (value <= minValue_)
369 {
370 coefs(irow, 0) = 1.0;
371 continue;
372 }
373 if (value >= maxValue_)
374 {
375 coefs(irow, lastControlPoint_) = 1.0;
376 continue;
377 }
378 // find interval
379 int k, k1;
380 for (k=0, k1=1; k<lastControlPoint_; k++, k1++)
381 {
382 if (value < knots_[k1]) break;
383 }
384 // begin recursion
385 coefs(irow, k) = 1.0;
386 for (int d=1; d<=degree_; d++)
387 {
388 // right (south-west corner) term only
389 coefs(irow, k-d) = ( (knots_[k1] - value)/(knots_[k1] - knots_[k1-d]) ) * coefs(irow, k1-d);
390 // compute internal terms
391 for (int i = k1-d; i<k; i++)
392 {
393 const Real knots_i = knots_[i], knots_id1 = knots_[i+d+1];
394 coefs(irow, i) = ( (value - knots_i)/(knots_[i+d] - knots_i) ) * coefs(irow, i)
395 + ( (knots_id1 - value)/(knots_id1 - knots_[i+1]) ) * coefs(irow, i+1);
396 }
397 // left (north-west corner) term only
398 coefs(irow, k) *= (value - knots_[k])/(knots_[k+d] - knots_[k]);
399 }
400 }
401 return coefs;
402}
403
404/* compute the knots of the B-spline curves.*/
405template<class Data>
407{
408 // resize and initialize knots
409 knots_.resize( Range(0, nbKnots_) ) = minValue_;
410 // set knots values
411 switch (position_)
412 {
413 // uniform position
415 computeUniformKnots();
416 break;
417 // periodic position
419 computePeriodicKnots();
420 break;
421 // density position
423 computeDensityKnots(true);
424 break;
425 default:
426
428 return false;
429 break;
430 }
431 // shift knots
432 if (position_ != Regress::densityKnotsPositions_)
433 {
434 Real range = (maxValue_ - minValue_);
435 for (int k = 0; k < nbKnots_; k++) knots_[k] = minValue_ + range * knots_[k];
436 }
437 return true;
438}
439
440/* Compute the coefficients of the B-spline curves.*/
441template<class Data>
443{
444#ifdef STK_REGRESS_VERBOSE
445 stk_cout << _T("BSplineCoefficients::computeCoefficients()\n");
446#endif
447
448 // compute the coefficients
449 for (int i=p_data_->begin(); i< p_data_->end(); i++)
450 { computeCoefficientsRow(i, (*p_data_)[i]);}
451
452#ifdef STK_REGRESS_VERBOSE
453 stk_cout << _T("BSplineCoefficients::computeCoefficients() done\n");
454#endif
455}
456
457/* compute the position of the uniform knots.*/
458template<class Data>
460{
461 // compute step
462 Real step = 1.0/(dim_ - degree_);
463 // set internal knots
464 const int first = degree_ + 1;
465 for (int k = first, j = 1; k <= lastControlPoint_; j++, k++) knots_[k] = j * step;
466 // set external knots
467 for ( int k=0, j = lastControlPoint_+1; k < first; j++, k++)
468 {
469 knots_[k] = 0;
470 knots_[j] = 1;
471 }
472}
473/* compute the position of the periodic knots.*/
474template<class Data>
476{
477 // compute step
478 Real step = 1.0/(dim_ - degree_);
479 // set knots
480 for (int k = 0, j = -degree_; k < nbKnots_; j++, k++)
481 knots_[k] = j * step;
482;
483}
484/* compute the position of the density knots. */
485template<class Data>
487{
488 // sorted data
489 Data xtri(*p_data_, true);
490 // sort the data
492
493 // compute step
494 Real step = xtri.size()/(Real)(lastControlPoint_-degree_+1);
495
496 // set internal knots
497 int first = xtri.begin();
498 for (int k = degree_ + 1, kcell =1; k <= lastControlPoint_; k++, kcell++)
499 {
500 int cell = first + int(kcell* step);
501 knots_[k] = (xtri[cell] + xtri[cell+1])/2.;
502 }
503 // set external knots
504 for ( int k=0, j = lastControlPoint_+1; k <= degree_; j++, k++)
505 {
506 knots_[k] = xtri.front();
507 knots_[j] = xtri.back();
508 }
509}
510
511/* Compute a row of the coefficients
512 * @param irow index of the row
513 **/
514template<class Data>
516{
517 // value outside the range of the knots case
518 if (value <= minValue_)
519 {
520 coefficients_(irow, 0) = 1.0;
521 return;
522 }
523 if (value >= maxValue_)
524 {
525 coefficients_(irow, lastControlPoint_) = 1.0;
526 return;
527 }
528 // find interval
529 int k, k1;
530 for (k=0, k1=1; k<lastControlPoint_; k++, k1++)
531 {
532 if (value < knots_[k1]) break;
533 }
534 // begin recursion
535 coefficients_(irow, k) = 1.0;
536 for (int d=1; d<=degree_; d++)
537 {
538 // right (south-west corner) term only
539 coefficients_(irow, k-d) = ( (knots_[k1] - value)/(knots_[k1] - knots_[k1-d]) )
540 * coefficients_(irow, k1-d);
541 // compute internal terms
542 for (int i = k1-d; i<k; i++)
543 {
544 const Real knots_i = knots_[i], knots_id1 = knots_[i+d+1];
545 coefficients_(irow, i) = ( (value - knots_i)/(knots_[i+d] - knots_i) )
546 * coefficients_(irow, i)
547 + ( (knots_id1 - value)/(knots_id1 - knots_[i+1]) )
548 * coefficients_(irow, i+1);
549 }
550 // left (north-west corner) term only
551 coefficients_(irow, k) *= (value - knots_[k])/(knots_[k+d] - knots_[k]);
552 }
553}
554
555} // namespace STK
556
557#endif /* STK_BSPLINECOEFFICIENTS_H */
A Array2DVector is a one dimensional horizontal container.
This file define methods for displaying Arrays and Expressions.
In this file we define an implementation of the heapsort algorithm for IVector containers.
In this file we define the Interface class IBasis for basis functions.
#define STKERROR_NO_ARG(Where, Error)
Definition STK_Macros.h:49
#define STKRUNTIME_ERROR_NO_ARG(Where, Error)
Definition STK_Macros.h:138
#define stk_cout
Standard stk output stream.
#define _T(x)
Let x unmodified.
Compute the regression B-splines coefficients.
VectorX const & knots() const
void computeDensityKnots(bool isSorted)
compute the position of the density knots
int nbKnots_
number of knots of the B-spline curves.
BSplineCoefficients(Data const &data, int nbControlPoints, int degree=3, Regress::KnotsPosition position=Regress::uniformKnotsPositions_, bool useDataValues=true)
Constructor : initialize the data members.
int degree_
degree of the B-splines curves.
void computeCoefficientsRow(int irow, Real const &value)
Compute a row of the coefficients matrix for a given value.
void setDegree(int degree=3)
Set the degree of the BSpline basis.
void setDim(int dim)
Alias for setting the number of control point (the number of BSpline)
void computePeriodicKnots()
compute the position of the periodic knots.
IBasis< Data, ArrayXX > Base
void setData(Data const &data, int nbControlPoints, int degree=3, Regress::KnotsPosition position=Regress::uniformKnotsPositions_)
[DEPRECATED] Set the whole set of parameters for computing the coefficients
void computeUniformKnots()
compute the position of the uniform knots.
virtual bool run()
run the computations.
void computeCoefficients()
Compute the coefficients of the B-spline curves.
void setPosition(Regress::KnotsPosition position)
Set the kind of position to use for the knots.
bool computeKnots()
compute the position of the knots of the B-spline curves.
BSplineCoefficients(BSplineCoefficients const &coefs)
copy constructor.
void setNbControlPoints(int nbControlPoints)
Set the number of control point (the number of BSpline)
Regress::KnotsPosition position_
Method used in order to position the knots.
virtual ~BSplineCoefficients()
Destructor.
void setParameters(Data const &data, int nbControlPoints, int degree=3, Regress::KnotsPosition position=Regress::uniformKnotsPositions_)
Set the whole set of parameters for computing the coefficients.
VectorX knots_
Data of the knots.
BSplineCoefficients * clone() const
clone pattern implementation
BSplineCoefficients(Data const *p_data=0, int nbControlPoints=1, int degree=3, Regress::KnotsPosition position=Regress::uniformKnotsPositions_, bool useDataValues=true)
Default constructor : initialize the data members with default values.
int lastControlPoint_
Index of the last control point of the B-spline curves.
ArrayXX extrapolate(OtherVector const &x) const
Interface base class for all basis function.
Definition STK_IBasis.h:49
Data const * p_data_
the input data set
Definition STK_IBasis.h:110
Type minValue_
Minimal value of the data.
Definition STK_IBasis.h:116
Type maxValue_
Maximal value of the data.
Definition STK_IBasis.h:118
int dim_
number of dimension to build
Definition STK_IBasis.h:112
ArrayXX coefficients_
Array2D of the coefficients.
Definition STK_IBasis.h:121
virtual bool run()
run the computations.
virtual bool initializeStep()
perform any computation needed before the call of the regression method.
String msg_error_
String with the last error message.
Definition STK_IRunner.h:96
virtual void update()
update the runner.
Definition STK_IRunner.h:94
bool hasRun_
true if run has been used, false otherwise
Definition STK_IRunner.h:98
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
Array const & coefs() const
Index sub-vector region: Specialization when the size is unknown.
Definition STK_Range.h:265
KnotsPosition
Method to use for positioning the knots for BSpline basis.
@ uniformKnotsPositions_
uniform knots
@ densityKnotsPositions_
knots using density of the data
@ periodicKnotsPositions_
periodic knots
double Real
STK fundamental type of Real values.
The namespace STK is the main domain space of the Statistical ToolKit project.
TRange< UnknownSize > Range
Definition STK_Range.h:59