2020-02-06 09:58:52 +01:00
2020-02-06 09:58:52 +01:00
2020-02-06 09:58:52 +01:00
2020-02-06 09:58:52 +01:00
2020-02-06 09:58:52 +01:00
2020-02-06 09:58:52 +01:00
2020-02-06 09:58:52 +01:00

infer

is a simple inference engine. Its inspired by pgergis little library. I built my version based on the initial description and realized I ended up with a super different internal solution and decided it was interesting enough to be kept around.

For a problem description read the README of pgergis repo.

Example Usage

Using the human/mortal syllogism we end up with the following interaction:

$ infer '[{"premises": ["mortal", "alive"], "conclusion": "will die"}, {"premises": ["human"], "conclusion": "mortal"}]' human alive
Inferred the following statements: alive, human, mortal, will die

That seems right!

As you can see, usage is a little different. Firstly, the premisses are not a list but instead use the rest of the arguments after the JSON-formatted rules list. Secondly we pretty-print the results a little.

How does it work?

First we parse the JSON rules. Then we run infer, which will try and match the known premises against all the premises of the rules. If we find a match we insert it into the new known premises and discard the rule, since we know we dont have to apply it anymore. We do this until trying to apply all the rules does not yield any new results.

The code Ive written is fairly terse, so heres an annotated version of infer:

-- pre are the known premises, env is the rule environment
infer :: S.Set String -> [Rule] -> S.Set String
infer pre env =
  -- find will get us a tuple of found premises and the new set of rules
  let (found, nenv) = find
  -- if the new premises are nothing new were done
  in if S.isSubsetOf found pre
     then pre
     -- otherwise we do it all over again with our new premises and env
     else infer (S.union found pre) nenv
  -- find goes over the environment, building a tuple of premises and
  -- still applicable rules
  where find = foldr mlook (S.empty, []) env
        -- mlook gets a rule, the new found premises, and the new env
        mlook r@Rule{premises, conclusion} (f, e) =
          if S.isSubsetOf premises pre
          -- if the premise matches, we add the conclusion and ignore the
          -- rule, since we know its been applied
          then (S.insert conclusion f, e)
          -- otherwise we ignore the conclusion and add the rule for later
          -- retesting
          else (f, r:e)

Have fun!

Description
A syllogism engine, inspired by
https://github.com/pgergis/haskell-inferences
Readme 44 KiB
Languages
Haskell 100%