source: branches/stable/PARSIMONY/AP_main.cxx

Last change on this file was 17110, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AP_main.cxx                                       //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "ap_main.hxx"
12#include <aw_msg.hxx>
13#include <map>
14
15using namespace std;
16
17// ----------------
18//      AP_main
19
20GB_ERROR AP_main::open(const char *db_server) {
21    GB_ERROR error      = NULp;
22    gb_main             = GB_open(db_server, "rwt");
23    if (!gb_main) error = GB_await_error();
24    return error;
25}
26
27void AP_main::remember_user_state() {
28    user_frames.push(new UserFrame(frameLevel));
29    remember();
30}
31
32void AP_main::revert_user_state() {
33    if (user_frames.empty()) {
34        aw_message("No user-pop possible");
35    }
36    else {
37        UserFrame *wanted = user_frames.pop();
38        if (frameLevel<=wanted->get_level()) {
39            aw_message("Wanted user_frame not available");
40        }
41        else {
42            while (frameLevel>wanted->get_level()) {
43                revert();
44            }
45        }
46        delete wanted;
47    }
48}
49
50void AP_main::remember() {
51    /*! remember current tree state
52     * @see revert() and accept()
53     */
54
55    frameLevel ++;
56    if (currFrame) frames.push(currFrame);
57    currFrame = new NodeStack(frameData);
58    ap_assert(!frameData);
59    frameData = new StackFrameData;
60
61#if defined(CHECK_ROOT_POPS)
62    currFrame->root_at_create = DOWNCAST(AP_tree_nlen*, get_tree_root()->get_root_node());
63#endif
64}
65
66void AP_main::revert() {
67    /*! revert tree to last remembered state
68     * @see remember() and accept()
69     */
70    if (!currFrame) GBK_terminate("AP_main::pop on empty stack");
71
72    bool rootPopped = false;
73    {
74        AP_tree_nlen *node;
75        while ((node = currFrame->pop())) {
76            if (frameLevel != node->last_remembered_frame()) {
77                cerr << "Main frame level=" << frameLevel << " node frame level=" << node->last_remembered_frame() << endl;
78                GBK_terminate("AP_main::pop: main/node frame-level inconsistency");
79            }
80            node->revertToPreviousState(frameLevel, rootPopped);
81        }
82    }
83
84    ap_assert(rootPopped == frameData->root_pushed);
85#if defined(CHECK_ROOT_POPS)
86    ap_assert(currFrame->root_at_create == get_tree_root()->get_root_node()); // root has been restored!
87#endif
88
89    currFrame->revert_resources(frameData);
90    delete frameData;
91    frameData = currFrame->take_previous_frame_data();
92
93    delete currFrame;
94    currFrame = frames.pop();
95    frameLevel --;
96}
97
98struct HasLevelSmallerThan {
99    Level level;
100    HasLevelSmallerThan(Level level_) : level(level_) {}
101    bool operator()(const NodeState *state) const { return state->frameNr < level; }
102};
103
104void AP_main::push_nodes_changed_since(Level wanted_frameLevel) {
105    // does not consider currFrame (because we push_nodes to currFrame)
106    Level frame_level = frameLevel-1;
107    ap_assert(frame_level == frames.count_elements());
108
109    typedef map<AP_tree_nlen*,int> NodeCounter;
110    NodeCounter pops2skip; // specifies how many pops to skip for each node
111
112    AP_tree_nlen *oldRoot = get_root_node();
113
114    push_node(oldRoot, ROOT);
115
116    for (FrameStack::const_iterator f = frames.begin(); f != frames.end(); ++f, --frame_level) {
117        if (frame_level == wanted_frameLevel) break;
118        ap_assert(frame_level>wanted_frameLevel);
119
120        const NodeStack     *frame = *f;
121        HasLevelSmallerThan  hasWantedLevel(frame_level);
122
123        for (NodeStack::const_iterator n = frame->begin(); n != frame->end(); ++n) {
124            AP_tree_nlen *node = *n;
125            if (node == oldRoot) continue;
126
127            NodeCounter::iterator      skipCounter = pops2skip.find(node);
128            int                        skip        = skipCounter == pops2skip.end() ? 0 : skipCounter->second;
129            const StateStack&          states      = node->get_states();
130            StateStack::const_iterator toPush      = states.begin();
131
132            if (skip>0) advance(toPush, skip);
133
134            ap_assert(toPush != states.end()); // otherwise node should not be listed in 'frame'
135            ap_assert(hasWantedLevel(*toPush));
136
137            const NodeState *prevState = *toPush;
138            ap_assert(prevState->frameNr < frame_level);
139
140            AP_STACK_MODE mode = prevState->mode;
141            if (mode == ROOT || node->is_root_node()) {
142                mode = BOTH;
143            }
144#if defined(ASSERTION_USED)
145            Level lold = states.count_elements();
146#endif
147            int pushed = push_node(node, mode);
148
149            ap_assert(states.count_elements() == lold+pushed);
150
151            pops2skip[node] = skip+1+pushed;
152        }
153    }
154}
155
156void AP_main::rollback_to(Level wanted_frameLevel) {
157    // does not consider currFrame
158    // (assumes tree state is identical to state before last push())
159    Level frame_level = frameLevel-1;
160    ap_assert(frame_level == frames.count_elements());
161
162    typedef map<AP_tree_nlen*,int> NodeCounter;
163    NodeCounter pops2skip; // specifies how many pops to skip for each node
164
165    // skip pushes done by push_nodes_changed_since()
166    for (NodeStack::const_iterator n = currFrame->begin(); n != currFrame->end(); ++n) {
167        AP_tree_nlen *node = *n;
168        pops2skip[node]    = 1;
169    }
170
171    for (FrameStack::const_iterator f = frames.begin(); f != frames.end(); ++f, --frame_level) {
172        if (frame_level == wanted_frameLevel) break;
173        ap_assert(frame_level>wanted_frameLevel);
174
175        const NodeStack *frame = *f;
176#if defined(ASSERTION_USED)
177        HasLevelSmallerThan  hasWantedLevel(frame_level);
178#endif
179
180        for (NodeStack::const_iterator n = frame->begin(); n != frame->end(); ++n) {
181            AP_tree_nlen               *node        = *n;
182            NodeCounter::iterator       skipCounter = pops2skip.find(node);
183            int                         skip        = skipCounter == pops2skip.end() ? 0 : skipCounter->second;
184            const StateStack&           states      = node->get_states();
185            StateStack::const_iterator  toRestore   = states.begin();
186
187            if (skip>0) advance(toRestore, skip);
188
189            ap_assert(toRestore != states.end()); // otherwise node should not be listed in 'frame'
190            ap_assert(hasWantedLevel(*toRestore));
191
192            const NodeState *prevState = *toRestore;
193            ap_assert(prevState->frameNr < frame_level);
194            node->restore_nondestructive(*prevState);
195
196            pops2skip[node] = skip+1;
197        }
198
199#if defined(CHECK_ROOT_POPS)
200        ap_assert(frame->root_at_create == get_tree_root()->get_root_node()); // root has been restored!
201#endif
202    }
203}
204
205void AP_main::accept() {
206    /*! accept changes performed on tree (since last remember())
207     * @see revert()
208     */
209
210    if (!currFrame) GBK_terminate("AP_main::accept on empty stack");
211    ap_assert(frameData);
212
213    AP_tree_nlen *node;
214
215    NodeStack *prev_frame = frames.pop();
216
217    // detect nodes (and edges) created AND destroyed inside currently accepted stack frame
218    ResourceStack *common = NULp;
219    if (prev_frame) {
220        common = new ResourceStack;
221        frameData->extract_common_to(*common);
222    }
223
224    while ((node = currFrame->pop())) {
225        if (node->acceptCurrentState(frameLevel) != true) {
226            // stored node state was not discarded (because it was not stored for the previous stack frame).
227            // if revert() gets called for previous stack frane, it is necessary to revert
228            // the current change as well -> move into previous frame
229            if (prev_frame) {
230                if (common->has_node(node)) {
231                    // do NOT push nodes which get destroyed by accept_resources() below!
232                    ASSERT_RESULT(bool, true, node->acceptCurrentState(1)); // force state drop
233                }
234                else {
235                    prev_frame->push(node); // @@@ frames are pushed in reverted order (seems to be wrong)
236                }
237            }
238        }
239    }
240
241    currFrame->accept_resources(frameData, common);
242    delete frameData;
243    frameData = currFrame->take_previous_frame_data();
244
245    delete currFrame;
246    currFrame = prev_frame;
247    frameLevel --;
248
249    delete common;
250}
251
252bool AP_main::push_node(AP_tree_nlen *node, AP_STACK_MODE mode) {
253    /*! stores node in currFrame (if exists)
254     * if (mode&SEQUENCE) => sequence gets invalidated
255     * @return true, if a new entry has been created. false, if existing entry was extended or no stack exists.
256     */
257
258    bool pushed = false;
259    if (!currFrame) {
260        if (mode & SEQUENCE) node->unhash_sequence();
261    }
262    else {
263        if (frameLevel < node->last_remembered_frame()) {
264            cerr << "Main frame level=" << frameLevel << " node frame level=" << node->last_remembered_frame() << endl;
265            GBK_terminate("AP_main::push_node: main/node frame-level inconsistency");
266        }
267
268        if (mode == ROOT) {
269            // test that it is really root what is pushed
270            ap_assert(!node->father);
271            ap_assert(node->is_root_node());
272
273            if (frameData->root_pushed) {
274                // do not push root twice in same frame
275                mode = BOTH;
276            }
277            else {
278                frameData->root_pushed = true;
279#if defined(CHECK_ROOT_POPS)
280                ap_assert(node == currFrame->root_at_create); // make sure the pushed root is the correct one
281#endif
282            }
283        }
284
285        if (node->rememberState(mode, frameLevel)) {
286            currFrame->push(node);
287            pushed = true;
288        }
289        if (mode == ROOT) {
290            // In AP_main::pop(), root-node has to be restored after everything else has been restored.
291            // Move node to bottom of stack now to ensure that.
292            currFrame->remove(node);
293            currFrame->shift(node);
294        }
295    }
296    return pushed;
297}
298
299void AP_main::set_tree_root(AWT_graphic_parsimony *agt_) {
300    ap_assert(!agt && agt_); // do only once
301    agt = agt_;
302}
303
304const char *AP_main::get_aliname() const {
305    return get_tree_root()->get_aliview()->get_aliname();
306}
307
308#if defined(UNIT_TESTS)
309void AP_main::remember_whole_tree() {
310    remember();
311    AP_tree_nlen *root = get_root_node();
312    push_node(root, ROOT);
313    ap_assert(!root->is_leaf());
314    root->get_leftson()->remember_subtree(this);
315    root->get_rightson()->remember_subtree(this);
316}
317#endif
Note: See TracBrowser for help on using the repository browser.