def verify_model(prop, mod):
    """ It returns mod iff subj is related to obj according to rel,
    otherwise it returns None. Calls recursive func verify, which
    inspects the subject and object coordinates, and verfies if rel
    holds between the coordinates"""
    rel = utilities.relfn(prop)
    subj = utilities.subjfn(prop)
    obj = utilities.objfn(prop)
    subj_coords = utilities.finds(subj, mod)
    obj_coords = utilities.finds(obj, mod)
    return verify(rel, subj_coords, obj_coords, mod)
示例#2
0
    def decide(self, prop, mods):
        """ This function decides what func to call depending on what is
        already in the mods list of dictionaries. Each mod in mods is a
        separate model. prop (proposition) is a list containing reln, subject
        and object (e.g. [[0, 1, 0], ['[]'], ['O']]).
        find_item is used to check if subj and obj are in mods in 2 separate
        calls, it returns a list containing coords and mod if subj (or obj) is
        present, otherwise it returns None. The extract function extracts the
        model containing subject and object (if a model contains them) from
        the list of mods. It then calls call_appropriate function, which
        decides which functions to call based on if subj and/or obj are in
        mods. OVERRIDES the spatial reasoning function."""

        # For 'generate all 'models'
        if prop == [[]]:
            model = self.generate_all_models(mods[-1])
            return mods
        #rel = utilities.relfn(prop)
        obj = utilities.objfn(prop)
        subj = utilities.subjfn(prop)
        # Inttialize None and {} for coords and mods. These values are used if
        # find_item does not find subj and/or obj in mods (if it returns None).
        subj_coords = None
        obj_coords = None
        subj_mod = {}
        obj_mod = {}
        # Find subj and obj in mods
        subj_coords_mod = utilities.find_item(subj, mods)
        obj_coords_mod = utilities.find_item(obj, mods)
        if subj_coords_mod is not None:
            subj_coords = subj_coords_mod[0]
            subj_mod = subj_coords_mod[1]
        if obj_coords_mod is not None:
            obj_coords = obj_coords_mod[0]
            obj_mod = obj_coords_mod[1]
        # Extract the mod in which subj/obj were found from the list of mods,
        # this removes the relevant mod from mods. The updated model is
        # appended to model returned by call_appropriate_function.
        mods = utilities.extract(subj_mod, mods)
        mods = utilities.extract(obj_mod, mods)
        # Call call_appropriate_func to, well, call the appropriate function,
        # a model is returned whichever function is called from there. Before
        # that, package up the arguments, as there would be too many to pass
        # without upsetting Pylint.
        coords = (subj_coords, obj_coords)
        models_to_pass = (subj_mod, obj_mod)
        model = self.call_appropriate_func(prop, coords, models_to_pass)
        mods.append(model)
        # mods contains intermediate models
        return mods
示例#3
0
    def gen_and_print_conclusions(self, prop, mod):
        """ Function which generates the conclusion based on the intensional
        representaiton of the question premise -- prop (obtained from the rel
        between the subject and object in the question, and the model.
        OVERRIDES the spatial_reasoning function"""
        # Generate the conclusion premise in words from prop.
        conclusion = PARSER.generate_conclusion(prop)
        pmm_rel = list(utilities.relfn(prop))
        obj = utilities.objfn(prop)
        subj = utilities.subjfn(prop)
        # Replace the last premise with the generated conclusion
        self.premises[-1] = [conclusion]
        # No model variation necessary
        if self.annotations == []:
            print("No model variation necessary!")
            print("Conclusion: {}".format(conclusion))
            print("Preferred model: {}".format(self.neighbourhoodmodels[0][0]))
            return

        print("Conclusion in preferred model (usually accepted even though it "
              "can be incorrect): {}".format(conclusion))
        print("Preferred model: {}".format(self.neighbourhoodmodels[0][0]))
        print("However, Prism can also look for alternative models as "
              "annotations are present: model variation phase!")
        self.get_alternate_models(copy.deepcopy(mod))

        mods_dict = {
            k: v
            for k, v in self.neighbourhoodmodels.items() if k <= self.threshold
        }
        # Pop out the preferred model (key 0) as we have printed out its
        # conclusion
        mods_dict.pop(0, None)
        # Order mods_dict by key: convert it into an OrderedDict
        mods_dict = OrderedDict(sorted(mods_dict.items()))

        # Check if all the models within threshold have the same conclusion as
        # the preferred model. In this case, PRISM returns the possibly
        # incorrect result (based on threshold) that the conclusion is the
        # same in all the models.
        self.alternate_model_conclusion(mods_dict, subj, obj, pmm_rel)
        if self.true_index is None:
            # It still has its initial value: no change in the for loops
            print("Same conclusion found in preferred and alternative "
                  "models.")
        else:
            print("NO VALID CONCLUSION possible! But Prism says that the first"
                  " conclusion generated from the preferred model is usually"
                  " accepted.")
