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$ 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$ 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$ 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$ 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$ 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$ 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$ 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$ Commented May 22, 2021 at 14:49

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.