diff --git a/generator/main.py b/generator/main.py
index 590e20b12d710c53ece8c2dfcd62849b6a9df9ab..e75db2114bfcbd121347a1ce89bc50a230f76ef2 100755
--- a/generator/main.py
+++ b/generator/main.py
@@ -169,6 +169,7 @@ if __name__ == "__main__":
     pass_manager.register_analysis(GenerateAssertionsPass())
 
     pass_manager.register_analysis(FiniteStateMachineBuilder())
+    pass_manager.register_analysis(LogicMinimizer())
 
     # Statistics modules
     pass_manager.register_analysis(GlobalControlFlowMetric("%s/%s_metric" % (options.prefix, options.name)))
diff --git a/generator/transform/FiniteStateMachineBuilder.py b/generator/transform/FiniteStateMachineBuilder.py
index dfe23b1d55c0a0150d05581cfdc3613bf7994825..d06e0d4e47206e498b0dd72449cbaea55a1d662f 100644
--- a/generator/transform/FiniteStateMachineBuilder.py
+++ b/generator/transform/FiniteStateMachineBuilder.py
@@ -63,6 +63,28 @@ class FiniteStateMachine:
             for t in ev.transitions:
                 yield t
 
+    @property
+    def actions(self):
+        return self.action_mapping.keys()
+
+    def copy(self):
+        ret = FiniteStateMachine()
+        ret.initial_state = self.initial_state
+
+        #Copy Mappings
+        ret.action_mapping = self.action_mapping.copy()
+        ret.event_mapping = self.event_mapping.copy()
+        ret.state_mapping = self.state_mapping.copy()
+
+        # Generate new transitions and events
+        for event in self.events:
+            n_event = Event(event.name, [])
+            for t in event.transitions:
+                n_t = Transition(t.source, t.target, t.action)
+                n_event.add_transition(n_t)
+            ret.add_event(n_event)
+        return ret
+
     def add_event(self, event):
         self.events.append(event)
         if not event.name in self.event_mapping:
