001  (ns wildwood.schema
002    "The knowledge representation. This probably ends up looking a bit like a
003    Toulmin schema, where claims are represented as propositions. There also
004    need to be rules or predicates, things which can test whether a given
005    proposition has a given value. There may be other stuff in here.
006  
007    Internal representation of most of this will be as Clojure maps."
008    )
009  
010  (def required-keys
011    "Every proposition is expected to have values for these keys."
012    #{:verb :subject :object})
013  
014  (def consensual-keys
015    "Every proposition which has these keys, in a given decision process,
016    must have the same semantics and types for their values. The exact
017    representations used for the values of these keys does not
018    matter, it is consensual between all participating advocates in a
019    decision process."
020    #{:time       ;; a representation of time - which should have a canonical ordering;
021      :location   ;; a representation of place - which may have concepts of proximity;
022      :truth      ;; if present and value `false`, negates the proposition;
023      :data       ;; an argument structure...!
024      })
025  
026  (def argument-keys
027    "Every argument is a proposition, which additionally has these keys."
028    #{:confidence ;; how sure am I? A value, perhaps, in the range -1 to 1, although conventionally if less than 1 we probably set the `:truth` value to false;
029      :authority  ;; id of agent from whom, or rule from which, I know this.
030      })
031  
032  (def preserved-keys
033    "Keys whose values should not be minimised during proposition minimisation"
034    ;; TODO: actually, this may end up being just :data
035    (set (cons :data argument-keys)))
036  
037  (defn proposition?
038    "True if `o` qualifies as a proposition. A proposition is probably a map
039    with some privileged keys, and may look something like a minimised
040    `the-great-game.gossip.news-items` item.
041  
042    If `minimised` is passed and is `true`, then the proposition must
043    be minimised - that is to say, the values of keys in a proposition map may
044    not themselves be keys. Where the value of a key represents an object in the
045    world, that value must be simply the `id` of the object, not a richer
046    representation."
047    ([o]
048     (and
049       (map? o)
050       (every? #(o %) required-keys)))
051    ([o minimised]
052     (and
053       (proposition? o))
054     (not
055       (when
056         (true? minimised)
057         ;; not good enough. An argument is a proposition even if its argument-keys
058         ;; are not minimised (indeed, they should not be). TODO: fix.
059         (some map? (vals o))))))
060  
061  (defn truth
062    "If `p` is a proposition, return whether the value asserted by that
063    proposition is `true`. If the `:truth` key is missing, `true` is
064    assumed."
065    ;; TODO: for orthogonality, this might be renamed `decide`.
066    [p]
067    (if
068      (proposition? p)
069      (if
070        (false? (:truth p))
071        false
072        true)
073      nil))
074  
075  (defn rule?
076    "True if `o` qualifies as a rule. A rule is a structure which comprises
077    * an id and
078    * a function of two arguments, a proposition and a knowledge accessor,
079    and which should (if this can simply be checked) return an argument
080    structure."
081    [o]
082    ;; TODO: write this. In practice it may be simpler if we defprotocol or
083    ;; defrecord a rule structure.
084    false)
085  
086  (defn argument?
087    "True if `o` qualifies as an argument structure.
088  
089    An argument structure is a (potentially rich) proposition which, in addition, should have values
090    for `:confidence` and `:authority`. A value for `:data` may, and probably will,
091    also be present but is not required. The value of `:confidence` must be a number
092    in the range -1 to 1."
093    [o]
094    (and
095      (proposition? o)
096      (every? #(o %) argument-keys)
097      (number? (:confidence o))
098      (<= -1 (:confidence o) 1)))
099  
100  (set (cons :data argument-keys))
101  
102  (defn minimise
103    "Expecting that `o` is a (potentially rich) proposition, return a map identical
104    to `o` save that for each value `v` of key `k` in `o`, if `v` is a map and `k`
105    is not a member of `argument-keys`, then the returned map shall substitute the
106    value of `(:id v)`.
107  
108    see also `wildwood.knowledge-access/maximise`."
109    [o]
110    (if
111      (map? o)
112      (reduce
113        merge
114        {}
115        (map
116          (fn [k]
117            {k
118             (let [v (k o)]
119               (if
120                 (and (not (preserved-keys k)) (map? v))
121                 (:id v)
122                 v))})
123          (keys o)))
124      o))
125  
126  (proposition?
127    (minimise {:verb :kill
128               :subject {:id :brutus :name "Marcus Brutus"}
129               :object {:id :caesar :name "Gaius Julius Caesar" :wife :drusila}}))