Katkat

Solve Timed Logical and Quantitative Reasoning Cases

Epic SystemsSoftware Engineer · Online Assessment

Last updated

Implement a deduction engine that evaluates whether target query statements are definitely true, definitely false, or cannot be determined, given a set of observed facts and unidirectional logical implications.

Problem Description

Automated reasoning systems often evaluate statements under incomplete information. Given a set of ground-truth observations and logical rules, a proposition can be:

  • "TRUE": It must be true in all valid interpretations.
  • "FALSE": It must be false in all valid interpretations (its negation is proven true).
  • "CANNOT_DETERMINE": It is true in at least one valid interpretation and false in at least one valid interpretation.

You are given:

  1. facts: A list of strings representing propositions known to be unconditionally true. If a fact starts with !, its negated proposition is unconditionally false (for example, "!A" means proposition A is false).
  2. rules: A list of conditional implication strings in the format "P -> Q", meaning "if proposition P is true, then proposition Q must be true". Note that rules also enforce their contrapositive: "!Q -> !P".
  3. queries: A list of proposition strings to evaluate.

Each proposition token is a non-empty alphanumeric string without spaces (e.g., "HospitalA", "BedOccupied"). A token preceded by ! denotes the negation of that proposition. For any query variable X, determine if X is "TRUE", "FALSE", or "CANNOT_DETERMINE".

Assume there are no contradictory premises in facts and rules.

Function Interface

def evaluate_propositions(
    facts: list[str],
    rules: list[str],
    queries: list[str]
) -> list[str]:
    pass

Input & Output Format

  • facts: list of strings, each either "X" or "!X".
  • rules: list of strings, each of the form "X -> Y", where X and Y can each be either a variable or a negated variable (e.g., "!A -> B").
  • queries: list of query proposition strings (without !).
  • Returns: list of strings ("TRUE", "FALSE", or "CANNOT_DETERMINE"), corresponding to each query in queries in order.

Constraints

  • 1 <= len(facts) <= 200
  • 0 <= len(rules) <= 500
  • 1 <= len(queries) <= 200
  • Variable names consist of 1 to 20 alphanumeric characters.
  • The premises are guaranteed to be mutually consistent.

Examples

Example 1

facts = ["NurseOnDuty", "!Admitted"]
rules = [
    "NurseOnDuty -> TriageOpen",
    "TriageOpen -> Staffed",
    "Admitted -> BedAssigned"
]
queries = ["TriageOpen", "BedAssigned", "NurseOnDuty", "Admitted"]

# Output: ["TRUE", "CANNOT_DETERMINE", "TRUE", "FALSE"]

Explanation: NurseOnDuty is true, which implies TriageOpen is true. !Admitted means Admitted is false. However, Admitted -> BedAssigned only specifies what happens if Admitted is true; since Admitted is false, BedAssigned could be true or false (CANNOT_DETERMINE).

Example 2

facts = ["!Discharged"]
rules = [
    "Stable -> Discharged"
]
queries = ["Stable"]

# Output: ["FALSE"]

Explanation: By contrapositive, Stable -> Discharged implies !Discharged -> !Stable. Since Discharged is false, Stable must be false.

Hints

Hint 1

Every implication 'A -> B' has an equivalent contrapositive '!B -> !A', so represent each rule as two directed edges in an implication graph.

Hint 2

Double negations cancel out, so '!(!X)' is simply 'X'; parse literals into signed identifiers or integer IDs.

Hint 3

Perform breadth-first or depth-first search starting from the known true literals to find all reachable literals; if literal X is reached, X is TRUE, and if literal !X is reached, X is FALSE.

Follow-up questions

  • How would your algorithm detect if the provided facts and rules contained an internal contradiction?
  • How would you extend this engine to handle conjunctions in preconditions, such as 'A AND B -> C'?
  • If rules were assigned probabilities, how would you compute the lower and upper bounds of belief for each query?