def testCompositeSpec(self):
     a, b = 5, 7
     ab = a * b
     tObj = TestObj2(a, b)
     spec1 = Specification('t.b == b', candidate_name='t')
     spec2 = Specification('t.ab < ab', candidate_name='t')
     spec3 = Specification('1 <= t.a <= 7')
     cspec = spec1 & spec2 & spec3
     self.assertFalse(cspec.is_satisfied_by(tObj))
     cspec = spec1 | spec2 | spec3
     self.assertTrue(cspec.is_satisfied_by(tObj))
     cspec = spec1 ^ spec2 ^ spec3
     self.assertFalse(cspec.is_satisfied_by(tObj))
     cspec = spec1 & (spec2 & spec3)
     self.assertFalse(cspec.is_satisfied_by(tObj))
     cspec = (spec1 & spec2) | spec3
     self.assertTrue(cspec.is_satisfied_by(tObj))
     cspec = (spec1 | spec2) & ~spec3
     self.assertFalse(cspec.is_satisfied_by(tObj))
     cspec = (~spec1 | spec2) | ~spec3
     self.assertFalse(cspec.is_satisfied_by(tObj))
     cspec = (spec1 & ~spec2) & spec3
     self.assertTrue(cspec.is_satisfied_by(tObj))
     cspec = (spec1 & ~spec2) ^ spec3
     self.assertFalse(cspec.is_satisfied_by(tObj))
     cspec = (spec1 ^ spec2) & spec3
     self.assertTrue(cspec.is_satisfied_by(tObj))
     cspec = ~(spec1 ^ spec2) ^ spec3
     self.assertTrue(cspec.is_satisfied_by(tObj))
     cspec = ~(spec1 ^ spec2 ^ spec3)
     self.assertTrue(cspec.is_satisfied_by(tObj, ab=ab))
    def test_eq_and_hash(self):

        def op(x, y):
            return x == y                               # pragma: no cover

        spec1 = Specification("op(a, 1)", candidate_name='a')
        spec2 = Specification("op(a,1)", candidate_name='a')
        spec3 = Specification("a == 1")
        self.assertEqual(spec1, spec2)
        self.assertEqual(hash(spec1), hash(spec2))
        self.assertNotEqual(spec1, spec3)
        self.assertNotEqual(hash(spec1), hash(spec3))
        negspec1 = ~spec1
        negspec2 = ~spec2
        negspec3 = ~spec3
        self.assertEqual(negspec1, negspec2)
        self.assertEqual(hash(negspec1), hash(negspec2))
        self.assertNotEqual(negspec1, negspec3)
        self.assertNotEqual(hash(negspec1), hash(negspec3))
        self.assertNotEqual(spec1, negspec1)
        self.assertNotEqual(hash(spec1), hash(negspec1))
        cspec1 = spec1 & negspec2
        cspec2 = spec2 & negspec1
        cspec3 = spec1 & spec3
        self.assertEqual(cspec1, cspec2)
        self.assertEqual(hash(cspec1), hash(cspec2))
        self.assertNotEqual(cspec1, cspec3)
        self.assertNotEqual(hash(cspec1), hash(cspec3))
        self.assertNotEqual(spec1, cspec1)
        self.assertNotEqual(hash(spec1), hash(cspec1))
Esempio n. 3
0
 def __load_specifications(self):
     """
     Loads Specifications from the configurations and stores them in the
     internal storage.
     """
     try:
         params = rospy.get_param(self.__namespace)
         if isinstance(params, dict):
             specifications = []
             for x in params.values():
                 for y in x:
                     specifications.append(y)
         else:
             specifications = params
         for o in specifications:
             for seuid in o.keys():
                 if SEUID().is_valid(seuid):
                     spec = Specification()
                     spec.seuid = seuid
                     for k in o[seuid].keys():
                         spec.add_tuple((k, o[seuid][k]))
                     self.__specifications[seuid] = spec
                 else:
                     rospy.logdebug("[SpecificationHandler][__load_specifications] %s is not a valid seuid." % seuid)
     except KeyError:
         pass
     rospy.loginfo("[SpecificationHandler] Loaded %s parameters." % str(len(self.__specifications.keys())))
Esempio n. 4
0
 def __load_specifications(self):
     """
     Loads Specifications from the configurations and stores them in the
     internal storage.
     """
     try:
         params = rospy.get_param(self.__namespace)
         if isinstance(params, dict):
             specifications = []
             for x in params.values():
                 for y in x:
                     specifications.append(y)
         else:
             specifications = params
         for o in specifications:
             for seuid in o.keys():
                 if SEUID().is_valid(seuid):
                     spec = Specification()
                     spec.seuid = seuid
                     for k in o[seuid].keys():
                         spec.add_tuple((k, o[seuid][k]))
                     self.__specifications[seuid] = spec
                 else:
                     rospy.logdebug("[SpecificationHandler][__load_specifications] %s is not a valid seuid." % seuid)
     except KeyError:
         pass
     rospy.loginfo("[SpecificationHandler] Loaded %s parameters." % str(len(self.__specifications.keys())))
 def testCompositeSpec(self):
     spec1 = Specification('b == 2')
     spec2 = Specification('ab > 20')
     spec3 = Specification('2 < a <= 7')
     spec4 = Specification('ab not in range(-12, -7)')
     for op in (operator.and_, operator.or_, operator.xor):
         for spec1, spec2 in combinations((spec1, spec2, spec3, spec4), 2):
             spec = op(spec1, spec2)
             neg_spec = ~spec
             self.assertTrue(isinstance(neg_spec, Specification))
             self.assertEqual(spec, ~neg_spec)
Esempio n. 6
0
 def __init__(self,
              centralised_vcs_server,
              target_test_coverage_per_feature=1.0,
              tests_per_chunk_ratio=1,
              target_dependencies_per_feature=0
              ):
     change_management = ChangeManagement(centralised_vcs_server)
     self.specification = Specification(change_management)
     self.testing = Testing(change_management, target_test_coverage_per_feature, tests_per_chunk_ratio)
     self.implementation = Implementation(change_management)
     self.debugging = Debugging(change_management)
     self.refactoring = Refactoring(change_management, target_dependencies_per_feature)
 def testSpecFromExpression(self):
     src = "x==1"
     expr = ast.parse(src, mode='eval')
     spec = Specification(expr)
     self.assertIsInstance(spec._ast_expr, ast.Expression)
     self.assertEqual(spec._candidate_name, 'x')
     self.assertEqual(spec._context, {})
 def testAdditionalContext(self):
     year = 1999
     spec = Specification('deadline < date(year, 6, 30)',
                          candidate_name='deadline')
     dt = date(year, 5, 1)
     self.assertTrue(spec(dt))
     self.assertTrue(spec(dt, year=2000))
     self.assertFalse(spec(dt, year=1997))
Esempio n. 9
0
 def watch_spec(data, stat):
     if data:
         self.logger.debug('Reloading spec.yaml')
         self.spec = Specification(data)
         self.logger.debug('Parsed specification')
     else:
         self.spec = None
         self.logger.warn('Specification not found in {}'.format(BlacKnightClient.spec_znode))
Esempio n. 10
0
class TestIssue1(unittest.TestCase):

    def setUp(self):
        from decimal import Decimal                     # noqa
        self.spec = Specification("x == Decimal('5.4')",
                                  candidate_name='x')

    def testIsSatisfied(self):
        self.assertFalse(self.spec.is_satisfied_by(5))
