diff --git a/src/main/java/avatartranslator/AvatarSignal.java b/src/main/java/avatartranslator/AvatarSignal.java
index 0785eae2f9666b17de1c703a7e9a1034f90f1475..f960bec2241f432cc649be1a89ab82bdacd751ef 100644
--- a/src/main/java/avatartranslator/AvatarSignal.java
+++ b/src/main/java/avatartranslator/AvatarSignal.java
@@ -136,7 +136,9 @@ public class AvatarSignal extends AvatarMethod {
         }
         return cumul;
 	}*/
-    //fin DG 
+    //fin DG
+
+
 	public AvatarSignal advancedClone(AvatarStateMachineOwner _block) {
 		AvatarSignal as = new AvatarSignal(getName(), getInOut(), getReferenceObject());
 		setAdvancedClone(as, _block);
diff --git a/src/main/java/avatartranslator/AvatarSpecification.java b/src/main/java/avatartranslator/AvatarSpecification.java
index 632f52c641e07ff536999d29e1ea23c8f55c97cd..443d92973d06e9b58f44f76463a429f634e1e89c 100644
--- a/src/main/java/avatartranslator/AvatarSpecification.java
+++ b/src/main/java/avatartranslator/AvatarSpecification.java
@@ -41,8 +41,8 @@ package avatartranslator;
 import myutil.NameChecker;
 import myutil.TraceManager;
 import org.json.JSONArray;
+import org.json.JSONException;
 import org.json.JSONObject;
-import ui.TAttribute;
 
 import java.util.*;
 
@@ -59,25 +59,23 @@ public class AvatarSpecification extends AvatarElement {
     public final static int UPPAAL_MAX_INT = 32767;
 
     public static String[] ops = {">", "<", "+", "-", "*", "/", "[", "]", "(", ")", ":", "=", "==", ",", "!", "?", "{", "}", "|", "&"};
-    public List<String> checkedIDs;
     private final List<AvatarBlock> blocks;
     private final List<AvatarRelation> relations;
-    private  List<AvatarInterfaceRelation> irelations;
     private final List<AvatarAMSInterface> interfaces;
     /**
      * The list of all library functions that can be called.
      */
     private final List<AvatarLibraryFunction> libraryFunctions;
-
-    //private AvatarBroadcast broadcast;
-    private String applicationCode;
     private final List<AvatarPragma> pragmas; // Security pragmas
     private final List<String> safetyPragmas;
     private final HashMap<String, String> safetyPragmasRefs;
     private final List<AvatarPragmaLatency> latencyPragmas;
     private final List<AvatarConstant> constants;
     private final boolean robustnessMade = false;
-
+    public List<String> checkedIDs;
+    private List<AvatarInterfaceRelation> irelations;
+    //private AvatarBroadcast broadcast;
+    private String applicationCode;
     private Object informationSource; // Element from which the spec has been built
 
 
@@ -97,956 +95,19 @@ public class AvatarSpecification extends AvatarElement {
         this.libraryFunctions = new LinkedList<>();
     }
 
-
-    public List<AvatarLibraryFunction> getListOfLibraryFunctions() {
-        return this.libraryFunctions;
-    }
-
-    public void addLibraryFunction(AvatarLibraryFunction libraryFunction) {
-        this.libraryFunctions.add(libraryFunction);
-    }
-
-    // For code generation
-    public void addApplicationCode(String _code) {
-        if (_code == null) {
-            return;
-        }
-        if (applicationCode == null) {
-            applicationCode = _code;
-            return;
-        }
-        applicationCode += _code + "\n";
-    }
-
-    public String getApplicationCode() {
-        if (applicationCode == null) {
-            return "";
-        }
-        return applicationCode;
-    }
-
-    public boolean hasApplicationCode() {
-        if (applicationCode == null) {
-            return false;
-        }
-        return (applicationCode.indexOf("__user_init()") != -1);
-    }
-
-    public Object getInformationSource() {
-        return informationSource;
-    }
-
-    public void setInformationSource(Object o) {
-        informationSource = o;
-    }
-
-    public List<AvatarBlock> getListOfBlocks() {
-        return blocks;
-    }
-
-    public List<AvatarAMSInterface> getListOfInterfaces() {
-        return interfaces;
-    }
-
-    public List<AvatarRelation> getRelations() {
-        return relations;
-    }
-
-    public List<AvatarPragma> getPragmas() {
-        return pragmas;
-    }
-
-    public List<String> getSafetyPragmas() {
-        return safetyPragmas;
-    }
-
-    public List<AvatarPragmaLatency> getLatencyPragmas() {
-        return latencyPragmas;
-    }
-
-    public List<AvatarConstant> getAvatarConstants() {
-        return constants;
-    }
-
-    public HashMap<String, String> getSafetyPragmasRefs() {
-        return safetyPragmasRefs;
-    }
-
-    public int getNbOfASMGraphicalElements() {
-        int cpt = 0;
-        for (AvatarBlock block : blocks) {
-            cpt += block.getNbOfASMGraphicalElements();
-        }
-        return cpt;
-    }
-
-    public boolean isASynchronousSignal(AvatarSignal _as) {
-        for (AvatarRelation ar : relations) {
-            if (ar.containsSignal(_as)) {
-                return !(ar.isAsynchronous());
-            }
-        }
-
-        return false;
-    }
-
-    public AvatarSignal getCorrespondingSignal(AvatarSignal _as) {
-        for (AvatarRelation ar : relations) {
-            if (ar.containsSignal(_as)) {
-                int index = ar.hasSignal(_as);
-                return ar.getInSignal(index);
-            }
-        }
-        return null;
-    }
-
-    //DG
-    public boolean ASynchronousExist() {
-        List<AvatarRelation> asynchro = getRelations();
-
-        for (AvatarRelation ar : asynchro)
-            if (ar.isAsynchronous())
-                return true;
-
-        return false;
-    }
-
-    public boolean AMSExist() {
-        List<AvatarRelation> ams = getRelations();
-
-        for (AvatarRelation ar : ams)
-            if (ar.isAMS())
-                return true;
-
-        return false;
-    }
-
-    // end DG
-    public void addBlock(AvatarBlock _block) {
-        blocks.add(_block);
-    }
-
-    public void addInterface(AvatarAMSInterface _interface) {
-        interfaces.add(_interface);
-    }
-
-    /*public void addBroadcastSignal(AvatarSignal _as) {
-      if (!broadcast.containsSignal(_as)) {
-      broadcast.addSignal(_as);
-      }
-      }
-
-      public AvatarBroadcast getBroadcast() {
-      return broadcast;
-      }*/
-
-    public void addRelation(AvatarRelation _relation) {
-        relations.add(_relation);
-    }
-
-    public void addInterfaceRelation(AvatarInterfaceRelation _irelation) {
-        irelations.add(_irelation);
-    }
-
-    public void addPragma(AvatarPragma _pragma) {
-        pragmas.add(_pragma);
-    }
-
-    public void addSafetyPragma(String _pragma, String _refPragmas) {
-        safetyPragmas.add(_pragma);
-        safetyPragmasRefs.put(_pragma, _refPragmas);
-    }
-
-    public void addLatencyPragma(AvatarPragmaLatency _pragma) {
-        latencyPragmas.add(_pragma);
-    }
-
-    public void addConstant(AvatarConstant _constant) {
-        //Only add unique constants
-        if (this.getAvatarConstantWithName(_constant.getName()) == null) {
-            constants.add(_constant);
-        }
-    }
-
-    @Override
-    public String toString() {
-        //Thread.currentThread().dumpStack();
-        StringBuffer sb = new StringBuffer("Blocks:\n");
-        //TraceManager.addDev("TS Block");
-        for (AvatarBlock block : blocks) {
-            sb.append("*** " + block.toString() + "\n");
-        }
-        //TraceManager.addDev("TS Relations");
-        sb.append("\nRelations:\n");
-        for (AvatarRelation relation : relations) {
-            sb.append("Relation:" + relation.toString() + "\n");
-        }
-        sb.append("\nPragmas:\n");
-        for (AvatarPragma pragma : pragmas) {
-            sb.append("Pragma:" + pragma.toString() + "\n");
-        }
-        for (AvatarConstant constant : constants) {
-            sb.append("Constant:" + constant.toString() + "\n");
-        }
-
-        //TraceManager.addDev("TS All done");
-
-        return sb.toString();
-    }
-
-    public String toShortString() {
-        //TraceManager.addDev("To Short String");
-        //Thread.currentThread().dumpStack();
-        StringBuffer sb = new StringBuffer("Blocks:\n");
-        for (AvatarBlock block : blocks) {
-            sb.append("*** " + block.toShortString() + "\n");
-        }
-        sb.append("\nRelations:\n");
-        for (AvatarRelation relation : relations) {
-            sb.append("Relation:" + relation.toString() + "\n");
-        }
-        /*for (AvatarConstant constant: constants){
-            sb.append("Constant:" + constant.toString() + "\n");
-        }*/
-
-        return sb.toString();
-    }
-
-    public AvatarBlock getBlockWithName(String _name) {
-        for (AvatarBlock block : blocks) {
-            if (block.getName().compareTo(_name) == 0) {
-                return block;
-            }
-        }
-
-        return null;
-    }
-
-    public int getBlockIndex(AvatarBlock _block) {
-        int cpt = 0;
-        for (AvatarBlock block : blocks) {
-            if (block == _block) {
-                return cpt;
-            }
-            cpt++;
-        }
-
-        return -1;
-    }
-
-    public AvatarAMSInterface getAMSInterfaceWithName(String _name) {
-        for (AvatarAMSInterface interf : interfaces) {
-            if (interf.getName().compareTo(_name) == 0) {
-                return interf;
+    public AvatarRelation getAvatarRelationWithBlocks (AvatarBlock block1, AvatarBlock block2, boolean synchronous) {
+        for(AvatarRelation rel: relations) {
+            if ( (block1 == rel.block1) || (block1 == rel.block2) ) {
+                if ( (block2 == rel.block1) || (block2 == rel.block2) ) {
+                    if (rel.isAsynchronous() == !synchronous) {
+                        return rel;
+                    }
+                }
             }
         }
-
         return null;
     }
 
-    public AvatarConstant getAvatarConstantWithName(String _name) {
-        for (AvatarConstant constant : constants) {
-            if (constant.getName().compareTo(_name) == 0) {
-                return constant;
-            }
-        }
-
-        return null;
-    }
-
-    /* Generates the Expression Solvers, returns the AvatarStateMachineElement
-     * containing the errors */
-    public List<AvatarStateMachineElement> generateAllExpressionSolvers() {
-        List<AvatarStateMachineElement> errors = new ArrayList<>();
-        AvatarTransition at;
-        boolean returnVal;
-
-        AvatarExpressionSolver.emptyAttributesMap();
-
-        for (AvatarBlock block : getListOfBlocks()) {
-            AvatarStateMachine asm = block.getStateMachine();
-
-            for (AvatarStateMachineElement elt : asm.getListOfElements()) {
-                if (elt instanceof AvatarTransition) {
-                    at = (AvatarTransition) elt;
-                    if (at.isGuarded()) {
-                        returnVal = at.buildGuardSolver();
-                        if (returnVal == false) {
-                            errors.add(at);
-                        }
-                    }
-                    if (at.hasDelay()) {
-                        returnVal = at.buildDelaySolver();
-                        if (returnVal == false) {
-                            errors.add(at);
-                        }
-                    }
-                    for (AvatarAction aa : at.getActions()) {
-                        if (aa instanceof AvatarActionAssignment) {
-                            returnVal = ((AvatarActionAssignment) aa).buildActionSolver(block);
-                            if (returnVal == false) {
-                                errors.add(elt);
-                            }
-                        }
-                    }
-                } else if (elt instanceof AvatarActionOnSignal) {
-                    returnVal = ((AvatarActionOnSignal) elt).buildActionSolver(block);
-                    if (returnVal == false) {
-                        errors.add(elt);
-                    }
-                }
-            }
-        }
-
-        return errors;
-    }
-
-    public void removeCompositeStates() {
-        for (AvatarBlock block : blocks) {
-            //TraceManager.addDev("- - - - - - - - Removing composite states of " + block);
-            block.getStateMachine().removeCompositeStates(block);
-        }
-    }
-
-    public void makeFullStates() {
-        for (AvatarBlock block : blocks) {
-            block.getStateMachine().makeFullStates(block);
-        }
-    }
-
-    public void removeRandoms() {
-        for (AvatarBlock block : blocks) {
-            block.getStateMachine().removeRandoms(block);
-        }
-    }
-
-    public void removeAllDelays() {
-        for (AvatarBlock block : blocks) {
-            block.getStateMachine().removeAllDelays();
-        }
-    }
-
-    public void removeTimers() {
-        //renameTimers();
-
-        List<AvatarBlock> addedBlocks = new LinkedList<AvatarBlock>();
-        for (AvatarBlock block : blocks) {
-            if (block.hasTimerAttribute()) {
-                block.removeTimers(this, addedBlocks);
-            }
-        }
-
-        for (int i = 0; i < addedBlocks.size(); i++) {
-            addBlock(addedBlocks.get(i));
-        }
-    }
-
-    public void removeConstants() {
-        for (AvatarBlock block : blocks) {
-            block.removeConstantAttributes();
-        }
-    }
-
-    public void sortAttributes() {
-        for (AvatarBlock block : blocks) {
-            block.sortAttributes();
-        }
-    }
-
-    public void setAttributeOptRatio(int attributeOptRatio) {
-        for (AvatarBlock block : blocks) {
-            block.setAttributeOptRatio(attributeOptRatio);
-        }
-    }
-
-//
-//    private void renameTimers() {
-//        // Check whether timers have the same name in different blocks
-//        ArrayList<AvatarAttribute> allTimers = new ArrayList<AvatarAttribute>();
-//        for(AvatarBlock block: blocks) {
-//            allTimers.clear();
-//            block.putAllTimers(allTimers);
-//            for(AvatarAttribute att: allTimers) {
-//                for(AvatarBlock bl: blocks) {
-//                    if (block != bl) {
-//                        if (bl.hasTimer(att.getName())) {
-//                            // Must change name of timer
-//                            TraceManager.addDev("Changing name of Timer:" + att);
-//                            att.setName(att.getName() + "__" + block.getName());
-//                        }
-//                    }
-//                }
-//            }
-//        }
-//
-//    }
-
-    /**
-     * Removes all FIFOs by replacing them with
-     * synchronous relations and one block per FIFO
-     * The size of the infinite fifo is max 1024
-     * and min 1
-     *
-     * @param _maxSizeOfInfiniteFifo : the max size of the infinite fifo
-     */
-    public void removeFIFOs(int _maxSizeOfInfiniteFifo) {
-        List<AvatarRelation> oldOnes = new LinkedList<AvatarRelation>();
-        List<AvatarRelation> newOnes = new LinkedList<AvatarRelation>();
-
-        int FIFO_ID = 0;
-        for (AvatarRelation ar : relations) {
-            if (ar.isAsynchronous()) {
-                // Must be removed
-                int size = Math.min(_maxSizeOfInfiniteFifo, ar.getSizeOfFIFO());
-                //TraceManager.addDev("***************************** Size of FIFO:" + size);
-                size = Math.max(1, size);
-                FIFO_ID = removeFIFO(ar, size, oldOnes, newOnes, FIFO_ID);
-            }
-        }
-
-        for (AvatarRelation ar : oldOnes) {
-            relations.remove(ar);
-        }
-
-        for (AvatarRelation ar : newOnes) {
-            relations.add(ar);
-        }
-
-    }
-
-    private int removeFIFO(AvatarRelation _ar, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes, List<AvatarRelation> _newOnes, int FIFO_ID) {
-        for (int i = 0; i < _ar.nbOfSignals(); i++) {
-            //TraceManager.addDev("FIFO for AR: " + _ar.getBlock1().getName() + " --> " + _ar.getBlock2().getName());
-            if (_ar.getSignal1(i).isIn()) {
-                FIFO_ID = removeFIFO(_ar, _ar.getSignal2(i), _ar.getSignal1(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block2,
-                        _ar.block1);
-            } else {
-                FIFO_ID = removeFIFO(_ar, _ar.getSignal1(i), _ar.getSignal2(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block1,
-                        _ar.block2);
-            }
-        }
-        _oldOnes.add(_ar);
-        return FIFO_ID;
-    }
-
-    private int removeFIFO(AvatarRelation _ar, AvatarSignal _sig1, AvatarSignal _sig2, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes,
-                           List<AvatarRelation> _newOnes, int FIFO_ID, AvatarBlock block1, AvatarBlock block2) {
-        // We create the new block, and the new relation towards the new block
-        String nameOfBlock = "FIFO_" + _sig1.getName() + "_" + _sig2.getName() + "_" + FIFO_ID;
-        AvatarBlock fifoBlock = AvatarBlockTemplate.getFifoBlock(nameOfBlock, this, _ar, _ar.getReferenceObject(), _sig1, _sig2,
-                _sizeOfInfiniteFifo, FIFO_ID);
-        //fifoBlock.getStateMachine().groupUselessTransitions(fifoBlock);
-        blocks.add(fifoBlock);
-
-        // We now need to create the new relation
-        AvatarRelation newAR1 = new AvatarRelation("FIFO_write_" + FIFO_ID, block1, fifoBlock, _ar.getReferenceObject());
-        newAR1.setAsynchronous(false);
-        newAR1.setPrivate(_ar.isPrivate());
-        //TraceManager.addDev("FIFO. Connecting " + _sig1.getName() + " to write of FIFO " + fifoBlock.getName());
-        newAR1.addSignals(_sig1, fifoBlock.getSignalByName("write"));
-        _newOnes.add(newAR1);
-
-        AvatarRelation newAR2 = new AvatarRelation("FIFO_read_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject());
-        newAR2.setAsynchronous(false);
-        newAR2.setPrivate(_ar.isPrivate());
-        //TraceManager.addDev("FIFO. Connecting FIFO " + fifoBlock.getName() + " read to " + _sig2.getName());
-        newAR2.addSignals(fifoBlock.getSignalByName("read"), _sig2);
-        _newOnes.add(newAR2);
-
-        // We also add the query signals to the newAR2 relation
-
-
-        AvatarSignal queryS = new AvatarSignal("query_FIFO_read_" + FIFO_ID, AvatarSignal.IN, _sig2.getReferenceObject());
-        block2.addSignal(queryS);
-        AvatarAttribute queryA = new  AvatarAttribute("queryA", AvatarType.INTEGER, null, _sig2.getReferenceObject());
-        queryS.addParameter(queryA);
-
-        AvatarRelation newAR3 = new AvatarRelation("FIFO_query_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject());
-        newAR3.setAsynchronous(false);
-        newAR3.setPrivate(_ar.isPrivate());
-        newAR3.addSignals(fifoBlock.getSignalByName("query"), queryS);
-        _newOnes.add(newAR3);
-
-        // Replace query in block2 for _sig2 by readOnSignal with signal queryS. Use the same attribute as before
-        block2.replaceQueriesWithReadSignal(_sig2, queryS);
-
-
-        FIFO_ID++;
-
-        return FIFO_ID;
-    }
-
-    public boolean areSynchronized(AvatarSignal as1, AvatarSignal as2) {
-        AvatarRelation ar = getAvatarRelationWithSignal(as1);
-        if (ar == null) {
-            return false;
-        }
-
-        int index1 = ar.getIndexOfSignal(as1);
-        int index2 = ar.getIndexOfSignal(as2);
-
-        return (index1 == index2);
-    }
-
-    public AvatarRelation getAvatarRelationWithSignal(AvatarSignal _as) {
-        for (AvatarRelation ar : relations) {
-            if (ar.hasSignal(_as) > -1) {
-                return ar;
-            }
-        }
-        return null;
-    }
-
-    public AvatarStateMachineElement getStateMachineElementFromReferenceObject(Object _o) {
-        AvatarStateMachineElement asme;
-        for (AvatarBlock block : blocks) {
-            asme = block.getStateMachineElementFromReferenceObject(_o);
-            if (asme != null) {
-                return asme;
-            }
-        }
-        return null;
-    }
-
-    public AvatarBlock getBlockFromReferenceObject(Object _o) {
-        for (AvatarBlock block : blocks) {
-            if (block.containsStateMachineElementWithReferenceObject(_o)) {
-                return block;
-            }
-        }
-        return null;
-    }
-
-    public AvatarBlock getBlockWithAttribute(String _attributeName) {
-        int index;
-
-        for (AvatarBlock block : blocks) {
-            index = block.getIndexOfAvatarAttributeWithName(_attributeName);
-            if (index > -1) {
-                return block;
-            }
-        }
-        return null;
-    }
-
-    public void removeElseGuards() {
-        for (AvatarBlock block : blocks) {
-            removeElseGuards(block.getStateMachine());
-        }
-        for (AvatarLibraryFunction function : libraryFunctions) {
-            removeElseGuards(function.getStateMachine());
-        }
-    }
-
-
-    private void removeElseGuards(AvatarStateMachine asm) {
-        if (asm == null)
-            return;
-
-        for (AvatarStateMachineElement asme : asm.getListOfElements()) {
-            if (!(asme instanceof AvatarState))
-                continue;
-
-            //TraceManager.addDev("Working with state " + asme.getNiceName());
-            for (AvatarStateMachineElement next : asme.getNexts()) {
-                if (!(next instanceof AvatarTransition))
-                    continue;
-                AvatarTransition at = (AvatarTransition) next;
-                AvatarGuard ancientGuard = at.getGuard();
-
-                if (ancientGuard == null)
-                    continue;
-
-                //TraceManager.addDev("[[[[[[[[[[[[[[[ Guard before: " + ancientGuard.toString() + " type:" + ancientGuard.getClass().toString());
-                at.setGuard(ancientGuard.getRealGuard(asme));
-                //TraceManager.addDev("]]]]]]]]]]]]]]] Guard after: " + at.getGuard().toString());
-            }
-        }
-    }
-
-    /**
-     * Removes all function calls by inlining them.
-     */
-    public void removeLibraryFunctionCalls() {
-        for (AvatarBlock block : this.blocks) {
-            AvatarStateMachine asm = block.getStateMachine();
-            if (asm == null)
-                continue;
-
-            asm.removeLibraryFunctionCalls(block);
-        }
-
-
-        //TraceManager.addDev("\n\nNew spec:" + this.toString() + "\n");
-    }
-
-    public boolean hasLossyChannel() {
-        for (AvatarRelation relation : relations)
-            if (relation.isLossy())
-                return true;
-
-        return false;
-    }
-
-
-    public void removeEmptyTransitions(boolean _canOptimize) {
-        for (AvatarBlock block : this.blocks) {
-            AvatarStateMachine asm = block.getStateMachine();
-            if (asm != null)
-                asm.removeEmptyTransitions(block, _canOptimize);
-        }
-    }
-
-    public void groupUselessTransitions() {
-        for (AvatarBlock block : this.blocks) {
-            AvatarStateMachine asm = block.getStateMachine();
-            if (asm != null)
-                asm.groupUselessTransitions(block);
-        }
-    }
-
-
-    public void makeRobustness() {
-        //TraceManager.addDev("Make robustness");
-        if (robustnessMade) {
-            return;
-        }
-
-        /*robustnessMade = true;
-
-          TraceManager.addDev("Testing lossy channels");
-
-          if (hasLossyChannel()) {
-          TraceManager.addDev("Making robustness");
-          int idstate = 0;
-          for(AvatarBlock block: blocks) {
-          idstate = block.getStateMachine().makeMessageLostRobustness(idstate);
-          }
-
-          /*AvatarBlock ab = new AvatarBlock("Robustness__", this.getReferenceObject());
-          addBlock(ab);
-          AvatarMethod am = new AvatarMethod("messageLost", null);
-          ab.addMethod(am);
-          AvatarStateMachine asm = ab.getStateMachine();
-          AvatarStartState ass = new AvatarStartState("StartState", null);
-          asm.addElement(ass);
-          asm.setStartState(ass);
-          AvatarTransition at = new AvatarTransition("Transition", null);
-          asm.addElement(at);
-          ass.addNext(at);
-          AvatarState state = new AvatarState("MainState", null);
-          asm.addElement(state);
-          at.addNext(state);
-
-          // Parsing all state machines to add robustness
-          AvatarStateMachine sm;
-          AvatarActionOnSignal aaos;
-          AvatarSignal as;
-          AvatarState state0;
-          int i;
-
-          for(AvatarRelation ar: relations) {
-          if (ar.isAsynchronous() && ar.isLossy()) {
-          // Modify the relation
-          ar.makeRobustness();
-          for(i=0; i<ar.nbOfSignals(); i = i+2) {
-          as = ar.getInSignal(i);
-          at = new AvatarTransition("TransitionToReceiving", null);
-          asm.addElement(at);
-          state.addNext(at);
-          aaos = new AvatarActionOnSignal("Receiving__" + as.getName(), as, null);
-          asm.addElement(aaos);
-          at.addNext(aaos);
-          at = new AvatarTransition("TransitionToIntermediateState", null);
-          asm.addElement(at);
-          state0 = new AvatarState("Choice__" + as.getName(), null);
-          asm.addElement(state0);
-          aaos.addNext(at);
-          at.addNext(state0);
-          at = new AvatarTransition("TransitionToMainState", null);
-          at.addAction("messageLost()");
-          asm.addElement(at);
-          state0.addNext(at);
-          at.addNext(state);
-
-          as = ar.getOutSignal(i+1);
-          at = new AvatarTransition("TransitionToSending", null);
-          asm.addElement(at);
-          aaos = new AvatarActionOnSignal("Sending__" + as.getName(), as, null);
-          asm.addElement(aaos);
-          state0.addNext(at);
-          at.addNext(aaos);
-          at = new AvatarTransition("TransitionAfterSending", null);
-          asm.addElement(at);
-          aaos.addNext(at);
-          at.addNext(state);
-          }
-
-          }
-          }
-          }*/
-    }
-
-    public AvatarSpecification advancedClone() {
-        AvatarSpecification spec = new AvatarSpecification(this.getName(), this.getReferenceObject());
-        Map<AvatarBlock, AvatarBlock> correspondenceBlocks = new HashMap<AvatarBlock, AvatarBlock>();
-
-        // Cloning block definition
-        for (AvatarBlock block : blocks) {
-            AvatarBlock nB = block.advancedClone(spec);
-            correspondenceBlocks.put(block, nB);
-            spec.addBlock(nB);
-        }
-
-        // Handling the clone of fathers
-        for (AvatarBlock block : blocks) {
-            AvatarBlock father = block.getFather();
-            if (father != null) {
-                AvatarBlock nb = spec.getBlockWithName(block.getName());
-                if (nb != null) {
-                    AvatarBlock nf = spec.getBlockWithName(father.getName());
-                    if (nf != null) {
-                        //TraceManager.addDev("Setting "+ nf.getName() + " as the father of " + nb.getName());
-                        nb.setFather(nf);
-                    }
-                }
-            }
-        }
-
-        // Cloning asm
-        for (AvatarBlock block : blocks) {
-            AvatarBlock nb = spec.getBlockWithName(block.getName());
-            block.getStateMachine().advancedClone(nb.getStateMachine(), nb);
-        }
-
-        // Relations
-        for (AvatarRelation relation : relations) {
-            AvatarRelation nR = relation.advancedClone(correspondenceBlocks);
-            if (nR != null) {
-                spec.addRelation(nR);
-            }
-        }
-	
-		/*for(AvatarPragma pragma: pragmas) {
-		    AvatarPragma nP = pragma.advancedClone();
-		    spec.addPragma(nP);
-		    }*/
-
-        for (String safetyPragma : safetyPragmas) {
-            spec.addSafetyPragma(safetyPragma, safetyPragmasRefs.get(safetyPragma));
-        }
-
-        for (AvatarPragmaLatency latencyPragma : latencyPragmas) {
-            spec.addLatencyPragma(latencyPragma);
-        }
-
-        for (AvatarConstant constant : constants) {
-            AvatarConstant cN = constant.advancedClone();
-            spec.addConstant(cN);
-        }
-        for (String id : checkedIDs) {
-            spec.checkedIDs.add(id);
-        }
-
-        spec.setInformationSource(getInformationSource());
-        spec.addApplicationCode(getApplicationCode());
-
-        return spec;
-    }
-
-    public AvatarAttribute getMatchingAttribute(AvatarAttribute aa) {
-        for (AvatarBlock block : this.blocks) {
-            if (block.getName().compareTo(aa.getBlock().getName()) == 0) {
-                return block.getAvatarAttributeWithName(aa.getName());
-            }
-        }
-
-        return null;
-    }
-
-    public AvatarDependencyGraph makeDependencyGraph() {
-        return makeDependencyGraph(true);
-    }
-
-    public AvatarDependencyGraph makeDependencyGraph(boolean withID) {
-        AvatarDependencyGraph adg = new AvatarDependencyGraph();
-        adg.buildGraph(this, withID);
-        return adg;
-    }
-
-
-    public AvatarSpecification simplifyFromDependencies(ArrayList<AvatarElement> eltsOfInterest) {
-        AvatarSpecification clonedSpec = advancedClone();
-        AvatarDependencyGraph adg = clonedSpec.makeDependencyGraph();
-        AvatarDependencyGraph reducedGraph = adg.reduceGraphBefore(eltsOfInterest);
-        clonedSpec.reduceFromDependencyGraph(reducedGraph);
-        return clonedSpec;
-    }
-
-
-    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);
-                }
-            }
-        }
-
-        // If a block has a father in toBeRemoved, then keep the father, and the father of the father, etc.
-        for(AvatarBlock block: blocks) {
-            AvatarBlock bl = block.getFather();
-            while(bl != null) {
-                if (toBeRemoved.contains(bl)) {
-                    toBeRemoved.remove(bl);
-                }
-                bl = bl.getFather();
-             }
-        }
-
-
-        blocks.removeAll(toBeRemoved);
-    }
-
-    /**
-     * Removes attributes that are not used
-     */
-    public void removeUselessAttributes() {
-        ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>();
-        for(AvatarBlock block: blocks) {
-            block.removeUselessAttributes();
-        }
-    }
-
-
-
-
-
-    // TO BE COMPLETED
-    // We assume the graph has been reduced already to what is necessary:
-    // We now need to reduce the avatarspec accordingly
-    public void reduceFromDependencyGraph(AvatarDependencyGraph _adg) {
-
-        // We have to update the state machines according to the graph
-        for(AvatarBlock block: blocks) {
-            //TraceManager.addDev("Handling block " + block.getName());
-            AvatarStateMachine asm = block.getStateMachine();
-            // We first check if the start is still in the graph
-            // If not, the state machine is empty: we just create a stop, and that's it
-            AvatarStartState ass = asm.getStartState();
-            if (_adg.getFirstStateWithReference(ass) == null) {
-                TraceManager.addDev("No start state in " + block.getName());
-                asm.makeBasicSM(block);
-                block.clearAttributes();
-            } else {
-
-                // Otherwise we keep the start and consider all other elements
-                // We remove all elements with no correspondence in the graph
-                // Then, we redo a valid ASM i.e. all elements with no nexts (apart from states)
-                // are given a stop state after
-
-                TraceManager.addDev("Reducing state machine of " + block.getName());
-
-                ArrayList<AvatarElement> toRemove = new ArrayList<>();
-                for(AvatarStateMachineElement asme: asm.getListOfElements()) {
-                    if (_adg.getFirstStateWithReference(asme) == null) {
-                        boolean toBeRemoved = false;
-                        if (asme instanceof AvatarTransition) {
-                            if (!((AvatarTransition) asme).isEmpty()) {
-                                toBeRemoved = true;
-                            }
-                        } else {
-                            toBeRemoved = true;
-                        }
-
-                        if (toBeRemoved)
-                            toRemove.add(asme);
-
-                    }
-
-                }
-                TraceManager.addDev("To remove size: " + toRemove.size() + " size of ASM: " + asm.getListOfElements().size());
-                asm.getListOfElements().removeAll(toRemove);
-                TraceManager.addDev("Removed. New size of ASM: " + asm.getListOfElements().size());
-                asm.makeCorrect(block);
-            }
-        }
-
-
-        // Then we can remove useless attributes i.e attributes that are not used
-
-
-
-        removeUselessSignalAssociations();
-
-        removeUselessAttributes();
-
-        removeEmptyBlocks();
-
-    }
-
-
-    public NameChecker.NamedElement[] getSubNamedElements() {
-        NameChecker.NamedElement[] lne = new NameChecker.NamedElement[blocks.size()];
-        int index = 0;
-        for(AvatarBlock bl: blocks) {
-            lne[index] = bl;
-            index ++;
-        }
-        return lne;
-    }
-
     /*
     * Typical JSON:
     *
@@ -1452,70 +513,1108 @@ public class AvatarSpecification extends AvatarElement {
     *
     *
      */
-    public static AvatarSpecification fromJSON(String _spec, String _name, Object _referenceObject) {
-        AvatarSpecification spec = new AvatarSpecification(_name, _referenceObject);
+    public static AvatarSpecification fromJSON(String _spec, String _name, Object _referenceObject) {
+        AvatarSpecification spec = new AvatarSpecification(_name, _referenceObject);
+
+        int indexStart = _spec.indexOf('{');
+        int indexStop = _spec.lastIndexOf('}');
+
+        if ((indexStart == -1) || (indexStop == -1) || (indexStart > indexStop)) {
+            throw new org.json.JSONException("Invalid JSON object");
+        }
+
+        _spec = _spec.substring(indexStart, indexStop + 1);
+
+        TraceManager.addDev("Cut spec: " + _spec);
+
+        JSONObject mainObject = new JSONObject(_spec);
+
+        JSONArray blocksA = mainObject.getJSONArray("blocks");
+
+        if (blocksA == null) {
+            TraceManager.addDev("No blocks in json");
+            return spec;
+        }
+
+        for (int i = 0; i < blocksA.length(); i++) {
+            JSONObject blockO = blocksA.getJSONObject(i);
+            String name = spec.removeSpaces(blockO.getString("name"));
+            if (name != null) {
+                AvatarBlock newBlock = new AvatarBlock(name, spec, _referenceObject);
+                spec.addBlock(newBlock);
+
+                try {
+                    JSONArray attributesA = blockO.getJSONArray("attributes");
+
+                    for (int j = 0; j < attributesA.length(); j++) {
+                        String nameA = spec.removeSpaces(attributesA.getJSONObject(j).getString("name"));
+                        String typeA = attributesA.getJSONObject(j).getString("type");
+                        AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject);
+                        newBlock.addAttribute(aa);
+                    }
+                } catch (JSONException je) {
+                }
+
+                try {
+                    JSONArray methodsA = blockO.getJSONArray("methods");
+                    for (int j = 0; j < methodsA.length(); j++) {
+                        String nameM = spec.removeSpaces(methodsA.getJSONObject(j).getString("name"));
+                        AvatarMethod am = new AvatarMethod(nameM, _referenceObject);
+                        JSONArray params = methodsA.getJSONObject(j).getJSONArray("parameters");
+                        for (int k = 0; k < params.length(); k++) {
+                            String nameA = spec.removeSpaces(params.getJSONObject(k).getString("name"));
+                            String typeA = params.getJSONObject(k).getString("type");
+                            AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject);
+                            am.addParameter(aa);
+                        }
+                        String returnT = methodsA.getJSONObject(j).getString("returnType");
+                        AvatarType at = AvatarType.getType(returnT);
+                        if (at != AvatarType.UNDEFINED) {
+                            am.addReturnParameter(new AvatarAttribute("returnType", at, newBlock, _referenceObject));
+                        }
+
+                        newBlock.addMethod(am);
+                    }
+                } catch (JSONException je) {
+                }
+
+                try {
+                    JSONArray signalS = blockO.getJSONArray("signals");
+                    for (int j = 0; j < signalS.length(); j++) {
+                        String nameS = spec.removeSpaces(signalS.getJSONObject(j).getString("name"));
+                        String typeS = signalS.getJSONObject(j).getString("type");
+                        int inout = AvatarSignal.IN;
+                        if (typeS.compareTo("output") == 0) {
+                            inout = AvatarSignal.OUT;
+                        }
+                        AvatarSignal as = new AvatarSignal(nameS, inout, _referenceObject);
+
+                        JSONArray params = signalS.getJSONObject(j).getJSONArray("parameters");
+                        for (int k = 0; k < params.length(); k++) {
+                            String nameA = spec.removeSpaces(params.getJSONObject(k).getString("name"));
+                            String typeA = params.getJSONObject(k).getString("type");
+                            AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject);
+                            as.addParameter(aa);
+                        }
+
+                        newBlock.addSignal(as);
+                    }
+                } catch (JSONException je) {
+                }
+
+            }
+        }
+
+        JSONArray connections = mainObject.getJSONArray("connections");
+
+        if (connections == null) {
+            TraceManager.addDev("No connections in json");
+            return spec;
+        }
+
+        for (int i = 0; i < connections.length(); i++) {
+            JSONObject blockO = connections.getJSONObject(i);
+            String sourceBlock = spec.removeSpaces(blockO.getString("sourceBlock"));
+
+            AvatarBlock srcB = spec.getBlockWithName(sourceBlock);
+            if (srcB == null) {
+                srcB = new AvatarBlock(sourceBlock, spec, _referenceObject);
+                spec.addBlock(srcB);
+            }
+            String sourceSignal = spec.removeSpaces(blockO.getString("sourceSignal"));
+            AvatarSignal srcSig = srcB.getSignalByName(sourceSignal);
+
+            if (srcSig == null) {
+                srcSig = new AvatarSignal(sourceSignal, AvatarSignal.OUT, _referenceObject);
+                srcB.addSignal(srcSig);
+            }
+            if (srcSig.isIn()) {
+                TraceManager.addDev("Signal " + sourceSignal + " in block: " + sourceBlock + " should be out");
+                continue;
+            }
+            String destinationBlock = spec.removeSpaces(blockO.getString("destinationBlock"));
+            AvatarBlock dstB = spec.getBlockWithName(destinationBlock);
+
+            if (dstB == null) {
+                dstB = new AvatarBlock(destinationBlock, spec, _referenceObject);
+                spec.addBlock(dstB);
+            }
+            String dstSignal = spec.removeSpaces(blockO.getString("destinationSignal"));
+            AvatarSignal dstSig = srcB.getSignalByName(dstSignal);
+
+            if (dstSig == null) {
+                dstSig = new AvatarSignal(sourceSignal, AvatarSignal.IN, _referenceObject);
+                dstB.addSignal(dstSig);
+            }
+            if (srcSig.isOut()) {
+                TraceManager.addDev("Signal " + dstSignal + " in block: " + destinationBlock + " should be in");
+                continue;
+            }
+
+            if (!srcSig.isCompatibleWith(dstSig)) {
+                TraceManager.addDev("Signals " + srcSig + " and " + dstSignal + " are not compatible");
+                continue;
+            }
+
+            String communicationType = spec.removeSpaces(blockO.getString("communicationType"));
+            boolean synchronous = communicationType.compareTo("synchronous") == 0;
+
+            AvatarRelation ar = spec.getAvatarRelationWithBlocks(srcB, dstB, synchronous);
+
+            if (ar == null) {
+                ar = new AvatarRelation("relation", srcB, dstB, _referenceObject);
+                ar.setAsynchronous(!synchronous);
+                spec.addRelation(ar);
+            }
+
+            ar.addSignals(srcSig, dstSig);
+
+        }
+
+
+        return spec;
+
+    }
+
+    public String removeSpaces(String _input) {
+        return _input.trim().replaceAll(" ", "_");
+    }
+
+    public List<AvatarLibraryFunction> getListOfLibraryFunctions() {
+        return this.libraryFunctions;
+    }
+
+    public void addLibraryFunction(AvatarLibraryFunction libraryFunction) {
+        this.libraryFunctions.add(libraryFunction);
+    }
+
+    // For code generation
+    public void addApplicationCode(String _code) {
+        if (_code == null) {
+            return;
+        }
+        if (applicationCode == null) {
+            applicationCode = _code;
+            return;
+        }
+        applicationCode += _code + "\n";
+    }
+
+    public String getApplicationCode() {
+        if (applicationCode == null) {
+            return "";
+        }
+        return applicationCode;
+    }
+
+    public boolean hasApplicationCode() {
+        if (applicationCode == null) {
+            return false;
+        }
+        return (applicationCode.indexOf("__user_init()") != -1);
+    }
+
+    public Object getInformationSource() {
+        return informationSource;
+    }
+
+    public void setInformationSource(Object o) {
+        informationSource = o;
+    }
+
+    public List<AvatarBlock> getListOfBlocks() {
+        return blocks;
+    }
+
+    public List<AvatarAMSInterface> getListOfInterfaces() {
+        return interfaces;
+    }
+
+    public List<AvatarRelation> getRelations() {
+        return relations;
+    }
+
+    public List<AvatarPragma> getPragmas() {
+        return pragmas;
+    }
+
+    public List<String> getSafetyPragmas() {
+        return safetyPragmas;
+    }
+
+    public List<AvatarPragmaLatency> getLatencyPragmas() {
+        return latencyPragmas;
+    }
+
+    public List<AvatarConstant> getAvatarConstants() {
+        return constants;
+    }
+
+    public HashMap<String, String> getSafetyPragmasRefs() {
+        return safetyPragmasRefs;
+    }
+
+    public int getNbOfASMGraphicalElements() {
+        int cpt = 0;
+        for (AvatarBlock block : blocks) {
+            cpt += block.getNbOfASMGraphicalElements();
+        }
+        return cpt;
+    }
+
+    public boolean isASynchronousSignal(AvatarSignal _as) {
+        for (AvatarRelation ar : relations) {
+            if (ar.containsSignal(_as)) {
+                return !(ar.isAsynchronous());
+            }
+        }
+
+        return false;
+    }
+
+    public AvatarSignal getCorrespondingSignal(AvatarSignal _as) {
+        for (AvatarRelation ar : relations) {
+            if (ar.containsSignal(_as)) {
+                int index = ar.hasSignal(_as);
+                return ar.getInSignal(index);
+            }
+        }
+        return null;
+    }
+
+    //DG
+    public boolean ASynchronousExist() {
+        List<AvatarRelation> asynchro = getRelations();
+
+        for (AvatarRelation ar : asynchro)
+            if (ar.isAsynchronous())
+                return true;
+
+        return false;
+    }
+
+    public boolean AMSExist() {
+        List<AvatarRelation> ams = getRelations();
+
+        for (AvatarRelation ar : ams)
+            if (ar.isAMS())
+                return true;
+
+        return false;
+    }
+
+    // end DG
+    public void addBlock(AvatarBlock _block) {
+        blocks.add(_block);
+    }
+
+    /*public void addBroadcastSignal(AvatarSignal _as) {
+      if (!broadcast.containsSignal(_as)) {
+      broadcast.addSignal(_as);
+      }
+      }
+
+      public AvatarBroadcast getBroadcast() {
+      return broadcast;
+      }*/
+
+    public void addInterface(AvatarAMSInterface _interface) {
+        interfaces.add(_interface);
+    }
+
+    public void addRelation(AvatarRelation _relation) {
+        relations.add(_relation);
+    }
+
+    public void addInterfaceRelation(AvatarInterfaceRelation _irelation) {
+        irelations.add(_irelation);
+    }
+
+    public void addPragma(AvatarPragma _pragma) {
+        pragmas.add(_pragma);
+    }
+
+    public void addSafetyPragma(String _pragma, String _refPragmas) {
+        safetyPragmas.add(_pragma);
+        safetyPragmasRefs.put(_pragma, _refPragmas);
+    }
+
+    public void addLatencyPragma(AvatarPragmaLatency _pragma) {
+        latencyPragmas.add(_pragma);
+    }
+
+    public void addConstant(AvatarConstant _constant) {
+        //Only add unique constants
+        if (this.getAvatarConstantWithName(_constant.getName()) == null) {
+            constants.add(_constant);
+        }
+    }
+
+    @Override
+    public String toString() {
+        //Thread.currentThread().dumpStack();
+        StringBuffer sb = new StringBuffer("Blocks:\n");
+        //TraceManager.addDev("TS Block");
+        for (AvatarBlock block : blocks) {
+            sb.append("*** " + block.toString() + "\n");
+        }
+        //TraceManager.addDev("TS Relations");
+        sb.append("\nRelations:\n");
+        for (AvatarRelation relation : relations) {
+            sb.append("Relation:" + relation.toString() + "\n");
+        }
+        sb.append("\nPragmas:\n");
+        for (AvatarPragma pragma : pragmas) {
+            sb.append("Pragma:" + pragma.toString() + "\n");
+        }
+        for (AvatarConstant constant : constants) {
+            sb.append("Constant:" + constant.toString() + "\n");
+        }
+
+        //TraceManager.addDev("TS All done");
+
+        return sb.toString();
+    }
+
+    public String toShortString() {
+        //TraceManager.addDev("To Short String");
+        //Thread.currentThread().dumpStack();
+        StringBuffer sb = new StringBuffer("Blocks:\n");
+        for (AvatarBlock block : blocks) {
+            sb.append("*** " + block.toShortString() + "\n");
+        }
+        sb.append("\nRelations:\n");
+        for (AvatarRelation relation : relations) {
+            sb.append("Relation:" + relation.toString() + "\n");
+        }
+        /*for (AvatarConstant constant: constants){
+            sb.append("Constant:" + constant.toString() + "\n");
+        }*/
+
+        return sb.toString();
+    }
+
+    public AvatarBlock getBlockWithName(String _name) {
+        for (AvatarBlock block : blocks) {
+            if (block.getName().compareTo(_name) == 0) {
+                return block;
+            }
+        }
+
+        return null;
+    }
+
+    public int getBlockIndex(AvatarBlock _block) {
+        int cpt = 0;
+        for (AvatarBlock block : blocks) {
+            if (block == _block) {
+                return cpt;
+            }
+            cpt++;
+        }
+
+        return -1;
+    }
+
+    public AvatarAMSInterface getAMSInterfaceWithName(String _name) {
+        for (AvatarAMSInterface interf : interfaces) {
+            if (interf.getName().compareTo(_name) == 0) {
+                return interf;
+            }
+        }
+
+        return null;
+    }
+
+    public AvatarConstant getAvatarConstantWithName(String _name) {
+        for (AvatarConstant constant : constants) {
+            if (constant.getName().compareTo(_name) == 0) {
+                return constant;
+            }
+        }
+
+        return null;
+    }
+
+    /* Generates the Expression Solvers, returns the AvatarStateMachineElement
+     * containing the errors */
+    public List<AvatarStateMachineElement> generateAllExpressionSolvers() {
+        List<AvatarStateMachineElement> errors = new ArrayList<>();
+        AvatarTransition at;
+        boolean returnVal;
+
+        AvatarExpressionSolver.emptyAttributesMap();
+
+        for (AvatarBlock block : getListOfBlocks()) {
+            AvatarStateMachine asm = block.getStateMachine();
+
+            for (AvatarStateMachineElement elt : asm.getListOfElements()) {
+                if (elt instanceof AvatarTransition) {
+                    at = (AvatarTransition) elt;
+                    if (at.isGuarded()) {
+                        returnVal = at.buildGuardSolver();
+                        if (returnVal == false) {
+                            errors.add(at);
+                        }
+                    }
+                    if (at.hasDelay()) {
+                        returnVal = at.buildDelaySolver();
+                        if (returnVal == false) {
+                            errors.add(at);
+                        }
+                    }
+                    for (AvatarAction aa : at.getActions()) {
+                        if (aa instanceof AvatarActionAssignment) {
+                            returnVal = ((AvatarActionAssignment) aa).buildActionSolver(block);
+                            if (returnVal == false) {
+                                errors.add(elt);
+                            }
+                        }
+                    }
+                } else if (elt instanceof AvatarActionOnSignal) {
+                    returnVal = ((AvatarActionOnSignal) elt).buildActionSolver(block);
+                    if (returnVal == false) {
+                        errors.add(elt);
+                    }
+                }
+            }
+        }
+
+        return errors;
+    }
+
+    public void removeCompositeStates() {
+        for (AvatarBlock block : blocks) {
+            //TraceManager.addDev("- - - - - - - - Removing composite states of " + block);
+            block.getStateMachine().removeCompositeStates(block);
+        }
+    }
+
+    public void makeFullStates() {
+        for (AvatarBlock block : blocks) {
+            block.getStateMachine().makeFullStates(block);
+        }
+    }
+
+    public void removeRandoms() {
+        for (AvatarBlock block : blocks) {
+            block.getStateMachine().removeRandoms(block);
+        }
+    }
+
+    public void removeAllDelays() {
+        for (AvatarBlock block : blocks) {
+            block.getStateMachine().removeAllDelays();
+        }
+    }
+
+    public void removeTimers() {
+        //renameTimers();
+
+        List<AvatarBlock> addedBlocks = new LinkedList<AvatarBlock>();
+        for (AvatarBlock block : blocks) {
+            if (block.hasTimerAttribute()) {
+                block.removeTimers(this, addedBlocks);
+            }
+        }
+
+        for (int i = 0; i < addedBlocks.size(); i++) {
+            addBlock(addedBlocks.get(i));
+        }
+    }
+
+    public void removeConstants() {
+        for (AvatarBlock block : blocks) {
+            block.removeConstantAttributes();
+        }
+    }
+
+    public void sortAttributes() {
+        for (AvatarBlock block : blocks) {
+            block.sortAttributes();
+        }
+    }
+
+//
+//    private void renameTimers() {
+//        // Check whether timers have the same name in different blocks
+//        ArrayList<AvatarAttribute> allTimers = new ArrayList<AvatarAttribute>();
+//        for(AvatarBlock block: blocks) {
+//            allTimers.clear();
+//            block.putAllTimers(allTimers);
+//            for(AvatarAttribute att: allTimers) {
+//                for(AvatarBlock bl: blocks) {
+//                    if (block != bl) {
+//                        if (bl.hasTimer(att.getName())) {
+//                            // Must change name of timer
+//                            TraceManager.addDev("Changing name of Timer:" + att);
+//                            att.setName(att.getName() + "__" + block.getName());
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//
+//    }
+
+    public void setAttributeOptRatio(int attributeOptRatio) {
+        for (AvatarBlock block : blocks) {
+            block.setAttributeOptRatio(attributeOptRatio);
+        }
+    }
+
+    /**
+     * Removes all FIFOs by replacing them with
+     * synchronous relations and one block per FIFO
+     * The size of the infinite fifo is max 1024
+     * and min 1
+     *
+     * @param _maxSizeOfInfiniteFifo : the max size of the infinite fifo
+     */
+    public void removeFIFOs(int _maxSizeOfInfiniteFifo) {
+        List<AvatarRelation> oldOnes = new LinkedList<AvatarRelation>();
+        List<AvatarRelation> newOnes = new LinkedList<AvatarRelation>();
+
+        int FIFO_ID = 0;
+        for (AvatarRelation ar : relations) {
+            if (ar.isAsynchronous()) {
+                // Must be removed
+                int size = Math.min(_maxSizeOfInfiniteFifo, ar.getSizeOfFIFO());
+                //TraceManager.addDev("***************************** Size of FIFO:" + size);
+                size = Math.max(1, size);
+                FIFO_ID = removeFIFO(ar, size, oldOnes, newOnes, FIFO_ID);
+            }
+        }
+
+        for (AvatarRelation ar : oldOnes) {
+            relations.remove(ar);
+        }
+
+        for (AvatarRelation ar : newOnes) {
+            relations.add(ar);
+        }
+
+    }
+
+    private int removeFIFO(AvatarRelation _ar, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes, List<AvatarRelation> _newOnes, int FIFO_ID) {
+        for (int i = 0; i < _ar.nbOfSignals(); i++) {
+            //TraceManager.addDev("FIFO for AR: " + _ar.getBlock1().getName() + " --> " + _ar.getBlock2().getName());
+            if (_ar.getSignal1(i).isIn()) {
+                FIFO_ID = removeFIFO(_ar, _ar.getSignal2(i), _ar.getSignal1(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block2,
+                        _ar.block1);
+            } else {
+                FIFO_ID = removeFIFO(_ar, _ar.getSignal1(i), _ar.getSignal2(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block1,
+                        _ar.block2);
+            }
+        }
+        _oldOnes.add(_ar);
+        return FIFO_ID;
+    }
+
+    private int removeFIFO(AvatarRelation _ar, AvatarSignal _sig1, AvatarSignal _sig2, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes,
+                           List<AvatarRelation> _newOnes, int FIFO_ID, AvatarBlock block1, AvatarBlock block2) {
+        // We create the new block, and the new relation towards the new block
+        String nameOfBlock = "FIFO_" + _sig1.getName() + "_" + _sig2.getName() + "_" + FIFO_ID;
+        AvatarBlock fifoBlock = AvatarBlockTemplate.getFifoBlock(nameOfBlock, this, _ar, _ar.getReferenceObject(), _sig1, _sig2,
+                _sizeOfInfiniteFifo, FIFO_ID);
+        //fifoBlock.getStateMachine().groupUselessTransitions(fifoBlock);
+        blocks.add(fifoBlock);
+
+        // We now need to create the new relation
+        AvatarRelation newAR1 = new AvatarRelation("FIFO_write_" + FIFO_ID, block1, fifoBlock, _ar.getReferenceObject());
+        newAR1.setAsynchronous(false);
+        newAR1.setPrivate(_ar.isPrivate());
+        //TraceManager.addDev("FIFO. Connecting " + _sig1.getName() + " to write of FIFO " + fifoBlock.getName());
+        newAR1.addSignals(_sig1, fifoBlock.getSignalByName("write"));
+        _newOnes.add(newAR1);
+
+        AvatarRelation newAR2 = new AvatarRelation("FIFO_read_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject());
+        newAR2.setAsynchronous(false);
+        newAR2.setPrivate(_ar.isPrivate());
+        //TraceManager.addDev("FIFO. Connecting FIFO " + fifoBlock.getName() + " read to " + _sig2.getName());
+        newAR2.addSignals(fifoBlock.getSignalByName("read"), _sig2);
+        _newOnes.add(newAR2);
+
+        // We also add the query signals to the newAR2 relation
+
+
+        AvatarSignal queryS = new AvatarSignal("query_FIFO_read_" + FIFO_ID, AvatarSignal.IN, _sig2.getReferenceObject());
+        block2.addSignal(queryS);
+        AvatarAttribute queryA = new AvatarAttribute("queryA", AvatarType.INTEGER, null, _sig2.getReferenceObject());
+        queryS.addParameter(queryA);
+
+        AvatarRelation newAR3 = new AvatarRelation("FIFO_query_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject());
+        newAR3.setAsynchronous(false);
+        newAR3.setPrivate(_ar.isPrivate());
+        newAR3.addSignals(fifoBlock.getSignalByName("query"), queryS);
+        _newOnes.add(newAR3);
+
+        // Replace query in block2 for _sig2 by readOnSignal with signal queryS. Use the same attribute as before
+        block2.replaceQueriesWithReadSignal(_sig2, queryS);
+
+
+        FIFO_ID++;
+
+        return FIFO_ID;
+    }
+
+    public boolean areSynchronized(AvatarSignal as1, AvatarSignal as2) {
+        AvatarRelation ar = getAvatarRelationWithSignal(as1);
+        if (ar == null) {
+            return false;
+        }
+
+        int index1 = ar.getIndexOfSignal(as1);
+        int index2 = ar.getIndexOfSignal(as2);
+
+        return (index1 == index2);
+    }
+
+    public AvatarRelation getAvatarRelationWithSignal(AvatarSignal _as) {
+        for (AvatarRelation ar : relations) {
+            if (ar.hasSignal(_as) > -1) {
+                return ar;
+            }
+        }
+        return null;
+    }
+
+    public AvatarStateMachineElement getStateMachineElementFromReferenceObject(Object _o) {
+        AvatarStateMachineElement asme;
+        for (AvatarBlock block : blocks) {
+            asme = block.getStateMachineElementFromReferenceObject(_o);
+            if (asme != null) {
+                return asme;
+            }
+        }
+        return null;
+    }
+
+    public AvatarBlock getBlockFromReferenceObject(Object _o) {
+        for (AvatarBlock block : blocks) {
+            if (block.containsStateMachineElementWithReferenceObject(_o)) {
+                return block;
+            }
+        }
+        return null;
+    }
+
+    public AvatarBlock getBlockWithAttribute(String _attributeName) {
+        int index;
+
+        for (AvatarBlock block : blocks) {
+            index = block.getIndexOfAvatarAttributeWithName(_attributeName);
+            if (index > -1) {
+                return block;
+            }
+        }
+        return null;
+    }
+
+    public void removeElseGuards() {
+        for (AvatarBlock block : blocks) {
+            removeElseGuards(block.getStateMachine());
+        }
+        for (AvatarLibraryFunction function : libraryFunctions) {
+            removeElseGuards(function.getStateMachine());
+        }
+    }
+
+    private void removeElseGuards(AvatarStateMachine asm) {
+        if (asm == null)
+            return;
+
+        for (AvatarStateMachineElement asme : asm.getListOfElements()) {
+            if (!(asme instanceof AvatarState))
+                continue;
+
+            //TraceManager.addDev("Working with state " + asme.getNiceName());
+            for (AvatarStateMachineElement next : asme.getNexts()) {
+                if (!(next instanceof AvatarTransition))
+                    continue;
+                AvatarTransition at = (AvatarTransition) next;
+                AvatarGuard ancientGuard = at.getGuard();
+
+                if (ancientGuard == null)
+                    continue;
+
+                //TraceManager.addDev("[[[[[[[[[[[[[[[ Guard before: " + ancientGuard.toString() + " type:" + ancientGuard.getClass().toString());
+                at.setGuard(ancientGuard.getRealGuard(asme));
+                //TraceManager.addDev("]]]]]]]]]]]]]]] Guard after: " + at.getGuard().toString());
+            }
+        }
+    }
+
+    /**
+     * Removes all function calls by inlining them.
+     */
+    public void removeLibraryFunctionCalls() {
+        for (AvatarBlock block : this.blocks) {
+            AvatarStateMachine asm = block.getStateMachine();
+            if (asm == null)
+                continue;
+
+            asm.removeLibraryFunctionCalls(block);
+        }
+
+
+        //TraceManager.addDev("\n\nNew spec:" + this.toString() + "\n");
+    }
+
+    public boolean hasLossyChannel() {
+        for (AvatarRelation relation : relations)
+            if (relation.isLossy())
+                return true;
+
+        return false;
+    }
+
+    public void removeEmptyTransitions(boolean _canOptimize) {
+        for (AvatarBlock block : this.blocks) {
+            AvatarStateMachine asm = block.getStateMachine();
+            if (asm != null)
+                asm.removeEmptyTransitions(block, _canOptimize);
+        }
+    }
+
+    public void groupUselessTransitions() {
+        for (AvatarBlock block : this.blocks) {
+            AvatarStateMachine asm = block.getStateMachine();
+            if (asm != null)
+                asm.groupUselessTransitions(block);
+        }
+    }
+
+    public void makeRobustness() {
+        //TraceManager.addDev("Make robustness");
+        if (robustnessMade) {
+            return;
+        }
+
+        /*robustnessMade = true;
+
+          TraceManager.addDev("Testing lossy channels");
+
+          if (hasLossyChannel()) {
+          TraceManager.addDev("Making robustness");
+          int idstate = 0;
+          for(AvatarBlock block: blocks) {
+          idstate = block.getStateMachine().makeMessageLostRobustness(idstate);
+          }
+
+          /*AvatarBlock ab = new AvatarBlock("Robustness__", this.getReferenceObject());
+          addBlock(ab);
+          AvatarMethod am = new AvatarMethod("messageLost", null);
+          ab.addMethod(am);
+          AvatarStateMachine asm = ab.getStateMachine();
+          AvatarStartState ass = new AvatarStartState("StartState", null);
+          asm.addElement(ass);
+          asm.setStartState(ass);
+          AvatarTransition at = new AvatarTransition("Transition", null);
+          asm.addElement(at);
+          ass.addNext(at);
+          AvatarState state = new AvatarState("MainState", null);
+          asm.addElement(state);
+          at.addNext(state);
+
+          // Parsing all state machines to add robustness
+          AvatarStateMachine sm;
+          AvatarActionOnSignal aaos;
+          AvatarSignal as;
+          AvatarState state0;
+          int i;
+
+          for(AvatarRelation ar: relations) {
+          if (ar.isAsynchronous() && ar.isLossy()) {
+          // Modify the relation
+          ar.makeRobustness();
+          for(i=0; i<ar.nbOfSignals(); i = i+2) {
+          as = ar.getInSignal(i);
+          at = new AvatarTransition("TransitionToReceiving", null);
+          asm.addElement(at);
+          state.addNext(at);
+          aaos = new AvatarActionOnSignal("Receiving__" + as.getName(), as, null);
+          asm.addElement(aaos);
+          at.addNext(aaos);
+          at = new AvatarTransition("TransitionToIntermediateState", null);
+          asm.addElement(at);
+          state0 = new AvatarState("Choice__" + as.getName(), null);
+          asm.addElement(state0);
+          aaos.addNext(at);
+          at.addNext(state0);
+          at = new AvatarTransition("TransitionToMainState", null);
+          at.addAction("messageLost()");
+          asm.addElement(at);
+          state0.addNext(at);
+          at.addNext(state);
+
+          as = ar.getOutSignal(i+1);
+          at = new AvatarTransition("TransitionToSending", null);
+          asm.addElement(at);
+          aaos = new AvatarActionOnSignal("Sending__" + as.getName(), as, null);
+          asm.addElement(aaos);
+          state0.addNext(at);
+          at.addNext(aaos);
+          at = new AvatarTransition("TransitionAfterSending", null);
+          asm.addElement(at);
+          aaos.addNext(at);
+          at.addNext(state);
+          }
 
-        int indexStart = _spec.indexOf('{');
-        int indexStop = _spec.lastIndexOf('}');
+          }
+          }
+          }*/
+    }
 
-        if ((indexStart == -1) || (indexStop == -1) || (indexStart > indexStop)) {
-            throw new org.json.JSONException("Invalid JSON object");
+    public AvatarSpecification advancedClone() {
+        AvatarSpecification spec = new AvatarSpecification(this.getName(), this.getReferenceObject());
+        Map<AvatarBlock, AvatarBlock> correspondenceBlocks = new HashMap<AvatarBlock, AvatarBlock>();
+
+        // Cloning block definition
+        for (AvatarBlock block : blocks) {
+            AvatarBlock nB = block.advancedClone(spec);
+            correspondenceBlocks.put(block, nB);
+            spec.addBlock(nB);
         }
 
-        _spec = _spec.substring(indexStart, indexStop+1);
+        // Handling the clone of fathers
+        for (AvatarBlock block : blocks) {
+            AvatarBlock father = block.getFather();
+            if (father != null) {
+                AvatarBlock nb = spec.getBlockWithName(block.getName());
+                if (nb != null) {
+                    AvatarBlock nf = spec.getBlockWithName(father.getName());
+                    if (nf != null) {
+                        //TraceManager.addDev("Setting "+ nf.getName() + " as the father of " + nb.getName());
+                        nb.setFather(nf);
+                    }
+                }
+            }
+        }
 
-        TraceManager.addDev("Cut spec: " + _spec);
+        // Cloning asm
+        for (AvatarBlock block : blocks) {
+            AvatarBlock nb = spec.getBlockWithName(block.getName());
+            block.getStateMachine().advancedClone(nb.getStateMachine(), nb);
+        }
 
-        JSONObject mainObject = new JSONObject(_spec);
+        // Relations
+        for (AvatarRelation relation : relations) {
+            AvatarRelation nR = relation.advancedClone(correspondenceBlocks);
+            if (nR != null) {
+                spec.addRelation(nR);
+            }
+        }
 
-        JSONArray blocksA = mainObject.getJSONArray("blocks");
+		/*for(AvatarPragma pragma: pragmas) {
+		    AvatarPragma nP = pragma.advancedClone();
+		    spec.addPragma(nP);
+		    }*/
 
-        if (blocksA == null) {
-            TraceManager.addDev("No blocks in json");
-            return spec;
+        for (String safetyPragma : safetyPragmas) {
+            spec.addSafetyPragma(safetyPragma, safetyPragmasRefs.get(safetyPragma));
         }
 
-        for (int i=0; i<blocksA.length(); i++) {
-            JSONObject blockO = blocksA.getJSONObject(i);
-            String name = blockO.getString("name");
-            if (name != null) {
-                AvatarBlock newBlock = new AvatarBlock(name, spec, _referenceObject);
-                spec.addBlock(newBlock);
+        for (AvatarPragmaLatency latencyPragma : latencyPragmas) {
+            spec.addLatencyPragma(latencyPragma);
+        }
+
+        for (AvatarConstant constant : constants) {
+            AvatarConstant cN = constant.advancedClone();
+            spec.addConstant(cN);
+        }
+        for (String id : checkedIDs) {
+            spec.checkedIDs.add(id);
+        }
 
-                JSONArray attributesA = blockO.getJSONArray("attributes");
+        spec.setInformationSource(getInformationSource());
+        spec.addApplicationCode(getApplicationCode());
 
-                for (int j=0; j<attributesA.length(); j++) {
-                    String nameA = attributesA.getJSONObject(j).getString("name");
-                    String typeA = attributesA.getJSONObject(j).getString("type");
-                    AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject);
-                    newBlock.addAttribute(aa);
-                }
+        return spec;
+    }
 
-                JSONArray methodsA = blockO.getJSONArray("methods");
-                for (int j=0; j<methodsA.length(); j++) {
-                    String nameM = methodsA.getJSONObject(j).getString("name");
-                    AvatarMethod am = new AvatarMethod(nameM, _referenceObject);
-                    JSONArray params = methodsA.getJSONObject(j).getJSONArray("paremeters");
-                    for(int k=0; k<params.length(); k++) {
-                        String nameA = params.getJSONObject(k).getString("name");
-                        String typeA = params.getJSONObject(k).getString("type");
-                        AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject);
-                        am.addParameter(aa);
-                    }
-                    String returnT = methodsA.getJSONObject(j).getString("returnType");
-                    AvatarType at = AvatarType.getType(returnT);
-                    if (at != AvatarType.UNDEFINED) {
-                        am.addReturnParameter(new AvatarAttribute("returnType", at, newBlock, _referenceObject));
+    public AvatarAttribute getMatchingAttribute(AvatarAttribute aa) {
+        for (AvatarBlock block : this.blocks) {
+            if (block.getName().compareTo(aa.getBlock().getName()) == 0) {
+                return block.getAvatarAttributeWithName(aa.getName());
+            }
+        }
+
+        return null;
+    }
+
+    public AvatarDependencyGraph makeDependencyGraph() {
+        return makeDependencyGraph(true);
+    }
+
+    public AvatarDependencyGraph makeDependencyGraph(boolean withID) {
+        AvatarDependencyGraph adg = new AvatarDependencyGraph();
+        adg.buildGraph(this, withID);
+        return adg;
+    }
+
+    public AvatarSpecification simplifyFromDependencies(ArrayList<AvatarElement> eltsOfInterest) {
+        AvatarSpecification clonedSpec = advancedClone();
+        AvatarDependencyGraph adg = clonedSpec.makeDependencyGraph();
+        AvatarDependencyGraph reducedGraph = adg.reduceGraphBefore(eltsOfInterest);
+        clonedSpec.reduceFromDependencyGraph(reducedGraph);
+        return clonedSpec;
+    }
+
+    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);
+            }
+        }
+
+    }
 
-                    newBlock.addMethod(am);
+    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);
                 }
+            }
+        }
 
+        // If a block has a father in toBeRemoved, then keep the father, and the father of the father, etc.
+        for (AvatarBlock block : blocks) {
+            AvatarBlock bl = block.getFather();
+            while (bl != null) {
+                if (toBeRemoved.contains(bl)) {
+                    toBeRemoved.remove(bl);
+                }
+                bl = bl.getFather();
             }
         }
 
-        return spec;
 
+        blocks.removeAll(toBeRemoved);
+    }
+
+    /**
+     * Removes attributes that are not used
+     */
+    public void removeUselessAttributes() {
+        ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>();
+        for (AvatarBlock block : blocks) {
+            block.removeUselessAttributes();
+        }
+    }
+
+    // TO BE COMPLETED
+    // We assume the graph has been reduced already to what is necessary:
+    // We now need to reduce the avatarspec accordingly
+    public void reduceFromDependencyGraph(AvatarDependencyGraph _adg) {
+
+        // We have to update the state machines according to the graph
+        for (AvatarBlock block : blocks) {
+            //TraceManager.addDev("Handling block " + block.getName());
+            AvatarStateMachine asm = block.getStateMachine();
+            // We first check if the start is still in the graph
+            // If not, the state machine is empty: we just create a stop, and that's it
+            AvatarStartState ass = asm.getStartState();
+            if (_adg.getFirstStateWithReference(ass) == null) {
+                TraceManager.addDev("No start state in " + block.getName());
+                asm.makeBasicSM(block);
+                block.clearAttributes();
+            } else {
+
+                // Otherwise we keep the start and consider all other elements
+                // We remove all elements with no correspondence in the graph
+                // Then, we redo a valid ASM i.e. all elements with no nexts (apart from states)
+                // are given a stop state after
+
+                TraceManager.addDev("Reducing state machine of " + block.getName());
+
+                ArrayList<AvatarElement> toRemove = new ArrayList<>();
+                for (AvatarStateMachineElement asme : asm.getListOfElements()) {
+                    if (_adg.getFirstStateWithReference(asme) == null) {
+                        boolean toBeRemoved = false;
+                        if (asme instanceof AvatarTransition) {
+                            if (!((AvatarTransition) asme).isEmpty()) {
+                                toBeRemoved = true;
+                            }
+                        } else {
+                            toBeRemoved = true;
+                        }
+
+                        if (toBeRemoved)
+                            toRemove.add(asme);
+
+                    }
+
+                }
+                TraceManager.addDev("To remove size: " + toRemove.size() + " size of ASM: " + asm.getListOfElements().size());
+                asm.getListOfElements().removeAll(toRemove);
+                TraceManager.addDev("Removed. New size of ASM: " + asm.getListOfElements().size());
+                asm.makeCorrect(block);
+            }
+        }
+
+
+        // Then we can remove useless attributes i.e attributes that are not used
+
+
+        removeUselessSignalAssociations();
+
+        removeUselessAttributes();
+
+        removeEmptyBlocks();
+
+    }
+
+    public NameChecker.NamedElement[] getSubNamedElements() {
+        NameChecker.NamedElement[] lne = new NameChecker.NamedElement[blocks.size()];
+        int index = 0;
+        for (AvatarBlock bl : blocks) {
+            lne[index] = bl;
+            index++;
+        }
+        return lne;
     }
 
 }
