Python- np.random.choice

Question:

I am using the numpy.random.choice module to generate an ‘array’ of choices based on an array of functions:

def f(x):
    return np.sin(x)

def g(x):
    return np.cos(x)


base=[f, g]

funcs=np.random.choice(base,size=2)

This code will produce an ‘array’ of 2 items referencing a function from the base array.

The reason for this post is, I have printed the outcome of funcs and recieved:

[<function f at 0x00000225AC94F0D0> <function f at 0x00000225AC94F0D0>]

Clearly this returns a reference to the functions in some form, not that I understand what that form is or how to manipulate it, this is where the problem comes in. I want to change the choice of function, so that it is no longer random and instead depends on some conditions, so it might be:

for i in range(2):
    if testvar=='true':
        choice[i] = 0 
    if testvar== 'false':
        choice[i] = 1

This would return an array of indicies to be put in later function

The problem is, the further operations of the code (I think) require this previous form of function reference: [ ] as an input, instead of a simple array of 0,1 Indicies and I don’t know how I can get an array of form [ ] by using if statements.

I could be completely wrong about the rest of the code requiring this input, but I don’t know how I can amend it, so am hence posting it here. The full code is as follows: (it is a slight variation of code provided by @Attack68 on Evolving functions in python) It aims to store a function that is multiplied by a random function on each iteration and integrates accordingly. (I have put a comment on the code above the function that is causing the problem)

import numpy as np
import scipy.integrate as int

def f(x):
    return np.sin(x)

def g(x):
    return np.cos(x)

base = [f, g]

funcs = np.random.choice(base, size=2)
print(funcs)
#The below function is where I believe the [<function...>] input to be required
def apply(x, funcs):
    y = 1
    for func in funcs:
        y *= func(x)
    return y

print('function value at 1.5 ', apply(1.5, funcs))

answer = int.quad(apply, 1, 2, args=(funcs,))
print('integration over [1,2]: ', answer)

Here is my attempt of implementing a non-random event:

import numpy as np
import scipy.integrate as int
import random
def f(x):
    return np.sin(x)

def g(x):
    return np.cos(x)

base = [f, g]

funcs = list()
for i in range(2):
    testvar=random.randint(0,100) #In my actual code, this would not be random but dependent on some other situation I have not accounted for here
    if testvar>50:
        func_idx = 0 # choose a np.random operation: 0=f, 1=g
    else:
        func_idx= 1
    funcs.append(func_idx)
#funcs = np.random.choice(base, size=10)
print(funcs)
def apply(x, funcs):
    y = 1
    for func in funcs:
        y *= func(x)
    return y

print('function value at 1.5 ', apply(1.5, funcs))

answer = int.quad(apply, 1, 2, args=(funcs,))
print('integration over [1,2]: ', answer)

This returns the following error:

TypeError: 'int' object is not callable
Asked By: George

||

Answers:

If you still want to use your function apply as-is, you need to keep your input a list of functions. Instead of providing a list of indices, you can use those indices to create your list of functions.

Instead of apply(1.5, funcs), try:

apply(1.5, [base(n) for n in funcs])
Answered By: busybear

If: You are trying to refactor your original code that operates on a list of randomly chosen functions to a version that operates with random indices which correspond to items in a list of functions. Refactor apply.

def apply(x,indices,base=base):
    y = 1
    for i in indices:
        f = base[i]
        y *= f(x)
    return y

…this returns a reference to the functions in some form, not that I understand what that form is or how to manipulate it…

Functions are objects, the list contains a reference to the objects themselves. They can be used by either assigning them to a name then calling them or indexing the list and calling the object:

>>> def f():
...     return 'f'

>>> def g():
...     return 'g'

>>> a = [f,g]
>>> q = a[0]
>>> q()
'f'
>>> a[1]()
'g'
>>> for thing in a:
    print(thing())

f
g

Or you can pass them around:

>>> def h(thing):
...     return thing()

>>> h(a[1])
'g'
>>>
Answered By: wwii
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.