Esempio n. 11
0
 def testNestedproperty(self):
     a, b = 5, 7
     ab = a * b
     tObj = TestObj1(a=3, b=TestObj2(a, b))
     spec = Specification(f't.b.ab == {ab}')
     self.assertTrue(spec.is_satisfied_by(tObj))
     spec = ~Specification(f't.b.ab != {ab}')
     self.assertTrue(spec.is_satisfied_by(tObj))
     ispec = Specification('1 <= t.b.a <= 7')
     self.assertTrue(ispec.is_satisfied_by(tObj))
     cspec = spec & ispec
     self.assertTrue(cspec.is_satisfied_by(tObj))
Esempio n. 12
0
 def testSpecFromStr(self):
     expr = "b == 2"
     spec = Specification(expr)
     self.assertIsInstance(spec._ast_expr, ast.Expression)
     self.assertEqual(spec._candidate_name, 'b')
     self.assertEqual(spec._context, {})
     # nested attribute
     expr = "b.x.y==2"
     spec = Specification(expr)
     self.assertIsInstance(spec._ast_expr, ast.Expression)
     self.assertEqual(spec._candidate_name, 'b')
     self.assertEqual(spec._context, {})
     # nested attribute and context variables
     y = object()
     z = object()
     expr = "y.a > x.b >= z.c"
     spec = Specification(expr, candidate_name='x')
     self.assertIsInstance(spec._ast_expr, ast.Expression)
     self.assertEqual(spec._candidate_name, 'x')
     self.assertEqual(spec._context, {'y': y, 'z': z})
Esempio n. 13
0
 def testReprAndStr(self):
     op = lambda x, y: x == y                        # noqa
     spec = Specification('op(o.a,1)', candidate_name='o')
     self.assertEqual(repr(spec),
                      "Specification('op(o.a, 1)', candidate_name='o')")
     self.assertEqual(str(spec), '<o: op(o.a, 1)>')
     self.assertEqual(repr(~spec),
                      "Specification('not op(o.a, 1)', "
                      "candidate_name='o')")
     self.assertEqual(str(~spec), '<o: not op(o.a, 1)>')
     spec = Specification('x.a == 1')
     self.assertEqual(repr(spec), "Specification('x.a == 1')")
     self.assertEqual(str(spec), '<x: x.a == 1>')
     ispec = Specification('0 <  a.b <=6')
     self.assertEqual(repr(ispec), "Specification('0 < a.b <= 6')")
     self.assertEqual(str(ispec), '<a: 0 < a.b <= 6>')
     cspec = ispec & spec
     self.assertEqual(repr(cspec),
                      "Specification('0 < a.b <= 6 and a.a == 1')")
     self.assertEqual(str(cspec), '<a: 0 < a.b <= 6 and a.a == 1>')
Esempio n. 14
0
 def testSimpleSpec(self):
     for op1, op2 in [('==', '!='),
                      ('<', '>='),
                      ('>', '<='),
                      ('is', 'is not')]:
         spec1 = Specification(f'a {op1} 1')
         spec2 = Specification(f'a {op2} 1')
         neg_spec1 = ~spec1
         neg_spec2 = ~spec2
         self.assertTrue(isinstance(neg_spec1, Specification))
         self.assertTrue(isinstance(neg_spec2, Specification))
         self.assertEqual(spec1, neg_spec2)
         self.assertEqual(spec2, neg_spec1)
         self.assertEqual(spec1, ~neg_spec1)
         self.assertEqual(spec2, ~neg_spec2)
     # non-predefined operator:
     op = lambda x, y: x == y                        # noqa
     spec = Specification(f'op(a, 1)', candidate_name='a')
     neg_spec = ~spec
     self.assertTrue(isinstance(neg_spec, Specification))
     self.assertEqual(spec, ~neg_spec)
Esempio n. 15
0
 def test_find(self):
     repo = self.repo(Person)
     p1 = Person('Hans', 'Berlinger', date(1982, 12, 3))
     self.assertIsNone(repo.add(p1))
     p2 = Person('Bert', 'Berlinger', date(1962, 2, 14))
     self.assertIsNone(repo.add(p2))
     p3 = Prospect('Hans', 'Berliner', date(1982, 12, 3))
     self.assertIsNone(repo.add(p3))
     spec = Specification('x.date_of_birth >= date(1980, 1, 1)',
                          candidate_name='x')
     res = list(repo.find(spec))
     self.assertEqual(len(res), 2)
     self.assertIn(p1, res)
     self.assertIn(p3, res)
Esempio n. 16
0
class TestDrivenDevelopment(object):

    is_workflow = True

    def __init__(self,
                 centralised_vcs_server,
                 target_test_coverage_per_feature=1.0,
                 tests_per_chunk_ratio=1,
                 target_dependencies_per_feature=0
                 ):
        change_management = ChangeManagement(centralised_vcs_server)
        self.specification = Specification(change_management)
        self.testing = Testing(change_management, target_test_coverage_per_feature, tests_per_chunk_ratio)
        self.implementation = Implementation(change_management)
        self.debugging = Debugging(change_management)
        self.refactoring = Refactoring(change_management, target_dependencies_per_feature)

    @default_cost()
    def implement_feature_tdd(self, user_story, random):
        """
        Implements the sequence of activities in a tests driven development workflow.
        """
        self.specification.add_feature(user_story.logical_name, user_story.size, random)
        self.testing.test_per_chunk_ratio(user_story.logical_name, random)
        self.implementation.implement_feature(user_story.logical_name, random)
        self.debugging.debug_feature(user_story.logical_name, random)
        self.refactoring.refactor_feature(user_story.logical_name, random)

    @default_cost()
    def work_from_backlog(self, product_backlog, random):
        while True:
            try:
                user_story = product_backlog.get(block=False)
                self.implement_feature_tdd(user_story, random)
            except Empty:
                break
Esempio n. 17
0
 def setUp(self):
     self.x = x = object()                        # noqa
     self.y = y = 5                               # noqa
     self.z = z = 13                              # noqa
     self.spec1 = Specification("y == 2")
     self.spec2 = Specification("ab>20")
     self.spec3 = Specification("x==y", candidate_name='x')
     self.spec4 = Specification("x.ab>=z", candidate_name='x')
     self.spec5 = Specification("x.ab>=z", candidate_name='z')
     self.spec6 = Specification("x.ab>=z", candidate_name='x',
                                namespace = {'z': 7})
Esempio n. 18
0
 def testSimpleSpec(self):
     val = 5
     tObj = TestObj1(b=val)
     for op1, op2 in [(operator.eq, operator.ne),
                      (operator.lt, operator.ge),
                      (operator.gt, operator.le),
                      (operator.is_, operator.is_not)]:
         spec1 = Specification(f't.b {op2sym[op1]} {val}')
         spec2 = Specification(f't.b {op2sym[op2]} {val}')
         self.assertEqual(spec1.is_satisfied_by(tObj), op1(tObj.b, val))
         self.assertFalse(spec1.is_satisfied_by(tObj) and
                          spec2.is_satisfied_by(tObj))
         spec1 = Specification(f't.b {op2sym[op1]} {-val}')
         spec2 = Specification(f't.b {op2sym[op2]} {-val}')
         self.assertEqual(spec1.is_satisfied_by(tObj), op1(tObj.b, -val))
         self.assertFalse(spec1.is_satisfied_by(tObj) and
                          spec2.is_satisfied_by(tObj))
     # compare instance of subclass
     tObj = TestObj2(b=val)
     spec = Specification(f't.b == {val}')
     self.assertTrue(spec.is_satisfied_by(tObj))
     spec = Specification(f't.b < {val}')
     self.assertFalse(spec.is_satisfied_by(tObj))
