CompositeFunction.cpp 23.1 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
/// Copy contructor
26
27
28
29
CompositeFunction::CompositeFunction(const CompositeFunction& f):
//m_nActive(f.m_nParams),
m_nParams(f.m_nParams),
m_iConstraintFunction(0)
30
31
{
  m_functions.assign(f.m_functions.begin(),f.m_functions.end());
32
  //m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
33
34
35
36
37
38
  m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
}

///Assignment operator
CompositeFunction& CompositeFunction::operator=(const CompositeFunction& f)
{
39
  //m_nActive = f.m_nActive;
40
41
  m_nParams = f.m_nParams;
  m_functions.assign(f.m_functions.begin(),f.m_functions.end());
42
  //m_activeOffsets.assign(f.m_activeOffsets.begin(),f.m_activeOffsets.end());
43
  m_paramOffsets.assign(f.m_paramOffsets.begin(),f.m_paramOffsets.end());
44
  m_iConstraintFunction = f.m_iConstraintFunction;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  return *this;
}

///Destructor
CompositeFunction::~CompositeFunction()
{
}


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

59
60
61
62
63
64
65
66
67
68
69
/** 
 * 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=(" << ... <<")";
 *   }
70
 * @return the string representation of the composite function
71
 */
72
73
74
std::string CompositeFunction::asString()const
{
  std::ostringstream ostr;
75
  if (name() != "CompositeFunction")
76
77
78
  {
    ostr << "composite=" <<name() << ";";
  }
Peterson, Peter's avatar
Peterson, Peter committed
79
  for(size_t i=0;i<nFunctions();i++)
80
  {
81
82
    IFunction_sptr fun = getFunction(i);
    bool isComp = boost::dynamic_pointer_cast<CompositeFunction>(fun) != 0;
83
    if (isComp) ostr << '(';
84
    ostr << fun->asString();
85
    if (isComp) ostr << ')';
86
87
88
89
90
91
    if (i < nFunctions() - 1)
    {
      ostr << ';';
    }
  }
  std::string ties;
92
  for(size_t i=0;i<nParams();i++)
93
94
95
96
  {
    const ParameterTie* tie = getTie(i);
    if (tie)
    {
97
98
      IFunction_sptr fun = getFunction(functionIndex(i));
      std::string tmp = tie->asString(fun.get());
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
      if (tmp.empty())
      {
        tmp = tie->asString(this);
        if (!tmp.empty())
        {
          if (!ties.empty())
          {
            ties += ",";
          }
          ties += tmp;
        }
      }
    }
  }
  if (!ties.empty())
  {
    ostr << ";ties=(" << ties << ")";
116
117
118
119
  }
  return ostr.str();
}

120
121
122
123
124
125
/** 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);
126
  values.zeroCalculated();
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  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)
  {
143
    PartialJacobian J(&jacobian,paramOffset(iFun));
144
145
146
147
    getFunction(iFun)->functionDeriv(domain,J);
  }
}

148
/** Sets a new value to the i-th parameter.
149
150
151
 *  @param i :: The parameter index
 *  @param value :: The new value
 *  @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
152
 */
153
void CompositeFunction::setParameter(size_t i, const double& value, bool explicitlySet)
154
{
155
  size_t iFun = functionIndex(i);
156
  m_functions[ iFun ]->setParameter(i - m_paramOffsets[iFun],value,explicitlySet);
157
158
}

159
160
161
162
163
164
/** 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)
{
165
  size_t iFun = functionIndex(i);
166
167
168
  m_functions[ iFun ]->setParameterDescription(i - m_paramOffsets[iFun],description);
}

169
/** Get the i-th parameter.
170
 *  @param i :: The parameter index
171
 *  @return value of the requested parameter
172
 */
173
double CompositeFunction::getParameter(size_t i)const
174
{
Peterson, Peter's avatar
Peterson, Peter committed
175
  size_t iFun = functionIndex(i);
176
  return m_functions[ iFun ]->getParameter(i - m_paramOffsets[iFun]);
177
178
}

179
180
/**
 * Sets a new value to a parameter by name.
181
182
183
 * @param name :: The name of the parameter.
 * @param value :: The new value
 * @param explicitlySet :: A boolean falgging the parameter as explicitly set (by user)
184
185
 */
void CompositeFunction::setParameter(const std::string& name, const double& value, bool explicitlySet)
186
{
187
  std::string pname;
188
  size_t index;
189
  parseName(name,index,pname);
190
  getFunction(index)->setParameter(pname,value,explicitlySet);
191
192
}