def switch(newprop, fixprops, mod):
    """ If rel is converse of the one in mod, this func tries to
    swap subj and obj items, otherwise (or if swap yields model
    conflicting with item in fixprops), it tries to move subj, and if
    that fails, it tries to move obj. Otherwise returns None. """
    rel = utilities.relfn(newprop)
    obj = utilities.objfn(newprop)
    subj = utilities.subjfn(newprop)
    subj_coord = utilities.finds(subj, mod)
    obj_coord = utilities.finds(obj, mod)
    # Semantics between subj and obj in mod is opposite of current rel:
        # we need to swap subj and obj in mod.
    newmod = swap(subj, subj_coord, obj, obj_coord, mod)
    newmod = spaces_to_none(newmod)
    newmod = spatial_array.copy_shrink_array(newmod)
    # Check if the relation between subject and object is opposite to
    # rel in newprop, and if none of the props in fixprop are false in
    # the model produced by swapping subj  and obj. If so, return newmod.
    # Note: conflict props returns [] if there are no conflicting props
    if find_rel_prop(subj_coord, obj_coord) == utilities.convert(rel) and \
       conflict_props(fixprops, newmod) == [] and newmod != {}:
        return newmod
    # After swapping the subject and object in the conclusion premise, there
    # are some conflicting props (premises) . In each of these premises, move
    # subj from subj_coord to new coordinates. If there is no conflict, return
    # the resulting model. Otherwise, try to move object to new position.
    newmod = move(subj, subj_coord, rel, obj_coord, mod)
    newmod = spaces_to_none(newmod)
    newmod = spatial_array.copy_shrink_array(newmod)
    if conflict_props(fixprops, newmod) == [] and newmod != {}:
        return newmod
    # Move object from obj_coord to new coordinates. If there is no
    # conflict, return the resulting model. Otherwise, return None.
    obj_rel = utilities.convert(rel)
    newmod = move(obj, obj_coord, obj_rel, subj_coord, mod)
    newmod = spaces_to_none(newmod)
    newmod = spatial_array.copy_shrink_array(newmod)
    if conflict_props(fixprops, newmod) == [] and newmod != {}:
        return newmod
    return None
def conflict(premises, mod):
    """ Returns list of props corresponding to those premises false in model,
    excluding those containing referents that are not in the model. """
    false_props = []
    for premise in premises:
        # premise is a list of containing the premise, premise[0]: string.
        prop = PARSER.parse(premise[0])
        subj = utilities.subjfn(prop)
        obj = utilities.objfn(prop)
        # If either subject or object is not found, we can't tell if there
        # is a conflict.
        if utilities.finds(subj, mod) is None or \
           utilities.finds(obj, mod) is None:
            continue
        # Check if rel between subj and obj in current prop holds in mod
        if verify_model(prop, mod) is None:
            # verify_model returns None when the rel between subj and obj in
            # prop is invalid in mod, i.e. the premise is false in mod.
            false_props.append(prop)
        # If verify_model returned a list (not None), go to the next premise
        # (end of loop)
    return false_props
