Ejemplo n.º 1
0
 def test_monitor_with_delay_model(self):
     m = Monitor("test/test_py-monitor-delay-simple.pl", 'x')
     # delayed step function (x1 is slower than a1)
     i0 = Itoms([Itom('a1', 0, variable='a'), Itom('x1', 0, variable='x')])
     i1 = Itoms([Itom('a1', 1, variable='a'), Itom('x1', 0, variable='x')])
     i2 = Itoms([Itom('a1', 1, variable='a'), Itom('x1', 1, variable='x')])
     failed = m.monitor(i0)
     self.assertEqual(failed, None)
     failed = m.monitor(i0)
     self.assertEqual(failed, None)
     failed = m.monitor(i1)
     self.assertEqual(failed, None)
     # x1 (value is still 0) doesn't follow a1 (v=1)
     failed = m.monitor(i1)
     self.assertNotEqual(failed, None)
     failed = m.monitor(i2)
     self.assertEqual(failed, None)
     # delay = 2 timesteps
     m = Monitor("test/test_py-monitor-delay-general.pl", 'x')
     failed = m.monitor(i0)
     self.assertEqual(failed, None)
     failed = m.monitor(i0)
     self.assertEqual(failed, None)
     failed = m.monitor(i1)
     self.assertEqual(failed, None)
     failed = m.monitor(i1)
     self.assertEqual(failed, None)
     failed = m.monitor(i1)
     self.assertNotEqual(failed, None)
     failed = m.monitor(i2)
     self.assertEqual(failed, None)
Ejemplo n.º 2
0
    def execute(self, itoms):
        """Executes the function given the itoms.

        itoms -- 'Itoms' object, list or dictionary of itoms

        """
        # make sure its an Itoms-object
        itoms = Itoms(itoms)
        # verify inputs
        if not set([v.name for v in self.__vin]).issubset(
                set([v.name for v in itoms.values()])):
            raise RuntimeError("Missing itoms to execute the function.")
        # generate code
        code = self.__enclosed_code()
        # execute code
        itom_vars = {i.codename: i for i in itoms.values()}
        self.__locals.update(itom_vars)
        exec(code, {
            'Itom': Itom,
            'copy': copy,
            'interval': interval
        }, self.__locals)
        # local_vars may include utils and functions
        # -> keep only inputs and output
        itoms[self.vout.name] = self.__locals[self.vout.name]
        return itoms
Ejemplo n.º 3
0
 def __recollect(self, itoms):
     itoms = Itoms(itoms)
     recollected = False
     if self.__substitutions is None \
        or set(itoms.keys()) != set(self.__itoms.keys()):
         self.__substitutions = self.__collect_substitutions(itoms)
         recollected = True
     return recollected
Ejemplo n.º 4
0
 def test_execute(self):
     f = Function('a', ['b', 'c'], "a.v = b.v + c.v", name="add")
     a = Itom('a', 0)
     b = Itom('b', 1)
     c = Itom('c', 2)
     itoms = Itoms([a, b, c])
     v = f.execute(itoms)
     self.assertAlmostEqual(v['a'].v, 3)
     b.v = 4
     c.v = 2
     v = f.execute(itoms)
     self.assertAlmostEqual(v['a'].v, 6)
     a.v = 0
     b.v = 5
     c.v = 5
     v = f.execute(itoms)
     self.assertAlmostEqual(v['a'].v, 10)
     with self.assertRaises(Exception):
         f.execute({a.name: a})
     with self.assertRaises(Exception):
         f.execute({b.name: b})
     # test execution without wrapping the code in a function
     f = Function('a', ['b', 'c'],
                  "a.v = b.v + c.v",
                  name="add",
                  wrap=False)
     b.v = 1
     c.v = 2
     v = f.execute(itoms)
     self.assertAlmostEqual(v['a'].v, 3)
     # function setting timestamp
     f = Function('a', ['b', 'c'],
                  "a.v = b.v + c.v; a.t = max(b.t, c.t)",
                  name="add")
     b.t = 0
     c.t = 1
     v = f.execute(itoms)
     self.assertEqual(v['a'].t, 1)
     # test execution with non-Python-identifiers as variables
     b = Itom('0b', 1)
     c = Itom('1c', 2)
     f = Function('a', [b.name, c.name],
                  "a.v = {}.v + {}.v".format(b.codename, c.codename))
     v = f.execute(Itoms([b, c]))
     self.assertAlmostEqual(v['a'].v, 3)
     # function with lists (e.g., ROS itoms representing point clouds)
     sonar = Itom('/p2os/sonar', [1, 3, 4])
     f = Function('dmin', [sonar.name],
                  "dmin.v = min({}.v)".format(sonar.codename))
     v = f.execute(Itoms([sonar]))
     self.assertAlmostEqual(v['dmin'].v, 1)
