package org.oakgp.mutate;

import org.oakgp.NodeEvolver;
import org.oakgp.PrimitiveSet;
import org.oakgp.function.Function;
import org.oakgp.node.FunctionNode;
import org.oakgp.node.Node;
import org.oakgp.selector.NodeSelector;
import org.oakgp.util.Random;
import org.oakgp.util.Utils;

/** Performs mutation (also known as node replacement mutation). */
public final class PointMutation implements NodeEvolver {
   private final Random random;
   private final PrimitiveSet primitiveSet;

   public PointMutation(Random random, PrimitiveSet primitiveSet) {
      this.random = random;
      this.primitiveSet = primitiveSet;
   }

   @Override
   public Node evolve(NodeSelector selector) {
      Node root = selector.next();
      int mutationPoint = Utils.selectSubNodeIndex(root, random);
      return root.replaceAt(mutationPoint, node -> {
         if (node.getNodeType().isFunction()) {
            FunctionNode functionNode = (FunctionNode) node;
            Function function = primitiveSet.nextAlternativeFunction(functionNode.getFunction());
            return new FunctionNode(function, functionNode.getArguments());
         } else {
            return primitiveSet.nextAlternativeTerminal(node);
         }
      });
   }
}

@@ -20,16 +20,64 @@
 utate;%0A%0A
+import static org.oakgp.util.Utils.isFunction;%0A%0A
 import o
@@ -905,27 +905,8 @@
 if (
-node.getNodeType().
 isFu
@@ -912,16 +912,20 @@
 unction(
+node
 )) %7B%0A   

use Utils.isFunction