PageRenderTime 24ms CodeModel.GetById 14ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

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