All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.jenetics.prog.op.BoolOp Maven / Gradle / Ivy

/*
 * Java Genetic Algorithm Library (jenetics-8.1.0).
 * Copyright (c) 2007-2024 Franz Wilhelmstötter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author:
 *    Franz Wilhelmstötter ([email protected])
 */
package io.jenetics.prog.op;

import static java.util.Objects.requireNonNull;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

import io.jenetics.ext.util.Tree;
import io.jenetics.ext.util.TreeNode;

/**
 * This class contains basic and secondary boolean operations.
 *
 * @author Franz Wilhelmstötter
 * @version 5.0
 * @since 5.0
 */
public enum BoolOp implements Op {

	/**
	 * Conjunction. This operation has arity 2.
	 */
	AND("and", 2, v -> v[0] && v[1]),

	/**
	 * Disjunction. This operation has arity 2.
	 */
	OR("or", 2, v -> v[0] || v[1]),

	/**
	 * Negation. This operation has arity 1.
	 */
	NOT("not", 1, v -> !v[0]),

	/**
	 * Implication. This operation has arity 2.
	 */
	IMP("imp", 2, v -> !v[0] || v[1]),

	/**
	 * Exclusive or. This operation has arity 2.
	 */
	XOR("xor", 2, v -> (v[0] || v[1]) && !(v[0] && v[1])),

	/**
	 * Equivalence. This operation has arity 2.
	 */
	EQU("equ", 2, v -> (v[0] && v[1]) || (!v[0] && !v[1]));

	/**
	 * Represents the constant {@code true}.
	 */
	public static final Const TRUE = Const.of("true", true);

	/**
	 * Represents the constant {@code true}.
	 */
	public static final Const FALSE = Const.of("false", false);


	private final String _name;
	private final int _arity;
	private final Function _function;

	BoolOp(
		final String name,
		final int arity,
		final Function function
	) {
		assert name != null;
		assert arity >= 0;
		assert function != null;

		_name = name;
		_function = function;
		_arity = arity;
	}

	@Override
	public int arity() {
		return _arity;
	}

	@Override
	public Boolean apply(final Boolean[] args) {
		return _function.apply(args);
	}

	/**
	 * Evaluates the operation with the given arguments.
	 *
	 * @see #apply(Boolean[])
	 *
	 * @param args the operation arguments
	 * @return the evaluated operation
	 */
	public boolean eval(final boolean... args) {
		final Boolean[] v = new Boolean[args.length];
		for (int i = 0; i < args.length; ++i) {
			v[i] = args[i];
		}

		return apply(v);
	}

	@Override
	public String toString() {
		return _name;
	}


	/**
	 * Converts the string representation of an operation to the operation
	 * object. It is used for converting the string representation of a tree to
	 * an operation tree. If you use it that way, you should not forget to
	 * re-index the tree variables.
	 *
	 * {@snippet lang="java":
	 * final TreeNode> tree = TreeNode.parse(
	 *     "and(or(x,y),not(y))",
	 *     BoolOp::toBoolOp
	 * );
	 *
	 * assert Program.eval(tree, false, false) == false;
	 * Var.reindex(tree);
	 * assert Program.eval(tree, false, false) == true;
	 * }
	 *
	 * @since 5.0
	 *
	 * @see Var#reindex(TreeNode)
	 * @see Program#eval(Tree, Object[])
	 *
	 * @param string the string representation of an operation which should be
	 *        converted
	 * @return the operation, converted from the given string
	 * @throws IllegalArgumentException if the given {@code value} doesn't
	 *         represent a mathematical expression
	 * @throws NullPointerException if the given string {@code value} is
	 *         {@code null}
	 */
	public static Op toBoolOp(final String string) {
		requireNonNull(string);

		final Op result;
		final Optional> cop = toConst(string);
		if (cop.isPresent()) {
			result = cop.orElseThrow(AssertionError::new);
		} else {
			final Optional> mop = toOp(string);
			result = mop.isPresent()
				? mop.orElseThrow(AssertionError::new)
				: Var.parse(string);
		}

		return result;
	}

	static Optional> toConst(final String string) {
		return tryParseBoolean(string)
			.map(Const::of);
	}

	private static Optional tryParseBoolean(final String value) {
        return switch (value) {
            case "true", "1" -> Optional.of(true);
            case "false", "0" -> Optional.of(false);
            default -> Optional.empty();
        };
	}

	private static Optional> toOp(final String string) {
		return Stream.of(values())
			.filter(op -> Objects.equals(op._name, string))
			.map(op -> (Op)op)
			.findFirst();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy