Source code: exptree/expressionTree.java
1 /* Evolvo - Image Generator
2 * Copyright (C) 2000 Andrew Molloy
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /*
20 * @(#)exptressionTree.java 0.1 08/19/2000
21 */
22
23 package exptree;
24
25 import java.lang.ref.*;
26 import java.io.*;
27 import exptree.operators.*;
28 import exptree.utilities.*;
29
30 /**
31 * Handles mathematic expressions in a tree structure, including
32 * storage, evaluation, and display. Will eventually provide the
33 * functionality to manipulate the tree as well.
34 *
35 * @version 1.1 08/19/2000
36 * @author Andy Molloy
37 */
38 public class expressionTree implements Serializable
39 {
40 /** Holds parameters to this node's operator. */
41 expressionTree[] params;
42 /** Holds the operator for this node of the tree. */
43 operatorInterface operator;
44 /** Holds the cached value for this branch. */
45 double cachedValue;
46 boolean cacheable = false;
47
48 /** Creates a new expressionTree */
49 public expressionTree() {}
50
51 /** Creates a new expressionTree with operator op and parameters prms[] */
52 public expressionTree(expressionTree[] prms, operatorInterface op)
53 {
54 params = prms;
55 operator = op;
56 }
57
58 /** Convenience method to retrieve a clone of expressionTree as type expressionTree. */
59 public expressionTree getClone(variablePackage v)
60 {
61 int counter;
62
63 expressionTree[] newParams = new expressionTree[operator.getNumberOfParameters()]; // create a new array of expressionTrees
64 for (counter = 0; counter < operator.getNumberOfParameters(); counter++ )
65 {
66 newParams[counter] = params[counter].getClone(v); // and fill it with clones of our current parameters.
67 } // This recurses until it reaches terminal nodes.
68
69 expressionTree newET = new expressionTree(newParams, operator); // create a new expressionTree using this new array
70
71 return newET;
72 }
73
74 /** Evaluate the expressionTree, returning the result as a double. */
75 public double evaluate()
76 {
77 if (cacheable)
78 {
79 return cachedValue;
80 }
81 else
82 {
83 return operator.evaluate(params);
84 }
85 }
86
87 /** Returns a (sort of) human readable string representation of the expression.
88 * The resulting string contains the expression written in prefix notation. For example,
89 * The simple equation "1+1" would be written as "+(1, 1)". This notation is
90 * somewhat unusual, but is the closest written notation to this class' internal representation
91 * of the expression. */
92 public String toString()
93 {
94 int count;
95 int len = operator.getNumberOfParameters();
96 StringBuffer theString = new StringBuffer();
97
98 theString.append(operator.getName() + "(");
99
100 for(count = 0; count < len; count++)
101 {
102 theString.append(params[count].toString()); // Recurse into the params array
103 if(count < (len - 1))
104 {
105 theString.append(", ");
106 }
107 }
108
109 theString.append(")");
110
111 return theString.toString();
112 }
113
114 /** Returns the name of this node's operator. */
115 public String getName()
116 {
117 return(operator.getName());
118 }
119
120 /** Returns the number of parameter's this node's operator expects. */
121 public int getParamLength()
122 {
123 return(operator.getNumberOfParameters());
124 }
125
126 /** Set this node's parameters.
127 * <B>Note:</B> Currently does not check that p[] has the correct number of
128 * elements. If p[] has too many elements, the extras are simply thrown out.
129 * If, however, there are too few, the results are unpredicatable.
130 *
131 * This behavior should be modified in future versions to be more robust.
132 */
133 public void setParams(expressionTree p[])
134 {
135 int count;
136 int len = operator.getNumberOfParameters();
137
138 params = new expressionTree[len];
139
140 for(count = 0; count < len; count++)
141 {
142 params[count] = p[count];
143 }
144 }
145
146 /** Returns the number of parameters this node expects. */
147 public int getNumParams()
148 {
149 return operator.getNumberOfParameters();
150 }
151
152 /** Returns the parameters this node is holding. */
153 public expressionTree[] getParams()
154 {
155 return params;
156 }
157
158 /** Returns the operator this node holds. */
159 public operatorInterface getOperator()
160 {
161 return operator;
162 }
163
164 /** Sets this node's operator.
165 * <B>Note:</B> If the new operator expects more parameters than
166 * the current operator, results are unpredicatable.
167 *
168 * This behaviour should be modified in future version to be more robust. */
169 public void setOperator(operatorInterface o)
170 {
171 operator = o;
172 }
173
174 /** Determines if this branch of the tree is cacheable (ie, the value never changes).
175 * A side effect of calling this function is that a cache is built.
176 */
177 public boolean isCacheable()
178 {
179 boolean canBeCached = true;
180
181 for (int i = 0; i < operator.getNumberOfParameters(); i++)
182 {
183 canBeCached &= params[i].isCacheable();
184 }
185
186 if (canBeCached)
187 {
188 cachedValue = evaluate();
189 }
190
191 cacheable = canBeCached;
192
193 return cacheable;
194 }
195
196 /** Builds a cache for this branch. Simply calls the isCacheable() method, throwing away its
197 * return value.
198 */
199 public void buildCache()
200 {
201 cacheable = false;
202 boolean trash = isCacheable();
203 }
204 }