Example #1
0
def classify_hard_rule(state, params, input_type, normalized_answer, fs):
    """Find the first hard rule that matches."""
    best_matched_answer_group = None
    best_matched_answer_group_index = len(state.interaction.answer_groups)
    best_matched_rule_spec_index = None
    best_matched_truth_value = rule_domain.CERTAIN_FALSE_VALUE

    for (answer_group_index, answer_group) in enumerate(
            state.interaction.answer_groups):
        ored_truth_value = rule_domain.CERTAIN_FALSE_VALUE
        for (rule_spec_index, rule_spec) in enumerate(
                answer_group.rule_specs):
            if rule_spec.rule_type != rule_domain.FUZZY_RULE_TYPE:
                evaluated_truth_value = rule_domain.evaluate_rule(
                    rule_spec, input_type, params, normalized_answer, fs)
                if evaluated_truth_value > ored_truth_value:
                    ored_truth_value = evaluated_truth_value
                    best_rule_spec_index = rule_spec_index
        if ored_truth_value == rule_domain.CERTAIN_TRUE_VALUE:
            best_matched_truth_value = ored_truth_value
            best_matched_answer_group = answer_group
            best_matched_answer_group_index = answer_group_index
            best_matched_rule_spec_index = best_rule_spec_index
            return {
                'outcome': best_matched_answer_group.outcome.to_dict(),
                'answer_group_index': best_matched_answer_group_index,
                'classification_certainty': best_matched_truth_value,
                'rule_spec_index': best_matched_rule_spec_index,
            }

    return None
Example #2
0
def classify_soft_rule(state, params, input_type, normalized_answer, fs):
    """Find the maximum soft rule that matches. This is done by ORing
    (maximizing) all truth values of all rules over all answer groups. The
    group with the highest truth value is considered the best match.
    """
    best_matched_answer_group = None
    best_matched_answer_group_index = len(state.interaction.answer_groups)
    best_matched_rule_spec_index = None
    best_matched_truth_value = rule_domain.CERTAIN_FALSE_VALUE

    for (answer_group_index, answer_group) in enumerate(
            state.interaction.answer_groups):
        fuzzy_rule_spec_index = answer_group.get_fuzzy_rule_index()
        if fuzzy_rule_spec_index is not None:
            fuzzy_rule_spec = answer_group.rule_specs[fuzzy_rule_spec_index]
        else:
            fuzzy_rule_spec = None
        if fuzzy_rule_spec is not None:
            evaluated_truth_value = rule_domain.evaluate_rule(
                fuzzy_rule_spec, input_type, params, normalized_answer, fs)
            if evaluated_truth_value == rule_domain.CERTAIN_TRUE_VALUE:
                best_matched_truth_value = evaluated_truth_value
                best_matched_rule_spec_index = fuzzy_rule_spec_index
                best_matched_answer_group = answer_group
                best_matched_answer_group_index = answer_group_index
                return {
                    'outcome': best_matched_answer_group.outcome.to_dict(),
                    'answer_group_index': best_matched_answer_group_index,
                    'classification_certainty': best_matched_truth_value,
                    'rule_spec_index': best_matched_rule_spec_index,
                }

    return None
Example #3
0
def classify(
        exp_id, exp_param_specs, state, handler_name, answer, params):
    """Normalize the answer and return the first rulespec that it satisfies."""
    interaction_instance = interaction_registry.Registry.get_interaction_by_id(
        state.interaction.id)
    normalized_answer = interaction_instance.normalize_answer(
        answer, handler_name)

    handler = next(
        h for h in state.interaction.handlers if h.name == handler_name)
    fs = fs_domain.AbstractFileSystem(fs_domain.ExplorationFileSystem(exp_id))
    input_type = interaction_instance.get_handler_by_name(
        handler_name).obj_type
    for rule_spec in handler.rule_specs:
        if rule_domain.evaluate_rule(
                rule_spec.definition, exp_param_specs, input_type, params,
                normalized_answer, fs):
            return rule_spec

    raise Exception(
        'No matching rule found for handler %s. Rule specs are %s.' % (
            handler.name,
            [rule_spec.to_dict() for rule_spec in handler.rule_specs]
        )
    )
