diff --git a/src/Checker/Mage.py b/src/Checker/Mage.py
new file mode 100644
index 0000000000000000000000000000000000000000..224253dfc57a0ba94df2fd585b1eef24836b7f12
--- /dev/null
+++ b/src/Checker/Mage.py
@@ -0,0 +1,198 @@
+# -*- coding: utf-8 -*-
+
+import time
+
+from queue import Queue
+from tools import flatten
+from functools import reduce
+
+from PyQt5.QtCore import QCoreApplication
+
+from Checker.Checker import AbstractModelChecker, STATUS
+
+_translate = QCoreApplication.translate
+
+class MageNetworkGraphChecker(AbstractModelChecker):
+    def __init__(self, connectivity = True):
+        super(MageNetworkGraphChecker, self).__init__()
+
+        self._mode_conn = connectivity
+
+        if connectivity:
+            mode = "connectivity"
+        else:
+            mode = "cycle"
+
+        self._name = _translate("Checker", f"Mage network graph {mode} checker")
+        self._description = _translate("Checker", "Check if the network graph is valid")
+
+    def _connectivity(self, summary, status, graph):
+        # Keep only enabled edges
+        edges = list(
+            filter(
+                lambda e: e.is_enable(),
+                graph.edges()
+            )
+        )
+        # Get all related nodes
+        nodes = list(
+            set(
+                flatten(
+                    map(
+                        lambda e: [e.node1, e.node2],
+                        edges
+                    )
+                )
+            )
+        )
+
+        # Visite graph
+        q = Queue()
+        for node in nodes:
+            if graph.is_upstream_node(node):
+                q.put(node)
+                break           # We take only one node
+
+        if q.qsize() == 0:
+            summary = "no_upstream_node"
+            status = STATUS.ERROR
+            return summary, status
+
+        visited = set()
+        while q.qsize() != 0:
+            current = q.get()
+            if current is None:
+                continue
+
+            if current in visited:
+                continue
+
+            related_edges = list(
+                filter(
+                    lambda e: e.node1 == current or e.node2 == current,
+                    edges
+                )
+            )
+
+            # Get next node(s) to visite
+            nexts = flatten(
+                map(
+                    lambda e: [e.node1, e.node2],
+                    related_edges
+                )
+            )
+
+            for n in nexts:
+                q.put(n)
+
+            # Visited node
+            visited.add(current)
+
+        if len(visited) != len(nodes):
+            if "ok" in summary:
+                summary = "network_connectivity"
+            else:
+                summary = summary + "|" + "network_connectivity"
+            status = STATUS.ERROR
+            return summary, status
+
+        return summary, status
+
+    def _cycle(self, summary, status, graph):
+        # Keep only enabled edges
+        edges = list(
+            filter(
+                lambda e: e.is_enable(),
+                graph.edges()
+            )
+        )
+        # Get all related nodes
+        nodes = list(
+            set(
+                flatten(
+                    map(
+                        lambda e: [e.node1, e.node2],
+                        edges
+                    )
+                )
+            )
+        )
+
+
+        for edge in edges:
+            # Visite graph
+            q = Queue()
+            initial = edge.node1
+            q.put(initial)
+
+            visited = set()
+            while q.qsize() != 0:
+                current = q.get()
+                if current is None:
+                    continue
+
+                if current in visited:
+                    continue
+
+                related_edges = list(
+                    filter(
+                        lambda e: e.node1 == current,
+                        edges
+                    )
+                )
+
+                # Get next node(s) to visite
+                nexts = list(
+                    map(
+                        lambda e: e.node2,
+                        related_edges
+                    )
+                )
+
+                # The initial node cannot be visited a second time where visite
+                # started by this node, otherelse there is a cycle in the graph
+                if initial in nexts:
+                    if "ok" in summary:
+                        summary = "cycle_detected"
+                    else:
+                        summary = summary + "|" + "cycle_detected"
+                    status = STATUS.ERROR
+                    return summary, status
+
+                for n in nexts:
+                    q.put(n)
+
+                # Visited node
+                visited.add(current)
+
+        return summary, status
+
+    def run(self, study):
+        summary = "ok"
+        status = STATUS.OK
+
+        if study is None:
+            self._status = STATUS.ERROR
+            self._summary = "invalid_study"
+            return False
+
+        river = study.river
+        if river is None:
+            self._status = STATUS.ERROR
+            self._summary = "no_river_found"
+            return False
+
+        edges = list(filter(lambda e: e.is_enable(), river.edges()))
+        if len(edges) == 0:
+            self._status = STATUS.ERROR
+            self._summary = "no_reach_defined"
+            return False
+
+        if self._mode_conn:
+            summary, status = self._connectivity(summary, status, river)
+        else:
+            summary, status = self._cycle(summary, status, river)
+
+        self._summary = summary
+        self._status = status
+        return True
diff --git a/src/Solver/ASolver.py b/src/Solver/ASolver.py
index 7cef9f6a63287670f654fa7f2634f32d2068602e..ad7302bb03c0e544233162d072af70f3d782a19f 100644
--- a/src/Solver/ASolver.py
+++ b/src/Solver/ASolver.py
@@ -52,7 +52,7 @@ class AbstractSolver(object):
     @classmethod
     def default_parameters(cls):
         lst = [
-            ("all_init_time", "00:00:00:00"),
+            ("all_init_time", "000:00:00:00"),
             ("all_final_time", "999:99:00:00"),
             ("all_timestep", "300.0"),
         ]
@@ -122,6 +122,17 @@ class AbstractSolver(object):
     def export(self, study, repertory, qlog = None):
         raise NotImplementedMethodeError(self, self.export)
 
+    def input_param(self):
+        """Return input command line parameter(s)
+
+        Args:
+            study: The study object
+
+        Returns:
+            Returns input parameter(s) string
+        """
+        raise NotImplementedMethodeError(self, self.input_param)
+
     #######
     # Run #
     #######
@@ -137,8 +148,10 @@ class AbstractSolver(object):
             return True
 
         cmd = self._cmd_solver
-        cmd = cmd.replace("@path", self._path_solver).split()
+        cmd = cmd.replace("@path", self._path_solver)
+        cmd = cmd.replace("@input", self.input_param())
 
+        cmd = cmd.split()
         exe = cmd[0]
         args = cmd[1:]
 
diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py
index 8e81e6ced7f460d0480c8c7976bee8f2e4b3b8b6..54a0eb25d64b9cdee5225ec9381f69a1899994c6 100644
--- a/src/Solver/Mage.py
+++ b/src/Solver/Mage.py
@@ -5,6 +5,7 @@ import os
 from tools import timer
 
 from Solver.ASolver import AbstractSolver
+from Checker.Mage import MageNetworkGraphChecker
 
 class Mage(AbstractSolver):
     def __init__(self, name):
@@ -49,10 +50,22 @@ class Mage(AbstractSolver):
 
         return lst
 
+    @classmethod
+    def checkers(cls):
+        lst = [
+            MageNetworkGraphChecker(connectivity = True),
+            MageNetworkGraphChecker(connectivity = False)
+        ]
+
+        return lst
+
     ##########
     # Export #
     ##########
 
+    def input_param(self):
+        return "0.REP"
+
     @timer
     def _export_ST(self, study, repertory, qlog):
         files = []