added expressions

This commit is contained in:
hneemann 2016-05-04 21:51:00 +02:00
parent b1d1b672a7
commit 5aeb8525a0
24 changed files with 1260 additions and 0 deletions

View File

@ -0,0 +1,43 @@
package de.neemann.digital.analyse.expression;
/**
* Used to fill a table.
* The first section of input values is set by the {@link BitSetter}
*
* @author hneemann
*/
public abstract class BitSetter {
private final int bitCount;
/**
* Creates a new instance
*
* @param bitCount th number of bits
*/
public BitSetter(int bitCount) {
this.bitCount = bitCount;
}
/**
* Fills the row value
*
* @param row the row
*/
public void fill(int row) {
int mask = 1 << (bitCount - 1);
for (int bit = 0; bit < bitCount; bit++) {
setBit(row, bit, (row & mask) > 0);
mask >>= 1;
}
}
/**
* Used to fill the row
*
* @param row the row number
* @param bit the bit to set, refers to the variable number
* @param value the value
*/
public abstract void setBit(int row, int bit, boolean value);
}

View File

@ -0,0 +1,49 @@
package de.neemann.digital.analyse.expression;
/**
* A constant
*
* @author hneemann
*/
public final class Constant implements Expression {
private final boolean value;
/**
* The constant true or one
*/
public static final Constant ONE = new Constant(true);
/**
* The constant false or zero
*/
public static final Constant ZERO = new Constant(false);
private Constant(boolean value) {
this.value = value;
}
@Override
public boolean calculate(Context context) {
return value;
}
@Override
public <V extends ExpressionVisitor> V traverse(V v) {
v.visit(this);
return v;
}
@Override
public String getOrderString() {
return Boolean.toString(value);
}
/**
* Retorns the constants value
*
* @return the value
*/
public boolean getValue() {
return value;
}
}

View File

@ -0,0 +1,17 @@
package de.neemann.digital.analyse.expression;
/**
* The context used to evaluate an expression
*
* @author hneemann
*/
public interface Context {
/**
* Returns the value of the given variable
*
* @param variable the variable
* @return the variables value
* @throws ExpressionException ExpressionException
*/
boolean get(Variable variable) throws ExpressionException;
}

View File

@ -0,0 +1,89 @@
package de.neemann.digital.analyse.expression;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
/**
* @author hneemann
*/
public class ContextFiller extends ContextMap implements Iterable<Variable> {
private final ArrayList<Variable> vars;
private final int rowCount;
private final BitSetter bitSetter;
/**
* Creates a new instance.
* The needed variables are taken from the expression
*
* @param expression the expression to extravt the variables
*/
public ContextFiller(Expression expression) {
this(new ArrayList<>(expression.traverse(new VariableVisitor()).getVariables()));
Collections.sort(vars);
}
/**
* Creates a new instance
*
* @param variables the variables to use
*/
public ContextFiller(ArrayList<Variable> variables) {
vars = variables;
rowCount = 1 << vars.size();
bitSetter = new BitSetter(vars.size()) {
@Override
public void setBit(int row, int i, boolean value) {
set(vars.get(i), value);
}
};
}
@Override
public Iterator<Variable> iterator() {
return vars.iterator();
}
/**
* Returns the variable with the given index
*
* @param index the index
* @return the variable
*/
public Variable getVar(int index) {
return vars.get(index);
}
/**
* @return the number of variables
*/
public int getVarCount() {
return vars.size();
}
/**
* @return the number of tablerows to describe all variable combinations
*/
public int getRowCount() {
return rowCount;
}
/**
* Fills the context with the given rows bit value
*
* @param bitValue the bit value, in most cases the tables row
* @return this for call chaining
*/
public ContextFiller setContextTo(int bitValue) {
bitSetter.fill(bitValue);
return this;
}
/**
* @return the variables to use
*/
public ArrayList<Variable> getVariables() {
return vars;
}
}

View File