Example #4
0
    def classify(self, state_name, handler_name, answer, params):
        """Return the first rule that is satisfied by a reader's answer."""
        state = self.states[state_name]

        # Get the widget to determine the input type.
        generic_handler = widget_registry.Registry.get_widget_by_id(
            feconf.INTERACTIVE_PREFIX, state.widget.widget_id
        ).get_handler_by_name(handler_name)

        handler = next(
            h for h in state.widget.handlers if h.name == handler_name)
        fs = fs_domain.AbstractFileSystem(
            fs_domain.ExplorationFileSystem(self.id))

        for rule_spec in handler.rule_specs:
            if rule_domain.evaluate_rule(
                    rule_spec.definition, self.param_specs,
                    generic_handler.obj_type, params, answer, fs):
                return rule_spec

        raise Exception(
            'No matching rule found for handler %s. Rule specs are %s.' % (
                handler.name,
                [rule_spec.to_dict() for rule_spec in handler.rule_specs]
            )
        )
Example #5
0
def classify_hard_rule(state, params, input_type, normalized_answer, fs):
    """Find the first hard rule that matches."""
    best_matched_answer_group = None
    best_matched_answer_group_index = len(state.interaction.answer_groups)
    best_matched_rule_spec_index = None
    best_matched_truth_value = rule_domain.CERTAIN_FALSE_VALUE

    for (answer_group_index,
         answer_group) in enumerate(state.interaction.answer_groups):
        ored_truth_value = rule_domain.CERTAIN_FALSE_VALUE
        for (rule_spec_index, rule_spec) in enumerate(answer_group.rule_specs):
            if rule_spec.rule_type != rule_domain.FUZZY_RULE_TYPE:
                evaluated_truth_value = rule_domain.evaluate_rule(
                    rule_spec, input_type, params, normalized_answer, fs)
                if evaluated_truth_value > ored_truth_value:
                    ored_truth_value = evaluated_truth_value
                    best_rule_spec_index = rule_spec_index
        if ored_truth_value == rule_domain.CERTAIN_TRUE_VALUE:
            best_matched_truth_value = ored_truth_value
            best_matched_answer_group = answer_group
            best_matched_answer_group_index = answer_group_index
            best_matched_rule_spec_index = best_rule_spec_index
            return {
                'outcome': best_matched_answer_group.outcome.to_dict(),
                'answer_group_index': best_matched_answer_group_index,
                'classification_certainty': best_matched_truth_value,
                'rule_spec_index': best_matched_rule_spec_index,
            }

    return None
Example #6
0
def classify_soft_rule(state, params, input_type, normalized_answer, fs):
    """Find the maximum soft rule that matches. This is done by ORing
    (maximizing) all truth values of all rules over all answer groups. The
    group with the highest truth value is considered the best match.
    """
    best_matched_answer_group = None
    best_matched_answer_group_index = len(state.interaction.answer_groups)
    best_matched_rule_spec_index = None
    best_matched_truth_value = rule_domain.CERTAIN_FALSE_VALUE

    for (answer_group_index,
         answer_group) in enumerate(state.interaction.answer_groups):
        fuzzy_rule_spec_index = answer_group.get_fuzzy_rule_index()
        if fuzzy_rule_spec_index is not None:
            fuzzy_rule_spec = answer_group.rule_specs[fuzzy_rule_spec_index]
        else:
            fuzzy_rule_spec = None
        if fuzzy_rule_spec is not None:
            evaluated_truth_value = rule_domain.evaluate_rule(
                fuzzy_rule_spec, input_type, params, normalized_answer, fs)
            if evaluated_truth_value == rule_domain.CERTAIN_TRUE_VALUE:
                best_matched_truth_value = evaluated_truth_value
                best_matched_rule_spec_index = fuzzy_rule_spec_index
                best_matched_answer_group = answer_group
                best_matched_answer_group_index = answer_group_index
                return {
                    'outcome': best_matched_answer_group.outcome.to_dict(),
                    'answer_group_index': best_matched_answer_group_index,
                    'classification_certainty': best_matched_truth_value,
                    'rule_spec_index': best_matched_rule_spec_index,
                }

    return None