Esempio n. 19
0
 def testNameConflict(self):
     spec = Specification('dt >= date(2020, 1, 1)', candidate_name='dt')
     # conflict with given keyword
     candidate = date(2021, 8, 1)
     self.assertRaises(ValueError, spec, candidate, date=date,
                       dt=date.today())
Esempio n. 20
0
    def run(self):
        from nusmv import dd
        import marduk_utils
        import time

        start_wall_clock = time.clock()
        
        self.println("------------------------------------------------------")
        self.println("Synthesize " + str(self.input_file) +  " to " + str(self.output_file))
        if self.__options.mode != None:
            self.println("Mode: " + self.__options.mode.upper())
        if self.__options.language != None:
            self.println("Output Language: " + self.__options.language.upper())

        from datetime import datetime
        self.println("Start time: %s" % datetime.now().ctime())
            
        #print "Reordering status:", dd.dd_reordering_status(dd.cvar.dd_manager)
        
        self.println("\n Dynamic reordering \t\t\t\t\t" + str(self.dyn_reorder))
        self.println(" Reordering method for dynamic reordering \t\t" + marduk_utils.reorder_method_to_string(self.dyn_reorder_method))
        self.println(" Reordering method for forced reordering \t\t" + marduk_utils.reorder_method_to_string(self.reorder_method))
        self.println(" Reorder BDD after reading configuration \t\t" + str(self.r1))
        self.println(" Reorder BDD after generating output functions  \t" + str(self.r2))
        self.println(" Kill strategy and reorder afterwards   \t\t" + str(self.kill))
        self.println(" One-hot encoding of jx vars\t\t\t\t" + str(self.one_hot))
        self.println(" Transfer functions to new DD manager and reorder \t" + str(self.transfer_functions))
        self.println(" Generate functions according to\n Baneres, Cortadella, Kishinevsky (DAC'04)\t\t" + str(self.dac04))
        if self.dac04:
            if self.dac_search_mode == 'dfs':
                self.println(" DAC'04 search mode \t\t\t\t\tDepth First")
                self.println(" DAC'04 recursion depth limit\t\t\t\t" + str(self.dac_recur_limit))
            elif self.dac_search_mode == 'bfs':
                self.println(" DAC'04 search mode \t\t\t\t\tBreadth First")
                self.println(" DAC'04 call limit\t\t\t\t\t" + str(self.dac_call_limit))

        if self.__mode in (marduk_utils.Modes.IRRSOP, marduk_utils.Modes.FACTOR):
            if self.cache_size != None:
                self.println(" Function cache size \t\t\t\t\t" + str(self.cache_size))
            else:
                self.println(" Function cache size \t\t\t\t\tunlimited")
            self.println(" Number of class vectors \t\t\t\t" + str(self.num_class_vectors))
            self.println(" Number of new vectors for cache reorganization \t" + str(self.update_sigs_size))
            self.println(" Use don't care upper bound for ISoP_d \t\t\t" + str(self.dont_care_upper_bound))
            self.println(" Check combinations of 2 functions \t\t\t" + str(self.check_combinations))

        self._starttime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime
        
        self.println("\n Timing Information:")
        
        # Load specification from input file
        self.__specification = Specification(self)
        self.__specification.readSpecification()
        self._specificationtime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        self.println("   Specification read within\t\t\t %7.2f seconds" %(self._specificationtime-self._starttime))

        # Create list of variables and store it here in main class, for central access
        self.__variables = self.__specification.create_variable_list()

        if self.verbose > 1:
            print "Length of variables list: ", len(self.__variables)
            for var in self.__variables:
                print var

        if self.verbose > 1:        
            print "Current Ordering:"
            print marduk_utils.print_variable_ordering(self.vars)

        if self.var_order:
            self.println('    Forcing variable order: ' + self.var_order)
            marduk_utils.set_variable_ordering(self.var_order, self.vars, self.dd_mgr)
            
        if self.verbose > 1:
            print "Current Ordering:"
            print marduk_utils.print_variable_ordering(self.vars)
        
        # Compute winning region
        import sys    
        self.__winning_region = WinningRegion(self, self.__specification)
        self.__winning_region.calcWinningRegion()
        self._winningregiontime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime

        self.println("   Compute winning region within \t\t %7.2f seconds" %(self._winningregiontime - self._reorder1time))
        if(not(self.__winning_region.isRealizable())):
            self.println("The given specification is NOT REALIZABLE!\n")
            if not self.debug_mode:
                self.println("Use the argument --dm to debug unrealizability\n")
                return
            del self.__winning_region
            self.__spec_debugger = SpecDebugger(self)
            self.__spec_debugger.debug(self.debug_mode)
            return
        self.__winning_region_size = self.__winning_region.winRegion.size    

        
        # Compute strategy
        self.__strategy = Strategy(self)
        self.__strategy.calcStrategy()
        self._strategytime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        self.println("   Compute strategy within \t\t\t %7.2f seconds" %(self._strategytime-self._winningregiontime))

        from marduk_utils import VariableType

        self.println("\nStrategy Characterization:")
        input_vars = [var.ns for var in self.input_vars] + [var.ps for var in self.vars]
        output_vars = [var.ns for var in self.vars if var.type != VariableType.INPUT]
        begin = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        strat_char = marduk_utils.characterize_relation(self.__strategy.strategy_bdd, input_vars, output_vars, return_bdds=True)
        char_time = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime - begin
        self.println("(computed in %7.2f seconds)" % char_time)
        total = 2 ** strat_char['num_inputs']
        defined = (strat_char['num_defined'] / total) * 100
        fixed = (strat_char['num_fixed'] / total) * 100
        dc = (strat_char['num_dc'] / total) * 100
        non_dc = (strat_char['num_non_dc'] / total) * 100
        self.println("Defined:%7.2f%%" % defined)
        self.println("Fixed:\t %7.2f%%" % fixed)
        self.println("DC:\t %7.2f%%" % dc)
        self.println("Non-DC:\t %7.2f%%\n" % non_dc)

        strat_dc = strat_char['dc_bdd']
        del strat_char
        
        if self.__mode in (marduk_utils.Modes.COFACTOR, marduk_utils.Modes.OLD):
            self.do_cofactor_mode()
        else:
            self.do_function_generator_mode(strat_dc=strat_dc)


        if self.transfer_functions:
            self.println("   Transferred output functions within \t\t %7.2f seconds" % self.__code_generator._transfer_time)
            self.println("   Reordering transferred BDD took \t\t %7.2f seconds" % self.__code_generator._reorder_time)
        self.println("\n   Results in needed overall time of\t\t %7.2f seconds \n" %(self._codegentime - self._starttime))

        stop_wall_clock_time = time.clock()
        self.println("   Overall wall clock time\t\t\t %7.2f seconds" % (stop_wall_clock_time - start_wall_clock))

        self.println("\n BDD-Size Information:")
        self.println("   Size of Winning Region: \t\t %10d bdd-nodes" % self.__winning_region_size)
        self.println("   Size of rho1 is \t\t\t %10d bdd-nodes" %self.__strategy.rho1_size)
        self.println("   Size of rho2 is \t\t\t %10d bdd-nodes" %self.__strategy.rho2_size)
        self.println("   Size of rho3 is \t\t\t %10d bdd-nodes" %self.__strategy.rho3_size)

        self.println("------------------------------------------------------")
        self.println("                FINISHED synthesis!"            )
        self.println("------------------------------------------------------")

        if self.verbose > 1:
            print "Current Ordering:"
            print marduk_utils.print_variable_ordering(self.vars)
        
        
        # The following should be the last block in the run method:
        self.__code_generator.append_comment(self.__printed_lines)
        # Killing references to other objects, break up circular references
        self.__specification = None
        self.__winning_region = None
        self.__strategy = None
        self.__output_functions = None
        self.__code_generator = None
