1

I'd like to define a function of three variables which produces a new, named function of a single variable, where this final variable is not a member of the first three. So I'd like something where I have

f0[x_ , y_ , z_] := << complicated function >>

which gives f1[p_]. Furthermore, I'd like to have the functions be defined in such a way that when I write

IN:= f0[x0,y0,z0]

I get

OUT:= fx0y0z0[p_]

so that I can easily identify which inputs produced the function. So, basically, I'd like to wind up with a function produced via Interpolation and I'd like that function to have a specific name defined by my inputs.

For instance, let's say I'm creating a numerical function by writing down a table in two variables (say, p and q) that requires x, y, and z as inputs. Then I'd like to integrate over q and interpolate over p so that my final function is just a function over q only.

So, let's say that my first function is

g[x_,y_,z_,p_,q_] := (x + y + z) p / q

Now I'd like to tabulate this over p and q for given values of x, y, and z. Then I'd like to integrate over p and have a function of q only. I can for instance do the following

f1[x_,y_,z_] := NIntegrate[
  Interpolation[
    Flatten[Table[{q, p, 
       g[x,y,z,p,q]}, {p,p0,p1}, {q,q0,q1}],1]][#,
    p], {p, p0, p1}] &

and then this is a well-behaved function of q which I can make tables of, which I can then plot, integrate, etc. just by writing f1[x0,y0,x0][q]. But this is not very convenient for me since it requires me to write out a new function name every time I want to examine the behavior as a function of different values of x, y, and z, and I will ultimately need many values of x, y, and z. Is there any way to write a meta-function that is capable of producing a brand new interpolating function of q only, with the name including the input values of x, y, and z?

Emilio Pisanty
  • 10,255
  • 1
  • 36
  • 69
user1451632
  • 113
  • 2

1 Answers1

1

I typically use pure functions for this type of meta programming. For example:

generator[p_,q_] := Function[{x,y,z},
  Evaluate[ 
    Integrate[ (x+y+z)/(p+q), {p,p0,p1},{q,q0,q1}]
  ]
]

Then one can use it as

fpXqY = generator[X,Y]

And then fpXqY will be a pure function you can use. This only works for function that can be treated as pure functions. However, one can also do something similar by just calling SetDelayed[] (which is the full form of :=) within your generator to create a new function. So something like:

generator2[p_,q_] := SetDelayed[ 
  ToExpression[ StringJoin[ "fp", ToString[p], "q", ToString[q]]][x_, y_, z_]
  , Integrate[ (x+y+z)/(p+q), {p,p0,p1},{q,q0,q1}]
]

And then call it as

generator2[X,Y]

and you should then find you can use fpXqY as your evaluator. Note that you can either use Set or SetDelayed as you need.

tkott
  • 4,939
  • 25
  • 44
  • Thanks -- this seems to be on the right track. However, my goal is to produce a function with an entirely new name.

    Say I have

    g[x_,y_,z_,p_,q_]:=(x+y+z)p/q

    f1[x_,y_,z_] := NIntegrate[Interpolation[Flatten[Table[{q,p,g[x,y,z,p,q]},{p,10}, {q,10}],1]][#,p],{p,1,10}]&

    as before. What is wrong with the following?

    generator[x_,y_,z_]:=SetDelayed[ToExpression[ToString[StringForm["f1``````",x,y,z]]][#]&,Interpolation[Table[f1[x,y,z][p],{p,10}]]]

    I'd like to produce, e.g.,

    f1323 = Interpolation[Table[f1[3,2,3][x],{x,10}]];

    which is easily identifiable and very fast. Thank you for your help!

    – user1451632 Nov 12 '13 at 16:43
  • @user1451632 right sorry, let me fix that -- see the updated generator 2. In general, you should avoid using StringForm for producing function names -- the *Form sometimes introduces odd quirks – tkott Nov 12 '13 at 17:31
  • Terrific! This really helps. Thank you for your time. – user1451632 Nov 12 '13 at 21:27