diff --git a/src/gboml/ast/__init__.py b/src/gboml/ast/__init__.py
index 391efbe5008caf59b7dc24f69331167a83379460..be4da11911fda64d808d7a09d793473f7633fa02 100644
--- a/src/gboml/ast/__init__.py
+++ b/src/gboml/ast/__init__.py
@@ -7,7 +7,8 @@ __all__ = [
     "HyperEdge", "NodeDefinition", "NodeImport", "HyperEdgeDefinition", "HyperEdgeImport",
     "ExpressionOp", "GBOMLGraph", "ImplicitLoop", "RValue", "RValueWithGen", "GeneratedRValue",
     "Range", "MultiLoop", "DictEntry", "Dictionary", "NodeGenerator", "HyperEdgeGenerator",
-    "DefinitionType", "FunctionDefinition", "ConstantDefinition", "ExpressionDefinition"
+    "DefinitionType", "FunctionDefinition", "ConstantDefinition", "ExpressionDefinition",
+    "CtrActivation", "ObjActivation", "ActivationType", "Activation"
 ]
 
 from gboml.ast.arrays import *
@@ -25,3 +26,4 @@ from gboml.ast.objectives import *
 from gboml.ast.path import *
 from gboml.ast.rvalue import *
 from gboml.ast.variables import *
+from gboml.ast.activation import *
\ No newline at end of file
diff --git a/src/gboml/ast/activation.py b/src/gboml/ast/activation.py
new file mode 100644
index 0000000000000000000000000000000000000000..690b1fd07a1d6f6def84a2daadfc5b8115fa082e
--- /dev/null
+++ b/src/gboml/ast/activation.py
@@ -0,0 +1,18 @@
+from dataclasses import dataclass
+from enum import Enum
+from typing import Optional
+
+from gboml.ast.base import GBOMLObject
+from gboml.ast.expressions import BoolExpression
+
+
+class ActivationType(Enum):
+    activate = "activate"
+    deactivate = "deactivate"
+
+
+@dataclass
+class Activation(GBOMLObject):
+    type: ActivationType
+    what: list[str]
+    condition: Optional[BoolExpression]
\ No newline at end of file
diff --git a/src/gboml/ast/constraints.py b/src/gboml/ast/constraints.py
index 17cc19c3dcb86f79e019099f6a412ca7fdf796ae..42038b5e90c4a36d28a0acd32294766762745a02 100644
--- a/src/gboml/ast/constraints.py
+++ b/src/gboml/ast/constraints.py
@@ -2,6 +2,7 @@ from dataclasses import dataclass, field
 from enum import Enum
 from typing import Optional
 
+from gboml.ast.activation import Activation
 from gboml.ast.arrays import Array
 from gboml.ast.base import GBOMLObject
 from gboml.ast.expression_operators import Operator
@@ -34,3 +35,8 @@ class SOSConstraint(Constraint):
     content: Array
     loop: Optional[Loop] = None
     tags: list[str] = field(default_factory=list)
+
+
+@dataclass
+class CtrActivation(Activation):
+    pass
diff --git a/src/gboml/ast/hyperedges.py b/src/gboml/ast/hyperedges.py
index ddd209717cd161e25007ee77f7956a84e4993978..f6fdeb73e2f0a0d930890590925e8ee552edc3f2 100644
--- a/src/gboml/ast/hyperedges.py
+++ b/src/gboml/ast/hyperedges.py
@@ -2,7 +2,7 @@ from dataclasses import dataclass, field
 
 from gboml.ast import Loop
 from gboml.ast.base import GBOMLObject
-from gboml.ast.constraints import Constraint
+from gboml.ast.constraints import Constraint, CtrActivation
 from gboml.ast.path import VarOrParam
 from gboml.ast.variables import Definition
 
@@ -17,6 +17,7 @@ class HyperEdgeDefinition(HyperEdge):
     name: str
     parameters: list[Definition] = field(default_factory=list)
     constraints: list[Constraint] = field(default_factory=list)
+    activations: list[CtrActivation] = field(default_factory=list)
     tags: list[str] = field(default_factory=list)
 
 
@@ -26,6 +27,7 @@ class HyperEdgeGenerator(HyperEdge):
     loop: Loop
     parameters: list[Definition] = field(default_factory=list)
     constraints: list[Constraint] = field(default_factory=list)
+    activations: list[CtrActivation] = field(default_factory=list)
     tags: list[str] = field(default_factory=list)
 
 
