CompositeFunction.cpp 24.4 KB
Newer Older
1
2
3
4
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/Exception.h"
5
6
#include "MantidAPI/CompositeFunction.h"
#include "MantidAPI/ParameterTie.h"
7
#include "MantidAPI/IConstraint.h"
8

9
#include <boost/lexical_cast.hpp>
10
11
12
#include <boost/shared_array.hpp>
#include <sstream>
#include <iostream>
13
#include <algorithm>
14
15
16
17
18
19

namespace Mantid
{
namespace API
{

20
//DECLARE_FUNCTION(CompositeFunction)
21

22
23
/// Copy contructor
CompositeFunction::CompositeFunction(const CompositeFunction& f)
24
:m_nActive(f.m_nParams),m_nParams(f.m_nParams),m_iConstraintFunction(0)
25
26
27
28
29
30
31
32
33
34
35
36
37
38
{
  m_functions.assign(f.m_functions.begin(),f.m_functions.end());
  m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
  m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
}

///Assignment operator
CompositeFunction& CompositeFunction::operator=(const CompositeFunction& f)
{
  m_nActive = f.m_nActive;
  m_nParams = f.m_nParams;
  m_functions.assign(f.m_functions.begin(),f.m_functions.end());
  m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
  m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
39
  m_iConstraintFunction = f.m_iConstraintFunction;
40
41
42
43
44
45
  return *this;
}

///Destructor
CompositeFunction::~CompositeFunction()
{
46
  for(int i=0;i<nFunctions();i++)
47
48
49
50
51
52
53
54
55
    if (m_functions[i]) delete m_functions[i];
}


/// Function initialization. Declare function parameters in this method.
void CompositeFunction::init()
{
}

56
57
58
59
60
61
62
63
64
65
66
/** 
 * Writes itself into a string. Functions derived from CompositeFunction must
 * override this method with something like this:
 *   std::string NewFunction::asString()const
 *   {
 *      ostr << "composite=" << this->name() << ';';
 *      // write NewFunction's own attributes and parameters
 *      ostr << CompositeFunction::asString();
 *      // write NewFunction's own ties and constraints
 *      // ostr << ";constraints=(" << ... <<")";
 *   }
67
 * @return the string representation of the composite function
68
 */
69
70
71
std::string CompositeFunction::asString()const
{
  std::ostringstream ostr;
72
  for(int i=0;i<nFunctions();i++)
73
  {
74
    IFitFunction* fun = getFunction(i);
75
76
    bool isComp = dynamic_cast<CompositeFunction*>(fun) != 0;
    if (isComp) ostr << '(';
77
    ostr << fun->asString();
78
    if (isComp) ostr << ')';
79
80
81
82
83
84
    if (i < nFunctions() - 1)
    {
      ostr << ';';
    }
  }
  std::string ties;
85
  for(int i=0;i<nParams();i++)
86
87
88
89
  {
    const ParameterTie* tie = getTie(i);
    if (tie)
    {
90
      IFitFunction* fun = getFunction(functionIndex(i));
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
      std::string tmp = tie->asString(fun);
      if (tmp.empty())
      {
        tmp = tie->asString(this);
        if (!tmp.empty())
        {
          if (!ties.empty())
          {
            ties += ",";
          }
          ties += tmp;
        }
      }
    }
  }
  if (!ties.empty())
  {
    ostr << ";ties=(" << ties << ")";
109
110
111
112
  }
  return ostr.str();
}

113
/** Sets a new value to the i-th parameter.
114
115
116
 *  @param i :: The parameter index
 *  @param value :: The new value
 *  @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
117
 */
118
void CompositeFunction::setParameter(int i, const double& value, bool explicitlySet)
119
{
120
  int iFun = functionIndex(i);
121
  m_functions[ iFun ]->setParameter(i - m_paramOffsets[iFun],value,explicitlySet);
122
123
}

124
125
126
127
128
129
130
131
132
133
/** Sets a new description to the i-th parameter.
 *  @param i :: The parameter index
 *  @param description :: The new description
 */
void CompositeFunction::setParameterDescription(size_t i, const std::string& description)
{
  int iFun = functionIndex(i);
  m_functions[ iFun ]->setParameterDescription(i - m_paramOffsets[iFun],description);
}

134
/** Get the i-th parameter.
135
 *  @param i :: The parameter index
136
 *  @return value of the requested parameter
137
 */
138
double CompositeFunction::getParameter(int i)const
139
{
140
  int iFun = functionIndex(i);
141
  return m_functions[ iFun ]->getParameter(i - m_paramOffsets[iFun]);
142
143
}

144
145
/**
 * Sets a new value to a parameter by name.
146
147
148
 * @param name :: The name of the parameter.
 * @param value :: The new value
 * @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
149
150
 */
void CompositeFunction::setParameter(const std::string& name, const double& value, bool explicitlySet)
151
{
152
  std::string pname;
153
  int index;
154
  parseName(name,index,pname);
155
156
157
158
159
160
  if (index < 0)
    throw std::invalid_argument("CompositeFunction::getParameter: parameter name must contain function index");
  else
  {   
    getFunction(index)->setParameter(pname,value,explicitlySet);
  }
161
162
}

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/**
 * Sets a new description to a parameter by name.
 * @param name :: The name of the parameter.
 * @param value :: The new description
 */
void CompositeFunction::setParameterDescription(const std::string& name, const std::string& description)
{
  std::string pname;
  int index;
  parseName(name,index,pname);
  if (index < 0)
    throw std::invalid_argument("CompositeFunction::getParameter: parameter name must contain function index");
  else
  {   
    getFunction(index)->setParameterDescription(pname,description);
  }
}

181
182
/**
 * Parameters by name.
183
 * @param name :: The name of the parameter.
184
 * @return value of the requested named parameter
185
 */
186
187
double CompositeFunction::getParameter(const std::string& name)const
{
188
  std::string pname;
189
  int index;
190
  parseName(name,index,pname);
191
192
193
194
195
196
  if (index < 0)
    throw std::invalid_argument("CompositeFunction::getParameter: parameter name must contain function index");
  else
  {   
    return getFunction(index)->getParameter(pname);
  }
197
198
199
}

/// Total number of parameters
200
int CompositeFunction::nParams()const
201
202
203
204
{
  return m_nParams;
}

205
/**
206
 * 
207
 * @param name :: The name of a parameter
208
 * @return index of the requested named parameter
209
 */
210
int CompositeFunction::parameterIndex(const std::string& name)const
211
{
212
  std::string pname;
213
  int index;
214
  parseName(name,index,pname);
215
216
217
  if (index < 0)
    throw std::invalid_argument("CompositeFunction::getParameter: parameter name must contain function index");

218
  return getFunction(index)->parameterIndex(pname) + m_paramOffsets[index];
219
220
}

Nick Draper's avatar
re #100    
Nick Draper committed
221
/// Returns the name of parameter
222
/// @param i :: The index
Nick Draper's avatar
re #100    
Nick Draper committed
223
/// @return The name of the parameter
224
std::string CompositeFunction::parameterName(int i)const
225
{
226
  int iFun = functionIndex(i);
227
228
229
  std::ostringstream ostr;
  ostr << 'f' << iFun << '.' << m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
  return ostr.str();
230
231
}

232
233
234
235
236
237
238
239
240
241
242
/// Returns the description of parameter
/// @param i :: The index
/// @return The description of the parameter
std::string CompositeFunction::parameterDescription(size_t i)const
{
  int iFun = functionIndex(i);
  std::ostringstream ostr;
  ostr << m_functions[ iFun ]->parameterDescription(i - m_paramOffsets[iFun]);
  return ostr.str();
}

243
/// Number of active (in terms of fitting) parameters
244
int CompositeFunction::nActive()const
245
246
247
248
249
{
  return m_nActive;
}

/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
250
double CompositeFunction::activeParameter(int i)const
251
{
252
  int iFun = functionIndexActive(i);
253
254
255
256
257
258
  return m_functions[ iFun ]->activeParameter(i - m_activeOffsets[iFun]);
}

/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
void CompositeFunction::setActiveParameter(int i, double value)
{
259
  int iFun = functionIndexActive(i);
260
  m_functions[ iFun ]->setActiveParameter(i - m_activeOffsets[iFun],value);
261
262
263
264
265
266
267
268
269
}

/// Update parameters after a fitting iteration
void CompositeFunction::updateActive(const double* in)
{
  for(int iFun = 0; iFun < int(m_functions.size()); iFun++)
  {
    m_functions[ iFun ]->updateActive(in + m_activeOffsets[ iFun ]);
  }
270
  applyTies();
271
272
273
}

/// Returns "global" index of active parameter i
274
int CompositeFunction::indexOfActive(int i)const
275
{
276
  int iFun = functionIndexActive(i);
277
278
279
280
  return m_paramOffsets[ iFun ] + m_functions[ iFun ]->indexOfActive(i - m_activeOffsets[iFun]);
}

/// Returns the name of active parameter i
281
std::string CompositeFunction::nameOfActive(int i)const
282
{
283
  int iFun = functionIndexActive(i);
284
285
  std::ostringstream ostr;
  ostr << 'f' << iFun << '.' << m_functions[ iFun ]->nameOfActive(i - m_activeOffsets[iFun]);
286
287
288
289
290
291
292
293
294
  return ostr.str();
}

/// Returns the description of active parameter i
std::string CompositeFunction::descriptionOfActive(size_t i)const
{
  int iFun = functionIndexActive(i);
  std::ostringstream ostr;
  ostr << m_functions[ iFun ]->descriptionOfActive(i - m_activeOffsets[iFun]);
295
  return ostr.str();
296
297
}

298
/**
299
 * query to see in the function is active
300
 * @param i :: The index of a declared parameter
301
 * @return true if parameter i is active
302
 */
303
bool CompositeFunction::isActive(int i)const
304
305
306
307
308
309
{
  int iFun = functionIndex(i);
  return m_functions[ iFun ]->isActive(i - m_paramOffsets[iFun]);
}

/**
310
 * @param i :: A declared parameter index to be removed from active
311
 */
312
void CompositeFunction::removeActive(int i)
313
{
314
  if (!isActive(i)) return;
315
316
  int iFun = functionIndex(i);
  int ia = m_activeOffsets[iFun] + m_functions[iFun]->activeIndex(i - m_paramOffsets[iFun]);
317
  m_IFitFunctionActive.erase(m_IFitFunctionActive.begin()+ia);
318
319
  m_functions[ iFun ]->removeActive(i - m_paramOffsets[iFun]);

320
  m_nActive--;
321
  for(int j=iFun+1;j<nFunctions();j++)
322
323
324
    m_activeOffsets[j] -= 1;
}

325
/** Makes a parameter active again. It doesn't change the parameter's tie.
326
 * @param i :: A declared parameter index to be restored to active
327
 */
328
void CompositeFunction::restoreActive(int i)
329
{
330
331
  int iFun = functionIndex(i);
  int ia = m_activeOffsets[iFun] + m_functions[iFun]->activeIndex(i - m_paramOffsets[iFun]);
332

333
  std::vector<int>::iterator itFun = 
334
    std::find_if(m_IFitFunctionActive.begin(),m_IFitFunctionActive.end(),std::bind2nd(std::greater<int>(),i));
335

336
  m_IFitFunctionActive.insert(itFun,1,ia);
337
338
339
  m_functions[ iFun ]->restoreActive(i - m_paramOffsets[iFun]);

  m_nActive++;
340
  for(int j=iFun+1;j<nFunctions();j++)
341
342
343
    m_activeOffsets[j] += 1;
}

344
/**
345
 * @param i :: The index of a declared parameter
346
347
348
 * @return The index of declared parameter i in the list of active parameters or -1
 *         if the parameter is tied.
 */
349
int CompositeFunction::activeIndex(int i)const
350
{
351
352
  int iFun = functionIndex(i);
  int j = m_functions[iFun]->activeIndex(i - m_paramOffsets[iFun]);
353
354
355
356
357
358
359

  if (j == -1) 
  {
    return -1;
  }

  return m_activeOffsets[iFun] + j;
360
361
}

362
363
364
365
366
367
368
369
/** Makes sure that the function is consistent. 
 */
void CompositeFunction::checkFunction()
{
  m_nParams = 0;
  m_nActive = 0;
  m_paramOffsets.clear();
  m_activeOffsets.clear();
370
371
  m_IFitFunction.clear();
  m_IFitFunctionActive.clear();
372

373
  std::vector<IFitFunction*> functions(m_functions.begin(),m_functions.end());
374
375
  m_functions.clear();

376
  for(std::vector<IFitFunction*>::size_type i=0;i<functions.size();i++)
377
  {
378
    IFitFunction* f = functions[i];
379
380
    CompositeFunction* cf = dynamic_cast<CompositeFunction*>(f);
    if (cf) cf->checkFunction();
381
382
383
384
    addFunction(f);
  }
}

385
/** Add a function
386
 * @param f :: A pointer to the added function
387
 * @return The function index
388
 */
389
int CompositeFunction::addFunction(IFitFunction* f)
390
{
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
391
392
  m_IFitFunction.insert(m_IFitFunction.end(),f->nParams(), static_cast<int>(m_functions.size()));
  m_IFitFunctionActive.insert(m_IFitFunctionActive.end(),f->nActive(),static_cast<int>(m_functions.size()));
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  m_functions.push_back(f);
  //?f->init();
  if (m_paramOffsets.size() == 0)
  {
    m_paramOffsets.push_back(0);
    m_activeOffsets.push_back(0);
    m_nParams = f->nParams();
    m_nActive = f->nActive();
  }
  else
  {
    m_paramOffsets.push_back(m_nParams);
    m_activeOffsets.push_back(m_nActive);
    m_nParams += f->nParams();
    m_nActive += f->nActive();
  }
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
409
  return static_cast<int>(m_functions.size())-1;
410
411
}

412
/** Remove a function
413
414
 * @param i :: The index of the function to remove
 * @param del :: The deletion flag. If true the function will be deleted otherwise - simply detached
415
 */
416
void CompositeFunction::removeFunction(int i, bool del)
417
418
419
420
{
  if ( i >= nFunctions() )
    throw std::out_of_range("Function index out of range.");

421
  IFitFunction* fun = getFunction(i);
422

423
424
  int dna = fun->nActive();
  int dnp = fun->nParams();
425

426
  for(int j=0;j<nParams();)
427
428
  {
    ParameterTie* tie = getTie(j);
429
    if (tie && tie->findParametersOf(fun))
430
431
432
433
434
435
436
437
438
439
    {
      removeTie(j);
    }
    else
    {
      j++;
    }
  }

  // Shift down the function indeces for parameters
440
  for(std::vector<int>::iterator it=m_IFitFunction.begin();it!=m_IFitFunction.end();)
441
  {
442

443
444
    if (*it == i)
    {
445
      it = m_IFitFunction.erase(it);
446
    }
447
    else
448
    {
449
450
451
452
453
      if (*it > i)
      {
        *it -= 1;
      }
      it++;
454
455
456
457
    }
  }

  // Shift down the function indeces for active parameters
458
  for(std::vector<int>::iterator it=m_IFitFunctionActive.begin();it!=m_IFitFunctionActive.end();)
459
460
461
  {
    if (*it == i)
    {
462
      it = m_IFitFunctionActive.erase(it);
463
    }
464
    else
465
    {
466
467
468
469
470
      if (*it > i)
      {
        *it -= 1;
      }
      it++;
471
472
473
474
475
    }
  }

  m_nActive -= dna;
  // Shift the active offsets down by the number of i-th function's active params
476
  for(int j=i+1;j<nFunctions();j++)
477
478
479
480
481
482
483
  {
    m_activeOffsets[j] -= dna;
  }
  m_activeOffsets.erase(m_activeOffsets.begin()+i);

  m_nParams -= dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
484
  for(int j=i+1;j<nFunctions();j++)
485
486
487
488
489
490
  {
    m_paramOffsets[j] -= dnp;
  }
  m_paramOffsets.erase(m_paramOffsets.begin()+i);

  m_functions.erase(m_functions.begin()+i);
491
492
493
494
  if (del)
  {
    delete fun;
  }
495
496
}

497
/** Replace a function with a new one. The old function is deleted.
498
 *  The new function must have already its workspace set.
499
 * @param f_old :: The pointer to the function to replace. If it's not
500
 *  a member of this composite function nothing happens
501
 * @param f_new :: A pointer to the new function
502
 */
503
void CompositeFunction::replaceFunction(const IFitFunction* f_old,IFitFunction* f_new)
504
{
505
  std::vector<IFitFunction*>::const_iterator it = 
506
507
    std::find(m_functions.begin(),m_functions.end(),f_old);
  if (it == m_functions.end()) return;
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
508
509
  std::vector<IFitFunction*>::difference_type iFun = it - m_functions.begin();
  replaceFunction(static_cast<int>(iFun),f_new);
510
511
}

512
/** Replace a function with a new one. The old function is deleted.
513
514
 * @param i :: The index of the function to replace
 * @param f :: A pointer to the new function
515
 */
516
void CompositeFunction::replaceFunction(int i,IFitFunction* f)
517
518
519
520
{
  if ( i >= nFunctions() )
    throw std::out_of_range("Function index out of range.");

521
  IFitFunction* fun = getFunction(i);
522
523
  int na_old = fun->nActive();
  int np_old = fun->nParams();
524

525
526
  int na_new = f->nActive();
  int np_new = f->nParams();
527
528
529

  // Modify function indeces: The new function may have different number of parameters
  {
530
    std::vector<int>::iterator itFun = std::find(m_IFitFunction.begin(),m_IFitFunction.end(),i);
531
    if(itFun != m_IFitFunction.end()) // functions must have at least 1 parameter
532
    {
533
534
      if (np_old > np_new)
      {
535
        m_IFitFunction.erase(itFun,itFun + np_old - np_new);
536
537
538
      }
      else if (np_old < np_new) 
      {
539
        m_IFitFunction.insert(itFun,np_new - np_old,i);
540
      }
541
    }
542
543
    else if (np_new > 0) // it could happen if the old function is an empty CompositeFunction
    {
544
545
      itFun = std::find_if(m_IFitFunction.begin(),m_IFitFunction.end(),std::bind2nd(std::greater<int>(),i));
      m_IFitFunction.insert(itFun,np_new,i);
546
    }
547
548
549
550
  }

  // Modify function indeces: The new function may have different number of active parameters
  {
551
    std::vector<int>::iterator itFun = std::find(m_IFitFunctionActive.begin(),m_IFitFunctionActive.end(),i);
552
    if (itFun != m_IFitFunctionActive.end())
553
554
555
    {
      if (na_old > na_new)
      {
556
        m_IFitFunctionActive.erase(itFun,itFun + na_old - na_new);
557
558
559
      }
      else if (na_old < na_new) 
      {
560
        m_IFitFunctionActive.insert(itFun,na_new - na_old,i);
561
562
563
564
      }
    }
    else if (na_new > 0)
    {
565
566
      itFun = std::find_if(m_IFitFunctionActive.begin(),m_IFitFunctionActive.end(),std::bind2nd(std::greater<int>(),i));
      m_IFitFunctionActive.insert(itFun,na_new,i);
567
568
569
    }
  }

570
  int dna = na_new - na_old;
571
572
  m_nActive += dna;
  // Recalc the active offsets 
573
  for(int j=i+1;j<nFunctions();j++)
574
575
576
577
  {
    m_activeOffsets[j] += dna;
  }

578
  int dnp = np_new - np_old;
579
580
  m_nParams += dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
581
  for(int j=i+1;j<nFunctions();j++)
582
583
584
585
586
587
588
589
  {
    m_paramOffsets[j] += dnp;
  }

  m_functions[i] = f;
  delete fun;
}

590
/**
591
 * @param i :: The index of the function
592
 * @return function at the requested index
593
 */
594
IFitFunction* CompositeFunction::getFunction(int i)const
595
{
596
  if ( i >= nFunctions()  || i < 0)
597
  {
598
    throw std::out_of_range("Function index out of range.");
599
  }
600
601
602
  return m_functions[i];
}

603
604
/**
 * Get the index of the function to which parameter i belongs
605
 * @param i :: The parameter index
606
 * @return function index of the requested parameter
607
 */
608
int CompositeFunction::functionIndex(int i)const
609
{
610
  if (i >= nParams() || i < 0)
611
  {
612
    throw std::out_of_range("Function parameter index out of range.");
613
  }
614
  return m_IFitFunction[i];
615
616
617
618
}

/**
 * Get the index of the function to which parameter i belongs
619
 * @param i :: The active parameter index
620
 * @return active function index of the requested parameter
621
 */
622
int CompositeFunction::functionIndexActive(int i)const
623
{
624
  if (i >= nParams() || i < 0)
625
    throw std::out_of_range("Function parameter index out of range.");
626
  return m_IFitFunctionActive[i];
627
628
629
}

/**
630
631
632
* @param varName :: The variable name which may contain function index ( [f<index.>]name )
* @param index :: Receives function index or -1 
* @param name :: Receives the parameter name
633
*/
634
void CompositeFunction::parseName(const std::string& varName,int& index, std::string& name)
635
{
636
637
638
639
  size_t i = varName.find('.');
  if (i == std::string::npos)
  {
    name = varName;
640
641
    index = -1;
    return;
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  }
  else
  {
    if (varName[0] != 'f')
      throw std::invalid_argument("External function parameter name must start with 'f'");

    std::string sindex = varName.substr(1,i-1);
    index = boost::lexical_cast<int>(sindex);

    if (i == varName.size() - 1)
      throw std::invalid_argument("Name cannot be empty");

    name = varName.substr(i+1);
  }
656
657
}

658
/** Returns the index of parameter i as it declared in its function
659
 * @param i :: The parameter index
660
661
 * @return The local index of the parameter
 */
662
int CompositeFunction::parameterLocalIndex(int i)const
663
664
665
666
667
{
  int iFun = functionIndex(i);
  return i - m_paramOffsets[iFun];
}

668
/** Returns the name of parameter i as it declared in its function
669
 * @param i :: The parameter index
670
671
 * @return The pure parameter name (without the function identifier f#.)
 */
672
std::string CompositeFunction::parameterLocalName(int i)const
673
674
675
676
677
{
  int iFun = functionIndex(i);
  return m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
}

Janik Zikovsky's avatar
Janik Zikovsky committed
678
679
680
681
682
683
// /** Initialize the function providing it the workspace
// * @param workspace :: The shared pointer to a workspace to which the function will be fitted
// * @param spec :: The number of a spectrum for fitting
// * @param xMin :: The minimum bin index of spectrum spec that will be used in fitting
// * @param xMax :: The maximum bin index of spectrum spec that will be used in fitting
// */
684
685
686
687
688
689
690
691
//void CompositeFunction::setMatrixWorkspace(boost::shared_ptr<const API::MatrixWorkspace> workspace,int spec,int xMin,int xMax)
//{
//  IFitFunction::setMatrixWorkspace(workspace,spec,xMin,xMax);
//  for(int i=0;i<nFunctions();i++)
//  {
//    getFunction(i)->setMatrixWorkspace(workspace,spec,xMin,xMax);
//  }
//}
692

693
/**
694
 * Apply the ties.
695
696
697
 */
void CompositeFunction::applyTies()
{
698
  for(int i=0;i<nFunctions();i++)
699
700
701
702
703
704
705
706
707
708
  {
    getFunction(i)->applyTies();
  }
}

/**
 * Clear the ties. 
 */
void CompositeFunction::clearTies()
{
709
  for(int i=0;i<nFunctions();i++)
710
711
712
713
714
715
  {
    getFunction(i)->clearTies();
  }
}

/** Removes i-th parameter's tie if it is tied or does nothing.
716
 * @param i :: The index of the tied parameter.
717
718
 * @return True if successfull
 */
719
bool CompositeFunction::removeTie(int i)
720
{
721
  int iFun = functionIndex(i);
722
723
724
725
726
727
728
729
730
  bool res = m_functions[ iFun ]->removeTie(i - m_paramOffsets[iFun]);
  if (res)
  {
    m_nActive++;
  }
  return res;
}

/** Get the tie of i-th parameter
731
 * @param i :: The parameter index
732
 * @return A pointer to the tie.
733
 */
734
ParameterTie* CompositeFunction::getTie(int i)const
735
736
737
738
739
740
741
{
  int iFun = functionIndex(i);
  return m_functions[ iFun ]->getTie(i - m_paramOffsets[iFun]);
}

/**
 * Attaches a tie to this function. The attached tie is owned by the function.
742
 * @param tie :: A pointer to a new tie
743
744
745
 */
void CompositeFunction::addTie(ParameterTie* tie)
{
746
  int i = getParameterIndex(*tie);
747
748
749
750
751
752
753
754
755
756
  if (i < 0)
  {
    throw std::logic_error("Trying to use a tie on a parameter not belonging to this function");
  }
  int iFun = functionIndex(i);
  m_functions[iFun]->addTie(tie);
}

/**
 * Declare a new parameter. To used in the implementation'c constructor.
757
758
 * @param name :: The parameter name.
 * @param initValue :: The initial value for the parameter
759
 */
760
void CompositeFunction::declareParameter(const std::string& name, double initValue, const std::string& description)
761
{
762
763
  (void) name; //Avoid compiler warning
  (void) initValue; //Avoid compiler warning
764
  (void) description; //Avoid compiler warning
765
766
767
768
  throw Kernel::Exception::NotImplementedError("CompositeFunction cannot not have its own parameters.");
}

/** Add a constraint
769
 *  @param ic :: Pointer to a constraint.
770
771
772
 */
void CompositeFunction::addConstraint(IConstraint* ic)
{
773
774
775
  int i = getParameterIndex(*ic);
  int iFun = functionIndex(i);
  getFunction(iFun)->addConstraint(ic);
776
777
}

778
779
void CompositeFunction::setParametersToSatisfyConstraints()
{
780
  for(int i=0;i<nFunctions();i++)
781
782
783
784
785
  {
    getFunction(i)->setParametersToSatisfyConstraints();
  }
}

Nick Draper's avatar
re #100    
Nick Draper committed
786
/// Get constraint
787
/// @param i :: the index
Nick Draper's avatar
re #100    
Nick Draper committed
788
/// @return A pointer to the constraint
789
IConstraint* CompositeFunction::getConstraint(int i)const
790
{
791
  int iFun = functionIndex(i);
792
  return m_functions[ iFun ]->getConstraint(i - m_paramOffsets[iFun]);
793
794
}

795
/** Remove a constraint
796
 * @param parName :: The name of a parameter which constarint to remove.
797
798
799
800
801
802
803
804
 */
void CompositeFunction::removeConstraint(const std::string& parName)
{
  int iPar = parameterIndex(parName);
  int iFun = functionIndex(iPar);
  getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
}

805
/** Checks if a constraint has been explicitly set
806
 *  @param i :: The parameter index
807
 *  @return true if the function is explicitly set
808
 */
809
bool CompositeFunction::isExplicitlySet(int i)const
810
{
811
  int iFun = functionIndex(i);
812
813
814
  return m_functions[ iFun ]->isExplicitlySet(i - m_paramOffsets[iFun]);
}

815
816
/**
 * Returns the index of parameter if the ref points to one of the member function or -1
817
 * @param ref :: A reference to a parameter
818
819
 * @return Parameter index or -1
 */
820
int CompositeFunction::getParameterIndex(const ParameterReference& ref)const
821
{
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
822
  if (ref.getFunction() == this && static_cast<int>(ref.getIndex()) < nParams())
823
  {
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
824
    return static_cast<int>(ref.getIndex());
825
  }
826
  for(int iFun=0;iFun<nFunctions();iFun++)
827
  {
828
    int iLocalIndex = getFunction(iFun)->getParameterIndex(ref);
829
830
831
832
833
    if (iLocalIndex >= 0)
    {
      return m_paramOffsets[iFun] + iLocalIndex;
    }
  }
834
835
836
  return -1;
}

837
/**
838
 * @param ref :: The reference
839
840
 * @return A function containing parameter pointed to by ref
 */
841
IFitFunction* CompositeFunction::getContainingFunction(const ParameterReference& ref)const
842
{
Gigg, Martyn Anthony's avatar
Gigg, Martyn Anthony committed
843
  if (ref.getFunction() == this && static_cast<int>(ref.getIndex()) < nParams())
844
845
846
  {
    return ref.getFunction();
  }
847
  for(int iFun=0;iFun<nFunctions();iFun++)
848
  {
849
    IFitFunction* fun = static_cast<IFitFunction*>(getFunction(iFun)->getContainingFunction(ref));
850
851
852
853
854
855
856
    if (fun)
    {
      return getFunction(iFun);
    }
  }
  return NULL;
}
857

858
/**
859
 * @param fun :: The searched function
860
861
 * @return A function containing the argument function fun
 */
862
IFitFunction* CompositeFunction::getContainingFunction(const IFitFunction* fun)
863
864
865
866
867
{
  if (fun == this)
  {
    return this;
  }
868
  for(int iFun=0;iFun<nFunctions();iFun++)
869
  {
870
    IFitFunction* f = static_cast<IFitFunction*>(getFunction(iFun)->getContainingFunction(fun));
871
872
873
874
875
876
877
878
    if (f)
    {
      return getFunction(iFun);
    }
  }
  return NULL;
}

879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
//void CompositeFunction::setWorkspace(boost::shared_ptr<Workspace> ws,const std::string& slicing)
//{
//  IFitFunction::setWorkspace(ws,slicing);
//  for(int iFun=0;iFun<nFunctions();iFun++)
//  {
//    getFunction(iFun)->setUpNewStuff(m_xValues,m_weights);
//  }
//}

//void CompositeFunction::setUpNewStuff(boost::shared_array<double> xs,boost::shared_array<double> weights)
//{
//  IFitFunction::setUpNewStuff(xs,weights);
//  for(int iFun=0;iFun<nFunctions();iFun++)
//  {
//    getFunction(iFun)->setUpNewStuff(xs,weights);
//  }
//}
896

897
898
} // namespace API
} // namespace Mantid