Esempio n. 21
0
class Marduk(object):
    """
    This is the main class of the Marduk implementation. It is the main start of control flow.
    Furthermore it stores global options, parameters, and other objects and provides appropriate
    access methods.
    """    


    def __init__(self, options, args):
        """
        Marduk constructor. Analyzes and stores options.
        """

        self.__options = options
        self.__args = args

         # Initialize DD manager for synthesis.
        from nusmv import dd
        self.__dd_manager = dd.create_dd_manager(0,0,251,131071,0)  # Values from PerlDD


        self.__printed_lines = ["This file was automatically synthesized with Marduk.",
                                "Information on the synthesis process is displayed below.",
                                "---------------------------------------------------------------------------\n"]

        
        if options.input_file == None:
            self.println("WARNING: No input file specified! Using 'input.xml' as default input file!")
            self.__input_file = "input.xml"
        else:
            self.__input_file = options.input_file
                
        if options.output_file == None:
            self.println("WARNING: No output file specified! Using 'marduk_out' as default output file!")
            self.__output_file = "marduk_out"
        else:
            self.__output_file = options.output_file
        
        if options.mode == None:
            self.println("WARNING: No mode specified! Using 'cofactor' as default!")
            self.__mode = marduk_utils.Modes.COFACTOR
        elif options.mode.lower() == "cofactor":
            self.__mode = marduk_utils.Modes.COFACTOR
        elif options.mode.lower() == "irrsop":
            self.__mode = marduk_utils.Modes.IRRSOP
        elif options.mode.lower() == "factor":
            self.__mode = marduk_utils.Modes.FACTOR
        elif options.mode.lower() == "old":
            self.__mode = marduk_utils.Modes.OLD
            self.println("WARNING: In 'OLD' mode, the language setting will be ignored. Output will be in BLIF format.")
        else:
            self.println("WARNING: Unknown mode: '" + options.mode + \
                "'! Using 'cofactor' as default!")
            self.__mode = marduk_utils.Modes.COFACTOR
            options.mode = "COFACTOR"

        if options.language == None:
            self.println("WARNING: No language specified! Using 'blif' as default!")
            self.__language = marduk_utils.Languages.BLIF
        elif options.language.lower() == "blif":
            self.__language = marduk_utils.Languages.BLIF
        elif options.language.lower() == "verilog":
            self.__language = marduk_utils.Languages.VERILOG
        elif options.language.lower() == "hif":
            self.__language = marduk_utils.Languages.HIF
        else:
            self.println("WARNING: Unknown language: '" + options.language + \
                "'! Using 'blif' as default!")
            self.__language = marduk_utils.Languages.BLIF
            options.language = "BLIF"


        if options.transfer_functions and not self.__mode in (marduk_utils.Modes.COFACTOR, marduk_utils.Modes.OLD):
            self.println("WARNING: Cannot use 'transfer' option in '%s' mode. Will be ignored!" % options.mode)
            options.transfer_functions = False
            
        # Handle options concerning IrrSOP (cache)
        try:
            self.__num_class_vectors = int(options.num_class_vectors)
        except ValueError:
            self.println("WARNING: Given number of class-vectors '" + options.num_class_vectors + "' is not an integer.")
            self.println("         Using '1024' as default!")
            self.__num_class_vectors = 1024

        try:
            self.__update_sigs_size = int(options.update_sigs_size)
        except ValueError:
            self.println("WARNING: Given number for update signatures '" + options.update_sigs_size + "' is not an integer.")
            self.println("         Using '32' as default!")
            self.__update_sigs_size = 32
            
        try:
            self.__cache_size = int(options.cache_size)
        except TypeError:
            if not options.cache_size:
                self.__cache_size = None
            else:
                raise Exception("Unexpected TypeError for argument --cache-size='%s'." % options.cache_size)
        except ValueError:
            self.println("WARNING: Given cache size '" + options.cache_size + "' is not an integer.")
            self.println("         Using 'None' (=no limit) as default!")
            self.__cache_size = None

        self.__dont_care_upper_bound = options.dont_care_upper_bound
            
        # The following are not handled yet!    
        self.__check_combinations = options.check_combinations
        # Missing: option to set threshold for signature update

        
        
        if options.partition == None:
            self.__partition = None
        elif options.partition.lower() == "threshold":
            self.__partition = "Threshold"
        elif options.partition.lower() == "monolithic":
            self.__partition = "Monolithic"
        elif options.partition.lower() == "Iwls95CP".lower():
            self.__partition = "Iwls95CP"
        else:
            self.println("WARNING: Unknown partition method: '%s'! Using 'None' as default!" % options.partition)
            self.__partition = None

        try:
            self.__verbose = int(options.verbose)
        except ValueError:
            self.println("WARNING: Given verbose level '" + options.verbose + "' is not an integer.")
            self.println("         Using '0' as default!")
            self.__verbose = 0

        if options.dac_recur_limit and options.dac04:
            try:
                self.__dac_recur_limit = int(options.dac_recur_limit)
            except ValueError:
                self.println("WARNING: Given dac-recur-limit '" + options.verbose + "' is not an integer.")
                self.println("         Using '5' as default!")
                self.__dac_recur_limit = 5
        else:
            self.__dac_recur_limit = None

            
        if options.dac_call_limit and options.dac04:
            try:
                self.__dac_call_limit = int(options.dac_call_limit)
            except ValueError:
                self.println("WARNING: Given dac-call-limit '" + options.verbose + "' is not an integer.")
                self.println("         Using '10' as default!")
                self.__dac_call_limit = 10
        else:
            self.__dac_call_limit = None

        if options.dac_search_mode and options.dac04:
            if options.dac_search_mode.lower() in ['dfs', 'bfs']:
                self.__dac_search_mode = options.dac_search_mode
            else:
                self.println("WARNING: Given dac-search-mode '%s' is unknown." % options.dac_search_mode)
                self.println("         Using 'bfs' as default.")
        else:
            if options.dac04:
                self.println("WARNING: No dac-search-mode given. Using 'dfs' as default.")
                self.__dac_search_mode = 'dfs'
            else:
                self.__dac_search_mode = None

                
        if (not options.dac04) and options.dac_search_mode != None:
            self.println("WARNING: Specified a dac-search-mode, but '--dac04' was not given.")
            self.println("         The given mode will be ignored.")
                
        if (options.dac_recur_limit and (not options.dac04 or self.__dac_search_mode != 'dfs')):
            self.println("WARNING: A dac-recur-limit was given, but program is not in DAC04-DFS mode.")
            self.println("         The given limit will be ignored.")

        if (options.dac_call_limit and (not options.dac04 or self.__dac_search_mode != 'bfs')):
            self.println("WARNING: A dac-call-limit was given, but program is not in DAC04-BFS mode.")
            self.println("         The given limit will be ignored.")
            
        if options.dac04:
            if self.__dac_search_mode == 'dfs' and self.__dac_recur_limit == None:
                self.println("WARNING: Using DAC'04 in DFS mode without a recursion limit!")
                self.println("         Run time and memory consumption might become very high!")
            if self.__dac_search_mode == 'bfs' and self.__dac_call_limit == None:
                self.println("WARNING: Using DAC'04 in BFS mode without a call limit!")
                self.println("         Run time and memory consumption might become very high!")                
                
                         
            
        # Propagate necessary options to NuSMV
        from nusmv import opt
        from nusmv import dd
        from nusmv import game
        import re

        opt.set_batch(opt.OptsHandler_get_instance())
        opt.set_verbose_level(opt.OptsHandler_get_instance(), self.__verbose)
        print "marduk game mode: ", game.opt_game_game(opt.OptsHandler_get_instance())
        game.unset_game_game(opt.OptsHandler_get_instance())
        print "marduk game mode: ", game.opt_game_game(opt.OptsHandler_get_instance())

        # Dealing with reorder method for forced reorderings
        reorder_method = options.reorder_method.upper()
        reorder_method = re.sub('CUDD_','',reorder_method)
        reorder_method = re.sub('REORDER_','',reorder_method)
        reorder_method = re.sub('_CONVERGE','_CONV',reorder_method)

        self.__reorder_method = -1

        if reorder_method == "SAME":
            self.__reorder_method = dd.REORDER_SAME
        elif reorder_method == "NONE":
            self.__reorder_method = dd.REORDER_NONE
        elif reorder_method == "RANDOM":
            self.__reorder_method = dd.REORDER_RANDOM
        elif reorder_method == "RANDOM_PIVOT":
            self.__reorder_method = dd.REORDER_RANDOM_PIVOT
        elif reorder_method == "SIFT":
            self.__reorder_method = dd.REORDER_SIFT
        elif reorder_method == "SIFT_CONV":
            self.__reorder_method = dd.REORDER_SIFT_CONV
        elif reorder_method == "SYMM_SIFT":
            self.__reorder_method = dd.REORDER_SYMM_SIFT
        elif reorder_method == "SYMM_SIFT_CONV":
            self.__reorder_method = dd.REORDER_SYMM_SIFT_CONV
        elif reorder_method == "WINDOW2":
            self.__reorder_method = dd.REORDER_WINDOW2
        elif reorder_method == "WINDOW3":
            self.__reorder_method = dd.REORDER_WINDOW3
        elif reorder_method == "WINDOW4":
            self.__reorder_method = dd.REORDER_WINDOW4
        elif reorder_method == "WINDOW2_CONV":
            self.__reorder_method = dd.REORDER_WINDOW2_CONV
        elif reorder_method == "WINDOW3_CONV":
            self.__reorder_method = dd.REORDER_WINDOW3_CONV
        elif reorder_method == "WINDOW4_CONV":
            self.__reorder_method = dd.REORDER_WINDOW4_CONV
        elif reorder_method == "GROUP_SIFT":
            self.__reorder_method = dd.REORDER_GROUP_SIFT
        elif reorder_method == "GROUP_SIFT_CONV":
            self.__reorder_method = dd.REORDER_GROUP_SIFT_CONV
        elif reorder_method == "ANNEALING":
            self.__reorder_method = dd.REORDER_ANNEALING
        elif reorder_method == "GENETIC":
            self.__reorder_method = dd.REORDER_GENETIC
        elif reorder_method == "LINEAR":
            self.__reorder_method = dd.REORDER_LINEAR
        elif reorder_method == "LINEAR_CONV":
            self.__reorder_method = dd.REORDER_LINEAR_CONVERGE
        elif reorder_method == "EXACT":
            self.__reorder_method = dd.REORDER_EXACT
        else:
            self.println("WARNING: Specified unknown reordering method '%s'! Using NONE as default instead." % options.reorder_method)
            self.__reorder_method = dd.REORDER_NONE


        # Dealing with reorder method for dynamic reorderings
            
        dyn_reorder_method = options.dyn_reorder_method.upper()
        dyn_reorder_method = re.sub('CUDD_','',dyn_reorder_method)
        dyn_reorder_method = re.sub('REORDER_','',dyn_reorder_method)
        dyn_reorder_method = re.sub('_CONVERGE','_CONV',dyn_reorder_method)
        
        self.__dyn_reorder_method = -1

        if dyn_reorder_method == "SAME":
            self.__dyn_reorder_method = dd.REORDER_SAME
        elif dyn_reorder_method == "NONE":
            self.__dyn_reorder_method = dd.REORDER_NONE
        elif dyn_reorder_method == "RANDOM":
            self.__dyn_reorder_method = dd.REORDER_RANDOM
        elif dyn_reorder_method == "RANDOM_PIVOT":
            self.__dyn_reorder_method = dd.REORDER_RANDOM_PIVOT
        elif dyn_reorder_method == "SIFT":
            self.__dyn_reorder_method = dd.REORDER_SIFT
        elif dyn_reorder_method == "SIFT_CONV":
            self.__dyn_reorder_method = dd.REORDER_SIFT_CONV
        elif dyn_reorder_method == "SYMM_SIFT":
            self.__dyn_reorder_method = dd.REORDER_SYMM_SIFT
        elif dyn_reorder_method == "SYMM_SIFT_CONV":
            self.__dyn_reorder_method = dd.REORDER_SYMM_SIFT_CONV
        elif dyn_reorder_method == "WINDOW2":
            self.__dyn_reorder_method = dd.REORDER_WINDOW2
        elif dyn_reorder_method == "WINDOW3":
            self.__dyn_reorder_method = dd.REORDER_WINDOW3
        elif dyn_reorder_method == "WINDOW4":
            self.__dyn_reorder_method = dd.REORDER_WINDOW4
        elif dyn_reorder_method == "WINDOW2_CONV":
            self.__dyn_reorder_method = dd.REORDER_WINDOW2_CONV
        elif dyn_reorder_method == "WINDOW3_CONV":
            self.__dyn_reorder_method = dd.REORDER_WINDOW3_CONV
        elif dyn_reorder_method == "WINDOW4_CONV":
            self.__dyn_reorder_method = dd.REORDER_WINDOW4_CONV
        elif dyn_reorder_method == "GROUP_SIFT":
            self.__dyn_reorder_method = dd.REORDER_GROUP_SIFT
        elif dyn_reorder_method == "GROUP_SIFT_CONV":
            self.__dyn_reorder_method = dd.REORDER_GROUP_SIFT_CONV
        elif dyn_reorder_method == "ANNEALING":
            self.__dyn_reorder_method = dd.REORDER_ANNEALING
        elif dyn_reorder_method == "GENETIC":
            self.__dyn_reorder_method = dd.REORDER_GENETIC
        elif dyn_reorder_method == "LINEAR":
            self.__dyn_reorder_method = dd.REORDER_LINEAR
        elif dyn_reorder_method == "LINEAR_CONV":
            self.__dyn_reorder_method = dd.REORDER_LINEAR_CONVERGE
        elif dyn_reorder_method == "EXACT":
            self.__dyn_reorder_method = dd.REORDER_EXACT
        else:
            self.println("WARNING: Specified unknown dynamic reordering method '%s'! Using NONE as default instead." % options.dyn_reorder_method)
            self.__dyn_reorder_method = dd.REORDER_NONE

            
        if options.dyn_reorder:
            dd.dd_autodyn_enable(dd.cvar.dd_manager, self.__dyn_reorder_method)
            dd.dd_autodyn_enable(self.__dd_manager, self.__dyn_reorder_method)
        else:
            dd.dd_autodyn_disable(dd.cvar.dd_manager)
            dd.dd_autodyn_disable(self.__dd_manager)
        

        if self.__verbose > 0:
            # FIXXME: Format this output more nicely
            self.println("Used the following command line options/parameters:")
            self.println(str(options) + " " +  str(self.__args))
        
        # "Declare" attributes, initialize them to empty values.
        self.__specification = None
        self.__winning_region = None
        self.__strategy = None
        self.__output_functions = None
        self.__code_generator = None
        self.__variables = []

       
    ######################################################################################
    ######################################################################################
    #
    # Access functions to various members/properties

    def get_verbose(self):
        return self.__verbose
    verbose = property(get_verbose)

    def get_dyn_reorder(self):
        return self.__options.dyn_reorder
    dyn_reorder = property(get_dyn_reorder)

    def get_mode(self):
        return self.__mode
    mode = property(get_mode)

    def get_language(self):
        return self.__language
    language = property(get_language)
    
    def get_cache_size(self):
        return self.__cache_size
    cache_size = property(get_cache_size)

    def get_update_sigs_size(self):
        return self.__update_sigs_size
    update_sigs_size = property(get_update_sigs_size)

    def get_num_class_vectors(self):
        return self.__num_class_vectors
    num_class_vectors = property(get_num_class_vectors)

    def get_dont_care_upper_bound(self):
        return self.__dont_care_upper_bound
    dont_care_upper_bound = property(get_dont_care_upper_bound)
    
    def get_check_combinations(self):
        return self.__check_combinations
    check_combinations = property(get_check_combinations)

    def get_partition(self):
        return self.__partition
    partition = property(get_partition)

    def get_var_order(self):
        return self.__options.var_order
    var_order = property(get_var_order)
    
    def get_reorder1(self):
        return self.__options.reorder1
    reorder1 = property(get_reorder1)
    r1 = reorder1

    def get_reorder2(self):
        return self.__options.reorder2
    reorder2 = property(get_reorder2)
    r2 = reorder2

    def get_kill(self):
        return self.__options.kill
    kill = property(get_kill)

    def get_transfer_functions(self):
        return self.__options.transfer_functions
    transfer_functions = property(get_transfer_functions)
    
    def get_dac04(self):
        return self.__options.dac04
    dac04 = property(get_dac04)

    def get_dac_recur_limit(self):
        return self.__dac_recur_limit
    dac_recur_limit = property(get_dac_recur_limit)

    def get_dac_call_limit(self):
        return self.__dac_call_limit
    dac_call_limit = property(get_dac_call_limit)

    def get_dac_search_mode(self):
        return self.__dac_search_mode
    dac_search_mode = property(get_dac_search_mode)
    
    def get_reorder_method(self):
        return self.__reorder_method
    reorder_method = property(get_reorder_method)
    
    def get_dyn_reorder_method(self):
        return self.__dyn_reorder_method
    dyn_reorder_method = property(get_dyn_reorder_method)
    
    def get_one_hot(self):
        return self.__options.one_hot
    one_hot = property(get_one_hot)
            
    def get_variables(self):
        return self.__variables[:]
    def set_variables(self, variables):
        self.__variables = variables[:]
    vars = property(get_variables, set_variables)
    
    def get_input_variables(self):
        return [var for var in self.__variables if var.type == marduk_utils.VariableType.INPUT]
    input_vars = property(get_input_variables)

    def get_output_variables(self):
        return [var for var in self.__variables if var.type == marduk_utils.VariableType.OUTPUT]
    output_vars = property(get_output_variables)

    def get_state_variables(self):
        return [var for var in self.__variables if var.type == marduk_utils.VariableType.STATE]
    state_vars = property(get_state_variables)

    def get_input_file_name(self):
        return self.__input_file
    input_file = property(get_input_file_name)
    

    def get_output_file_name(self):
        return self.__output_file
    output_file = property(get_output_file_name)

    def get_debug_mode(self):
        return self.__options.debug_mode
    debug_mode = property(get_debug_mode)

    def get_winning_region(self):
        return self.__winning_region
    def set_winning_region(self, winning_region):
        self.__winning_region = winning_region
    winning_region = property(get_winning_region, set_winning_region)

    def get_specification(self):
        return self.__specification
    def set_specification(self, specification):
        self.__specification = specification
    specification = property(get_specification, set_specification)

    def get_dd_manager(self):
        return self.__dd_manager
    dd_mgr = property(get_dd_manager)


    def add_variable(self, var):
        """
        Adds the given variable to the internal list of variables.
        This function can be used to add variables, which are not part
        of the initial specification, e.g. the state (jx) variables.

        If a variable with the given name already exists, an exception
        is thrown.
        """
        if var.name in [variable.name for variable in self.__variables]:
            raise MardukException(("Error: A variable with name '%s' already exists!" % var.name)) 
        self.__variables.append(var)

    def print_welcome_message():
        print "------------------------------------------------------"
        print "  Welcome to Marduk - The God who slaughtered Anzu! "
        print "------------------------------------------------------\n"
    
    print_welcome_message = staticmethod(print_welcome_message)
    
    def run(self):
        from nusmv import dd
        import marduk_utils
        import time

        start_wall_clock = time.clock()
        
        self.println("------------------------------------------------------")
        self.println("Synthesize " + str(self.input_file) +  " to " + str(self.output_file))
        if self.__options.mode != None:
            self.println("Mode: " + self.__options.mode.upper())
        if self.__options.language != None:
            self.println("Output Language: " + self.__options.language.upper())

        from datetime import datetime
        self.println("Start time: %s" % datetime.now().ctime())
            
        #print "Reordering status:", dd.dd_reordering_status(dd.cvar.dd_manager)
        
        self.println("\n Dynamic reordering \t\t\t\t\t" + str(self.dyn_reorder))
        self.println(" Reordering method for dynamic reordering \t\t" + marduk_utils.reorder_method_to_string(self.dyn_reorder_method))
        self.println(" Reordering method for forced reordering \t\t" + marduk_utils.reorder_method_to_string(self.reorder_method))
        self.println(" Reorder BDD after reading configuration \t\t" + str(self.r1))
        self.println(" Reorder BDD after generating output functions  \t" + str(self.r2))
        self.println(" Kill strategy and reorder afterwards   \t\t" + str(self.kill))
        self.println(" One-hot encoding of jx vars\t\t\t\t" + str(self.one_hot))
        self.println(" Transfer functions to new DD manager and reorder \t" + str(self.transfer_functions))
        self.println(" Generate functions according to\n Baneres, Cortadella, Kishinevsky (DAC'04)\t\t" + str(self.dac04))
        if self.dac04:
            if self.dac_search_mode == 'dfs':
                self.println(" DAC'04 search mode \t\t\t\t\tDepth First")
                self.println(" DAC'04 recursion depth limit\t\t\t\t" + str(self.dac_recur_limit))
            elif self.dac_search_mode == 'bfs':
                self.println(" DAC'04 search mode \t\t\t\t\tBreadth First")
                self.println(" DAC'04 call limit\t\t\t\t\t" + str(self.dac_call_limit))

        if self.__mode in (marduk_utils.Modes.IRRSOP, marduk_utils.Modes.FACTOR):
            if self.cache_size != None:
                self.println(" Function cache size \t\t\t\t\t" + str(self.cache_size))
            else:
                self.println(" Function cache size \t\t\t\t\tunlimited")
            self.println(" Number of class vectors \t\t\t\t" + str(self.num_class_vectors))
            self.println(" Number of new vectors for cache reorganization \t" + str(self.update_sigs_size))
            self.println(" Use don't care upper bound for ISoP_d \t\t\t" + str(self.dont_care_upper_bound))
            self.println(" Check combinations of 2 functions \t\t\t" + str(self.check_combinations))

        self._starttime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime
        
        self.println("\n Timing Information:")
        
        # Load specification from input file
        self.__specification = Specification(self)
        self.__specification.readSpecification()
        self._specificationtime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        self.println("   Specification read within\t\t\t %7.2f seconds" %(self._specificationtime-self._starttime))

        # Create list of variables and store it here in main class, for central access
        self.__variables = self.__specification.create_variable_list()

        if self.verbose > 1:
            print "Length of variables list: ", len(self.__variables)
            for var in self.__variables:
                print var

        if self.verbose > 1:        
            print "Current Ordering:"
            print marduk_utils.print_variable_ordering(self.vars)

        if self.var_order:
            self.println('    Forcing variable order: ' + self.var_order)
            marduk_utils.set_variable_ordering(self.var_order, self.vars, self.dd_mgr)
            
        if self.verbose > 1:
            print "Current Ordering:"
            print marduk_utils.print_variable_ordering(self.vars)
        
        # Compute winning region
        import sys    
        self.__winning_region = WinningRegion(self, self.__specification)
        self.__winning_region.calcWinningRegion()
        self._winningregiontime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime

        self.println("   Compute winning region within \t\t %7.2f seconds" %(self._winningregiontime - self._reorder1time))
        if(not(self.__winning_region.isRealizable())):
            self.println("The given specification is NOT REALIZABLE!\n")
            if not self.debug_mode:
                self.println("Use the argument --dm to debug unrealizability\n")
                return
            del self.__winning_region
            self.__spec_debugger = SpecDebugger(self)
            self.__spec_debugger.debug(self.debug_mode)
            return
        self.__winning_region_size = self.__winning_region.winRegion.size    

        
        # Compute strategy
        self.__strategy = Strategy(self)
        self.__strategy.calcStrategy()
        self._strategytime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        self.println("   Compute strategy within \t\t\t %7.2f seconds" %(self._strategytime-self._winningregiontime))

        from marduk_utils import VariableType

        self.println("\nStrategy Characterization:")
        input_vars = [var.ns for var in self.input_vars] + [var.ps for var in self.vars]
        output_vars = [var.ns for var in self.vars if var.type != VariableType.INPUT]
        begin = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        strat_char = marduk_utils.characterize_relation(self.__strategy.strategy_bdd, input_vars, output_vars, return_bdds=True)
        char_time = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime - begin
        self.println("(computed in %7.2f seconds)" % char_time)
        total = 2 ** strat_char['num_inputs']
        defined = (strat_char['num_defined'] / total) * 100
        fixed = (strat_char['num_fixed'] / total) * 100
        dc = (strat_char['num_dc'] / total) * 100
        non_dc = (strat_char['num_non_dc'] / total) * 100
        self.println("Defined:%7.2f%%" % defined)
        self.println("Fixed:\t %7.2f%%" % fixed)
        self.println("DC:\t %7.2f%%" % dc)
        self.println("Non-DC:\t %7.2f%%\n" % non_dc)

        strat_dc = strat_char['dc_bdd']
        del strat_char
        
        if self.__mode in (marduk_utils.Modes.COFACTOR, marduk_utils.Modes.OLD):
            self.do_cofactor_mode()
        else:
            self.do_function_generator_mode(strat_dc=strat_dc)


        if self.transfer_functions:
            self.println("   Transferred output functions within \t\t %7.2f seconds" % self.__code_generator._transfer_time)
            self.println("   Reordering transferred BDD took \t\t %7.2f seconds" % self.__code_generator._reorder_time)
        self.println("\n   Results in needed overall time of\t\t %7.2f seconds \n" %(self._codegentime - self._starttime))

        stop_wall_clock_time = time.clock()
        self.println("   Overall wall clock time\t\t\t %7.2f seconds" % (stop_wall_clock_time - start_wall_clock))

        self.println("\n BDD-Size Information:")
        self.println("   Size of Winning Region: \t\t %10d bdd-nodes" % self.__winning_region_size)
        self.println("   Size of rho1 is \t\t\t %10d bdd-nodes" %self.__strategy.rho1_size)
        self.println("   Size of rho2 is \t\t\t %10d bdd-nodes" %self.__strategy.rho2_size)
        self.println("   Size of rho3 is \t\t\t %10d bdd-nodes" %self.__strategy.rho3_size)

        self.println("------------------------------------------------------")
        self.println("                FINISHED synthesis!"            )
        self.println("------------------------------------------------------")

        if self.verbose > 1:
            print "Current Ordering:"
            print marduk_utils.print_variable_ordering(self.vars)
        
        
        # The following should be the last block in the run method:
        self.__code_generator.append_comment(self.__printed_lines)
        # Killing references to other objects, break up circular references
        self.__specification = None
        self.__winning_region = None
        self.__strategy = None
        self.__output_functions = None
        self.__code_generator = None
        

