/** Returns true if inner1 can feasibly be swapped into inner2's position. */
  public boolean verifyPoints(
      final GPInitializer initializer, final GPNode inner1, final GPNode inner2) {
    // first check to see if inner1 is swap-compatible with inner2
    // on a type basis
    if (!inner1.swapCompatibleWith(initializer, inner2)) return false;

    // next check to see if inner1 can fit in inner2's spot
    if (inner1.depth() + inner2.atDepth() > maxDepth) return false;

    // check for size
    // NOTE: this is done twice, which is more costly than it should be.  But
    // on the other hand it allows us to toss a child without testing both times
    // and it's simpler to have it all here in the verifyPoints code.
    if (maxSize != NO_SIZE_LIMIT) {
      // first easy check
      int inner1size = inner1.numNodes(GPNode.NODESEARCH_ALL);
      int inner2size = inner2.numNodes(GPNode.NODESEARCH_ALL);
      if (inner1size > inner2size) // need to test further
      {
        // let's keep on going for the more complex test
        GPNode root2 = ((GPTree) (inner2.rootParent())).child;
        int root2size = root2.numNodes(GPNode.NODESEARCH_ALL);
        if (root2size - inner2size + inner1size
            > maxSize) // take root2, remove inner2 and swap in inner1.  Is it still small enough?
        return false;
      }
    }

    // checks done!
    return true;
  }