diff --git a/src/main/java/ui/util/IconManager.java b/src/main/java/ui/util/IconManager.java
index 95ee2562bfb2a095719437cea1c9f0575f684937..f35f5964c736c58159abb692a8689cfd1adb3359 100755
--- a/src/main/java/ui/util/IconManager.java
+++ b/src/main/java/ui/util/IconManager.java
@@ -42,6 +42,11 @@ package ui.util;
 import javax.swing.*;
 import java.awt.*;
 import java.net.URL;
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import javax.swing.ImageIcon;
 
 
 /**
@@ -1329,4 +1334,24 @@ public class IconManager {
         imgic8030 = getIcon(icon8030);
     }
 
+
+
+    public static ImageIcon rotateImageIcon(ImageIcon icon, double degrees) {
+        int w = icon.getIconWidth();
+        int h = icon.getIconHeight();
+        int type = BufferedImage.TYPE_INT_ARGB;  // Other options
+        BufferedImage image = new BufferedImage(h, w, type);
+        Graphics2D g2 = image.createGraphics();
+        double x = (h - w)/2.0;
+        double y = (h - w)/2.0;
+        AffineTransform at = AffineTransform.getTranslateInstance(x, y);
+        at.rotate(Math.toRadians(degrees), w/2.0, h/2.0);
+        g2.setBackground(Color.white);
+        g2.drawImage(icon.getImage(), at, null);
+        g2.dispose();
+        icon = new ImageIcon(image);
+        return icon;
+    }
+
+
 } // Class
diff --git a/src/main/java/ui/window/JFrameAI.java b/src/main/java/ui/window/JFrameAI.java
index f6523ccb96ae532cda4f2a6b83737782654b5416..8459cfca2f223e0fe40755563141eaa3de451b6f 100644
--- a/src/main/java/ui/window/JFrameAI.java
+++ b/src/main/java/ui/window/JFrameAI.java
@@ -62,6 +62,7 @@ import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;
+import java.util.HashMap;
 
 
 /**
@@ -102,13 +103,13 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable {
     private String KNOWLEDGE_ON_JSON_FOR_BLOCKS = "JSON for block diagram is as follows: " +
             "{blocks: [{ \"name\": \"Name of block\", \"attributes\": [\"name\": \"name of attribute\", \"type\": \"int or boolean\" ...}" + " same" +
             "(with its parameters : int, boolean ; and its return type : nothing, int or boolean)" +
-            "and signals (with its list of parameters : int or boolean ; and each signal is either an output signal or an input signal), ..." +
+            "and signals (with its list of parameters : int or boolean, and a type (input, output)" +
             " then the list of connections between block signals: \"connections\": [\n" +"{\n" + " \"sourceBlock\": \"name of block\",\n" +
             " \"sourceSignal\": \"name of output signal\",\n" +
             " \"destinationBlock\": \"name of destination block\",\n" +
             " \"destinationSignal\": \"rechargeBattery\",\n" +
             " \"communicationType\": \"synchronous (or asynchronous)\"\n" +
-            "},";
+            "}. A connection must connect one output signal of a block to one input signal of a block";
 
     private String QUESTION_IDENTIFY_SYSTEM_BLOCKS = "From the following system specification, using the specified JSON format, identify the " +
             "typical system blocks. All this in JSON.\n";
@@ -133,7 +134,9 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable {
 
     private boolean go = false;
 
-    private class ChatData {
+    private HashMap<Integer, ImageIcon> rotatedI = new HashMap<>();
+
+    private class ChatData implements Runnable {
         public AIInterface aiinterface;
         public boolean knowledgeOnProperties = false;
         public boolean knowledgeOnBlockJSON = false;
@@ -141,6 +144,9 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable {
         public String lastAnswer = "";
         public int previousKind;
         public TDiagramPanel tdp;
+        public boolean doIconRotation = false;
+        private Thread t;
+
 
         public ChatData() {}
 
@@ -148,8 +154,49 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable {
             lastAnswer = "";
             answer.setText("");
         }
+
+        public void startAnimation() {
+            doIconRotation = true;
+            t = new Thread(this);
+            t.start();
+        }
+
+        public void stopAnimation() {
+            doIconRotation = false;
+            if (t != null) {
+                t.interrupt();
+            }
+            t = null;
+        }
+
+
+        public void run() {
+            int angle = 0;
+
+            while( doIconRotation ) {
+                angle = (angle - 15) % 360;
+                ImageIcon rotated = rotatedI.get(angle);
+                if ( rotated == null ) {
+                    rotated = IconManager.rotateImageIcon(IconManager.imgic154, angle);
+                    rotatedI.put(angle, rotated);
+                }
+
+                setIcon(this, rotated);
+                try {
+                    Thread.currentThread().sleep(100);
+                } catch (Exception e) {
+                    TraceManager.addDev("Interrupted");
+                    doIconRotation = false;
+                };
+            }
+            setIcon(this, IconManager.imgic154);
+        }
     }
 
+    public void setIcon(ChatData _data, Icon newIcon) {
+        int index = chats.indexOf(_data);
+        answerPane.setIconAt(index, newIcon);
+    }
 
     private JButton buttonClose, buttonStart, buttonApplyResponse;
 
@@ -325,6 +372,9 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable {
 
 
     private void close() {
+        for(ChatData data: chats) {
+            data.stopAnimation();
+        }
         dispose();
     }
 
@@ -480,6 +530,8 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable {
     }
 
     public void run() {
+        ChatData selected = selectedChat();
+        selected.startAnimation();
         go = true;
         enableDisableActions();
 
@@ -506,6 +558,7 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable {
         }
 
         go = false;
+        selected.stopAnimation();
         enableDisableActions();
     }