10
10
11
11
import matplotlib .pyplot as plt
12
12
import numpy as np
13
+ from copy import deepcopy
13
14
from scipy import integrate , linalg , optimize
14
15
15
16
try :
@@ -499,12 +500,16 @@ def set_discrete(
499
500
interpolation = "spline" ,
500
501
extrapolation = "constant" ,
501
502
one_by_one = True ,
503
+ mutate_self = True ,
502
504
):
503
- """This method transforms function defined Functions into list
504
- defined Functions. It evaluates the function at certain points
505
- (sampling range) and stores the results in a list, which is converted
506
- into a Function and then returned. The original Function object is
507
- replaced by the new one.
505
+ """This method discretizes a 1-D or 2-D Function by evaluating it at
506
+ certain points (sampling range) and storing the results in a list,
507
+ which is converted into a Function and then returned. By default, the
508
+ original Function object is replaced by the new one, which can be
509
+ changed by the attribute `mutate_self`.
510
+
511
+ This method is specially useful to change a dataset sampling or to
512
+ convert a Function defined by a callable into a list based Function.
508
513
509
514
Parameters
510
515
----------
@@ -528,18 +533,32 @@ def set_discrete(
528
533
one_by_one : boolean, optional
529
534
If True, evaluate Function in each sample point separately. If
530
535
False, evaluates Function in vectorized form. Default is True.
536
+ mutate_self : boolean, optional
537
+ If True, the original Function object source will be replaced by
538
+ the new one. If False, the original Function object source will
539
+ remain unchanged, and the new one is simply returned.
540
+ Default is True.
531
541
532
542
Returns
533
543
-------
534
544
self : Function
545
+
546
+ Notes
547
+ -----
548
+ 1. This method performs by default in place replacement of the original
549
+ Function object source. This can be changed by the attribute `mutate_self`.
550
+
551
+ 2. Currently, this method only supports 1-D and 2-D Functions.
535
552
"""
536
- if self .__dom_dim__ == 1 :
553
+ func = deepcopy (self ) if not mutate_self else self
554
+
555
+ if func .__dom_dim__ == 1 :
537
556
xs = np .linspace (lower , upper , samples )
538
- ys = self .get_value (xs .tolist ()) if one_by_one else self .get_value (xs )
539
- self .set_source (np .concatenate (([xs ], [ys ])).transpose ())
540
- self .set_interpolation (interpolation )
541
- self .set_extrapolation (extrapolation )
542
- elif self .__dom_dim__ == 2 :
557
+ ys = func .get_value (xs .tolist ()) if one_by_one else func .get_value (xs )
558
+ func .set_source (np .concatenate (([xs ], [ys ])).transpose ())
559
+ func .set_interpolation (interpolation )
560
+ func .set_extrapolation (extrapolation )
561
+ elif func .__dom_dim__ == 2 :
543
562
lower = 2 * [lower ] if isinstance (lower , (int , float )) else lower
544
563
upper = 2 * [upper ] if isinstance (upper , (int , float )) else upper
545
564
sam = 2 * [samples ] if isinstance (samples , (int , float )) else samples
@@ -548,22 +567,29 @@ def set_discrete(
548
567
ys = np .linspace (lower [1 ], upper [1 ], sam [1 ])
549
568
xs , ys = np .array (np .meshgrid (xs , ys )).reshape (2 , xs .size * ys .size )
550
569
# Evaluate function at all mesh nodes and convert it to matrix
551
- zs = np .array (self .get_value (xs , ys ))
552
- self .__interpolation__ = "shepard"
553
- self .__extrapolation__ = "natural"
554
- self .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
555
- return self
570
+ zs = np .array (func .get_value (xs , ys ))
571
+ func .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
572
+ func .__interpolation__ = "shepard"
573
+ func .__extrapolation__ = "natural"
574
+ else :
575
+ raise ValueError (
576
+ "Discretization is only supported for 1-D and 2-D Functions."
577
+ )
578
+ return func
556
579
557
580
def set_discrete_based_on_model (
558
- self , model_function , one_by_one = True , keep_self = True
581
+ self , model_function , one_by_one = True , keep_self = True , mutate_self = True
559
582
):
560
- """This method transforms the domain of Function instance into a list of
561
- discrete points based on the domain of a model Function instance. It
562
- does so by retrieving the domain, domain name, interpolation method and
563
- extrapolation method of the model Function instance. It then evaluates
564
- the original Function instance in all points of the retrieved domain to
565
- generate the list of discrete points that will be used for interpolation
566
- when this Function is called.
583
+ """This method transforms the domain of a 1-D or 2-D Function instance
584
+ into a list of discrete points based on the domain of a model Function
585
+ instance. It does so by retrieving the domain, domain name,
586
+ interpolation method and extrapolation method of the model Function
587
+ instance. It then evaluates the original Function instance in all
588
+ points of the retrieved domain to generate the list of discrete points
589
+ that will be used for interpolation when this Function is called.
590
+
591
+ By default, the original Function object is replaced by the new one,
592
+ which can be changed by the attribute `mutate_self`.
567
593
568
594
Parameters
569
595
----------
@@ -573,15 +599,17 @@ def set_discrete_based_on_model(
573
599
Must be a Function whose source attribute is a list (i.e. a list
574
600
based Function instance). Must have the same domain dimension as the
575
601
Function to be discretized.
576
-
577
602
one_by_one : boolean, optional
578
603
If True, evaluate Function in each sample point separately. If
579
604
False, evaluates Function in vectorized form. Default is True.
580
-
581
- keepSelf : boolean, optional
605
+ keep_self : boolean, optional
582
606
If True, the original Function interpolation and extrapolation
583
607
methods will be kept. If False, those are substituted by the ones
584
608
from the model Function. Default is True.
609
+ mutate_self : boolean, optional
610
+ If True, the original Function object source will be replaced by
611
+ the new one. If False, the original Function object source will
612
+ remain unchanged, and the new one is simply returned.
585
613
586
614
Returns
587
615
-------
@@ -629,40 +657,48 @@ def set_discrete_based_on_model(
629
657
630
658
Notes
631
659
-----
632
- 1. This method performs in place replacement of the original Function
633
- object source.
660
+ 1. This method performs by default in place replacement of the original
661
+ Function object source. This can be changed by the attribute `mutate_self` .
634
662
635
663
2. This method is similar to set_discrete, but it uses the domain of a
636
664
model Function to define the domain of the new Function instance.
665
+
666
+ 3. Currently, this method only supports 1-D and 2-D Functions.
637
667
"""
638
668
if not isinstance (model_function .source , np .ndarray ):
639
669
raise TypeError ("model_function must be a list based Function." )
640
670
if model_function .__dom_dim__ != self .__dom_dim__ :
641
671
raise ValueError ("model_function must have the same domain dimension." )
642
672
643
- if self .__dom_dim__ == 1 :
673
+ func = deepcopy (self ) if not mutate_self else self
674
+
675
+ if func .__dom_dim__ == 1 :
644
676
xs = model_function .source [:, 0 ]
645
- ys = self .get_value (xs .tolist ()) if one_by_one else self .get_value (xs )
646
- self .set_source (np .concatenate (([xs ], [ys ])).transpose ())
647
- elif self .__dom_dim__ == 2 :
677
+ ys = func .get_value (xs .tolist ()) if one_by_one else func .get_value (xs )
678
+ func .set_source (np .concatenate (([xs ], [ys ])).transpose ())
679
+ elif func .__dom_dim__ == 2 :
648
680
# Create nodes to evaluate function
649
681
xs = model_function .source [:, 0 ]
650
682
ys = model_function .source [:, 1 ]
651
683
# Evaluate function at all mesh nodes and convert it to matrix
652
- zs = np .array (self .get_value (xs , ys ))
653
- self .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
684
+ zs = np .array (func .get_value (xs , ys ))
685
+ func .set_source (np .concatenate (([xs ], [ys ], [zs ])).transpose ())
686
+ else :
687
+ raise ValueError (
688
+ "Discretization is only supported for 1-D and 2-D Functions."
689
+ )
654
690
655
691
interp = (
656
- self .__interpolation__ if keep_self else model_function .__interpolation__
692
+ func .__interpolation__ if keep_self else model_function .__interpolation__
657
693
)
658
694
extrap = (
659
- self .__extrapolation__ if keep_self else model_function .__extrapolation__
695
+ func .__extrapolation__ if keep_self else model_function .__extrapolation__
660
696
)
661
697
662
- self .set_interpolation (interp )
663
- self .set_extrapolation (extrap )
698
+ func .set_interpolation (interp )
699
+ func .set_extrapolation (extrap )
664
700
665
- return self
701
+ return func
666
702
667
703
def reset (
668
704
self ,
0 commit comments