@ -0,0 +1,39 @@
package de.neemann.digital.analyse.expression;
import java.util.HashMap;
/**
* Simple {@link Context} based on a HashMap
*
* @author hneemann
*/
public class ContextMap implements Context {
private HashMap<Variable, Boolean> map;
/**
* Creates a new instance
*/
public ContextMap() {
map = new HashMap<>();
}
@Override
public boolean get(Variable variable) throws ExpressionException {
Boolean aBoolean = map.get(variable);
if (aBoolean == null)
throw new ExpressionException(variable + " not defined");
return aBoolean;
}
/**
* Sets a value
*
* @param v the variable
* @param b the variables value
* @return this for call chaining
*/
public ContextMap set(Variable v, boolean b) {
map.put(v, b);
return this;
}
}

View File

@ -0,0 +1,34 @@
package de.neemann.digital.analyse.expression;
/**
* An expression which can be evaluated to a boolean value
*
* @author hneemann
*/
public interface Expression {
/**
* Evaluates the expression and returns the bool value
*
* @param context the expressions context
* @return the bool value
* @throws ExpressionException ExpressionException
*/
boolean calculate(Context context) throws ExpressionException;
/**
* Traverses the expression
*
* @param visitor the visitor
* @param <V> the visitors type
* @return the visitor
*/
<V extends ExpressionVisitor> V traverse(V visitor);
/**
* String used to order expressions
*
* @return the ordering string
*/
String getOrderString();
}

View File

@ -0,0 +1,17 @@
package de.neemann.digital.analyse.expression;
/**
* Error thrown during evaluation of an expression
*
* @author hneemann
*/
public class ExpressionException extends Exception {
/**
* Creates a new instance
*
* @param message the message
*/
public ExpressionException(String message) {
super(message);
}
}

View File

@ -0,0 +1,17 @@
package de.neemann.digital.analyse.expression;
/**
* Visitor used the visit all sub expressions of the expression tree
*
* @author hneemann
*/
public interface ExpressionVisitor {
/**
* if true is returned the visitor goes down the tree.
*
* @param expression the expression to visit
* @return if true operation goes down
*/
boolean visit(Expression expression);
}

View File

@ -0,0 +1,56 @@
package de.neemann.digital.analyse.expression;
/**
* @author hneemann
*/
public final class Not implements Expression {
private final Expression expression;
/**
* Creates a not expression
*
* @param a the child expression to invert
* @return the inverted expression
*/
public static Expression not(Expression a) {
if (a == Constant.ONE)
return Constant.ZERO;
if (a == Constant.ZERO)
return Constant.ONE;
if (a instanceof Not) {
return ((Not) a).expression;
} else
return new Not(a);
}
private Not(Expression expression) {
this.expression = expression;
}
@Override
public boolean calculate(Context context) throws ExpressionException {
return !expression.calculate(context);
}
@Override
public <V extends ExpressionVisitor> V traverse(V v) {
if (v.visit(this)) {
expression.traverse(v);
}
return v;
}
@Override
public String getOrderString() {
return expression.getOrderString();
}
/**
* @return the negated expression
*/
public Expression getExpression() {
return expression;
}
}

View File

@ -0,0 +1,169 @@
package de.neemann.digital.analyse.expression;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
/**
* A operation
* There are only two implementations: The AND and the OR operation
*
* @author hneemann
*/
public abstract class Operation implements Expression {
private static final Comparator<Expression> EXPRESSION_COMPARATOR
= (a, b) -> a.getOrderString().compareTo(b.getOrderString());
private final ArrayList<Expression> expr;
/**
* Creates a new OR expression
*
* @param exp the expressions to OR
* @return the created expression
*/
public static Expression or(Iterable<Expression> exp) {
return simplify(new Or(exp));
}
/**
* Creates a new OR expression
*
* @param exp the expressions to OR
* @return the created expression
*/
public static Expression or(Expression... exp) {
return simplify(new Or(Arrays.asList(exp)));
}
/**
* Creates a new AND expression
*
* @param exp the expressions to AND
* @return the created expression
*/
public static Expression and(Iterable<Expression> exp) {
return simplify(new And(exp));
}
/**
* Creates a new AND expression
*
* @param exp the expressions to AND
* @return the created expression
*/
public static Expression and(Expression... exp) {
return simplify(new And(Arrays.asList(exp)));
}
private static Expression simplify(Operation operation) {
int size = operation.getExpressions().size();
switch (size) {
case 0:
return null;
case 1:
return operation.getExpressions().get(0);
default:
Collections.sort(operation.getExpressions(), EXPRESSION_COMPARATOR);
return operation;
}
}
private Operation(Iterable<Expression> exp) {
expr = new ArrayList<>();
for (Expression e : exp)
if (e != null)
merge(e);
}
private void merge(Expression e) {
if (e.getClass() == getClass()) {
expr.addAll(((Operation) e).getExpressions());
} else
expr.add(e);
}
@Override
public boolean calculate(Context context) throws ExpressionException {
boolean result = getNeutral();
for (Expression e : expr)
result = calc(result, e.calculate(context));
return result;
}
@Override
public <V extends ExpressionVisitor> V traverse(V v) {
if (v.visit(this)) {
for (Expression e : expr)
e.traverse(v);
}
return v;
}
/**
* @return the sub expressions
*/
public ArrayList<Expression> getExpressions() {
return expr;
}
@Override
public String getOrderString() {
return expr.get(0).getOrderString();
}
/**
* @return the neutral element of this operation
*/
protected abstract boolean getNeutral();
/**
* Performs the calculation
*
* @param a value a
* @param b value b
* @return result
*/
protected abstract boolean calc(boolean a, boolean b);
/**
* The AND expression
*/
public static final class And extends Operation {
private And(Iterable<Expression> exp) {
super(exp);
}
@Override
protected boolean getNeutral() {
return true;
}
@Override
protected boolean calc(boolean a, boolean b) {
return a && b;
}
}
/**
* The OR expression
*/
public static final class Or extends Operation {
private Or(Iterable<Expression> exp) {
super(exp);
}
@Override
protected boolean getNeutral() {
return false;
}
@Override
protected boolean calc(boolean a, boolean b) {
return a || b;
}
}
}

View File

@ -0,0 +1,74 @@
package de.neemann.digital.analyse.expression;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class Variable implements Comparable<Variable>, Expression {
private String identifier;
public static Variable v(String name) {
return new Variable(name);
}
public static ArrayList<Variable> vars(int n) {
ArrayList<Variable> v = new ArrayList<Variable>();
for (int i = 0; i < n; i++)
v.add(new Variable("" + (char) ('A' + i)));
return v;
}
public static ArrayList<Variable> vars(String... names) {
ArrayList<Variable> v = new ArrayList<Variable>();
for (String n : names)
v.add(new Variable(n));
return v;
}
public Variable(String identifier) {
this.identifier = identifier;
}
public boolean calculate(Context context) throws ExpressionException {
return context.get(this);
}
@Override
public <V extends ExpressionVisitor> V traverse(V v) {
v.visit(this);
return v;
}
@Override
public String getOrderString() {
return identifier;
}
public String getIdentifier() {
return identifier;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Variable that = (Variable) o;
return identifier.equals(that.identifier);
}
@Override
public int hashCode() {
return identifier.hashCode();
}
@Override
public int compareTo(Variable o) {
return identifier.compareTo(o.identifier);
}
}

View File

@ -0,0 +1,38 @@
package de.neemann.digital.analyse.expression;
import java.util.Collection;
import java.util.HashSet;
/**
* Visitor to collect all used variables in an expression
*
* @author hneemann
*/
public class VariableVisitor implements ExpressionVisitor {
private final HashSet<Variable> variables;
/**
* Creates a new instance
*/
public VariableVisitor() {
variables = new HashSet<>();
}
@Override
public boolean visit(Expression expression) {
if (expression instanceof Variable) {
variables.add((Variable) expression);
}
return true;
}
/**
* Rerurns all used variables
*
* @return used variables
*/
public Collection<Variable> getVariables() {
return variables;
}
}

View File

@ -0,0 +1,154 @@
package de.neemann.digital.analyse.expression.format;
import de.neemann.digital.analyse.expression.*;
/**
* Used to format an expression to a simple string
*
* @author hneemann
*/
public class FormatToExpression implements Formatter {
/**
* Creates a string compatible to Java
*/
public static final FormatToExpression FORMATTER_JAVA = new FormatToExpression("||", "&&", "!", "false", "true");
/**
* Creates a string compatible to Derive
*/
public static final FormatToExpression FORMATTER_DERIVE = new FormatToExpression("OR", "AND", "NOT ", "false", "true");
/**
* Creates a string compatible to Logisim
*/
public static final FormatToExpression FORMATTER_LOGISIM = new FormatToExpression("+", "", "~", "false", "true");
/**
* Creates a unicode string
*/
public static final FormatToExpression FORMATTER_UNICODE = new FormatToExpression("\u2228", "\u2227", "\u00AC", "0", "1");
/**
* Creates a LaTeX representation
*/
public static final FormatToExpression FORMATTER_LATEX = new FormatterLatex();
private final String orString;
private final String andString;
private final String falseString;
private final String trueString;
private final String notString;
private FormatToExpression(String orString, String andString, String notString, String falseString, String trueString) {
this.orString = orString;
this.andString = andString;
this.notString = notString;
this.falseString = falseString;
this.trueString = trueString;
}
@Override
public String format(String name, Expression expression) throws FormatterException {
return identifier(name) + "=" + format(expression);
}
/**
* Formats the given expression
*
* @param expression the expression
* @return the formated string
* @throws FormatterException FormatterException
*/
public String format(Expression expression) throws FormatterException {
if (expression instanceof Variable) {
return identifier(((Variable) expression).getIdentifier());
} else if (expression instanceof Constant) {
return constant(((Constant) expression).getValue());
} else if (expression instanceof Not) {
return formatNot((Not) expression);
} else if (expression instanceof Operation.And) {
return formatAnd((Operation.And) expression);
} else if (expression instanceof Operation.Or) {
return formatOr((Operation.Or) expression);
} else throw new FormatterException("unknown type " + expression.getClass().getSimpleName());
}
/**
* Formats a not expression
*
* @param expression the nor expression
* @return the formatted string
* @throws FormatterException FormatterException
*/
public String formatNot(Not expression) throws FormatterException {
if (expression.getExpression() instanceof Operation)
return notString + "(" + format(expression.getExpression()) + ")";
else
return notString + format(expression.getExpression());
}
private String formatAnd(Operation.And expression) throws FormatterException {
return formatOp(expression.getExpressions(), andString);
}
private String formatOr(Operation.Or expression) throws FormatterException {
return formatOp(expression.getExpressions(), orString);
}
/**
* Formats an operation
*
* @param expressions the expressions
* @param opString the string representation of the operation
* @return the formated string
* @throws FormatterException FormatterException
*/
public String formatOp(Iterable<Expression> expressions, String opString) throws FormatterException {
StringBuilder sb = new StringBuilder();
for (Expression e : expressions) {
if (sb.length() > 0) {
sb.append(" ").append(opString).append(" ");
}
if (e instanceof Operation)
sb.append("(").append(format(e)).append(")");
else
sb.append(format(e));
}
return sb.toString();
}
/**
* Formats the given constant
*
* @param value th constant
* @return the string representation
*/
public String constant(boolean value) {
if (value) return trueString;
else return falseString;
}
/**
* Formats the given identifier
*
* @param identifier the identifier
* @return the string representation of the identifier
*/
public String identifier(String identifier) {
return identifier;
}
private static class FormatterLatex extends FormatToExpression {
FormatterLatex() {
super("\\oder", "\\und", null, "0", "1");
}
@Override
public String formatNot(Not expression) throws FormatterException {
return "\\nicht{" + format(expression.getExpression()) + "}";
}
@Override
public String identifier(String identifier) {
return FormatToTableLatex.formatIdentifier(identifier);
}
}
}

View File