Example #7
0
def classify(exp_id, state, answer, params):
    """Normalize the answer and select among the answer groups the group in
    which the answer best belongs. The best group is decided by finding the
    first rule best satisfied by the answer. Returns a dict with the following
    keys:
        'outcome': A dict representing the outcome of the answer group matched.
        'rule_spec_string': A descriptive string representation of the rule
            matched.
    When the default rule is matched, outcome is the default_outcome of the
    state's interaction and the rule_spec_string is just 'Default.'
    """
    interaction_instance = interaction_registry.Registry.get_interaction_by_id(
        state.interaction.id)
    normalized_answer = interaction_instance.normalize_answer(answer)

    # Find the first group which best matches the given answer.
    for answer_group in state.interaction.answer_groups:
        fs = fs_domain.AbstractFileSystem(
            fs_domain.ExplorationFileSystem(exp_id))
        input_type = interaction_instance.answer_type
        matched_rule_spec = None
        for rule_spec in answer_group.rule_specs:
            if rule_domain.evaluate_rule(rule_spec, input_type, params,
                                         normalized_answer, fs):
                matched_rule_spec = rule_spec
                break
        if matched_rule_spec is not None:
            return {
                'outcome': answer_group.outcome.to_dict(),
                'rule_spec_string':
                (matched_rule_spec.stringify_classified_rule())
            }

    # If no other groups match, then the default group automatically matches
    # (if there is one present).
    if state.interaction.default_outcome is not None:
        return {
            'outcome': state.interaction.default_outcome.to_dict(),
            'rule_spec_string': exp_domain.DEFAULT_RULESPEC_STR
        }

    raise Exception(
        'Something has seriously gone wrong with the exploration. '
        'Oppia does not know what to do with this answer. Please contact the '
        'exploration owner.')
Example #8
0
def classify(exp_id, state, answer, params):
    """Normalize the answer and select among the answer groups the group in
    which the answer best belongs. The best group is decided by finding the
    first rule best satisfied by the answer. Returns a dict with the following
    keys:
        'outcome': A dict representing the outcome of the answer group matched.
        'rule_spec_string': A descriptive string representation of the rule
            matched.
    When the default rule is matched, outcome is the default_outcome of the
    state's interaction and the rule_spec_string is just 'Default.'
    """
    interaction_instance = interaction_registry.Registry.get_interaction_by_id(
        state.interaction.id)
    normalized_answer = interaction_instance.normalize_answer(answer)

    # Find the first group which best matches the given answer.
    for answer_group in state.interaction.answer_groups:
        fs = fs_domain.AbstractFileSystem(
            fs_domain.ExplorationFileSystem(exp_id))
        input_type = interaction_instance.answer_type
        matched_rule_spec = None
        for rule_spec in answer_group.rule_specs:
            if rule_domain.evaluate_rule(
                    rule_spec, input_type, params, normalized_answer, fs):
                matched_rule_spec = rule_spec
                break
        if matched_rule_spec is not None:
            return {
                'outcome': answer_group.outcome.to_dict(),
                'rule_spec_string': (
                    matched_rule_spec.stringify_classified_rule())
            }

    # If no other groups match, then the default group automatically matches
    # (if there is one present).
    if state.interaction.default_outcome is not None:
        return {
            'outcome': state.interaction.default_outcome.to_dict(),
            'rule_spec_string': exp_domain.DEFAULT_RULESPEC_STR
        }

    raise Exception('Something has seriously gone wrong with the exploration. '
        'Oppia does not know what to do with this answer. Please contact the '
        'exploration owner.')
