Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 18.43 KB | None | 0 0
  1. /* Copyright 2009-2016 David Hadka
  2.  *
  3.  * This file is part of the MOEA Framework.
  4.  *
  5.  * The MOEA Framework is free software: you can redistribute it and/or modify
  6.  * it under the terms of the GNU Lesser General Public License as published by
  7.  * the Free Software Foundation, either version 3 of the License, or (at your
  8.  * option) any later version.
  9.  *
  10.  * The MOEA Framework is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  12.  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  13.  * License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public License
  16.  * along with the MOEA Framework.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18. package org.moeaframework.util.tree;
  19.  
  20. /**
  21.  * A node in an expression tree.  Expression trees are strongly typed, meaning
  22.  * nodes have defined return types and argument types.  The return type of all
  23.  * nodes must match the argument type from its parent node.
  24.  */
  25. public abstract class Node {
  26.    
  27.     /**
  28.      * {@code true} if this node should not be modified, altered or replaced;
  29.      * {@code false} otherwise.
  30.      */
  31.     private boolean fixed;
  32.  
  33.     /**
  34.      * The parent of this node; or {@code null} if this node has no parent.
  35.      */
  36.     private Node parent;
  37.  
  38.     /**
  39.      * The arguments (children) of this node.
  40.      */
  41.     private final Node[] arguments;
  42.    
  43.     /**
  44.      * The return type of this node.
  45.      */
  46.     private final Class<?> returnType;
  47.    
  48.     /**
  49.      * The types of the arguments (children) of this node.
  50.      */
  51.     private final Class<?>[] argumentTypes;
  52.    
  53.     /**
  54.      * Constructs a new node.
  55.      */
  56.     public Node() {
  57.         this(Void.class);
  58.     }
  59.  
  60.     /**
  61.      * Constructs a new node with the given return type and argument types.
  62.      *
  63.      * @param returnType the return type of the node
  64.      * @param argumentTypes the type of the arguments, if any, for the node
  65.      */
  66.     public Node(Class<?> returnType, Class<?>... argumentTypes) {
  67.         super();
  68.         this.returnType = returnType;
  69.         this.argumentTypes = argumentTypes;
  70.        
  71.         arguments = new Node[argumentTypes.length];
  72.     }
  73.    
  74.     /**
  75.      * Calls {@link #setFixed(boolean)} on all nodes in the subtree rooted at
  76.      * this node.
  77.      *
  78.      * @param fixed {@code true} if all nodes in the subtree rooted at this
  79.      *        node should not be modified, altered, or replaced; {@code false}
  80.      *        otherwise
  81.      */
  82.     public void setFixedTree(boolean fixed) {
  83.         setFixed(fixed);
  84.        
  85.         for (Node argument : arguments) {
  86.             if (argument != null) {
  87.                 argument.setFixedTree(fixed);
  88.             }
  89.         }
  90.     }
  91.    
  92.     /**
  93.      * Set to {@code true} if this node should not be modified, altered, or
  94.      * replaced; {@code false} otherwise.
  95.      *
  96.      * @param fixed {@code true} if this node should not be modified, altered,
  97.      *        or replaced; {@code false} otherwise
  98.      */
  99.     public void setFixed(boolean fixed) {
  100.         this.fixed = fixed;
  101.     }
  102.    
  103.     /**
  104.      * Returns {@code true} if this node should not be modified, altered, or
  105.      * replaced; {@code false} otherwise.
  106.      *
  107.      * @return {@code true} if this node should not be modified, altered, or
  108.      *         replaced; {@code false} otherwise
  109.      */
  110.     public boolean isFixed() {
  111.         return fixed;
  112.     }
  113.  
  114.     /**
  115.      * Returns the number of arguments (child nodes) of this node.
  116.      *
  117.      * @return the number of arguments (child nodes) of this node
  118.      */
  119.     public int getNumberOfArguments() {
  120.         return argumentTypes.length;
  121.     }
  122.  
  123.     /**
  124.      * Returns the argument (child node) at the specified index.
  125.      *
  126.      * @param index the index of çthe argument to return
  127.      * @return the argument (child node) at the specified index
  128.      */
  129.     public Node getArgument(int index) {
  130.         return arguments[index];
  131.     }
  132.  
  133.     /**
  134.      * Returns the parent of this node; or {@code null} if this node has no
  135.      * parent.
  136.      *
  137.      * @return the parent of this node; or {@code null} if this node has no
  138.      *         parent
  139.      */
  140.     public Node getParent() {
  141.         return parent;
  142.     }
  143.  
  144.     /**
  145.      * Sets the parent of this node.
  146.      *
  147.      * @param parent the parent of this node
  148.      */
  149.     void setParent(Node parent) {
  150.         this.parent = parent;
  151.     }
  152.    
  153.     /**
  154.      * Returns the return type of this node.
  155.      *
  156.      * @return the return type of this node
  157.      */
  158.     public Class<?> getReturnType() {
  159.         return returnType;
  160.     }
  161.    
  162.     /**
  163.      * Returns the type of the argument (child node) at the specified index.
  164.      *
  165.      * @param index the index of the argument
  166.      * @return the type of the argument (child node) at the specified index
  167.      */
  168.     public Class<?> getArgumentType(int index) {
  169.         return argumentTypes[index];
  170.     }
  171.  
  172.     /**
  173.      * Sets the argument (child node) at the specified index.
  174.      *
  175.      * @param index the index of the new argument
  176.      * @param expression the expression defining the argument
  177.      * @return a reference to this node, allowing multiple calls to be chained
  178.      *         together
  179.      */
  180.     public Node setArgument(int index, Node expression) {
  181.         expression.setParent(this);
  182.         arguments[index] = expression;
  183.         return this;
  184.     }
  185.    
  186.     /**
  187.      * Returns the number of nodes contained in the tree rooted at this node.
  188.      *
  189.      * @return the number of nodes contained in the tree rooted at this node
  190.      */
  191.     public int size() {
  192.         int size = 0;
  193.        
  194.         for (Node argument : arguments) {
  195.             size += argument.size();
  196.         }
  197.        
  198.         return size + 1;
  199.     }
  200.  
  201.     /**
  202.      * Returns the depth of this node, which is the number of branches between
  203.      * this node and the root.
  204.      *
  205.      * @return the depth of this node
  206.      */
  207.     public int getDepth() {
  208.         if (parent == null) {
  209.             return 0;
  210.         } else {
  211.             return parent.getDepth() + 1;
  212.         }
  213.     }
  214.  
  215.     /**
  216.      * Returns the number of branches between this node and the nearest leaf.
  217.      *
  218.      * @return the number of branches between this node and the nearest leaf
  219.      */
  220.     public int getMinimumHeight() {
  221.         if (arguments.length == 0) {
  222.             return 0;
  223.         } else {
  224.             int height = Integer.MAX_VALUE;
  225.            
  226.             for (Node argument : arguments) {
  227.                 height = Math.min(height, argument.getMinimumHeight());
  228.             }
  229.            
  230.             return height + 1;
  231.         }
  232.     }
  233.  
  234.     /**
  235.      * Returns the number of branches between this node and the furthest leaf.
  236.      *
  237.      * @return the number of branches between this node and the furthest leaf
  238.      */
  239.     public int getMaximumHeight() {
  240.         if (arguments.length == 0) {
  241.             return 0;
  242.         } else {
  243.             int height = 0;
  244.            
  245.             for (Node argument : arguments) {
  246.                 height = Math.max(height, argument.getMaximumHeight());
  247.             }
  248.            
  249.             return height+1;
  250.         }
  251.     }
  252.  
  253.     /**
  254.      * Returns a copy of this node, but without any children or parents
  255.      * assigned.
  256.      *
  257.      * @return a copy of this node, but without any children or parents
  258.      *         assigned
  259.      */
  260.     public abstract Node copyNode();
  261.  
  262.     /**
  263.      * Returns a copy of this node including copies of all its arguments (child
  264.      * nodes).  All attributes of the node are also retained, such as
  265.      * {@link #isFixed()}.
  266.      *
  267.      * @return a copy of this node including copies of all its arguments (child
  268.      *         nodes)
  269.      */
  270.     public Node copyTree() {
  271.         Node node = copyNode();
  272.        
  273.         node.setFixed(isFixed());
  274.        
  275.         for (int i = 0; i < getNumberOfArguments(); i++) {
  276.             if (getArgument(i) != null) {
  277.                 node.setArgument(i, getArgument(i).copyTree());
  278.             }
  279.         }
  280.        
  281.         return node;
  282.     }
  283.  
  284.     /**
  285.      * Evaluates this node in the context of the specified environment.
  286.      *
  287.      * @param environment the execution environment
  288.      * @return the result of evaluating this node
  289.      */
  290.     public abstract Object evaluate(Environment environment);
  291.    
  292.     /**
  293.      * Returns {@code true} if this node and its arguments are valid;
  294.      * {@code false} otherwise.  A valid node has all arguments defined,
  295.      * all arguments are valid, and all arguments are the appropriate type.
  296.      *
  297.      * @return {@code true} if this node and its arguments are valid;
  298.      *         {@code false} otherwise
  299.      */
  300.     public boolean isValid() {
  301.         for (int i = 0; i < getNumberOfArguments(); i++) {
  302.             Node argument = getArgument(i);
  303.            
  304.             if (argument == null) {
  305.                 System.err.println("argument is null");
  306.                 return false;
  307.             }
  308.            
  309.             if (!getArgumentType(i).isAssignableFrom(argument.getReturnType())) {
  310.                 System.err.println(getClass().getSimpleName() + " (" + i +
  311.                         "): " + getArgumentType(i) + " not assignable from " +
  312.                         argument.getReturnType());
  313.                 return false;
  314.             }
  315.            
  316.             if (!argument.isValid()) {
  317.                 return false;
  318.             }
  319.         }
  320.        
  321.         return true;
  322.     }
  323.    
  324.     @Override
  325.     public String toString() {
  326.         StringBuilder sb = new StringBuilder();
  327.         sb.append('(');
  328.         sb.append(getClass().getSimpleName());
  329.         //System.out.println(getClass().getSimpleName()+ " lol") ;
  330.         for (int i = 0; i < getNumberOfArguments(); i++) {
  331.             sb.append(' ');
  332.             if (getArgument(i) == null) {
  333.                 sb.append(getArgumentType(i).getSimpleName());
  334.             } else {
  335.                 sb.append(getArgument(i).toString());
  336.             }
  337.         }
  338.            
  339.         sb.append(')');
  340.         return sb.toString();
  341.     }
  342.     //to use for binary trees
  343.     public String todot(int id)
  344.     {
  345.         StringBuilder sb = new StringBuilder();
  346.        
  347.         sb.append(" "+id + " [label = \""+this.getName() + "\" ]") ;
  348.        
  349.         int child_id ;
  350.        
  351.        
  352.         for (int i = 0; i < getNumberOfArguments(); i++) {
  353.            
  354.                child_id = 2*id+i ;
  355.                sb.append(" "+id+"->"+child_id+";") ;
  356.                sb.append(getArgument(i).todot(2*id+i)) ;
  357.             }
  358.            
  359.        
  360.         return sb.toString();
  361.     }
  362.     public String getName()
  363.     {
  364.         return getClass().getSimpleName() ;
  365.     }
  366.     /**
  367.      * Returns the types of the arguments of this node.
  368.      *
  369.      * @return the types of the arguments of this node
  370.      */
  371.     Class<?>[] getArgumentTypes() {
  372.         return argumentTypes;
  373.     }
  374.    
  375.     /**
  376.      * Returns {@code true} if this is a terminal node (has no arguments);
  377.      * {@code false} otherwise.
  378.      *
  379.      * @return {@code true} if this is a terminal node (has no arguments);
  380.      *         {@code false} otherwise
  381.      */
  382.     public boolean isTerminal() {
  383.         return getNumberOfArguments() == 0;
  384.     }
  385.    
  386.     /**
  387.      * Returns the number of function (non-terminal) nodes contained in the
  388.      * subtree rooted at this node that match the given return type.
  389.      *
  390.      * @param type the return type of the node
  391.      * @return the number of function (non-terminal) nodes contained in the
  392.      *         subtree rooted at this node that match the given return type
  393.      */
  394.     public int getNumberOfFunctions(Class<?> type) {
  395.         return getNumberOfNodes(type, true, false);
  396.     }
  397.  
  398.     /**
  399.      * Returns the function (non-terminal) node at the specified index in the
  400.      * subtree rooted at this node, counting only nodes that match the given
  401.      * return type.  A depth-first search (DFS) walk of the tree is used to
  402.      * find the appropriate node.
  403.      *
  404.      * @param type the return type of the node
  405.      * @param index the index of the node to return
  406.      * @return the function (non-terminal) node at the specified index in the
  407.      *         subtree rooted at this node, counting only nodes that match the
  408.      *         given return type
  409.      * @throws IndexOutOfBoundsException if the index refers to a node not
  410.      *         within the subtree rooted at this node
  411.      */
  412.     public Node getFunctionAt(Class<?> type, int index) {
  413.         return getNodeAt(type, true, false, index);
  414.     }
  415.    
  416.     /**
  417.      * Returns the number of function (non-terminal) nodes contained in the
  418.      * subtree rooted at this node.
  419.      *
  420.      * @return the number of function (non-terminal) nodes contained in the
  421.      *         subtree rooted at this node
  422.      */
  423.     public int getNumberOfFunctions() {
  424.         return getNumberOfFunctions(Object.class);
  425.     }
  426.    
  427.     /**
  428.      * Returns the function (non-terminal) node at the specified index in the
  429.      * subtree rooted at this node.  A depth-first search (DFS) walk of the
  430.      * tree is used to find the appropriate node.
  431.      *
  432.      * @param index the index of the node to return
  433.      * @return the function (non-terminal) node at the specified index in the
  434.      *         subtree rooted at this node
  435.      * @throws IndexOutOfBoundsException if the index refers to a node not
  436.      *         within the subtree rooted at this node
  437.      */
  438.     public Node getFunctionAt(int index) {
  439.         return getFunctionAt(Object.class, index);
  440.     }
  441.    
  442.     /**
  443.      * Returns the number of terminal nodes contained in the subtree rooted at
  444.      * this node that match the given return type.
  445.      *
  446.      * @param type the return type of the node
  447.      * @return the number of terminal nodes contained in the subtree rooted at
  448.      *         this node that match the given return type
  449.      */
  450.     public int getNumberOfTerminals(Class<?> type) {
  451.         return getNumberOfNodes(type, false, true);
  452.     }
  453.    
  454.     /**
  455.      * Returns the terminal node at the specified index in the subtree rooted
  456.      * at this node, counting only nodes that match the given return type.  A
  457.      * depth-first search (DFS) walk of the tree is used to find the
  458.      * appropriate node.
  459.      *
  460.      * @param type the return type of the node
  461.      * @param index the index of the node to return
  462.      * @return the terminal node at the specified index in the subtree rooted
  463.      *         at this node, counting only nodes that match the given return
  464.      *         type
  465.      * @throws IndexOutOfBoundsException if the index refers to a node not
  466.      *         within the subtree rooted at this node
  467.      */
  468.     public Node getTerminalAt(Class<?> type, int index) {
  469.         return getNodeAt(type, false, true, index);
  470.     }
  471.    
  472.     /**
  473.      * Returns the number of terminal nodes contained in the subtree rooted at
  474.      * this node.
  475.      *
  476.      * @return the number of terminal nodes contained in the subtree rooted at
  477.      *         this node
  478.      */
  479.     public int getNumberOfTerminals() {
  480.         return getNumberOfTerminals(Object.class);
  481.     }
  482.    
  483.     /**
  484.      * Returns the terminal node at the specified index in the subtree rooted
  485.      * at this node.  A depth-first search (DFS) walk of the tree is used to
  486.      * find the appropriate node.
  487.      *
  488.      * @param index the index of the node to return
  489.      * @return the terminal node at the specified index in the subtree rooted
  490.      *         at this node
  491.      * @throws IndexOutOfBoundsException if the index refers to a node not
  492.      *         within the subtree rooted at this node
  493.      */
  494.     public Node getTerminalAt(int index) {
  495.         return getTerminalAt(Object.class, index);
  496.     }
  497.    
  498.     /**
  499.      * Returns the number of nodes contained in the subtree rooted at this
  500.      * node that match the given return type.
  501.      *
  502.      * @param type the return type of the node
  503.      * @return the number of nodes contained in the subtree rooted at this
  504.      *         node that match the given return type
  505.      */
  506.     public int getNumberOfNodes(Class<?> type) {
  507.         return getNumberOfNodes(type, true, true);
  508.     }
  509.    
  510.     /**
  511.      * Returns the node at the specified index in the subtree rooted at this
  512.      * node, counting only nodes that match the given return type.  A
  513.      * depth-first search (DFS) walk of the tree is used to find the
  514.      * appropriate node.
  515.      *
  516.      * @param type the return type of the node
  517.      * @param index the index of the node to return
  518.      * @return the node at the specified index in the subtree rooted at this
  519.      *         node, counting only nodes that match the given return type
  520.      * @throws IndexOutOfBoundsException if the index refers to a node not
  521.      *         within the subtree rooted at this node
  522.      */
  523.     public Node getNodeAt(Class<?> type, int index) {
  524.         return getNodeAt(type, true, true, index);
  525.     }
  526.    
  527.     /**
  528.      * Returns the number of nodes contained in the subtree rooted at this
  529.      * node.
  530.      *
  531.      * @return the number of nodes contained in the subtree rooted at this
  532.      *         node
  533.      */
  534.     public int getNumberOfNodes() {
  535.         return getNumberOfNodes(Object.class);
  536.     }
  537.    
  538.     /**
  539.      * Returns the node at the specified index in the subtree rooted at this
  540.      * node.  A depth-first search (DFS) walk of the tree is used to find the
  541.      * appropriate node.
  542.      *
  543.      * @param index the index of the node to return
  544.      * @return the node at the specified index in the subtree rooted at this
  545.      *         node
  546.      * @throws IndexOutOfBoundsException if the index refers to a node not
  547.      *         within the subtree rooted at this node
  548.      */
  549.     public Node getNodeAt(int index) {
  550.         return getNodeAt(Object.class, index);
  551.     }
  552.    
  553.     /**
  554.      * Returns the number of nodes contained in the subtree rooted at this
  555.      * node.
  556.      *
  557.      * @param type the return type of the node
  558.      * @param includeFunctions {@code true} if functions (non-terminals) are
  559.      *        counted; {@code false} otherwise
  560.      * @param includeTerminals {@code true} if terminals are counted;
  561.      *        {@code false} otherwise
  562.      * @return the number of nodes contained in the subtree rooted at this
  563.      *         node
  564.      */
  565.     protected int getNumberOfNodes(Class<?> type, boolean includeFunctions,
  566.             boolean includeTerminals) {
  567.         int result = 0;
  568.  
  569.         // is this node a match?
  570.         if ((isTerminal() &&
  571.                 includeTerminals &&
  572.                 type.isAssignableFrom(getReturnType())) ||
  573.             (!isTerminal() &&
  574.                 includeFunctions &&
  575.                 type.isAssignableFrom(getReturnType()))) {
  576.             result++;
  577.         }
  578.        
  579.         // count matching nodes in arguments
  580.         for (Node argument : arguments) {
  581.             result += argument.getNumberOfNodes(type, includeFunctions,
  582.                     includeTerminals);
  583.         }
  584.        
  585.         return result;
  586.     }
  587.    
  588.     /**
  589.      * Returns the node at the specified index in the subtree rooted at this
  590.      * node.  A depth-first search (DFS) walk of the tree is used to find the
  591.      * appropriate node.
  592.      *
  593.      * @param type the return type of the node
  594.      * @param includeFunctions {@code true} if functions (non-terminals) are
  595.      *        counted; {@code false} otherwise
  596.      * @param includeTerminals {@code true} if terminals are counted;
  597.      *        {@code false} otherwise
  598.      * @param index the index of the node to return
  599.      * @return the node at the specified index in the subtree rooted at this
  600.      *         node
  601.      * @throws IndexOutOfBoundsException if the index refers to a node not
  602.      *         within the subtree rooted at this node
  603.      */
  604.     protected Node getNodeAt(Class<?> type, boolean includeFunctions,
  605.             boolean includeTerminals, int index) {
  606.         // is this node a match?
  607.         if ((isTerminal() && includeTerminals &&
  608.                 type.isAssignableFrom(getReturnType())) ||
  609.             (!isTerminal() && includeFunctions &&
  610.                 type.isAssignableFrom(getReturnType()))) {
  611.             if (index == 0) {
  612.                 return this;
  613.             } else {
  614.                 index--;
  615.             }
  616.         }
  617.        
  618.         // recurse on matching nodes in arguments
  619.         for (Node argument : arguments) {
  620.             int size = argument.getNumberOfNodes(type, includeFunctions,
  621.                     includeTerminals);
  622.            
  623.             if (size > index) {
  624.                 // this argument contains the node to return
  625.                 return argument.getNodeAt(type, includeFunctions,
  626.                         includeTerminals, index);
  627.             } else {
  628.                 // this argument does not contain the node
  629.                 index -= size;
  630.             }
  631.         }
  632.        
  633.         throw new IndexOutOfBoundsException(
  634.                 "index does not reference node in tree");
  635.     }
  636.  
  637. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement