added possibility to create circuits with gates with only two inputs

This commit is contained in:
hneemann 2016-05-12 09:20:18 +02:00
parent 82a7d20143
commit 4e4ec3e70e
8 changed files with 1008 additions and 867 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
public final class Not implements Expression {
private Expression expression;
private boolean protect = false;
/**
* Creates a not expression.
@ -22,7 +23,7 @@ public final class Not implements Expression {
if (a == Constant.ZERO)
return Constant.ONE;
if (a instanceof Not) {
if (a instanceof Not && !((Not) a).protect) {
return ((Not) a).expression;
} else
return new Not(a);
@ -32,12 +33,22 @@ public final class Not implements Expression {
* Creates a new instance.
* In most cases it's better to use {@link Not#not(Expression)}.
*
* @param expression
* @param expression the expression to invert
*/
public Not(Expression expression) {
this.expression = expression;
}
/**
* Protects this not against simplification
*
* @return this for call chaning
*/
public Not protect() {
protect = true;
return this;
}
@Override
public boolean calculate(Context context) throws ExpressionException {
return !expression.calculate(context);

View File

@ -26,7 +26,7 @@ public abstract class Operation implements Expression {
* @return the created expression
*/
public static Expression or(Iterable<Expression> exp) {
return simplify(new Or(exp));
return simplify(new Or(exp, true));
}
/**
@ -36,7 +36,17 @@ public abstract class Operation implements Expression {
* @return the created expression
*/
public static Expression or(Expression... exp) {
return simplify(new Or(Arrays.asList(exp)));
return simplify(new Or(Arrays.asList(exp), true));
}
/**
* Creates a new OR expression
*
* @param exp the expressions to OR
* @return the created expression
*/
public static Expression orNoMerge(Expression... exp) {
return simplify(new Or(Arrays.asList(exp), false));
}
/**
@ -46,7 +56,7 @@ public abstract class Operation implements Expression {
* @return the created expression
*/
public static Expression and(Iterable<Expression> exp) {
return simplify(new And(exp));
return simplify(new And(exp, true));
}
/**
@ -56,7 +66,17 @@ public abstract class Operation implements Expression {
* @return the created expression
*/
public static Expression and(Expression... exp) {
return simplify(new And(Arrays.asList(exp)));
return simplify(new And(Arrays.asList(exp), true));
}
/**
* Creates a new AND expression
*
* @param exp the expressions to AND
* @return the created expression
*/
public static Expression andNoMerge(Expression... exp) {
return simplify(new And(Arrays.asList(exp), false));
}
private static Expression simplify(Operation operation) {
@ -72,11 +92,14 @@ public abstract class Operation implements Expression {
}
}
private Operation(Iterable<Expression> exp) {
private Operation(Iterable<Expression> exp, boolean merge) {
expr = new ArrayList<>();
for (Expression e : exp)
if (e != null)
merge(e);
if (merge)
merge(e);
else
expr.add(e);
}
private void merge(Expression e) {
@ -143,8 +166,8 @@ public abstract class Operation implements Expression {
*/
public static final class And extends Operation {
private And(Iterable<Expression> exp) {
super(exp);
private And(Iterable<Expression> exp, boolean merge) {
super(exp, merge);
}
@Override
@ -163,8 +186,8 @@ public abstract class Operation implements Expression {
*/
public static final class Or extends Operation {
private Or(Iterable<Expression> exp) {
super(exp);
private Or(Iterable<Expression> exp, boolean merge) {
super(exp, merge);
}
@Override

View File

@ -25,6 +25,19 @@ public interface ExpressionModifier {
return modifier.modify(expression);
}
/**
* Modifies the given expression with the given modifiers
*
* @param expression the expression to modify
* @param modifiers the modifiers to use
* @return the modified expression
*/
static Expression modifyExpression(Expression expression, ExpressionModifier... modifiers) {
for (ExpressionModifier m : modifiers)
expression = modifyExpression(expression, m);
return expression;
}
/**
* Modifies an expression.
* Don't recurse! Recursion is done by calling {@link Expression#modify(ExpressionModifier)}

View File

@ -16,12 +16,12 @@ public class NAnd implements ExpressionModifier {
@Override
public Expression modify(Expression expression) {
if (expression instanceof Operation.And) {
return new Not(not(expression));
return not(new Not(expression).protect());
} else if (expression instanceof Operation.Or) {
ArrayList<Expression> exp = new ArrayList<>();
for (Expression e : ((Operation.Or) expression).getExpressions())
exp.add(not(e));
return not(Operation.and(exp));
return new Not(Operation.and(exp)).protect();
} else
return expression;
}

View File

@ -16,13 +16,13 @@ public class NOr implements ExpressionModifier {
@Override
public Expression modify(Expression expression) {
if (expression instanceof Operation.Or) {
return new Not(not(expression));
return not(new Not(expression).protect());
} else
if (expression instanceof Operation.And) {
ArrayList<Expression> exp = new ArrayList<>();
for (Expression e : ((Operation.And) expression).getExpressions())
exp.add(not(e));
return not(Operation.or(exp));
return new Not(Operation.or(exp)).protect();
} else
return expression;
}

View File

@ -0,0 +1,62 @@
package de.neemann.digital.analyse.expression.modify;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.Operation;
import java.util.ArrayList;
import static de.neemann.digital.analyse.expression.Operation.andNoMerge;
import static de.neemann.digital.analyse.expression.Operation.orNoMerge;
/**
* @author hneemann
*/
public class TwoInputs implements ExpressionModifier {
@Override
public Expression modify(Expression expression) {
if (expression instanceof Operation) {
Operation op = (Operation) expression;
if (op.getExpressions().size() > 2) {
if (expression instanceof Operation.And)
return new Twoer(op.getExpressions(), (a, b) -> andNoMerge(a, b)).generate();
else if (expression instanceof Operation.Or)
return new Twoer(op.getExpressions(), (a, b) -> orNoMerge(a, b)).generate();
else
throw new RuntimeException("operation not supported: " + expression.getClass().getSimpleName());
} else
return expression;
} else
return expression;
}
private interface OpGen {
Expression op(Expression a, Expression b);
}
private static final class Twoer {
private final ArrayList<Expression> expressions;
private final OpGen opGen;
Twoer(ArrayList<Expression> expressions, OpGen opGen) {
this.expressions = expressions;
this.opGen = opGen;
}
Expression generate() {
return gen(0, expressions.size() - 1);
}
private Expression gen(int a, int b) {
if (a == b)
return expressions.get(a);
else if (a == b - 1)
return opGen.op(expressions.get(a), expressions.get(b));
else {
int i = (a + b) / 2;
return opGen.op(gen(a, i), gen(i + 1, b));
}
}
}
}

View File

@ -9,6 +9,7 @@ import de.neemann.digital.analyse.expression.format.FormatterException;
import de.neemann.digital.analyse.expression.modify.ExpressionModifier;
import de.neemann.digital.analyse.expression.modify.NAnd;
import de.neemann.digital.analyse.expression.modify.NOr;
import de.neemann.digital.analyse.expression.modify.TwoInputs;
import de.neemann.digital.draw.builder.Builder;
import de.neemann.digital.draw.builder.BuilderException;
import de.neemann.digital.draw.elements.Circuit;
@ -128,19 +129,42 @@ public class TableFrame extends JFrame {
createCircuit(ExpressionModifier.IDENTITY);
}
}.setToolTip(Lang.get("menu_table_create_tt")).createJMenuItem());
if (Main.enableExperimental()) {
createMenu.add(new ToolTipAction(Lang.get("menu_table_createTwo")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
createCircuit(new TwoInputs());
}
}.setToolTip(Lang.get("menu_table_createTwo_tt")).createJMenuItem());
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNAnd")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
createCircuit(new NAnd());
}
}.setToolTip(Lang.get("menu_table_createNAnd_tt")).createJMenuItem());
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNAndTwo")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
createCircuit(new TwoInputs(), new NAnd());
}
}.setToolTip(Lang.get("menu_table_createNAndTwo_tt")).createJMenuItem());
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNOr")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
createCircuit(new NOr());
}
}.setToolTip(Lang.get("menu_table_createNOr_tt")).createJMenuItem());
createMenu.add(new ToolTipAction(Lang.get("menu_table_createNOrTwo")) {
@Override
public void actionPerformed(ActionEvent actionEvent) {
createCircuit(new TwoInputs(), new NOr());
}
}.setToolTip(Lang.get("menu_table_createNOrTwo_tt")).createJMenuItem());
}
bar.add(createMenu);
@ -155,7 +179,7 @@ public class TableFrame extends JFrame {
setLocationRelativeTo(parent);
}
private void createCircuit(ExpressionModifier modifier) {
private void createCircuit(ExpressionModifier... modifier) {
try {
Builder builder = new Builder(shapeFactory);
HashSet<String> contained = new HashSet<>();