Ejemplo n.º 5
0
 def __collect_substitutions(self, itoms=[]):
     """Find relations from variables (given itoms) to domain."""
     program = "\n"
     if "itomsOf" not in self.__pli.program and len(itoms) > 0:
         # be sure itoms is of the right type 'Itoms'
         itoms = Itoms(itoms)
         # append available itoms to program with "itomsOf(variable,[itom1,..])"
         for variable, il in itoms.availability.items():
             assert variable is not None and variable != ""
             names = [i.name for i in il]
             program += "itomsOf({},[{}]).\n".format(variable, ','.join(names))
         program += "\n"
     if len(itoms) > 0:
         assert "itomsOf" in program or "itomsOf" in self.__pli.program
     # get all valid substitutions for the domain
     # -> query problog knowledge base
     program += "query(substitution({},S)).".format(self.__domain)
     result = self.__pli.evaluate(program)
     S = []
     for r in result.keys():
         s = self.__pli.parse_substitution(str(r))
         S.append(s)
     if len(itoms) == 0:
         # set itoms used (default value)
         for s in S:
             for v in s.vin:
                 self.__itoms[v.name] = Itom(v.name, 0.0, variable=v.name)
     return S
Ejemplo n.º 6
0
 def test_execute_with_interval(self):
     f = Function('a', ['b', 'c'], "a.v = b.v + c.v", name="add")
     b = Itom('b', interval([0.5, 1.5]))
     c = Itom('c', interval([1, 3]))
     o = f.execute(Itoms([b, c]))
     self.assertEqual(o['a'].v, interval([1.5, 4.5]))
     # mix interval arithmetic with scalars
     b = Itom('b', 1)
     o = f.execute(Itoms([b, c]))
     self.assertEqual(o['a'].v, interval([2, 4]))
     # timestamps are intervals
     code = "a.v = b.v + c.v" + "\n" + "a.t = b.t & c.t"
     f = Function('a', ['b', 'c'], code, name="add")
     b = Itom('b', 1, interval([0.1, 0.2]))
     c = Itom('c', 2, interval([0.15, 0.25]))
     o = f.execute(Itoms([b, c]))
     self.assertEqual(o['a'].v, 3)
     self.assertEqual(o['a'].t, interval([0.15, 0.2]))
Ejemplo n.º 7
0
 def test_implementation_multiline(self):
     self.__pli.reset()
     self.__pli.load("test/test_py-implementation-multiline.pl")
     result = self.__pli.evaluate("query(implementation(r1, X)).")
     relation, code = self.__pli.parse_implementation(list(result)[0])
     self.assertEqual(relation, "r1")
     # create function to execute
     f = Function('a', 'b', code, name='r1')
     itoms = f.execute(Itoms([Itom('b', 1, timestamp=0, variable='b')]))
     self.assertEqual(itoms['a'].v, 2)
     self.assertEqual(itoms['a'].t, 0)
     # execute through substitution
     S = self.__get_substitutions("query(substitution(a,S)).")
     itoms = Itoms([Itom('b1', 1, timestamp=0, variable='b')])
     outputs = self.__execute_substitutions(S, itoms)
     s = list(S)[0]
     self.assertEqual(outputs[s]['a'].v, 2)
     self.assertEqual(outputs[s]['a'].t, 0)
Ejemplo n.º 8
0
 def test_availability(self):
     a1 = Itom('a1', 0, variable='a')
     a2 = Itom('a2', 1, variable='a')
     b1 = Itom('b1', 2.1, variable='b')
     itoms = Itoms([a1, a2, b1])
     av = itoms.availability
     self.assertEqual(len(av.keys()), 2)
     self.assertEqual(len(av['a']), 2)
     self.assertTrue('a1' in [itom.name for itom in av['a']])
     self.assertEqual(len(av['b']), 1)
Ejemplo n.º 9
0
 def test_execute(self):
     s = Substitution([self.__f_add, self.__f_mult])
     b = Itom('b', 1)
     c = Itom('c', 2)
     itoms = Itoms(list=[b, c])
     variables = s.execute(itoms)
     self.assertEqual(variables['d'].v, 6)
     # function names not unique
     s = Substitution([self.__f_add, self.__f_add2])
     variables = s.execute([b, c])
     self.assertEqual(variables['a'].v, 3)
