CompositeFunction.cpp 22.3 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
#include "MantidAPI/FunctionFactory.h"
9

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

namespace Mantid
{
namespace API
{

Peterson, Peter's avatar
Peterson, Peter committed
21
22
using std::size_t;

23
DECLARE_FUNCTION(CompositeFunction)
24

25
26
27
28
29
30
31
32
33
34
///Destructor
CompositeFunction::~CompositeFunction()
{
}

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

35
36
37
38
39
40
41
42
43
44
45
/** 
 * 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=(" << ... <<")";
 *   }
46
 * @return the string representation of the composite function
47
 */
48
49
50
std::string CompositeFunction::asString()const
{
  std::ostringstream ostr;
51
52
53
54
55
56
57
  
  // if empty just return function name
  if (nFunctions() == 0)
  {
    return "name=" + name();
  }

58
  if (name() != "CompositeFunction")
59
60
61
  {
    ostr << "composite=" <<name() << ";";
  }
Peterson, Peter's avatar
Peterson, Peter committed
62
  for(size_t i=0;i<nFunctions();i++)
63
  {
64
65
    IFunction_sptr fun = getFunction(i);
    bool isComp = boost::dynamic_pointer_cast<CompositeFunction>(fun) != 0;
66
    if (isComp) ostr << '(';
67
    ostr << fun->asString();
68
    if (isComp) ostr << ')';
69
70
71
72
73
74
    if (i < nFunctions() - 1)
    {
      ostr << ';';
    }
  }
  std::string ties;
75
  for(size_t i=0;i<nParams();i++)
76
77
78
79
  {
    const ParameterTie* tie = getTie(i);
    if (tie)
    {
80
81
      IFunction_sptr fun = getFunction(functionIndex(i));
      std::string tmp = tie->asString(fun.get());
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
      if (tmp.empty())
      {
        tmp = tie->asString(this);
        if (!tmp.empty())
        {
          if (!ties.empty())
          {
            ties += ",";
          }
          ties += tmp;
        }
      }
    }
  }
  if (!ties.empty())
  {
    ostr << ";ties=(" << ties << ")";
99
100
101
102
  }
  return ostr.str();
}

103
104
105
106
107
108
/** Function you want to fit to. 
 *  @param domain :: The buffer for writing the calculated values. Must be big enough to accept dataSize() values
 */
void CompositeFunction::function(const FunctionDomain& domain, FunctionValues& values)const
{
  FunctionValues tmp(domain);
109
  values.zeroCalculated();
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
  {
    m_functions[ iFun ]->function(domain,tmp);
    values += tmp;
  }
}

/**
 * Derivatives of function with respect to active parameters
 * @param domain :: Function domain to get the arguments from.
 * @param jacobian :: A Jacobian to store the derivatives.
 */
void CompositeFunction::functionDeriv(const FunctionDomain& domain, Jacobian& jacobian)
{
  for(size_t iFun = 0; iFun < nFunctions(); ++iFun)
  {
126
    PartialJacobian J(&jacobian,paramOffset(iFun));
127
128
129
130
    getFunction(iFun)->functionDeriv(domain,J);
  }
}

131
/** Sets a new value to the i-th parameter.
132
133
134
 *  @param i :: The parameter index
 *  @param value :: The new value
 *  @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
135
 */
136
void CompositeFunction::setParameter(size_t i, const double& value, bool explicitlySet)
137
{
138
  size_t iFun = functionIndex(i);
139
  m_functions[ iFun ]->setParameter(i - m_paramOffsets[iFun],value,explicitlySet);
140
141
}

142
143
144
145
146
147
/** 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)
{
148
  size_t iFun = functionIndex(i);
149
150
151
  m_functions[ iFun ]->setParameterDescription(i - m_paramOffsets[iFun],description);
}

152
/** Get the i-th parameter.
153
 *  @param i :: The parameter index
154
 *  @return value of the requested parameter
155
 */
156
double CompositeFunction::getParameter(size_t i)const
157
{
Peterson, Peter's avatar
Peterson, Peter committed
158
  size_t iFun = functionIndex(i);
159
  return m_functions[ iFun ]->getParameter(i - m_paramOffsets[iFun]);
160
161
}

162
163
/**
 * Sets a new value to a parameter by name.
164
165
166
 * @param name :: The name of the parameter.
 * @param value :: The new value
 * @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
167
168
 */
void CompositeFunction::setParameter(const std::string& name, const double& value, bool explicitlySet)
169
{
170
  std::string pname;
171
  size_t index;
172
  parseName(name,index,pname);
173
  getFunction(index)->setParameter(pname,value,explicitlySet);
174
175
}

176
177
178
/**
 * Sets a new description to a parameter by name.
 * @param name :: The name of the parameter.
179
 * @param description :: The new description
180
181
182
183
 */
void CompositeFunction::setParameterDescription(const std::string& name, const std::string& description)
{
  std::string pname;
184
  size_t index;
185
  parseName(name,index,pname);
186
  getFunction(index)->setParameterDescription(pname,description);
187
188
}

189
190
/**
 * Parameters by name.
191
 * @param name :: The name of the parameter.
192
 * @return value of the requested named parameter
193
 */
194
195
double CompositeFunction::getParameter(const std::string& name)const
{
196
  std::string pname;
197
  size_t index;
198
  parseName(name,index,pname);
199
  return getFunction(index)->getParameter(pname);
200
201
202
}

/// Total number of parameters
203
size_t CompositeFunction::nParams()const
204
205
206
207
{
  return m_nParams;
}

208
/**
209
 * 
210
 * @param name :: The name of a parameter
211
 * @return index of the requested named parameter
212
 */
213
size_t CompositeFunction::parameterIndex(const std::string& name)const
214
{
215
  std::string pname;
216
  size_t index;
217
  parseName(name,index,pname);
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(size_t i)const
225
{
226
  size_t 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
/// Returns the description of parameter
/// @param i :: The index
/// @return The description of the parameter
std::string CompositeFunction::parameterDescription(size_t i)const
{
237
  size_t iFun = functionIndex(i);
238
239
240
241
242
  std::ostringstream ostr;
  ostr << m_functions[ iFun ]->parameterDescription(i - m_paramOffsets[iFun]);
  return ostr.str();
}

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/** 
 * Get the fitting error for a parameter
 * @param i :: The index of a parameter
 * @return :: the error
 */
double CompositeFunction::getError(size_t i) const
{
  size_t iFun = functionIndex(i);
  return m_functions[ iFun ]->getError(i - m_paramOffsets[iFun]);
}

/** 
 * Set the fitting error for a parameter
 * @param i :: The index of a parameter
 * @param err :: The error value to set
 */
void CompositeFunction::setError(size_t i, double err)
{
  size_t iFun = functionIndex(i);
  m_functions[ iFun ]->setError(i - m_paramOffsets[iFun], err);
}

265
/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
266
double CompositeFunction::activeParameter(size_t i)const
267
{
268
269
  size_t iFun = functionIndex(i);
  return m_functions[ iFun ]->activeParameter(i - m_paramOffsets[iFun]);
270
271
272
}

/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
273
void CompositeFunction::setActiveParameter(size_t i, double value)
274
{
275
276
  size_t iFun = functionIndex(i);
  m_functions[ iFun ]->setActiveParameter(i - m_paramOffsets[iFun],value);
277
278
279
}

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

/// Returns the description of active parameter i
std::string CompositeFunction::descriptionOfActive(size_t i)const
{
291
  size_t iFun = functionIndex(i);
292
  std::ostringstream ostr;
293
  ostr << m_functions[ iFun ]->descriptionOfActive(i - m_paramOffsets[iFun]);
294
  return ostr.str();
295
296
}

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

308
/**
309
 * query to see in the function is active
310
 * @param i :: The index of a declared parameter
311
 * @return true if parameter i is active
312
 */
313
bool CompositeFunction::isFixed(size_t i)const
314
{
315
  size_t iFun = functionIndex(i);
316
  return m_functions[ iFun ]->isFixed(i - m_paramOffsets[iFun]);
317
318
319
}

/**
320
 * @param i :: A declared parameter index to be removed from active
321
 */
322
void CompositeFunction::fix(size_t i)
323
{
324
  size_t iFun = functionIndex(i);
325
326
327
328
329
330
331
  //std::vector<size_t>::iterator ia = std::find(m_IFunctionActive.begin(),m_IFunctionActive.end(),iFun);
  //if (ia == m_IFunctionActive.end())
  //{// isFixed(i) should have returned true
  //  throw std::runtime_error("Inconsistency in CompositeFunction when fixing parameter "+
  //    boost::lexical_cast<std::string>(i));
  //}
  //m_IFunctionActive.erase(ia);
332
  m_functions[ iFun ]->fix(i - m_paramOffsets[iFun]);
333

334
335
336
  //m_nActive--;
  //for(size_t j=iFun+1;j<nFunctions();j++)
  //  m_activeOffsets[j] -= 1;
337
338
}

339
/** Makes a parameter active again. It doesn't change the parameter's tie.
340
 * @param i :: A declared parameter index to be restored to active
341
 */
342
void CompositeFunction::unfix(size_t i)
343
{
344
  size_t iFun = functionIndex(i);
345

346
  //m_IFunctionActive.insert(m_IFunctionActive.begin() + m_activeOffsets[iFun],iFun);
347
  m_functions[ iFun ]->unfix(i - m_paramOffsets[iFun]);
348

349
350
351
  //m_nActive++;
  //for(size_t j=iFun+1;j<nFunctions();j++)
  //  m_activeOffsets[j] += 1;
352
353
}

354
355
356
357
358
/** Makes sure that the function is consistent. 
 */
void CompositeFunction::checkFunction()
{
  m_nParams = 0;
359
  //m_nActive = 0;
360
  m_paramOffsets.clear();
361
  //m_activeOffsets.clear();
362
  m_IFunction.clear();
363
  //m_IFunctionActive.clear();
364

365
  std::vector<IFunction_sptr> functions(m_functions.begin(),m_functions.end());
366
367
  m_functions.clear();

368
  for(std::vector<IFunction_sptr>::size_type i=0;i<functions.size();i++)
369
  {
370
371
    IFunction_sptr f = functions[i];
    CompositeFunction_sptr cf = boost::dynamic_pointer_cast<CompositeFunction>(f);
372
    if (cf) cf->checkFunction();
373
374
375
376
    addFunction(f);
  }
}

377
/** Add a function
378
 * @param f :: A pointer to the added function
379
 * @return The function index
380
 */
381
size_t CompositeFunction::addFunction(IFunction_sptr f)
382
{
383
  m_IFunction.insert(m_IFunction.end(),f->nParams(), m_functions.size());
384
  //m_IFunctionActive.insert(m_IFunctionActive.end(),f->nActive(),m_functions.size());
385
386
387
388
389
  m_functions.push_back(f);
  //?f->init();
  if (m_paramOffsets.size() == 0)
  {
    m_paramOffsets.push_back(0);
390
    //m_activeOffsets.push_back(0);
391
    m_nParams = f->nParams();
392
    //m_nActive = f->nActive();
393
394
395
396
  }
  else
  {
    m_paramOffsets.push_back(m_nParams);
397
    //m_activeOffsets.push_back(m_nActive);
398
    m_nParams += f->nParams();
399
    //m_nActive += f->nActive();
400
  }
401
  return m_functions.size() - 1;
402
403
}

404
/** Remove a function
405
406
 * @param i :: The index of the function to remove
 * @param del :: The deletion flag. If true the function will be deleted otherwise - simply detached
407
 */
408
void CompositeFunction::removeFunction(size_t i)
409
{
410
  if ( i >= nFunctions() )
411
412
    throw std::out_of_range("Function index out of range.");

413
  IFunction_sptr fun = getFunction(i);
414

415
  //size_t dna = fun->nActive();
416
  size_t dnp = fun->nParams();
417

418
  for(size_t j=0;j<nParams();)
419
420
  {
    ParameterTie* tie = getTie(j);
421
    if (tie && tie->findParametersOf(fun.get()))
422
423
424
425
426
427
428
429
430
431
    {
      removeTie(j);
    }
    else
    {
      j++;
    }
  }

  // Shift down the function indeces for parameters
432
  for(std::vector<size_t>::iterator it=m_IFunction.begin();it!=m_IFunction.end();)
433
  {
434

435
436
    if (*it == i)
    {
437
      it = m_IFunction.erase(it);
438
    }
439
    else
440
    {
441
442
443
444
      if (*it > i)
      {
        *it -= 1;
      }
445
      ++it;
446
447
448
449
    }
  }

  // Shift down the function indeces for active parameters
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  //for(std::vector<size_t>::iterator it=m_IFunctionActive.begin();it!=m_IFunctionActive.end();)
  //{
  //  if (*it == i)
  //  {
  //    it = m_IFunctionActive.erase(it);
  //  }
  //  else
  //  {
  //    if (*it > i)
  //    {
  //      *it -= 1;
  //    }
  //    ++it;
  //  }
  //}

  //m_nActive -= dna;
  //// Shift the active offsets down by the number of i-th function's active params
  //for(size_t j=i+1;j<nFunctions();j++)
  //{
  //  m_activeOffsets[j] -= dna;
  //}
  //m_activeOffsets.erase(m_activeOffsets.begin()+i);
473
474
475

  m_nParams -= dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
476
  for(size_t j=i+1;j<nFunctions();j++)
477
478
479
480
481
482
483
484
  {
    m_paramOffsets[j] -= dnp;
  }
  m_paramOffsets.erase(m_paramOffsets.begin()+i);

  m_functions.erase(m_functions.begin()+i);
}

485
/** Replace a function with a new one. The old function is deleted.
486
 *  The new function must have already its workspace set.
487
 * @param f_old :: The pointer to the function to replace. If it's not
488
 *  a member of this composite function nothing happens
489
 * @param f_new :: A pointer to the new function
490
 */
491
void CompositeFunction::replaceFunctionPtr(const IFunction_sptr f_old,IFunction_sptr f_new)
492
{
493
  std::vector<IFunction_sptr>::const_iterator it = 
494
495
    std::find(m_functions.begin(),m_functions.end(),f_old);
  if (it == m_functions.end()) return;
496
  std::vector<IFunction_sptr>::difference_type iFun = it - m_functions.begin();
497
  replaceFunction(iFun,f_new);
498
499
}

500
/** Replace a function with a new one. The old function is deleted.
501
502
 * @param i :: The index of the function to replace
 * @param f :: A pointer to the new function
503
 */
504
void CompositeFunction::replaceFunction(size_t i,IFunction_sptr f)
505
{
506
  if ( i >= nFunctions() )
507
508
    throw std::out_of_range("Function index out of range.");

509
  IFunction_sptr fun = getFunction(i);
510
  //size_t na_old = fun->nActive();
511
  size_t np_old = fun->nParams();
512

513
  //size_t na_new = f->nActive();
514
  size_t np_new = f->nParams();
515
516
517

  // Modify function indeces: The new function may have different number of parameters
  {
518
519
    std::vector<size_t>::iterator itFun = std::find(m_IFunction.begin(),m_IFunction.end(),i);
    if(itFun != m_IFunction.end()) // functions must have at least 1 parameter
520
    {
521
522
      if (np_old > np_new)
      {
523
        m_IFunction.erase(itFun,itFun + np_old - np_new);
524
525
526
      }
      else if (np_old < np_new) 
      {
527
        m_IFunction.insert(itFun,np_new - np_old,i);
528
      }
529
    }
530
531
    else if (np_new > 0) // it could happen if the old function is an empty CompositeFunction
    {
532
533
      itFun = std::find_if(m_IFunction.begin(),m_IFunction.end(),std::bind2nd(std::greater<size_t>(),i));
      m_IFunction.insert(itFun,np_new,i);
534
    }
535
536
537
  }

  // Modify function indeces: The new function may have different number of active parameters
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
  //{
  //  std::vector<size_t>::iterator itFun = std::find(m_IFunctionActive.begin(),m_IFunctionActive.end(),i);
  //  if (itFun != m_IFunctionActive.end())
  //  {
  //    if (na_old > na_new)
  //    {
  //      m_IFunctionActive.erase(itFun,itFun + na_old - na_new);
  //    }
  //    else if (na_old < na_new) 
  //    {
  //      m_IFunctionActive.insert(itFun,na_new - na_old,i);
  //    }
  //  }
  //  else if (na_new > 0)
  //  {
  //    itFun = std::find_if(m_IFunctionActive.begin(),m_IFunctionActive.end(),std::bind2nd(std::greater<size_t>(),i));
  //    m_IFunctionActive.insert(itFun,na_new,i);
  //  }
  //}

  //size_t dna = na_new - na_old;
  //m_nActive += dna;
  //// Recalc the active offsets 
  //for(size_t j=i+1;j<nFunctions();j++)
  //{
  //  m_activeOffsets[j] += dna;
  //}
565

566
  size_t dnp = np_new - np_old;
567
568
  m_nParams += dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
569
  for(size_t j=i+1;j<nFunctions();j++)
570
571
572
573
574
575
576
  {
    m_paramOffsets[j] += dnp;
  }

  m_functions[i] = f;
}

577
/**
578
 * @param i :: The index of the function
579
 * @return function at the requested index
580
 */
581
IFunction_sptr CompositeFunction::getFunction(std::size_t i)const
582
{
Peterson, Peter's avatar
Peterson, Peter committed
583
  if ( i >= nFunctions() )
584
  {
585
    throw std::out_of_range("Function index out of range.");
586
  }
587
588
589
  return m_functions[i];
}

590
591
/**
 * Get the index of the function to which parameter i belongs
592
 * @param i :: The parameter index
593
 * @return function index of the requested parameter
594
 */
595
size_t CompositeFunction::functionIndex(std::size_t i)const
596
{
597
  if( i >= nParams() )
598
  {
599
    throw std::out_of_range("Function parameter index out of range.");
600
  }
601
  return m_IFunction[i];
602
603
604
605
}

/**
 * Get the index of the function to which parameter i belongs
606
 * @param i :: The active parameter index
607
 * @return active function index of the requested parameter
608
 */
609
610
611
612
613
614
//size_t CompositeFunction::functionIndexActive(std::size_t i)const
//{
//  if( i >= nParams() )
//    throw std::out_of_range("Function parameter index out of range.");
//  return m_IFunctionActive[i];
//}
615
616

/**
617
* @param varName :: The variable name which may contain function index ( [f<index.>]name )
618
* @param index :: Receives function index or throws std::invalid_argument
619
* @param name :: Receives the parameter name
620
*/
621
void CompositeFunction::parseName(const std::string& varName,size_t& index, std::string& name)
622
{
623
624
625
  size_t i = varName.find('.');
  if (i == std::string::npos)
  {
626
    throw std::invalid_argument("Parameter " + varName + " not found.");
627
628
629
630
631
632
  }
  else
  {
    if (varName[0] != 'f')
      throw std::invalid_argument("External function parameter name must start with 'f'");

633
    std::string sindex = varName.substr(1,i - 1);
634
635
636
637
638
639
640
    index = boost::lexical_cast<int>(sindex);

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

    name = varName.substr(i+1);
  }
641
642
}

643
/** Returns the index of parameter i as it declared in its function
644
 * @param i :: The parameter index
645
646
 * @return The local index of the parameter
 */
647
size_t CompositeFunction::parameterLocalIndex(size_t i)const
648
{
649
  size_t iFun = functionIndex(i);
650
651
652
  return i - m_paramOffsets[iFun];
}

653
/** Returns the name of parameter i as it declared in its function
654
 * @param i :: The parameter index
655
656
 * @return The pure parameter name (without the function identifier f#.)
 */
657
std::string CompositeFunction::parameterLocalName(size_t i)const
658
{
659
  size_t iFun = functionIndex(i);
660
661
662
  return m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
}

663
/**
664
 * Apply the ties.
665
666
667
 */
void CompositeFunction::applyTies()
{
Peterson, Peter's avatar
Peterson, Peter committed
668
  for(size_t i=0;i<nFunctions();i++)
669
670
671
672
673
674
675
676
677
678
  {
    getFunction(i)->applyTies();
  }
}

/**
 * Clear the ties. 
 */
void CompositeFunction::clearTies()
{
Peterson, Peter's avatar
Peterson, Peter committed
679
  for(size_t i=0;i<nFunctions();i++)
680
681
682
683
684
685
  {
    getFunction(i)->clearTies();
  }
}

/** Removes i-th parameter's tie if it is tied or does nothing.
686
 * @param i :: The index of the tied parameter.
687
688
 * @return True if successfull
 */
689
bool CompositeFunction::removeTie(size_t i)
690
{
691
  size_t iFun = functionIndex(i);
692
  bool res = m_functions[ iFun ]->removeTie(i - m_paramOffsets[iFun]);
693
694
695
696
  //if (res)
  //{
  //  m_nActive++;
  //}
697
698
699
700
  return res;
}

/** Get the tie of i-th parameter
701
 * @param i :: The parameter index
702
 * @return A pointer to the tie.
703
 */
704
ParameterTie* CompositeFunction::getTie(size_t i)const
705
{
706
  size_t iFun = functionIndex(i);
707
708
709
710
711
  return m_functions[ iFun ]->getTie(i - m_paramOffsets[iFun]);
}

/**
 * Attaches a tie to this function. The attached tie is owned by the function.
712
 * @param tie :: A pointer to a new tie
713
714
715
 */
void CompositeFunction::addTie(ParameterTie* tie)
{
716
717
  size_t i = getParameterIndex(*tie);
  size_t iFun = functionIndex(i);
718
719
720
721
722
  m_functions[iFun]->addTie(tie);
}

/**
 * Declare a new parameter. To used in the implementation'c constructor.
723
724
 * @param name :: The parameter name.
 * @param initValue :: The initial value for the parameter
725
 * @param description :: Parameter documentation
726
 */
727
void CompositeFunction::declareParameter(const std::string& name, double initValue, const std::string& description)
728
{
729
730
  (void) name; //Avoid compiler warning
  (void) initValue; //Avoid compiler warning
731
  (void) description; //Avoid compiler warning
732
733
734
735
  throw Kernel::Exception::NotImplementedError("CompositeFunction cannot not have its own parameters.");
}

/** Add a constraint
736
 *  @param ic :: Pointer to a constraint.
737
738
739
 */
void CompositeFunction::addConstraint(IConstraint* ic)
{
740
741
  size_t i = getParameterIndex(*ic);
  size_t iFun = functionIndex(i);
742
  getFunction(iFun)->addConstraint(ic);
743
744
}

745
746
void CompositeFunction::setParametersToSatisfyConstraints()
{
Peterson, Peter's avatar
Peterson, Peter committed
747
  for(size_t i=0;i<nFunctions();i++)
748
749
750
751
752
  {
    getFunction(i)->setParametersToSatisfyConstraints();
  }
}

Nick Draper's avatar
re #100    
Nick Draper committed
753
/// Get constraint
754
/// @param i :: the index
Nick Draper's avatar
re #100    
Nick Draper committed
755
/// @return A pointer to the constraint
756
IConstraint* CompositeFunction::getConstraint(size_t i)const
757
{
758
  size_t iFun = functionIndex(i);
759
  return m_functions[ iFun ]->getConstraint(i - m_paramOffsets[iFun]);
760
761
}

762
/** Remove a constraint
763
 * @param parName :: The name of a parameter which constarint to remove.
764
765
766
 */
void CompositeFunction::removeConstraint(const std::string& parName)
{
767
768
  size_t iPar = parameterIndex(parName);
  size_t iFun = functionIndex(iPar);
769
770
771
  getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
}

772
/** Checks if a constraint has been explicitly set
773
 *  @param i :: The parameter index
774
 *  @return true if the function is explicitly set
775
 */
776
bool CompositeFunction::isExplicitlySet(size_t i)const
777
{
778
  size_t iFun = functionIndex(i);
779
780
781
  return m_functions[ iFun ]->isExplicitlySet(i - m_paramOffsets[iFun]);
}

782
/**
783
 * Returns the index of parameter if the ref points to one of the member function
784
 * @param ref :: A reference to a parameter
785
 * @return Parameter index or number of nParams() if parameter not found
786
 */
787
size_t CompositeFunction::getParameterIndex(const ParameterReference& ref)const
788
{
789
  if (ref.getFunction() == this && ref.getIndex() < nParams())
790
  {
791
    return ref.getIndex();
792
  }
Peterson, Peter's avatar
Peterson, Peter committed
793
  for(size_t iFun=0;iFun<nFunctions();iFun++)
794
  {
795
    IFunction_sptr fun = getFunction(iFun);
796
797
    size_t iLocalIndex = fun->getParameterIndex(ref);
    if (iLocalIndex < fun->nParams())
798
799
800
801
    {
      return m_paramOffsets[iFun] + iLocalIndex;
    }
  }
802
  return nParams();
803
804
}

805
/**
806
 * Returns the shrared pointer to the function conataining a parameter
807
 * @param ref :: The reference
808
809
 * @return A function containing parameter pointed to by ref
 */
810
IFunction_sptr CompositeFunction::getContainingFunction(const ParameterReference& ref)const
811
{
Peterson, Peter's avatar
Peterson, Peter committed
812
  for(size_t iFun=0;iFun<nFunctions();iFun++)
813
  {
814
815
    IFunction_sptr fun = getFunction(iFun);
    if (fun->getParameterIndex(ref) < fun->nParams())
816
    {
817
      return fun;
818
819
    }
  }
820
821
822
  return IFunction_sptr();
}

823
824
} // namespace API
} // namespace Mantid