def generate_example_type_1(problem, nl_propositions):
    """Generates a type 1 training example.

  Args:
    problem: a lib.InferenceProblem instance.
    nl_propositions: the natural language versions of all the propositions
      appearing in "problem".

  Returns:
    An instance of "Example", or None if any issue was found.
  """
    problem = ip.generate_problem_canonical_renaming(problem)
    if not problem:
        return None
    premises = problem.premises
    inferences = problem.inferences
    propositions = problem.propositions
    [problem_inference, _] = random.choice(inferences)
    nl_inference = rules.render_language_clause(problem_inference,
                                                propositions, nl_propositions)
    nl_premises = []
    for premise in premises:
        nl_premises.append(
            rules.capitalize(
                rules.render_language_clause(premise, propositions,
                                             nl_propositions)))
    inputs = "Translate the following inference to logic notation: "
    inputs += (". ".join(nl_premises)) + f". Therefore {nl_inference}."
    targets = ". ".join([rules.render_logic_clause(x) for x in premises])
    targets = (f"{targets}. Therefore " +
               f"{rules.render_logic_clause(problem_inference)}.")
    return lib.Example(inputs, targets, "1", problem)
def generate_example_type_2b(problem, one_step_inferences, propositions,
                             nl_propositions):
    """Generates a type 2b training example.

  Args:
    problem: an InferenceProblem instance.
    one_step_inferences: the list of one step inferences that can be reahced
      form the premises.
    propositions: the list of propositions in the problem.
    nl_propositions: the natural language versions of "propositions".

  Returns:
    An instance of "lib.Example", or None if any issue was found.
  """

    premises = problem.premises
    example_type = "2b"
    nl_premises = []
    for premise in premises:
        nl_premises.append(
            rules.capitalize(
                rules.render_language_clause(premise, propositions,
                                             nl_propositions)))
    name_rule = random.choice([True, False])
    rule_name = None
    nl_inferences = []
    for [rule_inference, rule] in one_step_inferences:
        rule_name = rule.rule_name
        inference_str = rules.capitalize(
            rules.render_language_clause(rule_inference, propositions,
                                         nl_propositions))
        if name_rule:
            inference_str += f" can be inferred via the {rule_name} rule"
        nl_inferences.append(inference_str)
    inputs = ("What can be inferred from the following premises in a single "
              "inference step (ignoring inferences that add new predicates or "
              "constants)? ")
    if name_rule:
        inputs += "Name the inference rule being used: "
    inputs += (". ".join(nl_premises)) + "."
    targets = (". ".join(nl_inferences)) + "."

    if not nl_inferences:
        example_type = "2b-empty"
        targets = "Nothing can be inferred from these premises."
    elif problem.contains_contradiction:
        example_type = "2b-cont"
        targets = (
            "Since the premises are contradictory, we can infer anything "
            "from them.")

    return lib.Example(inputs, targets, example_type, problem)
def generate_example_type_2a(problem, one_step_inferences):
    """Generates a type 2a training example.

  Args:
    problem: a lib.InferenceProblem instance.
    one_step_inferences: the list of one step inferences that can be reahced
      form the premises.

  Returns:
    An instance of "Example", or None if any issue was found.
  """

    premises = problem.premises
    example_type = "2a"
    name_rule = random.choice([True, False])
    inputs = ("What can be inferred from the following premises in a single "
              "inference step (ignoring inferences that add new predicates or "
              "constants)? ")
    if name_rule:
        inputs += "Name the inference rule being used: "
    inputs += (". ".join([rules.render_logic_clause(x)
                          for x in premises])) + "."
    inferences_str = []
    for [rule_inference, rule] in one_step_inferences:
        rule_name = rule.rule_name
        inference_str = rules.render_logic_clause(rule_inference)
        if name_rule:
            inference_str += f" can be inferred via the {rule_name} rule"
        inferences_str.append(inference_str)
    targets = (". ".join(inferences_str)) + "."

    if not inferences_str:
        example_type = "2a-empty"
        targets = "Nothing can be inferred from these premises."
    elif problem.contains_contradiction:
        example_type = "2a-cont"
        targets = (
            "Since the premises are contradictory, we can infer anything "
            "from them.")

    return lib.Example(inputs, targets, example_type, problem)
