1 /*
2 * parameter.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #ifndef PARAMETER_H_
24 #define PARAMETER_H_
25
26 // C++ includes:
27 #include <limits>
28 #include <cmath>
29
30 // Includes from nestkernel:
31 #include "nest_names.h"
32 #include "nest_types.h"
33 #include "nestmodule.h"
34 #include "node_collection.h"
35 #include "random_generators.h"
36
37 // Includes from libnestutil:
38 #include "dictutils.h"
39
40 namespace nest
41 {
42
43 class AbstractLayer;
44
45 /**
46 * Abstract base class for parameters.
47 */
48 class Parameter
49 {
50 public:
51 /**
52 * Creates a Parameter, with optionally specified attributes.
53 * @param is_spatial true if the Parameter contains spatial elements
54 * @param returns_int_only true if the value of the parameter can only be an integer
55 */
56 Parameter( bool is_spatial = false, bool returns_int_only = false )
is_spatial_(is_spatial)57 : is_spatial_( is_spatial )
58 , returns_int_only_( returns_int_only )
59 {
60 }
61
62 /**
63 * Copy constructor
64 */
65 Parameter( const Parameter& p ) = default;
66
67 /**
68 * Virtual destructor
69 */
70 virtual ~Parameter() = default;
71
72 /**
73 * Generates a value based on parameter specifications and arguments.
74 * Used when getting a parameter value based on random values or node attributes,
75 * like position. Note that not all parameters support all overloaded versions.
76 * @param rng pointer to the random number generator
77 * @param node pointer to the node, used when the node position is relevant
78 * @returns the value of the parameter.
79 */
80 virtual double value( RngPtr rng, Node* node ) = 0;
81
82 /**
83 * Generates a value based on parameter specifications and arguments.
84 * Used when connecting spatial nodes. Note that not all parameters
85 * support all overloaded versions.
86 * @param rng pointer to the random number generator
87 * @param source_pos position of the source node
88 * @param target_pos position of the target node
89 * @param layer spatial layer
90 * @param node target node, required for normal and lognormal parameters
91 * @returns the value of the parameter.
92 */
93 virtual double value( RngPtr rng,
94 const std::vector< double >& source_pos,
95 const std::vector< double >& target_pos,
96 const AbstractLayer& layer,
97 Node* node );
98
99 /**
100 * Applies a parameter on a single-node ID NodeCollection and given array of positions.
101 * @returns array of result values, one per position in the TokenArray.
102 */
103 std::vector< double > apply( const NodeCollectionPTR&, const TokenArray& );
104
105 /**
106 * Check if the Parameter is based on spatial properties.
107 * @returns true if the Parameter is based on spatial properties, false otherwise.
108 */
109 bool is_spatial() const;
110
111 /**
112 * Check if the Parameter only returns integer values.
113 * @returns true if the Parameter only returns integers, false otherwise.
114 */
115 bool returns_int_only() const;
116
117 protected:
118 bool is_spatial_{ false };
119 bool returns_int_only_{ false };
120
121 bool value_is_integer_( const double value ) const;
122 };
123
124 /**
125 * Parameter with constant value.
126 */
127 class ConstantParameter : public Parameter
128 {
129 public:
130 using Parameter::value;
131
132 /**
133 * Creates a ConstantParameter with a specified value.
134 * @param value parameter value
135 */
ConstantParameter(double value)136 ConstantParameter( double value )
137 : value_( value )
138 {
139 }
140
141 /**
142 * Creates a ConstantParameter with the value specified in a dictionary.
143 * @param d dictionary with the parameter value
144 *
145 * The dictionary must include the following entry:
146 * value - constant value of this parameter
147 */
ConstantParameter(const DictionaryDatum & d)148 ConstantParameter( const DictionaryDatum& d )
149 {
150 value_ = getValue< double >( d, "value" );
151 returns_int_only_ = value_is_integer_( value_ );
152 }
153
154 ~ConstantParameter() override = default;
155
156 /**
157 * @returns the constant value of this parameter.
158 */
159 double
value(RngPtr,Node *)160 value( RngPtr, Node* ) override
161 {
162 return value_;
163 }
164
165 private:
166 double value_;
167 };
168
169
170 /**
171 * Random parameter with uniform distribution in [min,max).
172 */
173 class UniformParameter : public Parameter
174 {
175 public:
176 using Parameter::value;
177
178 /**
179 * Creates a UniformParameter with specifications specified in a dictionary.
180 * @param d dictionary with parameter specifications
181 *
182 * The dictionary can include the following entries:
183 * min - minimum value
184 * max - maximum value
185 */
UniformParameter(const DictionaryDatum & d)186 UniformParameter( const DictionaryDatum& d )
187 : lower_( 0.0 )
188 , range_( 1.0 )
189 {
190 updateValue< double >( d, names::min, lower_ );
191 updateValue< double >( d, names::max, range_ );
192 if ( lower_ >= range_ )
193 {
194 throw BadProperty(
195 "nest::UniformParameter: "
196 "min < max required." );
197 }
198
199 range_ -= lower_;
200 }
201
202 double
value(RngPtr rng,Node *)203 value( RngPtr rng, Node* ) override
204 {
205 return lower_ + rng->drand() * range_;
206 }
207
208 private:
209 double lower_, range_;
210 };
211
212 /**
213 * Random parameter with uniform distribution in [0,max), yielding integer values.
214 */
215 class UniformIntParameter : public Parameter
216 {
217 public:
218 using Parameter::value;
219
220 /**
221 * Creates a UniformIntParameter with specifications specified in a dictionary.
222 * @param d dictionary with parameter specifications
223 *
224 * The dictionary can include the following entries:
225 * max - maximum value
226 */
UniformIntParameter(const DictionaryDatum & d)227 UniformIntParameter( const DictionaryDatum& d )
228 : Parameter( false, true )
229 , max_( 1.0 )
230 {
231 updateValue< long >( d, names::max, max_ );
232 if ( max_ <= 0 )
233 {
234 throw BadProperty( "nest::UniformIntParameter: max > 0 required." );
235 }
236 }
237
238 double
value(RngPtr rng,Node *)239 value( RngPtr rng, Node* ) override
240 {
241 return rng->ulrand( max_ );
242 }
243
244 private:
245 double max_;
246 };
247
248
249 /**
250 * Random parameter with normal distribution.
251 */
252 class NormalParameter : public Parameter
253 {
254 public:
255 using Parameter::value;
256
257 /**
258 * Creates a NormalParameter with specifications specified in a dictionary.
259 * @param d dictionary with parameter specifications
260 *
261 * The dictionary can include the following entries:
262 * mean - mean value
263 * std - standard deviation
264 */
265 NormalParameter( const DictionaryDatum& d );
266
267 double value( RngPtr rng, Node* node ) override;
268
269 private:
270 double mean_, std_;
271 std::vector< normal_distribution > normal_dists_;
272 };
273
274
275 /**
276 * Random parameter with lognormal distribution.
277 */
278 class LognormalParameter : public Parameter
279 {
280 public:
281 using Parameter::value;
282
283 /**
284 * Creates a LognormalParameter with specifications specified in a dictionary.
285 * @param d dictionary with parameter specifications
286 *
287 * The dictionary can include the following entries:
288 * mean - mean value of logarithm
289 * sigma - standard distribution of logarithm
290 */
291 LognormalParameter( const DictionaryDatum& d );
292
293 double value( RngPtr rng, Node* node ) override;
294
295 private:
296 double mean_, std_;
297 std::vector< lognormal_distribution > lognormal_dists_;
298 };
299
300
301 /**
302 * Random parameter with exponential distribution.
303 */
304 class ExponentialParameter : public Parameter
305 {
306 public:
307 using Parameter::value;
308
309 /**
310 * Creates a ExponentialParameter with specifications specified in a dictionary.
311 * @param d dictionary with parameter specifications
312 *
313 * The dictionary can include the following entries:
314 * beta - the scale parameter
315 */
ExponentialParameter(const DictionaryDatum & d)316 ExponentialParameter( const DictionaryDatum& d )
317 : beta_( 1.0 )
318 {
319 updateValue< double >( d, names::beta, beta_ );
320 }
321
322 double
value(RngPtr rng,Node *)323 value( RngPtr rng, Node* ) override
324 {
325 return beta_ * ( -std::log( 1 - rng->drand() ) );
326 }
327
328 private:
329 double beta_;
330 };
331
332
333 /**
334 * Node position parameter.
335 */
336 class NodePosParameter : public Parameter
337 {
338 public:
339 /**
340 * Creates a NodePosParameter with specifications specified in a dictionary.
341 * @param d dictionary with parameter specifications
342 *
343 * The dictionary can include the following entries:
344 * dimension - Dimension from which to get the position value of the node.
345 * 0: x, 1: y, 2: z.
346 * synaptic_endpoint - If specified, specifies if the position should be taken
347 * from the presynaptic or postsynaptic node in a connection.
348 * 0: unspecified, 1: presynaptic, 2: postsynaptic.
349 */
NodePosParameter(const DictionaryDatum & d)350 NodePosParameter( const DictionaryDatum& d )
351 : Parameter( true )
352 , dimension_( 0 )
353 , synaptic_endpoint_( 0 )
354 {
355 bool dimension_specified = updateValue< long >( d, names::dimension, dimension_ );
356 if ( not dimension_specified )
357 {
358 throw BadParameterValue( "Dimension must be specified when creating a node position parameter." );
359 }
360 if ( dimension_ < 0 )
361 {
362 throw BadParameterValue( "Node position parameter dimension cannot be negative." );
363 }
364 updateValue< long >( d, names::synaptic_endpoint, synaptic_endpoint_ );
365 if ( synaptic_endpoint_ < 0 or 2 < synaptic_endpoint_ )
366 {
367 throw BadParameterValue( "Synaptic endpoint must either be unspecified (0), source (1) or target (2)." );
368 }
369 }
370
371 double
value(RngPtr,Node * node)372 value( RngPtr, Node* node ) override
373 {
374 if ( synaptic_endpoint_ != 0 )
375 {
376 throw BadParameterValue( "Source or target position parameter can only be used when connecting." );
377 }
378 if ( node == nullptr )
379 {
380 throw KernelException( "Node position parameter can only be used when connecting spatially distributed nodes." );
381 }
382 return get_node_pos_( node );
383 }
384
385 double
value(RngPtr,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer &,Node *)386 value( RngPtr,
387 const std::vector< double >& source_pos,
388 const std::vector< double >& target_pos,
389 const AbstractLayer&,
390 Node* ) override
391 {
392 switch ( synaptic_endpoint_ )
393 {
394 case 0:
395 throw BadParameterValue( "Node position parameter cannot be used when connecting." );
396 case 1:
397 {
398 return source_pos[ dimension_ ];
399 }
400 case 2:
401 return target_pos[ dimension_ ];
402 }
403 throw KernelException( "Wrong synaptic_endpoint_." );
404 }
405
406 private:
407 int dimension_;
408 int synaptic_endpoint_;
409
410 double get_node_pos_( Node* node ) const;
411 };
412
413
414 /**
415 * Parameter representing the spatial distance between two nodes, optionally in a specific dimension.
416 */
417 class SpatialDistanceParameter : public Parameter
418 {
419 public:
SpatialDistanceParameter(const DictionaryDatum & d)420 SpatialDistanceParameter( const DictionaryDatum& d )
421 : Parameter( true )
422 , dimension_( 0 )
423 {
424 updateValue< long >( d, names::dimension, dimension_ );
425 if ( dimension_ < 0 )
426 {
427 throw BadParameterValue( "Spatial distance parameter dimension cannot be negative." );
428 }
429 }
430
431 double
value(RngPtr,Node *)432 value( RngPtr, Node* ) override
433 {
434 throw BadParameterValue( "Spatial distance parameter can only be used when connecting." );
435 }
436
437 double value( RngPtr rng,
438 const std::vector< double >& source_pos,
439 const std::vector< double >& target_pos,
440 const AbstractLayer& layer,
441 Node* ) override;
442
443 private:
444 int dimension_;
445 };
446
447
448 /**
449 * Parameter class representing the product of two parameters.
450 */
451 class ProductParameter : public Parameter
452 {
453 public:
454 /**
455 * Construct the product of the two given parameters. Copies are made
456 * of the supplied Parameter objects.
457 */
ProductParameter(const std::shared_ptr<Parameter> m1,const std::shared_ptr<Parameter> m2)458 ProductParameter( const std::shared_ptr< Parameter > m1, const std::shared_ptr< Parameter > m2 )
459 : Parameter( m1->is_spatial() or m2->is_spatial(), m1->returns_int_only() and m2->returns_int_only() )
460 , parameter1_( m1 )
461 , parameter2_( m2 )
462 {
463 }
464
465 /**
466 * Copy constructor.
467 */
ProductParameter(const ProductParameter & p)468 ProductParameter( const ProductParameter& p )
469 : Parameter( p )
470 , parameter1_( p.parameter1_ )
471 , parameter2_( p.parameter2_ )
472 {
473 }
474
475 /**
476 * @returns the value of the product.
477 */
478 double
value(RngPtr rng,Node * node)479 value( RngPtr rng, Node* node ) override
480 {
481 return parameter1_->value( rng, node ) * parameter2_->value( rng, node );
482 }
483
484 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)485 value( RngPtr rng,
486 const std::vector< double >& source_pos,
487 const std::vector< double >& target_pos,
488 const AbstractLayer& layer,
489 Node* node ) override
490 {
491 return parameter1_->value( rng, source_pos, target_pos, layer, node )
492 * parameter2_->value( rng, source_pos, target_pos, layer, node );
493 }
494
495 protected:
496 std::shared_ptr< Parameter > const parameter1_;
497 std::shared_ptr< Parameter > const parameter2_;
498 };
499
500 /**
501 * Parameter class representing the quotient of two parameters.
502 */
503 class QuotientParameter : public Parameter
504 {
505 public:
506 /**
507 * Construct the quotient of two given parameters. Copies are made
508 * of the supplied Parameter objects.
509 */
QuotientParameter(std::shared_ptr<Parameter> m1,std::shared_ptr<Parameter> m2)510 QuotientParameter( std::shared_ptr< Parameter > m1, std::shared_ptr< Parameter > m2 )
511 : Parameter( m1->is_spatial() or m2->is_spatial(), m1->returns_int_only() and m2->returns_int_only() )
512 , parameter1_( m1 )
513 , parameter2_( m2 )
514 {
515 }
516
517 /**
518 * Copy constructor.
519 */
QuotientParameter(const QuotientParameter & p)520 QuotientParameter( const QuotientParameter& p )
521 : Parameter( p )
522 , parameter1_( p.parameter1_ )
523 , parameter2_( p.parameter2_ )
524 {
525 }
526
527 /**
528 * @returns the value of the product.
529 */
530 double
value(RngPtr rng,Node * node)531 value( RngPtr rng, Node* node ) override
532 {
533 return parameter1_->value( rng, node ) / parameter2_->value( rng, node );
534 }
535
536 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)537 value( RngPtr rng,
538 const std::vector< double >& source_pos,
539 const std::vector< double >& target_pos,
540 const AbstractLayer& layer,
541 Node* node ) override
542 {
543 return parameter1_->value( rng, source_pos, target_pos, layer, node )
544 / parameter2_->value( rng, source_pos, target_pos, layer, node );
545 }
546
547 protected:
548 std::shared_ptr< Parameter > const parameter1_;
549 std::shared_ptr< Parameter > const parameter2_;
550 };
551
552 /**
553 * Parameter class representing the sum of two parameters
554 */
555 class SumParameter : public Parameter
556 {
557 public:
558 /**
559 * Construct the sum of two given parameters. Copies are made
560 * of the supplied Parameter objects.
561 */
SumParameter(std::shared_ptr<Parameter> m1,std::shared_ptr<Parameter> m2)562 SumParameter( std::shared_ptr< Parameter > m1, std::shared_ptr< Parameter > m2 )
563 : Parameter( m1->is_spatial() or m2->is_spatial(), m1->returns_int_only() and m2->returns_int_only() )
564 , parameter1_( m1 )
565 , parameter2_( m2 )
566 {
567 }
568
569 /**
570 * Copy constructor.
571 */
SumParameter(const SumParameter & p)572 SumParameter( const SumParameter& p )
573 : Parameter( p )
574 , parameter1_( p.parameter1_ )
575 , parameter2_( p.parameter2_ )
576 {
577 }
578
579 /**
580 * @returns the value of the sum.
581 */
582 double
value(RngPtr rng,Node * node)583 value( RngPtr rng, Node* node ) override
584 {
585 return parameter1_->value( rng, node ) + parameter2_->value( rng, node );
586 }
587
588 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)589 value( RngPtr rng,
590 const std::vector< double >& source_pos,
591 const std::vector< double >& target_pos,
592 const AbstractLayer& layer,
593 Node* node ) override
594 {
595 return parameter1_->value( rng, source_pos, target_pos, layer, node )
596 + parameter2_->value( rng, source_pos, target_pos, layer, node );
597 }
598
599 protected:
600 std::shared_ptr< Parameter > const parameter1_;
601 std::shared_ptr< Parameter > const parameter2_;
602 };
603
604 /**
605 * Parameter class representing the difference of two parameters
606 */
607 class DifferenceParameter : public Parameter
608 {
609 public:
610 /**
611 * Construct the difference of two given parameters. Copies are made
612 * of the supplied Parameter objects.
613 */
DifferenceParameter(std::shared_ptr<Parameter> m1,std::shared_ptr<Parameter> m2)614 DifferenceParameter( std::shared_ptr< Parameter > m1, std::shared_ptr< Parameter > m2 )
615 : Parameter( m1->is_spatial() or m2->is_spatial(), m1->returns_int_only() and m2->returns_int_only() )
616 , parameter1_( m1 )
617 , parameter2_( m2 )
618 {
619 }
620
621 /**
622 * Copy constructor.
623 */
DifferenceParameter(const DifferenceParameter & p)624 DifferenceParameter( const DifferenceParameter& p )
625 : Parameter( p )
626 , parameter1_( p.parameter1_ )
627 , parameter2_( p.parameter2_ )
628 {
629 }
630
631 /**
632 * @returns the value of the difference.
633 */
634 double
value(RngPtr rng,Node * node)635 value( RngPtr rng, Node* node ) override
636 {
637 return parameter1_->value( rng, node ) - parameter2_->value( rng, node );
638 }
639
640 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)641 value( RngPtr rng,
642 const std::vector< double >& source_pos,
643 const std::vector< double >& target_pos,
644 const AbstractLayer& layer,
645 Node* node ) override
646 {
647 return parameter1_->value( rng, source_pos, target_pos, layer, node )
648 - parameter2_->value( rng, source_pos, target_pos, layer, node );
649 }
650
651 protected:
652 std::shared_ptr< Parameter > const parameter1_;
653 std::shared_ptr< Parameter > const parameter2_;
654 };
655
656 /**
657 * Parameter class representing the comparison of two parameters.
658 */
659 class ComparingParameter : public Parameter
660 {
661 public:
662 /**
663 * Construct the comparison of the two given parameters. Copies are made
664 * of the supplied Parameter objects.
665 *
666 * comparator - Operator to use as a comparator.
667 * 0: <
668 * 2: <=
669 * 4: ==
670 * 5: !=
671 * 3: >=
672 * 1: >
673 *
674 */
ComparingParameter(std::shared_ptr<Parameter> m1,std::shared_ptr<Parameter> m2,const DictionaryDatum & d)675 ComparingParameter( std::shared_ptr< Parameter > m1, std::shared_ptr< Parameter > m2, const DictionaryDatum& d )
676 : Parameter( m1->is_spatial() or m2->is_spatial(), true )
677 , parameter1_( m1 )
678 , parameter2_( m2 )
679 , comparator_( -1 )
680 {
681 if ( not updateValue< long >( d, names::comparator, comparator_ ) )
682 {
683 throw BadParameter( "A comparator has to be specified." );
684 }
685 if ( comparator_ < 0 or 5 < comparator_ )
686 {
687 throw BadParameter( "Comparator specification has to be in the range 0-5." );
688 }
689 }
690
691 /**
692 * Copy constructor.
693 */
ComparingParameter(const ComparingParameter & p)694 ComparingParameter( const ComparingParameter& p )
695 : Parameter( p )
696 , parameter1_( p.parameter1_ )
697 , parameter2_( p.parameter2_ )
698 , comparator_( p.comparator_ )
699 {
700 }
701
702 /**
703 * @returns the result of the comparison, bool given as a double.
704 */
705 double
value(RngPtr rng,Node * node)706 value( RngPtr rng, Node* node ) override
707 {
708 return compare_( parameter1_->value( rng, node ), parameter2_->value( rng, node ) );
709 }
710
711 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)712 value( RngPtr rng,
713 const std::vector< double >& source_pos,
714 const std::vector< double >& target_pos,
715 const AbstractLayer& layer,
716 Node* node ) override
717 {
718 return compare_( parameter1_->value( rng, source_pos, target_pos, layer, node ),
719 parameter2_->value( rng, source_pos, target_pos, layer, node ) );
720 }
721
722 protected:
723 std::shared_ptr< Parameter > const parameter1_;
724 std::shared_ptr< Parameter > const parameter2_;
725
726 private:
727 bool
compare_(double value_a,double value_b)728 compare_( double value_a, double value_b ) const
729 {
730 switch ( comparator_ )
731 {
732 case 0:
733 return value_a < value_b;
734 case 1:
735 return value_a <= value_b;
736 case 2:
737 return value_a == value_b;
738 case 3:
739 return value_a != value_b;
740 case 4:
741 return value_a >= value_b;
742 case 5:
743 return value_a > value_b;
744 }
745 throw KernelException( "Wrong comparison operator." );
746 }
747
748 int comparator_;
749 };
750
751
752 /**
753 * Parameter class choosing a value based on a comparing parameter.
754 */
755 class ConditionalParameter : public Parameter
756 {
757 public:
758 /**
759 * Construct the choice of two given parameters, based on a third.
760 * Copies are made of the supplied Parameter objects.
761 */
ConditionalParameter(std::shared_ptr<Parameter> condition,std::shared_ptr<Parameter> if_true,std::shared_ptr<Parameter> if_false)762 ConditionalParameter( std::shared_ptr< Parameter > condition,
763 std::shared_ptr< Parameter > if_true,
764 std::shared_ptr< Parameter > if_false )
765 : Parameter( condition->is_spatial() or if_true->is_spatial() or if_false->is_spatial(),
766 if_true->returns_int_only() and if_false->returns_int_only() )
767 , condition_( condition )
768 , if_true_( if_true )
769 , if_false_( if_false )
770 {
771 }
772
773 /**
774 * Copy constructor.
775 */
ConditionalParameter(const ConditionalParameter & p)776 ConditionalParameter( const ConditionalParameter& p )
777 : Parameter( p )
778 , condition_( p.condition_ )
779 , if_true_( p.if_true_ )
780 , if_false_( p.if_false_ )
781 {
782 }
783
784 /**
785 * @returns the value chosen by the comparison.
786 */
787 double
value(RngPtr rng,Node * node)788 value( RngPtr rng, Node* node ) override
789 {
790 if ( condition_->value( rng, node ) )
791 {
792 return if_true_->value( rng, node );
793 }
794 else
795 {
796 return if_false_->value( rng, node );
797 }
798 }
799
800 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)801 value( RngPtr rng,
802 const std::vector< double >& source_pos,
803 const std::vector< double >& target_pos,
804 const AbstractLayer& layer,
805 Node* node ) override
806 {
807 if ( condition_->value( rng, source_pos, target_pos, layer, node ) )
808 {
809 return if_true_->value( rng, source_pos, target_pos, layer, node );
810 }
811 else
812 {
813 return if_false_->value( rng, source_pos, target_pos, layer, node );
814 }
815 }
816
817 protected:
818 std::shared_ptr< Parameter > const condition_;
819 std::shared_ptr< Parameter > const if_true_;
820 std::shared_ptr< Parameter > const if_false_;
821 };
822
823
824 /**
825 * Parameter class representing the minimum of a parameter's value and a given value.
826 */
827 class MinParameter : public Parameter
828 {
829 public:
830 /**
831 * Construct a min parameter. A copy is made of the supplied Parameter
832 * object.
833 */
MinParameter(std::shared_ptr<Parameter> p,const double other_value)834 MinParameter( std::shared_ptr< Parameter > p, const double other_value )
835 : Parameter( p->is_spatial(), p->returns_int_only() and value_is_integer_( other_value ) )
836 , p_( p )
837 , other_value_( other_value )
838 {
839 assert( is_spatial_ == p->is_spatial() );
840 }
841
842 /**
843 * Copy constructor.
844 */
MinParameter(const MinParameter & p)845 MinParameter( const MinParameter& p )
846 : Parameter( p )
847 , p_( p.p_ )
848 , other_value_( p.other_value_ )
849 {
850 }
851
852 /**
853 * @returns the value of the parameter.
854 */
855 double
value(RngPtr rng,Node * node)856 value( RngPtr rng, Node* node ) override
857 {
858 return std::min( p_->value( rng, node ), other_value_ );
859 }
860
861 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)862 value( RngPtr rng,
863 const std::vector< double >& source_pos,
864 const std::vector< double >& target_pos,
865 const AbstractLayer& layer,
866 Node* node ) override
867 {
868 return std::min( p_->value( rng, source_pos, target_pos, layer, node ), other_value_ );
869 }
870
871 protected:
872 std::shared_ptr< Parameter > const p_;
873 double other_value_;
874 };
875
876
877 /**
878 * Parameter class representing the maximum of a parameter's value and a given value.
879 */
880 class MaxParameter : public Parameter
881 {
882 public:
883 /**
884 * Construct a max parameter. A copy is made of the supplied Parameter
885 * object.
886 */
MaxParameter(std::shared_ptr<Parameter> p,const double other_value)887 MaxParameter( std::shared_ptr< Parameter > p, const double other_value )
888 : Parameter( p->is_spatial(), p->returns_int_only() and value_is_integer_( other_value ) )
889 , p_( p )
890 , other_value_( other_value )
891 {
892 }
893
894 /**
895 * Copy constructor.
896 */
MaxParameter(const MaxParameter & p)897 MaxParameter( const MaxParameter& p )
898 : Parameter( p )
899 , p_( p.p_ )
900 , other_value_( p.other_value_ )
901 {
902 }
903
904 /**
905 * @returns the value of the parameter.
906 */
907 double
value(RngPtr rng,Node * node)908 value( RngPtr rng, Node* node ) override
909 {
910 return std::max( p_->value( rng, node ), other_value_ );
911 }
912
913 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)914 value( RngPtr rng,
915 const std::vector< double >& source_pos,
916 const std::vector< double >& target_pos,
917 const AbstractLayer& layer,
918 Node* node ) override
919 {
920 return std::max( p_->value( rng, source_pos, target_pos, layer, node ), other_value_ );
921 }
922
923 protected:
924 std::shared_ptr< Parameter > const p_;
925 double other_value_;
926 };
927
928
929 /**
930 * Parameter class redrawing a parameter value if it is outside of specified limits.
931 */
932 class RedrawParameter : public Parameter
933 {
934 public:
935 /**
936 * Construct a redrawing parameter. A copy is made of the supplied Parameter
937 * object.
938 */
939 RedrawParameter( std::shared_ptr< Parameter > p, const double min, const double max );
940
941 /**
942 * Copy constructor.
943 */
RedrawParameter(const RedrawParameter & p)944 RedrawParameter( const RedrawParameter& p )
945 : Parameter( p )
946 , p_( p.p_ )
947 , min_( p.min_ )
948 , max_( p.max_ )
949 , max_redraws_( p.max_redraws_ )
950 {
951 }
952
953 /**
954 * @returns the value of the parameter.
955 */
956 double value( RngPtr rng, Node* node ) override;
957 double value( RngPtr rng,
958 const std::vector< double >& source_pos,
959 const std::vector< double >& target_pos,
960 const AbstractLayer& layer,
961 Node* node ) override;
962
963 protected:
964 std::shared_ptr< Parameter > const p_;
965 double min_;
966 double max_;
967 const size_t max_redraws_;
968 };
969
970
971 /**
972 * Parameter class representing the exponential of a parameter.
973 */
974 class ExpParameter : public Parameter
975 {
976 public:
977 /**
978 * Construct the exponential of the given parameter. A copy is made of the
979 * supplied Parameter object.
980 */
ExpParameter(std::shared_ptr<Parameter> p)981 ExpParameter( std::shared_ptr< Parameter > p )
982 : Parameter( p->is_spatial() )
983 , p_( p )
984 {
985 }
986
987 /**
988 * Copy constructor.
989 */
ExpParameter(const ExpParameter & p)990 ExpParameter( const ExpParameter& p )
991 : Parameter( p )
992 , p_( p.p_ )
993 {
994 }
995
996 /**
997 * @returns the value of the parameter.
998 */
999 double
value(RngPtr rng,Node * node)1000 value( RngPtr rng, Node* node ) override
1001 {
1002 return std::exp( p_->value( rng, node ) );
1003 }
1004
1005 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)1006 value( RngPtr rng,
1007 const std::vector< double >& source_pos,
1008 const std::vector< double >& target_pos,
1009 const AbstractLayer& layer,
1010 Node* node ) override
1011 {
1012 return std::exp( p_->value( rng, source_pos, target_pos, layer, node ) );
1013 }
1014
1015 protected:
1016 std::shared_ptr< Parameter > const p_;
1017 };
1018
1019
1020 /**
1021 * Parameter class representing the sine of a parameter.
1022 */
1023 class SinParameter : public Parameter
1024 {
1025 public:
1026 /**
1027 * Construct the sine of the given parameter. A copy is made of the
1028 * supplied Parameter object.
1029 */
SinParameter(std::shared_ptr<Parameter> p)1030 SinParameter( std::shared_ptr< Parameter > p )
1031 : Parameter( p->is_spatial() )
1032 , p_( p )
1033 {
1034 }
1035
1036 /**
1037 * Copy constructor.
1038 */
SinParameter(const SinParameter & p)1039 SinParameter( const SinParameter& p )
1040 : Parameter( p )
1041 , p_( p.p_ )
1042 {
1043 }
1044
1045 /**
1046 * @returns the value of the parameter.
1047 */
1048 double
value(RngPtr rng,Node * node)1049 value( RngPtr rng, Node* node ) override
1050 {
1051 return std::sin( p_->value( rng, node ) );
1052 }
1053
1054 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)1055 value( RngPtr rng,
1056 const std::vector< double >& source_pos,
1057 const std::vector< double >& target_pos,
1058 const AbstractLayer& layer,
1059 Node* node ) override
1060 {
1061 return std::sin( p_->value( rng, source_pos, target_pos, layer, node ) );
1062 }
1063
1064 protected:
1065 std::shared_ptr< Parameter > const p_;
1066 };
1067
1068 /**
1069 * Parameter class representing the cosine of a parameter.
1070 */
1071 class CosParameter : public Parameter
1072 {
1073 public:
1074 /**
1075 * Construct the exponential of the given parameter. A copy is made of the
1076 * supplied Parameter object.
1077 */
CosParameter(std::shared_ptr<Parameter> p)1078 CosParameter( std::shared_ptr< Parameter > p )
1079 : Parameter( p->is_spatial() )
1080 , p_( p )
1081 {
1082 }
1083
1084 /**
1085 * Copy constructor.
1086 */
CosParameter(const CosParameter & p)1087 CosParameter( const CosParameter& p )
1088 : Parameter( p )
1089 , p_( p.p_ )
1090 {
1091 }
1092
1093 /**
1094 * @returns the value of the parameter.
1095 */
1096 double
value(RngPtr rng,Node * node)1097 value( RngPtr rng, Node* node ) override
1098 {
1099 return std::cos( p_->value( rng, node ) );
1100 }
1101
1102 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)1103 value( RngPtr rng,
1104 const std::vector< double >& source_pos,
1105 const std::vector< double >& target_pos,
1106 const AbstractLayer& layer,
1107 Node* node ) override
1108 {
1109 return std::cos( p_->value( rng, source_pos, target_pos, layer, node ) );
1110 }
1111
1112 protected:
1113 std::shared_ptr< Parameter > const p_;
1114 };
1115
1116
1117 /**
1118 * Parameter class representing the parameter raised to the power of an
1119 * exponent.
1120 */
1121 class PowParameter : public Parameter
1122 {
1123 public:
1124 /**
1125 * Construct the parameter. A copy is made of the supplied Parameter object.
1126 */
PowParameter(std::shared_ptr<Parameter> p,const double exponent)1127 PowParameter( std::shared_ptr< Parameter > p, const double exponent )
1128 : Parameter( p->is_spatial(), p->returns_int_only() )
1129 , p_( p )
1130 , exponent_( exponent )
1131 {
1132 }
1133
1134 /**
1135 * Copy constructor.
1136 */
PowParameter(const PowParameter & p)1137 PowParameter( const PowParameter& p )
1138 : Parameter( p )
1139 , p_( p.p_ )
1140 , exponent_( p.exponent_ )
1141 {
1142 }
1143
1144 /**
1145 * @returns the value of the parameter.
1146 */
1147 double
value(RngPtr rng,Node * node)1148 value( RngPtr rng, Node* node ) override
1149 {
1150 return std::pow( p_->value( rng, node ), exponent_ );
1151 }
1152
1153 double
value(RngPtr rng,const std::vector<double> & source_pos,const std::vector<double> & target_pos,const AbstractLayer & layer,Node * node)1154 value( RngPtr rng,
1155 const std::vector< double >& source_pos,
1156 const std::vector< double >& target_pos,
1157 const AbstractLayer& layer,
1158 Node* node ) override
1159 {
1160 return std::pow( p_->value( rng, source_pos, target_pos, layer, node ), exponent_ );
1161 }
1162
1163 protected:
1164 std::shared_ptr< Parameter > const p_;
1165 const double exponent_;
1166 };
1167
1168
1169 /**
1170 * Position-generating Parameter class. One Parameter per dimension is
1171 * stored. When getting a position vector, a value for each dimension is
1172 * generated from their respective Parameters.
1173 */
1174 class DimensionParameter : public Parameter
1175 {
1176 public:
1177 using Parameter::value;
1178
1179 /**
1180 * Construct the Parameter with one given Parameter per dimension. A
1181 * copy is made of the supplied Parameter objects.
1182 */
DimensionParameter(std::shared_ptr<Parameter> px,std::shared_ptr<Parameter> py)1183 DimensionParameter( std::shared_ptr< Parameter > px, std::shared_ptr< Parameter > py )
1184 : Parameter( true )
1185 , num_dimensions_( 2 )
1186 , px_( px )
1187 , py_( py )
1188 , pz_( nullptr )
1189 {
1190 }
1191
DimensionParameter(std::shared_ptr<Parameter> px,std::shared_ptr<Parameter> py,std::shared_ptr<Parameter> pz)1192 DimensionParameter( std::shared_ptr< Parameter > px,
1193 std::shared_ptr< Parameter > py,
1194 std::shared_ptr< Parameter > pz )
1195 : Parameter( true )
1196 , num_dimensions_( 3 )
1197 , px_( px )
1198 , py_( py )
1199 , pz_( pz )
1200 {
1201 }
1202
1203 /**
1204 * Copy constructor.
1205 */
DimensionParameter(const DimensionParameter & p)1206 DimensionParameter( const DimensionParameter& p )
1207 : Parameter( p )
1208 , num_dimensions_( p.num_dimensions_ )
1209 , px_( p.px_ )
1210 , py_( p.py_ )
1211 , pz_( p.pz_ )
1212 {
1213 }
1214
1215 /**
1216 * The DimensionParameter has no double value, so this method will always throw.
1217 */
1218 double
value(RngPtr,Node *)1219 value( RngPtr, Node* ) override
1220 {
1221 throw KernelException( "Cannot get value of DimensionParameter." );
1222 }
1223
1224 /**
1225 * Generates a position with values for each dimension generated from their respective parameters.
1226 * @returns The position, given as an array.
1227 */
1228 std::vector< double >
get_values(RngPtr rng)1229 get_values( RngPtr rng )
1230 {
1231 switch ( num_dimensions_ )
1232 {
1233 case 2:
1234 return { px_->value( rng, nullptr ), py_->value( rng, nullptr ) };
1235 case 3:
1236 return { px_->value( rng, nullptr ), py_->value( rng, nullptr ), pz_->value( rng, nullptr ) };
1237 }
1238 throw KernelException( "Wrong number of dimensions in get_values!" );
1239 }
1240
1241 int
get_num_dimensions()1242 get_num_dimensions() const
1243 {
1244 return num_dimensions_;
1245 }
1246
1247 protected:
1248 int num_dimensions_;
1249 std::shared_ptr< Parameter > const px_;
1250 std::shared_ptr< Parameter > const py_;
1251 std::shared_ptr< Parameter > const pz_;
1252 };
1253
1254
1255 /**
1256 * Parameter class representing an exponential distribution applied on a parameter.
1257 * Can only be used when connecting spatially distributed nodes.
1258 */
1259 class ExpDistParameter : public Parameter
1260 {
1261 public:
1262 using Parameter::value;
1263
1264 /**
1265 * Construct the parameter from a dictionary of arguments.
1266 */
1267 ExpDistParameter( const DictionaryDatum& d );
1268
1269 /**
1270 * Copy constructor.
1271 */
ExpDistParameter(const ExpDistParameter & p)1272 ExpDistParameter( const ExpDistParameter& p )
1273 : Parameter( p )
1274 , p_( p.p_ )
1275 , inv_beta_( p.inv_beta_ )
1276 {
1277 assert( is_spatial_ == p.is_spatial() );
1278 }
1279
1280 /**
1281 * @returns the value of the parameter.
1282 */
1283 double
value(RngPtr,Node *)1284 value( RngPtr, Node* ) override
1285 {
1286 throw BadParameterValue( "Exponential distribution parameter can only be used when connecting." );
1287 }
1288
1289 double value( RngPtr rng,
1290 const std::vector< double >& source_pos,
1291 const std::vector< double >& target_pos,
1292 const AbstractLayer& layer,
1293 Node* node ) override;
1294
1295 protected:
1296 std::shared_ptr< Parameter > const p_;
1297 const double inv_beta_;
1298 };
1299
1300
1301 /**
1302 * Parameter class representing a gaussian distribution applied on a parameter.
1303 * Can only be used when connecting spatially distributed nodes.
1304 */
1305 class GaussianParameter : public Parameter
1306 {
1307 public:
1308 using Parameter::value;
1309
1310 /**
1311 * Construct the parameter from a dictionary of arguments.
1312 */
1313 GaussianParameter( const DictionaryDatum& d );
1314
1315 /**
1316 * Copy constructor.
1317 */
GaussianParameter(const GaussianParameter & p)1318 GaussianParameter( const GaussianParameter& p )
1319 : Parameter( p )
1320 , p_( p.p_ )
1321 , mean_( p.mean_ )
1322 , inv_two_std2_( p.inv_two_std2_ )
1323 {
1324 }
1325
1326 /**
1327 * @returns the value of the parameter.
1328 */
1329 double
value(RngPtr,Node *)1330 value( RngPtr, Node* ) override
1331 {
1332 throw BadParameterValue( "Gaussian distribution parameter can only be used when connecting." );
1333 }
1334
1335 double value( RngPtr rng,
1336 const std::vector< double >& source_pos,
1337 const std::vector< double >& target_pos,
1338 const AbstractLayer& layer,
1339 Node* node ) override;
1340
1341 protected:
1342 std::shared_ptr< Parameter > const p_;
1343 const double mean_;
1344 const double inv_two_std2_;
1345 };
1346
1347
1348 /**
1349 * Parameter class representing a gaussian distribution in two dimensions applied on a parameter.
1350 * Can only be used when connecting spatially distributed nodes.
1351 */
1352 class Gaussian2DParameter : public Parameter
1353 {
1354 public:
1355 using Parameter::value;
1356
1357 /**
1358 * Construct the parameter from a dictionary of arguments.
1359 */
1360 Gaussian2DParameter( const DictionaryDatum& d );
1361
1362 /**
1363 * Copy constructor.
1364 */
Gaussian2DParameter(const Gaussian2DParameter & p)1365 Gaussian2DParameter( const Gaussian2DParameter& p )
1366 : Parameter( p )
1367 , px_( p.px_ )
1368 , py_( p.py_ )
1369 , mean_x_( p.mean_x_ )
1370 , mean_y_( p.mean_y_ )
1371 , x_term_const_( p.x_term_const_ )
1372 , y_term_const_( p.y_term_const_ )
1373 , xy_term_const_( p.xy_term_const_ )
1374 {
1375 }
1376
1377 /**
1378 * @returns the value of the parameter.
1379 */
1380 double
value(RngPtr,Node *)1381 value( RngPtr, Node* ) override
1382 {
1383 throw BadParameterValue( "Gaussian 2D parameter can only be used when connecting." );
1384 }
1385
1386 double value( RngPtr rng,
1387 const std::vector< double >& source_pos,
1388 const std::vector< double >& target_pos,
1389 const AbstractLayer& layer,
1390 Node* node ) override;
1391
1392 protected:
1393 std::shared_ptr< Parameter > const px_;
1394 std::shared_ptr< Parameter > const py_;
1395 const double mean_x_;
1396 const double mean_y_;
1397 const double x_term_const_;
1398 const double y_term_const_;
1399 const double xy_term_const_;
1400 };
1401
1402
1403 /**
1404 * Parameter class representing a gamma distribution applied on a parameter.
1405 * Can only be used when connecting spatially distributed nodes.
1406 */
1407 class GammaParameter : public Parameter
1408 {
1409 public:
1410 using Parameter::value;
1411
1412 /**
1413 * Construct the parameter from a dictionary of arguments.
1414 */
1415 GammaParameter( const DictionaryDatum& d );
1416
1417 /**
1418 * Copy constructor.
1419 */
GammaParameter(const GammaParameter & p)1420 GammaParameter( const GammaParameter& p )
1421 : Parameter( p )
1422 , p_( p.p_ )
1423 , kappa_( p.kappa_ )
1424 , inv_theta_( p.inv_theta_ )
1425 , delta_( p.delta_ )
1426 {
1427 }
1428
1429 /**
1430 * @returns the value of the parameter.
1431 */
1432 double
value(RngPtr,Node *)1433 value( RngPtr, Node* ) override
1434 {
1435 throw BadParameterValue( "Gamma distribution parameter can only be used when connecting." );
1436 }
1437
1438 double value( RngPtr rng,
1439 const std::vector< double >& source_pos,
1440 const std::vector< double >& target_pos,
1441 const AbstractLayer& layer,
1442 Node* node ) override;
1443
1444 protected:
1445 std::shared_ptr< Parameter > const p_;
1446 const double kappa_;
1447 const double inv_theta_;
1448 const double delta_;
1449 };
1450
1451 inline double
value(RngPtr rng,const std::vector<double> &,const std::vector<double> &,const AbstractLayer &,Node * node)1452 Parameter::value( RngPtr rng,
1453 const std::vector< double >&,
1454 const std::vector< double >&,
1455 const AbstractLayer&,
1456 Node* node )
1457 {
1458 return value( rng, node );
1459 }
1460
1461 inline bool
is_spatial()1462 Parameter::is_spatial() const
1463 {
1464 return is_spatial_;
1465 }
1466
1467 inline bool
returns_int_only()1468 Parameter::returns_int_only() const
1469 {
1470 return returns_int_only_;
1471 }
1472
1473 inline bool
value_is_integer_(const double value)1474 Parameter::value_is_integer_( const double value ) const
1475 {
1476 // Here fmod calculates the remainder of the division operation x/y. By using y=1.0,
1477 // the remainder is the fractional part of the value. If the fractional part
1478 // is zero, the value is an integer.
1479 return std::fmod( value, static_cast< double >( 1.0 ) ) == 0.0;
1480 }
1481
1482
1483 /**
1484 * Create the product of one parameter with another.
1485 * @returns a new dynamically allocated parameter.
1486 */
1487 std::shared_ptr< Parameter > multiply_parameter( const std::shared_ptr< Parameter > first,
1488 const std::shared_ptr< Parameter > second );
1489
1490 /**
1491 * Create the quotient of one parameter with another.
1492 * @returns a new dynamically allocated parameter.
1493 */
1494 std::shared_ptr< Parameter > divide_parameter( const std::shared_ptr< Parameter > first,
1495 const std::shared_ptr< Parameter > second );
1496
1497 /**
1498 * Create the sum of one parameter with another.
1499 * @returns a new dynamically allocated parameter.
1500 */
1501 std::shared_ptr< Parameter > add_parameter( const std::shared_ptr< Parameter > first,
1502 const std::shared_ptr< Parameter > second );
1503
1504 /**
1505 * Create the difference between one parameter and another.
1506 * @returns a new dynamically allocated parameter.
1507 */
1508 std::shared_ptr< Parameter > subtract_parameter( const std::shared_ptr< Parameter > first,
1509 const std::shared_ptr< Parameter > second );
1510
1511 /**
1512 * Create comparison of one parameter with another.
1513 * @returns a new dynamically allocated parameter.
1514 */
1515 std::shared_ptr< Parameter > compare_parameter( const std::shared_ptr< Parameter > first,
1516 const std::shared_ptr< Parameter > second,
1517 const DictionaryDatum& d );
1518
1519 /**
1520 * Create a parameter that chooses between two other parameters,
1521 * based on a given condition parameter. The resulting value of the condition parameter
1522 * is treated as a bool, meaning that a zero value evaluates as false, and all other values
1523 * evaluate as true.
1524 * @returns a new dynamically allocated parameter.
1525 */
1526 std::shared_ptr< Parameter > conditional_parameter( const std::shared_ptr< Parameter > condition,
1527 const std::shared_ptr< Parameter > if_true,
1528 const std::shared_ptr< Parameter > if_false );
1529
1530 /**
1531 * Create parameter whose value is the minimum of a given parameter's value and the given value.
1532 * @returns a new dynamically allocated parameter.
1533 */
1534 std::shared_ptr< Parameter > min_parameter( const std::shared_ptr< Parameter > parameter, const double other );
1535
1536 /**
1537 * Create parameter whose value is the maximum of a given parameter's value and the given value.
1538 * @returns a new dynamically allocated parameter.
1539 */
1540 std::shared_ptr< Parameter > max_parameter( const std::shared_ptr< Parameter > parameter, const double other );
1541
1542 /**
1543 * Create parameter redrawing the value if the value of a parameter is outside the set limits.
1544 * @returns a new dynamically allocated parameter.
1545 */
1546 std::shared_ptr< Parameter >
1547 redraw_parameter( const std::shared_ptr< Parameter > parameter, const double min, const double max );
1548
1549 /**
1550 * Create the exponential of a parameter.
1551 * @returns a new dynamically allocated parameter.
1552 */
1553 std::shared_ptr< Parameter > exp_parameter( const std::shared_ptr< Parameter > parameter );
1554
1555 /**
1556 * Create the sine of a parameter.
1557 * @returns a new dynamically allocated parameter.
1558 */
1559 std::shared_ptr< Parameter > sin_parameter( const std::shared_ptr< Parameter > parameter );
1560
1561 /**
1562 * Create the cosine of a parameter.
1563 * @returns a new dynamically allocated parameter.
1564 */
1565 std::shared_ptr< Parameter > cos_parameter( const std::shared_ptr< Parameter > parameter );
1566
1567 /**
1568 * Create a parameter raised to the power of an exponent.
1569 * @returns a new dynamically allocated parameter.
1570 */
1571 std::shared_ptr< Parameter > pow_parameter( const std::shared_ptr< Parameter > parameter, const double exponent );
1572
1573 /**
1574 * Create a parameter that can generate position vectors from a given set of parameters.
1575 * @returns a new dynamically allocated parameter.
1576 */
1577 std::shared_ptr< Parameter > dimension_parameter( const std::shared_ptr< Parameter > x_parameter,
1578 const std::shared_ptr< Parameter > y_parameter );
1579
1580 std::shared_ptr< Parameter > dimension_parameter( const std::shared_ptr< Parameter > x_parameter,
1581 const std::shared_ptr< Parameter > y_parameter,
1582 const std::shared_ptr< Parameter > z_parameter );
1583
1584
1585 } // namespace nest
1586
1587 #endif
1588