Example #2
0
 public void checkConstraints(
     final EvolutionState state,
     final int tree,
     final GPIndividual typicalIndividual,
     final Parameter individualBase) {
   super.checkConstraints(state, tree, typicalIndividual, individualBase);
   if (children.length != 0)
     state.output.error(
         "Incorrect number of children for node " + toStringForError() + " at " + individualBase);
 }
  public GPNode newRootedTree(
      final EvolutionState state,
      GPType type,
      final int thread,
      final GPNodeParent parent,
      final GPFunctionSet set,
      final int argposition,
      int requestedSize) {
    // ptc2 can mess up if there are no available terminals for a given type.  If this occurs,
    // and we find ourselves unable to pick a terminal when we want to do so, we will issue a
    // warning,
    // and pick a nonterminal, violating the ptc2 size and depth contracts.  This can lead to
    // pathological situations
    // where the system will continue to go on and on unable to stop because it can't pick a
    // terminal,
    // resulting in running out of memory or some such.  But there are cases where we'd want to let
    // this work itself out.
    boolean triedTerminals = false;

    if (!(set instanceof PTCFunctionSetForm))
      state.output.fatal(
          "Set "
              + set.name
              + " is not of the class ec.gp.build.PTCFunctionSetForm, and so cannot be used with PTC Nodebuilders.");

    PTCFunctionSetForm pset = (PTCFunctionSetForm) set;

    // pick a size from the distribution
    if (requestedSize == NOSIZEGIVEN) requestedSize = pickSize(state, thread);

    GPNode root;

    int t = type.type;
    GPNode[] terminals = set.terminals[t];
    GPNode[] nonterminals = set.nonterminals[t];
    GPNode[] nodes = set.nodes[t];

    if (nodes.length == 0) errorAboutNoNodeWithType(type, state); // total failure

    // return a terminal
    if ((requestedSize == 1
            || // Now pick a terminal if our size is 1
            warnAboutNonterminal(nonterminals.length == 0, type, false, state))
        && // OR if there are NO nonterminals!
        (triedTerminals = true)
        && // [first set triedTerminals]
        terminals.length != 0) // AND if there are available terminals
    {
      root =
          (GPNode)
              terminals[
                  RandomChoice.pickFromDistribution(
                      pset.terminalProbabilities(t),
                      state.random[thread].nextFloat(),
                      CHECK_BOUNDARY)]
                  .lightClone();
      root.resetNode(state, thread); // give ERCs a chance to randomize
      root.argposition = (byte) argposition;
      root.parent = parent;
    } else // return a nonterminal-rooted tree
    {
      if (triedTerminals)
        warnAboutNoTerminalWithType(
            type, false, state); // we tried terminals and we're here because there were none!

      // pick a nonterminal
      root =
          (GPNode)
              nonterminals[
                  RandomChoice.pickFromDistribution(
                      pset.nonterminalProbabilities(t),
                      state.random[thread].nextFloat(),
                      CHECK_BOUNDARY)]
                  .lightClone();
      root.resetNode(state, thread); // give ERCs a chance to randomize
      root.argposition = (byte) argposition;
      root.parent = parent;

      // set the depth, size, and enqueuing, and reset the random dequeue

      s_size = 0; // pretty critical!
      int s = 1;
      GPInitializer initializer = ((GPInitializer) state.initializer);
      GPType[] childtypes = root.constraints(initializer).childtypes;
      for (int x = 0; x < childtypes.length; x++) enqueue(root, x, 1); /* depth 1 */

      while (s_size > 0) {
        triedTerminals = false;
        randomDequeue(state, thread);
        type = dequeue_node.constraints(initializer).childtypes[dequeue_argpos];

        int y = type.type;
        terminals = set.terminals[y];
        nonterminals = set.nonterminals[y];
        nodes = set.nodes[y];

        if (nodes.length == 0) errorAboutNoNodeWithType(type, state); // total failure

        // pick a terminal
        if ((s_size + s >= requestedSize
                || // if we need no more nonterminal nodes
                dequeue_depth == maxDepth
                || // OR if we're at max depth and must pick a terminal
                warnAboutNonterminal(nonterminals.length == 0, type, false, state))
            && // OR if there are NO nonterminals!
            (triedTerminals = true)
            && // [first set triedTerminals]
            terminals.length != 0) // AND if there are available terminals
        {
          GPNode n =
              (GPNode)
                  terminals[
                      RandomChoice.pickFromDistribution(
                          pset.terminalProbabilities(y),
                          state.random[thread].nextFloat(),
                          CHECK_BOUNDARY)]
                      .lightClone();
          dequeue_node.children[dequeue_argpos] = n;
          n.resetNode(state, thread); // give ERCs a chance to randomize
          n.argposition = (byte) dequeue_argpos;
          n.parent = dequeue_node;
        }

        // pick a nonterminal and enqueue its children
        else {
          if (triedTerminals)
            warnAboutNoTerminalWithType(
                type, false, state); // we tried terminals and we're here because there were none!

          GPNode n =
              (GPNode)
                  nonterminals[
                      RandomChoice.pickFromDistribution(
                          pset.nonterminalProbabilities(y),
                          state.random[thread].nextFloat(),
                          CHECK_BOUNDARY)]
                      .lightClone();
          dequeue_node.children[dequeue_argpos] = n;
          n.resetNode(state, thread); // give ERCs a chance to randomize
          n.argposition = (byte) dequeue_argpos;
          n.parent = dequeue_node;

          childtypes = n.constraints(initializer).childtypes;
          for (int x = 0; x < childtypes.length; x++) enqueue(n, x, dequeue_depth + 1);
        }
        s++;
      }
    }

    return root;
  }
  public int produce(
      final int min,
      final int max,
      final int start,
      final int subpopulation,
      final Individual[] inds,
      final EvolutionState state,
      final int thread) {

    // how many individuals should we make?
    int n = typicalIndsProduced();
    if (n < min) n = min;
    if (n > max) n = max;

    // should we bother?
    if (!state.random[thread].nextBoolean(likelihood))
      return reproduce(
          n,
          start,
          subpopulation,
          inds,
          state,
          thread,
          true); // DO produce children from source -- we've not done so already

    // random select one tree from treelib
    // int treeIndex = (new Random()).nextInt(state.maxTreelibSize);

    // GPNode TR = state.treelib[treeIndex];
    // create tree: 1 - TR
    GPNode OneSubTR = (GPNode) (((GPNode[]) fs.nodesByName.get("-"))[0]).lightClone();
    OneSubTR.children = new GPNode[2];

    RegERC oneNode = new RegERC();
    oneNode.constraints = 6;
    oneNode.children = new GPNode[0];
    oneNode.value = 1;

    OneSubTR.children[0] = oneNode;

    GPInitializer initializer = ((GPInitializer) state.initializer);

    for (int q = start; q < n + start; /* no increment */ ) // keep on going until we're filled up
    {
      // grab two individuals from our sources
      if (sources[0] == sources[1]) // grab from the same source
      sources[0].produce(2, 2, 0, subpopulation, parents, state, thread);
      else // grab from different sources
      {
        sources[0].produce(1, 1, 0, subpopulation, parents, state, thread);
        sources[1].produce(1, 1, 1, subpopulation, parents, state, thread);
      }

      // at this point, parents[] contains our two selected individuals

      // random select one tree from treelib
      int treeIndex = (new Random()).nextInt(state.maxTreelibSize);
      GPNode TR = state.treelib[treeIndex];

      OneSubTR.children[1] = (GPNode) TR.clone();

      double[] randomSemanticTraining = state.semanticTreelibTraining[treeIndex];
      double[] randomSemanticTesting = state.semanticTreelibTesting[treeIndex];

      // are our tree values valid?
      if (tree1 != TREE_UNFIXED && (tree1 < 0 || tree1 >= parents[0].trees.length))
        // uh oh
        state.output.fatal(
            "GP Crossover Pipeline attempted to fix tree.0 to a value which was out of bounds of the array of the individual's trees.  Check the pipeline's fixed tree values -- they may be negative or greater than the number of trees in an individual");
      if (tree2 != TREE_UNFIXED && (tree2 < 0 || tree2 >= parents[1].trees.length))
        // uh oh
        state.output.fatal(
            "GP Crossover Pipeline attempted to fix tree.1 to a value which was out of bounds of the array of the individual's trees.  Check the pipeline's fixed tree values -- they may be negative or greater than the number of trees in an individual");

      int t1 = 0;
      int t2 = 0;
      if (tree1 == TREE_UNFIXED || tree2 == TREE_UNFIXED) {
        do
        // pick random trees  -- their GPTreeConstraints must be the same
        {
          if (tree1 == TREE_UNFIXED)
            if (parents[0].trees.length > 1)
              t1 = state.random[thread].nextInt(parents[0].trees.length);
            else t1 = 0;
          else t1 = tree1;

          if (tree2 == TREE_UNFIXED)
            if (parents[1].trees.length > 1)
              t2 = state.random[thread].nextInt(parents[1].trees.length);
            else t2 = 0;
          else t2 = tree2;
        } while (parents[0].trees[t1].constraints(initializer)
            != parents[1].trees[t2].constraints(initializer));
      } else {
        t1 = tree1;
        t2 = tree2;
        // make sure the constraints are okay
        if (parents[0].trees[t1].constraints(initializer)
            != parents[1].trees[t2].constraints(initializer)) // uh oh
        state.output.fatal(
              "GP Crossover Pipeline's two tree choices are both specified by the user -- but their GPTreeConstraints are not the same");
      }

      // number of crossover
      state.numOfSGX[state.generation][0] += 1;

      GPIndividual child1 = (GPIndividual) (parents[0].lightClone());
      child1.trees[0].semanticTraining = new double[randomSemanticTraining.length];
      child1.trees[0].semanticTesting = new double[randomSemanticTesting.length];

      GPIndividual child2 = null;
      if (n - (q - start) >= 2 && !tossSecondParent) {
        child2 = (GPIndividual) (parents[1].lightClone());
        child2.trees[0].semanticTraining = new double[randomSemanticTraining.length];
        child2.trees[0].semanticTesting = new double[randomSemanticTesting.length];
      }

      // geometric semantic crossover on training set
      for (int i = 0; i < parents[0].trees[0].semanticTraining.length; i++) {
        child1.trees[0].semanticTraining[i] =
            randomSemanticTraining[i] * parents[0].trees[0].semanticTraining[i]
                + (1 - randomSemanticTraining[i]) * parents[1].trees[0].semanticTraining[i];
        child1.evaluated = false;

        if (child2 != null) {
          child2.trees[0].semanticTraining[i] =
              (1 - randomSemanticTraining[i]) * parents[0].trees[0].semanticTraining[i]
                  + randomSemanticTraining[i] * parents[1].trees[0].semanticTraining[i];
          child2.evaluated = false;
        }
      }

      // geometric semantic crossover on testing set
      for (int i = 0; i < parents[0].trees[0].semanticTesting.length; i++) {
        child1.trees[0].semanticTesting[i] =
            randomSemanticTesting[i] * parents[0].trees[0].semanticTesting[i]
                + (1 - randomSemanticTesting[i]) * parents[1].trees[0].semanticTesting[i];

        if (child2 != null) {
          child2.trees[0].semanticTesting[i] =
              (1 - randomSemanticTesting[i]) * parents[0].trees[0].semanticTesting[i]
                  + randomSemanticTesting[i] * parents[1].trees[0].semanticTesting[i];
        }
      }

      // add the individuals to the population
      inds[q] = child1;
      q++;
      if (q < n + start && !tossSecondParent) {
        inds[q] = child2;
        q++;
      }
    }
    return n;
  }
  public void setup(final EvolutionState state, final Parameter base) {
    super.setup(state, base);

    Parameter def = defaultBase();
    Parameter p = base.push(P_NODESELECTOR).push("0");
    Parameter d = def.push(P_NODESELECTOR).push("0");

    nodeselect1 =
        (GPNodeSelector) (state.parameters.getInstanceForParameter(p, d, GPNodeSelector.class));
    nodeselect1.setup(state, p);

    p = base.push(P_NODESELECTOR).push("1");
    d = def.push(P_NODESELECTOR).push("1");

    if (state.parameters.exists(p, d) && state.parameters.getString(p, d).equals(V_SAME))
      // can't just copy it this time; the selectors
      // use internal caches.  So we have to clone it no matter what
      nodeselect2 = (GPNodeSelector) (nodeselect1.clone());
    else {
      nodeselect2 =
          (GPNodeSelector) (state.parameters.getInstanceForParameter(p, d, GPNodeSelector.class));
      nodeselect2.setup(state, p);
    }

    numTries = state.parameters.getInt(base.push(P_NUM_TRIES), def.push(P_NUM_TRIES), 1);
    if (numTries == 0)
      state.output.fatal(
          "GPCrossover Pipeline has an invalid number of tries (it must be >= 1).",
          base.push(P_NUM_TRIES),
          def.push(P_NUM_TRIES));

    maxDepth = state.parameters.getInt(base.push(P_MAXDEPTH), def.push(P_MAXDEPTH), 1);
    if (maxDepth == 0)
      state.output.fatal(
          "GPCrossover Pipeline has an invalid maximum depth (it must be >= 1).",
          base.push(P_MAXDEPTH),
          def.push(P_MAXDEPTH));

    maxSize = NO_SIZE_LIMIT;
    if (state.parameters.exists(base.push(P_MAXSIZE), def.push(P_MAXSIZE))) {
      maxSize = state.parameters.getInt(base.push(P_MAXSIZE), def.push(P_MAXSIZE), 1);
      if (maxSize < 1) state.output.fatal("Maximum tree size, if defined, must be >= 1");
    }

    tree1 = TREE_UNFIXED;
    if (state.parameters.exists(base.push(P_TREE).push("" + 0), def.push(P_TREE).push("" + 0))) {
      tree1 =
          state.parameters.getInt(base.push(P_TREE).push("" + 0), def.push(P_TREE).push("" + 0), 0);
      if (tree1 == -1) state.output.fatal("Tree fixed value, if defined, must be >= 0");
    }

    tree2 = TREE_UNFIXED;
    if (state.parameters.exists(base.push(P_TREE).push("" + 1), def.push(P_TREE).push("" + 1))) {
      tree2 =
          state.parameters.getInt(base.push(P_TREE).push("" + 1), def.push(P_TREE).push("" + 1), 0);
      if (tree2 == -1) state.output.fatal("Tree fixed value, if defined, must be >= 0");
    }
    tossSecondParent = state.parameters.getBoolean(base.push(P_TOSS), def.push(P_TOSS), false);

    GPInitializer initializer = ((GPInitializer) state.initializer);
    fs = initializer.treeConstraints[0].functionset;

    templateTree = (GPNode) (((GPNode[]) fs.nodesByName.get("+"))[0]).lightClone();
    GPNode left = (GPNode) (((GPNode[]) fs.nodesByName.get("*"))[0]).lightClone();
    GPNode right = (GPNode) (((GPNode[]) fs.nodesByName.get("*"))[0]).lightClone();
    // RegERC ercNode1 = (RegERC)((((GPNode[])fs.nodesByName.get("ERC"))[0]).lightClone());
    //
    // generate TR node that will be replated by random tree
    // GPNode TRNode = new GPNode();
    // ercNode.constraints = 6;
    // ercNode.children = new GPNode[0];

    templateTree.children = new GPNode[2];
    templateTree.children[0] = left;
    templateTree.children[1] = right;

    left.children = new GPNode[2];
    left.children[0] = null;
    left.children[1] = null;

    right.children = new GPNode[2];
    right.children[0] = null;
    right.children[1] = null;
  }