Ejemplo n.º 10
0
 def setUp(self):
     self.__itoms1 = Itoms([
         Itom('x1', 10, variable='x'),
         Itom('x2', 10.01, variable='x'),
         Itom('a1', 5, variable='a'),
         Itom('b1', 5.1, variable='b'),
         Itom('c1', 4.95, variable='c'),
         Itom('d1', 19, variable='d'),
     ])
     # no error (all intervals intersect in the common domain)
     self.__itoms2 = Itoms([
         Itom('x1', interval([9, 11]), variable='x'),
         Itom('a1', interval([4.9, 5.1]), variable='a'),
         Itom('d1', interval([19.5, 20.5]), variable='d'),
     ])
     # error (d1)
     self.__itoms2_err = Itoms([
         Itom('x1', interval([9, 11]), variable='x'),
         Itom('a1', interval([4.9, 5.1]), variable='a'),
         Itom('d1', interval([23, 25]), variable='d'),
         # error because: 9..11 does not inersect with 11.5..12.5
     ])
Ejemplo n.º 11
0
    def __init__(self, model, domain, itoms=[], librarypaths=["./model/"],
                 recollect=True):
        """Initialize the monitor.

        model -- SHSA knowledge base collecting the relations between
            variables.
        domain -- Common domain (a variable in the knowledge base) where the
            itoms will be compared to each other.
        itoms -- Itoms-object holding inputs to the monitor.
        librarypaths -- Set paths of problog libraries used in model.
        filter_window_size -- Set the size of the window for the median filter.

        """
        self.__pli = ProblogInterface(librarypaths=librarypaths)
        self.__pli.load(model)
        """SHSA knowledge base."""
        self.__domain = domain
        """Variable domain where the itoms shall be compared."""
        self.__recollect_enabled = recollect
        """Indicates that a change in the itoms should trigger a re-query of the
        substitutions."""
        self.__itoms = Itoms(itoms)
        """Available itoms or last itoms monitored.
        Used to identify a change in the itoms."""
        self.__substitutions = None
        """List of substitutions used to bring the itoms into the common domain."""
        # workaround: for ROS monitor (subscribe based on model)
        try:
            self.__substitutions = self.__collect_substitutions(itoms)
            # workaround: triggers reset on first monitor (necessary to fully initialize)
            self.__itoms = Itoms(itoms)
        except problog.engine.UnknownClause as e:
            # no itomsOf in the problog model (needed to find substitutions)
            # we will try later (monitor)
            pass
        # debugging
        self._debug_callback = None
        """Called at the end of monitor(.) to debug the monitor step."""
Ejemplo n.º 12
0
    def execute(self, itoms):
        """Execute the substitution and returns all variables.

        itoms -- dictionary of itom-name->'Itom'-object. These will be passed
          as local variables to the functions.

        Passes itoms through the functions. Output variables of functions may
        be appended (variable-name->'Itom'-object). However, the last variable
        assigned is 'this.vout' which is the result of the substitution given
        the inputs 'itoms'. The value (and possibly a timestamp) of 'this.vout'
        can be retrieved from the returned variables ('this.vout.v').

        """
        # make sure its an Itoms-object
        itoms = Itoms(itoms)
        # verify inputs
        if not set([v.name for v in self.vin]).issubset(
                set([v.name for v in itoms.values()])):
            raise RuntimeError("Missing itoms to execute the substitution.")
        # execute function after function
        for f in self:
            itoms = f.execute(itoms)
        return itoms
Ejemplo n.º 13
0
 def test_time_uncertainty(self):
     m = Monitor("test/test_py-monitor-simple.pl", 'x')
     # itoms with uncertainties in time
     iok = Itoms([
         Itom('x1',
              interval([9, 11]),
              timestamp=interval([0.1, 0.2]),
              variable='x'),
         Itom('a1',
              interval([5, 6]),
              timestamp=interval([0.15, 0.25]),
              variable='a'),
         Itom('b1',
              interval([4, 8]),
              timestamp=interval([0.1, 0.3]),
              variable='b'),
     ])
     failed = m.monitor(iok)
     self.assertEqual(failed, None)
     # some itoms timestamps do not overlap
     ilate = Itoms([
         Itom('x1',
              interval([9, 11]),
              timestamp=interval([0.0, 0.09]),
              variable='x'),
         Itom('a1',
              interval([5, 6]),
              timestamp=interval([0.15, 0.25]),
              variable='a'),
         Itom('b1',
              interval([4, 8]),
              timestamp=interval([0.1, 0.3]),
              variable='b'),
     ])
     failed = m.monitor(ilate)
     self.assertEqual(failed, None)