diff --git a/src/gboml/ast/nodes.py b/src/gboml/ast/nodes.py
index 2b452b35e05bfcd596b562cd5a1cfa4cfb3427f8..25dbef1db3652c7532e3317a8af6a66db77e8696 100644
--- a/src/gboml/ast/nodes.py
+++ b/src/gboml/ast/nodes.py
@@ -1,6 +1,6 @@
 from dataclasses import dataclass, field
 
-from gboml.ast import Loop
+from gboml.ast import Loop, Activation
 from gboml.ast.base import GBOMLObject
 from gboml.ast.constraints import Constraint
 from gboml.ast.path import VarOrParam
@@ -23,6 +23,7 @@ class NodeDefinition(Node):
     variables: list[VariableDefinition] = field(default_factory=list)
     constraints: list[Constraint] = field(default_factory=list)
     objectives: list[Objective] = field(default_factory=list)
+    activations: list[Activation] = field(default_factory=list)
     tags: list[str] = field(default_factory=list)
 
 
@@ -36,6 +37,7 @@ class NodeGenerator(Node):
     variables: list[VariableDefinition] = field(default_factory=list)
     constraints: list[Constraint] = field(default_factory=list)
     objectives: list[Objective] = field(default_factory=list)
+    activations: list[Activation] = field(default_factory=list)
     tags: list[str] = field(default_factory=list)
 
 
diff --git a/src/gboml/ast/objectives.py b/src/gboml/ast/objectives.py
index c78f5ee12b61262b3a07c66debb4b062a74fd2da..458decd69b57f60ced67a9b0dc3e29e6eadcb957 100644
--- a/src/gboml/ast/objectives.py
+++ b/src/gboml/ast/objectives.py
@@ -2,6 +2,7 @@ from dataclasses import dataclass, field
 from enum import Enum
 from typing import Optional
 
+from gboml.ast.activation import Activation
 from gboml.ast.base import GBOMLObject
 from gboml.ast.expressions import Expression
 from gboml.ast.loops import Loop
@@ -19,3 +20,7 @@ class Objective(GBOMLObject):
     expression: Expression
     loop: Optional[Loop] = None
     tags: list[str] = field(default_factory=list)
+
+@dataclass
+class ObjActivation(Activation):
+    pass
\ No newline at end of file
diff --git a/src/gboml/gboml.lark b/src/gboml/gboml.lark
index d37f0e6a95e461ac178ccb12ee13c0b0913ca52a..361c1f10609b23dce6ac0f4d2aa32998321587cc 100644
--- a/src/gboml/gboml.lark
+++ b/src/gboml/gboml.lark
@@ -40,8 +40,10 @@ _node_content: parameters_block program_block variables_block constraints_block
 parameters_block: (_block_repeat_or_pass{_opt_param_header,definition})?
 _opt_param_header: "#PARAMETERS"?
 variables_block: _block_repeat_or_pass{"#VARIABLES",variable_definition}
-constraints_block: (_block_repeat_or_pass{"#CONSTRAINTS",constraint})?
-objectives_block: (_block_repeat_or_pass{"#OBJECTIVES",objective})?
+constraints_block: (_block_repeat_or_pass{"#CONSTRAINTS",_constraint_block_c})?
+_constraint_block_c: constraint | ctr_activate | ctr_deactivate
+objectives_block: (_block_repeat_or_pass{"#OBJECTIVES",_objective_block_c})?
+_objective_block_c: objective | obj_activate | obj_deactivate
 
 node_import: "#NODE" ID "=" "import" var_or_param "from" STRING node_redefs
 node_redefs: ("with" redefinition*) | ";"
@@ -117,6 +119,16 @@ _maybe_unary_minus: value | unary_minus
 unary_minus: "-" value
 ?value: function | var_or_param | INT | FLOAT | ("(" expression ")")
 
+// ACTIVATE/DEACTIVATE
+_activate.1: "activate" separated_list{_activation_id, ","} ["if" bool_expression] ";"
+_deactivate.1: "deactivate" separated_list{_activation_id, ","} ["if" bool_expression] ";"
+_activation_id: ID | TAG
+ctr_activate: _activate
+ctr_deactivate: _deactivate
+obj_activate: _activate
+obj_deactivate: _deactivate
+
+
 // FUNCTIONS
 function: ID "(" separated_maybe_empty_list{generated_rvalue, ","} ")"
 
