/tutorial/backtracking/logigram/situation.e

http://github.com/tybor/Liberty · Specman e · 475 lines · 415 code · 35 blank · 25 comment · 11 complexity · fe7110b5e9b49a5e06a4b7bde206475d MD5 · raw file

  1. -- See the Copyright notice at the end of this file.
  2. --
  3. class SITUATION
  4. inherit
  5. BACKTRACKING
  6. feature {ANY}
  7. description: DESCRIPTION
  8. dimension: INTEGER
  9. pdim: INTEGER
  10. wdim: INTEGER
  11. permut: ARRAY[PERMUT]
  12. solution: FAST_ARRAY[PERMUT]
  13. p, q: PERMUT
  14. situation: FAST_ARRAY[BIT_STRING]
  15. undo_masks: FAST_ARRAY[BIT_STRING]
  16. undo_index: FAST_ARRAY[INTEGER]
  17. undo_top: INTEGER
  18. nrsol: INTEGER
  19. make (the_desc: like description) is
  20. require
  21. the_desc.is_valid
  22. do
  23. description := the_desc
  24. dimension := description.dimension
  25. pdim := fact(dimension)
  26. create p.make(dimension)
  27. create q.make(dimension)
  28. create permut.with_capacity(pdim, 1)
  29. make_permut(0)
  30. check
  31. permut.count = pdim
  32. end
  33. wdim := description.group_count
  34. wdim := wdim * (wdim - 1) // 2
  35. create situation.with_capacity(wdim)
  36. from
  37. until
  38. situation.count >= wdim
  39. loop
  40. situation.add_last(create {BIT_STRING}.make(pdim))
  41. end
  42. create undo_index.with_capacity(100)
  43. create undo_masks.with_capacity(100)
  44. create solution.with_capacity(description.group_count)
  45. from
  46. until
  47. solution.count = description.group_count
  48. loop
  49. solution.add_last(create {PERMUT}.make(dimension))
  50. end
  51. end
  52. solve is
  53. local
  54. builder: MASK_BUILDER
  55. do
  56. create builder.make(Current)
  57. situation.do_all(agent {BIT_STRING}.set_all)
  58. nrsol := 0
  59. from
  60. set_current_node(description.constraints.build_nodes(builder))
  61. search_first
  62. until
  63. is_off
  64. loop
  65. success
  66. search_next
  67. end
  68. print("%N")
  69. print(nrsol.out)
  70. print(" solution")
  71. if nrsol > 1 then
  72. print("s")
  73. end
  74. print("%N%N")
  75. end
  76. index (g1, g2: GROUP): INTEGER is
  77. -- The index of the group pair
  78. require
  79. g1 /= g2
  80. do
  81. if g1.index < g2.index then
  82. Result := index_integer(g1.index, g2.index)
  83. else
  84. Result := index_integer(g2.index, g1.index)
  85. end
  86. end
  87. index_integer (g1, g2: INTEGER): INTEGER is
  88. -- the index of the pair
  89. require
  90. g1 < g2
  91. do
  92. Result := g1 + (g2 * (g2 - 1)) // 2
  93. end
  94. context_clear is
  95. do
  96. undo_index.clear_count
  97. undo_top := undo_index.upper
  98. end
  99. context_push is
  100. do
  101. undo_index.add_last(undo_top)
  102. undo_top := undo_index.upper
  103. from
  104. until
  105. undo_top <= undo_masks.upper
  106. loop
  107. undo_masks.add_last(create {BIT_STRING}.make(pdim))
  108. end
  109. end
  110. context_restore is
  111. do
  112. from
  113. until
  114. undo_index.upper = undo_top
  115. loop
  116. situation.item(undo_index.last).copy(undo_masks.item(undo_index.upper))
  117. undo_index.remove_last
  118. end
  119. end
  120. context_restore_and_pop is
  121. do
  122. context_restore
  123. undo_top := undo_index.last
  124. undo_index.remove_last
  125. end
  126. context_cut is
  127. -- no cut allowed
  128. do
  129. check False end
  130. end
  131. change (idx: INTEGER; mask: BIT_STRING): BOOLEAN is
  132. local
  133. value: BIT_STRING
  134. do
  135. value := situation.item(idx)
  136. undo_index.add_last(idx)
  137. from
  138. until
  139. undo_index.upper <= undo_masks.upper
  140. loop
  141. undo_masks.add_last(create {BIT_STRING}.make(pdim))
  142. end
  143. undo_masks.item(undo_index.upper).copy(value)
  144. value.and_mask(mask)
  145. Result := not value.all_cleared
  146. end
  147. success is
  148. local
  149. i: INTEGER; x: PERMUT
  150. do
  151. from
  152. x := solution.item(0)
  153. i := 0
  154. until
  155. i = dimension
  156. loop
  157. x.put(i, i)
  158. i := i + 1
  159. end
  160. try_solution(1)
  161. end
  162. try_solution (idx: INTEGER) is
  163. -- if idx is a valid group index then test if that group 'idx'
  164. require
  165. idx > 0
  166. local
  167. i, j: INTEGER; b: BIT_STRING
  168. do
  169. if idx = description.group_count then
  170. nrsol := nrsol + 1
  171. print_solution
  172. else
  173. b := situation.item(index_integer(0, idx))
  174. from
  175. i := 1
  176. until
  177. i > pdim
  178. loop
  179. if b.item(i) then
  180. solution.put(permut.item(i), idx)
  181. from
  182. j := 1
  183. until
  184. j = idx or else not is_ok(j, idx)
  185. loop
  186. j := j + 1
  187. end
  188. if j = idx then
  189. try_solution(idx + 1)
  190. end
  191. end
  192. i := i + 1
  193. end
  194. end
  195. end
  196. is_ok (mid, last: INTEGER): BOOLEAN is
  197. require
  198. mid > 0
  199. last > mid
  200. local
  201. j, k: INTEGER; xmid, xlast: PERMUT
  202. do
  203. xlast := solution.item(last)
  204. xmid := solution.item(mid)
  205. from
  206. j := 0
  207. until
  208. j = dimension
  209. loop
  210. p.put(xlast.item(j), xmid.item(j))
  211. j := j + 1
  212. end
  213. k := index_of_permut(p)
  214. Result := situation.item(index_integer(mid, last)).item(k)
  215. end
  216. index_of_permut (x: PERMUT): INTEGER is
  217. -- the index of the permutation 'x'
  218. -- side effect: alter q
  219. local
  220. i, j, k: INTEGER
  221. do
  222. -- q is set to 1 2 3 4 ...
  223. from
  224. i := 0
  225. until
  226. i = dimension
  227. loop
  228. q.put(i, i)
  229. i := i + 1
  230. end
  231. from
  232. i := 0
  233. until
  234. i = dimension
  235. loop
  236. j := x.item(i)
  237. Result := Result * (dimension - i) + q.item(j)
  238. from
  239. k := j + 1
  240. until
  241. k = dimension
  242. loop
  243. q.put(q.item(k) - 1, k)
  244. k := k + 1
  245. end
  246. i := i + 1
  247. end
  248. Result := Result + 1
  249. check
  250. permut.item(Result).is_equal(x)
  251. end
  252. end
  253. print_solution is
  254. do
  255. print("%N")
  256. print_dash_line
  257. print_head_line
  258. print_dash_line
  259. print_content_lines
  260. print_dash_line
  261. end
  262. print_dash_line is
  263. local
  264. lgr, g, i: INTEGER
  265. do
  266. from
  267. print("+")
  268. g := 0
  269. until
  270. g = description.group_count
  271. loop
  272. from
  273. description.goto_index(g)
  274. lgr := description.group.width + 2
  275. i := 0
  276. until
  277. i = lgr
  278. loop
  279. print("-")
  280. i := i + 1
  281. end
  282. print("+")
  283. g := g + 1
  284. end
  285. print("%N")
  286. end
  287. print_head_line is
  288. local
  289. lgr, g, i: INTEGER
  290. do
  291. from
  292. print("|")
  293. g := 0
  294. until
  295. g = description.group_count
  296. loop
  297. from
  298. description.goto_index(g)
  299. lgr := description.group.width - description.group.name.count
  300. check lgr >= 0 end
  301. print(" ")
  302. print(description.group.name)
  303. i := 0
  304. until
  305. i = lgr
  306. loop
  307. print(" ")
  308. i := i + 1
  309. end
  310. print(" |")
  311. g := g + 1
  312. end
  313. print("%N")
  314. end
  315. print_content_lines is
  316. local
  317. lig, g, lgr, i: INTEGER; x: PERMUT
  318. do
  319. from
  320. lig := 0
  321. until
  322. lig = dimension
  323. loop
  324. from
  325. print("|")
  326. g := 0
  327. until
  328. g = description.group_count
  329. loop
  330. description.goto_index(g)
  331. x := solution.item(g)
  332. description.group.goto_index(x.item(lig))
  333. from
  334. lgr := description.group.width - description.group.item.name.count
  335. print(" ")
  336. print(description.group.item.name)
  337. i := 0
  338. until
  339. i = lgr
  340. loop
  341. print(" ")
  342. i := i + 1
  343. end
  344. print(" |")
  345. g := g + 1
  346. end
  347. print("%N")
  348. lig := lig + 1
  349. end
  350. end
  351. print_group_pair (g1, g2: GROUP) is
  352. local
  353. j, k: INTEGER; b: BIT_STRING; x: PERMUT
  354. do
  355. print("%NGROUP%T")
  356. print(g1.name)
  357. print("%T")
  358. print(g2.name)
  359. print("%N")
  360. print("%N")
  361. b := situation.item(index(g1, g2))
  362. from
  363. j := 1
  364. until
  365. j > pdim
  366. loop
  367. if b.item(j) then
  368. x := permut.item(j)
  369. from
  370. k := 0
  371. until
  372. k = dimension
  373. loop
  374. g1.goto_index(k)
  375. g2.goto_index(x @ k)
  376. print("%T")
  377. print(g1.item.name)
  378. print("%T")
  379. print(g2.item.name)
  380. print("%N")
  381. k := k + 1
  382. end
  383. print("%N")
  384. end
  385. j := j + 1
  386. end
  387. end
  388. feature {}
  389. fact (n: INTEGER): INTEGER is
  390. do
  391. if n > 1 then
  392. Result := n * fact(n - 1)
  393. else
  394. Result := 1
  395. end
  396. end
  397. make_permut (pos: INTEGER) is
  398. local
  399. i, j: INTEGER
  400. do
  401. if pos = dimension then
  402. permut.add_last(create {PERMUT}.from_collection(p))
  403. else
  404. from
  405. i := 0
  406. until
  407. i = dimension
  408. loop
  409. from
  410. j := 0
  411. until
  412. j = pos or else p.item(j) = i
  413. loop
  414. j := j + 1
  415. end
  416. if j = pos then
  417. p.put(i, pos)
  418. make_permut(pos + 1)
  419. end
  420. i := i + 1
  421. end
  422. end
  423. end
  424. end -- class SITUATION
  425. --
  426. -- ------------------------------------------------------------------------------------------------------------------------------
  427. -- Copyright notice below. Please read.
  428. --
  429. -- This file is free software, which comes along with SmartEiffel. This software is distributed in the hope that it will be
  430. -- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  431. -- You can modify it as you want, provided this footer is kept unaltered, and a notification of the changes is added.
  432. -- You are allowed to redistribute it and sell it, alone or as a part of another product.
  433. --
  434. -- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE
  435. -- Copyright(C) 2003-2005: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
  436. --
  437. -- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
  438. --
  439. -- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
  440. -- ------------------------------------------------------------------------------------------------------------------------------