
Master-Student @ Uni Ulm
PhD-Student @ Uni Würzburg
name/arity
… ==> …
)… <=> …
)… \ … <=> …
)Propagation Rule
Name @ H1, …, Hn ==> G1, …, Gm | B1, …, Bl
Simplification Rule
Name @ H1, …, Hn <=> G1, …, Gm | B1, …, Bl
Simpagation Rule
Name @ H1, …, Hk \ Hk+1 …, Hn <=> G1, …, Gm | B1, …, Bl
gcd
ExampleExample Program: Calculation of the greatest common divisor (GCD) using the subtraction-based Euclidean algorithm.
function gcd(a, b) while b > 0 if a > b a := a - b else b := b - a return a end
gcd(15, 12) == 3
gcd
Examplegcd1 @ gcd(0) <=> true. gcd2 @ gcd(N) \ gcd(M) <=> 0 < N, N <= M | gcd(M-N).
?- gcd(15), gcd(12) ... gcd(3)
Any application that can be written in JavaScript, will eventually be written in JavaScript.
let Constraint = CHR.Constraint
let gcd8 = new Constraint('gcd', 1, [ 8 ])
// name, arity, arguments
// some properties:
gcd8.id // unique
gcd8.alive // boolean
// prototype methods:
gcd8.toString() // 'gcd(8)'
let chr = new CHR()
let store = chr.Store // or:
// new CHR.Store()
// some properties:
store.length // int
store.invalid // boolean
// prototype methods:
store.add(gcd8)
store.kill(gcd8)
store.alive(gcd8) // boolean
store.reset()
store.toString() // tabular string representation
store.lookup(name, args) // generator
// events:
store.on('add', handler)
store.on('remove', handler)
let chr = new CHR()
let history = chr.History // or:
// new CHR.History()
// some methods:
history.add(ruleName, constraintIds)
history.has(ruleName, constraintIds)
history.notIn(ruleName, constraintIds)
let chr = new CHR()
chr`
ruleName @ gcd(0) <=> true
` // or:
// new CHR.Rule('gcd(0) <=> true')
let rule = chr.Rules.ruleName
// some methods:
rule.Fire(constraint)
// events resp. breakpoints:
rule.Breakpoints.onTry = handler
let firstGcdOccurrence = rule['gcd/1'][0]
firstGcdOccurrence.Breakpoints.onTry = handler
let chr = new CHR()
chr`
gcd1 @ gcd(0) <=> true
gcd2 @ gcd(N) \\ gcd(M) <=> 0 < N, N <= M | gcd(M-N)
`
// How to call gcd(15), gcd(12) ?
// Not working because of asynchronous functions:
// chr.gcd(15)
// chr.gcd(12)
// let result = chr.store.lookup(...)
In node.js everything runs in parallel,
except your code.
while queue.waitForMessage() queue.processNextMessage() end
gcd
Example, Naive Recursive Implementationfunction gcd (a, b) { if (b == 0) return a if (a > b) return gcd(a-b, b) return gcd(a, b-a) }
gcd
Example, Asynchronous Implementationfunction gcd (a, b, callback) { if (b == 0) { callback(a) } else if (a > b) { setTimeout(function () { gcd(a-b, b, callback) }, 0) } else { setTimeout(function () { gcd(a, b-a, callback) }, 0) } }
let chr = ...
chr.gcd(15).then(function () {
return chr.gcd(12)
}).then(function () {
// finished
})
Promise
.all([ chr.gcd(15), chr.gcd(12) ])
.then(function () {
// finished
})
gcd
Examplegcd1 @ gcd(0) <=> true. gcd2 @ gcd(N) \ gcd(M) <=> 0 < N, N <= M | gcd(M-N).
function (constraint,replacements) {
var M = constraint.args[0]
var constraintIds = [
self.Store.lookup("gcd", 1)
, [ constraint.id ]
]
return new Promise(function (resolve, reject) {
self.Helper.forEach(constraintIds,
function iterateConstraint (ids, callback) {
if (!self.Store.allAlive(ids)) return callback()
if (self.History.has("gcd2", ids)) return callback()
var N = self.Store.args(ids[0])[0]
...
}
})
}
...
var N = self.Store.args(ids[0])[0]
var guards = [
new Promise(function (s, j) { (0 < N) ? s() : j() })
, new Promise(function (s, j) { (N <= M) ? s() : j() })
]
Promise.all(guards)
.then(function () {
self.History.add("gcd2", ids)
self.Store.kill(ids[1])
Promise.resolve().then(function () {
return self.gcd(M - N)
})
})
}, resolve)
})
}
question(X) ==> ask(X)
Parse the given CHR source and create a syntax tree.
rem_long @ path(X,Y,L1) \ path(X,Y,L2) <=> L1 <= L2 | true;
path_add @ path(X,Y,L1), path(Y,Z,L2) ==> X !== Z | path(X,Z,L1+L2);
Modifications:
;
Start
= Program
CHRRule
= PropagationRule
/ SimplificationRule
/ SimpagationRule
PropagationRule
= RuleName? CHRConstraints "==>" Guard? Body {
...
}
RuleName
= identifier:Identifier "@" {
return identifier;
}
function _chr () {
/**
... static implementation for CHR runtime components ...
*/
function State (constraint, type, step, lookup, scope) {
this.type = type
this.constraint = constraint
this.step = step
this.lookup = lookup
this.scope = scope
}
function saveState (constraint, step, lookup, scope) {
return new State(constraint, 'intermediate', step, lookup, scope)
}
function constraintState (constraint) {
return new State(constraint, 'constraint', null, null, null)
}
function _chr () {
...
function tell () {
var current
while (chr.Tells.length > 0) {
current = chr.Tells.pop()
if (current.type === 'constraint') {
chr.Store.add(current.constraint)
}
dispatchTell(current)(current)
}
}
function dispatchTell (current) {
switch (current.constraint.functor) {
case 'gcd/1':
return gcd_1
break
}
}