Skip to content

Commit 547edbe

Browse files
committed
Added the simplifier, although it's not currently used, I don't think
1 parent 7170970 commit 547edbe

3 files changed

Lines changed: 151 additions & 22 deletions

File tree

project.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
:url "http://www.gnu.org/licenses/gpl-2.0.html"}
1313
:plugins [[lein-marginalia "0.7.1"]]
1414
:dependencies [[org.clojure/clojure "1.6.0"]
15-
[org.clojure/tools.trace "0.7.8"]
16-
[instaparse "1.3.5"]
15+
[org.clojure/tools.trace "0.7.9"]
16+
[instaparse "1.4.1"]
1717
[mw-engine "0.1.5-SNAPSHOT"]
1818
])

src/mw_parser/declarative.clj

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
DISJUNCT-CONDITION := CONDITION SPACE OR SPACE CONDITIONS;
2323
CONJUNCT-CONDITION := CONDITION SPACE AND SPACE CONDITIONS;
2424
CONDITION := NEIGHBOURS-CONDITION | PROPERTY-CONDITION;
25-
NEIGHBOURS-CONDITION := QUANTIFIER SPACE NEIGHBOURS SPACE IS SPACE PROPERTY-CONDITION | QUANTIFIER SPACE NEIGHBOURS IS EXPRESSION | QUALIFIER SPACE NEIGHBOURS-CONDITION;
25+
WITHIN-CONDITION := NEIGHBOURS-CONDITION SPACE WITHIN SPACE NUMERIC-EXPRESSION;
26+
NEIGHBOURS-CONDITION := WITHIN-CONDITION | QUANTIFIER SPACE NEIGHBOURS SPACE IS SPACE PROPERTY-CONDITION | QUANTIFIER SPACE NEIGHBOURS IS EXPRESSION | QUALIFIER SPACE NEIGHBOURS-CONDITION;
2627
PROPERTY-CONDITION := PROPERTY SPACE QUALIFIER SPACE EXPRESSION;
2728
EXPRESSION := SIMPLE-EXPRESSION | RANGE-EXPRESSION | NUMERIC-EXPRESSION | DISJUNCT-EXPRESSION | VALUE;
2829
SIMPLE-EXPRESSION := QUALIFIER SPACE EXPRESSION | VALUE;
@@ -46,6 +47,7 @@
4647
NONE := 'no';
4748
ALL := 'all'
4849
BETWEEN := 'between';
50+
WITHIN := 'within';
4951
IN := 'in';
5052
MORE := 'more';
5153
LESS := 'less' | 'fewer';
@@ -178,22 +180,57 @@
178180
:SYMBOL (list (keyword (second (second tree))) 'cell)
179181
(generate (second tree))))
180182

