001 /*
002 * Java Genetic Algorithm Library (jenetics-6.1.0).
003 * Copyright (c) 2007-2020 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020 package io.jenetics.prog.op;
021
022 import static java.lang.Math.abs;
023 import static java.lang.Math.acos;
024 import static java.lang.Math.asin;
025 import static java.lang.Math.atan;
026 import static java.lang.Math.cbrt;
027 import static java.lang.Math.ceil;
028 import static java.lang.Math.cos;
029 import static java.lang.Math.cosh;
030 import static java.lang.Math.exp;
031 import static java.lang.Math.floor;
032 import static java.lang.Math.hypot;
033 import static java.lang.Math.log;
034 import static java.lang.Math.log10;
035 import static java.lang.Math.max;
036 import static java.lang.Math.min;
037 import static java.lang.Math.pow;
038 import static java.lang.Math.rint;
039 import static java.lang.Math.signum;
040 import static java.lang.Math.sin;
041 import static java.lang.Math.sinh;
042 import static java.lang.Math.sqrt;
043 import static java.lang.Math.tan;
044 import static java.lang.Math.tanh;
045 import static java.util.Objects.requireNonNull;
046
047 import java.util.Objects;
048 import java.util.Optional;
049 import java.util.function.Function;
050 import java.util.stream.DoubleStream;
051 import java.util.stream.Stream;
052
053 import io.jenetics.ext.util.Tree;
054 import io.jenetics.ext.util.TreeNode;
055
056 /**
057 * This class contains operations for performing basic numeric operations.
058 *
059 * @see Math
060 *
061 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
062 * @version 5.0
063 * @since 3.9
064 */
065 public enum MathOp implements Op<Double> {
066
067
068 /* *************************************************************************
069 * Arithmetic operations
070 * ************************************************************************/
071
072 /**
073 * Return the absolute value of a double value.
074 * <em>This operation has arity 1.</em>
075 *
076 * @see Math#abs(double)
077 */
078 ABS("abs", 1, v -> abs(v[0])),
079
080 /**
081 * Return the negation value of a double value.
082 * <em>This operation has arity 1.</em>
083 */
084 NEG("neg", 1, v -> -v[0]),
085
086 /**
087 * Return the minimum of two values.
088 * <em>This operation has arity 2.</em>
089 *
090 * @see Math#min(double, double)
091 */
092 MIN("min", 2, v -> min(v[0], v[1])),
093
094 /**
095 * Return the maximum of two values
096 * <em>This operation has arity 2.</em>
097 *
098 * @see Math#max(double, double)
099 */
100 MAX("max", 2, v -> max(v[0], v[1])),
101
102 /**
103 * Returns the smallest (closest to negative infinity) double value that is
104 * greater than or equal to the argument and is equal to a mathematical
105 * integer.
106 * <em>This operation has arity 1.</em>
107 *
108 * @see Math#ceil(double)
109 */
110 CEIL("ceil", 1, v -> ceil(v[0])),
111
112 /**
113 * Returns the largest (closest to positive infinity) double value that is
114 * less than or equal to the argument and is equal to a mathematical integer.
115 * <em>This operation has arity 1.</em>
116 *
117 * @see Math#floor(double)
118 */
119 FLOOR("floor", 1, v -> floor(v[0])),
120
121 /**
122 * Returns the signum function of the argument; zero if the argument is
123 * zero, 1.0 if the argument is greater than zero, -1.0 if the argument is
124 * less than zero.
125 * <em>This operation has arity 1.</em>
126 *
127 * @see Math#signum(double)
128 */
129 SIGNUM("signum", 1, v -> signum(v[0])),
130
131 /**
132 * Returns the double value that is closest in value to the argument and is
133 * equal to a mathematical integer.
134 * <em>This operation has arity 1.</em>
135 *
136 * @see Math#rint(double)
137 */
138 RINT("rint", 1, v -> rint(v[0])),
139
140 /**
141 * Returns the sum of its arguments.
142 * <em>This operation has arity 2.</em>
143 */
144 ADD("add", 2, v -> v[0] + v[1]),
145
146 /**
147 * Return the diff of its arguments.
148 * <em>This operation has arity 2.</em>
149 */
150 SUB("sub", 2, v -> v[0] - v[1]),
151
152 /**
153 * Returns the product of its arguments.
154 * <em>This operation has arity 2.</em>
155 */
156 MUL("mul", 2, v -> v[0]*v[1]),
157
158 /**
159 * Returns the quotient of its arguments.
160 * <em>This operation has arity 2.</em>
161 */
162 DIV("div", 2, v -> v[0]/v[1]),
163
164 /**
165 * Returns the modulo of its arguments.
166 * <em>This operation has arity 2.</em>
167 */
168 MOD("mod", 2, v -> v[0]%v[1]),
169
170 /**
171 * Returns the value of the first argument raised to the power of the second
172 * argument.
173 * <em>This operation has arity 2.</em>
174 *
175 * @see Math#pow(double, double)
176 */
177 POW("pow", 2, v -> pow(v[0], v[1])),
178
179 /**
180 * Returns the square value of a given double value.
181 * <em>This operation has arity 1.</em>
182 */
183 SQR("sqr", 1, v -> v[0]*v[0]),
184
185 /**
186 * Returns the correctly rounded positive square root of a double value.
187 * <em>This operation has arity 1.</em>
188 *
189 * @see Math#sqrt(double)
190 */
191 SQRT("sqrt", 1, v -> sqrt(v[0])),
192
193 /**
194 * Returns the cube root of a double value.
195 * <em>This operation has arity 1.</em>
196 *
197 * @see Math#cbrt(double)
198 */
199 CBRT("cbrt", 1, v -> cbrt(v[0])),
200
201 /**
202 * Returns sqrt(<i>x</i><sup>2</sup> +<i>y</i><sup>2</sup>) without
203 * intermediate overflow or underflow.
204 * <em>This operation has arity 2.</em>
205 *
206 * @see Math#hypot(double, double)
207 */
208 HYPOT("hypot", 2, v -> hypot(v[0], v[1])),
209
210
211 /* *************************************************************************
212 * Exponential/logarithmic operations
213 * ************************************************************************/
214
215 /**
216 * Returns Euler's number e raised to the power of a double value.
217 * <em>This operation has arity 1.</em>
218 *
219 * @see Math#exp(double)
220 */
221 EXP("exp", 1, v -> exp(v[0])),
222
223 /**
224 * Returns the natural logarithm (base e) of a double value.
225 * <em>This operation has arity 1.</em>
226 *
227 * @see Math#log(double)
228 */
229 LOG("log", 1, v -> log(v[0])),
230
231 /**
232 * Returns the base 10 logarithm of a double value.
233 * <em>This operation has arity 1.</em>
234 *
235 * @see Math#log10(double)
236 */
237 LOG10("log10", 1, v -> log10(v[0])),
238
239
240 /* *************************************************************************
241 * Trigonometric operations
242 * ************************************************************************/
243
244 /**
245 * Returns the trigonometric sine of an angle.
246 * <em>This operation has arity 1.</em>
247 *
248 * @see Math#sin(double)
249 */
250 SIN("sin", 1, v -> sin(v[0])),
251
252 /**
253 * Returns the trigonometric cosine of an angle.
254 * <em>This operation has arity 1.</em>
255 *
256 * @see Math#cos(double)
257 */
258 COS("cos", 1, v -> cos(v[0])),
259
260 /**
261 * Returns the trigonometric tangent of an angle.
262 * <em>This operation has arity 1.</em>
263 *
264 * @see Math#tan(double)
265 */
266 TAN("tan", 1, v -> tan(v[0])),
267
268 /**
269 * Returns the arc cosine of a double value.
270 * <em>This operation has arity 1.</em>
271 *
272 * @see Math#acos(double)
273 */
274 ACOS("acos", 1, v -> acos(v[0])),
275
276 /**
277 * Returns the arc sine of a double value.
278 * <em>This operation has arity 1.</em>
279 *
280 * @see Math#asin(double)
281 */
282 ASIN("asin", 1, v -> asin(v[0])),
283
284 /**
285 * Returns the arc tangent of a value.
286 * <em>This operation has arity 1.</em>
287 *
288 * @see Math#atan(double)
289 */
290 ATAN("atan", 1, v -> atan(v[0])),
291
292 /**
293 * Returns the hyperbolic cosine of a double value.
294 * <em>This operation has arity 1.</em>
295 *
296 * @see Math#cosh(double)
297 */
298 COSH("cosh", 1, v -> cosh(v[0])),
299
300 /**
301 * Returns the hyperbolic sine of a double value.
302 * <em>This operation has arity 1.</em>
303 *
304 * @see Math#sinh(double)
305 */
306 SINH("sinh", 1, v -> sinh(v[0])),
307
308 /**
309 * Returns the hyperbolic tangent of a double value.
310 * <em>This operation has arity 1.</em>
311 *
312 * @see Math#tanh(double)
313 */
314 TANH("tanh", 1, v -> tanh(v[0])),
315
316 /* *************************************************************************
317 * Conditional functions
318 * ************************************************************************/
319
320 /**
321 * Returns +1.0 if its first argument is greater than its second argument
322 * and returns -1.0 otherwise.
323 *
324 * @since 5.0
325 */
326 GT("gt", 2, v -> v[0] > v[1] ? 1.0 : -1.0);
327
328 /* *************************************************************************
329 * Additional mathematical constants.
330 * ************************************************************************/
331
332 /**
333 * The double value that is closer than any other to pi, the ratio of the
334 * circumference of a circle to its diameter. <em>This is a terminal
335 * operation.</em>
336 *
337 * @see Math#PI
338 */
339 public static final Const<Double> PI = Const.of("π", Math.PI);
340
341 /**
342 * The double value that is closer than any other to e, the base of the
343 * natural logarithms. <em>This is a terminal operation.</em>
344 *
345 * @see Math#E
346 */
347 public static final Const<Double> E = Const.of("e", Math.E);
348
349
350 private final String _name;
351 private final int _arity;
352 private final Function<Double[], Double> _function;
353
354 MathOp(
355 final String name,
356 final int arity,
357 final Function<Double[], Double> function
358 ) {
359 assert name != null;
360 assert arity >= 0;
361 assert function != null;
362
363 _name = name;
364 _function = function;
365 _arity = arity;
366 }
367
368 @Override
369 public int arity() {
370 return _arity;
371 }
372
373 @Override
374 public Double apply(final Double[] args) {
375 return _function.apply(args);
376 }
377
378 /**
379 * Evaluates the operation with the given arguments.
380 *
381 * @since 5.0
382 *
383 * @see #apply(Double[])
384 *
385 * @param args the operation arguments
386 * @return the evaluated operation
387 */
388 public double eval(final double... args) {
389 return apply(
390 DoubleStream.of(args)
391 .boxed()
392 .toArray(Double[]::new)
393 );
394 }
395
396 @Override
397 public String toString() {
398 return _name;
399 }
400
401 /**
402 * Converts the string representation of an operation to the operation
403 * object. It is used for converting the string representation of a tree to
404 * an operation tree. <b>If you use it that way, you should not forget to
405 * re-index the tree variables.</b>
406 *
407 * <pre>{@code
408 * final TreeNode<Op<Double>> tree = TreeNode.parse(
409 * "add(mul(x,y),sub(y,x))",
410 * MathOp::toMathOp
411 * );
412 *
413 * assert Program.eval(tree, 10.0, 5.0) == 100.0;
414 * Var.reindex(tree);
415 * assert Program.eval(tree, 10.0, 5.0) == 45.0;
416 * }</pre>
417 *
418 * @since 5.0
419 *
420 * @see Var#reindex(TreeNode)
421 * @see Program#eval(Tree, Object[])
422 *
423 * @param string the string representation of an operation which should be
424 * converted
425 * @return the operation, converted from the given string
426 * @throws IllegalArgumentException if the given {@code value} doesn't
427 * represent a mathematical expression
428 * @throws NullPointerException if the given string {@code value} is
429 * {@code null}
430 */
431 public static Op<Double> toMathOp(final String string) {
432 requireNonNull(string);
433
434 final Op<Double> result;
435 final Optional<Const<Double>> cop = toConst(string);
436 if (cop.isPresent()) {
437 result = cop.orElseThrow(AssertionError::new);
438 } else {
439 final Optional<Op<Double>> mop = toOp(string);
440 result = mop.isPresent()
441 ? mop.orElseThrow(AssertionError::new)
442 : Var.parse(string);
443 }
444
445 return result;
446 }
447
448 static Optional<Const<Double>> toConst(final String string) {
449 return Numbers.toDoubleOptional(string)
450 .map(Const::of);
451 }
452
453 private static Optional<Op<Double>> toOp(final String string) {
454 return Stream.of(values())
455 .filter(op -> Objects.equals(op._name, string))
456 .map(op -> (Op<Double>)op)
457 .findFirst();
458 }
459
460 }
|