python - Computing the "closure" of the attributes of an object given functions that change the attributes -
i have object obj
, number of functions
def func1(obj): #... def func2(obj): #... def func3(obj): #...
that each change values of attributes of obj
.
i want input like
obj = myobject() obj.attr=22
this should passed function closure()
computes possible applictions of functions above, meaning func1(func2(obj))
, func3(func1(func1(obj)))
etc. stopping condition (e.g. no more 20 function compositions).
the output should list of possible outputs paths leading there. if, 104
, 93
1 possible final outputs if obj.attr=22
, , there 2 ways arrive @ 104
, 1 arrive @ 93
. then
print closure(obj)
should like
[22, 64, 21, 104] #first path 104 through , func1(obj),func1(func1(obj)), func1(func1(func3(obj))) [22, 73, 104] #second path 104 through , func3(obj),func3(func2(obj)), [22, 11, 93] #the path arrive @ 94
how implement this? suggested in comments, best done trees, although tried 2 days didn't make progress implementing (i'm new python/programming)!
example simple instead of func(obj)
directly use func(22)
example need work on more complicated, need use objects, minimal working example that.
the tree not full n-ary tree, since each function application contain test whether can applied current state (of attributes) of obj
, in cases test fail leaving (the attributes of) obj
unchanged.
here's simple example tries find whether number (goal
) predecessor of (inital_state
) when applying rule in collatz conjecture.
in example, obj
state
, , [func1, func2, ...]
functions
in example. version return path final output, minimizing number of function applications. instead of searching, can list states removing goal test , returning prev_states
after loop finishes.
from collections import deque def multiply_by_two(x): return x * 2 def sub_one_div_three(x): if (x - 1) % 3 == 0: return (x - 1) // 3 else: return none # invalid functions = [multiply_by_two, sub_one_div_three] # find path given function def bfs(initial_state, goal): initial_path = [] states = deque([(initial_state, initial_path)]) # deque of 2-tuples: (state, list of functions there) prev_states = {initial_state} # keep track of visited states avoid infinite loop while states: # print(list(map(lambda x: x[0], states))) # print states, not paths. useful see what's going on state, path = states.popleft() func in functions: new_state = func(state) if new_state == goal: # goal test: if found state, we're done return new_state, path + [func] if (new_state not none , # check state valid new_state not in prev_states): # , state hasn't been visited states.append((new_state, path + [func])) prev_states.add(new_state) # make sure state won't added again else: raise exception("could not state") print(functions) print(bfs(1, 5)) # prints (5, [<function multiply_by_two @ 0x000002e746727f28>, <function multiply_by_two @ 0x000002e746727f28>, <function multiply_by_two @ 0x000002e746727f28>, <function multiply_by_two @ 0x000002e746727f28>, <function sub_one_div_three @ 0x000002e7493c9400>]). can extract path here.
Comments
Post a Comment