source: CIVL/examples/compare/provesa/ADFirstAidKit/treeverse.f@ bb03188

main test-branch
Last change on this file since bb03188 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 9.4 KB
RevLine 
[4d61ad0]1C TREEVERSE MECHANISM V2
2C ========================
3
4c New version of TreeVerse that does not store the entire
5c reversal sequence, but rather uses a stack automaton to
6c generate the reversal actions one at a time.
7c Allows for nested calls to Treeverse, i.e.
8C nested iterative loops that use treeverse.
9c Uses a small enough stack,
10c allowing for 5 nested calls to TRV_INIT,
11c and for a cumulated number of snapshots of 99.
12
13c Usage:
14c Call TRV_INIT(length, nbSnap, firstStep)
15c giving to it:
16c -- the length of the sequence you need to inverse, including the
17c last step, the one that exits. E.g "do i=1,10" has length 11 !!
18c -- the number of snapshots your machine can accomodate,
19c -- the index of the first step in the sequence you need to inverse.
20c Then repeated calls to TRV_NEXT_ACTION(action, step)
21c return the successive actions the treeverse loop must perform.
22c Also return in "step" the time step on which the action operates.
23c When all actions are done, TRV_NEXT_ACTION returns .FALSE.
24
25c Global memory used to remember the state
26c when the stack automaton runs:
27c -STACK1 (one level (index is1) per nested treeverse session) :
28c STACK1(1,is1): index of initial level in STACK2 for this session
29c STACK1(2,is1): max number of snapshots allowed for this session
30c STACK1(3,is1): offset for step numbers in this session
31c -STACK2 (one level (index is2) per nested (simultaneous) snapshot) :
32c STACK2(1,is2): number of steps to be reversed by this snapshot level
33c STACK2(2,is2): rank of the current step in STACK2(1,is2)
34c STACK2(3,is2): rank of the chosen recursive cut in STACK2(1,is2)
35 BLOCK DATA TRV_GLOBAL_DATA
36 INTEGER STACK1(3,5), is1, STACK2(3,99), is2
37 COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
38 DATA is1/0/
39 DATA is2/0/
40 END
41
42c Initialize one nested session of treeverse commands,
43c using at most "nbSnap" snapshots, to reverse a sequence
44c of length "length", in which the first step in numbered "firstStep"
45c Does not alter its arguments, but modifies STACK1 and STACK2.
46 SUBROUTINE TRV_INIT(length, nbSnap, firstStep)
47 IMPLICIT NONE
48 INTEGER nbSnap, length, firstStep
49 INTEGER STACK1(3,5), is1, STACK2(3,99), is2
50 COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
51
52 IF (length.le.0) THEN
53 PRINT*,"Error: Cannot reverse a sequence of length ", length
54 STOP
55 ELSE IF (nbSnap.eq.0.and.length.ge.2) THEN
56 PRINT*,"Error: Cannot reverse a sequence of length ", length,
57 + " with no snapshot"
58 STOP
59 ELSE IF (is1.ge.5.or.is2+nbsnap+1.ge.99) THEN
60 PRINT*,"Error: Treeverse memory exceeded !"
61 STOP
62 ELSE
63 is1 = is1+1
64 is2 = is2+1
65 STACK1(1,is1) = is2
66 STACK1(2,is1) = nbSnap
67 STACK1(3,is1) = firstStep
68 STACK2(1,is2) = length
69 STACK2(2,is2) = 0
70 STACK2(3,is2) = 0
71 END IF
72 END
73
74c Finds the next action in the process of reversing the current
75c sequence of steps, i.e. running the current treeverse session.
76c Overwrites "action" withthis next action to perform,
77c and overwrites step with the index of the iteration step
78c that corresponds to this action. Also returns .TRUE. if there
79c is such an action waiting, and .FALSE. otherwise, i.e. the
80c current reversal session is terminated.
81 LOGICAL FUNCTION TRV_NEXT_ACTION(action, step)
82 IMPLICIT NONE
83 INTEGER action, step, i
84 INTEGER STACK1(3,5), is1, STACK2(3,99), is2
85 COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
86 INTEGER PUSHSNAP, LOOKSNAP, POPSNAP, ADVANCE, FIRSTTURN, TURN
87 PARAMETER (PUSHSNAP=1)
88 PARAMETER (LOOKSNAP=2)
89 PARAMETER (POPSNAP=3)
90 PARAMETER (ADVANCE=4)
91 PARAMETER (FIRSTTURN=5)
92 PARAMETER (TURN=6)
93
94c Part "only for debug":
95c PRINT*, ""
96c PRINT*, "STACK1:"
97c DO i=is1,1,-1
98c WRITE(*,910) STACK1(2,i), STACK1(1,i), STACK1(3,i)
99c ENDDO
100c PRINT*, "-------------------"
101c PRINT*, "STACK2:"
102c DO i=is2,1,-1
103c WRITE(*,920) i,STACK2(1,i), STACK2(2,i), STACK2(3,i)
104c ENDDO
105c PRINT*, "-------------------"
106c 910 format(i2," snapshots, stack2 bottom:",i2," (offset:",i3,")")
107c 920 format(i2,": R( ,",i3,") ",i3,"/",i3)
108c End of "only for debug" part
109
110 IF (STACK2(1,is2).le.0.and.is2.eq.STACK1(1,is1)) THEN
111c If we are at the top snapshot level and no step remains to be
112c reversed, then this inversion session is terminated.
113c Pop to the enclosing inversion session. Return .FALSE.
114 step = -1
115 action = -1
116 is1 = is1-1
117 is2 = is2-1
118 TRV_NEXT_ACTION = .FALSE.
119 ELSE
120c compute the index of the step to which the next action
121c corresponds or will apply:
122 step = 1 ;
123 DO i=STACK1(1,is1)+1,is2
124 step = step+STACK2(2,i)
125 ENDDO
126 IF (STACK2(2,is2).eq.-1) THEN
127c If the present position is -1, i.e. the current state does not
128c correspond to the next time step we are going to execute,
129c then take the correct state back from the snapshot.
130 IF (STACK2(1,is2).eq.1) THEN
131c POP the snapshot we are at last reversing the 1st step after it...
132 action = POPSNAP
133 ELSE
134c ... otherwise only LOOK at the snapshot, and keep it for later use.
135 action = LOOKSNAP
136 ENDIF
137 STACK2(2,is2) = 0
138 ELSE
139c Now the current state corresponds to the next time step to run on.
140 IF (STACK2(2,is2).eq.STACK2(1,is2)-1) THEN
141c if the current position is just before the end of the current
142c subsequence to reverse by this snapshot level. Then just TURN ...
143 IF (step.eq.STACK2(1,STACK1(1,is1))) THEN
144 action = FIRSTTURN
145 ELSE
146 action = TURN
147 ENDIF
148c ... and update the stack, popping the current snapshot level
149c if its work is finished, i.e. its remaining length to reverse is 0.
150c Attention do not pop the initial level of the current session.
151 IF (STACK2(2,is2).eq.0.and.is2.gt.STACK1(1,is1)) THEN
152 is2 = is2-1
153 STACK2(1,is2) = STACK2(3,is2)
154 ELSE
155 STACK2(1,is2) = STACK2(2,is2)
156 ENDIF
157c mark that the current state in memory is out of date
158 STACK2(2,is2) = -1
159c compute the new position for the deeper level snapshot
160 CALL TRV_SETCUT()
161 ELSE
162 IF (STACK2(2,is2).eq.STACK2(3,is2)) THEN
163c if we just reached the end of this level advance sequence,
164c then me must PUSH a snapshot and begin a new nested level of
165c snapshot in the current reversal session.
166 action = PUSHSNAP
167 is2 = is2+1
168 STACK2(1,is2) = STACK2(1,is2-1)-STACK2(2,is2-1)
169 STACK2(2,is2) = 0
170 CALL TRV_SETCUT()
171 step = step-1
172 ELSE
173c else we still need to ADVANCE to reach the next checkpoint
174 action = ADVANCE
175 STACK2(2,is2) = STACK2(2,is2)+1
176 ENDIF
177 ENDIF
178 ENDIF
179 TRV_NEXT_ACTION = .TRUE.
180 ENDIF
181 END
182
183c Find the index of the next CKP cut at the current checkpoint level.
184c Store this index into the current STACK2(3, is2).
185c Computation depends on the current length to reverse STACK2(1, is2)
186c and of the current number of available snapshots, computed as
187c STACK1(2,is1)-(is2-STACK1(1,is1))+1, i.e. the initial number of
188c snapshots for this session, minus the number of used snapshots,
189c i.e. the number of snapshot levels pushed onto STACK2 (minus 1).
190c Algorithm is first to find "minRecomp", the minimum number of
191c recomputations that allow reversing a sequence of this "length",
192c i.e. such that eta(nbSnap,minRecomp) is greater or equal to length.
193c By def, eta(nbSnap,recomp)=(nbSnap+recomp)!/(nbSnap!*recomp!)
194c Then this "minRecomp" defines the proportion of the length
195c which is before the CKP cut, which is
196c eta(nbSnap,minRecomp-1)/eta(nbSnap,minRecomp) which is
197c (by definition of eta) minRecomp/(minRecomp+nbSnap).
198c We find the cut index that approaches this proportion best.
199c Assert: length>=1 , nbSnap>=0
200c Alters the STACKs.
201 SUBROUTINE TRV_SETCUT()
202 IMPLICIT NONE
203 INTEGER STACK1(3,5), is1, STACK2(3,99), is2
204 COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
205 INTEGER length, nbSnap, eta, minRecomp
206
207 length = STACK2(1,is2)
208 nbSnap = STACK1(2,is1)-(is2-STACK1(1,is1))+1
209 IF (length.le.1) THEN
210 STACK2(3,is2) = 0
211 ELSE IF (nbSnap.eq.1) THEN
212 STACK2(3,is2) = length-1
213 ELSE
214 eta = nbSnap+1
215 minRecomp = 1
216 DO WHILE (eta.LT.length)
217 minRecomp = minRecomp+1
218 eta = (eta*(nbSnap+minRecomp))/minRecomp
219 END DO
220 STACK2(3,is2) = (length*minRecomp)/(minRecomp+nbSnap)
221 IF (STACK2(3,is2).eq.0) THEN
222 STACK2(3,is2) = 1
223 ELSE IF (STACK2(3,is2).ge.length) THEN
224 STACK2(3,is2) = length-1
225 END IF
226 ENDIF
227 END
228
229 SUBROUTINE TRV_RESIZE()
230 IMPLICIT NONE
231 INTEGER step, i
232 INTEGER STACK1(3,5), is1, STACK2(3,99), is2
233 COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
234
235 step = 1 ;
236 DO i=STACK1(1,is1)+1,is2
237 step = step+STACK2(2,i)
238 ENDDO
239 WRITE(*,930) "Binomial iteration exits on step",step-1,
240 + " before expected",STACK2(1,STACK1(1,is1))
241 930 format(a,i6,a,i6)
242 STACK2(1,STACK1(1,is1)) = step-1
243 STACK2(1,is2) = STACK2(2,is2)
244 STACK2(2,is2) = STACK2(2,is2)-1
245 END
Note: See TracBrowser for help on using the repository browser.