Ejemplo n.º 14
0
 def test_timestamp_model(self):
     m = Monitor("test/test_py-monitor-timestamp-simple.pl", 'c')
     self.assertEqual(m.buffer_size, 1)
     a1 = Itom('a1', 1, interval([0.11, 0.21]), variable='a')
     b1 = Itom('b1', 2, interval([0.12, 0.22]), variable='b')
     c1 = Itom('c1', 3, interval([0.05, 0.15]), variable='c')
     c2 = Itom('c2', 3, interval([0.14, 0.24]), variable='c')
     failed = m.monitor(Itoms([a1, b1, c1, c2]))
     self.assertEqual(failed, None)
     # wrong value, however time stamp do not overlap -> won't be used for comparison
     c1_late = Itom('c1', 0, interval([0.0, 0.04]), variable='c')
     failed = m.monitor(Itoms([a1, b1, c1_late, c2]))
     self.assertEqual(failed, None)
     # monitor shall compensate late itoms -> increase buffer size
     m = Monitor("test/test_py-monitor-timestamp-simple.pl",
                 'c',
                 buffer_size=2)
     self.assertEqual(m.buffer_size, 2)
     failed = m.monitor(Itoms([c1, c2]))
     failed = m.monitor(Itoms([c1_late, c2]))
     # another late value but wrong itom arrives
     c2_wrong = Itom('c2', 1, interval([0.0, 0.03]), variable='c')
     failed = m.monitor(Itoms([c1, c2_wrong]))
     self.assertNotEqual(failed, None)
Ejemplo n.º 15
0
 def test_implementation_simple(self):
     self.__pli.load("test/test_py-implementation-simple.pl")
     S = self.__get_substitutions("query(substitution(x,S)).")
     # create some dummy data
     x1 = Itom('x1', 2, variable='x')
     x2 = Itom('x2', 2, variable='x')
     a1 = Itom('a1', 1, variable='a')
     b1 = Itom('b1', 1, variable='b')
     c1 = Itom('c1', 1, variable='c')
     d1 = Itom('d1', 4, variable='d')
     itoms = Itoms([x1, x2, a1, b1, c1, d1])
     # execute substitutions
     outputs = self.__execute_substitutions(S, itoms)
     # check
     for output_itoms in outputs.values():
         self.assertAlmostEqual(output_itoms['x'].v, 2)
Ejemplo n.º 16
0
def bring_to_common_domain(S, itoms):
    """Apply substitutions to itoms.

    Returns values. Values is an ordered dictionary of substitution->itom
    (Itoms with key=substitution).

    """
    output = Itoms()
    for i, s in enumerate(S):
        try:
            result = s.execute(itoms)
            output[s] = result[variable]
        except Exception as e:
            print("Execution failed - value ignored. {}".format(e))
            raise e
    return output
Ejemplo n.º 17
0
 def test_init_itoms(self):
     empty = Itoms()
     a = Itom('a', 0)
     b = Itom('b', 1, variable='b')
     c = Itom('c', 2.1)
     l = Itoms(list=[a, b, c])
     self.assertEqual(len(l), 3)
     self.assertEqual(l['a'].v, 0)
     l = Itoms([a, b, c])
     self.assertEqual(len(l), 3)
     self.assertEqual(l['b'].v, 1)
     # try different initial iterables and keys
     l = Itoms({1: a, 2: b, 3: c})
     self.assertEqual(len(l), 3)
     self.assertEqual(l[1], a)
     l = Itoms(set([a, b, c]))
     self.assertEqual(len(l), 3)
     self.assertTrue(c in l.values())
     # start from empty dict
     l = Itoms()
     l['av'] = a
     self.assertEqual(len(l), 1)
     self.assertEqual(l['av'], a)
