YAP 7.1.0
core_dbtries.c
1/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2%
3% $Date: 2010-06-30 17:05:24 +0200 (Wed, 30 Jun 2010) $
4% $Revision: 1 $
5%
6% This file is part of YAP & ProbLog
7% http://www.dcc.fc.up.pt/~vsc/Yap/index.html
8% http://dtai.cs.kuleuven.be/problog
9%
10% ProbLog was developed at Katholieke Universiteit Leuven &
11% University of Porto
12%
13% Copyright 2010 Katholieke Universiteit Leuven & University of Porto
14%
15% Main authors of this file: Mantadelis Theofrastos, Ricardo Rocha
16%
17%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18%
19% Artistic License 2.0
20%
21% Copyright (c) 2000-2006, The Perl Foundation.
22%
23% Everyone is permitted to copy and distribute verbatim copies of this
24% license document, but changing it is not allowed. Preamble
25%
26% This license establishes the terms under which a given free software
27% Package may be copied, modified, distributed, and/or
28% redistributed. The intent is that the Copyright Holder maintains some
29% artistic control over the development of that Package while still
30% keeping the Package available as open source and free software.
31%
32% You are always permitted to make arrangements wholly outside of this
33% license directly with the Copyright Holder of a given Package. If the
34% terms of this license do not permit the full use that you propose to
35% make of the Package, you should contact the Copyright Holder and seek
36% a different licensing arrangement. Definitions
37%
38% "Copyright Holder" means the individual(s) or organization(s) named in
39% the copyright notice for the entire Package.
40%
41% "Contributor" means any party that has contributed code or other
42% material to the Package, in accordance with the Copyright Holder's
43% procedures.
44%
45% "You" and "your" means any person who would like to copy, distribute,
46% or modify the Package.
47%
48% "Package" means the collection of files distributed by the Copyright
49% Holder, and derivatives of that collection and/or of those files. A
50% given Package may consist of either the Standard Version, or a
51% Modified Version.
52%
53% "Distribute" means providing a copy of the Package or making it
54% accessible to anyone else, or in the case of a company or
55% organization, to others outside of your company or organization.
56%
57% "Distributor Fee" means any fee that you charge for Distributing this
58% Package or providing support for this Package to another party. It
59% does not mean licensing fees.
60%
61% "Standard Version" refers to the Package if it has not been modified,
62% or has been modified only in ways explicitly requested by the
63% Copyright Holder.
64%
65% "Modified Version" means the Package, if it has been changed, and such
66% changes were not explicitly requested by the Copyright Holder.
67%
68% "Original License" means this Artistic License as Distributed with the
69% Standard Version of the Package, in its current version or as it may
70% be modified by The Perl Foundation in the future.
71%
72% "Source" form means the source code, documentation source, and
73% configuration files for the Package.
74%
75% "Compiled" form means the compiled bytecode, object code, binary, or
76% any other form resulting from mechanical transformation or translation
77% of the Source form.
78%
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80%
81% Permission for Use and Modification Without Distribution
82%
83% (1) You are permitted to use the Standard Version and create and use
84% Modified Versions for any purpose without restriction, provided that
85% you do not Distribute the Modified Version.
86%
87% Permissions for Redistribution of the Standard Version
88%
89% (2) You may Distribute verbatim copies of the Source form of the
90% Standard Version of this Package in any medium without restriction,
91% either gratis or for a Distributor Fee, provided that you duplicate
92% all of the original copyright notices and associated disclaimers. At
93% your discretion, such verbatim copies may or may not include a
94% Compiled form of the Package.
95%
96% (3) You may apply any bug fixes, portability changes, and other
97% modifications made available from the Copyright Holder. The resulting
98% Package will still be considered the Standard Version, and as such
99% will be subject to the Original License.
100%
101% Distribution of Modified Versions of the Package as Source
102%
103% (4) You may Distribute your Modified Version as Source (either gratis
104% or for a Distributor Fee, and with or without a Compiled form of the
105% Modified Version) provided that you clearly document how it differs
106% from the Standard Version, including, but not limited to, documenting
107% any non-standard features, executables, or modules, and provided that
108% you do at least ONE of the following:
109%
110% (a) make the Modified Version available to the Copyright Holder of the
111% Standard Version, under the Original License, so that the Copyright
112% Holder may include your modifications in the Standard Version. (b)
113% ensure that installation of your Modified Version does not prevent the
114% user installing or running the Standard Version. In addition, the
115% modified Version must bear a name that is different from the name of
116% the Standard Version. (c) allow anyone who receives a copy of the
117% Modified Version to make the Source form of the Modified Version
118% available to others under (i) the Original License or (ii) a license
119% that permits the licensee to freely copy, modify and redistribute the
120% Modified Version using the same licensing terms that apply to the copy
121% that the licensee received, and requires that the Source form of the
122% Modified Version, and of any works derived from it, be made freely
123% available in that license fees are prohibited but Distributor Fees are
124% allowed.
125%
126% Distribution of Compiled Forms of the Standard Version or
127% Modified Versions without the Source
128%
129% (5) You may Distribute Compiled forms of the Standard Version without
130% the Source, provided that you include complete instructions on how to
131% get the Source of the Standard Version. Such instructions must be
132% valid at the time of your distribution. If these instructions, at any
133% time while you are carrying out such distribution, become invalid, you
134% must provide new instructions on demand or cease further
135% distribution. If you provide valid instructions or cease distribution
136% within thirty days after you become aware that the instructions are
137% invalid, then you do not forfeit any of your rights under this
138% license.
139%
140% (6) You may Distribute a Modified Version in Compiled form without the
141% Source, provided that you comply with Section 4 with respect to the
142% Source of the Modified Version.
143%
144% Aggregating or Linking the Package
145%
146% (7) You may aggregate the Package (either the Standard Version or
147% Modified Version) with other packages and Distribute the resulting
148% aggregation provided that you do not charge a licensing fee for the
149% Package. Distributor Fees are permitted, and licensing fees for other
150% components in the aggregation are permitted. The terms of this license
151% apply to the use and Distribution of the Standard or Modified Versions
152% as included in the aggregation.
153%
154% (8) You are permitted to link Modified and Standard Versions with
155% other works, to embed the Package in a larger work of your own, or to
156% build stand-alone binary or bytecode versions of applications that
157% include the Package, and Distribute the result without restriction,
158% provided the result does not expose a direct interface to the Package.
159%
160% Items That are Not Considered Part of a Modified Version
161%
162% (9) Works (including, but not limited to, modules and scripts) that
163% merely extend or make use of the Package, do not, by themselves, cause
164% the Package to be a Modified Version. In addition, such works are not
165% considered parts of the Package itself, and are not subject to the
166% terms of this license.
167%
168% General Provisions
169%
170% (10) Any use, modification, and distribution of the Standard or
171% Modified Versions is governed by this Artistic License. By using,
172% modifying or distributing the Package, you accept this license. Do not
173% use, modify, or distribute the Package, if you do not accept this
174% license.
175%
176% (11) If your Modified Version has been derived from a Modified Version
177% made by someone other than you, you are nevertheless required to
178% ensure that your Modified Version complies with the requirements of
179% this license.
180%
181% (12) This license does not grant you the right to use any trademark,
182% service mark, tradename, or logo of the Copyright Holder.
183%
184% (13) This license includes the non-exclusive, worldwide,
185% free-of-charge patent license to make, have made, use, offer to sell,
186% sell, import and otherwise transfer the Package with respect to any
187% patent claims licensable by the Copyright Holder that are necessarily
188% infringed by the Package. If you institute patent litigation
189% (including a cross-claim or counterclaim) against any party alleging
190% that the Package constitutes direct or contributory patent
191% infringement, then this Artistic License to you shall terminate on the
192% date that such litigation is filed.
193%
194% (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
195% HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
196% WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
197% PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
198% PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT
199% HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT,
200% INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
201% OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
202%
203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
204
205/* -------------------------- */
206/* Local Procedures */
207/* -------------------------- */
208
209int traverse_get_counter(TrNode node);
210YAP_Term generate_label(YAP_Int Index);
211YAP_Term update_depth_breadth_trie(TrEngine engine, TrNode root, YAP_Int opt_level, void (*construct_function)(TrNode), void (*destruct_function)(TrNode), void (*copy_function)(TrNode, TrNode), void (*correct_order_function)(void));
212YAP_Term get_return_node_term(TrNode node);
213void traverse_and_replace_nested_trie(TrNode node, YAP_Int nested_trie_id, YAP_Term new_term, void (*construct_function)(TrNode), void (*destruct_function)(TrNode));
214TrNode replace_nested_trie(TrNode node, TrNode child, YAP_Term new_term, void (*construct_function)(TrNode), void (*destruct_function)(TrNode));
215void check_attach_childs(TrNode parent, TrNode search_child, TrNode existing_child, void (*construct_function)(TrNode), void (*destruct_function)(TrNode));
216TrNode get_simplification_sibling(TrNode node);
217TrNode check_parent_first(TrNode node);
218TrNode TrNode_myparent(TrNode node);
219
220/* -------------------------- */
221/* Debug Procedures */
222/* -------------------------- */
223
224void displaynode(TrNode node);
225void displayentry(TrNode node);
226void displayterm(YAP_Term term);
227void displaytrie(TrNode node);
228void display_trie_inner(TrNode node);
229void trie_display_node(TrNode node);
230
231
232/* -------------------------- */
233/* Local Variables */
234/* -------------------------- */
235
236static YAP_Int LABEL_COUNTER;
237static YAP_Term TRIE_DEPTH_BREADTH_RETURN_TERM;
238static YAP_Int TRIE_DEPTH_BREADTH_MIN_PREFIX = 2;
239static YAP_Int TRIE_DEPTH_BREADTH_OPT_COUNT[3];
240
241
242/* -------------------------- */
243/* depth-breadth Trie */
244/* -------------------------- */
245
246
247YAP_Int core_get_trie_db_opt_min_prefix(void) {
248 return TRIE_DEPTH_BREADTH_MIN_PREFIX;
249}
250
251
252
253void core_set_trie_db_opt_min_prefix(YAP_Int min_prefix) {
254 TRIE_DEPTH_BREADTH_MIN_PREFIX = min_prefix;
255 return;
256}
257
258
259
260void core_depth_breadth_trie_replace_nested_trie(TrNode node, YAP_Int nested_trie_id, YAP_Term new_term, void (*construct_function)(TrNode), void (*destruct_function)(TrNode)) {
261 traverse_and_replace_nested_trie(node, nested_trie_id, new_term, construct_function, destruct_function);
262 return;
263}
264
265
266inline
267void traverse_and_replace_nested_trie(TrNode node, YAP_Int nested_trie_id, YAP_Term new_term, void (*construct_function)(TrNode), void (*destruct_function)(TrNode)) {
268 TrNode child, temp;
269 if (TrNode_entry(node) == PairEndTag) {
270 if (TrNode_next(node))
271 traverse_and_replace_nested_trie(TrNode_next(node), nested_trie_id, new_term, construct_function, destruct_function);
272 return;
273 } else if (IS_HASH_NODE(node)) {
274 printf("HASH NODE ERROR: db_tries do not support hash nodes.\n");
275 abort();
276 TrNode *first_bucket, *bucket;
277 TrHash hash = (TrHash) node;
278 first_bucket = TrHash_buckets(hash);
279 bucket = first_bucket + TrHash_num_buckets(hash);
280 do {
281 if ((node = *--bucket)) {
282 do {
283 traverse_and_replace_nested_trie(node, nested_trie_id, new_term, construct_function, destruct_function);
284 node = TrNode_next(node);
285 } while(node);
286 }
287 } while (bucket != first_bucket);
288 } else {
289 if (IS_FUNCTOR_NODE(node)) {
290 YAP_Functor f = (YAP_Functor) (~ApplTag & TrNode_entry(node));
291 YAP_Int arity = YAP_ArityOfFunctor(f);
292 if (arity == 1 && strcmp(YAP_AtomName(YAP_NameOfFunctor(f)), NESTED_TRIE_TERM) == 0) {
293 child = TrNode_child(node);
294 if (IS_HASH_NODE(child)) {
295 printf("HASH NODE ERROR: db_tries do not support hash nodes.\n");
296 abort();
297 TrNode *first_bucket, *bucket;
298 TrHash hash = (TrHash) child;
299 first_bucket = TrHash_buckets(hash);
300 bucket = first_bucket + TrHash_num_buckets(hash);
301 do {
302 if ((child = *--bucket)) {
303 do {
304 if (YAP_IntOfTerm(TrNode_entry(child)) == nested_trie_id) {
305 temp = TrNode_previous(node);
306 node = replace_nested_trie(node, child, new_term, construct_function, destruct_function);
307 if (temp) {
308 temp = TrNode_next(node);
309 if (temp)
310 node = temp;
311 } else {
312 traverse_and_replace_nested_trie(TrNode_child(node), nested_trie_id, new_term, construct_function, destruct_function);
313 return;
314 }
315 }
316 child = TrNode_next(child);
317 } while(child);
318 }
319 } while (bucket != first_bucket);
320
321 } else {
322 do {
323 if (YAP_IntOfTerm(TrNode_entry(child)) == nested_trie_id) {
324 temp = TrNode_next(node);
325 node = replace_nested_trie(node, child, new_term, construct_function, destruct_function);
326 traverse_and_replace_nested_trie(TrNode_child(node), nested_trie_id, new_term, construct_function, destruct_function);
327 if(temp)
328 traverse_and_replace_nested_trie(temp, nested_trie_id, new_term, construct_function, destruct_function);
329 return;
330 }
331 child = TrNode_next(child);
332 } while(child);
333 }
334 }
335 }
336 traverse_and_replace_nested_trie(TrNode_child(node), nested_trie_id, new_term, construct_function, destruct_function);
337 if (TrNode_next(node))
338 traverse_and_replace_nested_trie(TrNode_next(node), nested_trie_id, new_term, construct_function, destruct_function);
339 }
340 return;
341}
342
343/* fixmeeee */
344TrNode replace_nested_trie(TrNode node, TrNode child, YAP_Term new_term, void (*construct_function)(TrNode), void (*destruct_function)(TrNode)) {
345 TrNode newnode, temp, newnodef = NULL;
346 if (YAP_IsApplTerm(new_term)) {
347 YAP_Term new_term_functor = ApplTag | ((YAP_Term) YAP_FunctorOfTerm(new_term));
348 YAP_Int arity = YAP_ArityOfFunctor(YAP_FunctorOfTerm(new_term));
349 if (arity != 1) abort();
350 YAP_Term new_term_arg = YAP_ArgOfTerm(1, new_term);
351 temp = TrNode_child(TrNode_parent(node));
352 while (temp) {
353 if (TrNode_entry(temp) == new_term_functor) {
354 printf("Warning - non tested code, please report the example to Theo to test it!\n");
355 newnodef = temp;
356 temp = NULL;
357 } else {
358 temp = TrNode_next(temp);
359 }
360 }
361 if (newnodef == NULL) {
362 new_trie_node(newnodef, new_term_functor, TrNode_parent(node), NULL, TrNode_child(TrNode_parent(node)), NULL);
363 TrNode_previous(TrNode_child(TrNode_parent(node))) = newnodef;
364 TrNode_child(TrNode_parent(node)) = newnodef;
365 }
366 new_trie_node(newnode, new_term_arg, newnodef, TrNode_child(child), TrNode_child(newnodef), NULL);
367 if (TrNode_child(newnodef))
368 TrNode_previous(TrNode_child(newnodef)) = newnode;
369 TrNode_child(newnodef) = newnode;
370 } else {
371 /* Check if one of the node siblings have new_term */
372 temp = node;
373 while (TrNode_previous(temp))
374 temp = TrNode_previous(temp);
375 while (temp && TrNode_entry(temp) != new_term)
376 temp = TrNode_next(temp);
377 if (temp) {
378 newnode = temp;
379 // Check if the childs of node/child exist already otherwise attach them
380 check_attach_childs(newnode, TrNode_child(child), TrNode_child(newnode), construct_function, destruct_function);
381 DATA_DESTRUCT_FUNCTION = destruct_function;
382 remove_child_nodes(TrNode_child(child));
383 TrNode_child(child) = NULL;
384 remove_entry(child);
385 return newnode;
386 } else { // Make a new node
387 new_trie_node(newnode, new_term, TrNode_parent(node), TrNode_child(child), TrNode_child(TrNode_parent(node)), NULL);
388 TrNode_previous(TrNode_child(TrNode_parent(node))) = newnode;
389 TrNode_child(TrNode_parent(node)) = newnode;
390 }
391 }
392 temp = TrNode_child(child);
393 if (IS_HASH_NODE(temp)) {
394 printf("HASH NODE ERROR: db_tries do not support hash nodes.\n");
395 abort();
396 TrNode *first_bucket, *bucket;
397 TrHash hash = (TrHash) temp;
398 first_bucket = TrHash_buckets(hash);
399 bucket = first_bucket + TrHash_num_buckets(hash);
400 do {
401 if ((temp = *--bucket)) {
402 do {
403 TrNode_parent(temp) = newnode;
404 temp = TrNode_next(temp);
405 } while(temp);
406 }
407 } while (bucket != first_bucket);
408 } else {
409 while (temp) {
410 TrNode_parent(temp) = newnode;
411 temp = TrNode_next(temp);
412 }
413 }
414 DATA_DESTRUCT_FUNCTION = destruct_function;
415 TrNode_child(child) = NULL;
416 remove_entry(child);
417 return newnode;
418}
419
420
421void check_attach_childs(TrNode parent, TrNode search_child, TrNode existing_child, void (*construct_function)(TrNode), void (*destruct_function)(TrNode)) {
422 TrNode newnode;
423 // Check if the childs of node/child exist already otherwise attach them
424 do {
425 while(existing_child && (TrNode_entry(existing_child) != PairEndTag) && (TrNode_entry(existing_child) != TrNode_entry(search_child)))
426 existing_child = TrNode_next(existing_child);
427
428 if (existing_child) {
429 if (TrNode_entry(existing_child) != PairEndTag)
430 check_attach_childs(existing_child, TrNode_child(search_child), TrNode_child(existing_child), construct_function, destruct_function);
431 existing_child = TrNode_child(parent);
432 search_child = TrNode_next(search_child);
433 } else if (TrNode_entry(search_child) == PairEndTag) {
434 newnode = parent;
435 DATA_DESTRUCT_FUNCTION = destruct_function;
436 remove_child_nodes(TrNode_child(newnode));
437 TrNode_child(newnode) = NULL;
438 newnode = trie_node_check_insert(newnode, PairEndTag);
439 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
440 (*construct_function)(newnode);
441 return;
442 } else {
443 existing_child = search_child;
444 search_child = TrNode_next(search_child);
445 if(TrNode_child(TrNode_parent(existing_child)) == existing_child) {
446 if(TrNode_next(existing_child)) {
447 TrNode_child(TrNode_parent(existing_child)) = TrNode_next(existing_child);
448 } else {
449 newnode = TrNode_parent(existing_child);
450// DATA_DESTRUCT_FUNCTION = destruct_function;
451// remove_child_nodes(TrNode_child(newnode));
452 TrNode_child(newnode) = NULL;
453 newnode = trie_node_check_insert(newnode, PairEndTag);
454 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
455 (*construct_function)(newnode);
456 }
457 }
458
459 if (TrNode_next(existing_child))
460 TrNode_previous(TrNode_next(existing_child)) = TrNode_previous(existing_child);
461 if (TrNode_previous(existing_child))
462 TrNode_next(TrNode_previous(existing_child)) = TrNode_next(existing_child);
463
464 TrNode_parent(existing_child) = parent;
465 TrNode_previous(existing_child) = NULL;
466 TrNode_next(existing_child) = TrNode_child(parent);
467 TrNode_previous(TrNode_child(parent)) = existing_child;
468 TrNode_child(parent) = existing_child;
469 existing_child = TrNode_child(parent);
470 }
471 } while(search_child);
472}
473
474
475YAP_Term core_get_trie_db_return_term(void) {
476 return TRIE_DEPTH_BREADTH_RETURN_TERM;
477}
478
479
480
481void core_set_trie_db_return_term(YAP_Term return_value){
482 TRIE_DEPTH_BREADTH_RETURN_TERM = return_value;
483 return;
484}
485
486
487
488void core_set_label_counter(YAP_Int value) {
489 LABEL_COUNTER = value; // Initialize the counter
490 return;
491}
492
493
494YAP_Int core_get_label_counter(void) {
495 return LABEL_COUNTER;
496}
497
498
499void core_initialize_depth_breadth_trie(TrNode node, TrNode *depth_node, TrNode *breadth_node) {
500 TrNode root = node;
501 YAP_Functor f;
502 f = YAP_MkFunctor(YAP_LookupAtom("depth"),2);
503 node = trie_node_check_insert(root, ApplTag | ((YAP_Term) f));
504 *depth_node = trie_node_check_insert(node, PairInitTag);
505 f = YAP_MkFunctor(YAP_LookupAtom("breadth"),2);
506 node = trie_node_check_insert(root, ApplTag | ((YAP_Term) f));
507 *breadth_node = trie_node_check_insert(node, PairInitTag);
508 TRIE_DEPTH_BREADTH_OPT_COUNT[0] = 0;
509 TRIE_DEPTH_BREADTH_OPT_COUNT[1] = 0;
510 TRIE_DEPTH_BREADTH_OPT_COUNT[2] = 0;
511 return;
512}
513
514
515
516void core_finalize_depth_breadth_trie(TrNode depth_node, TrNode breadth_node) {
517 depth_node = trie_node_check_insert(depth_node, YAP_MkIntTerm(1));
518 depth_node = trie_node_check_insert(depth_node, PairEndTag);
519 depth_node = trie_node_check_insert(depth_node, YAP_MkIntTerm(1));
520 remove_entry(depth_node);
521 breadth_node = trie_node_check_insert(breadth_node, YAP_MkIntTerm(1));
522 breadth_node = trie_node_check_insert(breadth_node, PairEndTag);
523 breadth_node = trie_node_check_insert(breadth_node, YAP_MkIntTerm(1));
524 remove_entry(breadth_node);
525 return;
526}
527
528
529TrNode get_simplification_sibling(TrNode node) {
530 TrNode sibling = node;
531 while (sibling != NULL && TrNode_entry(sibling) != PairEndTag)
532 sibling = TrNode_next(sibling);
533 if (sibling != NULL && TrNode_entry(sibling) == PairEndTag) return sibling;
534 sibling = node;
535 while (sibling != NULL && TrNode_entry(sibling) != PairEndTag)
536 sibling = TrNode_previous(sibling);
537 return sibling;
538}
539
540TrNode check_parent_first(TrNode node) {
541 TrNode simplification;
542 if (TrNode_entry(TrNode_myparent(node)) != PairInitTag) {
543 simplification = check_parent_first(TrNode_myparent(node));
544 if (simplification != NULL && TrNode_entry(simplification) == PairEndTag) return simplification;
545 }
546 simplification = get_simplification_sibling(node);
547 return simplification;
548}
549
550TrNode TrNode_myparent(TrNode node) {
551 TrNode parent = TrNode_parent(node);
552 while (parent != NULL && IS_FUNCTOR_NODE(parent))
553 parent = TrNode_parent(parent);
554 return parent;
555}
556
557TrNode core_simplification_reduction(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)) {
558 /* Try to find the greatest parent that has a sibling that is a PairEndTag: this indicates a deep simplification */
559 node = check_parent_first(TrNode_myparent(node));
560 if (node != NULL) {
561 /* do breadth reduction simplification */
562 node = TrNode_parent(node);
563 DATA_DESTRUCT_FUNCTION = destruct_function;
564 remove_child_nodes(TrNode_child(node));
565 TrNode_child(node) = NULL;
566 node = trie_node_check_insert(node, PairEndTag);
567 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
568 }
569 return node;
570}
571
572
573TrNode core_depth_reduction(TrEngine engine, TrNode node, TrNode depth_node, YAP_Int opt_level, void (*construct_function)(TrNode), void (*destruct_function)(TrNode), void (*copy_function)(TrNode, TrNode), void (*correct_order_function)(void)) {
574 TrNode leaf = node;
575 YAP_Term t, *stack_top;
576 int count = -1;
577 /* collect depth nodes */
578 stack_args_base = stack_args = AUXILIARY_TERM_STACK;
579 stack_top = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1;
580 do {
581 node = TrNode_parent(node);
582 if (TrNode_entry(node) == PairInitTag) {
583 node = TrNode_child(node);
584 break;
585 }
586 //Nested Trie code
587 if (IS_FUNCTOR_NODE(TrNode_parent(node)) && (strcmp(YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & TrNode_entry(TrNode_parent(node))))), NESTED_TRIE_TERM) == 0)) {
588 /* nested trie: stop procedure and return nested trie node */
589 return node;
590 }
591 PUSH_DOWN(stack_args, TrNode_entry(node), stack_top);
592 if (!IS_FUNCTOR_NODE(node))
593 count++;
594 } while (TrNode_next(node) == NULL && TrNode_child(TrNode_parent(node)) == node);
595 if (!count)
596 return NULL;
597 while (IS_FUNCTOR_NODE(TrNode_parent(node))) {
598 node = TrNode_parent(node);
599 PUSH_DOWN(stack_args, TrNode_entry(node), stack_top);
600 }
601 TrNode temp = TrNode_child(TrNode_parent(node));
602 if (IS_HASH_NODE(temp)) {
603 printf("HASH NODE ERROR: db_tries do not support hash nodes.\n");
604 abort();
605 TrNode *first_bucket, *bucket;
606 TrHash hash = (TrHash) temp;
607 first_bucket = TrHash_buckets(hash);
608 bucket = first_bucket + TrHash_num_buckets(hash);
609 do {
610 if ((temp = *--bucket)) {
611 while(TrNode_next(temp) != NULL) {
612 if (TrNode_entry(temp) == PairEndTag)
613 return NULL;
614 temp = TrNode_next(temp);
615 }
616 }
617 } while (bucket != first_bucket);
618 } else {
619 while(TrNode_next(temp) != NULL) {
620 if (TrNode_entry(temp) == PairEndTag)
621 return NULL;
622 temp = TrNode_next(temp);
623 }
624 }
625
626 t = update_depth_breadth_trie(engine, depth_node, opt_level, construct_function, destruct_function, copy_function, correct_order_function);
627
628 /* do depth reduction */
629 DATA_DESTRUCT_FUNCTION = destruct_function;
630 node = trie_node_check_insert(TrNode_parent(node), t);
631 node = trie_node_check_insert(node, PairEndTag);
632 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
633 temp = TrNode_parent(leaf);
634 remove_child_nodes(TrNode_child(temp));
635 TrNode_child(temp) = NULL;
636 remove_entry(temp);
637 return node;
638}
639
640
641
642TrNode core_breadth_reduction(TrEngine engine, TrNode node, TrNode breadth_node, YAP_Int opt_level, void (*construct_function)(TrNode), void (*destruct_function)(TrNode), void (*copy_function)(TrNode, TrNode), void (*correct_order_function)(void)) {
643 YAP_Term t, *stack_top;
644 int count = -1;
645 TrNode child;
646
647 /* Simplification with breadth reduction (faster dbtrie execution worse BDD)
648 child = core_simplification_reduction(engine, node, destruct_function);
649 if (child) return child;
650 */
651
652 /* collect breadth nodes */
653 stack_args_base = stack_args = AUXILIARY_TERM_STACK;
654 stack_top = AUXILIARY_TERM_STACK + CURRENT_AUXILIARY_TERM_STACK_SIZE - 1;
655 node = TrNode_parent(TrNode_parent(node));
656 // printf("start node: "); displaynode(node);
657 if (IS_FUNCTOR_NODE(node)) {
658 while(IS_FUNCTOR_NODE(node))
659 node = TrNode_parent(node);
660 child = TrNode_child(node);
661 while((TrNode_next(child) == NULL) && (TrNode_child(TrNode_parent(child)) == child) && (TrNode_entry(TrNode_child(child)) != PairEndTag))
662 child = TrNode_child(child);
663 } else
664 child = TrNode_child(node);
665 // printf("Chosen start node: "); displaynode(child);
666 if (IS_HASH_NODE(child)) {
667 printf("HASH NODE ERROR: db_tries do not support hash nodes.\n");
668 abort();
669 /* Comment code for HASH NODES - the commented code 100% has a bug
670 TrNode *first_bucket, *bucket;
671 TrHash hash = (TrHash) child;
672 first_bucket = TrHash_buckets(hash);
673 bucket = first_bucket + TrHash_num_buckets(hash);
674 do {
675 if ((child = *--bucket)) {
676 do {
677 if (TrNode_entry(child) == PairEndTag)
678 return core_breadth_reduction(engine, child, breadth_node, opt_level, construct_function, destruct_function, copy_function, correct_order_function);
679 while (IS_FUNCTOR_NODE(child)) {
680 child = TrNode_child(child);
681 if (IS_HASH_NODE(child)) { // gets first child in the hash
682 TrNode *first_bucket2, *bucket2;
683 TrHash hash2 = (TrHash) child;
684 first_bucket2 = TrHash_buckets(hash2);
685 bucket2 = first_bucket2 + TrHash_num_buckets(hash2);
686 while(!(child = *--bucket2));
687 }
688 }
689 TrNode temp = TrNode_child(child);
690 if (temp == NULL)
691 return NULL;
692 if (IS_HASH_NODE(temp)) {
693 TrNode *first_bucket2, *bucket2;
694 TrHash hash2 = (TrHash) temp;
695 first_bucket2 = TrHash_buckets(hash2);
696 bucket2 = first_bucket2 + TrHash_num_buckets(hash2);
697 do {
698 if ((temp = *--bucket2)) {
699 while((temp != NULL) && (TrNode_entry(temp) != PairEndTag))
700 temp = TrNode_next(temp);
701 }
702 } while (bucket2 != first_bucket2 && temp == NULL);
703 } else {
704 while((temp != NULL) && (TrNode_entry(temp) != PairEndTag))
705 temp = TrNode_next(temp);
706 }
707 //Nested Trie code
708 if (IS_FUNCTOR_NODE(TrNode_parent(child)) && (strcmp(YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & TrNode_entry(TrNode_parent(child))))), NESTED_TRIE_TERM) == 0)) {
709 // nested trie: stop procedure and return nested trie node
710 return child;
711 }
712 PUSH_DOWN(stack_args, TrNode_entry(child), stack_top);
713 count++;
714 if (IS_FUNCTOR_NODE(TrNode_parent(child))) {
715 temp = TrNode_parent(child);
716 while (IS_FUNCTOR_NODE(temp)) {
717 PUSH_DOWN(stack_args, TrNode_entry(temp), stack_top);
718 temp = TrNode_parent(temp);
719 }
720 while ((TrNode_next(child) == NULL) && IS_FUNCTOR_NODE(TrNode_parent(child)) && (bucket == first_bucket))
721 child = TrNode_parent(child);
722 }
723 child = TrNode_next(child);
724 } while (child);
725 }
726 } while (bucket != first_bucket);
727 */
728 } else {
729 do {
730 if (TrNode_entry(child) == PairEndTag) {
731 /* do breadth reduction simplification */
732 printf("SIMPLIFICATION ERROR: I should never arrive here, please contact Theo!\n");
733 abort();
734 /*
735 node = TrNode_parent(child);
736 DATA_DESTRUCT_FUNCTION = destruct_function;
737 remove_child_nodes(TrNode_child(node));
738 TrNode_child(node) = NULL;
739 node = trie_node_check_insert(node, PairEndTag);
740 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
741 return node;
742 */
743 }
744 while (IS_FUNCTOR_NODE(child)) {
745 child = TrNode_child(child);
746 if (IS_HASH_NODE(child)) { // gets first child in the hash
747 printf("HASH NODE ERROR: db_tries do not support hash nodes.\n");
748 abort();
749 TrNode *first_bucket, *bucket;
750 TrHash hash = (TrHash) child;
751 first_bucket = TrHash_buckets(hash);
752 bucket = first_bucket + TrHash_num_buckets(hash);
753 while(!(child = *--bucket));
754 }
755 }
756 if (TrNode_child(child) == NULL) return NULL;
757 if (TrNode_entry(TrNode_child(child)) != PairEndTag) return NULL;
758 /* nested trie: stop procedure and return nested trie node */
759 if (IS_FUNCTOR_NODE(TrNode_parent(child)) && (strcmp(YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(~ApplTag & TrNode_entry(TrNode_parent(child))))), NESTED_TRIE_TERM) == 0))
760 return child;
761 PUSH_DOWN(stack_args, TrNode_entry(child), stack_top);
762 count++;
763 if (IS_FUNCTOR_NODE(TrNode_parent(child))) {
764 TrNode temp = TrNode_parent(child);
765 while (IS_FUNCTOR_NODE(temp)) {
766 PUSH_DOWN(stack_args, TrNode_entry(temp), stack_top);
767 temp = TrNode_parent(temp);
768 }
769 while ((TrNode_next(child) == NULL) && IS_FUNCTOR_NODE(TrNode_parent(child)))
770 child = TrNode_parent(child);
771 }
772 child = TrNode_next(child);
773 } while (child);
774 }
775 if (!count) {
776 /* termination condition */
777 core_set_trie_db_return_term(get_return_node_term(TrNode_child(node)));
778 node = TrNode_parent(node);
779 DATA_DESTRUCT_FUNCTION = destruct_function;
780 remove_child_nodes(TrNode_child(node));
781 TrNode_child(node) = NULL;
782 return NULL;
783 }
784
785 t = update_depth_breadth_trie(engine, breadth_node, opt_level, construct_function, destruct_function, copy_function, correct_order_function);
786
787 /* do breadth reduction */
788 DATA_DESTRUCT_FUNCTION = destruct_function;
789 remove_child_nodes(TrNode_child(node));
790 TrNode_child(node) = NULL;
791 node = trie_node_check_insert(node, t);
792 node = trie_node_check_insert(node, PairEndTag);
793 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
794 return node;
795}
796
797
798inline
799YAP_Term get_return_node_term(TrNode node) {
800 YAP_Term args[1], t;
801 if (IS_HASH_NODE(node)) {
802 TrNode *first_bucket, *bucket;
803 TrHash hash = (TrHash) node;
804 first_bucket = TrHash_buckets(hash);
805 bucket = first_bucket + TrHash_num_buckets(hash);
806 while(!(node = *--bucket));
807 t = TrNode_entry(node);
808 } else if (IS_FUNCTOR_NODE(node)) {
809 args[0] = get_return_node_term(TrNode_child(node));
810 t = YAP_MkApplTerm((YAP_Functor)(~ApplTag & TrNode_entry(node)), 1, args);
811 } else {
812 t = TrNode_entry(node);
813 }
814 return t;
815}
816
817
818int traverse_get_counter(TrNode node) {
819 int count = -1;
820 while (TrNode_entry(node) != PairEndTag) {
821 if (!IS_FUNCTOR_NODE(node))
822 count++;
823 node = TrNode_child(node);
824 if (IS_HASH_NODE(node)) {
825 TrNode *first_bucket, *bucket;
826 TrHash hash = (TrHash) node;
827 first_bucket = TrHash_buckets(hash);
828 bucket = first_bucket + TrHash_num_buckets(hash);
829 do {
830 if ((node = *--bucket)) {
831 while(TrNode_next(node) != NULL)
832 node = TrNode_next(node);
833 }
834 } while (bucket != first_bucket);
835 } else {
836 while(TrNode_next(node) != NULL)
837 node = TrNode_next(node);
838 }
839 }
840 return atoi(YAP_AtomName(YAP_AtomOfTerm(TrNode_entry(TrNode_child(node)))) + 1) - count;
841}
842
843
844YAP_Term generate_label(YAP_Int Index) {
845 char label[20];
846 sprintf(label,"L%" Int_F, Index);
847 return YAP_MkAtomTerm(YAP_LookupAtom(label));
848}
849
850
851
852YAP_Term update_depth_breadth_trie(TrEngine engine, TrNode root, YAP_Int opt_level, void (*construct_function)(TrNode), void (*destruct_function)(TrNode), void (*copy_function)(TrNode, TrNode), void (*correct_order_function)(void)) {
853 TrNode node = root, remember = NULL;
854 int count = -1, cnt = -1, c_cnt = 0, f_cnt = 0;
855 YAP_Int BAK_CURRENT_TRIE_MODE = CURRENT_TRIE_MODE;
856 YAP_Term t, tt, ret_t = PairEndTag;
857 if (opt_level > 0)
858 CURRENT_TRIE_MODE = TRIE_MODE_MINIMAL;
859 else
860 CURRENT_TRIE_MODE = TRIE_MODE_STANDARD;
861 CURRENT_TRIE_ENGINE = engine;
862 DATA_DESTRUCT_FUNCTION = destruct_function;
863 DATA_COPY_FUNCTION = copy_function;
864 do {
865 t = POP_UP(stack_args);
866 node = trie_node_check_insert(node, t);
867 if (!IS_FUNCTOR_NODE(node))
868 count++;
869 if (opt_level > 0) {
870 // Optimization 1: when asserting a non-minimal you can reuse minimal.
871 if (TrNode_entry(node) == PairEndTag) {
872 // Check to find the longest re-usage
873 TrNode c_node = trie_node_check(TrNode_parent(node), t), end_node;
874 c_cnt = 0;
875 f_cnt = 0;
876 while (c_node != NULL) {
877 if (stack_args_base != stack_args) {
878 c_cnt++;
879 tt = POP_UP(stack_args);
880 end_node = trie_node_check(c_node, PairEndTag);
881 c_node = trie_node_check(c_node, tt);
882 if ((c_node!= NULL) && !IS_FUNCTOR_NODE(c_node))
883 f_cnt++;
884 if ((end_node != NULL)) {
885 count += f_cnt;
886 f_cnt = 0;
887 c_cnt = 0;
888 t = tt;
889 node = end_node;
890 }
891 } else {
892 // reached the end
893 node = c_node;
894 c_node = NULL;
895 count += f_cnt;
896 f_cnt = 0;
897 c_cnt = 0;
898 }
899 }
900 stack_args += c_cnt;
901 }
902 if (TrNode_entry(node) == PairEndTag) {
903 if (count > TRIE_DEPTH_BREADTH_MIN_PREFIX - 2) {
904 TRIE_DEPTH_BREADTH_OPT_COUNT[0]++;
905 cnt = -1; // reset optimization 3 counter
906 count = 0;
907 node = trie_node_check_insert(root, TrNode_entry(TrNode_child(node)));
908 if (TrNode_child(node) != NULL)
909 cnt++;
910 node = trie_node_check_insert(node, t);
911 if (!IS_FUNCTOR_NODE(node)) {
912 count++;
913 if (TrNode_child(node) != NULL)
914 cnt++;
915 }
916 } else {
917 CURRENT_TRIE_MODE = TRIE_MODE_STANDARD;
918 node = trie_node_check_insert(TrNode_parent(node), t);
919 CURRENT_TRIE_MODE = TRIE_MODE_MINIMAL;
920 }
921 }
922 }
923 if (opt_level > 2) {
924 // Optimization 3: when asserting common prefix of size 2 or longer.
925 // 1) remember last node and count
926 // 2) after normal assertion ends go to remembered node, count
927 // 3) assert PairEndTag to triger optimization 2
928 if (TrNode_child(node) != NULL) {
929 if (!IS_FUNCTOR_NODE(node))
930 cnt++;
931 } else {
932 if ((remember == NULL) && (cnt > 0) && (cnt > TRIE_DEPTH_BREADTH_MIN_PREFIX - 2)) {
933 TRIE_DEPTH_BREADTH_OPT_COUNT[1]--;
934 TRIE_DEPTH_BREADTH_OPT_COUNT[2]++;
935 remember = node;
936 do {
937 remember = TrNode_parent(remember);
938 } while(IS_FUNCTOR_NODE(remember));
939 }
940 }
941 }
942 } while (stack_args_base != stack_args);
943 do {
944 t = PairEndTag;
945 if (opt_level > 1) {
946 // Optimization 2: when asserting a more minimal you can reuse it
947 // a) Traverse and find the lowest L and the length of branch LN = (L? - (length - 1) + count)
948 // b) insert LN
949 // c) copy childs of node
950 // d) remove childs of node
951 // e) insert ]
952 // f) insert LN
953 // g) REORDER Entries
954 if ((TrNode_child(node) != NULL) && (TrNode_entry(TrNode_child(node)) != PairEndTag) && (count > TRIE_DEPTH_BREADTH_MIN_PREFIX - 2)) {
955 TRIE_DEPTH_BREADTH_OPT_COUNT[1]++;
956 t = generate_label(traverse_get_counter(node));
957 root = trie_node_check_insert(root, t);
958 TrNode_child(root) = copy_child_nodes(root, TrNode_child(node));
959 remove_child_nodes(TrNode_child(node));
960 TrNode_child(node) = NULL;
961 }
962 }
963 node = trie_node_check_insert(node, PairEndTag);
964
965 if (t == PairEndTag) {
966 if (TrNode_child(node)) {
967 t = TrNode_entry(TrNode_child(node));
968 } else {
969 LABEL_COUNTER += count;
970 t = generate_label(LABEL_COUNTER);
971 node = trie_node_check_insert(node, t);
972 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
973 (*construct_function)(node);
974 }
975 } else {
976 node = trie_node_check_insert(node, t);
977 INCREMENT_ENTRIES(CURRENT_TRIE_ENGINE);
978 (*construct_function)(node);
979 (*correct_order_function)();
980 }
981 // Optimization 3: part 2
982 node = remember;
983 count = cnt;
984 remember = NULL;
985 if (ret_t == PairEndTag)
986 ret_t = t;
987 } while(node != NULL);
988
989 CURRENT_TRIE_MODE = BAK_CURRENT_TRIE_MODE;
990 return ret_t;
991}
992
993
994
995YAP_Int core_db_trie_get_optimization_level_count(YAP_Int opt_level) {
996 return TRIE_DEPTH_BREADTH_OPT_COUNT[opt_level - 1];
997}
998
999
1000/* -------------------------- */
1001/* Debug Procedures */
1002/* -------------------------- */
1003
1004void displaynode(TrNode node) {
1005 if (node != NULL) {
1006 if (IS_HASH_NODE(node))
1007 printf("HASH n%i, b%i, p%p\n", TrHash_num_nodes((TrHash) node), TrHash_num_buckets((TrHash) node), node);
1008 else if (TrNode_entry(node) == PairInitTag)
1009 printf("PairInitTag\n");
1010 else if (TrNode_entry(node) == PairEndTag)
1011 printf("PairEndTag\n");
1012 else if (IS_FUNCTOR_NODE(node))
1013 printf("functor(%s)\n", YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)( ~ApplTag & TrNode_entry(node)))));
1014 else if (YAP_IsIntTerm(TrNode_entry(node)))
1015 printf("int(%"Int_F")\n", YAP_IntOfTerm(TrNode_entry(node)));
1016 else if (YAP_IsAtomTerm(TrNode_entry(node)))
1017 printf("atom(%s)\n", YAP_AtomName(YAP_AtomOfTerm(TrNode_entry(node))));
1018 else
1019 printf("What?\n");
1020 } else
1021 printf("null\n");
1022 return;
1023}
1024
1025void displayentry(TrNode node) {
1026 printf("Entry Contains Bottom Up:\n");
1027 while (node) {
1028 displaynode(node);
1029 node = TrNode_parent(node);
1030 }
1031 printf("--- End of Entry ---\n");
1032}
1033
1034void displayterm(YAP_Term term) {
1035 if (term) {
1036 if (term == PairInitTag)
1037 printf("PairInitTag\n");
1038 else if (term == PairEndTag)
1039 printf("PairEndTag\n");
1040 else if (YAP_IsApplTerm(term))
1041 printf("functor(%s)\n", YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)( ~ApplTag & term))));
1042 else if (YAP_IsIntTerm(term))
1043 printf("int(%"Int_F")\n", YAP_IntOfTerm(term));
1044 else if (YAP_IsAtomTerm(term))
1045 printf("atom(%s)\n", YAP_AtomName(YAP_AtomOfTerm(term)));
1046 else
1047 printf("What?\n");
1048 } else
1049 printf("null\n");
1050 return;
1051}
1052
1053void displaytrie(TrNode node) {
1054 while(TrNode_entry(node) != PairInitTag){
1055 printf("?: "); displaynode(node);
1056 node = TrNode_parent(node);
1057 }
1058 display_trie_inner(node);
1059}
1060
1061void display_trie_inner(TrNode node) {
1062 trie_display_node(node);
1063 if (TrNode_entry(node) != PairEndTag && TrNode_child(node))
1064 display_trie_inner(TrNode_child(node));
1065 if (TrNode_next(node)) {
1066 trie_display_node(TrNode_parent(node)); display_trie_inner(TrNode_next(node));
1067 }
1068}
1069
1070void trie_display_node(TrNode node) {
1071 if (node != NULL) {
1072 if (IS_HASH_NODE(node))
1073 printf("HASH(n%i, b%i, p%p), ", TrHash_num_nodes((TrHash) node), TrHash_num_buckets((TrHash) node), node);
1074 else if (TrNode_entry(node) == PairInitTag)
1075 printf("PairInitTag, ");
1076 else if (TrNode_entry(node) == PairEndTag)
1077 printf("PairEndTag\n");
1078 else if (IS_FUNCTOR_NODE(node))
1079 printf("functor(%s), ", YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)( ~ApplTag & TrNode_entry(node)))));
1080 else if (YAP_IsIntTerm(TrNode_entry(node)))
1081 printf("int(%" Int_F"), ", YAP_IntOfTerm(TrNode_entry(node)));
1082 else if (YAP_IsAtomTerm(TrNode_entry(node)))
1083 printf("atom(%s), ", YAP_AtomName(YAP_AtomOfTerm(TrNode_entry(node))));
1084 else
1085 printf("What?\n");
1086 } else
1087 printf("null\n");
1088 return;
1089}
1090
Definition: hash.h:40