@ -0,0 +1,103 @@
package de.neemann.digital.analyse.expression.format;
import de.neemann.digital.analyse.expression.ContextFiller;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.Variable;
/**
* Creates a table representation of the given expression
*
* @author hneemann
*/
public class FormatToTable implements Formatter {
@Override
public String format(String name, Expression expression) throws FormatterException, ExpressionException {
StringBuilder sb = new StringBuilder();
ContextFiller cf = new ContextFiller(expression);
formatHead(sb, cf.getVarCount());
for (Variable v : cf)
sb.append(formatVariable(v));
sb.append(formatResultVariable());
sb.append("\n");
formatTableStart(sb);
for (int i = 0; i < cf.getRowCount(); i++) {
cf.setContextTo(i);
for (Variable v : cf)
sb.append(formatValue(cf.get(v)));
sb.append(formatResult(expression.calculate(cf)));
sb.append("\n");
}
formatEnd(sb);
return sb.toString();
}
/**
* Formats the table head
*
* @param sb the string builder to add the text to
* @param varCount the number of variables
*/
protected void formatHead(StringBuilder sb, int varCount) {
}
/**
* Formats the table start
*
* @param sb the string builder to add the text to
*/
protected void formatTableStart(StringBuilder sb) {
}
/**
* Formats the table end
*
* @param sb the string builder to add the text to
*/
protected void formatEnd(StringBuilder sb) {
}
/**
* Formats a variable
*
* @param v the variable
* @return the formatted text
*/
protected String formatVariable(Variable v) {
return v.getIdentifier();
}
/**
* formats the result variable
*
* @return the formatted text
*/
protected String formatResultVariable() {
return "|Y";
}
/**
* Formats a result value
*
* @param value the value to format
* @return the formatted text
*/
protected String formatResult(boolean value) {
return "|" + formatValue(value);
}
/**
* Formats a value
*
* @param val the value
* @return the formatted text
*/
protected String formatValue(boolean val) {
if (val) return "1";
else return "0";
}
}

View File

@ -0,0 +1,61 @@
package de.neemann.digital.analyse.expression.format;
import de.neemann.digital.analyse.expression.Variable;
/**
* @author hneemann
*/
public class FormatToTableLatex extends FormatToTable {
@Override
protected void formatHead(StringBuilder sb, int varCount) {
sb.append("\\begin{tabular}{");
for (int i = 0; i < varCount; i++)
sb.append("c");
sb.append("|c}\n");
}
@Override
protected String formatVariable(Variable v) {
return "$" + formatIdentifier(super.formatVariable(v)) + "$&";
}
@Override
protected String formatResultVariable() {
return "$Y$\\\\";
}
@Override
protected void formatTableStart(StringBuilder sb) {
sb.append("\\hline\n");
}
@Override
protected String formatValue(boolean val) {
return super.formatValue(val) + "&";
}
@Override
protected String formatResult(boolean value) {
return super.formatValue(value) + "\\\\";
}
@Override
protected void formatEnd(StringBuilder sb) {
sb.append("\\end{tabular}\n");
}
/**
* Formats the given identifier
*
* @param identifier the identifier
* @return the formatted text
*/
protected static String formatIdentifier(String identifier) {
if (identifier.length() <= 1)
return identifier;
else
return identifier.charAt(0) + "_{" + identifier.substring(1) + "}";
}
}

View File

@ -0,0 +1,24 @@
package de.neemann.digital.analyse.expression.format;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException;
/**
* Used to format an expression
*
* @author hneemann
*/
public interface Formatter {
/**
* Formats an expression
*
* @param name name of the expression
* @param expression the expression
* @return the formated expression
* @throws FormatterException FormatterException
* @throws ExpressionException ExpressionException
*/
String format(String name, Expression expression) throws FormatterException, ExpressionException;
}

View File

@ -0,0 +1,17 @@
package de.neemann.digital.analyse.expression.format;
/**
* Error thrown if there is an formatting error
*
* @author hneemann
*/
public class FormatterException extends Throwable {
/**
* Creates a new instance
*
* @param message the error message
*/
public FormatterException(String message) {
super(message);
}
}

View File

@ -0,0 +1,6 @@
/**
* Classes used to format an expression
*
* @author hneemann
*/
package de.neemann.digital.analyse.expression.format;

View File

@ -0,0 +1,6 @@
/**
* Used to describe an expression which can be evaluated to a boolean value
*
* @author hneemann
*/
package de.neemann.digital.analyse.expression;

View File

