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);