Ejemplo n.º 18
0
class BaseMonitor(object):
    """Base class for monitors."""

    def __init__(self, model, domain, itoms=[], librarypaths=["./model/"],
                 recollect=True):
        """Initialize the monitor.

        model -- SHSA knowledge base collecting the relations between
            variables.
        domain -- Common domain (a variable in the knowledge base) where the
            itoms will be compared to each other.
        itoms -- Itoms-object holding inputs to the monitor.
        librarypaths -- Set paths of problog libraries used in model.
        filter_window_size -- Set the size of the window for the median filter.

        """
        self.__pli = ProblogInterface(librarypaths=librarypaths)
        self.__pli.load(model)
        """SHSA knowledge base."""
        self.__domain = domain
        """Variable domain where the itoms shall be compared."""
        self.__recollect_enabled = recollect
        """Indicates that a change in the itoms should trigger a re-query of the
        substitutions."""
        self.__itoms = Itoms(itoms)
        """Available itoms or last itoms monitored.
        Used to identify a change in the itoms."""
        self.__substitutions = None
        """List of substitutions used to bring the itoms into the common domain."""
        # workaround: for ROS monitor (subscribe based on model)
        try:
            self.__substitutions = self.__collect_substitutions(itoms)
            # workaround: triggers reset on first monitor (necessary to fully initialize)
            self.__itoms = Itoms(itoms)
        except problog.engine.UnknownClause as e:
            # no itomsOf in the problog model (needed to find substitutions)
            # we will try later (monitor)
            pass
        # debugging
        self._debug_callback = None
        """Called at the end of monitor(.) to debug the monitor step."""

    @property
    def model(self):
        """Returns the underlying SHSA model."""
        return self.__pli.program

    @property
    def domain(self):
        """Returns the monitoring domain."""
        return self.__domain

    @property
    def substitutions(self):
        """Returns the list of substitutions used to bring the itoms into the common
        domain."""
        return self.__substitutions

    def update(self, model, domain):
        """Resets the model and the domain, i.e., variable to monitor."""
        self.__domain = domain
        self.__pli.reset()
        self.__pli.load(model)

    def set_debug_callback(self, fct):
        self._debug_callback = fct
        return

    def __collect_substitutions(self, itoms=[]):
        """Find relations from variables (given itoms) to domain."""
        program = "\n"
        if "itomsOf" not in self.__pli.program and len(itoms) > 0:
            # be sure itoms is of the right type 'Itoms'
            itoms = Itoms(itoms)
            # append available itoms to program with "itomsOf(variable,[itom1,..])"
            for variable, il in itoms.availability.items():
                assert variable is not None and variable != ""
                names = [i.name for i in il]
                program += "itomsOf({},[{}]).\n".format(variable, ','.join(names))
            program += "\n"
        if len(itoms) > 0:
            assert "itomsOf" in program or "itomsOf" in self.__pli.program
        # get all valid substitutions for the domain
        # -> query problog knowledge base
        program += "query(substitution({},S)).".format(self.__domain)
        result = self.__pli.evaluate(program)
        S = []
        for r in result.keys():
            s = self.__pli.parse_substitution(str(r))
            S.append(s)
        if len(itoms) == 0:
            # set itoms used (default value)
            for s in S:
                for v in s.vin:
                    self.__itoms[v.name] = Itom(v.name, 0.0, variable=v.name)
        return S

    def __recollect(self, itoms):
        itoms = Itoms(itoms)
        recollected = False
        if self.__substitutions is None \
           or set(itoms.keys()) != set(self.__itoms.keys()):
            self.__substitutions = self.__collect_substitutions(itoms)
            recollected = True
        return recollected

    def _monitor(self, itoms, reset=False):
        raise NotImplementedError

    def monitor(self, itoms):
        reset = False
        if self.__recollect_enabled:
            # recollect substitutions if itoms changed
            reset = self.__recollect(itoms)
            self.__itoms = itoms  # save to identify changes in the next monitor step
        # monitor implemented in sub class
        failed = self._monitor(itoms, reset)
        # done
        return failed
Ejemplo n.º 19
0
 def __execute_substitutions(self, S, itoms):
     output = Itoms()
     for i, s in enumerate(S):
         output[s] = s.execute(itoms)
     return output
Ejemplo n.º 20
0
    'b1': 1,
    'c1': 1,
    'd1': 1,
}

#
# get the available itoms
#

try:
    data = pd.read_csv(args.csv)
except Exception as e:
    raise SystemExit("Failed to parse csv. {}".format(e))

# get variable/itoms available from column name (header) 'variable:itom'
itoms = Itoms()
try:
    for head in data.columns.values:
        head = head.strip().split(':')
        v = head[0]
        i = head[1]
        # empty value and timestamp for this itom describing the header only
        itom = Itom(i, None, variable=v, timestamp=None)
        itoms[itom.name] = itom
except Exception as e:
    raise SystemExit(
        "Failed to parse column name 'variable:itom'. {}".format(e))

# problog knows the mapping now, so we can change the column names to itoms only
# substitution only needs itom names
data.columns = itoms.keys()