#-------------------------------------------------------------------------------------------------------------------
    def do_cofactor_mode(self):
        # Compute output functions
        self.__output_functions = OutputFunctions(self, self.__winning_region, self.__strategy)

        if not self.dac04:
            #new_rel =
            self.__output_functions.constructFunctions()
        else:
            new_rel = self.__output_functions.constructFunctionsDAC04(recur_limit=self.dac_recur_limit, call_limit=self.dac_call_limit,
                                                                      bfs=(self.dac_search_mode == 'bfs'))

        self._size_gen_strat = None # new_rel.size
        self._outputfcttime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime
        self._reorder2time = self._outputfcttime
        self._killingtime = self._outputfcttime
        self.println("   Compute output functions within \t\t %7.2f seconds" %(self._outputfcttime - self._strategytime))
        if self.reorder2:
            result = dd.dd_reorder(self.__dd_manager, self.reorder_method,0)
            self._reorder2time = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
            self.println("   Second reordering of bdd takes \t\t %7.2f seconds" %(self._reorder2time - self._outputfcttime))

        if self.kill:
            self.__strategy.killStrategy()
            dd.dd_reorder(self.__dd_manager, self.reorder_method,0)
            self._killingtime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime
            self.println("   Killing strat and reordering takes\t\t %7.2f seconds" %(self._killingtime - self._reorder2time))

        before_code_gen = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime
       
        if not self.mode == marduk_utils.Modes.OLD:    
            if self.language == marduk_utils.Languages.BLIF:
                self.__code_generator = BlifFromGatesGenerator(self.output_file)
            elif self.language == marduk_utils.Languages.HIF:
                self.__code_generator = HifGenerator(self.output_file)
            elif self.language == marduk_utils.Languages.VERILOG:
	        self.__code_generator = VerilogGenerator(self.output_file)
	
	
            dd.dd_autodyn_disable(dd.cvar.dd_manager)
            dd.dd_autodyn_disable(self.__dd_manager)
            self.__code_generator.convert_functions_to_gates(self, self.__output_functions, self.__dd_manager) 
        else:
            self.__code_generator = BlifGenerator(self, self.__output_functions)   
        
        self.__code_generator.write_code_to_file()
        self._codegentime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime
        self.println("   Code generation takes \t\t\t %7.2f seconds" %(self._codegentime - before_code_gen))
        return