def classify(exploration_id, state_id, handler_name, answer, params):
    """Return the first rule that is satisfied by a reader's answer."""

    exploration = get_exploration_by_id(exploration_id)
    state = get_state_by_id(exploration_id, state_id)

    # Get the widget to determine the input type.
    generic_handler = widget_domain.Registry.get_widget_by_id(
        feconf.INTERACTIVE_PREFIX, state.widget.widget_id
    ).get_handler_by_name(handler_name)

    handler = next(h for h in state.widget.handlers if h.name == handler_name)

    if generic_handler.input_type is None:
        return handler.rule_specs[0]
    else:
        for rule_spec in handler.rule_specs:
            if rule_domain.evaluate_rule(
                    rule_spec.definition, exploration.param_specs,
                    generic_handler.input_type, params, answer):
                return rule_spec

        raise Exception(
            'No matching rule found for handler %s.' % handler.name)
Example #10
0
def classify(exp_id, state, answer, params):
    """Normalize the answer and select among the answer groups the group in
    which the answer best belongs. The best group is decided by finding the
    first rule best satisfied by the answer. Returns a dict with the following
    keys:
        'outcome': A dict representing the outcome of the answer group matched.
        'rule_spec_string': A descriptive string representation of the rule
            matched.
        'answer_group_index': An index into the answer groups list indicating
            which one was selected as the group which this answer belongs to.
            This is equal to the number of answer groups if the default outcome
            was matched.
        'classification_certainty': A normalized value within the range of
            [0, 1] representing at which confidence level the answer belongs in
            the chosen answer group. A certainty of 1 means it is the best
            possible match. A certainty of 0 means it is matched to the default
            outcome.
    When the default rule is matched, outcome is the default_outcome of the
    state's interaction and the rule_spec_string is just 'Default.'
    """
    interaction_instance = interaction_registry.Registry.get_interaction_by_id(
        state.interaction.id)
    normalized_answer = interaction_instance.normalize_answer(answer)

    # Find the first group that satisfactorily matches the given answer. This is
    # done by ORing (maximizing) all truth values of all rules over all answer
    # groups. The group with the highest truth value is considered the best
    # match.
    best_matched_answer_group = None
    best_matched_answer_group_index = len(state.interaction.answer_groups)
    best_matched_rule_spec = None
    best_matched_truth_value = 0.0
    for (i, answer_group) in enumerate(state.interaction.answer_groups):
        fs = fs_domain.AbstractFileSystem(
            fs_domain.ExplorationFileSystem(exp_id))
        input_type = interaction_instance.answer_type
        ored_truth_value = 0.0
        best_rule_spec = None
        for rule_spec in answer_group.rule_specs:
            evaluated_truth_value = rule_domain.evaluate_rule(
                rule_spec, input_type, params, normalized_answer, fs)
            if evaluated_truth_value > ored_truth_value:
                ored_truth_value = evaluated_truth_value
                best_rule_spec = rule_spec
        if ored_truth_value > best_matched_truth_value:
            best_matched_truth_value = ored_truth_value
            best_matched_rule_spec = best_rule_spec
            best_matched_answer_group = answer_group
            best_matched_answer_group_index = i

    # The best matched group must match above a certain threshold. If no group
    # meets this requirement, then the default 'group' automatically matches
    # resulting in the outcome of the answer being the default outcome of the
    # state.
    if (best_matched_truth_value >=
            feconf.DEFAULT_ANSWER_GROUP_CLASSIFICATION_THRESHOLD):
        return {
            'outcome': best_matched_answer_group.outcome.to_dict(),
            'rule_spec_string': (
                best_matched_rule_spec.stringify_classified_rule()),
            'answer_group_index': best_matched_answer_group_index,
            'classification_certainty': best_matched_truth_value
        }
    elif state.interaction.default_outcome is not None:
        return {
            'outcome': state.interaction.default_outcome.to_dict(),
            'rule_spec_string': exp_domain.DEFAULT_RULESPEC_STR,
            'answer_group_index': len(state.interaction.answer_groups),
            'classification_certainty': 0.0
        }

    raise Exception('Something has seriously gone wrong with the exploration. '
        'Oppia does not know what to do with this answer. Please contact the '
        'exploration owner.')