diff --git a/src/gboml/parsing.py b/src/gboml/parsing.py
index 5709e5d7f48e9016215a8b67e19342f901eb3169..c37a3413adc8582f502671c42a5a9d764e77ef31 100644
--- a/src/gboml/parsing.py
+++ b/src/gboml/parsing.py
@@ -89,7 +89,11 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
             "range": Range,
             "dict_entry": DictEntry,
             "array": Array,
-            "dict": Dictionary
+            "dict": Dictionary,
+            "ctr_activate": lambda *x, meta: CtrActivation(ActivationType.activate, *x, meta=meta),
+            "ctr_deactivate": lambda *x, meta: CtrActivation(ActivationType.deactivate, *x, meta=meta),
+            "obj_activate": lambda *x, meta: ObjActivation(ActivationType.activate, *x, meta=meta),
+            "obj_deactivate": lambda *x, meta: ObjActivation(ActivationType.deactivate, *x, meta=meta)
         }
 
         def __default__(self, data, children, _):
@@ -122,33 +126,38 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
             return self.NodesAndHyperEdges([x for x in childrens if isinstance(x, Node)], [x for x in childrens if isinstance(x, HyperEdge)])
 
         def hyperedge_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop], tags: list[str],
-                                 param_block: list[Definition] = None, constraint_block: list[Constraint] = None):
+                                 param_block: list[Definition] = None,
+                                 constraint_block: list[Constraint | CtrActivation] = None):
             if constraint_block is None:
                 constraint_block = []
+            activations = [x for x in constraint_block if isinstance(x, CtrActivation)]
+            constraint_block = [x for x in constraint_block if isinstance(x, Constraint)]
             if param_block is None:
                 param_block = []
 
             if loop is None:
                 if len(name.path) != 1 or len(name.path[0].indices) != 0:
                     raise Exception(f"Invalid name for node: {name}")
-                return HyperEdgeDefinition(name.path[0].name, param_block, constraint_block, tags, meta=meta)
+                return HyperEdgeDefinition(name.path[0].name, param_block, constraint_block,
+                                           activations, tags, meta=meta)
             else:
-                return HyperEdgeGenerator(name, loop, param_block, constraint_block, tags, meta=meta)
+                return HyperEdgeGenerator(name, loop, param_block, constraint_block,
+                                          activations, tags, meta=meta)
 
         def node_definition(self, meta: Meta, name: VarOrParam, loop: Optional[Loop], tags: list[str],
                             param_block: list[Definition] = None, subprogram_block: NodesAndHyperEdges = None,
-                            variable_block: list[VariableDefinition] = None, constraint_block: list[Constraint] = None,
-                            objectives_block: list[Objective] = None):
-            if objectives_block is None:
-                objectives_block = []
-            if constraint_block is None:
-                constraint_block = []
-            if variable_block is None:
-                variable_block = []
-            if param_block is None:
-                param_block = []
-            if subprogram_block is None:
-                subprogram_block = self.NodesAndHyperEdges([], [])
+                            variable_block: list[VariableDefinition] = None,
+                            constraint_block: list[Constraint | CtrActivation] = None,
+                            objectives_block: list[Objective | ObjActivation] = None):
+            objectives_block = objectives_block or []
+            constraint_block = constraint_block or []
+            variable_block = variable_block or []
+            param_block = param_block or []
+            subprogram_block = subprogram_block or self.NodesAndHyperEdges([], [])
+
+            activations: list[Activation] = [x for x in constraint_block if isinstance(x, CtrActivation)] + [x for x in objectives_block if isinstance(x, ObjActivation)]
+            constraint_block = [x for x in constraint_block if isinstance(x, Constraint)]
+            objectives_block = [x for x in objectives_block if isinstance(x, Objective)]
 
             if loop is None:
                 if len(name.path) != 1 or len(name.path[0].indices) != 0:
@@ -157,13 +166,13 @@ def _lark_to_gboml(tree: Tree, filename: Optional[str] = None) -> GBOMLGraph:
                                       param_block,
                                       subprogram_block.nodes, subprogram_block.hyperedges,
                                       variable_block, constraint_block,
-                                      objectives_block, tags, meta=meta)
+                                      objectives_block, activations, tags, meta=meta)
             else:
                 return NodeGenerator(name, loop,
                                      param_block,
                                      subprogram_block.nodes, subprogram_block.hyperedges,
                                      variable_block, constraint_block,
-                                     objectives_block, tags, meta=meta)
+                                     objectives_block, activations, tags, meta=meta)
 
         def node_import(self, meta: Meta, name: str, imported_name: VarOrParam, imported_from: str, redef: list[ScopeChange | Definition]):
             return NodeImport(name, imported_name, imported_from,