@ -0,0 +1,63 @@
package de.neemann.digital.analyse.expression;
import junit.framework.TestCase;
import static de.neemann.digital.analyse.expression.Not.not;
import static de.neemann.digital.analyse.expression.Operation.and;
import static de.neemann.digital.analyse.expression.Operation.or;
/**
* @author hneemann
*/
public class ExpressionTest extends TestCase {
public void testCalculate() throws Exception {
Variable a = new Variable("A");
Variable b = new Variable("B");
Expression e = and(not(or(not(a), not(b))), not(and(not(a), not(b))));
ContextFiller fc = new ContextFiller(e);
assertEquals(false, e.calculate(fc.setContextTo(0)));
assertEquals(false, e.calculate(fc.setContextTo(1)));
assertEquals(false, e.calculate(fc.setContextTo(2)));
assertEquals(true, e.calculate(fc.setContextTo(3)));
}
/**
* public void test2() throws FormatterException, ExpressionException {
* Variable a = new Variable("A");// Vorlesung
* Variable b = new Variable("B");
* Variable c = new Variable("C");
* Variable d = new Variable("D");
* <p>
* Expression e = or(and(a, and(c, d)), or(and(not(c), not(d)), and(not(b), c)));
* String out = FormatToExpression.FORMATTER_LATEX.format(e);
* assertEquals("(A \\und C \\und D) \\oder (\\nicht{B} \\und C) \\oder (\\nicht{C} \\und \\nicht{D})", out);
* <p>
* ContextFiller fc = new ContextFiller(e);
* <p>
* int[] vector = new int[]{1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1};
* for (int i = 0; i < vector.length; i++)
* assertEquals(vector[i] == 1, e.calculate(fc.setContextTo(i)));
* }
*/
public void testConstant() throws ExpressionException {
Variable a = new Variable("A");
Expression e = or(a, Constant.ONE);
ContextMap c = new ContextMap();
assertTrue(e.calculate(c.set(a, true)));
assertTrue(e.calculate(c.set(a, false)));
e = and(a, Constant.ONE);
assertTrue(e.calculate(c.set(a, true)));
assertFalse(e.calculate(c.set(a, false)));
e = or(a, Constant.ZERO);
assertTrue(e.calculate(c.set(a, true)));
assertFalse(e.calculate(c.set(a, false)));
}
}

View File

@ -0,0 +1,22 @@
package de.neemann.digital.analyse.expression;
import junit.framework.TestCase;
import static de.neemann.digital.analyse.expression.Not.not;
import static de.neemann.digital.analyse.expression.Variable.v;
/**
* @author hneemann
*/
public class NotTest extends TestCase {
public void testNot() throws Exception {
assertEquals(Constant.ONE, not(Constant.ZERO));
assertEquals(Constant.ZERO, not(Constant.ONE));
Variable a = v("a");
assertEquals(a, not(not(a)));
//assertEquals("¬a", not(a).toString());
}
}

View File

@ -0,0 +1,55 @@
package de.neemann.digital.analyse.expression;
import junit.framework.TestCase;
import static de.neemann.digital.analyse.expression.Not.not;
import static de.neemann.digital.analyse.expression.Operation.and;
import static de.neemann.digital.analyse.expression.Operation.or;
import static de.neemann.digital.analyse.expression.Variable.v;
/**
* @author hneemann
*/
public class OperationTest extends TestCase {
public void testOr() throws Exception {
Variable a = v("a");
Variable b = v("b");
Variable c = v("c");
Expression i = or(a);
assertTrue(i instanceof Variable);
i = or(a, b);
assertTrue(i instanceof Operation.Or);
assertEquals(2, ((Operation.Or) i).getExpressions().size());
i = or(c, i);
assertEquals(3, ((Operation.Or) i).getExpressions().size());
i = or(and(a, b), c);
assertTrue(i instanceof Operation.Or);
assertEquals(2, ((Operation.Or) i).getExpressions().size());
i = or(not(a));
assertTrue(i instanceof Not);
}
public void testAnd() throws Exception {
Variable a = v("a");
Variable b = v("b");
Variable c = v("c");
assertTrue(and(a) instanceof Variable);
Expression i = and(a, b);
assertTrue(i instanceof Operation.And);
assertEquals(2, ((Operation.And) i).getExpressions().size());
i = and(c, i);
assertEquals(3, ((Operation.And) i).getExpressions().size());
i = and(or(a, b), c);
assertTrue(i instanceof Operation.And);
assertEquals(2, ((Operation.And) i).getExpressions().size());
i = and(not(a));
assertTrue(i instanceof Not);
}
}

