Hey @krono86 ,
I see that you are trying to use Numba for a recursive generator function, but it seems that Numba encounters difficulties when deriving machine code from a dynamic generator function. Numba’s strength lies in cases where data types can be inferred statically.
@DannyWeitekamp’s suggestion to refactor the code or consider an alternative algorithm, such as an iterative solution for set partitions, is a practical approach that should work. One option is to replace the generator with a typed list. Below are some basic examples using typed lists.
from numba import njit, int64
from numba.typed import List
@njit
def func_recursive_nb(n):
codes = List.empty_list(int64)
if n == 0:
codes = [0]
return codes
else:
codes = func_recursive_nb(n - 1)
new_codes = []
for code in codes[::-1]:
new_codes.append(2**(n-1) + code)
return codes + new_codes
@njit
def func_iterative_nb(n):
codes = List.empty_list(int64)
codes = [0]
for i in range(n):
new_codes = []
for code in codes[::-1]:
new_codes.append(2**i + code)
codes += new_codes
return codes
@njit
def func_generator_iterative_nb(n):
codes = List.empty_list(int64)
codes = [0]
yield 0
for i in range(n):
for code in codes[::-1]:
yield 2**i + code
codes += [2**i + code for code in codes[::-1]]
@njit
def func_generator_recursive_nb(n):
"""Remark: Result is different by design; Code will fail in nopython mode."""
if n == 0:
yield 0
else:
yield from func_recursive_nb(n - 1)
for code in func_recursive_nb(n - 1):
yield 2**(n-1) + code
func_recursive = func_recursive_nb.py_func
func_iterative = func_iterative_nb.py_func
func_generator_iterative = func_generator_iterative_nb.py_func
func_generator_recursive = func_generator_recursive_nb.py_func
print('recursive:')
print(func_recursive(3))
print(func_recursive_nb(3))
print('iterative:')
print(func_iterative(3))
print(func_iterative_nb(3))
print('generator (iterative):')
print(list(func_generator_iterative(3)))
print(list(func_generator_iterative_nb(3)))
print('generator (recursive):')
print(list(func_generator_recursive(3)))
print(list(func_generator_recursive_nb(3)))
# recursive:
# [0, 1, 3, 2, 6, 7, 5, 4]
# [0, 1, 3, 2, 6, 7, 5, 4]
# iterative:
# [0, 1, 3, 2, 6, 7, 5, 4]
# [0, 1, 3, 2, 6, 7, 5, 4]
# generator (iterative):
# [0, 1, 3, 2, 6, 7, 5, 4]
# [0, 1, 3, 2, 6, 7, 5, 4]
# generator (recursive):
# [0, 1, 3, 2, 4, 5, 7, 6]
# UnsupportedError: Use of unsupported opcode (GET_YIELD_FROM_ITER) found