Related
I would like to implement a numerical integral whose integrand is evaluated at quadrature points. Therefore something like: integral(domain, f), where domain is indeed the domain where I want to integrate and f is the function to integrate. f is only a function of the Point p (quadrature points) inside the domain and can have vector values (scalar is a particular case).
Since the function f can be, in general, a combination of different functions, I wonder how to overload arithmetic operators for functions.
I already found this Implementing multiplication operator for mathematical functions C++
but it does not cover my question, because the Function returns only x, while In my case I would like to have different Functions which can return a more complex function of x.
So, let f_1,...f_N be different functions which have the same return type, for example a std::array<double,M> with given length M, and which receive the same input Point p, i.e for I=1,...,N:
std::array<double,M> f_i(Point p)
{ std::array<double,M> x;
\\ compute x somehow depending on i
return x;}
Then I would like to create f as a combination of the previous f_1,...f_N, e.g. f=f_1 *f_2+(f_3*f_4)*f_5... (here the operations are meant to be component wise).
In this way I could evaluate f(p) inside integral(domain, f), obtaining for each quadrature point exactly:
f_1(p) *f_2(p)+(f_3(p)*f_4(p))*f_5(p)...
Edit:
I know I have to use functors and not simple functions (which I used just to state the problem), but I am not able to figure out how for this purpose.
Any hint?
Thank you
In the Julia Manual under the Anonymous Functions section one of the examples that is offered is (x,y,z)->2x+y-z.
Could someone please show me how one would pass a set of arguments to this function?
Say x=(1,2,3); y=(2,3,4); z=(1,3,5).
If you define x,y and z to be arrays then you can just call the function and pass them in:
fun = (x,y,z)->2x+y-z
x=[1,2,3]
y=[2,3,4]
z=[1,3,5]
fun(x, y, z)
giving the result:
3-element Array{Int64,1}:
3
4
5
But if you want to do this with tuples, as per your example, you will need to use map:
x=(1,2,3)
y=(2,3,4)
z=(1,3,5)
map(fun, x, y, z)
this gives the same result, but this time as a tuple:
(3, 4, 5)
This is because the *, + and - operators are not defined for tuples so the formula 2x+y-z can't work. Using map gets around this by calling the function multiple times passing in scalars.
You have to assign the anonymous function to a variable, in order to call it.
julia> fun = (x,y,z)->2x+y-z
(anonymous function)
julia> fun((1,2,3),(2,3,4),(1,3,5))
ERROR: no method *(Int64, (Int64,Int64,Int64))
in anonymous at none:1
It does not work, because the tuples you set for x, does not implement the * function.
How is it possible to use a mathematical function as module- parameter
Such as:
PersonalPlot[fun0_, var0_, min0_, max0_] :=
Module[{fun = fun0, var = var0 , min = min0, max = max0},
(*this is incorrect*)
fun = fun[var_];
Plot[fun, {var, min, max}]
]
PersonalPlot[x^2,x,0,3];
You're right, that statement is incorrect. Mathematica evaluates it to something like
x^2[x]
when you call PersonalPlot and that evaluates to, well, in words to x to the power of 2 of x which doesn't make a lot of sense. There are a number of ways round the problem. The simplest would be to dispense with a Module altogether and define:
PersonalPlot1[fun0_, var0_, min0_, max0_] := Plot[fun0, {var0, min0, max0}]
which you would call like this:
PersonalPlot1[x^2, x, 0, 3]
Note that a call like this PersonalPlot1[x^2, y, 0, 3] produces an empty plot because the variable in the function passed in is not the same variable as the second argument. Read on.
If you want to define a module which takes a function as an argument, then this is one way of doing it:
PersonalPlot2[fun0_, var0_, min0_, max0_] :=
Module[{fun = fun0, var = var0, min = min0, max = max0},
Plot[fun[var], {var, min, max}]]
which you would call like this
PersonalPlot2[#^2 &, x, 0, 3]
Note:
The function passed into the function is a pure function. If you are not already familiar with Mathematica's pure functions now would be a good time to consult the relevant parts of the documentation.
This explicitly tells the Plot command to evaluate fun[var] over the range you specify.
Your local variables are not strictly necessary since your function works by side-effect, producing a plot rather than manipulating (copies of) the arguments passed to it. You could rewrite this simply as:
PersonalPlot2b[fun0_, var0_, min0_, max0_] := Module[{},
Plot[fun0[var0], {var0, min0, max0}]]
Another possibility would be to drop the argument which represents the variable input to the function passed to PersonalPlot, like this:
PersonalPlot3[fun0_, min0_, max0_] := Module[{x},
Plot[fun0[x], {x, min0, max0}]]
which you would call like this
PersonalPlot3[#^2 &, 0, 3]
In this version I've made x local to the Module to avoid clashes with any workspace variable also called x. This avoids errors arising from using different names for the argument to the function (the pure function has no argument names) and the second argument to PersonalPlot; that has now been dropped.
There are probably several other useful ways of passing arguments to functions whether those functions use modules or not.
EDIT
Most of us who've used Mathematica for a while don't, I think, regard #^2& as something to avoid. If you don't like it, you could use the more explicit syntax, like this:
fun1 = Function[x,x^2]
which you can then pass around like this
PersonalPlot[fun1,0.0,4.0]
By using this approach you can make your functions a bit less error prone by requiring the right types to be passed in, like this
PersonalPlot[fun_Function, min_Real, max_Real] := ...
but it's really up to you.
Off the top of my head I don't know how Plot does it, I'd have to look in the documentation.
The following three examples may add to previous answer in illustrating some of the possible ways to pass functions as arguments.
Example 1:
square[x_] := x^2/50;
fplot1[f_, x1_, x2_] := Plot[f, {x, x1, x2}];
fplot1[x^2/50, -2 Pi, 2 Pi]
fplot1[{square[x], Sin[x]}, -2 Pi, 2 Pi]
Example 2:
fplot2[f_, x1_, x2_] :=
Module [ (*
This type of function passing works also works in Module so long as x is not defined as a local variable. *)
{},
Plot[f, {x, x1, x2}]
];
fplot2[Sin[x], -2 Pi, 2 Pi]
fplot2[{Sin[x], square[x]}, -2 Pi, 2 Pi]
Example 3:
fplot3[f_, x1_, x2_] :=
Module [ (* This type of function passing works in Module with x declared as local variable. Only one function name can be passed. *)
{x},
Plot[f[x], {x, x1, x2}]
];
fplot3[Sin, -2 Pi, 2 Pi]
fplot3[square, -2 Pi, 2 Pi]
Consider splatter in this Python code:
def splatter(fn):
return lambda (args): fn(*args)
def add(a, b):
return a + b
list1 = [1, 2, 3]
list2 = [4, 5, 6]
print map(splatter(add), zip(list1, list2))
Mapping an n-ary function over n zipped sequences seems like a common enough operation that there might be a name for this already, but I have no idea where I'd find that. It vaguely evokes currying, and it seems like there are probably other related argument-centric HOFs that I've never heard of. Does anyone know if this is a "well-known" function? When discussing it I am currently stuck with the type of awkward language used in the question title.
Edit
Wow, Python's map does this automatically. You can write:
map(add, list1, list2)
And it will do the right thing, saving you the trouble of splattering your function. The only difference is that zip returns a list whose length is the the length of its shortest argument, whereas map extends shorter lists with None.
I think zipWith is the function that you are searching (this name is at least used in Haskell). It is even a bit more general. In Haskell zipWith is defined as follows (where the first line is just the type):
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
zipWith _ _ _ = []
And your example would be something like
zipWith (+) [1, 2, 3] [4, 5, 6]
Since I do not know python very well I can only point to "zipWith analogue in Python?".
I randomly saw this in my list of "Questions asked," and was surprised that I now know the answer.
There are two interpretations of the function that I asked.
The first was my intent: to take a function that takes a fixed number of arguments and convert it into a function that takes those arguments as a fixed-size list or tuple. In Haskell, the function that does this operation is called uncurry.
uncurry :: (a -> b -> c) -> ((a, b) -> c)
(Extra parens for clarity.)
It's easy to imagine extending this to functions of more than two arguments, though it can't be expressed in Haskell. But uncurry3, uncurry4, etc. would not be out of place.
So I was right that it "vaguely evokes currying," as it is really the opposite.
The second interpretation is to take a function that takes an intentionally variable number of arguments and return a function that takes a single list.
Because splat is so weird as a syntactic construct in Python, this is hard to reason about.
But if we imagine, say, JavaScript, which has a first-class named function for "splatting:"
varFn.apply(null, args)
var splatter = function(f) {
return function(arg) {
return f.apply(null, arg);
};
};
Then we could rephrase that as merely a partial application of the "apply" function:
var splatter = function(f) {
return Function.prototype.apply.bind(f, null);
};
Or using, Underscore's partial, we can come up with the point-free definition:
var splatter = _.partial(Function.prototype.bind.bind(Function.prototype.apply), _, null)
Yes, that is a nightmare.
(The alternative to _.partial requires defining some sort of swap helper and would come out even less readable, I think.)
So I think that the name of this operation is just "a partial application of apply", or in the Python case it's almost like a section of the splat operator -- if splat were an "actual" operator.
But the particular combination of uncurry, zip, and map in the original question is exactly zipWith, as chris pointed out. In fact, HLint by default includes a rule to replace this complex construct with a single call to zipWith.
I hope that clears things up, past Ian.
I use the LINQ Aggregate operator quite often. Essentially, it lets you "accumulate" a function over a sequence by repeatedly applying the function on the last computed value of the function and the next element of the sequence.
For example:
int[] numbers = ...
int result = numbers.Aggregate(0, (result, next) => result + next * next);
will compute the sum of the squares of the elements of an array.
After some googling, I discovered that the general term for this in functional programming is "fold". This got me curious about functions that could be written as folds. In other words, the f in f = fold op.
I think that a function that can be computed with this operator only needs to satisfy (please correct me if I am wrong):
f(x1, x2, ..., xn) = f(f(x1, x2, ..., xn-1), xn)
This property seems common enough to deserve a special name. Is there one?
An Iterated binary operation may be what you are looking for.
You would also need to add some stopping conditions like
f(x) = something
f(x1,x2) = something2
They define a binary operation f and another function F in the link I provided to handle what happens when you get down to f(x1,x2).
To clarify the question: 'sum of squares' is a special function because it has the property that it can be expressed in terms of the fold functional plus a lambda, ie
sumSq = fold ((result, next) => result + next * next) 0
Which functions f have this property, where dom f = { A tuples }, ran f :: B?
Clearly, due to the mechanics of fold, the statement that f is foldable is the assertion that there exists an h :: A * B -> B such that for any n > 0, x1, ..., xn in A, f ((x1,...xn)) = h (xn, f ((x1,...,xn-1))).
The assertion that the h exists says almost the same thing as your condition that
f((x1, x2, ..., xn)) = f((f((x1, x2, ..., xn-1)), xn)) (*)
so you were very nearly correct; the difference is that you are requiring A=B which is a bit more restrictive than being a general fold-expressible function. More problematically though, fold in general also takes a starting value a, which is set to a = f nil. The main reason your formulation (*) is wrong is that it assumes that h is whatever f does on pair lists, but that is only true when h(x, a) = a. That is, in your example of sum of squares, the starting value you gave to Accumulate was 0, which is a does-nothing when you add it, but there are fold-expressible functions where the starting value does something, in which case we have a fold-expressible function which does not satisfy (*).
For example, take this fold-expressible function lengthPlusOne:
lengthPlusOne = fold ((result, next) => result + 1) 1
f (1) = 2, but f(f(), 1) = f(1, 1) = 3.
Finally, let's give an example of a functions on lists not expressible in terms of fold. Suppose we had a black box function and tested it on these inputs:
f (1) = 1
f (1, 1) = 1 (1)
f (2, 1) = 1
f (1, 2, 1) = 2 (2)
Such a function on tuples (=finite lists) obviously exists (we can just define it to have those outputs above and be zero on any other lists). Yet, it is not foldable because (1) implies h(1,1)=1, while (2) implies h(1,1)=2.
I don't know if there is other terminology than just saying 'a function expressible as a fold'. Perhaps a (left/right) context-free list function would be a good way of describing it?
In functional programming, fold is used to aggregate results on collections like list, array, sequence... Your formulation of fold is incorrect, which leads to confusion. A correct formulation could be:
fold f e [x1, x2, x3,..., xn] = f((...f(f(f(e, x1),x2),x3)...), xn)
The requirement for f is actually very loose. Lets say the type of elements is T and type of e is U. So function f indeed takes two arguments, the first one of type U and the second one of type T, and returns a value of type U (because this value will be supplied as the first argument of function f again). In short, we have an "accumulate" function with a signature f: U * T -> U. Due to this reason, I don't think there is a formal term for these kinds of function.
In your example, e = 0, T = int, U = int and your lambda function (result, next) => result + next * next has a signaturef: int * int -> int, which satisfies the condition of "foldable" functions.
In case you want to know, another variant of fold is foldBack, which accumulates results with the reverse order from xn to x1:
foldBack f [x1, x2,..., xn] e = f(x1,f(x2,...,f(n,e)...))
There are interesting cases with commutative functions, which satisfy f(x, y) = f(x, y), when fold and foldBack return the same result. About fold itself, it is a specific instance of catamorphism in category theory. You can read more about catamorphism here.