diff --git a/src/main/java/avatartranslator/AvatarBlock.java b/src/main/java/avatartranslator/AvatarBlock.java index 91de40f2574ff553d86900759c4ef510c36af2ba..0d8cd59cb9a13d75f3160bf55af3b0908ee955cc 100644 --- a/src/main/java/avatartranslator/AvatarBlock.java +++ b/src/main/java/avatartranslator/AvatarBlock.java @@ -837,6 +837,34 @@ public class AvatarBlock extends AvatarElement implements AvatarStateMachineOwne } + + public void removeUselessAttributes() { + AvatarTransition at; + List<AvatarAttribute> toBeRemoved = new LinkedList<AvatarAttribute>(); + + + for(AvatarAttribute aa: attributes) { + if (aa.isTimer()) { + if (!(asm.isTimerUsed(aa))) { + toBeRemoved.add(aa); + } + + + // Regular attribute. We have to search where it is used + } else { + if (!asm.isRegularAttributeUsed(aa)) { + toBeRemoved.add(aa); + } + } + } + + for(AvatarAttribute aa: toBeRemoved) { + attributes.remove(aa); + } + + } + + @Override public AvatarBlock advancedClone(AvatarSpecification avspec) { AvatarBlock av = new AvatarBlock(this.getName(), this.getAvatarSpecification(), this.getReferenceObject()); diff --git a/src/main/java/avatartranslator/AvatarRelation.java b/src/main/java/avatartranslator/AvatarRelation.java index 7e73109492d9254b138a62d7914d459cde22af8d..34866673cd969a70d272cbe2b93bd8c3287bf559 100644 --- a/src/main/java/avatartranslator/AvatarRelation.java +++ b/src/main/java/avatartranslator/AvatarRelation.java @@ -216,6 +216,11 @@ public class AvatarRelation extends AvatarElement { return block2; } + public void removeAssociation(AvatarSignal sig1, AvatarSignal sig2) { + signals1.remove(sig1); + signals2.remove(sig2); + } + public String toString() { StringBuffer sb = new StringBuffer(); for(int i=0; i<signals1.size(); i++) { diff --git a/src/main/java/avatartranslator/AvatarSpecification.java b/src/main/java/avatartranslator/AvatarSpecification.java index 2fdc20eef8b06e6df4f83664b0d39788521dc9c8..2785c2692ad0132b32ba52e64f6f7e38ba1229d9 100644 --- a/src/main/java/avatartranslator/AvatarSpecification.java +++ b/src/main/java/avatartranslator/AvatarSpecification.java @@ -834,6 +834,80 @@ public class AvatarSpecification extends AvatarElement { } + public boolean isSignalUsed(AvatarSignal _sig) { + for(AvatarBlock block: blocks) { + if (block.getStateMachine().isSignalUsed(_sig)) { + return true; + } + } + + return false; + } + + + public void removeUselessSignalAssociations() { + ArrayList<AvatarRelation> mightBeRemoved = new ArrayList<>(); + ArrayList<AvatarSignal> toBeRemoved1 = new ArrayList<>(); + ArrayList<AvatarSignal> toBeRemoved2 = new ArrayList<>(); + + for(AvatarRelation rel: relations) { + // For each signal association, we look for whether it is used or not + for(int i=0; i<rel.getSignals1().size(); i++) { + AvatarSignal sig1 = rel.getSignal1(i); + if (!isSignalUsed(sig1)) { + AvatarSignal sig2 = rel.getSignal2(i); + if (!isSignalUsed(sig2)) { + // We can remove the signals. We remove its declaration in blocks and we remove the signals from the relation + toBeRemoved1.add(sig1); + toBeRemoved2.add(sig2); + mightBeRemoved.add(rel); + } + } + } + } + + // Removing useless signals from blocks + for(AvatarBlock block: blocks) { + block.getSignals().removeAll(toBeRemoved1); + block.getSignals().removeAll(toBeRemoved2); + } + + // Removing signals from relations, and removing relations if applicable + for(int cpt=0; cpt<mightBeRemoved.size(); cpt++) { + AvatarRelation rel = mightBeRemoved.get(cpt); + rel.removeAssociation(toBeRemoved1.get(cpt), toBeRemoved2.get(cpt)); + if (rel.getSignals1().size() == 0) { + relations.remove(rel); + } + } + + } + + public void removeEmptyBlocks() { + // Remove all blocks with no ASM and no signals + ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>(); + for(AvatarBlock block: blocks) { + if (block.getStateMachine().isBasicStateMachine()) { + if (block.getSignals().size() == 0) { + toBeRemoved.add(block); + } + } + } + + blocks.removeAll(toBeRemoved); + } + + /** + * Removes attributes that are not used + */ + public void removeUselessAttributes() { + ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>(); + for(AvatarBlock block: blocks) { + block.removeUselessAttributes(); + } + } + + @@ -878,21 +952,15 @@ public class AvatarSpecification extends AvatarElement { } - // Then we can remove useless variables and signals and blocks + // Then we can remove useless attributes i.e attributes that are not used - // Remove all blocks with no ASM and no signals - ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>(); - for(AvatarBlock block: blocks) { - if (block.getStateMachine().isBasicStateMachine()) { - if (block.getSignals().size() == 0) { - toBeRemoved.add(block); - } - } - } - blocks.removeAll(toBeRemoved); + removeUselessSignalAssociations(); + + removeUselessAttributes(); + removeEmptyBlocks(); } diff --git a/src/main/java/avatartranslator/AvatarStateMachine.java b/src/main/java/avatartranslator/AvatarStateMachine.java index a446a333beb3aad4e0a73fc80468be3562e83f3c..209df735a34e781271e6643970a4e1e33d1ea101 100644 --- a/src/main/java/avatartranslator/AvatarStateMachine.java +++ b/src/main/java/avatartranslator/AvatarStateMachine.java @@ -274,6 +274,106 @@ public class AvatarStateMachine extends AvatarElement { return null; } + public boolean isSignalUsed(AvatarSignal _sig) { + for(AvatarStateMachineElement asme: elements) { + if (asme instanceof AvatarActionOnSignal) { + AvatarActionOnSignal aaos = (AvatarActionOnSignal) asme; + if (aaos.getSignal() == _sig) { + return true; + } + } + } + + return false; + } + + public boolean isTimerUsed(AvatarAttribute _timer) { + for(AvatarStateMachineElement asme: elements) { + if (asme instanceof AvatarTimerOperator) { + AvatarTimerOperator ato = (AvatarTimerOperator) asme; + if (ato.getTimer() == _timer) { + return true; + } + } + } + + return false; + } + + /** + * Analyze the usage of a regular attribute (int, bool) + * @param _aa + * @return + */ + public boolean isRegularAttributeUsed(AvatarAttribute _aa) { + boolean ret; + + AvatarExpressionSolver.emptyAttributesMap(); + for(AvatarStateMachineElement asme: elements) { + if (asme instanceof AvatarTransition) { + // Must check the guard, the delays and all the actions + AvatarTransition at = (AvatarTransition)asme; + + if (at.isGuarded()) { + ret = isInExpression(at.getGuard().toString(), _aa); + if (ret) { + return true; + } + } + + if (at.hasDelay()) { + ret = isInExpression(at.getMinDelay().toString(), _aa); + if (ret) { + return true; + } + ret = isInExpression(at.getMaxDelay().toString(), _aa); + if (ret) { + return true; + } + } + + for(AvatarAction act: at.getActions()) { + ret = isInExpression(act.toString(), _aa); + if (ret) { + return true; + } + } + + } else if (asme instanceof AvatarActionOnSignal) { + for(String s: ((AvatarActionOnSignal)asme).getValues()) { + ret = isInExpression(s, _aa); + if (ret) { + return true; + } + } + + } else if (asme instanceof AvatarRandom) { + AvatarRandom ar = (AvatarRandom)asme; + String s = ar.getVariable(); + ret = isInExpression(s, _aa); + if (ret) { + return true; + } + s = ar.getMinValue(); + ret = isInExpression(s, _aa); + if (ret) { + return true; + } + s = ar.getMaxValue(); + ret = isInExpression(s, _aa); + if (ret) { + return true; + } + } + } + + return false; + } + + private boolean isInExpression(String expr, AvatarAttribute _aa) { + return AvatarExpressionSolver.indexOfVariable(expr, _aa.getName()) > -1; + } + private int getSimplifiedElementsAux( Map<AvatarStateMachineElement, Integer> simplifiedElements, Set<AvatarStateMachineElement> visited, AvatarStateMachineElement root, int counter) { if (visited.contains(root)) { Integer name = simplifiedElements.get(root);