deltablue.lua 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314
  1. -- This code is derived from the SOM benchmarks, see AUTHORS.md file.
  2. --
  3. -- Copyright (c) 2016 Francois Perrad <[email protected]>
  4. --
  5. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  6. -- of this software and associated documentation files (the 'Software'), to deal
  7. -- in the Software without restriction, including without limitation the rights
  8. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. -- copies of the Software, and to permit persons to whom the Software is
  10. -- furnished to do so, subject to the following conditions:
  11. --
  12. -- The above copyright notice and this permission notice shall be included in
  13. -- all copies or substantial portions of the Software.
  14. --
  15. -- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. -- THE SOFTWARE.
  22. --[[
  23. The module 'bit' is available with:
  24. * LuaJIT
  25. * LuaBitOp extension which is available for:
  26. * Lua 5.1
  27. * Lua 5.2
  28. The module 'bit32' is available with:
  29. * Lua 5.2
  30. * Lua 5.3 when compiled with LUA_COMPAT_5_2
  31. The bitwise operators are added to Lua 5.3 as new lexemes (there causes
  32. lexical error in older version)
  33. --]]
  34. local band, bxor, rshift
  35. if _VERSION < 'Lua 5.3' then
  36. local bit = bit32 or require'bit'
  37. band = bit.band
  38. bxor = bit.bxor
  39. rshift = bit.rshift
  40. else
  41. band = assert(load'--[[band]] return function (a, b) return a & b end')()
  42. bxor = assert(load'--[[bxor]] return function (a, b) return a ~ b end')()
  43. rshift = assert(load'--[[rshift]] return function (a, b) return a >> b end')()
  44. end
  45. local alloc_array
  46. local ok, table_new = pcall(require, 'table.new') -- LuaJIT 2.1 extension
  47. if ok then
  48. alloc_array = function (n)
  49. local t = table_new(n, 1)
  50. t.n = n
  51. return t
  52. end
  53. else
  54. alloc_array = function (n)
  55. local t = {}
  56. t.n = n
  57. return t
  58. end
  59. end
  60. local Vector = {_CLASS = 'Vector'} do
  61. local floor = math.floor
  62. function Vector.new (size)
  63. local obj = {
  64. storage = alloc_array(size or 50),
  65. first_idx = 1,
  66. last_idx = 1,
  67. }
  68. return setmetatable(obj, {__index = Vector})
  69. end
  70. function Vector.with (elem)
  71. local v = Vector.new(1)
  72. v:append(elem)
  73. return v
  74. end
  75. function Vector:at (idx)
  76. if idx > self.storage.n then
  77. return nil
  78. end
  79. return self.storage[idx]
  80. end
  81. function Vector:at_put (idx, val)
  82. if idx > self.storage.n then
  83. local new_n = self.storage.n
  84. while idx > new_n do
  85. new_n = new_n * 2
  86. end
  87. local new_storage = alloc_array(new_n)
  88. for i = 1, self.storage.n do
  89. new_storage[i] = self.storage[i]
  90. end
  91. self.storage = new_storage
  92. end
  93. self.storage[idx] = val
  94. if self.last_idx < idx + 1 then
  95. self.last_idx = idx + 1
  96. end
  97. end
  98. function Vector:append (elem)
  99. if self.last_idx > self.storage.n then
  100. -- Need to expand capacity first
  101. local new_storage = alloc_array(2 * self.storage.n)
  102. for i = 1, self.storage.n do
  103. new_storage[i] = self.storage[i]
  104. end
  105. self.storage = new_storage
  106. end
  107. self.storage[self.last_idx] = elem
  108. self.last_idx = self.last_idx + 1
  109. end
  110. function Vector:is_empty ()
  111. return self.last_idx == self.first_idx
  112. end
  113. function Vector:each (fn)
  114. for i = self.first_idx, self.last_idx - 1 do
  115. fn(self.storage[i])
  116. end
  117. end
  118. function Vector:has_some (fn)
  119. for i = self.first_idx, self.last_idx - 1 do
  120. if fn(self.storage[i]) then
  121. return true
  122. end
  123. end
  124. return false
  125. end
  126. function Vector:get_one (fn)
  127. for i = self.first_idx, self.last_idx - 1 do
  128. local e = self.storage[i]
  129. if fn(e) then
  130. return e
  131. end
  132. end
  133. return nil
  134. end
  135. function Vector:remove_first ()
  136. if self:is_empty() then
  137. return nil
  138. end
  139. self.first_idx = self.first_idx + 1
  140. return self.storage[self.first_idx - 1]
  141. end
  142. function Vector:remove (obj)
  143. local new_array = alloc_array(self:capacity())
  144. local new_last = 1
  145. local found = false
  146. self:each(function (it)
  147. if it == obj then
  148. found = true
  149. else
  150. new_array[new_last] = it
  151. new_last = new_last + 1
  152. end
  153. end)
  154. self.storage = new_array
  155. self.last_idx = new_last
  156. self.first_idx = 1
  157. return found
  158. end
  159. function Vector:remove_all ()
  160. self.first_idx = 1
  161. self.last_idx = 1
  162. self.storage = alloc_array(self:capacity())
  163. end
  164. function Vector:size ()
  165. return self.last_idx - self.first_idx
  166. end
  167. function Vector:capacity ()
  168. return self.storage.n
  169. end
  170. function Vector:sort (fn)
  171. -- Make the argument, block, be the criterion for ordering elements of
  172. -- the receiver.
  173. -- Sort blocks with side effects may not work right.
  174. if self:size() > 0 then
  175. self:sort_range(self.first_idx, self.last_idx - 1, fn)
  176. end
  177. end
  178. function Vector:sort_range (i, j, fn)
  179. assert(fn)
  180. -- The prefix d means the data at that index.
  181. local n = j + 1 - i
  182. if n <= 1 then
  183. -- Nothing to sort
  184. return
  185. end
  186. local storage = self.storage
  187. -- Sort di, dj
  188. local di = storage[i]
  189. local dj = storage[j]
  190. -- i.e., should di precede dj?
  191. if not fn(di, dj) then
  192. local tmp = storage[i]
  193. storage[i] = storage[j]
  194. storage[j] = tmp
  195. local tt = di
  196. di = dj
  197. dj = tt
  198. end
  199. -- NOTE: For DeltaBlue, this is never reached.
  200. if n > 2 then -- More than two elements.
  201. local ij = floor((i + j) / 2) -- ij is the midpoint of i and j.
  202. local dij = storage[ij] -- Sort di,dij,dj. Make dij be their median.
  203. if fn(di, dij) then -- i.e. should di precede dij?
  204. if not fn(dij, dj) then -- i.e., should dij precede dj?
  205. local tmp = storage[j]
  206. storage[j] = storage[ij]
  207. storage[ij] = tmp
  208. dij = dj
  209. end
  210. else -- i.e. di should come after dij
  211. local tmp = storage[i]
  212. storage[i] = storage[ij]
  213. storage[ij] = tmp
  214. dij = di
  215. end
  216. if n > 3 then -- More than three elements.
  217. -- Find k>i and l<j such that dk,dij,dl are in reverse order.
  218. -- Swap k and l. Repeat this procedure until k and l pass each other.
  219. local k = i
  220. local l = j - 1
  221. while true do
  222. -- i.e. while dl succeeds dij
  223. while k <= l and fn(dij, storage[l]) do
  224. l = l - 1
  225. end
  226. k = k + 1
  227. -- i.e. while dij succeeds dk
  228. while k <= l and fn(storage[k], dij) do
  229. k = k + 1
  230. end
  231. if k > l then
  232. break
  233. end
  234. local tmp = storage[k]
  235. storage[k] = storage[l]
  236. storage[l] = tmp
  237. end
  238. -- Now l < k (either 1 or 2 less), and di through dl are all
  239. -- less than or equal to dk through dj. Sort those two segments.
  240. self:sort_range(i, l, fn)
  241. self:sort_range(k, j, fn)
  242. end
  243. end
  244. end
  245. end -- class Vector
  246. local Set = {_CLASS = 'Set'} do
  247. local INITIAL_SIZE = 10
  248. function Set.new (size)
  249. local obj = {
  250. items = Vector.new(size or INITIAL_SIZE)
  251. }
  252. return setmetatable(obj, {__index = Set})
  253. end
  254. function Set:size ()
  255. return self.items:size()
  256. end
  257. function Set:each (fn)
  258. self.items:each(fn)
  259. end
  260. function Set:has_some (fn)
  261. return self.items:has_some(fn)
  262. end
  263. function Set:get_one (fn)
  264. return self.items:get_one(fn)
  265. end
  266. function Set:add (obj)
  267. if not self:contains(obj) then
  268. self.items:append(obj)
  269. end
  270. end
  271. function Set:remove_all ()
  272. self.items:remove_all()
  273. end
  274. function Set:collect (fn)
  275. local coll = Vector.new()
  276. self:each(function (it)
  277. coll:append(fn(it))
  278. end)
  279. return coll
  280. end
  281. function Set:contains (obj)
  282. return self:has_some(function (it) return it == obj end)
  283. end
  284. end -- class Set
  285. local IdentitySet = {_CLASS = 'IdentitySet'} do
  286. setmetatable(IdentitySet, {__index = Set})
  287. function IdentitySet.new (size)
  288. local obj = Set.new(size)
  289. return setmetatable(obj, {__index = IdentitySet})
  290. end
  291. function IdentitySet:contains (obj)
  292. return self:has_some(function (it) return it == obj end)
  293. end
  294. end -- class IdentitySet
  295. local Entry = {_CLASS = 'Entry'} do
  296. function Entry.new (hash, key, value, next)
  297. local obj = {
  298. hash = hash,
  299. key = key,
  300. value = value,
  301. next = next,
  302. }
  303. return setmetatable(obj, {__index = Entry})
  304. end
  305. function Entry:match (hash, key)
  306. return self.hash == hash and self.key == key
  307. end
  308. end -- class Entry
  309. local Dictionary = {_CLASS = 'Dictionary'} do
  310. local INITIAL_CAPACITY = 16
  311. function Dictionary.new (size)
  312. local obj = {
  313. buckets = alloc_array(size or INITIAL_CAPACITY),
  314. size = 0,
  315. }
  316. return setmetatable(obj, {__index = Dictionary})
  317. end
  318. function Dictionary:hash (key)
  319. if not key then
  320. return 0
  321. end
  322. local hash = key:custom_hash()
  323. return bxor(hash, rshift(hash, 16))
  324. end
  325. function Dictionary:is_empty ()
  326. return self.size == 0
  327. end
  328. function Dictionary:get_bucket_idx (hash)
  329. return band(self.buckets.n - 1, hash) + 1
  330. end
  331. function Dictionary:get_bucket (hash)
  332. return self.buckets[self:get_bucket_idx(hash)]
  333. end
  334. function Dictionary:at (key)
  335. local hash = self:hash(key)
  336. local e = self:get_bucket(hash)
  337. while e do
  338. if e:match(hash, key) then
  339. return e.value
  340. end
  341. e = e.next
  342. end
  343. return nil
  344. end
  345. function Dictionary:contains_key (key)
  346. local hash = self:hash(key)
  347. local e = self:get_bucket(hash)
  348. while e do
  349. if e.match(hash, key) then
  350. return true
  351. end
  352. e = e.next
  353. end
  354. return false
  355. end
  356. function Dictionary:at_put (key, value)
  357. local hash = self:hash(key)
  358. local i = self:get_bucket_idx(hash)
  359. local current = self.buckets[i]
  360. if not current then
  361. self.buckets[i] = self:new_entry(key, value, hash)
  362. self.size = self.size + 1
  363. else
  364. self:insert_bucket_entry(key, value, hash, current)
  365. end
  366. if self.size > self.buckets.n then
  367. self:resize()
  368. end
  369. end
  370. function Dictionary:new_entry (key, value, hash)
  371. return Entry.new(hash, key, value, nil)
  372. end
  373. function Dictionary:insert_bucket_entry (key, value, hash, head)
  374. local current = head
  375. while true do
  376. if current:match(hash, key) then
  377. current.value = value
  378. return
  379. end
  380. if not current.next then
  381. self.size = self.size + 1
  382. current.next = self:new_entry(key, value, hash)
  383. return
  384. end
  385. current = current.next
  386. end
  387. end
  388. function Dictionary:resize ()
  389. local old_storage = self.buckets
  390. self.buckets = alloc_array(old_storage.n * 2)
  391. self:transfer_entries(old_storage)
  392. end
  393. function Dictionary:transfer_entries (old_storage)
  394. local buckets = self.buckets
  395. for i = 1, old_storage.n do
  396. local current = old_storage[i]
  397. if current then
  398. old_storage[i] = nil
  399. if not current.next then
  400. local hash = band(current.hash, buckets.n - 1) + 1
  401. buckets[hash] = current
  402. else
  403. self:split_bucket(old_storage, i, current)
  404. end
  405. end
  406. end
  407. end
  408. function Dictionary:split_bucket (old_storage, i, head)
  409. local lo_head, lo_tail = nil, nil
  410. local hi_head, hi_tail = nil, nil
  411. local current = head
  412. while current do
  413. if band(current.hash, old_storage.n) == 0 then
  414. if not lo_tail then
  415. lo_head = current
  416. else
  417. lo_tail.next = current
  418. end
  419. lo_tail = current
  420. else
  421. if not hi_tail then
  422. hi_head = current
  423. else
  424. hi_tail.next = current
  425. end
  426. hi_tail = current
  427. end
  428. current = current.next
  429. end
  430. if lo_tail then
  431. lo_tail.next = nil
  432. self.buckets[i] = lo_head
  433. end
  434. if hi_tail then
  435. hi_tail.next = nil
  436. self.buckets[i + old_storage.n] = hi_head
  437. end
  438. end
  439. function Dictionary:remove_all ()
  440. self.buckets = alloc_array(self.buckets.n)
  441. self.size = 0
  442. end
  443. function Dictionary:keys ()
  444. local keys = Vector.new(self.size)
  445. local buckets = self.buckets
  446. for i = 1, buckets.n do
  447. local current = buckets[i]
  448. while current do
  449. keys:append(current.key)
  450. current = current.next
  451. end
  452. end
  453. return keys
  454. end
  455. function Dictionary:values ()
  456. local vals = Vector.new(self.size)
  457. local buckets = self.buckets
  458. for i = 1, buckets.n do
  459. local current = buckets[i]
  460. while current do
  461. vals:append(current.value)
  462. current = current.next
  463. end
  464. end
  465. return vals
  466. end
  467. end -- class Dictionary
  468. local IdEntry = {_CLASS = 'IdEntry'} do
  469. setmetatable(IdEntry, {__index = Entry})
  470. function IdEntry.new (hash, key, value, next)
  471. local obj = Entry.new (hash, key, value, next)
  472. return setmetatable(obj, {__index = IdEntry})
  473. end
  474. function IdEntry:match (hash, key)
  475. return self.hash == hash and self.key == key
  476. end
  477. end -- class IdEntry
  478. local IdentityDictionary = {_CLASS = 'IdentityDictionary'} do
  479. setmetatable(IdentityDictionary, {__index = Dictionary})
  480. function IdentityDictionary.new (size)
  481. local obj = Dictionary.new (size)
  482. return setmetatable(obj, {__index = Dictionary})
  483. end
  484. function IdentityDictionary:new_entry (key, value, hash)
  485. return IdEntry.new(hash, key, value, nil)
  486. end
  487. end -- class IdentityDictionary
  488. local Random = {_CLASS = 'Random'} do
  489. function Random.new ()
  490. local obj = {seed = 74755}
  491. return setmetatable(obj, {__index = Random})
  492. end
  493. function Random:next ()
  494. self.seed = band(((self.seed * 1309) + 13849), 65535);
  495. return self.seed;
  496. end
  497. end -- class Random
  498. local Sym = {_CLASS = 'Sym'} do
  499. function Sym.new (hash)
  500. local obj = {hash = hash}
  501. return setmetatable(obj, {__index = Sym})
  502. end
  503. function Sym:custom_hash ()
  504. return self.hash
  505. end
  506. end -- class Sym
  507. local ABSOLUTE_STRONGEST = Sym.new(0)
  508. local REQUIRED = Sym.new(1)
  509. local STRONG_PREFERRED = Sym.new(2)
  510. local PREFERRED = Sym.new(3)
  511. local STRONG_DEFAULT = Sym.new(4)
  512. local DEFAULT = Sym.new(5)
  513. local WEAK_DEFAULT = Sym.new(6)
  514. local ABSOLUTE_WEAKEST = Sym.new(7)
  515. local Strength = {_CLASS = 'Strength'} do
  516. local function create_strength_table ()
  517. local dict = IdentityDictionary.new()
  518. dict:at_put(ABSOLUTE_STRONGEST, -10000)
  519. dict:at_put(REQUIRED, -800)
  520. dict:at_put(STRONG_PREFERRED, -600)
  521. dict:at_put(PREFERRED, -400)
  522. dict:at_put(STRONG_DEFAULT, -200)
  523. dict:at_put(DEFAULT, 0)
  524. dict:at_put(WEAK_DEFAULT, 500)
  525. dict:at_put(ABSOLUTE_WEAKEST, 10000)
  526. return dict
  527. end
  528. local STRENGHT_TABLE = create_strength_table()
  529. function Strength.new (strength_sym)
  530. local obj = {
  531. symbolic_value = strength_sym,
  532. arithmetic_value = STRENGHT_TABLE:at(strength_sym),
  533. }
  534. return setmetatable(obj, {__index = Strength})
  535. end
  536. local function create_strength_constants ()
  537. local dict = IdentityDictionary.new()
  538. STRENGHT_TABLE:keys():each(function (key)
  539. dict:at_put(key, Strength.new(key))
  540. end)
  541. return dict
  542. end
  543. local STRENGHT_CONSTANTS = create_strength_constants()
  544. function Strength.of (sym)
  545. return STRENGHT_CONSTANTS:at(sym)
  546. end
  547. Strength.ABSOLUTE_STRONGEST = Strength.of(ABSOLUTE_STRONGEST)
  548. Strength.ABSOLUTE_WEAKEST = Strength.of(ABSOLUTE_WEAKEST)
  549. Strength.REQUIRED = Strength.of(REQUIRED)
  550. function Strength:same_as (strength)
  551. return self.arithmetic_value == strength.arithmetic_value
  552. end
  553. function Strength:stronger (strength)
  554. return self.arithmetic_value < strength.arithmetic_value
  555. end
  556. function Strength:weaker (strength)
  557. return self.arithmetic_value > strength.arithmetic_value
  558. end
  559. function Strength:strongest (strength)
  560. if strength:stronger(self) then
  561. return strength
  562. else
  563. return self
  564. end
  565. end
  566. function Strength:weakest (strength)
  567. if strength:weaker(self) then
  568. return strength
  569. else
  570. return self
  571. end
  572. end
  573. end -- class Strength
  574. local AbstractConstraint = {_CLASS = 'AbstractConstraint'} do
  575. function AbstractConstraint:build (strength_sym)
  576. self.strength = Strength.of(strength_sym)
  577. end
  578. function AbstractConstraint:is_input ()
  579. return false
  580. end
  581. function AbstractConstraint:add_constraint (planner)
  582. self:add_to_graph()
  583. planner:incremental_add(self)
  584. end
  585. function AbstractConstraint:destroy_constraint (planner)
  586. if self:is_satisfied() then
  587. planner:incremental_remove(self)
  588. end
  589. self:remove_from_graph()
  590. end
  591. function AbstractConstraint:inputs_known (mark)
  592. return not self:inputs_has_one(function (v)
  593. return not ((v.mark == mark) or v.stay or (v.determined_by == nil))
  594. end)
  595. end
  596. function AbstractConstraint:satisfy (mark, planner)
  597. local overridden
  598. self:choose_method(mark)
  599. if self:is_satisfied() then
  600. -- constraint can be satisfied
  601. -- mark inputs to allow cycle detection in addPropagate
  602. self:inputs_do(function (i)
  603. i.mark = mark
  604. end)
  605. local out = self:output()
  606. overridden = out.determined_by
  607. if overridden then
  608. overridden:mark_unsatisfied()
  609. end
  610. out.determined_by = self
  611. assert(planner:add_propagate(self, mark),
  612. 'Cycle encountered adding: Constraint removed')
  613. out.mark = mark
  614. else
  615. overridden = nil
  616. assert(not self.strength:same_as(Strength.REQUIRED),
  617. 'Failed to satisfy a required constraint')
  618. end
  619. return overridden
  620. end
  621. end -- abstract class AbstractConstraint
  622. local BinaryConstraint = {_CLASS = 'BinaryConstraint'} do
  623. setmetatable(BinaryConstraint, {__index = AbstractConstraint})
  624. function BinaryConstraint:build (v1, v2, strength)
  625. AbstractConstraint.build(self, strength)
  626. self.v1 = v1
  627. self.v2 = v2
  628. self.direction = nil
  629. end
  630. function BinaryConstraint:is_satisfied ()
  631. return self.direction ~= nil
  632. end
  633. function BinaryConstraint:add_to_graph ()
  634. self.v1:add_constraint(self)
  635. self.v2:add_constraint(self)
  636. self.direction = nil
  637. end
  638. function BinaryConstraint:remove_from_graph ()
  639. if self.v1 then
  640. self.v1:remove_constraint(self)
  641. end
  642. if self.v2 then
  643. self.v2:remove_constraint(self)
  644. end
  645. self.direction = nil
  646. end
  647. function BinaryConstraint:choose_method (mark)
  648. if self.v1.mark == mark then
  649. if (self.v2.mark ~= mark) and self.strength:stronger(self.v2.walk_strength) then
  650. self.direction = 'forward'
  651. return self.direction
  652. else
  653. self.direction = nil
  654. return nil
  655. end
  656. end
  657. if self.v2.mark == mark then
  658. if (self.v1.mark ~= mark) and self.strength:stronger(self.v1.walk_strength) then
  659. self.direction = 'backward'
  660. return self.direction
  661. else
  662. self.direction = nil
  663. return nil
  664. end
  665. end
  666. -- If we get here, neither variable is marked, so we have a choice.
  667. if self.v1.walk_strength:weaker(self.v2.walk_strength) then
  668. if self.strength:stronger(self.v1.walk_strength) then
  669. self.direction = 'backward'
  670. return self.direction
  671. else
  672. self.direction = nil
  673. return nil
  674. end
  675. else
  676. if self.strength:stronger(self.v2.walk_strength) then
  677. self.direction = 'forward'
  678. return self.direction
  679. else
  680. self.direction = nil
  681. return nil
  682. end
  683. end
  684. end
  685. function BinaryConstraint:inputs_do (fn)
  686. if self.direction == 'forward' then
  687. fn(self.v1)
  688. else
  689. fn(self.v2)
  690. end
  691. end
  692. function BinaryConstraint:inputs_has_one (fn)
  693. if self.direction == 'forward' then
  694. return fn(self.v1)
  695. else
  696. return fn(self.v2)
  697. end
  698. end
  699. function BinaryConstraint:mark_unsatisfied ()
  700. self.direction = nil
  701. end
  702. function BinaryConstraint:output ()
  703. return self.direction == 'forward' and self.v2 or self.v1
  704. end
  705. function BinaryConstraint:recalculate ()
  706. local ihn, out
  707. if self.direction == 'forward' then
  708. ihn = self.v1
  709. out = self.v2
  710. else
  711. ihn = self.v2
  712. out = self.v1
  713. end
  714. out.walk_strength = self.strength:weakest(ihn.walk_strength)
  715. out.stay = ihn.stay
  716. if out.stay then
  717. self:execute()
  718. end
  719. end
  720. end -- abstract class BinaryConstraint
  721. local UnaryConstraint = {_CLASS = 'UnaryConstraint'} do
  722. setmetatable(UnaryConstraint, {__index = AbstractConstraint})
  723. function UnaryConstraint:build (v, strength, planner)
  724. AbstractConstraint.build(self, strength)
  725. self.output_ = v
  726. self.satisfied = false
  727. self:add_constraint(planner)
  728. end
  729. function UnaryConstraint:is_satisfied ()
  730. return self.satisfied
  731. end
  732. function UnaryConstraint:add_to_graph ()
  733. self.output_:add_constraint(self)
  734. self.satisfied = false
  735. end
  736. function UnaryConstraint:remove_from_graph ()
  737. if self.output_ then
  738. self.output_:remove_constraint(self)
  739. end
  740. self.satisfied = false
  741. end
  742. function UnaryConstraint:choose_method (mark)
  743. self.satisfied = (self.output_.mark ~= mark) and
  744. self.strength:stronger(self.output_.walk_strength)
  745. return nil
  746. end
  747. function UnaryConstraint:inputs_do ()
  748. -- No-op. I have no input variable.
  749. end
  750. function UnaryConstraint:inputs_has_one ()
  751. return false
  752. end
  753. function UnaryConstraint:mark_unsatisfied ()
  754. self.satisfied = false
  755. end
  756. function UnaryConstraint:output ()
  757. return self.output_
  758. end
  759. function UnaryConstraint:recalculate ()
  760. self.output_.walk_strength = self.strength
  761. self.output_.stay = not self.is_input()
  762. if self.output_.stay then
  763. self:execute() -- stay optimization
  764. end
  765. end
  766. end -- abstract class UnaryConstraint
  767. local EditConstraint = {_CLASS = 'EditConstraint'} do
  768. setmetatable(EditConstraint, {__index = UnaryConstraint})
  769. function EditConstraint.new (v, strength, planner)
  770. local obj = setmetatable({}, {__index = EditConstraint})
  771. UnaryConstraint.build(obj, v, strength, planner)
  772. return obj
  773. end
  774. function EditConstraint:is_input ()
  775. return true
  776. end
  777. function EditConstraint:execute ()
  778. -- Edit constraints does nothing.
  779. end
  780. end -- class EditConstraint
  781. local EqualityConstraint = {_CLASS = 'EqualityConstraint'} do
  782. setmetatable(EqualityConstraint, {__index = BinaryConstraint})
  783. function EqualityConstraint.new (var1, var2, strength, planner)
  784. local obj = setmetatable({}, {__index = EqualityConstraint})
  785. BinaryConstraint.build(obj, var1, var2, strength)
  786. obj:add_constraint(planner)
  787. return obj
  788. end
  789. function EqualityConstraint:execute ()
  790. if self.direction == 'forward' then
  791. self.v2.value = self.v1.value
  792. else
  793. self.v1.value = self.v2.value
  794. end
  795. end
  796. end -- class EqualityConstraint
  797. local ScaleConstraint = {_CLASS = 'ScaleConstraint'} do
  798. setmetatable(ScaleConstraint, {__index = BinaryConstraint})
  799. function ScaleConstraint.new (src, scale, offset, dest, strength, planner)
  800. local obj = {
  801. scale = scale,
  802. offset = offset,
  803. }
  804. setmetatable(obj, {__index = ScaleConstraint})
  805. BinaryConstraint.build(obj, src, dest, strength)
  806. obj:add_constraint(planner)
  807. return obj
  808. end
  809. function ScaleConstraint:add_to_graph ()
  810. self.v1:add_constraint(self)
  811. self.v2:add_constraint(self)
  812. self.scale:add_constraint(self)
  813. self.offset:add_constraint(self)
  814. self.direction = nil
  815. end
  816. function ScaleConstraint:remove_from_graph ()
  817. if self.v1 then
  818. self.v1:remove_constraint(self)
  819. end
  820. if self.v2 then
  821. self.v2:remove_constraint(self)
  822. end
  823. if self.scale then
  824. self.scale:remove_constraint(self)
  825. end
  826. if self.offset then
  827. self.offset:remove_constraint(self)
  828. end
  829. self.direction = nil
  830. end
  831. function ScaleConstraint:execute ()
  832. if self.direction == 'forward' then
  833. self.v2.value = self.v1.value * self.scale.value + self.offset.value
  834. else
  835. self.v1.value = (self.v2.value - self.offset.value) / self.scale.value
  836. end
  837. end
  838. function ScaleConstraint:inputs_do (fn)
  839. if self.direction == 'forward' then
  840. fn(self.v1)
  841. fn(self.scale)
  842. fn(self.offset)
  843. else
  844. fn(self.v2)
  845. fn(self.scale)
  846. fn(self.offset)
  847. end
  848. end
  849. function ScaleConstraint:recalculate ()
  850. local ihn, out
  851. if self.direction == 'forward' then
  852. ihn = self.v1
  853. out = self.v2
  854. else
  855. out = self.v1
  856. ihn = self.v2
  857. end
  858. out.walk_strength = self.strength:weakest(ihn.walk_strength)
  859. out.stay = ihn.stay and self.scale.stay and self.offset.stay
  860. if out.stay then
  861. self:execute() -- stay optimization
  862. end
  863. end
  864. end -- class ScaleConstraint
  865. local StayConstraint = {_CLASS = 'StayConstraint'} do
  866. setmetatable(StayConstraint, {__index = UnaryConstraint})
  867. function StayConstraint.new (v, strength, planner)
  868. local obj = setmetatable({}, {__index = StayConstraint})
  869. UnaryConstraint.build(obj, v, strength, planner)
  870. return obj
  871. end
  872. function StayConstraint:execute ()
  873. -- Stay Constraints do nothing
  874. end
  875. end -- class StayConstraint
  876. local Variable = {_CLASS = 'Variable'} do
  877. function Variable.new (initial_value)
  878. local obj = {
  879. value = initial_value or 0,
  880. constraints = Vector.new(2),
  881. determined_by = nil,
  882. walk_strength = Strength.ABSOLUTE_WEAKEST,
  883. stay = true,
  884. mark = 0,
  885. }
  886. return setmetatable(obj, {__index = Variable})
  887. end
  888. function Variable:add_constraint (constraint)
  889. self.constraints:append(constraint)
  890. end
  891. function Variable:remove_constraint (constraint)
  892. self.constraints:remove(constraint)
  893. if self.determined_by == constraint then
  894. self.determined_by = nil
  895. end
  896. end
  897. end -- class Variable
  898. local Plan = {_CLASS = 'Plan'} do
  899. setmetatable(Plan, {__index = Vector})
  900. function Plan.new ()
  901. local obj = Vector.new(15)
  902. return setmetatable(obj, {__index = Plan})
  903. end
  904. function Plan:execute ()
  905. self:each(function (c)
  906. c:execute()
  907. end)
  908. end
  909. end -- class Plan
  910. local Planner = {_CLASS = 'Planner'} do
  911. function Planner.new ()
  912. local obj = {current_mark = 1}
  913. return setmetatable(obj, {__index = Planner})
  914. end
  915. function Planner:incremental_add (constraint)
  916. local mark = self:new_mark()
  917. local overridden = constraint:satisfy(mark, self)
  918. while overridden do
  919. overridden = overridden:satisfy(mark, self)
  920. end
  921. end
  922. function Planner:incremental_remove (constraint)
  923. local out = constraint:output()
  924. constraint:mark_unsatisfied()
  925. constraint:remove_from_graph()
  926. local unsatisfied = self:remove_propagate_from(out)
  927. unsatisfied:each(function (u)
  928. self:incremental_add(u)
  929. end)
  930. end
  931. function Planner:extract_plan_from_constraints (constraints)
  932. local sources = Vector.new()
  933. constraints:each(function (c)
  934. if c:is_input() and c:is_satisfied() then
  935. sources:append(c)
  936. end
  937. end)
  938. return self:make_plan(sources)
  939. end
  940. function Planner:make_plan (sources)
  941. local mark = self:new_mark()
  942. local plan = Plan.new()
  943. local todo = sources
  944. while not todo:is_empty () do
  945. local c = todo:remove_first()
  946. if (c:output().mark ~= mark) and c:inputs_known(mark) then
  947. -- not in plan already and eligible for inclusion
  948. plan:append(c)
  949. c:output().mark = mark
  950. self:add_constraints_consuming_to(c:output(), todo)
  951. end
  952. end
  953. return plan
  954. end
  955. function Planner:propagate_from (v)
  956. local todo = Vector.new()
  957. self:add_constraints_consuming_to(v, todo)
  958. while not todo:is_empty() do
  959. local c = todo:remove_first()
  960. c:execute()
  961. self:add_constraints_consuming_to(c:output(), todo)
  962. end
  963. end
  964. function Planner:add_constraints_consuming_to (v, coll)
  965. local determining_c = v.determined_by
  966. v.constraints:each(function (c)
  967. if (c ~= determining_c) and c:is_satisfied() then
  968. coll:append(c)
  969. end
  970. end)
  971. end
  972. function Planner:add_propagate (c, mark)
  973. local todo = Vector.with(c)
  974. while not todo:is_empty() do
  975. local d = todo:remove_first()
  976. if d:output().mark == mark then
  977. self:incremental_remove(c)
  978. return false
  979. end
  980. d:recalculate()
  981. self:add_constraints_consuming_to(d:output(), todo)
  982. end
  983. return true
  984. end
  985. function Planner:change_var (var, val)
  986. local edit_constraint = EditConstraint.new(var, PREFERRED, self)
  987. local plan = self:extract_plan_from_constraints(Vector.with(edit_constraint))
  988. for _ = 1, 10 do
  989. var.value = val
  990. plan:execute()
  991. end
  992. edit_constraint:destroy_constraint(self)
  993. end
  994. function Planner:constraints_consuming (v, fn)
  995. local determining_c = v.determined_by
  996. v.constraints:each(function (c)
  997. if (c ~= determining_c) and c:is_satisfied() then
  998. fn(c)
  999. end
  1000. end)
  1001. end
  1002. function Planner:new_mark ()
  1003. local current_mark = self.current_mark
  1004. self.current_mark = current_mark + 1
  1005. return current_mark
  1006. end
  1007. function Planner:remove_propagate_from (out)
  1008. local unsatisfied = Vector.new()
  1009. out.determined_by = nil
  1010. out.walk_strength = Strength.ABSOLUTE_WEAKEST
  1011. out.stay = true
  1012. local todo = Vector.with(out)
  1013. while not todo:is_empty() do
  1014. local v = todo:remove_first()
  1015. v.constraints:each(function (c)
  1016. if not c:is_satisfied() then
  1017. unsatisfied:append(c)
  1018. end
  1019. end)
  1020. self:constraints_consuming(v, function (c)
  1021. c:recalculate()
  1022. todo:append(c:output())
  1023. end)
  1024. end
  1025. unsatisfied:sort(function (c1, c2)
  1026. return c1.strength:stronger(c2.strength)
  1027. end)
  1028. return unsatisfied
  1029. end
  1030. function Planner.chain_test (n)
  1031. -- This is the standard DeltaBlue benchmark. A long chain of equality
  1032. -- constraints is constructed with a stay constraint on one end. An
  1033. -- edit constraint is then added to the opposite end and the time is
  1034. -- measured for adding and removing this constraint, and extracting
  1035. -- and executing a constraint satisfaction plan. There are two cases.
  1036. -- In case 1, the added constraint is stronger than the stay
  1037. -- constraint and values must propagate down the entire length of the
  1038. -- chain. In case 2, the added constraint is weaker than the stay
  1039. -- constraint so it cannot be accomodated. The cost in this case is,
  1040. -- of course, very low. Typical situations lie somewhere between these
  1041. -- two extremes.
  1042. local planner = Planner.new()
  1043. local vars = {}
  1044. for i = 1, n + 1 do
  1045. vars[i] = Variable.new()
  1046. end
  1047. -- thread a chain of equality constraints through the variables
  1048. for i = 1, n do
  1049. local v1, v2 = vars[i], vars[i + 1]
  1050. EqualityConstraint.new(v1, v2, REQUIRED, planner)
  1051. end
  1052. StayConstraint.new(vars[n + 1], STRONG_DEFAULT, planner)
  1053. local edit = EditConstraint.new(vars[1], PREFERRED, planner)
  1054. local plan = planner:extract_plan_from_constraints(Vector.with(edit))
  1055. for v = 1, 100 do
  1056. vars[1].value = v
  1057. plan:execute()
  1058. assert(vars[n + 1].value == v, 'Chain test failed!')
  1059. end
  1060. edit:destroy_constraint(planner)
  1061. end
  1062. function Planner.projection_test (n)
  1063. -- This test constructs a two sets of variables related to each
  1064. -- other by a simple linear transformation (scale and offset). The
  1065. -- time is measured to change a variable on either side of the
  1066. -- mapping and to change the scale and offset factors.
  1067. local planner = Planner.new()
  1068. local dests = Vector.new()
  1069. local scale = Variable.new(10)
  1070. local offset = Variable.new(1000)
  1071. local src = nil
  1072. local dst = nil
  1073. for i = 1, n do
  1074. src = Variable.new(i)
  1075. dst = Variable.new(i)
  1076. dests:append(dst)
  1077. StayConstraint.new(src, DEFAULT, planner)
  1078. ScaleConstraint.new(src, scale, offset, dst, REQUIRED, planner)
  1079. end
  1080. planner:change_var(src, 17)
  1081. assert(dst.value == 1170, 'Projection 1 failed')
  1082. planner:change_var(dst, 1050)
  1083. assert(src.value == 5, 'Projection 2 failed')
  1084. planner:change_var(scale, 5)
  1085. for i = 1, n - 1 do
  1086. assert(dests:at(i).value == i * 5 + 1000, 'Projection 3 failed')
  1087. end
  1088. planner:change_var(offset, 2000)
  1089. for i = 1, n - 1 do
  1090. assert(dests:at(i).value == i * 5 + 2000, 'Projection 4 failed')
  1091. end
  1092. end
  1093. end -- class Planner
  1094. return function(N)
  1095. Planner.chain_test(N)
  1096. Planner.projection_test(N)
  1097. end