diff --git a/src/Main.java b/src/Main.java index e02bf34..2d14cbb 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,39 +1,48 @@ +import lombok.SneakyThrows; import models.EvaluatableTerm; import models.ResourceVariable; +import models.algebra.Expression; import models.algebra.Type; +import models.algebra.Variable; import models.dataConstraintModel.DataConstraintModel; +import models.dataFlowModel.DataTransferModel; +import models.meta.MetaRDLTerm; +import models.meta.MetaResourceVariable; +import models.meta.OrderConstraint; +import parser.Parser; +import parser.Parser.TokenStream; public class Main { + static TokenStream stream = new Parser.TokenStream(); + static Parser parser = new Parser(stream); + static DataTransferModel model = new DataTransferModel(); + public static void main(String[] args) { Type INT = DataConstraintModel.typeInt; - Type STR = DataConstraintModel.typeString; - ResourceVariable a = EvaluatableTerm.of("A", INT, 2); - ResourceVariable b = EvaluatableTerm.of("B", INT, 2); - ResourceVariable c = EvaluatableTerm.of("C", INT, 2); - ResourceVariable d = EvaluatableTerm.of("D", INT, 2); - ResourceVariable e = EvaluatableTerm.of("E", INT, 1); - ResourceVariable f = EvaluatableTerm.of("F", INT, 1); - ResourceVariable g = EvaluatableTerm.of("G", INT, 1); - ResourceVariable h = EvaluatableTerm.of("H", INT, 1); - ResourceVariable i = EvaluatableTerm.of("I", INT, 0); + var a = new ResourceVariable("a", INT, 2); + var b = new ResourceVariable("b", INT, 2); + var c = new ResourceVariable("c", INT, 1); + var d = EvaluatableTerm.of(a, b, c); - EvaluatableTerm te1 = EvaluatableTerm.of(g, h, i); - EvaluatableTerm te2 = EvaluatableTerm.of(a, b, c); - EvaluatableTerm te3 = EvaluatableTerm.of(te2, d, e); - EvaluatableTerm te4 = EvaluatableTerm.of(te3, f, te1); + var v1 = new MetaResourceVariable(new Variable("v1"), OrderConstraint.LE, parse("x + 1")); + var v2 = new MetaResourceVariable(new Variable("v1"), OrderConstraint.EQ, parse("x + 1")); + var v3 = new MetaResourceVariable(new Variable("v3"), OrderConstraint.LE, parse("x")); + var te = new MetaRDLTerm(v1, v2, v3); - var te5 = te4.linearRightNormalize(); - System.out.println(te4.toString()); - System.out.println(te4.getOrder()); - te4.selfLinearRightNormalize(); - System.out.println(te4.toString()); - System.out.println(te4.isLinearRightNormal()); - System.out.println(te4.getOrder()); - System.out.println(te5.toString()); + System.out.println(d.toString()); + System.out.println(te.toString()); + System.out.println(te.isMatchedBy(d)); } + @SneakyThrows + static Expression parse(String expr) { + stream.addLine(expr); + return parser.parseTerm(stream, model); + } + + } diff --git a/src/exceptions/CoefficientNotOneException.java b/src/exceptions/CoefficientNotOneException.java new file mode 100644 index 0000000..ddef07c --- /dev/null +++ b/src/exceptions/CoefficientNotOneException.java @@ -0,0 +1,13 @@ +package exceptions; + +public class CoefficientNotOneException extends RuntimeException { + + public CoefficientNotOneException(String msg) { + super(msg); + } + + public CoefficientNotOneException() { + super("Coefficient is not 1."); + } + +} diff --git a/src/exceptions/NonLinearExpressionException.java b/src/exceptions/NonLinearExpressionException.java new file mode 100644 index 0000000..fc56963 --- /dev/null +++ b/src/exceptions/NonLinearExpressionException.java @@ -0,0 +1,13 @@ +package exceptions; + +public class NonLinearExpressionException extends RuntimeException { + + public NonLinearExpressionException() { + super("This Expression is not linear"); + } + + public NonLinearExpressionException(String msg) { + super(msg); + } + +} diff --git a/src/exceptions/TooManyVariablesException.java b/src/exceptions/TooManyVariablesException.java new file mode 100644 index 0000000..407ca30 --- /dev/null +++ b/src/exceptions/TooManyVariablesException.java @@ -0,0 +1,13 @@ +package exceptions; + +public class TooManyVariablesException extends RuntimeException { + + public TooManyVariablesException(String msg) { + super(msg); + } + + public TooManyVariablesException() { + super("Too many variables"); + } + +} diff --git a/src/models/meta/MetaDependencyTermVariable.java b/src/models/meta/MetaDependencyTermVariable.java new file mode 100644 index 0000000..bbea73f --- /dev/null +++ b/src/models/meta/MetaDependencyTermVariable.java @@ -0,0 +1,24 @@ +package models.meta; + +import lombok.Getter; +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Variable; + +@Getter +public class MetaDependencyTermVariable extends MetaVariable { + + public MetaDependencyTermVariable(Variable variableName, OrderConstraint constraint, Expression order) { + super(new Symbol(":", 3), MetaRDLTerm.TermType.META_DEPENDENCY_TERM_VARIABLE, variableName, constraint, order); + } + + public MetaDependencyTermVariable(Variable variableName) { + super(new Symbol(":", 3), MetaRDLTerm.TermType.META_DEPENDENCY_TERM_VARIABLE, variableName, OrderConstraint.ANY, new Constant("0")); + } + + public MetaDependencyTermVariable(Variable variableName, Expression order) { + super(new Symbol(":", 3), MetaRDLTerm.TermType.META_DEPENDENCY_TERM_VARIABLE, variableName, OrderConstraint.EQ, order); + } + +} diff --git a/src/models/meta/MetaDependencyVariable.java b/src/models/meta/MetaDependencyVariable.java new file mode 100644 index 0000000..75aa7e7 --- /dev/null +++ b/src/models/meta/MetaDependencyVariable.java @@ -0,0 +1,24 @@ +package models.meta; + +import lombok.Getter; +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Variable; + +@Getter +public class MetaDependencyVariable extends MetaVariable { + + public MetaDependencyVariable(Variable variableName, OrderConstraint constraint, Expression order) { + super(new Symbol(":", 2), MetaRDLTerm.TermType.META_DEPENDENCY_VARIABLE, variableName, constraint, order); + } + + public MetaDependencyVariable(Variable variableName) { + super(new Symbol(":", 2), MetaRDLTerm.TermType.META_DEPENDENCY_VARIABLE, variableName, OrderConstraint.ANY, new Constant("0")); + } + + public MetaDependencyVariable(Variable variableName, Expression order) { + super(new Symbol(":", 2), MetaRDLTerm.TermType.META_DEPENDENCY_VARIABLE, variableName, OrderConstraint.EQ, order); + } + +} diff --git a/src/models/meta/MetaEvaluatableTermVariable.java b/src/models/meta/MetaEvaluatableTermVariable.java new file mode 100644 index 0000000..5c36b1e --- /dev/null +++ b/src/models/meta/MetaEvaluatableTermVariable.java @@ -0,0 +1,22 @@ +package models.meta; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Variable; + +public class MetaEvaluatableTermVariable extends MetaVariable { + + public MetaEvaluatableTermVariable(Variable variableName, OrderConstraint constraint, Expression order) { + super(new Symbol(":", 2), MetaRDLTerm.TermType.META_EVALUATABLE_TERM_VARIABLE, variableName, constraint, order); + } + + public MetaEvaluatableTermVariable(Variable variableName) { + super(new Symbol(":", 2), MetaRDLTerm.TermType.META_EVALUATABLE_TERM_VARIABLE, variableName, OrderConstraint.ANY, new Constant("0")); + } + + public MetaEvaluatableTermVariable(Variable variableName, Expression order) { + super(new Symbol(":", 2), MetaRDLTerm.TermType.META_EVALUATABLE_TERM_VARIABLE, variableName, OrderConstraint.EQ, order); + } + +} diff --git a/src/models/meta/MetaRDLTerm.java b/src/models/meta/MetaRDLTerm.java new file mode 100644 index 0000000..5647bc6 --- /dev/null +++ b/src/models/meta/MetaRDLTerm.java @@ -0,0 +1,238 @@ +package models.meta; + +import java.util.HashMap; +import java.util.Map; + +import exceptions.IllegalTypeException; +import lombok.Getter; +import models.Dependency; +import models.DependencyTerm; +import models.EvaluatableTerm; +import models.RDLTerm; +import models.ResourceVariable; +import models.algebra.Symbol; +import models.algebra.Variable; + +@Getter +public class MetaRDLTerm extends RDLTerm { + + protected static enum TermType { + META_RDL_TERM(RDLTerm.class), + META_DEPENDENCY(Dependency.class), + META_DEPENDENCY_LIST(Dependency.class), + META_DEPENDENCY_VARIABLE(Dependency.class), + META_DEPENDENCY_TERM(DependencyTerm.class), + META_DEPENDENCY_TERM_VARIABLE(DependencyTerm.class), + META_EVALUATABLE_TERM_VARIABLE(EvaluatableTerm.class), + META_RESOURCE_VARIABLE(ResourceVariable.class); + + @Getter + private Class baseTermClass; + + private TermType(Class clazz) { + this.baseTermClass = clazz; + } + + } + + protected TermType termType; + + protected MetaRDLTerm(Symbol symbol, TermType termType) { + super(symbol, -1); + this.termType = termType; + } + + //dependency + public MetaRDLTerm(RDLTerm dependingTerm, MetaResourceVariable dependedVariable) { + super(new Symbol(":", 2), dependedVariable.getOrder()); + addChild(dependingTerm); + addChild(dependedVariable); + this.termType = TermType.META_DEPENDENCY; + } + + public MetaRDLTerm(MetaRDLTerm dependingTerm, ResourceVariable dependedVariable) { + super(new Symbol(":", 2), dependedVariable.getOrder()); + addChild(dependingTerm); + addChild(dependedVariable); + this.termType = TermType.META_DEPENDENCY; + } + + public MetaRDLTerm(MetaRDLTerm dependingTerm, MetaResourceVariable dependedVariable) { + super(new Symbol(":", 2), dependedVariable.getOrder()); + addChild(dependingTerm); + addChild(dependedVariable); + this.termType = TermType.META_DEPENDENCY; + } + + //list type dependency + public MetaRDLTerm(MetaRDLTerm dependency) { + super(new Symbol(":", 1), dependency.getOrder() - 1); + addChild(dependency); + this.termType = TermType.META_DEPENDENCY_LIST; + } + + //dependency term + public MetaRDLTerm(MetaRDLTerm dependingTerm, MetaResourceVariable dependedVariable, MetaRDLTerm argumentTerm) { + super(new Symbol(":", 3), -1); + if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + addChild(dependingTerm); + addChild(dependedVariable); + addChild(argumentTerm); + this.termType = TermType.META_DEPENDENCY_TERM; + } + + public MetaRDLTerm(EvaluatableTerm dependingTerm, MetaRDLTerm dependedVariable, MetaRDLTerm argumentTerm) { + super(new Symbol(":", 3), -1); + if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + addChild(dependingTerm); + addChild(dependedVariable); + addChild(argumentTerm); + this.termType = TermType.META_DEPENDENCY_TERM; + } + + public MetaRDLTerm(MetaRDLTerm dependingTerm, ResourceVariable dependedVariable, MetaRDLTerm argumentTerm) { + super(new Symbol(":", 3), -1); + if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + addChild(dependingTerm); + addChild(dependedVariable); + addChild(argumentTerm); + this.termType = TermType.META_DEPENDENCY_TERM; + } + + public MetaRDLTerm(MetaRDLTerm dependingTerm, MetaRDLTerm dependedVariable, EvaluatableTerm argumentTerm) { + super(new Symbol(":", 3), -1); + if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + addChild(dependingTerm); + addChild(dependedVariable); + addChild(argumentTerm); + this.termType = TermType.META_DEPENDENCY_TERM; + } + + public MetaRDLTerm(MetaRDLTerm dependingTerm, ResourceVariable dependedVariable, EvaluatableTerm argumentTerm) { + super(new Symbol(":", 3), -1); + if (! EvaluatableTerm.class.isAssignableFrom(dependingTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + addChild(dependingTerm); + addChild(dependedVariable); + addChild(argumentTerm); + this.termType = TermType.META_DEPENDENCY_TERM; + } + + public MetaRDLTerm(EvaluatableTerm dependingTerm, MetaResourceVariable dependedVariable, EvaluatableTerm argumentTerm) { + super(new Symbol(":", 3), -1); + addChild(dependingTerm); + addChild(dependedVariable); + addChild(argumentTerm); + this.termType = TermType.META_DEPENDENCY_TERM; + } + + public MetaRDLTerm(EvaluatableTerm dependingTerm, ResourceVariable dependedVariable, MetaRDLTerm argumentTerm) { + super(new Symbol(":", 3), -1); + if(! EvaluatableTerm.class.isAssignableFrom(argumentTerm.getTermType().getBaseTermClass())) { + throw new IllegalTypeException(); + } + addChild(dependingTerm); + addChild(dependedVariable); + addChild(argumentTerm); + this.termType = TermType.META_DEPENDENCY_TERM; + } + + + public boolean isVariable() { + return false; + } + + public boolean isMatchedBy(RDLTerm another) { + return isMatchedBy(another, new HashMap<>(), new HashMap<>()); + } + + public boolean isMatchedBy(RDLTerm another, Map binding, Map orderConstraint) { + if (! another.getClass().isAssignableFrom(this.termType.getBaseTermClass())) { + return false; + } + if (this.getChildren().size() != another.getChildren().size()) { + return false; + } + for (int i = 0; i < this.getChildren().size(); i++) { + RDLTerm child = (RDLTerm) this.getChild(i); + RDLTerm anotherChild = (RDLTerm) another.getChild(i); + if (child instanceof MetaRDLTerm) { + MetaRDLTerm metaChild = (MetaRDLTerm) child; + if (! metaChild.isMatchedBy(anotherChild, binding, orderConstraint)) { + return false; + } + } else { + if (!(child.equals(anotherChild))) { + return false; + } + } + } + return true; + } + + + @Override + public String toString() { + switch(termType) { + case META_DEPENDENCY: + return "[" + getChild(0).toString() + " : " + getChild(1).toString() + "]"; + case META_DEPENDENCY_LIST: + return "[" + getChild(0).toString() + "]"; + case META_DEPENDENCY_TERM: + return "[" + getChild(0).toString() + " : " + getChild(1).toString() + " -> " + getChild(2).toString() + "]"; + default: + return ""; + } + } + + @Override + public String toStringWithOrder() { + switch(termType) { + case META_DEPENDENCY: + return "[" + ((RDLTerm) getChild(0)).toStringWithOrder() + " : " + ((RDLTerm) getChild(1)).toStringWithOrder() + "]"; + case META_DEPENDENCY_LIST: + return "[" + ((RDLTerm) getChild(0)).toStringWithOrder() + "]"; + case META_DEPENDENCY_TERM: + return "[" + ((RDLTerm) getChild(0)).toStringWithOrder() + " : " + + ((RDLTerm) getChild(1)).toStringWithOrder() + " -> " + ((RDLTerm) getChild(2)).toStringWithOrder() + "]"; + default: + return ""; + } + } + + @Override + public boolean equals(Object another) { + if(! (another instanceof MetaRDLTerm)) { + return false; + } + MetaRDLTerm anotherTerm = (MetaRDLTerm) another; + return super.equals(another) && termType == anotherTerm.getTermType(); + } + + @Override + public int hashCode() { + return (termType.toString() + toStringWithOrder()).hashCode(); + } + + @Override + public Object clone() { + + return null; + } + +} diff --git a/src/models/meta/MetaRDLTermVariable.java b/src/models/meta/MetaRDLTermVariable.java new file mode 100644 index 0000000..dd74db0 --- /dev/null +++ b/src/models/meta/MetaRDLTermVariable.java @@ -0,0 +1,22 @@ +package models.meta; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Variable; + +public class MetaRDLTermVariable extends MetaVariable { + + public MetaRDLTermVariable(Variable variableName, OrderConstraint constraint, Expression order) { + super(new Symbol("", -1), MetaRDLTerm.TermType.META_RDL_TERM, variableName, constraint, order); + } + + public MetaRDLTermVariable(Variable variableName) { + super(new Symbol("", -1), MetaRDLTerm.TermType.META_RDL_TERM, variableName, OrderConstraint.ANY, new Constant("0")); + } + + public MetaRDLTermVariable(Variable variableName, Expression order) { + super(new Symbol("", -1), MetaRDLTerm.TermType.META_RDL_TERM, variableName, OrderConstraint.EQ, order); + } + +} diff --git a/src/models/meta/MetaResourceVariable.java b/src/models/meta/MetaResourceVariable.java new file mode 100644 index 0000000..c3534f7 --- /dev/null +++ b/src/models/meta/MetaResourceVariable.java @@ -0,0 +1,23 @@ +package models.meta; + +import lombok.Getter; +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Variable; + +@Getter +public class MetaResourceVariable extends MetaVariable { + + public MetaResourceVariable(Variable variableName, OrderConstraint constraint, Expression order) { + super(new Symbol("", 0), MetaRDLTerm.TermType.META_RESOURCE_VARIABLE, variableName, constraint, order); + } + + public MetaResourceVariable(Variable variableName) { + super(new Symbol("", 0), MetaRDLTerm.TermType.META_RESOURCE_VARIABLE, variableName, OrderConstraint.ANY, new Constant("0")); + } + + public MetaResourceVariable(Variable variableName, Expression order) { + super(new Symbol("", 0), MetaRDLTerm.TermType.META_RESOURCE_VARIABLE, variableName, OrderConstraint.EQ, order); + } +} diff --git a/src/models/meta/MetaVariable.java b/src/models/meta/MetaVariable.java new file mode 100644 index 0000000..6357c67 --- /dev/null +++ b/src/models/meta/MetaVariable.java @@ -0,0 +1,208 @@ +package models.meta; + +import java.util.HashMap; +import java.util.Map; + +import exceptions.CoefficientNotOneException; +import exceptions.NonLinearExpressionException; +import exceptions.TooManyVariablesException; +import lombok.Getter; +import models.RDLTerm; +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Variable; +import models.dataConstraintModel.DataConstraintModel; + +@Getter +public abstract class MetaVariable extends MetaRDLTerm { + + protected Variable variableName; + protected OrderConstraint constraint; + protected Variable orderVariable; + protected int orderConstant; + protected Expression orderExpression; + + protected MetaVariable(Symbol symbol, TermType termType, Variable name, OrderConstraint constraint, Expression order) { + super(symbol, termType); + this.variableName = name; + this.constraint = constraint; + this.orderExpression = order; + Map coefficients = new HashMap<>(); + int constant = getCoefficientAndConstantsFromExpression(order, coefficients, 1); + if (coefficients.size() > 1) { + // todo: create exception + throw new TooManyVariablesException("Too many variables"); + } + if (coefficients.size() == 1) { + orderVariable = coefficients.keySet().iterator().next(); + if (coefficients.get(orderVariable) != 1) { + throw new CoefficientNotOneException(); + } + } else { + orderVariable = null; + } + orderConstant = constant; + } + + @Override + public boolean isVariable() { + return true; + } + + @Override + public boolean isMatchedBy(RDLTerm another, Map binding, + Map orderConstraint) { + if (! this.termType.getBaseTermClass().isAssignableFrom(another.getClass())) { + return false; + } + + if (! orderConstraintCheck(another, orderConstraint)) { + return false; + } + + if (! binding.containsKey(this.variableName)) { + binding.put(this.variableName, another); + return true; + } + return binding.get(this.variableName).equals(another); + } + + private boolean orderConstraintCheck(RDLTerm another, Map orderConstraints) { + if (orderVariable == null) { + switch (constraint) { + case ANY: + return true; + case EQ: + return another.getOrder() == orderConstant; + case GE: + return another.getOrder() >= orderConstant; + case GT: + return another.getOrder() > orderConstant; + case LE: + return another.getOrder() <= orderConstant; + case LT: + return another.getOrder() < orderConstant; + } + } else { + if (! orderConstraints.containsKey(orderVariable)) { + orderConstraints.put(orderVariable, new OrderVariableConstraint()); + } + var orderVarConst = orderConstraints.get(orderVariable); + return orderVarConst.setConstraint(another.getOrder() - orderConstant, constraint); + } + return false; + } + + private int getCoefficientAndConstantsFromExpression(Expression expression, Map coefficients, int curWeight) { + int res = 0; + if(expression instanceof Constant) { + return getConstantValue((Constant) expression) * curWeight; + } else if(expression instanceof Variable) { + coefficients.put((Variable) expression, coefficients.getOrDefault((Variable) expression, 0) + curWeight); + return 0; + } + Term term = (Term) expression; + Symbol symbol = term.getSymbol(); + if(symbol.equals(DataConstraintModel.add)) { + Expression c1 = term.getChild(0); + Expression c2 = term.getChild(1); + res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight); + res += getCoefficientAndConstantsFromExpression(c2, coefficients, curWeight); + } else if(symbol.equals(DataConstraintModel.sub)) { + Expression c1 = term.getChild(0); + Expression c2 = term.getChild(1); + res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight); + res += getCoefficientAndConstantsFromExpression(c2, coefficients, -curWeight); + } else if(symbol.equals(DataConstraintModel.mul)) { + Expression c1 = term.getChild(0); + Expression c2 = term.getChild(1); + if(c1.getVariables().size() == 0 && c2.getVariables().size() == 0) { + res += getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight) * + getCoefficientAndConstantsFromExpression(c2, coefficients, curWeight); + } else if(c1.getVariables().size() == 0) { + res += getCoefficientAndConstantsFromExpression( + c2, + coefficients, + getCoefficientAndConstantsFromExpression(c1, coefficients, curWeight) + ); + } else if(c2.getVariables().size() == 0){ + res += getCoefficientAndConstantsFromExpression( + c1, + coefficients, + getCoefficientAndConstantsFromExpression(c2, coefficients, curWeight) + ); + } else { + throw new NonLinearExpressionException("Order expression must be linear expression."); + } + } else if(symbol.equals(DataConstraintModel.minus)) { + Expression c1 = term.getChild(0); + res += getCoefficientAndConstantsFromExpression(c1, coefficients, -curWeight); + } else { + throw new NonLinearExpressionException("Order expression must be linear expression."); + } + return res; + + } + + private int getConstantValue(Constant constant) { + return Integer.parseInt((String) constant.getValue()); + } + + + @Override + public String toString() { + return variableName.toString(); + } + + @Override + public String toStringWithOrder() { + return toString() +getOrderString(); + } + + protected String getOrderString() { + switch(constraint) { + case ANY: + return "(*)"; + case EQ: + return "(= " + orderExpression.toString() + ")"; + case GE: + return "(>= " + orderExpression.toString() + ")"; + case GT: + return "(> " + orderExpression.toString() + ")"; + case LE: + return "(<= " + orderExpression.toString() + ")"; + case LT: + return "(< " + orderExpression.toString() + ")"; + } + return ""; + } + + @Override + public boolean equals(Object another) { + if (another instanceof MetaVariable) { + return false; + } + MetaVariable anotherVar = (MetaVariable) another; + return super.equals(another) + && variableName.equals(another) + && constraint == anotherVar.getConstraint() + && orderVariable.equals(anotherVar.getOrderVariable()) + && orderConstant == anotherVar.getOrderConstant(); + } + + @Override + public int hashCode() { + return (termType.name() + toString()).hashCode(); + } + + @Override + public Object clone() { + // TODO 自動生成されたメソッド・スタブ + return super.clone(); + } + + + +} diff --git a/src/models/meta/OrderConstraint.java b/src/models/meta/OrderConstraint.java new file mode 100644 index 0000000..000ca02 --- /dev/null +++ b/src/models/meta/OrderConstraint.java @@ -0,0 +1,12 @@ +package models.meta; + +public enum OrderConstraint { + + EQ, + LT, + LE, + GT, + GE, + ANY; + +} diff --git a/src/models/meta/OrderVariableConstraint.java b/src/models/meta/OrderVariableConstraint.java new file mode 100644 index 0000000..e4a1342 --- /dev/null +++ b/src/models/meta/OrderVariableConstraint.java @@ -0,0 +1,58 @@ +package models.meta; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class OrderVariableConstraint { + + // lower <= x <= upper + private int upper = 100000000; + private int lower = -1; + private boolean isOk = true; + + public boolean setConstraint(int value, OrderConstraint constraint) { + switch (constraint) { + case ANY: + return true; + case EQ: + return setEq(value); + case GE: + return setUpper(value); + case GT: + return setUpper(value - 1); + case LE: + return setLower(value); + case LT: + return setLower(value + 1); + } + return false; + } + + public boolean isOk() { + return isOk; + } + + + private boolean setEq(int eq) { + return setUpper(eq) && setLower(eq); + } + + private boolean setUpper(int upper) { + if (isOk && this.lower <= upper && upper <= this.upper) { + this.upper = upper; + return true; + } + isOk = false; + return false; + } + + private boolean setLower(int lower) { + if (isOk && this.lower <= lower && lower <= this.upper) { + this.lower = lower; + return true; + } + isOk = false; + return false; + } + +} diff --git a/src/tests/Utils.java b/src/tests/Utils.java new file mode 100644 index 0000000..d9e754e --- /dev/null +++ b/src/tests/Utils.java @@ -0,0 +1,31 @@ +package tests; + +import models.algebra.Expression; +import models.algebra.Type; +import models.dataConstraintModel.DataConstraintModel; +import models.dataFlowModel.DataTransferModel; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedDoubleQuotation; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; + +public class Utils { + + public static Type INT = DataConstraintModel.typeInt; + private static TokenStream stream = new Parser.TokenStream(); + private static Parser parser = new Parser(stream); + private static DataTransferModel model = new DataTransferModel(); + + public static Expression parse(String expr) { + stream.addLine(expr); + try { + return parser.parseTerm(stream, model); + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon | ExpectedDoubleQuotation e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/src/tests/meta/MetaResourceVariableTest.java b/src/tests/meta/MetaResourceVariableTest.java new file mode 100644 index 0000000..2afdb18 --- /dev/null +++ b/src/tests/meta/MetaResourceVariableTest.java @@ -0,0 +1,127 @@ +package tests.meta; + +import static org.junit.jupiter.api.Assertions.*; +import static tests.Utils.*; + +import org.junit.jupiter.api.Test; + +import models.Dependency; +import models.DependencyTerm; +import models.ResourceVariable; +import models.algebra.Variable; +import models.meta.MetaDependencyTermVariable; +import models.meta.MetaDependencyVariable; +import models.meta.MetaEvaluatableTermVariable; +import models.meta.MetaRDLTermVariable; +import models.meta.MetaResourceVariable; +import models.meta.OrderConstraint; + +public class MetaResourceVariableTest { + + @Test + void MetaResourceVariableMathcingWithoutOrder() { + ResourceVariable a = new ResourceVariable("a", INT, 0); + ResourceVariable b = new ResourceVariable("b", INT, 0); + ResourceVariable c = new ResourceVariable("c", INT, 0); + Dependency dep = new Dependency(a, b); + DependencyTerm depTerm = new DependencyTerm(a, b, c); + + MetaResourceVariable x = new MetaResourceVariable(new Variable("x")); + MetaDependencyVariable d = new MetaDependencyVariable(new Variable("d")); + MetaDependencyTermVariable dte = new MetaDependencyTermVariable(new Variable("dte")); + MetaEvaluatableTermVariable te = new MetaEvaluatableTermVariable(new Variable("te")); + MetaRDLTermVariable t = new MetaRDLTermVariable(new Variable("t")); + + // a matches x(resource variable) + assertTrue(x.isMatchedBy(a)); + // a does not match d(dependency) + assertFalse(d.isMatchedBy(a)); + // a does not match dte(dependency term) + assertFalse(dte.isMatchedBy(a)); + // a matches te(evaluatable term) + assertTrue(te.isMatchedBy(a)); + // a matches t(term) + assertTrue(t.isMatchedBy(a)); + // [a : b] does not match x(resource variable) + assertFalse(x.isMatchedBy(dep)); + // [a : b -> c] does not match x(resource variable) + assertFalse(x.isMatchedBy(depTerm)); + } + + @Test + void MetaResourceVariableMathcingWithConstantOrderEQ() { + ResourceVariable a = new ResourceVariable("a", INT, 1); + MetaResourceVariable x = new MetaResourceVariable(new Variable("x"), parse("0")); + MetaResourceVariable y = new MetaResourceVariable(new Variable("y"), parse("1")); + //a(1) does not match x(=0) + assertFalse(x.isMatchedBy(a)); + //a(1) matches y(=1) + assertTrue(y.isMatchedBy(a)); + } + + @Test + void MetaResourceVariableMathcingWithConstantOrderLT() { + ResourceVariable a = new ResourceVariable("a", INT, 1); + MetaResourceVariable x = new MetaResourceVariable(new Variable("x"), OrderConstraint.LT, parse("0")); + MetaResourceVariable y = new MetaResourceVariable(new Variable("y"), OrderConstraint.LT, parse("1")); + MetaResourceVariable z = new MetaResourceVariable(new Variable("z"), OrderConstraint.LT, parse("2")); + //a(1) does not match x(<0) + assertFalse(x.isMatchedBy(a)); + //a(1) matches y(<1) + assertFalse(y.isMatchedBy(a)); + //a(1) matches z(<2) + assertTrue(z.isMatchedBy(a)); + } + + @Test + void MetaResourceVariableMathcingWithConstantOrderLE() { + ResourceVariable a = new ResourceVariable("a", INT, 1); + MetaResourceVariable x = new MetaResourceVariable(new Variable("x"), OrderConstraint.LE, parse("0")); + MetaResourceVariable y = new MetaResourceVariable(new Variable("y"), OrderConstraint.LE, parse("1")); + MetaResourceVariable z = new MetaResourceVariable(new Variable("z"), OrderConstraint.LE, parse("2")); + //a(1) does not match x(<=0) + assertFalse(x.isMatchedBy(a)); + //a(1) matches y(<=1) + assertTrue(y.isMatchedBy(a)); + //a(1) matches z(<=2) + assertTrue(z.isMatchedBy(a)); + } + + @Test + void MetaResourceVariableMathcingWithConstantOrderGT() { + ResourceVariable a = new ResourceVariable("a", INT, 1); + MetaResourceVariable x = new MetaResourceVariable(new Variable("x"), OrderConstraint.GT, parse("0")); + MetaResourceVariable y = new MetaResourceVariable(new Variable("y"), OrderConstraint.GT, parse("1")); + MetaResourceVariable z = new MetaResourceVariable(new Variable("z"), OrderConstraint.GT, parse("2")); + //a(1) does not match x(>0) + assertTrue(x.isMatchedBy(a)); + //a(1) matches y(>1) + assertFalse(y.isMatchedBy(a)); + //a(1) matches z(>2) + assertFalse(z.isMatchedBy(a)); + } + + @Test + void MetaResourceVariableMathcingWithConstantOrderGE() { + ResourceVariable a = new ResourceVariable("a", INT, 1); + MetaResourceVariable x = new MetaResourceVariable(new Variable("x"), OrderConstraint.GE, parse("0")); + MetaResourceVariable y = new MetaResourceVariable(new Variable("y"), OrderConstraint.GE, parse("1")); + MetaResourceVariable z = new MetaResourceVariable(new Variable("z"), OrderConstraint.GE, parse("2")); + //a(1) does not match x(>=0) + assertTrue(x.isMatchedBy(a)); + //a(1) matches y(>=1) + assertTrue(y.isMatchedBy(a)); + //a(1) matches z(>2) + assertFalse(z.isMatchedBy(a)); + } + + @Test + void MetaResourceVariableMathcingWithEqOrder() { + ResourceVariable a = new ResourceVariable("a", INT, 0); + MetaResourceVariable x = new MetaResourceVariable(new Variable("x"), parse("x")); + + //a(0) matches x(x) + assertTrue(x.isMatchedBy(a)); + } + +}