class ImplementationTestCase(unittest.TestCase):
    """Test cases for implementation clauses in a pl-file."""

    def setUp(self):
        self.__pli = ProblogInterface(librarypaths=["model/"])

    def tearDown(self):
        self.__pli = None

    def __get_substitutions(self, query):
        result = self.__pli.evaluate(query)
        S = []
        for k, v in result.items():
            if v == 0.0:
                continue
            s = self.__pli.parse_substitution(str(k))
            S.append(s)
        return S

    def __execute_substitutions(self, S, itoms):
        output = Itoms()
        for i, s in enumerate(S):
            output[s] = s.execute(itoms)
        return output

    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)

    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)
Beispiel #2
0
 def test_evaluate(self):
     pli = ProblogInterface(["test/test_shsa.pl"], ["model/"])
     # evaluate all queries in test_shsa.pl
     # (testcase -> should all return true)
     result = pli.evaluate()
     self.assertEqual(sum(result.values()), len(result.values()))
     # program without queries
     pli.reset()
     pli.append("itom(a).")
     # evaluate a query without adding it to the program
     result = pli.evaluate("query(itom(X)).")
     self.assertEqual(len(result), 1)
Beispiel #3
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."""
Beispiel #4
0
 def _monitor(self, itoms, reset=False):
     # calculate error between substitutions
     error, overlap, outputs, values = self._compare(itoms, reset)
     match = self._match(error)
     assert np.equal(match, match.transpose()).all()
     pli = ProblogInterface(librarypaths=[])
     assert len(match) == 3
     pli.load("model/vote3.pl")
     program = ""
     for i in range(0,len(match)):
         for j in range(i+1,len(match)):
             m = str(match[i, j]).lower()
             program += "evidence(match(s{},s{}), {}).\n".format(i, j, m)
     for i in range(len(match)):
         program += "query(failed(s{}, s{}, s{})).\n".format(i, (i+1)%3, (i+2)%3)
     result = pli.evaluate(program)
     probs = result.values()  # probabilities
     # return substitution with highest failure probability
     failed = None
     if min(probs) > 0.49:  # 0.5 .. no idea if a failure occured or not
         idx = list(probs).index(max(probs))
         failed = self.substitutions[idx]
     return failed
 def setUp(self):
     self.__pli = ProblogInterface(librarypaths=["model/"])
Beispiel #6
0
                    nargs='*',
                    help="""Path to ProbLog files to include.""")
parser.add_argument('model',
                    type=str,
                    help="""SHSA model in Prolog/ProbLog.""")
parser.add_argument('csv',
                    type=str,
                    help="""CSV file of itoms. Header must match the itom names
                    in the model.""")
args = parser.parse_args()

#
# load the model
#

pli = ProblogInterface(librarypaths=args.include)
pli.load(args.model)

# define epsilon for itoms (static)
epsilon = {
    't_clock': 0,
    'x1': 1,
    'x2': 1,
    'a1': 1,
    'b1': 1,
    'c1': 1,
    'd1': 1,
}

#
# get the available itoms
Beispiel #7
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
Beispiel #8
0
 def test_init(self):
     pli = ProblogInterface()
     self.assertEqual(pli.program, "")
     pli.load("test/test_lists.pl")
     self.assertNotEqual(pli.program, "")
     pli = ProblogInterface(["test/test_shsa.pl"], ["model/"])
     self.assertNotEqual(pli.program, "")
     pli.reset()
     self.assertEqual(pli.program, "")
     pli.append("query(itom(X)).")
     self.assertNotEqual(pli.program, "")
     with self.assertRaises(Exception):
         problog = ProblogInterface("test")
Beispiel #9
0
 def test_parse_substitution(self):
     pli = ProblogInterface()
     s = pli.parse_substitution("substitution(a,a1)")
     self.assertEqual(len(s), 1)
     self.assertEqual(set([v.name for v in s.vin]), set(['a1']))
     # simple tests
     pli.append('implementation(r1,"a = b + c").')
     pli.append('implementation(r2,"c = 2 * d").')
     pli.append(
         'implementation(rstep,"a.v = (t - a_last.t)*0.1 + a_last.v").')
     s = pli.parse_substitution(
         "substitution(a, [function(a,r1,[b,c]), b1, c1] )")
     self.assertEqual(len(s), 3)
     self.assertEqual(s.vout.name, 'a')
     self.assertEqual(set([v.name for v in s.vin]), set(['b1', 'c1']))
     s = pli.parse_substitution(
         "substitution(a, [function(a,r1,[b,c]), b1, [function(c,r2,[d]),d1]] )"
     )
     self.assertEqual(len(s), 4)
     self.assertEqual(s.vout.name, 'a')
     self.assertEqual(set([v.name for v in s.vin]), set(['b1', 'd1']))
     s = pli.parse_substitution(
         "substitution(a, [function(a,rstep,[t, a_last]), t_clock, a1_last] )"
     )
     self.assertEqual(len(s), 3)
     self.assertEqual(s.vout.name, 'a')
     self.assertEqual(set([v.name for v in s.vin]),
                      set(['t_clock', 'a1_last']))
     # strings as identifiers
     pli.append('implementation(rds,"dmin.v = min(sonar.v)").')
     s = pli.parse_substitution(
         'substitution(dmin,[function(dmin,rds,[sonar]), "/p2os/sonar"])')
     self.assertEqual(len(s), 2)
     self.assertEqual(s.vout.name, 'dmin')
     self.assertEqual(set([v.name for v in s.vin]), set(['/p2os/sonar']))
Beispiel #10
0
 def test_parse_function(self):
     pli = ProblogInterface()
     # problog needs some clauses to be able to evaluate (e.g., get the code)
     # the code is retrieved from an implementation(relation_name,..) clause
     pli.append('implementation(r1,"a.v = b.v + c.v").')
     pli.append(
         'implementation(rstep,"a.v = (t.v - a_last.t)*0.1 + a_last.v").')
     pli.append('implementation(r2,"a.v = 2*b.v").')
     # single input
     f = pli.parse_function("function(a,r2,[b])")
     self.assertEqual(f.vout.name, 'a')
     self.assertEqual(set([str(v) for v in f.vin]), set(['b']))
     self.assertEqual(f.name, 'r2')
     result = f.execute({'b': 1})
     self.assertEqual(result['a'].v, 2)
     # valid formats
     pli.parse_function("function(a,r1,[b,c])")
     pli.parse_function("function( a , r1 , [b,c])")
     pli.parse_function("function( a , r1 , [ b , c ] )")
     pli.parse_function("function( a, rstep, [t, a_last])")
     # test initialization of function
     f = pli.parse_function("function( a , r1 , [b,c])")
     self.assertEqual(f.vout.name, 'a')
     self.assertEqual(set([v.name for v in f.vin]), set(['b', 'c']))
     self.assertEqual(f.name, 'r1')
     self.assertTrue("a.v = b.v + c.v" in f.code)
     result = f.execute({'b': -1, 'c': 2})
     self.assertEqual(result['a'].v, 1)
     # no implementation (unknown clause)
     pli.reset()
     with self.assertRaises(Exception):
         f = pli.parse_function("function( a , r1 , [b,c])")
     # ambiguous implementation
     pli.append('implementation(r1,"a.v = b.v + c.v").')
     pli.append('implementation(r1,"a.v = b.v * c.v").')
     with self.assertRaises(AmbiguousImplementation):
         f = pli.parse_function("function( a , r1 , [b,c])")
     # invalid formats (parse errors)
     with self.assertRaises(Exception):
         pli.parse_function("function(a, r1, invalid)")
     with self.assertRaises(Exception):
         pli.parse_function("function(a, r1, [b, c], invalid)")
Beispiel #11
0
 def test_parse_implementation(self):
     pli = ProblogInterface()
     relation, execstr = pli.parse_implementation(
         'implementation(r1,"a = 2*b")')
     self.assertEqual(relation, 'r1')
     self.assertEqual(execstr, "a = 2*b")
Beispiel #12
0
 def test_parse_variableOf(self):
     pli = ProblogInterface()
     v = pli.parse_variableOf("variableOf(a1,a)")
     self.assertEqual(v, 'a')
Beispiel #13
0
 def test_parse_and_execute_substitution(self):
     pli = ProblogInterface()
     pli.append('implementation(r1, "x.v = 2 * a.v").')
     # parse
     s = pli.parse_substitution(
         "substitution(x, [function(x,r1,[a]), a1] )")
     self.assertEqual(s.vout.name, 'x')
     self.assertEqual(set([v.name for v in s.vin]), set(['a1']))
     self.assertEqual(len(s), 2)
     # execute
     a1 = Itom('a1', 1)
     result = s.execute([a1])
     self.assertEqual(result['x'].v, 2)
     # ambiguous implementation
     pli.append('implementation(r1, "x.v = 4 * a.v").')
     with self.assertRaises(AmbiguousImplementation):
         s = pli.parse_substitution(
             "substitution(x, [function(x,r1,[a]), a1] )")
     # no implementation
     pli.reset()
     with self.assertRaises(Exception):
         s = pli.parse_substitution(
             "substitution(x, [function(x,r1,[a]), a1] )")
     # any string as itom identifiers
     pli.reset()
     b = Itom('/p2os/sonar', [1, 2, 3])
     pli.append('implementation(min, "a.v = min(b.v)").')
     s = pli.parse_substitution(
         "substitution(a, [function(a, min, [b]), {}]).".format('"' +
                                                                b.name +
                                                                '"'))
     v = s.execute([b])
     self.assertEqual(v['a'].v, 1)