diff --git a/generator/transform/LogicMinimizer.py b/generator/transform/LogicMinimizer.py
new file mode 100644
index 0000000000000000000000000000000000000000..df5d807ed60a880c68f16c4e40e9587318d459f2
--- /dev/null
+++ b/generator/transform/LogicMinimizer.py
@@ -0,0 +1,138 @@
+from generator.analysis import Analysis
+from collections import namedtuple, defaultdict
+from .FiniteStateMachineBuilder import FiniteStateMachine, Transition, Event
+import math
+import os
+import subprocess
+import logging
+
+class LogicMinimizer(Analysis):
+    def __init__(self):
+        super(LogicMinimizer, self).__init__()
+
+    def requires(self):
+        return ["fsm"]
+
+    def do(self):
+        fsm = self.system_graph.get_pass("fsm").fsm.copy()
+
+        self.fsm = self.call_nova(fsm)
+
+    def call_nova(self, fsm):
+        class isr_renamer:
+            def __init__(self):
+                self.mapping = {}
+                self.__i = 1
+            def __call__(self, action):
+                if action.conf.is_isr:
+                    return 0
+                    #return None
+                else:
+                    if not action in self.mapping:
+                        self.mapping[action] = self.__i
+                        self.__i += 1
+                    return self.mapping[action]
+            def max_int(self):
+                return self.__i
+
+        isr_rename = isr_renamer()
+        fsm.rename(events = True, actions = isr_rename)
+
+        # Generate Bitstrings
+        class binstring_renamer:
+            def __init__(self, max_items, prefix = ''):
+                self.bitwidth = math.ceil(math.log2(max_items))
+                self.__i = 0
+                self.prefix = prefix
+            def __call__(self, x):
+                if type(x) == int:
+                    l = x
+                elif x == None:
+                    return "-" * self.bitwidth
+                else:
+                    l = self.__i
+                    self.__i += 1
+                return "{2}{0:0{1}b}".format(l, self.bitwidth, self.prefix)
+
+        event_rename = binstring_renamer(len(fsm.events), 'e')
+        state_rename = binstring_renamer(len(fsm.states), 's')
+        action_rename = binstring_renamer(isr_rename.max_int())
+
+        # Rename to Bitstring
+        fsm.rename(events = event_rename,
+                   states = state_rename,
+                   actions = action_rename)
+
+        nova_input = "%snova.fsm" % self.system_graph.basefilename
+        with open(nova_input, "w+") as fd:
+            fd.write(".i {0}\n".format(event_rename.bitwidth))
+            fd.write(".o {0}\n".format(action_rename.bitwidth))
+            fd.write(".s {0}\n".format(len(fsm.states)))
+            fd.write(".symbolic input\n".format(len(fsm.states)))
+
+            fd.write(str(fsm) + "\n")
+            fd.write(".e\n")
+
+        stdout = subprocess.check_output(["nova", nova_input]).decode('ascii', 'ignore')
+        event_mapping = {}
+        state_mapping = {}
+        for line in stdout.split("\n"):
+            if line.startswith(".code"):
+                (_, old, new) = line.split()
+                if old.startswith("e"):
+                    event_mapping[old] = new
+                elif old.startswith("s"):
+                    state_mapping[old] = new
+                else:
+                    assert False, "Invalid NOVA output"
+
+        # No event encoding is used twice
+        assert len(event_mapping) == len(fsm.events)
+        assert len(event_mapping) == len(set(event_mapping.values()))
+
+        # No state is given doubled
+        assert len(state_mapping) == len(fsm.states)
+        assert len(state_mapping) == len(set(state_mapping.values()))
+        fsm.rename(events = lambda e: event_mapping[e],
+                   states = lambda s: state_mapping[s])
+
+        event_len = len(fsm.events[0].name)
+        state_len = len(fsm.initial_state)
+        action_len = action_rename.bitwidth
+        self.event_len, self.state_len, self.action_len \
+            = (event_len, state_len, action_len)
+
+        self.truth_table = []
+        # Read in the minimzed truth table
+        with open("%s.esp" % nova_input) as esp:
+            for line in esp.readlines():
+                line = [x for x in line if x in "01-"]
+                if len(line) == event_len + state_len * 2 + action_len:
+                    input_word = line[0:event_len+state_len]; del line[0:event_len+state_len]
+                    output_state = line[0:state_len]; del line[0:state_len]
+                    output_action = line
+
+                    # Generate pattern and mask
+                    mask_filter = {'0': '1', '1': '1', '-': '0'}
+                    pattern_filter = {'0': '0', '1': '1', '-': '0'}
+                    mask_word = [mask_filter[x] for x in input_word]
+                    pattern_word = [pattern_filter[x] for x in input_word]
+
+                    self.truth_table.append(("".join(mask_word), "".join(pattern_word),
+                                             "".join(output_state), "".join(output_action)))
+
+        matches = [0 for x in self.truth_table]
+        for transition in fsm.transitions:
+            input_word = int(transition.event+transition.source, 2)
+            desired_output_word = int(transition.target+transition.action, 2)
+            got_output_word = 0
+            for i, (mask_word, pattern_word, output_state, output_action) in enumerate(self.truth_table):
+                output_word = int(output_state+output_action, 2)
+                mask_word = int(mask_word, 2)
+                pattern_word = int(pattern_word, 2)
+                if (input_word & mask_word) == pattern_word:
+                    got_output_word |= output_word
+                    matches[i] += 1
+            assert got_output_word == desired_output_word
+        logging.info("%d lines in minimzed truth table", len(self.truth_table))
+        return fsm
diff --git a/generator/transform/__init__.py b/generator/transform/__init__.py
index f9670d9f91fc0d055810eb9138fb900447e00751..a150f16a4217efa6bdc99571247f8cf8f04dde5b 100644
--- a/generator/transform/__init__.py
+++ b/generator/transform/__init__.py
@@ -3,3 +3,4 @@ assert __name__ == "generator.transform"
 from .FiniteStateMachineBuilder import *
 from .CFGRegions import CFGRegions
 from .GenerateAssertions import *
+from .LogicMinimizer import LogicMinimizer