193
194
195
/**
 * Sets a new description to a parameter by name.
 * @param name :: The name of the parameter.
196
 * @param description :: The new description
197
198
199
200
 */
void CompositeFunction::setParameterDescription(const std::string& name, const std::string& description)
{
  std::string pname;
201
  size_t index;
202
  parseName(name,index,pname);
203
  getFunction(index)->setParameterDescription(pname,description);
204
205
}

206
207
/**
 * Parameters by name.
208
 * @param name :: The name of the parameter.
209
 * @return value of the requested named parameter
210
 */
211
212
double CompositeFunction::getParameter(const std::string& name)const
{
213
  std::string pname;
214
  size_t index;
215
  parseName(name,index,pname);
216
  return getFunction(index)->getParameter(pname);
217
218
219
}

/// Total number of parameters
220
size_t CompositeFunction::nParams()const
221
222
223
224
{
  return m_nParams;
}

225
/**
226
 * 
227
 * @param name :: The name of a parameter
228
 * @return index of the requested named parameter
229
 */
230
size_t CompositeFunction::parameterIndex(const std::string& name)const
231
{
232
  std::string pname;
233
  size_t index;
234
  parseName(name,index,pname);
235
  return getFunction(index)->parameterIndex(pname) + m_paramOffsets[index];
236
237
}

Nick Draper's avatar
re #100    
Nick Draper committed
238
/// Returns the name of parameter
239
/// @param i :: The index
Nick Draper's avatar
re #100    
Nick Draper committed
240
/// @return The name of the parameter
241
std::string CompositeFunction::parameterName(size_t i)const
242
{
243
  size_t iFun = functionIndex(i);
244
245
246
  std::ostringstream ostr;
  ostr << 'f' << iFun << '.' << m_functions[ iFun ]->parameterName(i - m_paramOffsets[iFun]);
  return ostr.str();
247
248
}

249
250
251
252
253
/// Returns the description of parameter
/// @param i :: The index
/// @return The description of the parameter
std::string CompositeFunction::parameterDescription(size_t i)const
{
254
  size_t iFun = functionIndex(i);
255
256
257
258
259
  std::ostringstream ostr;
  ostr << m_functions[ iFun ]->parameterDescription(i - m_paramOffsets[iFun]);
  return ostr.str();
}

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/** 
 * 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);
}

282
/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
283
double CompositeFunction::activeParameter(size_t i)const
284
{
285
286
  size_t iFun = functionIndex(i);
  return m_functions[ iFun ]->activeParameter(i - m_paramOffsets[iFun]);
287
288
289
}

/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
290
void CompositeFunction::setActiveParameter(size_t i, double value)
291
{
292
293
  size_t iFun = functionIndex(i);
  m_functions[ iFun ]->setActiveParameter(i - m_paramOffsets[iFun],value);
294
295
296
}

/// Returns the name of active parameter i
297
std::string CompositeFunction::nameOfActive(size_t i)const
298
{
299
  size_t iFun = functionIndex(i);
300
  std::ostringstream ostr;
301
  ostr << 'f' << iFun << '.' << m_functions[ iFun ]->nameOfActive(i - m_paramOffsets[iFun]);
302
303
304
305
306
307
  return ostr.str();
}

/// Returns the description of active parameter i
std::string CompositeFunction::descriptionOfActive(size_t i)const
{
308
  size_t iFun = functionIndex(i);
309
  std::ostringstream ostr;
310
  ostr << m_functions[ iFun ]->descriptionOfActive(i - m_paramOffsets[iFun]);
311
  return ostr.str();
312
313
}

314
315
316
317
318
319
320
321
322
323
324
/**
 * 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]);
}

325
/**
326
 * query to see in the function is active
327
 * @param i :: The index of a declared parameter
328
 * @return true if parameter i is active
329
 */
330
bool CompositeFunction::isFixed(size_t i)const
331
{
332
  size_t iFun = functionIndex(i);
333
  return m_functions[ iFun ]->isFixed(i - m_paramOffsets[iFun]);
334
335
336
}

/**
337
 * @param i :: A declared parameter index to be removed from active
338
 */
