4
$\begingroup$

I want to define a function based on a random choice from a list of possible functions.

For example, suppose the possible functions are {Sqrt,Log}. Then I want to define f[x] to be a (randomly chosen) one of f[x_]=Sqrt[x] and f[x_]:=Log[x]

What is a good way to do this? (and have it work with user defined functions in the list, like {Sqrt,Log,x^2+x}


My feeling is that I should make a function that takes a list of functions as an input, and randomly chooses one of them. I have an example of this below, but I have three concerns/issues with the below code:

  1. using ?fun1 gives fun1=Log, not fun1=Log[x]
    • I don't know how(/whether) this matters, but something nags at me that it does
  2. If I want a function that is either f[x_]:=Sqrt[x] f[x_]:=Log[x+1], I don't know how to incorporate this "+1" part
  3. I should probably be using := not = in the example code below

I imagine 1 and 3 can likely be corrected by some small tweak to the code, whereas for 2 all I can think of is using Which, but this seem unwieldy for long lists of possible functions.

I don't know how to go about correcting this hence my question.

Example code:

SeedRandom[10];
chooseFun[listFun_] := 
  Module[{randVal}, randVal = RandomInteger[{1, Length[listFun]}];
   listFun[[randVal]]
   ];
fun1 = chooseFun[{Sqrt, Log}];
fun2 = chooseFun[{Sqrt, Log}];

Edit: Note: Its not a requirement that the function take a list of functions as an input. I would be okay, say, defining ListOfFunctions before calling SeedRandom in the below code.

Also, an additional concern/question: Normally when we do something like f[x_]:=x^2 it assigns the RHS to the LHS. But in the case here I dont want to assign the LHS to the RHS, but the something based on the output of the RHS. (Sorry if I have not explained this well)


Edit 2: Heres another attempt I have made. This one uses a function that defines another function (based on a name that is the input).

  • Is this a good approach?
  • Note here ?test gives test[x$_] := listFun[x$][[randNum$61000]]

.

Clear["Global`*"]

SeedRandom[10];
listFun[x_] := {Sqrt[x], Log[x + 1]};
chooseRandFunc[name_] := Module[{randNum},
  randNum = RandomInteger[{1, Length[listFun[x]]}];
  name[x_] := listFun[x][[randNum]]
  ];
chooseRandFunc[test]

Edit 3: It seems the question was not clear, so I went back to try to clarify. Sorry to the existing answers

$\endgroup$
7
  • $\begingroup$ why not simply ClearAll[chooseFun]; chooseFun=RandomChoice? $\endgroup$
    – kglr
    Commented May 22, 2021 at 14:06
  • $\begingroup$ @kglr Honestly, I was not aware of that function. Does chooseFun[x] evaluate properly though, in particular if one of the options is a user defined function like Log[x+1] or x^2_x as opposed to a system one like Log or Sqrt? (I ask because I usually think about f[x_]:=x^2 as saying "take x^2 and replace x by whatever is given", but chooseFun=RandomChoice doesn't take an input which confuses me.) $\endgroup$
    – user106860
    Commented May 22, 2021 at 14:12
  • $\begingroup$ you need to use it as chooseFunb[{Sqrt, Log}]@xx or as fa =chooseFunb[{Sqrt, Log}]; fa@x $\endgroup$
    – kglr
    Commented May 22, 2021 at 14:15
  • $\begingroup$ alternatively, you can define choseFun as ClearAll[chooseFun]; chooseFun := RandomChoice[{Sqrt, Log}]; Then chooseFun[t] gives Sqrt[t] or Log[t] at each invocation. $\endgroup$
    – kglr
    Commented May 22, 2021 at 14:20
  • $\begingroup$ @kglr Sorry I am not understanding stuff, and/or I have not explained my question well. First, why chooseFunb in the earlier comment (i.e. why is there a "b" there?). Second, with ClearAll[chooseFun] chooseFun := RandomChoice[{Sqrt, Log}];, chooseFun[t] would (potentially) switch from Sqrt to Log on different evaluations, wouldn't it? $\endgroup$
    – user106860
    Commented May 22, 2021 at 14:24

1 Answer 1

4
$\begingroup$
Clear["Global`*"]

SeedRandom[10];

Use pure functions and RandomChoice

listFun = {E^# - 1 &, Sqrt, Log[# + 1] &, #^2 &, Sin, Cos};

func[x_] := RandomChoice[listFun][x]

Plot[Evaluate[f = func[x]], {x, 0, 2}, PlotLabel -> f]

enter image description here

Plot[Evaluate@DeleteDuplicates@Table[func[x], 3], {x, 0, 2}, 
 PlotLegends -> "Expressions"]

enter image description here

$\endgroup$
3
  • $\begingroup$ This looks really nice, however I have an issue (sorry if I didn't explain my question well), func[x] can change from being Cos to Sin from one evaluation to the next. I don't want that to be possible. Specifically, I want a function, func[x_]:=, that becomes one of the functions in listFun, and once it becomes one of those functions it no longer changes. Does that make sense? (I think changing := to = might fix this though?) $\endgroup$
    – user106860
    Commented May 22, 2021 at 14:38
  • $\begingroup$ Perhaps another way of saying this is as follows: With the code you have provided ?func gives func[x_] := RandomChoice[listFun][x]. What I want it to be is func[x_]:=Cos[x], or an equivalent version of that (not need to be Cos, I just use Cos as example since that is the first thing you func evaluate to). Then, if I have func1[x_] := RandomChoice[listFun][x], func2[x_] := RandomChoice[listFun][x], func1 might be Sin,Cos, etc, and func2 can possibly be a different one, and so on $\endgroup$
    – user106860
    Commented May 22, 2021 at 14:40
  • 1
    $\begingroup$ Yes Set would give a fixed result. That is what Evaluate does in the plots. $\endgroup$
    – Bob Hanlon
    Commented May 22, 2021 at 14:49

Your Answer

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

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