Open JayDeng2837 opened 7 years ago
The generation of trees is done randomly while making sure type constraints are respected. If any primitive has an input type that no primitive and terminal can provide, chances are that this primitive will be picked and placed in the tree, resulting in the impossibility to complete the tree within the limit fixed by the generator. For example, when generating a full tree of height 2, suppose "op" takes a boolean and a float, "and" takes 2 boolean and "neg" takes a float, no terminal is defined and the arguments are booleans. The following situation will occur where no terminal can be placed to complete the tree.
In this case, DEAP raises an IndexError with the message "The gp.generate function tried to add a terminal of type float, but there is none available."
Alleast one relation should be there for each type
Input args -> return args
np.ndarray -> float
float -> np.ndarray
and you were missing the 1st case
For all primitive you have used should atleast have one terminals for them
and you are missing the 2nd case
pset = gp.PrimitiveSetTyped("MAIN", [np.ndarray, np.ndarray],np.ndarray, 2)
pset.addPrimitive(numpy.add, [np.ndarray, np.ndarray],np.ndarray, name="vadd")
pset.addPrimitive(numpy.subtract, [np.ndarray, np.ndarray] ,np.ndarray, name="vsub")
pset.addPrimitive(numpy.multiply, [np.ndarray, np.ndarray] ,np.ndarray, name="vmul")
pset.addPrimitive(numpy.multiply, [np.ndarray, float] ,np.ndarray, name="fmul")
pset.addPrimitive(numpy.negative, [np.ndarray] ,np.ndarray, name="vneg")
def dummy_primitive_for_numpyarray_to_float(numpy_array):
# and you have handle this return in each method
return None
pset.addPrimitive(dummy_primitive_for_numpyarray_to_float, [np.ndarray] ,float, name="dummy_primitive")
# adding many ephemeral constants
for i in range(300):
pset.addEphemeralConstant("rand%s"%i, lambda: random.randint(-1,1), float)
# dummy terminal
pset.addTerminal("dummy_terminal",lamda: None, np.ndarray)
pset.renameArguments(ARG0='x')
pset.renameArguments(ARG1='y')
toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=10)
You have keep in mind that all dummy terminals and primitive shouldn't get selected.
p.s. - I'm terrible at explaining things. Sorry for that.
This is a bug here: https://github.com/DEAP/deap/blob/master/deap/gp.py#L634
Basically it should not check the condition if either terminals or primitives are not available. Both not being available would be a legitimate error. I can make a PR for it.
Hi,
I was trying to formulate a problem two numpy arrays as terminals and undetermined number of random floats as ephemeral constants. (these random floats are the second input for function fmul that multiples an numpy array with a float).
The tree depth is limited to 10 and I added 300 constants, however i still get the following error.... is there a way to fix it? thanks.
IndexError: The gp.generate function tried to add a primitive of type '<type 'float'>', but there is none available.
`pset = gp.PrimitiveSetTyped("MAIN", [np.ndarray, np.ndarray],np.ndarray, 2) pset.addPrimitive(numpy.add, [np.ndarray, np.ndarray],np.ndarray, name="vadd") pset.addPrimitive(numpy.subtract, [np.ndarray, np.ndarray] ,np.ndarray, name="vsub") pset.addPrimitive(numpy.multiply, [np.ndarray, np.ndarray] ,np.ndarray, name="vmul") pset.addPrimitive(numpy.multiply, [np.ndarray, float] ,np.ndarray, name="fmul") pset.addPrimitive(numpy.negative, [np.ndarray] ,np.ndarray, name="vneg")
adding many ephemeral constants
for i in range(300): pset.addEphemeralConstant("rand%s"%i, lambda: random.randint(-1,1), float)
pset.renameArguments(ARG0='x') pset.renameArguments(ARG1='y') toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min=1, max=10)`