#---------------------------------------------------------------------------------------------------------------------
    def do_function_generator_mode(self, strat_dc=None):

        if self.dac04:
            raise MardukException("ERROR! DAC'04 function generation is not implemented (yet) for function-generator mode!")
        
        # Compute output functions
        import sys
        self.__output_functions = OutputFunctions(self, self.__winning_region, self.__strategy)
        self.__code_generator = self.__output_functions.constructFunctionsUsingGenerator(strat_dc=strat_dc)
        
        self._outputfcttime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        self.println("   Compute output functions within \t\t %7.2f seconds" %(self._outputfcttime - self._strategytime))
        if self.reorder2:
            self.println("WARNING: Using --reorder2 in IrrSOP mode just takes time and has no merit.")
            result = dd.dd_reorder(self.__dd_manager, self.reorder_method,0)
            self._reorder2time = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
            self.println("   Second reordering of bdd takes \t\t %7.2f seconds" %(self._reorder2time - self._outputfcttime))
        self._reorder2time = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime 
        if self.kill:
            self.println("WARNING: Using --kill in IrrSOP mode just takes time and has no merit."            )
            self.__strategy.killStrategy()
            dd.dd_reorder(self.__dd_manager, self.reorder_method,0)
            self._killingtime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime
            self.println("   Killing strat and reordering takes\t\t %7.2f seconds" %(self._killingtime - self._reorder2time))
        
        self.__code_generator.write_code_to_file()
        self._codegentime = resource.getrusage(resource.RUSAGE_SELF).ru_utime + resource.getrusage(resource.RUSAGE_SELF).ru_stime

        return

    def println(self, line):
        print line
        self.__printed_lines.append(line)