181-
;; (defn generate-neighbours-condition
182-
;; "Generate code for a condition which refers to neighbours."
183-
;; ([tree]
184-
;; (let [q (second tree)]
185-
;; (if (number? q)
186-
;; (generate-neighbours-condition '= q
187-
;; ([comp1 quantity property value remainder comp2 distance]
188-
;; [(list comp1
189-
;; (list 'count
190-
;; (list 'get-neighbours-with-property-value 'world
191-
;; '(cell :x) '(cell :y) distance
192-
;; (keyword property) (keyword-or-numeric value) comp2))
193-
;; quantity)
194-
;; remainder])
195-
;; ([comp1 quantity property value remainder comp2]
196-
;; (gen-neighbours-condition comp1 quantity property value remainder comp2 1)))
183+
(defn generate-neighbours-condition
184+
"Generate code for a condition which refers to neighbours."
185+
([tree]
186+
(generate-neighbours-condition tree (first (second tree))))
187+
([tree quantifier-type]
188+
(let [quantifier (second (second tree))
189+
pc (generate (nth tree 4))]
190+
(case quantifier-type
191+
:NUMBER (generate-neighbours-condition '= (read-string quantifier) pc 1)
192+
:SOME (generate-neighbours-condition '> 0 pc 1)
193+
:QUANTIFIER
194+
(let [comparative (generate (simplify (second quantifier)))
195+
value (simplify (nth quantifier 5))]
196+
(generate-neighbours-condition comparative value pc 1)))))
197+
([comp1 quantity property-condition distance]
198+
(list comp1
199+
(list 'count (list 'remove false (list 'map (list 'fn ['cell] property-condition) '(get-neighbours cell world distance)))) quantity))
200+
([comp1 quantity property-condition]
201+
(generate-neighbours-condition comp1 quantity property-condition 1)))
202+
203+
;; (def s1 "if 3 neighbours have state equal to forest then state should be forest")
204+
;; (def s2 "if some neighbours have state equal to forest then state should be forest")
205+
;; (def s3 "if more than 3 neighbours have state equal to forest then state should be forest")
206+
;; (def s4 "if fewer than 3 neighbours have state equal to forest then state should be forest")
207+
;; (def s5 "if all neighbours have state equal to forest then state should be forest")
208+
;; (def s6 "if more than 3 neighbours within 2 have state equal to forest then state should be forest")
209+
210+
;; (nth (simplify (parse-rule s1)) 2)
211+
;; (second (nth (simplify (parse-rule s1)) 2))
212+
;; (nth (simplify (parse-rule s2)) 2)
213+
;; (map simplify (nth (simplify (parse-rule s2)) 2))
214+
;; ;; (second (nth (simplify (parse-rule s2)) 2))
215+
;; ;; (nth (simplify (parse-rule s3)) 2)
216+
;; (second (nth (simplify (parse-rule s3)) 2))
217+
;; (map simplify (second (nth (simplify (parse-rule s3)) 2)))
218+
;; ;; (nth (simplify (parse-rule s4)) 2)
219+
;; ;; (second (nth (simplify (parse-rule s4)) 2))
220+
;; ;; (nth (simplify (parse-rule s5)) 2)
221+
;; ;; (second (nth (simplify (parse-rule s5)) 2))
222+
;; ;; (nth (simplify (parse-rule s6)) 2)
223+
;; ;; (second (nth (simplify (parse-rule s6)) 2))
224+
225+
;; ;; (generate (nth (nth (simplify (parse-rule s5)) 2) 4))
226+
;; ;; (generate (nth (simplify (parse-rule s2)) 2))
227+
;; ;; (generate (nth (simplify (parse-rule s1)) 2))
228+
229+
230+
;; (generate-neighbours-condition '= 3 '(= (:state cell) :forest) 1)
231+
;; (generate-neighbours-condition (nth (simplify (parse-rule s3)) 2))
232+
;; (generate-neighbours-condition (nth (simplify (parse-rule s2)) 2))
233+
;; (generate-neighbours-condition (nth (simplify (parse-rule s1)) 2))
197234

198235

199236
(defn generate
@@ -209,7 +246,6 @@
209246
:CONDITIONS (generate-conditions tree)
210247
:CONJUNCT-CONDITION (generate-conjunct-condition tree)
211248
:DISJUNCT-CONDITION (generate-disjunct-condition tree)
212-
:PROPERTY-CONDITION (generate-property-condition tree)
213249
:DISJUNCT-EXPRESSION (generate (nth tree 2))
214250
:DISJUNCT-VALUE (generate-disjunct-value tree)
215251
:EQUIVALENCE '=
@@ -220,10 +256,11 @@
220256
= 'not=
221257
> '<
222258
< '>)
223-
;; :NEIGHBOURS-CONDITION (generate-neighbours-condition tree)
259+
:NEIGHBOURS-CONDITION (generate-neighbours-condition tree)
224260
:NUMERIC-EXPRESSION (generate-numeric-expression tree)
225261
:NUMBER (read-string (second tree))
226262
:PROPERTY (list (generate (second tree)) 'cell) ;; dubious - may not be right
263+
:PROPERTY-CONDITION (generate-property-condition tree)
227264
:QUALIFIER (generate (second tree))
228265
:RULE (generate-rule tree)
229266
:SIMPLE-ACTION (generate-simple-action tree)
@@ -271,7 +308,7 @@
271308
:CONDITION (simplify-second-of-two tree)
272309
:CONDITIONS (simplify-second-of-two tree)
273310
:EXPRESSION (simplify-second-of-two tree)
274-
:QUANTIFIER (simplify-second-of-two tree)
311+
;; :QUANTIFIER (simplify-second-of-two tree)
275312
:NOT nil
276313
:PROPERTY (simplify-second-of-two tree)
277314
:SPACE nil

src/mw_parser/simplifier.clj

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
(ns mw-parser.simplifier
2+
(:use mw-engine.utils
3+
mw-parser.parser))
4+
5+
(declare simplify)
6+
7+
(defn simplify-qualifier
8+
"Given that this `tree` fragment represents a qualifier, what
9+
qualifier is that?"
10+
[tree]
11+
(cond
12+
(empty? tree) nil
13+
(and (coll? tree)
14+
(member? (first tree) '(:EQUIVALENCE :COMPARATIVE))) tree
15+
(coll? (first tree)) (or (simplify-qualifier (first tree))
16+
(simplify-qualifier (rest tree)))
17+
(coll? tree) (simplify-qualifier (rest tree))
18+
true tree))
19+
20+
(defn simplify-second-of-two
21+
"There are a number of possible simplifications such that if the `tree` has
22+
only two elements, the second is semantically sufficient."
23+
[tree]
24+
(if (= (count tree) 2) (simplify (nth tree 1)) tree))
25+
26+
27+
(defn simplify-some
28+
"'some' is the same as 'more than zero'"
29+
[tree]
30+
[:COMPARATIVE '> 0])
31+
32+
(defn simplify-none
33+
"'none' is the same as 'zero'"
34+
[tree]
35+
[:COMPARATIVE '= 0])
36+
37+
(defn simplify-all
38+
"'all' isn't actually the same as 'eight', because cells at the edges of the world have
39+
fewer than eight neighbours; but it's a simplifying (ha!) assumption for now."
40+
[tree]
41+
[:COMPARATIVE '= 8])
42+
43+
(defn simplify-quantifier
44+
"If this quantifier is a number, 'simplifiy' it into a comparative whose operator is '='
45+
and whose quantity is that number. This is actually more complicated but makes generation easier."
46+
[tree]
47+
(if (number? (second tree)) [:COMPARATIVE '= (second tree)] (simplify (second tree))))
48+
49+
(defn simplify
50+
"Simplify/canonicalise this `tree`. Opportunistically replace complex fragments with
51+
semantically identical simpler fragments"
52+
[tree]
53+
(if
54+
(coll? tree)
55+
(case (first tree)
56+
:SPACE nil
57+
:QUALIFIER (simplify-qualifier tree)
58+
:CONDITIONS (simplify-second-of-two tree)
59+
:CONDITION (simplify-second-of-two tree)
60+
:EXPRESSION (simplify-second-of-two tree)
61+
:COMPARATIVE (simplify-second-of-two tree)
62+
:QUANTIFIER (simplify-quantifier tree)
63+
:VALUE (simplify-second-of-two tree)
64+
:PROPERTY (simplify-second-of-two tree)
65+
:ACTIONS (simplify-second-of-two tree)
66+
:ACTION (simplify-second-of-two tree)
67+
:ALL (simplify-all tree)
68+
:SOME (simplify-some tree)
69+
:NONE (simplify-none tree)
70+
(remove nil? (map simplify tree)))
71+
tree))
72+
73+
(simplify (parse-rule "if state is climax and 4 neighbours have state equal to fire then 3 chance in 5 state should be fire"))
74+
(simplify (parse-rule "if state is climax and no neighbours have state equal to fire then 3 chance in 5 state should be fire"))
75+
76+
(simplify (parse-rule "if state is in grassland or pasture or heath and more than 4 neighbours have state equal to water then state should be village"))
77+
78+
(simplify (parse-rule "if 6 neighbours have state equal to water then state should be village"))
79+
80+
(simplify (parse-rule "if fertility is between 55 and 75 then state should be climax"))
81+
82+
(simplify (parse-rule "if state is forest then state should be climax"))
83+
84+
85+
(simplify (parse-rule "if state is in grassland or pasture or heath and more than 4 neighbours have state equal to water then state should be village"))
86+
(simplify (parse-rule "if altitude is less than 100 and state is forest then state should be climax and deer should be 3"))
87+
(simplify (parse-rule "if altitude is 100 or fertility is 25 then state should be heath and fertility should be 24.3"))
88+
(simplify (parse-rule "if altitude is 100 or fertility is 25 then state should be heath"))
89+
90+
(simplify (parse-rule "if deer is more than 2 and wolves is 0 and fertility is more than 20 then deer should be deer + 2"))
91+
(simplify (parse-rule "if deer is more than 1 and wolves is more than 1 then deer should be deer - wolves"))
92+
(simplify (parse-rule "if state is grassland and 4 neighbours have state equal to water then state should be village"))

0 commit comments

Comments
 (0)