1
$\begingroup$

How do you define a variable amount of functions with a variable amount of arguments? I don't get the reference at all :

    Clear["Global`*"]
    ClearAll[Subscript]
    n = 3;

    cost = Table[Subscript[c, i], {i, n}];
    Do[Subscript[c, i] = RandomInteger[{0, 400}]/1000, {i, n}];
    price = Table[Subscript[p, i], {i, n}];
    equations = Table[Subscript[eq, i], {i, n}];

 Do[Subscript[eq, i] = 
       Subscript[p, i] - Subscript[c, i] + 
        1/(Sum[Subscript[p, l]*Boole[l != i], {l, n}]), {i, n}];

    Do[Subscript[p, i] = Symbol["p" <> ToString[i]], {i, n}];
    g1[p1_, p2_, p3_] := Evaluate[equations[[1]]];
    g1 @@ {0.1, 0.1, 0.2}

I need to be able to generate g1..gn functions with arguments gi[p1,..pn], is there a way to make it with some kind of loop {i,n}?

I tried something like this without success:

Do[Symbol["g" <> ToString[i]][p__] := Evaluate[equations[[i]]], {i, n}]

I also wonder how do I explicit that the first argument is p1, the second is p2... and the nth is pn.

$\endgroup$
2
  • 2
    $\begingroup$ Can you describe a little bit about the functions that you are trying to create? As it is, it's hard to parse what you are trying to do. $\endgroup$
    – march
    Jul 25, 2018 at 18:31
  • $\begingroup$ I have a system of equations that NSolve/FindInstance can't handle. So I'm trying to work a fixed point for several variables convergence with this. (btw the equation above is a dummy, not the real problem) $\endgroup$
    – Rodrigo
    Jul 25, 2018 at 18:41

1 Answer 1

0
$\begingroup$

I would probably do this by generating Functions rather than expressions involving formal arguments. And instead of trying to give symbols indexed names, I'd make the index a parameter.

So, instead of the eventual function call looking like this:

g1[0.1, 0.1, 0.2]

I want something more like this:

g[1][0.1, 0.1, 0.2]

But we have to deal with a couple of issues. First, g[1] is ambiguous, because we don't know what the "order" is (you set this in your code with a global n). So, one parameter isn't enough. We'll need something like this:

g[n, i][<list of n args>]

where n is the order (3 in your example) and i is the ith function among the group of n functions.

Next, we need to deal with the randomness of cost. We could work the randomness into our definition for g, but I don't like having that hidden effect. So, we'll add yet another parameter for cost (and you can still generate a random value if you want to pass in). So, we want to define something like:

g[cost_, order_, index_] := Function[<...need to figure this bit out...>]

Using Function relieves us of the problem is coming up with unique argument names, because we can use Slot. For kicks, I'll memoize this as well. So we end up with something like this:

g[cost_, order_, index_] := 
  g[cost, order, index] = 
    Function[
      Null, 
      Evaluate[cost + Slot[index] + 1/Plus @@ Delete[Array[Slot, order], index]]]

Let's try it out:

g[c, 3, 1][x, y, z] (* c + x + (y + z)^(-1) *)
g[c, 4, 3][w, x, y, z] (* c + y + (w + x + z)^(-1) *)
g[1, 4, 2][1, 2, 3, 4] (* 25/8 *)
g[RandomReal[], 2, 2][1, 2] (* I got 3.495947182193526 *)

One slight, potential problem is that we're not checking the number of arguments passed. So, something like g[1, 4, 2][1, 2, 3] will generate error messages and produce a not-very-useful output. But your original formulation had basically the same problem, but you'd just get an unevaluated g1 (or whatever) instead of error messages.

You might consider making cost an argument to the Function rather than a parameter of g.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.