Esempio n. 22
0
 def setUp(self):
     from decimal import Decimal                     # noqa
     self.spec = Specification("x == Decimal('5.4')",
                               candidate_name='x')
Esempio n. 23
0
class BlacKnightClient(object):
    """
    The client that runs on every host in a BlacKnight-based appliance.

    This class wraps the ZooKeeper client around which BlacKnight is built. The clients are perpetually engaged in a leader election which is initiaited by the :func:`run` method. The current leader is responsible for appliance monitoring and remediation. When a leader is elected it calls the :func:`lead`.
    """
    # ZooKeeper paths
    zk_path = '/blacknight'
    spec_znode = zk_path + '/spec.yaml'
    elect_path = zk_path + '/elect'
    lock_path = zk_path + '/lock'
    barrier_path = zk_path + '/barrier'
    ensemble_path = zk_path + '/ensemble'
    services_path = zk_path + '/services'
    unused_hosts_path = services_path + '/unused_hosts'
    hosts_path = zk_path + '/hosts'
    args_path = zk_path + '/args'

    def __init__(self, port):
        # TODO: figure out why this docstring disappears
        """
        Initialize a client to run on a host.

        :param port: port on which local ZooKeeper server is running

        :type: port: string
        """
        self.logger = logging.getLogger('blacknight.client')
        self.local_zk = 'localhost' + ':' + str(port)

        # Start the ZK client
        self.logger.debug('Connecting to ZooKeeper at {}'.format(self.local_zk))
        self.client = KazooClient(self.local_zk)
        self.client.start()

        # Load the appliance specification
        # TODO: handle no spec in ZooKeeper (barrier before run?)
        @self.client.DataWatch(BlacKnightClient.spec_znode)
        def watch_spec(data, stat):
            if data:
                self.logger.debug('Reloading spec.yaml')
                self.spec = Specification(data)
                self.logger.debug('Parsed specification')
            else:
                self.spec = None
                self.logger.warn('Specification not found in {}'.format(BlacKnightClient.spec_znode))

        # Get synchronization info
        self.election = self.client.Election(BlacKnightClient.elect_path)
        self.lock = self.client.Lock(BlacKnightClient.lock_path)
        self.barrier = self.client.Barrier(BlacKnightClient.barrier_path)

    def run(self):
        """
        Add this client to the election.

        After calling this method, the client should either be the leader or blocked in the election.
        """
        # TODO: check client and spec before running
        self.logger.debug('Joining election')
        self.election.run(self.lead)

    def lead(self):
        """
        Called when this client is elected leader.

        This function monitors the appliance by registering a watcher on the *services* node. Each service keeps an ephemeral

        WRITEME
        """
        self.logger.debug('Elected leader')

        self.client.ensure_path(BlacKnightClient.args_path)
        self.client.ensure_path(BlacKnightClient.services_path)

        # TODO: should we set allow_session_lost=True for this watcher?
        @self.client.ChildrenWatch(BlacKnightClient.services_path)
        def watch_services(children):

            # Perform remediation under lock in case a watcher from a previous
            # leader hasn't been cleared for some reason
            with self.lock:

                self.logger.debug('Detected change')

                # TODO: find a better way to wait for ephemeral nodes to vanish
                sleep(2)
                # TODO: reconfigure ZooKeeper
                # ensemble = self._client.get_children(event.path)
                # ensemble = reduce(lambda a, b: a + ',' + b, ensemble)
                # self._client.reconfig('', '', ensemble)

                # Query appliance state and remediate if necessary
                services, args = self.query()
                actions = self.spec.diff(services)
                self.logger.debug('Actions: {}'.format(actions))
                for action in actions:
                    action.run(services, args)

            # The barrier must be reset every time the watcher is triggered
            self.barrier.remove()

        # Wait behind a barrier for a watcher to be triggered
        while True:
            self.barrier.create()
            self.barrier.wait()

    def query(self):
        """
        Retrieve the current state of the appliance.

        This method surveys the ``/blacknight/service/`` znode to construct the current applinace state. The services are returned as a dictionary mapping each role to a list of services. The arguments (global configuration parameters such as secret keys) are a returned as a dictionary mapping each argument key to its value.

        :return: services, args
        :rtype: Tuple({string: []}, {string: string})
        """
        services = {}
        children = self.client.get_children(BlacKnightClient.services_path)
        for role in children:
            role_path = BlacKnightClient.services_path + '/' + role
            services[role] = self.client.get_children(role_path)

        # Get current appliance configuration
        args = {}
        children = self.client.get_children(BlacKnightClient.args_path)
        for arg in children:
            path = BlacKnightClient.args_path + '/' + arg
            value, stat = self.client.get(path)
            args[arg] = value

        return services, args