Protected division replaces ordinary division when the denominator produces an invalid result, allowing numerical expressions to continue with a defined fallback value. section 4.1.1
A NumPy implementation handles both scalar and array evaluation:
- Suppresses divide-by-zero and invalid-operation warnings while computing the quotient. section 4.1.1
- Replaces infinities and NaNs with 1 for array results and scalar results. section 4.1.1
- Registers the protected operator in a genetic-programming primitive set so evolved expressions remain evaluable. section 4.1.1
Symbolic regression
A genetic-programming regression uses protected division while evolving expressions over four NumPy inputs. The compiled expression is evaluated across 10,000 rows, and squared error measures fitness against the generated target. section 4.1.1
Listing 4.1 EDL_4_1_GP_Regression.ipynb: Setting up the expression
pset = gp.PrimitiveSet("MAIN", 4) #1
pset.addPrimitive(np.add, 2, name="vadd") #2
pset.addPrimitive(np.subtract, 2, name="vsub")
pset.addPrimitive(np.multiply, 2, name="vmul")
pset.addPrimitive(protectedDiv, 2)
pset.addPrimitive(np.negative, 1, name="vneg")
pset.addPrimitive(np.cos, 1, name="vcos")
pset.addPrimitive(np.sin, 1, name="vsin")
pset.addEphemeralConstant("rand101", lambda:
random.randint(-1,1)) #3
pset.renameArguments(ARG0='x1') #4
pset.renameArguments(ARG1='x2')
pset.renameArguments(ARG2='x3')
pset.renameArguments(ARG3='x4')
Inspect the primitive-set setup that adds protected division alongside arithmetic, trigonometric, and negation operators. section 4.1.1