def generate_example_type_3b(problem,
                             nl_propositions,
                             probability_of_adding_direct_inference=0.1,
                             answer_at_the_end=True):
    """Generates a type 3b training example.

  Args:
    problem: an InferenceProblem instance.
    nl_propositions: the natural language versions of "propositions".
    probability_of_adding_direct_inference: the probability of having one of the
      premises as the target im.
    answer_at_the_end: whether to put the answer at the end of the targets, or
      at the beginning.

  Returns:
    An instance of "Example", or None if any issue was found.
  """

    # Since "unrelated" is usually larger, we randomly reduce it to size 1:
    example_type = "3b"
    premises = problem.premises
    unrelated = list(problem.unrelated)
    while len(unrelated) > 1:
        unrelated.remove(random.choice(unrelated))
    choices = ([(x, "inference") for x in problem.inferences] +
               [(x, "contradiction")
                for x in problem.contradictions] + [([x, []], "unrelated")
                                                    for x in unrelated])
    # With some probability we also allow direct inferences (which are directly
    # given in the premises):
    if random.random() < probability_of_adding_direct_inference:
        for premise in premises:
            choices.append(([premise, []], "inference"))
    if not choices:
        return None
    ([target_inference, chain], inference_type) = random.choice(choices)
    name_rule = random.choice([True, False])

    nl_premises = []
    for premise in premises:
        nl_premises.append(
            rules.capitalize(
                rules.render_language_clause(premise, problem.propositions,
                                             nl_propositions)))
    nl_target_inference = rules.capitalize(
        rules.render_language_clause(target_inference, problem.propositions,
                                     nl_propositions))

    inputs = "Consider the following premises. "
    inputs += (". ".join(nl_premises)) + ". "
    inputs += "Can we infer the following from them? "
    if name_rule:
        inputs += "If we can, name the inference rule being used: "
    inputs += nl_target_inference + "."
    if inference_type == "inference":
        if not chain:
            example_type = "3b-premise"
            if answer_at_the_end:
                targets = "That is one of the premises. Therefore, the answer is yes."
            else:
                targets = "Yes, that is one of the premises."
        elif len(chain) == 1:
            if name_rule:
                rule_name = chain[0][2]
                if answer_at_the_end:
                    targets = (
                        "We can infer this via the "
                        f"{rule_name} rule. Therefore, the answer is yes.")
                else:
                    targets = f"Yes, we can infer this via the {rule_name} rule."
            else:
                targets = "Yes."
        else:
            if problem.contains_contradiction:
                example_type = "3b-cont"
            if answer_at_the_end:
                targets = ""
            else:
                if problem.contains_contradiction:
                    targets = (
                        "Yes, the premises are contradictory, so we can infer "
                        "anything from them. For example via the following "
                        "inference chain.")
                else:
                    targets = "Yes, via the following inference chain."
            for i in range(len(chain)):
                # Each element in the chain is: ("premises, inferences, name")
                if i == len(chain) - 1:
                    targets += " Finally, from the fact that"
                else:
                    targets += " From the fact that"
                # Premises:
                for j in range(len(chain[i][0])):
                    premise = chain[i][0][j]
                    nl_premise = rules.render_language_clause(
                        premise, problem.propositions, nl_propositions)
                    if j != 0:
                        if j == len(chain[i][0]) - 1:
                            targets += ", and that"
                        else:
                            targets += ", that"
                    targets += f" {nl_premise}"
                targets += " we can infer that"
                # Inferences:
                for j in range(len(chain[i][1])):
                    chain_inference = chain[i][1][j]
                    nl_inference = rules.render_language_clause(
                        chain_inference, problem.propositions, nl_propositions)
                    if j != 0:
                        targets += ","
                    targets += f" {nl_inference}"
                if name_rule:
                    targets += f" via {chain[i][2]}"
                targets += "."
            if answer_at_the_end:
                if problem.contains_contradiction:
                    targets += (
                        " Therefore, the answer is yes. Notice, however, that "
                        "the premises were contradictory, so we can infer "
                        "anything from them.")
                else:
                    targets += " Therefore, the answer is yes."

    elif inference_type == "contradiction":
        if problem.contains_contradiction:
            example_type = "3b-cont"
            if answer_at_the_end:
                targets = ("The premises are contradictory and we can infer "
                           "anything from them. Therefore, the answer is yes.")
            else:
                targets = (
                    "Yes, the premises are contradictory, so we can infer "
                    "anything from them.")
        elif len(chain) <= 1:
            example_type = "3b-no-1"
            if answer_at_the_end:
                targets = "That contradicts the premises. Therefore the answer is no."
            else:
                targets = "No, that contradicts the premises."
        else:
            example_type = "3b-no"
            if answer_at_the_end:
                targets = ""
            else:
                targets = "No, we can see why via the following inference chain."
            for i in range(len(chain)):
                # Each element in the chain is: ("premises, inferences, name")
                if i == len(chain) - 1:
                    targets += " Finally, from the fact that"
                else:
                    targets += " From the fact that"
                # Premises:
                for j in range(len(chain[i][0])):
                    premise = chain[i][0][j]
                    nl_premise = rules.render_language_clause(
                        premise, problem.propositions, nl_propositions)
                    if j != 0:
                        if j == len(chain[i][0]) - 1:
                            targets += ", and that"
                        else:
                            targets += ", that"
                    targets += f" {nl_premise}"
                targets += " we can infer that"
                # Inferences:
                for j in range(len(chain[i][1])):
                    chain_inference = chain[i][1][j]
                    nl_inference = rules.render_language_clause(
                        chain_inference, problem.propositions, nl_propositions)
                    if j != 0:
                        targets += ","
                    targets += f" {nl_inference}"
                if name_rule:
                    targets += f" via {chain[i][2]}"
                targets += "."
            targets = targets[:-1]  # Remove the last dot.
            targets += f", which contradicts that {nl_target_inference}."
            if answer_at_the_end:
                targets += " Therefore, the answer is no."

    else:
        example_type = "3b-unrelated"
        if answer_at_the_end:
            targets = "We cannot infer that from the premises."
            targets += " Therefore the answer is no."
        else:
            targets = "No, we cannot infer that from the premises."

    return lib.Example(inputs, targets, example_type, problem)