示例#6
0
    def call_appropriate_func(self, prop, coords, models):
        """ This function calls appropriate functions depending on
        whether subj_coords or obj_coords are already in mods (not None).
        If subj and obj are in models , it calls verify_model. If one of
        them is in mods, it calls add-item (add subj or add object).
        If neither is in models, it calls startmod. If subj_mod
        and obj_mod are mutually independent, it calls combine.
        OVERRIDES the spatial_reasoning function"""
        # Unpack coords and mods: this is necessary only to avoid upsetting
        # Pylint.
        subj_coords = coords[0]
        obj_coords = coords[1]
        subj_mod = models[0]
        obj_mod = models[1]
        rel = utilities.relfn(prop)
        subj = utilities.subjfn(prop)
        obj = utilities.objfn(prop)
        if subj_coords is not None and obj_coords is not None:
            if subj_mod == obj_mod:
                # We have reached a conclusion premise, i.e. subj and obj
                # were found in the same mod. OR we need to generate a
                # conclusion if rel = (), empty tuple returned by relfn
                if rel == ():
                    # We have to generate the relation between subj and
                    # obj as we have a generate conclusion current premise
                    rel = model_validation.find_rel_prop(
                        subj_coords, obj_coords)
                    prop[0] = list(rel)
                    # Add initial mod to modelslist and to neighbourhoodmodels
                    self.modelslist.append(subj_mod)
                    self.neighbourhoodmodels[0].append(subj_mod)
                    # Call a function to generate the conclusion(s) and print
                    # them. If the conclusions are different in the preferred
                    # model and in alternative models, both conclusions are
                    # printed, along with the models.
                    self.gen_and_print_conclusions(prop, subj_mod)
                    return subj_mod
                print("Verifying if the conclusion is correct!")
                mod = model_validation.verify_model(prop, subj_mod)
                if mod is not None:
                    # If premises are true in preferred model, no need for
                    # variation. Return the model.
                    print("Premises are true in model, no model variation "
                          "required (possibly invalid result if multiple "
                          "models are possible).")
                    print("Final model: \n{},".format(mod))
                    return mod
                # verify_model returned None: model variation may be required
                # to try to find a true result in the alternate models.
                if self.annotations == []:
                    # Determinate, return the false model: no model variation
                    print("Premises are false in model. No model variation "
                          "necessary!")
                    print("Final model: \n{},".format(subj_mod))
                    return subj_mod
                # Annotation(s) present: alternative models present.
                # Model variation required.
                print("Model variation necessary as annotation(s) are present")
                # First, put the preferred model in the models list and in
                # the neighbourhood models defaultdict
                self.modelslist.append(subj_mod)
                self.neighbourhoodmodels[0].append(subj_mod)
                self.get_alternate_models(copy.deepcopy(subj_mod))
                # Print alternative models upto threhold
                self.print_alt_mods_threshold()
                # Dummy return: we are going to use self.modelsist for print
                # in this case
                return subj_mod

            # There are separate subj and obj mods which need to be combined
            # (subj_mod != obj_mod)
            print("Combining 2 separate models together.")
            mod = model_combination.combine(rel, subj_coords, obj_coords,
                                            subj_mod, obj_mod)
            print("Intermediate model: \n{}".format(mod))
            return mod
        elif subj_coords is not None and obj_coords is None:
            print("Adding object!")
            # Subj-obj order interchanged, rel interchanged.
            rel = utilities.convert(rel)
            mod, annotations_p = model_builder.add_item_prism(
                subj_coords, rel, obj, subj_mod, self.annotations)
            print("Intermediate model: \n{}".format(mod))
            #return mod
        elif subj_coords is None and obj_coords is not None:
            print("Adding subject!")
            # Regular 2nd premise, rel unchanged
            mod, annotations_p = model_builder.add_item_prism(
                obj_coords, rel, subj, obj_mod, self.annotations)
            self.annotations = annotations_p
            print("Intermediate model: \n{}".format(mod))
            #return mod
        else:
            print("Starting model")
            mod = model_builder.start_mod(rel, subj, obj)
            print("Intermediate model: \n{}".format(mod))
        # return model: applies for add subj, add obj and start model
        return mod
    def call_appropriate_func(self, prop, coords, models):
        """ This function calls appropriate functions depending on
        whether subj_coords or obj_coords are already in mods (not None).
        If subj and obj are in models , it calls verify_model. If one of
        them is in mods, it calls add-item (add subj or add object).
        If neither is in models, it calls startmod. If subj_mod
        and obj_mod are mutually independent, it calls combine."""
        # Unpack coords and mods tuples: this is necessary only to prevent
        # Pylint no. of vairables and no. of statements warnings.
        subj_coords, obj_coords = coords
        subj_mod, obj_mod = models
        rel = utilities.relfn(prop)
        subj = utilities.subjfn(prop)
        obj = utilities.objfn(prop)
        if subj_coords is not None and obj_coords is not None:
            if subj_mod == obj_mod:
                # We have reached a conclusion premise, i.e. subj and obj
                # were found in the same mod. OR we need to generate a
                # conclusion if rel = (), empty tuple returned by relfn
                if rel == ():
                    # We have to generate the relation between subj and
                    # obj as we have a generate conclusion current premise
                    rel = model_validation.find_rel_prop(
                        subj_coords, obj_coords)
                    prop[0] = list(rel)
                    # Call a function to generate the conclusion and print
                    # it. If the conclusions are different in the preferred
                    # model and in an alternative model, both conclusions are
                    # printed, along with the 2 models.
                    self.gen_and_print_conclusions(prop, subj_mod)
                    return subj_mod
                print("Verifying if the conclusion is correct!")
                mod = model_validation.verify_model(prop, subj_mod)
                if mod is not None:
                    print(
                        "Premises are true in model. \nIntermediate model: "
                        "\n{}.\nAttempting to falsify the model.".format(mod))
                    alt_mod = model_validation.make_false(
                        prop, subj_mod, self.premises)
                    print("Make false returned mod: \n{}".format(alt_mod))
                    if mod == alt_mod:
                        print("No falsifying model found!\nPremise follows "
                              "validly from previous premises.\nFinal model "
                              "(premises true): {}".format(mod))
                    else:
                        print("Premise was previously possibly true, but can "
                              "also be false.\n Initial model (premises true):"
                              "\n{}\nVaried model (premises false):\n {}\n".
                              format(mod, alt_mod))
                        self.models.append(mod)
                        self.models.append(alt_mod)
                    return alt_mod
                # verify_model returned None
                print(
                    "Premises are false in model.\nIntermediate model: \n{}"
                    "\nAttempting to make the model true.\n".format(subj_mod))
                alt_mod = model_validation.make_true(prop, subj_mod,
                                                     self.premises)
                print("Make true returned mod: \n{}".format(alt_mod))
                if subj_mod == alt_mod:
                    print("No true model found!\nPremise is inconsistent with "
                          "previous premises.\nFinal model (premises false):"
                          "\n{}:\n".format(subj_mod))
                else:
                    print("Premise was previously possibly false, but can also"
                          " be true.\nInitial model (premises false):\n {}\n"
                          "Altered model (premises true):{}\n".format(
                              subj_mod, alt_mod))
                    self.models.append(subj_mod)
                    self.models.append(alt_mod)
                return subj_mod

            # There are separate subj and obj mods which need to be combined
            # (subj_mod != obj_mod)
            print("Combining 2 separate models together.")
            mod = model_combination.combine(rel, subj_coords, obj_coords,
                                            subj_mod, obj_mod)
            print("Intermediate model: \n{}".format(mod))
            return mod
        elif subj_coords is not None and obj_coords is None:
            print("Adding object!")
            # Subj-obj order interchanged, rel interchanged.
            mod = model_builder.add_item(subj_coords, utilities.convert(rel),
                                         obj, subj_mod)
            print("Intermediate model: \n{}".format(mod))
        elif subj_coords is None and obj_coords is not None:
            print("Adding subject!")
            # Regular 2nd premise, rel unchanged
            mod = model_builder.add_item(obj_coords, rel, subj, obj_mod)
            print("Intermediate model: \n{}".format(mod))
        else:
            print("Starting model")
            mod = model_builder.start_mod(rel, subj, obj)
            print("Intermediate model: \n{}".format(mod))
        # return model: applies for add subj, add obj and start model
        return mod