339
void CompositeFunction::fix(size_t i)
340
{
341
  size_t iFun = functionIndex(i);
342
343
344
345
346
347
348
  //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);
349
  m_functions[ iFun ]->fix(i - m_paramOffsets[iFun]);
350

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

356
/** Makes a parameter active again. It doesn't change the parameter's tie.
357
 * @param i :: A declared parameter index to be restored to active
358
 */
359
void CompositeFunction::unfix(size_t i)
360
{
361
  size_t iFun = functionIndex(i);
362

363
  //m_IFunctionActive.insert(m_IFunctionActive.begin() + m_activeOffsets[iFun],iFun);
364
  m_functions[ iFun ]->unfix(i - m_paramOffsets[iFun]);
365

366
367
368
  //m_nActive++;
  //for(size_t j=iFun+1;j<nFunctions();j++)
  //  m_activeOffsets[j] += 1;
369
370
}

371
372
373
374
375
/** Makes sure that the function is consistent. 
 */
void CompositeFunction::checkFunction()
{
  m_nParams = 0;
376
  //m_nActive = 0;
377
  m_paramOffsets.clear();
378
  //m_activeOffsets.clear();
379
  m_IFunction.clear();
380
  //m_IFunctionActive.clear();
381

382
  std::vector<IFunction_sptr> functions(m_functions.begin(),m_functions.end());
383
384
  m_functions.clear();

385
  for(std::vector<IFunction_sptr>::size_type i=0;i<functions.size();i++)
386
  {
387
388
    IFunction_sptr f = functions[i];
    CompositeFunction_sptr cf = boost::dynamic_pointer_cast<CompositeFunction>(f);
389
    if (cf) cf->checkFunction();
390
391
392
393
    addFunction(f);
  }
}

394
/** Add a function
395
 * @param f :: A pointer to the added function
396
 * @return The function index
397
 */
398
size_t CompositeFunction::addFunction(IFunction_sptr f)
399
{
400
  m_IFunction.insert(m_IFunction.end(),f->nParams(), m_functions.size());
401
  //m_IFunctionActive.insert(m_IFunctionActive.end(),f->nActive(),m_functions.size());
402
403
404
405
406
  m_functions.push_back(f);
  //?f->init();
  if (m_paramOffsets.size() == 0)
  {
    m_paramOffsets.push_back(0);
407
    //m_activeOffsets.push_back(0);
408
    m_nParams = f->nParams();
409
    //m_nActive = f->nActive();
410
411
412
413
  }
  else
  {
    m_paramOffsets.push_back(m_nParams);
414
    //m_activeOffsets.push_back(m_nActive);
415
    m_nParams += f->nParams();
416
    //m_nActive += f->nActive();
417
  }
418
  return m_functions.size() - 1;
419
420
}

421
/** Remove a function
422
423
 * @param i :: The index of the function to remove
 * @param del :: The deletion flag. If true the function will be deleted otherwise - simply detached
424
 */
425
void CompositeFunction::removeFunction(size_t i)
426
{
427
  if ( i >= nFunctions() )
428
429
    throw std::out_of_range("Function index out of range.");

430
  IFunction_sptr fun = getFunction(i);
431

432
  //size_t dna = fun->nActive();
433
  size_t dnp = fun->nParams();
434

435
  for(size_t j=0;j<nParams();)
436
437
  {
    ParameterTie* tie = getTie(j);
438
    if (tie && tie->findParametersOf(fun.get()))
439
440
441
442
443
444
445
446
447
448
    {
      removeTie(j);
    }
    else
    {
      j++;
    }
  }

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

452
453
    if (*it == i)
    {
454
      it = m_IFunction.erase(it);
455
    }
456
    else
457
    {
458
459
460
461
      if (*it > i)
      {
        *it -= 1;
      }
462
      ++it;
463
464
465
466
    }
  }

  // Shift down the function indeces for active parameters
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  //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);
490
491
492

  m_nParams -= dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
493
  for(size_t j=i+1;j<nFunctions();j++)
494
495
496
497
498
499
500
501
  {
    m_paramOffsets[j] -= dnp;
  }
  m_paramOffsets.erase(m_paramOffsets.begin()+i);

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

502
/** Replace a function with a new one. The old function is deleted.
503
 *  The new function must have already its workspace set.
504
 * @param f_old :: The pointer to the function to replace. If it's not
505
 *  a member of this composite function nothing happens
506
 * @param f_new :: A pointer to the new function
507
 */
508
void CompositeFunction::replaceFunctionPtr(const IFunction_sptr f_old,IFunction_sptr f_new)
509
{
510
  std::vector<IFunction_sptr>::const_iterator it = 
511
512
    std::find(m_functions.begin(),m_functions.end(),f_old);
  if (it == m_functions.end()) return;
513
  std::vector<IFunction_sptr>::difference_type iFun = it - m_functions.begin();
514
  replaceFunction(iFun,f_new);
515
516
}

517
/** Replace a function with a new one. The old function is deleted.
518
519
 * @param i :: The index of the function to replace
 * @param f :: A pointer to the new function
520
 */
521
void CompositeFunction::replaceFunction(size_t i,IFunction_sptr f)
522
{
523
  if ( i >= nFunctions() )
524
525
    throw std::out_of_range("Function index out of range.");

526
  IFunction_sptr fun = getFunction(i);
527
  //size_t na_old = fun->nActive();
528
  size_t np_old = fun->nParams();
529

530
  //size_t na_new = f->nActive();
531
  size_t np_new = f->nParams();
532
533
534

  // Modify function indeces: The new function may have different number of parameters
  {
535
536
    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
537
    {
538
539
      if (np_old > np_new)
      {
540
        m_IFunction.erase(itFun,itFun + np_old - np_new);
541
542
543
      }
      else if (np_old < np_new) 
      {
544
        m_IFunction.insert(itFun,np_new - np_old,i);
545
      }
546
    }
547
548
    else if (np_new > 0) // it could happen if the old function is an empty CompositeFunction
    {
549
550
      itFun = std::find_if(m_IFunction.begin(),m_IFunction.end(),std::bind2nd(std::greater<size_t>(),i));
      m_IFunction.insert(itFun,np_new,i);
551
    }
552
553
554
  }

  // Modify function indeces: The new function may have different number of active parameters
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
  //{
  //  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;
  //}
582

583
  size_t dnp = np_new - np_old;
584
585
  m_nParams += dnp;
  // Shift the parameter offsets down by the total number of i-th function's params
586
  for(size_t j=i+1;j<nFunctions();j++)
587
588
589
590
591
592
593
  {
    m_paramOffsets[j] += dnp;
  }

  m_functions[i] = f;
}

594
/**
595
 * @param i :: The index of the function
596
 * @return function at the requested index
597
 */
598
IFunction_sptr CompositeFunction::getFunction(std::size_t i)const
599
{
Peterson, Peter's avatar
Peterson, Peter committed
600
  if ( i >= nFunctions() )
601
  {
602
    throw std::out_of_range("Function index out of range.");
603
  }
604
605
606
  return m_functions[i];
}

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

/**
 * Get the index of the function to which parameter i belongs
623
 * @param i :: The active parameter index
624
 * @return active function index of the requested parameter
625
 */
626
627
628
629
630
631
//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];
//}
632
633

/**
634
* @param varName :: The variable name which may contain function index ( [f<index.>]name )
635
* @param index :: Receives function index or throws std::invalid_argument
636
* @param name :: Receives the parameter name
637
*/
638
void CompositeFunction::parseName(const std::string& varName,size_t& index, std::string& name)
639
{
640
641
642
  size_t i = varName.find('.');
  if (i == std::string::npos)
  {
643
    throw std::invalid_argument("Parameter " + varName + " not found.");
644
645
646
647
648
649
  }
  else
  {
    if (varName[0] != 'f')
      throw std::invalid_argument("External function parameter name must start with 'f'");

650
    std::string sindex = varName.substr(1,i - 1);
651
652
653
654
655
656
657
    index = boost::lexical_cast<int>(sindex);

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

    name = varName.substr(i+1);
  }
658
659
}

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

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

680
/**
681
 * Apply the ties.
682
683
684
 */
void CompositeFunction::applyTies()
{
Peterson, Peter's avatar
Peterson, Peter committed
685
  for(size_t i=0;i<nFunctions();i++)
686
687
688
689
690
691
692
693
694
695
  {
    getFunction(i)->applyTies();
  }
}

/**
 * Clear the ties. 
 */
void CompositeFunction::clearTies()
{
Peterson, Peter's avatar
Peterson, Peter committed
696
  for(size_t i=0;i<nFunctions();i++)
697
698
699
700
701
702
  {
    getFunction(i)->clearTies();
  }
}

/** Removes i-th parameter's tie if it is tied or does nothing.
703
 * @param i :: The index of the tied parameter.
704
705
 * @return True if successfull
 */
706
bool CompositeFunction::removeTie(size_t i)
707
{
708
  size_t iFun = functionIndex(i);
709
  bool res = m_functions[ iFun ]->removeTie(i - m_paramOffsets[iFun]);
710
711
712
713
  //if (res)
  //{
  //  m_nActive++;
  //}
714
715
716
717
  return res;
}

/** Get the tie of i-th parameter
718
 * @param i :: The parameter index
719
 * @return A pointer to the tie.
720
 */
721
ParameterTie* CompositeFunction::getTie(size_t i)const
722
{
723
  size_t iFun = functionIndex(i);
724
725
726
727
728
  return m_functions[ iFun ]->getTie(i - m_paramOffsets[iFun]);
}

/**
 * Attaches a tie to this function. The attached tie is owned by the function.
729
 * @param tie :: A pointer to a new tie
730
731
732
 */
void CompositeFunction::addTie(ParameterTie* tie)
{
733
734
  size_t i = getParameterIndex(*tie);
  size_t iFun = functionIndex(i);
735
736
737
738
739
  m_functions[iFun]->addTie(tie);
}

/**
 * Declare a new parameter. To used in the implementation'c constructor.
740
741
 * @param name :: The parameter name.
 * @param initValue :: The initial value for the parameter
742
 * @param description :: Parameter documentation
743
 */
744
void CompositeFunction::declareParameter(const std::string& name, double initValue, const std::string& description)
745
{
746
747
  (void) name; //Avoid compiler warning
  (void) initValue; //Avoid compiler warning
748
  (void) description; //Avoid compiler warning
749
750
751
752
  throw Kernel::Exception::NotImplementedError("CompositeFunction cannot not have its own parameters.");
}

/** Add a constraint
753
 *  @param ic :: Pointer to a constraint.
754
755
756
 */
void CompositeFunction::addConstraint(IConstraint* ic)
{
757
758
  size_t i = getParameterIndex(*ic);
  size_t iFun = functionIndex(i);
759
  getFunction(iFun)->addConstraint(ic);
760
761
}

762
763
void CompositeFunction::setParametersToSatisfyConstraints()
{
Peterson, Peter's avatar
Peterson, Peter committed
764
  for(size_t i=0;i<nFunctions();i++)
765
766
767
768
769
  {
    getFunction(i)->setParametersToSatisfyConstraints();
  }
}

Nick Draper's avatar
re #100    
Nick Draper committed
770
/// Get constraint
771
/// @param i :: the index
Nick Draper's avatar
re #100    
Nick Draper committed
772
/// @return A pointer to the constraint
773
IConstraint* CompositeFunction::getConstraint(size_t i)const
774
{
775
  size_t iFun = functionIndex(i);
776
  return m_functions[ iFun ]->getConstraint(i - m_paramOffsets[iFun]);
777
778
}

779
/** Remove a constraint
780
 * @param parName :: The name of a parameter which constarint to remove.
781
782
783
 */
void CompositeFunction::removeConstraint(const std::string& parName)
{
784
785
  size_t iPar = parameterIndex(parName);
  size_t iFun = functionIndex(iPar);
786
787
788
  getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
}

789
/** Checks if a constraint has been explicitly set
790
 *  @param i :: The parameter index
791
 *  @return true if the function is explicitly set
792
 */
793
bool CompositeFunction::isExplicitlySet(size_t i)const
794
{
795
  size_t iFun = functionIndex(i);
796
797
798
  return m_functions[ iFun ]->isExplicitlySet(i - m_paramOffsets[iFun]);
}

799
/**
800
 * Returns the index of parameter if the ref points to one of the member function
801
 * @param ref :: A reference to a parameter
802
 * @return Parameter index or number of nParams() if parameter not found
803
 */
804
size_t CompositeFunction::getParameterIndex(const ParameterReference& ref)const
805
{
806
  if (ref.getFunction() == this && ref.getIndex() < nParams())
807
  {
808
    return ref.getIndex();
809
  }
Peterson, Peter's avatar
Peterson, Peter committed
810
  for(size_t iFun=0;iFun<nFunctions();iFun++)
811
  {
812
    IFunction_sptr fun = getFunction(iFun);
813
814
    size_t iLocalIndex = fun->getParameterIndex(ref);
    if (iLocalIndex < fun->nParams())
815
816
817
818
    {
      return m_paramOffsets[iFun] + iLocalIndex;
    }
  }
819
  return nParams();
820
821
}

822
/**
823
 * Returns the shrared pointer to the function conataining a parameter
824
 * @param ref :: The reference
825
826
 * @return A function containing parameter pointed to by ref
 */
827
IFunction_sptr CompositeFunction::getContainingFunction(const ParameterReference& ref)const
828
{
Peterson, Peter's avatar
Peterson, Peter committed
829
  for(size_t iFun=0;iFun<nFunctions();iFun++)
830
  {
831
832
    IFunction_sptr fun = getFunction(iFun);
    if (fun->getParameterIndex(ref) < fun->nParams())
833
    {
834
      return fun;
835
836
    }
  }
837
838
839
  return IFunction_sptr();
}

840
841
} // namespace API
} // namespace Mantid