View File

@ -0,0 +1,23 @@
package de.neemann.digital.analyse.expression;
import junit.framework.TestCase;
import java.util.ArrayList;
import static de.neemann.digital.analyse.expression.Variable.vars;
/**
* @author hneemann
*/
public class VariableTest extends TestCase {
public void testVars() throws Exception {
ArrayList<Variable> v = vars(5);
assertEquals(5, v.size());
assertEquals("A", v.get(0).getIdentifier());
assertEquals("B", v.get(1).getIdentifier());
assertEquals("C", v.get(2).getIdentifier());
assertEquals("D", v.get(3).getIdentifier());
assertEquals("E", v.get(4).getIdentifier());
}
}

View File

@ -0,0 +1,84 @@
package de.neemann.digital.analyse.expression.format;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.Variable;
import junit.framework.TestCase;
import static de.neemann.digital.analyse.expression.Not.not;
import static de.neemann.digital.analyse.expression.Operation.and;
import static de.neemann.digital.analyse.expression.Operation.or;
import static de.neemann.digital.analyse.expression.Variable.v;
/**
* @author hneemann
*/
public class FormatterTest extends TestCase {
public void testFormatExp() throws Exception, FormatterException {
Variable a = v("A");
Variable b = v("B");
Expression e = and(not(or(not(a), not(b))), not(and(not(a), not(b))));
assertEquals("!(!A || !B) && !(!A && !B)", FormatToExpression.FORMATTER_JAVA.format(e));
assertEquals("\\nicht{\\nicht{A} \\oder \\nicht{B}} \\und \\nicht{\\nicht{A} \\und \\nicht{B}}", FormatToExpression.FORMATTER_LATEX.format(e));
assertEquals("NOT (NOT A OR NOT B) AND NOT (NOT A AND NOT B)", FormatToExpression.FORMATTER_DERIVE.format(e));
assertEquals("~(~A + ~B) ~(~A ~B)", FormatToExpression.FORMATTER_LOGISIM.format(e));
assertEquals("¬(¬A ¬B) ∧ ¬(¬A ∧ ¬B)", FormatToExpression.FORMATTER_UNICODE.format(e));
}
public void testFormatExpNot() throws Exception, FormatterException {
Variable a = new Variable("A");
Expression e = not(a);
assertEquals("¬A", FormatToExpression.FORMATTER_UNICODE.format(e));
}
public void testFormatExpNot2() throws Exception, FormatterException {
Variable a = v("A");
Variable b = v("B");
Variable c = v("C");
Expression e = or(and(a, b), not(c));
assertEquals("(A ∧ B) ¬C", FormatToExpression.FORMATTER_UNICODE.format(e));
}
public void testFormatExpLaTeX() throws Exception, FormatterException {
Variable a = new Variable("An");
Variable b = new Variable("Bn");
Expression e = and(a, not(b));
assertEquals("Y_{n+1}=A_{n} \\und \\nicht{B_{n}}", FormatToExpression.FORMATTER_LATEX.format("Yn+1", e));
}
public void testFormatTable() throws Exception, FormatterException {
Variable a = new Variable("A");
Variable b = new Variable("B");
Expression e = and(not(or(not(a), not(b))), not(and(not(a), not(b))));
assertEquals("AB|Y\n" +
"00|0\n" +
"01|0\n" +
"10|0\n" +
"11|1\n", new FormatToTable().format("", e));
}
public void testFormatLatex() throws Exception, FormatterException {
Variable a = new Variable("A");
Variable b = new Variable("B");
Expression e = and(not(or(not(a), not(b))), not(and(not(a), not(b))));
assertEquals("\\begin{tabular}{cc|c}\n" +
"$A$&$B$&$Y$\\\\\n" +
"\\hline\n" +
"0&0&0\\\\\n" +
"0&1&0\\\\\n" +
"1&0&0\\\\\n" +
"1&1&1\\\\\n" +
"\\end{tabular}\n", new FormatToTableLatex().format("", e));
}
}