Example #11
0
def classify(exp_id, state, answer, params):
    """Normalize the answer and select among the answer groups the group in
    which the answer best belongs. The best group is decided by finding the
    first rule best satisfied by the answer. Returns a dict with the following
    keys:
        'outcome': A dict representing the outcome of the answer group matched.
        'rule_spec_string': A descriptive string representation of the rule
            matched.
        'answer_group_index': An index into the answer groups list indicating
            which one was selected as the group which this answer belongs to.
            This is equal to the number of answer groups if the default outcome
            was matched.
        'classification_certainty': A normalized value within the range of
            [0, 1] representing at which confidence level the answer belongs in
            the chosen answer group. A certainty of 1 means it is the best
            possible match. A certainty of 0 means it is matched to the default
            outcome.
    When the default rule is matched, outcome is the default_outcome of the
    state's interaction and the rule_spec_string is just 'Default.'
    """
    interaction_instance = interaction_registry.Registry.get_interaction_by_id(
        state.interaction.id)
    normalized_answer = interaction_instance.normalize_answer(answer)

    # Find the first group that satisfactorily matches the given answer. This is
    # done by ORing (maximizing) all truth values of all rules over all answer
    # groups. The group with the highest truth value is considered the best
    # match.
    best_matched_answer_group = None
    best_matched_answer_group_index = len(state.interaction.answer_groups)
    best_matched_rule_spec = None
    best_matched_truth_value = 0.0
    for (i, answer_group) in enumerate(state.interaction.answer_groups):
        fs = fs_domain.AbstractFileSystem(
            fs_domain.ExplorationFileSystem(exp_id))
        input_type = interaction_instance.answer_type
        ored_truth_value = 0.0
        best_rule_spec = None
        for rule_spec in answer_group.rule_specs:
            evaluated_truth_value = rule_domain.evaluate_rule(
                rule_spec, input_type, params, normalized_answer, fs)
            if evaluated_truth_value > ored_truth_value:
                ored_truth_value = evaluated_truth_value
                best_rule_spec = rule_spec
        if ored_truth_value > best_matched_truth_value:
            best_matched_truth_value = ored_truth_value
            best_matched_rule_spec = best_rule_spec
            best_matched_answer_group = answer_group
            best_matched_answer_group_index = i

    # The best matched group must match above a certain threshold. If no group
    # meets this requirement, then the default 'group' automatically matches
    # resulting in the outcome of the answer being the default outcome of the
    # state.
    if (best_matched_truth_value >=
            feconf.DEFAULT_ANSWER_GROUP_CLASSIFICATION_THRESHOLD):
        return {
            'outcome': best_matched_answer_group.outcome.to_dict(),
            'rule_spec_string': (
                best_matched_rule_spec.stringify_classified_rule()),
            'answer_group_index': best_matched_answer_group_index,
            'classification_certainty': best_matched_truth_value
        }
    elif state.interaction.default_outcome is not None:
        return {
            'outcome': state.interaction.default_outcome.to_dict(),
            'rule_spec_string': exp_domain.DEFAULT_RULESPEC_STR,
            'answer_group_index': len(state.interaction.answer_groups),
            'classification_certainty': 0.0
        }

    raise Exception('Something has seriously gone wrong with the exploration. '
        'Oppia does not know what to do with this answer. Please contact the '
        'exploration owner.')