fix syntax error message handling
improve redblack trees and use it to reimplement association lists and to have better implementation of several graph algorithms. git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1591 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
parent
39daac182e
commit
783ae4b9a0
@ -17,9 +17,9 @@
|
||||
]).
|
||||
|
||||
:- use_module(library(rbtrees), [
|
||||
new/1,
|
||||
lookup/3,
|
||||
insert/4
|
||||
rb_new/1,
|
||||
rb_lookup/3,
|
||||
rb_insert/4
|
||||
]).
|
||||
|
||||
:- meta_predicate store_evidence(:).
|
||||
@ -68,7 +68,7 @@ add_links([K0|TVs],K) :-
|
||||
|
||||
|
||||
incorporate_evidence(Vs,AllVs) :-
|
||||
new(Cache0),
|
||||
rb_new(Cache0),
|
||||
create_open_list(Vs, OL, FL, Cache0, CacheI),
|
||||
do_variables(OL, FL, CacheI),
|
||||
extract_vars(OL, AllVs).
|
||||
@ -77,7 +77,7 @@ create_open_list([], L, L, C, C).
|
||||
create_open_list([V|Vs], [K-V|OL], FL, C0, CF) :-
|
||||
clpbn:get_atts(V,[key(K)]),
|
||||
add_evidence(K, V),
|
||||
insert(C0, K, V, CI),
|
||||
rb_insert(C0, K, V, CI),
|
||||
create_open_list(Vs, OL, FL, CI, CF).
|
||||
|
||||
do_variables([], [], _) :- !.
|
||||
@ -94,10 +94,10 @@ create_new_variable(K, V, Vf0, Vff, C0, Cf) :-
|
||||
|
||||
add_variables([], [], Vf, Vf, C, C).
|
||||
add_variables([K|TVs], [V|NTVs], Vf0, Vff, C0, Cf) :-
|
||||
lookup(K, V, C0), !,
|
||||
rb_lookup(K, V, C0), !,
|
||||
add_variables(TVs, NTVs, Vf0, Vff, C0, Cf).
|
||||
add_variables([K|TVs], [V|NTVs], [K-V|Vf0], Vff, C0, Cf) :-
|
||||
insert(C0, K, V, C1),
|
||||
rb_insert(C0, K, V, C1),
|
||||
create_new_variable(K, V, Vf0, Vf1, C1, C2),
|
||||
add_variables(TVs, NTVs, Vf1, Vff, C2, Cf).
|
||||
|
||||
|
@ -11,9 +11,9 @@
|
||||
check_if_gibbs_done/1]).
|
||||
|
||||
:- use_module(library(rbtrees),
|
||||
[new/1,
|
||||
insert/4,
|
||||
lookup/3]).
|
||||
[rb_new/1,
|
||||
rb_insert/4,
|
||||
rb_lookup/3]).
|
||||
|
||||
:- use_module(library(lists),
|
||||
[member/2,
|
||||
@ -62,7 +62,7 @@ initialise(LVs, Graph, GVs, OutputVars, VarOrder) :-
|
||||
add_output_vars(GVs, Keys, OutputVars).
|
||||
|
||||
init_keys(Keys0) :-
|
||||
new(Keys0).
|
||||
rb_new(Keys0).
|
||||
|
||||
gen_keys([], I, I, Keys, Keys).
|
||||
gen_keys([V|Vs], I0, If, Keys0, Keys) :-
|
||||
@ -70,7 +70,7 @@ gen_keys([V|Vs], I0, If, Keys0, Keys) :-
|
||||
gen_keys(Vs, I0, If, Keys0, Keys).
|
||||
gen_keys([V|Vs], I0, If, Keys0, Keys) :-
|
||||
I is I0+1,
|
||||
insert(Keys0,V,I,KeysI),
|
||||
rb_insert(Keys0,V,I,KeysI),
|
||||
gen_keys(Vs, I, If, KeysI, Keys).
|
||||
|
||||
graph_representation([],_,_,_,[]).
|
||||
@ -112,7 +112,7 @@ get_sizes([V|Parents], [Sz|Szs]) :-
|
||||
|
||||
parent_indices([], _, []).
|
||||
parent_indices([V|Parents], Keys, [I|IParents]) :-
|
||||
lookup(V, I, Keys),
|
||||
rb_lookup(V, I, Keys),
|
||||
parent_indices(Parents, Keys, IParents).
|
||||
|
||||
|
||||
@ -139,7 +139,7 @@ propagate2parents([V|NewParents], Table, Variables, Graph, Keys) :-
|
||||
propagate2parents(NewParents,Table, Variables, Graph, Keys).
|
||||
|
||||
add2graph(V, Vals, Table, IParents, Graph, Keys) :-
|
||||
lookup(V, Index, Keys),
|
||||
rb_lookup(V, Index, Keys),
|
||||
(var(Vals) -> true ; length(Vals,Sz)),
|
||||
arg(Index, Graph, var(V,Index,_,Vals,Sz,VarSlot,_,_,_)),
|
||||
member(tabular(Table,Index,IParents), VarSlot), !.
|
||||
@ -156,7 +156,7 @@ split_parents([I-V|Sorted], [V|SortedNVs],[I|SortedIndices]) :-
|
||||
|
||||
vars2indices([],_,[]).
|
||||
vars2indices([V|Parents],Keys,[I-V|IParents]) :-
|
||||
lookup(V, I, Keys),
|
||||
rb_lookup(V, I, Keys),
|
||||
vars2indices(Parents,Keys,IParents).
|
||||
|
||||
compact_table(NewTable, RepTable) :-
|
||||
@ -297,7 +297,7 @@ store_mblanket(I,Values,Probs) :-
|
||||
|
||||
add_output_vars([], _, []).
|
||||
add_output_vars([V|LVs], Keys, [I|OutputVars]) :-
|
||||
lookup(V, I, Keys),
|
||||
rb_lookup(V, I, Keys),
|
||||
add_output_vars(LVs, Keys, OutputVars).
|
||||
|
||||
process(VarOrder, Graph, OutputVars, Estimates) :-
|
||||
|
@ -4,9 +4,9 @@
|
||||
reversed_topsort/2]).
|
||||
|
||||
:- use_module(library(rbtrees),
|
||||
[new/1,
|
||||
lookup/3,
|
||||
insert/4]).
|
||||
[rb_new/1,
|
||||
rb_lookup/3,
|
||||
rb_insert/4]).
|
||||
|
||||
:- use_module(library(lists),
|
||||
[reverse/2]).
|
||||
@ -15,18 +15,18 @@
|
||||
/* graph is as Node-[Parents] */
|
||||
|
||||
topsort(Graph0, Sorted) :-
|
||||
new(RB),
|
||||
rb_new(RB),
|
||||
topsort(Graph0, [], RB, Sorted).
|
||||
|
||||
topsort(Graph0, Sorted0, Sorted) :-
|
||||
new(RB),
|
||||
rb_new(RB),
|
||||
topsort(Graph0, Sorted0, RB, Sorted).
|
||||
|
||||
%
|
||||
% Have children first in the list
|
||||
%
|
||||
reversed_topsort(Graph0, RSorted) :-
|
||||
new(RB),
|
||||
rb_new(RB),
|
||||
topsort(Graph0, [], RB, Sorted),
|
||||
reverse(Sorted, RSorted).
|
||||
|
||||
@ -42,7 +42,7 @@ add_nodes([N-Ns|Graph0], Found0, SortI, NewGraph, Found, NSort) :-
|
||||
( NNs == [] ->
|
||||
NewGraph = IGraph,
|
||||
NSort = [N|Sort],
|
||||
insert(Found0, N, '$', FoundI)
|
||||
rb_insert(Found0, N, '$', FoundI)
|
||||
;
|
||||
NewGraph = [N-NNs|IGraph],
|
||||
NSort = Sort,
|
||||
@ -52,7 +52,7 @@ add_nodes([N-Ns|Graph0], Found0, SortI, NewGraph, Found, NSort) :-
|
||||
|
||||
delete_nodes([], _, []).
|
||||
delete_nodes([N|Ns], Found, NNs) :-
|
||||
lookup(N,'$',Found), !,
|
||||
rb_lookup(N,'$',Found), !,
|
||||
delete_nodes(Ns, Found, NNs).
|
||||
delete_nodes([N|Ns], Found, [N|NNs]) :-
|
||||
delete_nodes(Ns, Found, NNs).
|
||||
|
@ -15,8 +15,18 @@
|
||||
<h1>Changes in YAP-5.1</h1>
|
||||
|
||||
<h2>Yap-5.1.0:</h2>
|
||||
<ul> FIXED: compiling inline lists would compile the lists and more
|
||||
(obs Nicos Angelopoulos). </li>
|
||||
<ul> NEW: new implementation of association list, based on red-black
|
||||
trees. </li>
|
||||
<ul> NEW: undgraph library, based on dgraphs. </li>
|
||||
<ul> NEW: undgraph library, based on dgraphs. </li>
|
||||
<ul> NEW: dgraphs library, towards a more efficient implementation of
|
||||
directed graphs. </li>
|
||||
<ul> NEW: rb_update, rb_apply, rb_visit, rb_keys and rb_map. </li>
|
||||
<ul> FIXED: use rb_ prefix for all red black predicates. </li>
|
||||
<ul> FIXED: got confused about position of syntax error (obs Mark
|
||||
Goadrich). </li>
|
||||
<ul> FIXED: compiling inline lists would compile the lists and then
|
||||
some more (obs Nicos Angelopoulos). </li>
|
||||
<ul> FIXED: message queue ops should not fail silently (obs Paulo
|
||||
Moura). </li>
|
||||
<ul> FIXED: stream bugs in iopreds.c (Takeyuki SHIRAMOTO). </li>
|
||||
|
493
docs/yap.tex
493
docs/yap.tex
@ -200,6 +200,8 @@ Subnodes of Library
|
||||
* Timeout:: Call With Timeout
|
||||
* Trees:: Updatable Binary Trees
|
||||
* UGraphs:: Unweighted Graphs
|
||||
* DGraphs:: Directed Graphs Implemented With Red-Black Trees
|
||||
* UnDGraphs:: Undirected Graphs Using DGraphs
|
||||
|
||||
Subnodes of Debugging
|
||||
* Deb Preds:: Debugging Predicates
|
||||
@ -6739,6 +6741,8 @@ Library, Extensions, Builtins, Top
|
||||
* Timeout:: Call With Timeout
|
||||
* Trees:: Updatable Binary Trees
|
||||
* UGraphs:: Unweighted Graphs
|
||||
* DGraphs:: Directed Graphs Implemented With Red-Black Trees
|
||||
* UnDGraphs:: Undirected Graphs Using DGraphs
|
||||
|
||||
|
||||
@end menu
|
||||
@ -6866,7 +6870,10 @@ maplist(mapargs(number_atom),[c(1),s(1,2,3)],[c('1'),s('1','2','3')]).
|
||||
@cindex association list
|
||||
|
||||
The following association list manipulation predicates are available
|
||||
once included with the @code{use_module(library(assoc))} command.
|
||||
once included with the @code{use_module(library(assoc))} command. The
|
||||
original library used Richard O'Keefe's implementation, on top of
|
||||
unbalanced binary trees. The current code utilises code from the
|
||||
red-black trees library and emulates the SICStus Prolog interface.
|
||||
|
||||
@table @code
|
||||
@item assoc_to_list(+@var{Assoc},?@var{List})
|
||||
@ -6877,6 +6884,29 @@ Given an association list @var{Assoc} unify @var{List} with a list of
|
||||
the form @var{Key-Val}, where the elements @var{Key} are in ascending
|
||||
order.
|
||||
|
||||
@item del_assoc(+@var{Key}, +@var{Assoc}, ?@var{Val}, ?@var{NewAssoc})
|
||||
@findex del_assoc/4
|
||||
@syindex del_assoc/4
|
||||
@cnindex del_assoc/4
|
||||
Succeeds if @var{NewAssoc} is an association list, obtained by removing
|
||||
the element with @var{Key} and @var{Val} from the list @var{Assoc}.
|
||||
|
||||
@item del_max_assoc(+@var{Assoc}, ?@var{Key}, ?@var{Val}, ?@var{NewAssoc})
|
||||
@findex del_max_assoc/4
|
||||
@syindex del_max_assoc/4
|
||||
@cnindex del_max_assoc/4
|
||||
Succeeds if @var{NewAssoc} is an association list, obtained by removing
|
||||
the largest element of the list, with @var{Key} and @var{Val} from the
|
||||
list @var{Assoc}.
|
||||
|
||||
@item del_min_assoc(+@var{Assoc}, ?@var{Key}, ?@var{Val}, ?@var{NewAssoc})
|
||||
@findex del_min_assoc/4
|
||||
@syindex del_min_assoc/4
|
||||
@cnindex del_min_assoc/4
|
||||
Succeeds if @var{NewAssoc} is an association list, obtained by removing
|
||||
the smallest element of the list, with @var{Key} and @var{Val}
|
||||
from the list @var{Assoc}.
|
||||
|
||||
@item empty_assoc(+@var{Assoc})
|
||||
@findex empty_assoc/1
|
||||
@syindex empty_assoc/1
|
||||
@ -6892,9 +6922,9 @@ with two associated elements. It can be used to enumerate all elements
|
||||
in the association list.
|
||||
|
||||
@item get_assoc(+@var{Key},+@var{Assoc},?@var{Value})
|
||||
@findex get_assoc/3
|
||||
@syindex get_assoc/3
|
||||
@cnindex get_assoc/3
|
||||
@findex get_next_assoc/4
|
||||
@syindex get_next_assoc/4
|
||||
@cnindex get_next_assoc/4
|
||||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||||
return the associated value.
|
||||
|
||||
@ -6906,6 +6936,27 @@ If @var{Key} is one of the elements in the association list @var{Assoc},
|
||||
return the associated value @var{Value} and a new association list
|
||||
@var{NAssoc} where @var{Key} is associated with @var{NValue}.
|
||||
|
||||
@item get_prev_assoc(+@var{Key},+@var{Assoc},?@var{Next},?@var{Value})
|
||||
@findex get_prev_assoc/4
|
||||
@syindex get_prev_assoc/4
|
||||
@cnindex get_prev_assoc/4
|
||||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||||
return the previous key, @var{Next}, and its value, @var{Value}.
|
||||
|
||||
@item get_next_assoc(+@var{Key},+@var{Assoc},?@var{Next},?@var{Value})
|
||||
@findex get_assoc/3
|
||||
@syindex get_assoc/3
|
||||
@cnindex get_assoc/3
|
||||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||||
return the next key, @var{Next}, and its value, @var{Value}.
|
||||
|
||||
@item is_assoc(+@var{Assoc})
|
||||
@findex is_assoc/1
|
||||
@syindex is_assoc/1
|
||||
@cnindex is_assoc/1
|
||||
Succeeds if @var{Assoc} is an association list, that is, if it is a
|
||||
red-black tree.
|
||||
|
||||
@item list_to_assoc(+@var{List},?@var{Assoc})
|
||||
@findex list_to_assoc/2
|
||||
@syindex list_to_assoc/2
|
||||
@ -6914,6 +6965,13 @@ Given a list @var{List} such that each element of @var{List} is of the
|
||||
form @var{Key-Val}, and all the @var{Keys} are unique, @var{Assoc} is
|
||||
the corresponding association list.
|
||||
|
||||
@item map_assoc(+@var{Pred},+@var{Assoc})
|
||||
@findex map_assoc/2
|
||||
@syindex map_assoc/2
|
||||
@cnindex map_assoc/2
|
||||
Succeeds if the unary predicate name @var{Pred}(@var{Val}) holds for every
|
||||
element in the association list.
|
||||
|
||||
@item map_assoc(+@var{Pred},+@var{Assoc},?@var{New})
|
||||
@findex map_assoc/3
|
||||
@syindex map_assoc/3
|
||||
@ -6923,6 +6981,22 @@ Given the binary predicate name @var{Pred} and the association list
|
||||
and such that if @var{Key-Val} is in @var{Assoc}, and @var{Key-Ans} is in
|
||||
@var{New}, then @var{Pred}(@var{Val},@var{Ans}) holds.
|
||||
|
||||
@item max_assoc(+@var{Assoc},-@var{Key},?@var{Value})
|
||||
@findex max_assoc/3
|
||||
@syindex max_assoc/3
|
||||
@cnindex max_assoc/3
|
||||
Given the association list
|
||||
@var{Assoc}, @var{Key} in the largest key in the list, and @var{Value}
|
||||
the associated value.
|
||||
|
||||
@item min_assoc(+@var{Assoc},-@var{Key},?@var{Value})
|
||||
@findex min_assoc/3
|
||||
@syindex min_assoc/3
|
||||
@cnindex min_assoc/3
|
||||
Given the association list
|
||||
@var{Assoc}, @var{Key} in the smallest key in the list, and @var{Value}
|
||||
the associated value.
|
||||
|
||||
@item ord_list_to_assoc(+@var{List},?@var{Assoc})
|
||||
@findex ord_list_to_assoc/2
|
||||
@syindex ord_list_to_assoc/2
|
||||
@ -7580,41 +7654,179 @@ Leiserson, Rivest and Stein. The library includes routines to insert,
|
||||
lookup and delete elements in the tree.
|
||||
|
||||
@table @code
|
||||
@item insert(+@var{T0},+@var{Key},?@var{Value},+@var{TF})
|
||||
@findex insert/4
|
||||
@snindex insert/4
|
||||
@cnindex insert/4
|
||||
@item rb_new(?@var{T})
|
||||
@findex rb_new/1
|
||||
@snindex rb_new/1
|
||||
@cnindex rb_new/1
|
||||
Create a new tree.
|
||||
|
||||
@item rb_empty(?@var{T})
|
||||
@findex rb_empty/1
|
||||
@snindex rb_empty/1
|
||||
@cnindex rb_empty/1
|
||||
Succeeds if tree @var{T} is empty.
|
||||
|
||||
@item is_rbtree(+@var{T})
|
||||
@findex is_rbtree/1
|
||||
@snindex is_rbtree/1
|
||||
@cnindex is_rbtree/1
|
||||
Check whether @var{T} is a valid red-black tree.
|
||||
|
||||
@item rb_insert(+@var{T0},+@var{Key},?@var{Value},+@var{TF})
|
||||
@findex rb_insert/4
|
||||
@snindex rb_insert/4
|
||||
@cnindex rb_insert/4
|
||||
Add an element with key @var{Key} and @var{Value} to the tree
|
||||
@var{T0} creating a new AVL tree @var{TF}. Duplicated elements are not
|
||||
@var{T0} creating a new red-black tree @var{TF}. Duplicated elements are not
|
||||
allowed.
|
||||
|
||||
@item lookup(+@var{Key},-@var{Value},+@var{T})
|
||||
@findex lookup/3
|
||||
@snindex lookup/3
|
||||
@cnindex lookup/3
|
||||
Lookup an element with key @var{Key} in the red-black tree
|
||||
@var{T}, returning the value @var{Value}.
|
||||
@item rb_lookup(+@var{Key},-@var{Value},+@var{T})
|
||||
@findex rb_lookup/3
|
||||
@snindex rb_lookup/3
|
||||
@cnindex rb_lookup/3
|
||||
Backtrack through all elements with key @var{Key} in the red-black tree
|
||||
@var{T}, returning for each the value @var{Value}.
|
||||
|
||||
@item lookupall(+@var{Key},-@var{Value},+@var{T})
|
||||
@findex lookupall/3
|
||||
@snindex lookupall/3
|
||||
@cnindex lookupall/3
|
||||
@item rb_lookupall(+@var{Key},-@var{Value},+@var{T})
|
||||
@findex rb_lookupall/3
|
||||
@snindex rb_lookupall/3
|
||||
@cnindex rb_lookupall/3
|
||||
Lookup all elements with key @var{Key} in the red-black tree
|
||||
@var{T}, returning the value @var{Value}.
|
||||
|
||||
@item new(?@var{T})
|
||||
@findex new/1
|
||||
@snindex new/1
|
||||
@cnindex new/1
|
||||
Create a new tree.
|
||||
|
||||
@item delete(+@var{T},+@var{Key},-@var{TN})
|
||||
@findex delete/3
|
||||
@snindex delete/3
|
||||
@cnindex delete/3
|
||||
@item rb_delete(+@var{T},+@var{Key},-@var{TN})
|
||||
@findex rb_delete/3
|
||||
@snindex rb_delete/3
|
||||
@cnindex rb_delete/3
|
||||
Delete element with key @var{Key} from the tree @var{T}, returning a new
|
||||
tree @var{TN}.
|
||||
|
||||
@item rb_delete(+@var{T},+@var{Key},-@var{Val},-@var{TN})
|
||||
@findex rb_delete/4
|
||||
@snindex rb_delete/4
|
||||
@cnindex rb_delete/4
|
||||
Delete element with key @var{Key} from the tree @var{T}, returning the
|
||||
value @var{Val} associated with the key and a new tree @var{TN}.
|
||||
|
||||
@item rb_del_min(+@var{T},-@var{Key},-@var{Val},-@var{TN})
|
||||
@findex rb_del_min/4
|
||||
@snindex rb_del_min/4
|
||||
@cnindex rb_del_min/4
|
||||
Delete the least element from the tree @var{T}, returning the key
|
||||
@var{Key}, the value @var{Val} associated with the key and a new tree
|
||||
@var{TN}.
|
||||
|
||||
@item rb_del_max(+@var{T},-@var{Key},-@var{Val},-@var{TN})
|
||||
@findex rb_del_max/4
|
||||
@snindex rb_del_max/4
|
||||
@cnindex rb_del_max/4
|
||||
Delete the largest element from the tree @var{T}, returning the key
|
||||
@var{Key}, the value @var{Val} associated with the key and a new tree
|
||||
@var{TN}.
|
||||
|
||||
@item rb_update(+@var{T},+@var{Key},+@var{NewVal},-@var{TN})
|
||||
@findex rb_update/4
|
||||
@snindex rb_update/4
|
||||
@cnindex rb_update/4
|
||||
Tree @var{TN} is tree @var{T}, but with value for @var{Key} associated
|
||||
with @var{NewVal}. Fails if it cannot find @var{Key} in @var{T}.
|
||||
|
||||
@item rb_apply(+@var{T},+@var{Key},+@var{G},-@var{TN})
|
||||
@findex rb_apply/4
|
||||
@snindex rb_apply/4
|
||||
@cnindex rb_apply/4
|
||||
If the value associated with key @var{Key} is @var{Val0} in @var{T}, and
|
||||
if @var{call(G,Val0,ValF)} holds, then @var{TN} differs from @var{T}
|
||||
only in that @var{Key} is associated with value @var{ValF} in tree
|
||||
@var{TN}. Fails if it cannot find @var{Key} in @var{T}, or if
|
||||
@var{call(G,Val0,ValF)} is not satisfiable.
|
||||
|
||||
@item rb_visit(+@var{T},-@var{Pairs})
|
||||
@findex rb_visit/2
|
||||
@snindex rb_visit/2
|
||||
@cnindex rb_visit/2
|
||||
@var{Pairs} is an infix visit of tree @var{T}, where each element of
|
||||
@var{Pairs} is of the form @var{K-Val}.
|
||||
|
||||
@item rb_size(+@var{T},-@var{Size})
|
||||
@findex rb_size/2
|
||||
@snindex rb_size/2
|
||||
@cnindex rb_size/2
|
||||
@var{Size} is the number of elements in @var{T}.
|
||||
|
||||
@item rb_keys(+@var{T},+@var{Keys})
|
||||
@findex rb_keys/2
|
||||
@snindex rb_keys/2
|
||||
@cnindex rb_keys/2
|
||||
@var{Keys} is an infix visit with all keys in tree @var{T}. Keys will be
|
||||
sorted, but may be duplicate.
|
||||
|
||||
@item rb_map(+@var{T},+@var{G},-@var{TN})
|
||||
@findex rb_map/3
|
||||
@snindex rb_map/3
|
||||
@cnindex rb_map/3
|
||||
For all nodes @var{Key} in the tree @var{T}, if the value associated with
|
||||
key @var{Key} is @var{Val0} in tree @var{T}, and if
|
||||
@var{call(G,Val0,ValF)} holds, then the value associated with @var{Key}
|
||||
in @var{TN} is @var{ValF}. Fails if or if @var{call(G,Val0,ValF)} is not
|
||||
satisfiable for all @var{Var0}.
|
||||
|
||||
@item rb_partial_map(+@var{T},+@var{Keys},+@var{G},-@var{TN})
|
||||
@findex rb_partial_map/4
|
||||
@snindex rb_partial_map/4
|
||||
@cnindex rb_partial_map/4
|
||||
For all nodes @var{Key} in @var{Keys}, if the value associated with key
|
||||
@var{Key} is @var{Val0} in tree @var{T}, and if @var{call(G,Val0,ValF)}
|
||||
holds, then the value associated with @var{Key} in @var{TN} is
|
||||
@var{ValF}. Fails if or if @var{call(G,Val0,ValF)} is not satisfiable
|
||||
for all @var{Var0}. Assumes keys are not repeated.
|
||||
|
||||
@item rb_clone(+@var{T},+@var{NT},+@var{Nodes})
|
||||
@findex rb_clone/3
|
||||
@snindex rb_clone/3
|
||||
@cnindex rb_clone/3
|
||||
``Clone'' the red-back tree into a new tree with the same keys as the
|
||||
original but with all values set to unbound values. Nodes is a list
|
||||
containing all new nodes as pairs @var{K-V}.
|
||||
|
||||
@item rb_min(+@var{T},-@var{Key},-@var{Value})
|
||||
@findex rb_min/3
|
||||
@snindex rb_min/3
|
||||
@cnindex rb_min/3
|
||||
@var{Key} is the minimum key in @var{T}, and is associated with @var{Val}.
|
||||
|
||||
@item rb_max(+@var{T},-@var{Key},-@var{Value})
|
||||
@findex rb_max/3
|
||||
@snindex rb_max/3
|
||||
@cnindex rb_max/3
|
||||
@var{Key} is the maximal key in @var{T}, and is associated with @var{Val}.
|
||||
|
||||
@item rb_next(+@var{T}, +@var{Key},-@var{Next},-@var{Value})
|
||||
@findex rb_next/4
|
||||
@snindex rb_next/4
|
||||
@cnindex rb_next/4
|
||||
@var{Next} is the next element after @var{Key} in @var{T}, and is
|
||||
associated with @var{Val}.
|
||||
|
||||
@item rb_previous(+@var{T}, +@var{Key},-@var{Previous},-@var{Value})
|
||||
@findex rb_previous/4
|
||||
@snindex rb_previous/4
|
||||
@cnindex rb_previous/4
|
||||
@var{Previous} is the previous element after @var{Key} in @var{T}, and is
|
||||
associated with @var{Val}.
|
||||
|
||||
@item list_to_rbtree(+@var{L}, -@var{T})
|
||||
@findex list_to_rbtree/2
|
||||
@snindex list_to_rbtree/2
|
||||
@cnindex list_to_rbtree/2
|
||||
@var{T} is the red-black tree corresponding to the mapping in list @var{L}.
|
||||
|
||||
@item ord_list_to_rbtree(+@var{L}, -@var{T})
|
||||
@findex list_to_rbtree/2
|
||||
@snindex list_to_rbtree/2
|
||||
@cnindex list_to_rbtree/2
|
||||
@var{T} is the red-black tree corresponding to the mapping in ordered
|
||||
list @var{L}.
|
||||
@end table
|
||||
|
||||
@node RegExp, Splay Trees, Red-Black Trees, Library
|
||||
@ -8534,11 +8746,11 @@ Is the converse operation to list_to_tree.
|
||||
|
||||
@end table
|
||||
|
||||
@node UGraphs, , Trees, Library
|
||||
@node UGraphs, DGraphs, Trees, Library
|
||||
@section Unweighted Graphs
|
||||
@cindex unweighted graphs
|
||||
|
||||
The following graph manipulation routines are based from code originally
|
||||
The following graph manipulation routines are based in code originally
|
||||
written by Richard O'Keefe. The code was then extended to be compatible
|
||||
with the SICStus Prolog ugraphs library. The routines assume directed
|
||||
graphs, undirected graphs may be implemented by using two edges. Graphs
|
||||
@ -8597,9 +8809,9 @@ L = [1,2,3,4,5]
|
||||
@end example
|
||||
|
||||
@item edges(+@var{Graph}, -@var{Edges})
|
||||
@findex vertices/2
|
||||
@syindex vertices/2
|
||||
@cnindex vertices/2
|
||||
@findex edges/2
|
||||
@syindex edges/2
|
||||
@cnindex edges/2
|
||||
Unify @var{Edges} with all edges appearing in graph
|
||||
@var{Graph}. In the next example:
|
||||
@example
|
||||
@ -8651,10 +8863,10 @@ edges @var{Edges} to the graph @var{Graph}. In the next example:
|
||||
NL = [1-[3,5,6],2-[3,4],3-[2],4-[5],5-[7],6-[],7-[],8-[]]
|
||||
@end example
|
||||
|
||||
@item sub_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||||
@findex sub_edges/3
|
||||
@syindex sub_edges/3
|
||||
@cnindex sub_edges/3
|
||||
@item del_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||||
@findex del_edges/3
|
||||
@syindex del_edges/3
|
||||
@cnindex del_edges/3
|
||||
Unify @var{NewGraph} with a new graph obtained by removing the list of
|
||||
edges @var{Edges} from the graph @var{Graph}. Notice that no vertices
|
||||
are deleted. In the next example:
|
||||
@ -8783,6 +8995,211 @@ V = [1,3,5]
|
||||
|
||||
@end table
|
||||
|
||||
@node DGraphs, UnDGraphs, UGraphs, Library
|
||||
@section Directed Graphs
|
||||
@cindex Efficient Directed Graphs
|
||||
|
||||
The following graph manipulation routines use the red-black tree library
|
||||
to try to avoid linear-time scans of the graph for all graph
|
||||
operations. Graphs are represented as a red-black tree, where the key is
|
||||
the vertex, and the associated value is a list of vertices reachable
|
||||
from that vertex through an edge (ie, a list of edges).
|
||||
|
||||
@table @code
|
||||
|
||||
@item dgraph_new(+@var{Graph})
|
||||
@findex dgraph_new/1
|
||||
@snindex dgraph_new/1
|
||||
@cnindex dgraph_new/1
|
||||
Create a new directed graph. This operation must be performed before
|
||||
trying to use the graph.
|
||||
|
||||
@item dgraph_vertices(+@var{Graph}, -@var{Vertices})
|
||||
@findex dgraph_vertices/2
|
||||
@snindex dgraph_vertices/2
|
||||
@cnindex dgraph_vertices/2
|
||||
Unify @var{Vertices} with all vertices appearing in graph
|
||||
@var{Graph}.
|
||||
|
||||
@item dgraph_edges(+@var{Graph}, -@var{Edges})
|
||||
@findex dgraph_edges/2
|
||||
@snindex dgraph_edges/2
|
||||
@cnindex dgraph_edges/2
|
||||
Unify @var{Edges} with all edges appearing in graph
|
||||
@var{Graph}.
|
||||
|
||||
@item dgraph_add_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph})
|
||||
@findex dgraph_add_vertices/3
|
||||
@snindex dgraph_add_vertices/3
|
||||
@cnindex dgraph_add_vertices/3
|
||||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||||
vertices @var{Vertices} to the graph @var{Graph}.
|
||||
|
||||
@item dgraph_del_vertices(+@var{Vertices}, +@var{Graph}, -@var{NewGraph})
|
||||
@findex dgraph_del_vertices/3
|
||||
@syindex dgraph_del_vertices/3
|
||||
@cnindex dgraph_del_vertices/3
|
||||
Unify @var{NewGraph} with a new graph obtained by deleting the list of
|
||||
vertices @var{Vertices} and all the edges that start from or go to a
|
||||
vertex in @var{Vertices} to the graph @var{Graph}.
|
||||
|
||||
@item dgraph_add_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||||
@findex dgraph_add_edges/3
|
||||
@snindex dgraph_add_edges/3
|
||||
@cnindex dgraph_add_edges/3
|
||||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||||
edges @var{Edges} to the graph @var{Graph}.
|
||||
|
||||
@item dgraph_del_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||||
@findex dgraph_del_edges/3
|
||||
@snindex dgraph_del_edges/3
|
||||
@cnindex dgraph_del_edges/3
|
||||
Unify @var{NewGraph} with a new graph obtained by removing the list of
|
||||
edges @var{Edges} from the graph @var{Graph}. Notice that no vertices
|
||||
are deleted.
|
||||
|
||||
@item dgraph_neighbors(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||||
@findex dgraph_neighbors/3
|
||||
@snindex dgraph_neighbors/3
|
||||
@cnindex dgraph_neighbors/3
|
||||
Unify @var{Vertices} with the list of neighbors of vertex @var{Vertex}
|
||||
in @var{Graph}. If the vertice is not in the graph fail.
|
||||
|
||||
@item dgraph_neighbours(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||||
@findex dgraph_neighbours/3
|
||||
@snindex dgraph_neighbours/3
|
||||
@cnindex dgraph_neighbours/3
|
||||
Unify @var{Vertices} with the list of neighbours of vertex @var{Vertex}
|
||||
in @var{Graph}.
|
||||
|
||||
@item dgraph_complement(+@var{Graph}, -@var{NewGraph})
|
||||
@findex dgraph_complement/2
|
||||
@snindex dgraph_complement/2
|
||||
@cnindex dgraph_complement/2
|
||||
Unify @var{NewGraph} with the graph complementary to @var{Graph}.
|
||||
|
||||
@item dgraph_transpose(+@var{Graph}, -@var{Transpose})
|
||||
@findex dgraph_transpose/2
|
||||
@snindex dgraph_transpose/2
|
||||
@cnindex dgraph_transpose/2
|
||||
Unify @var{NewGraph} with a new graph obtained from @var{Graph} by
|
||||
replacing all edges of the form @var{V1-V2} by edges of the form
|
||||
@var{V2-V1}.
|
||||
|
||||
@item dgraph_close(+@var{Graph1}, +@var{Graph2}, -@var{ComposedGraph})
|
||||
@findex dgraph_compose/3
|
||||
@snindex dgraph_compose/3
|
||||
@cnindex dgraph_compose/3
|
||||
Unify @var{ComposedGraph} with a new graph obtained by composing
|
||||
@var{Graph1} and @var{Graph2}, ie, @var{ComposedGraph} has an edge
|
||||
@var{V1-V2} iff there is a @var{V} such that @var{V1-V} in @var{Graph1}
|
||||
and @var{V-V2} in @var{Graph2}.
|
||||
|
||||
@item dgraph_transitive_closure(+@var{Graph}, -@var{Closure})
|
||||
@findex dgraph_transitive_closure/2
|
||||
@snindex dgraph_transitive_closure/2
|
||||
@cnindex dgraph_transitive_closure/2
|
||||
Unify @var{Closure} with the transitive closure of graph @var{Graph}.
|
||||
|
||||
@item dgraph_symmetric_closure(+@var{Graph}, -@var{Closure})
|
||||
@findex dgraph_symmetric_closure/2
|
||||
@snindex dgraph_symmetric_closure/2
|
||||
@cnindex dgraph_symmetric_closure/2
|
||||
Unify @var{Closure} with the symmetric closure of graph @var{Graph},
|
||||
that is, if @var{Closure} contains an edge @var{U-V} it must also
|
||||
contain the edge @var{V-U}.
|
||||
|
||||
@item dgraph_top_sort(+@var{Graph}, -@var{Vertices})
|
||||
@findex dgraph_top_sort/2
|
||||
@snindex dgraph_top_sort/2
|
||||
@cnindex dgraph_top_sort/2
|
||||
Unify @var{Vertices} with the topological sort of graph @var{Graph}.
|
||||
|
||||
@end table
|
||||
|
||||
@node UnDGraphs, , DGraphs, Library
|
||||
@section Undirected Graphs
|
||||
@cindex undrected graphs
|
||||
|
||||
The following graph manipulation routines use the red-black tree graph
|
||||
library to implement undirected graphs. Mostly, this is done by having
|
||||
two directed edges per undirected edge.
|
||||
|
||||
@table @code
|
||||
|
||||
@item undgraph_new(+@var{Graph})
|
||||
@findex undgraph_new/1
|
||||
@snindex undgraph_new/1
|
||||
@cnindex undgraph_new/1
|
||||
Create a new directed graph. This operation must be performed before
|
||||
trying to use the graph.
|
||||
|
||||
@item undgraph_vertices(+@var{Graph}, -@var{Vertices})
|
||||
@findex undgraph_vertices/2
|
||||
@snindex undgraph_vertices/2
|
||||
@cnindex undgraph_vertices/2
|
||||
Unify @var{Vertices} with all vertices appearing in graph
|
||||
@var{Graph}.
|
||||
|
||||
@item undgraph_edges(+@var{Graph}, -@var{Edges})
|
||||
@findex undgraph_edges/2
|
||||
@snindex undgraph_edges/2
|
||||
@cnindex undgraph_edges/2
|
||||
Unify @var{Edges} with all edges appearing in graph
|
||||
@var{Graph}.
|
||||
|
||||
@item undgraph_add_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph})
|
||||
@findex undgraph_add_vertices/3
|
||||
@snindex undgraph_add_vertices/3
|
||||
@cnindex undgraph_add_vertices/3
|
||||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||||
vertices @var{Vertices} to the graph @var{Graph}.
|
||||
|
||||
@item undgraph_del_vertices(+@var{Vertices}, +@var{Graph}, -@var{NewGraph})
|
||||
@findex undgraph_del_vertices/3
|
||||
@syindex undgraph_del_vertices/3
|
||||
@cnindex undgraph_del_vertices/3
|
||||
Unify @var{NewGraph} with a new graph obtained by deleting the list of
|
||||
vertices @var{Vertices} and all the edges that start from or go to a
|
||||
vertex in @var{Vertices} to the graph @var{Graph}.
|
||||
|
||||
@item undgraph_add_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||||
@findex undgraph_add_edges/3
|
||||
@snindex undgraph_add_edges/3
|
||||
@cnindex undgraph_add_edges/3
|
||||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||||
edges @var{Edges} to the graph @var{Graph}.
|
||||
|
||||
@item undgraph_del_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||||
@findex undgraph_del_edges/3
|
||||
@snindex undgraph_del_edges/3
|
||||
@cnindex undgraph_del_edges/3
|
||||
Unify @var{NewGraph} with a new graph obtained by removing the list of
|
||||
edges @var{Edges} from the graph @var{Graph}. Notice that no vertices
|
||||
are deleted.
|
||||
|
||||
@item undgraph_neighbors(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||||
@findex undgraph_neighbors/3
|
||||
@snindex undgraph_neighbors/3
|
||||
@cnindex undgraph_neighbors/3
|
||||
Unify @var{Vertices} with the list of neighbors of vertex @var{Vertex}
|
||||
in @var{Graph}. If the vertice is not in the graph fail.
|
||||
|
||||
@item undgraph_neighbours(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||||
@findex undgraph_neighbours/3
|
||||
@snindex undgraph_neighbours/3
|
||||
@cnindex undgraph_neighbours/3
|
||||
Unify @var{Vertices} with the list of neighbours of vertex @var{Vertex}
|
||||
in @var{Graph}.
|
||||
|
||||
@item undgraph_complement(+@var{Graph}, -@var{NewGraph})
|
||||
@findex undgraph_complement/2
|
||||
@snindex undgraph_complement/2
|
||||
@cnindex undgraph_complement/2
|
||||
Unify @var{NewGraph} with the graph complementary to @var{Graph}.
|
||||
@end table
|
||||
|
||||
|
||||
@node SWI-Prolog, Extensions, Library, Top
|
||||
@cindex SWI-Prolog
|
||||
|
||||
|
@ -30,6 +30,7 @@ PROGRAMS= $(srcdir)/apply_macros.yap \
|
||||
$(srcdir)/avl.yap \
|
||||
$(srcdir)/charsio.yap \
|
||||
$(srcdir)/cleanup.yap \
|
||||
$(srcdir)/dgraphs.yap \
|
||||
$(srcdir)/gensym.yap \
|
||||
$(srcdir)/heaps.yap \
|
||||
$(srcdir)/listing.yap \
|
||||
@ -49,6 +50,7 @@ PROGRAMS= $(srcdir)/apply_macros.yap \
|
||||
$(srcdir)/timeout.yap \
|
||||
$(srcdir)/trees.yap \
|
||||
$(srcdir)/ugraphs.yap \
|
||||
$(srcdir)/undgraphs.yap \
|
||||
$(srcdir)/ypp.yap
|
||||
|
||||
MYDDAS_PROGRAMS= $(srcdir)/MYDDAS/myddas.ypp \
|
||||
|
@ -1,129 +1,121 @@
|
||||
% This file has been included as an YAP library by Vitor Santos Costa, 1999
|
||||
|
||||
% File : ASSOC.PL
|
||||
% Author : R.A.O'Keefe
|
||||
% Updated: 9 November 1983
|
||||
% Purpose: Binary tree implementation of "association lists".
|
||||
% Red-Black Implementation of Association Lists.
|
||||
|
||||
% Note : the keys should be ground, the associated values need not be.
|
||||
% Note : the keys should be bound, the associated values need not be.
|
||||
|
||||
:- module(assoc, [
|
||||
empty_assoc/1,
|
||||
assoc_to_list/2,
|
||||
is_assoc/1,
|
||||
min_assoc/3,
|
||||
max_assoc/3,
|
||||
gen_assoc/3,
|
||||
get_assoc/3,
|
||||
get_assoc/5,
|
||||
get_next_assoc/4,
|
||||
get_prev_assoc/4,
|
||||
list_to_assoc/2,
|
||||
map_assoc/3,
|
||||
ord_list_to_assoc/2,
|
||||
map_assoc/2,
|
||||
map_assoc/3,
|
||||
put_assoc/4,
|
||||
empty_assoc/1
|
||||
del_assoc/4,
|
||||
del_min_assoc/4,
|
||||
del_max_assoc/4
|
||||
]).
|
||||
|
||||
:- meta_predicate map_assoc(:, ?, ?).
|
||||
:- meta_predicate map_assoc(:, +, -), map_assoc(:, +).
|
||||
|
||||
/*
|
||||
:- mode
|
||||
assoc_to_list(+, -),
|
||||
assoc_to_list(+, -, +),
|
||||
gen_assoc(+, ?, ?),
|
||||
get_assoc(+, +, ?),
|
||||
get_assoc(+, +, +, +, +, ?),
|
||||
list_to_assoc(+, -),
|
||||
list_to_assoc(+, +, -, +),
|
||||
map_assoc(+, +, -),
|
||||
put_assoc(+, +, +, -),
|
||||
put_assoc(+, +, +,+,+,+, +, -).
|
||||
*/
|
||||
:- use_module(library(rbtrees), [
|
||||
rb_empty/1,
|
||||
rb_visit/2,
|
||||
is_rbtree/1,
|
||||
rb_min/3,
|
||||
rb_max/3,
|
||||
rb_in/3,
|
||||
rb_lookup/3,
|
||||
rb_update/5,
|
||||
rb_next/4,
|
||||
rb_previous/4,
|
||||
list_to_rbtree/2,
|
||||
ord_list_to_rbtree/2,
|
||||
rb_map/2,
|
||||
rb_map/3,
|
||||
rb_update/4,
|
||||
rb_insert/4,
|
||||
rb_delete/4,
|
||||
rb_del_min/4,
|
||||
rb_del_max/4
|
||||
]).
|
||||
|
||||
empty_assoc(T) :-
|
||||
rb_empty(T).
|
||||
|
||||
assoc_to_list(T, L) :-
|
||||
rb_visit(T, L).
|
||||
|
||||
is_assoc(T) :-
|
||||
is_rbtree(T).
|
||||
|
||||
min_assoc(T,K,V) :-
|
||||
rb_min(T,K,V).
|
||||
|
||||
max_assoc(T,K,V) :-
|
||||
rb_max(T,K,V).
|
||||
|
||||
gen_assoc(K,T,V) :-
|
||||
rb_in(K,V,T).
|
||||
|
||||
get_assoc(K,T,V) :-
|
||||
rb_lookup(K,V,T).
|
||||
|
||||
get_assoc(K,T,V,NT,NV) :-
|
||||
rb_update(T,K,V,NV,NT).
|
||||
|
||||
get_next_assoc(K,T,KN,VN) :-
|
||||
rb_next(T,K,KN,VN).
|
||||
|
||||
get_prev_assoc(K,T,KP,VP) :-
|
||||
rb_previous(T,K,KP,VP).
|
||||
|
||||
list_to_assoc(L, T) :-
|
||||
list_to_rbtree(L, T).
|
||||
|
||||
ord_list_to_assoc(L, T) :-
|
||||
ord_list_to_rbtree(L, T).
|
||||
|
||||
map_assoc(P, T) :-
|
||||
yap_flag(typein_module, M0),
|
||||
extract_mod(P, M0, M, G),
|
||||
functor(G, Name, 1),
|
||||
rb_map(T, M:Name).
|
||||
|
||||
map_assoc(P, T, NT) :-
|
||||
yap_flag(typein_module, M0),
|
||||
extract_mod(P, M0, M, G),
|
||||
functor(G, Name, 2),
|
||||
rb_map(T, M:Name, NT).
|
||||
|
||||
|
||||
empty_assoc(t).
|
||||
extract_mod(G,_,_) :- var(G), !, fail.
|
||||
extract_mod(M:G, _, FM, FG ) :- !,
|
||||
extract_mod(G, M, FM, FG ).
|
||||
extract_mod(G, M, M, G ).
|
||||
|
||||
assoc_to_list(Assoc, List) :-
|
||||
assoc_to_list(Assoc, List, []).
|
||||
put_assoc(K, T, V, NT) :-
|
||||
rb_update(T, K, V, NT), !.
|
||||
put_assoc(K, T, V, NT) :-
|
||||
rb_insert(T, K, V, NT).
|
||||
|
||||
del_assoc(K, T, V, NT) :-
|
||||
rb_delete(T, K, V, NT).
|
||||
|
||||
assoc_to_list(t(Key,Val,L,R), List, Rest) :-
|
||||
assoc_to_list(L, List, [Key-Val|More]),
|
||||
assoc_to_list(R, More, Rest).
|
||||
assoc_to_list(t, List, List).
|
||||
del_min_assoc(T, K, V, NT) :-
|
||||
rb_del_min(T, K, V, NT).
|
||||
|
||||
del_max_assoc(T, K, V, NT) :-
|
||||
rb_del_max(T, K, V, NT).
|
||||
|
||||
|
||||
|
||||
gen_assoc(t(_,_,L,_), Key, Val) :-
|
||||
gen_assoc(L, Key, Val).
|
||||
gen_assoc(t(Key,Val,_,_), Key, Val).
|
||||
gen_assoc(t(_,_,_,R), Key, Val) :-
|
||||
gen_assoc(R, Key, Val).
|
||||
|
||||
|
||||
|
||||
get_assoc(Key, t(K,V,L,R), Val) :-
|
||||
compare(Rel, Key, K),
|
||||
get_assoc(Rel, Key, V, L, R, Val).
|
||||
|
||||
|
||||
get_assoc(=, _, Val, _, _, Val).
|
||||
get_assoc(<, Key, _, Tree, _, Val) :-
|
||||
get_assoc(Key, Tree, Val).
|
||||
get_assoc(>, Key, _, _, Tree, Val) :-
|
||||
get_assoc(Key, Tree, Val).
|
||||
|
||||
|
||||
get_assoc(Key, t(K,V,L,R), Val, t(K,NV,NL,NR), NVal) :-
|
||||
compare(Rel, Key, K),
|
||||
get_assoc(Rel, Key, V, L, R, Val, NV, NL, NR, NVal).
|
||||
|
||||
|
||||
get_assoc(=, _, Val, L, R, Val, NVal, L, R, NVal).
|
||||
get_assoc(<, Key, V, L, R, Val, V, NL, R, NVal) :-
|
||||
get_assoc(Key, L, Val, NL, NVal).
|
||||
get_assoc(>, Key, V, L, R, Val, V, L, NR, NVal) :-
|
||||
get_assoc(Key, R, Val, NR, NVal).
|
||||
|
||||
|
||||
|
||||
list_to_assoc(List, Assoc) :-
|
||||
list_to_assoc(List, t, Assoc).
|
||||
|
||||
list_to_assoc([], Assoc, Assoc).
|
||||
list_to_assoc([Key-Val|List], Assoc0, Assoc) :-
|
||||
put_assoc(Key, Assoc0, Val, AssocI),
|
||||
list_to_assoc(List, AssocI, Assoc).
|
||||
|
||||
ord_list_to_assoc(Keys, Assoc) :-
|
||||
list_to_assoc(Keys, Assoc).
|
||||
/*
|
||||
length(Keys,L),
|
||||
list_to_assoc(N, Keys, Assoc, []).
|
||||
|
||||
|
||||
ord_list_to_assoc(0, List, t, List).
|
||||
ord_list_to_assoc(N, List, t(Key,Val,L,R), Rest) :-
|
||||
A is (N-1)//2,
|
||||
Z is (N-1)-A,
|
||||
ord_list_to_assoc(A, List, L, [Key-Val|More]),
|
||||
ord_list_to_assoc(Z, More, R, Rest).
|
||||
*/
|
||||
|
||||
map_assoc(Pred, t(Key,Val,L0,R0), t(Key,Ans,L1,R1)) :- !,
|
||||
map_assoc(Pred, L0, L1),
|
||||
assoc_apply(Pred, [Val,Ans]),
|
||||
map_assoc(Pred, R0, R1).
|
||||
map_assoc(_, t, t).
|
||||
|
||||
assoc_apply(Pred,Args) :-
|
||||
G =.. [Pred,Args],
|
||||
call(G), !.
|
||||
|
||||
put_assoc(Key, t(K,V,L,R), Val, New) :-
|
||||
compare(Rel, Key, K),
|
||||
put_assoc(Rel, Key, K, V, L, R, Val, New).
|
||||
put_assoc(Key, t, Val, t(Key,Val,t,t)).
|
||||
|
||||
|
||||
put_assoc(=, Key, _, _, L, R, Val, t(Key,Val,L,R)).
|
||||
put_assoc(<, Key, K, V, L, R, Val, t(K,V,Tree,R)) :-
|
||||
put_assoc(Key, L, Val, Tree).
|
||||
put_assoc(>, Key, K, V, L, R, Val, t(K,V,L,Tree)) :-
|
||||
put_assoc(Key, R, Val, Tree).
|
||||
|
||||
|
330
library/dgraphs.yap
Normal file
330
library/dgraphs.yap
Normal file
@ -0,0 +1,330 @@
|
||||
% File : dgraphs.yap
|
||||
% Author : Vitor Santos Costa
|
||||
% Updated: 2006
|
||||
% Purpose: Directed Graph Processing Utilities.
|
||||
|
||||
:- module( dgraphs,
|
||||
[
|
||||
dgraph_new/1,
|
||||
dgraph_add_edge/4,
|
||||
dgraph_add_edges/3,
|
||||
dgraph_add_vertex/3,
|
||||
dgraph_add_vertices/3,
|
||||
dgraph_del_edge/4,
|
||||
dgraph_del_edges/3,
|
||||
dgraph_del_vertex/3,
|
||||
dgraph_del_vertices/3,
|
||||
dgraph_edges/2,
|
||||
dgraph_vertices/2,
|
||||
dgraph_neighbors/2,
|
||||
dgraph_neighbours/2,
|
||||
dgraph_complement/2,
|
||||
dgraph_transpose/2,
|
||||
dgraph_compose/3,
|
||||
dgraph_transitive_closure/2,
|
||||
dgraph_symmetric_closure/2,
|
||||
dgraph_top_sort/2]).
|
||||
|
||||
:- use_module(library(rbtrees),
|
||||
[rb_new/1,
|
||||
rb_empty/1,
|
||||
rb_lookup/3,
|
||||
rb_apply/4,
|
||||
rb_insert/4,
|
||||
rb_visit/2,
|
||||
rb_keys/2,
|
||||
rb_delete/3,
|
||||
rb_map/3,
|
||||
rb_clone/3,
|
||||
ord_list_to_rbtree/2]).
|
||||
|
||||
:- use_module(library(ordsets),
|
||||
[ord_insert/3,
|
||||
ord_union/3,
|
||||
ord_subtract/3,
|
||||
ord_del_element/3,
|
||||
ord_member/2]).
|
||||
|
||||
dgraph_new(Vertices) :-
|
||||
rb_new(Vertices).
|
||||
|
||||
dgraph_add_edge(V1,V2,Vs0,Vs2) :-
|
||||
dgraph_new_edge(V1,V2,Vs0,Vs1),
|
||||
dgraph_add_vertex(V2,Vs1,Vs2).
|
||||
|
||||
dgraph_add_edges(Edges, V0, VF) :-
|
||||
rb_empty(V0), !,
|
||||
sort(Edges,SortedEdges),
|
||||
all_vertices_in_edges(SortedEdges,Vertices),
|
||||
sort(Vertices,SortedVertices),
|
||||
edges2graphl(SortedVertices, SortedEdges, GraphL),
|
||||
ord_list_to_rbtree(GraphL, VF).
|
||||
dgraph_add_edges(Edges) -->
|
||||
{
|
||||
sort(Edges,SortedEdges),
|
||||
all_vertices_in_edges(SortedEdges,Vertices),
|
||||
sort(Vertices,SortedVertices)
|
||||
},
|
||||
dgraph_add_egdes(SortedVertices,SortedEdges).
|
||||
|
||||
all_vertices_in_edges([],[]).
|
||||
all_vertices_in_edges([V1-V2|Edges],[V1,V2|Vertices]) :-
|
||||
all_vertices_in_edges(Edges,Vertices).
|
||||
|
||||
edges2graphl([], [], []).
|
||||
edges2graphl([V|Vertices], [V-V1|SortedEdges], [V-[V1|Children]|GraphL]) :- !,
|
||||
get_extra_children(SortedEdges,V,Children,RemEdges),
|
||||
edges2graphl(Vertices, RemEdges, GraphL).
|
||||
edges2graphl([V|Vertices], SortedEdges, [V-[]|GraphL]) :-
|
||||
edges2graphl(Vertices, SortedEdges, GraphL).
|
||||
|
||||
|
||||
dgraph_add_egdes([],[]) --> [].
|
||||
dgraph_add_egdes([V|Vs],[V-V1|Es]) --> !,
|
||||
{ get_extra_children(Es,V,Children,REs) },
|
||||
dgraph_update_vertex(V,[V1|Children]),
|
||||
dgraph_add_egdes(Vs,REs).
|
||||
dgraph_add_egdes([V|Vs],Es) --> !,
|
||||
dgraph_update_vertex(V,[]),
|
||||
dgraph_add_egdes(Vs,Es).
|
||||
|
||||
get_extra_children([V-C|Es],V,[C|Children],REs) :- !,
|
||||
get_extra_children(Es,V,Children,REs).
|
||||
get_extra_children(Es,_,[],Es).
|
||||
|
||||
dgraph_update_vertex(V,Children, Vs0, Vs) :-
|
||||
rb_apply(Vs0, V, add_edges(Children), Vs), !.
|
||||
dgraph_update_vertex(V,Children, Vs0, Vs) :-
|
||||
rb_insert(Vs0,V,Children,Vs).
|
||||
|
||||
add_edges(E0,E1,E) :-
|
||||
ord_union(E0,E1,E).
|
||||
|
||||
dgraph_new_edge(V1,V2,Vs0,Vs) :-
|
||||
rb_apply(Vs0, V1, insert_edge(V2), Vs), !.
|
||||
dgraph_new_edge(V1,V2,Vs0,Vs) :-
|
||||
rb_insert(Vs0,V1,[V2],Vs).
|
||||
|
||||
insert_edge(V2, Children0, Children) :-
|
||||
ord_insert(Children0,V2,Children).
|
||||
|
||||
dgraph_add_vertices([]) --> [].
|
||||
dgraph_add_vertices([V|Vs]) -->
|
||||
dgraph_add_vertex(V),
|
||||
dgraph_add_vertices(Vs).
|
||||
|
||||
|
||||
dgraph_add_vertex(V,Vs0,Vs0) :-
|
||||
rb_lookup(V,_,Vs0), !.
|
||||
dgraph_add_vertex(V, Vs0, Vs) :-
|
||||
rb_insert(Vs0, V, [], Vs).
|
||||
|
||||
dgraph_edges(Vs,Edges) :-
|
||||
rb_visit(Vs,L0),
|
||||
cvt2edges(L0,Edges).
|
||||
|
||||
dgraph_vertices(Vs,Vertices) :-
|
||||
rb_keys(Vs,Vertices).
|
||||
|
||||
cvt2edges([],[]).
|
||||
cvt2edges([V-Children|L0],Edges) :-
|
||||
children2edges(Children,V,Edges,Edges0),
|
||||
cvt2edges(L0,Edges0).
|
||||
|
||||
children2edges([],_,Edges,Edges).
|
||||
children2edges([Child|L0],V,[V-Child|EdgesF],Edges0) :-
|
||||
children2edges(L0,V,EdgesF,Edges0).
|
||||
|
||||
dgraph_neighbours(V,Vertices,Children) :-
|
||||
rb_lookup(V,Children,Vertices).
|
||||
dgraph_neighbors(V,Vertices,Children) :-
|
||||
rb_lookup(V,Children,Vertices).
|
||||
|
||||
add_vertices(Graph, [], Graph).
|
||||
add_vertices(Graph, [V|Vertices], NewGraph) :-
|
||||
rb_insert(Graph, V, [], IntGraph),
|
||||
add_vertices(IntGraph, Vertices, NewGraph).
|
||||
|
||||
|
||||
dgraph_complement(Vs0,VsF) :-
|
||||
dgraph_vertices(Vs0,Vertices),
|
||||
rb_map(Vs0,complement(Vertices),VsF).
|
||||
|
||||
complement(Vs,Children,NewChildren) :-
|
||||
ord_subtract(Vs,Children,NewChildren).
|
||||
|
||||
dgraph_del_edge(V1,V2,Vs0,Vs1) :-
|
||||
rb_apply(Vs0, V1, delete_edge(V2), Vs1).
|
||||
|
||||
dgraph_del_edges(Edges) -->
|
||||
{
|
||||
sort(Edges,SortedEdges)
|
||||
},
|
||||
continue_del_edges(SortedEdges).
|
||||
|
||||
continue_del_edges([]) --> [].
|
||||
continue_del_edges([V-V1|Es]) --> !,
|
||||
{ get_extra_children(Es,V,Children,REs) },
|
||||
contract_vertex(V,[V1|Children]),
|
||||
continue_del_edges(REs).
|
||||
|
||||
contract_vertex(V,Children, Vs0, Vs) :-
|
||||
rb_apply(Vs0, V, del_edges(Children), Vs).
|
||||
|
||||
del_edges(ToRemove,E0,E) :-
|
||||
ord_subtract(E0,ToRemove,E).
|
||||
|
||||
dgraph_del_vertex(V,Vs0,Vsf) :-
|
||||
rb_delete(Vs0, V, Vs1),
|
||||
rb_map(Vs1, delete_edge(V), Vsf).
|
||||
|
||||
delete_edge(V, Edges0, Edges) :-
|
||||
ord_del_element(Edges0, V, Edges).
|
||||
|
||||
dgraph_del_vertices(Vs) -->
|
||||
{ sort(Vs,SortedVs) },
|
||||
delete_all(SortedVs),
|
||||
delete_remaining_edges(SortedVs).
|
||||
|
||||
% it would be nice to be able to delete a set of elements from an RB tree
|
||||
% but I don't how to do it yet.
|
||||
delete_all([]) --> [].
|
||||
delete_all([V|Vs],Vs0,Vsf) :-
|
||||
rb_delete(Vs0, V, Vsi),
|
||||
delete_all(Vs,Vsi,Vsf).
|
||||
|
||||
delete_remaining_edges(SortedVs,Vs0,Vsf) :-
|
||||
rb_map(Vs0, del_edges(SortedVs), Vsf).
|
||||
|
||||
dgraph_transpose(Graph, TGraph) :-
|
||||
rb_visit(Graph, Edges),
|
||||
rb_clone(Graph, TGraph, NewNodes),
|
||||
tedges(Edges,UnsortedTEdges),
|
||||
sort(UnsortedTEdges,TEdges),
|
||||
fill_nodes(NewNodes,TEdges).
|
||||
|
||||
tedges([],[]).
|
||||
tedges([V-Vs|Edges],TEdges) :-
|
||||
fill_tedges(Vs, V, TEdges, TEdges0),
|
||||
tedges(Edges,TEdges0).
|
||||
|
||||
fill_tedges([], _, TEdges, TEdges).
|
||||
fill_tedges([V1|Vs], V, [V1-V|TEdges], TEdges0) :-
|
||||
fill_tedges(Vs, V, TEdges, TEdges0).
|
||||
|
||||
|
||||
fill_nodes([],[]).
|
||||
fill_nodes([V-[Child|MoreChildren]|Nodes],[V-Child|Edges]) :- !,
|
||||
get_extra_children(Edges,V,MoreChildren,REdges),
|
||||
fill_nodes(Nodes,REdges).
|
||||
fill_nodes([_-[]|Edges],TEdges) :-
|
||||
fill_nodes(Edges,TEdges).
|
||||
|
||||
dgraph_compose(T1,T2,CT) :-
|
||||
rb_visit(T1,Nodes),
|
||||
compose(Nodes,T2,NewNodes),
|
||||
dgraph_new(CT0),
|
||||
dgraph_add_edges(NewNodes,CT0,CT).
|
||||
|
||||
compose([],_,[]).
|
||||
compose([V-Children|Nodes],T2,NewNodes) :-
|
||||
compose2(Children,V,T2,NewNodes,NewNodes0),
|
||||
compose(Nodes,T2,NewNodes0).
|
||||
|
||||
compose2([],_,_,NewNodes,NewNodes).
|
||||
compose2([C|Children],V,T2,NewNodes,NewNodes0) :-
|
||||
rb_lookup(C, GrandChildren, T2),
|
||||
compose3(GrandChildren, V, NewNodes,NewNodesI),
|
||||
compose2(Children,V,T2,NewNodesI,NewNodes0).
|
||||
|
||||
compose3([], _, NewNodes, NewNodes).
|
||||
compose3([GC|GrandChildren], V, [V-GC|NewNodes], NewNodes0) :-
|
||||
compose3(GrandChildren, V, NewNodes, NewNodes0).
|
||||
|
||||
dgraph_transitive_closure(G,Closure) :-
|
||||
dgraph_edges(G,Edges),
|
||||
continue_closure(Edges,G,Closure).
|
||||
|
||||
continue_closure([], Closure, Closure) :- !.
|
||||
continue_closure(Edges, G, Closure) :-
|
||||
transit_graph(Edges,G,NewEdges),
|
||||
dgraph_add_edges(NewEdges, G, GN),
|
||||
continue_closure(NewEdges, GN, Closure).
|
||||
|
||||
transit_graph([],_,[]).
|
||||
transit_graph([V-V1|Edges],G,NewEdges) :-
|
||||
rb_lookup(V1, GrandChildren, G),
|
||||
transit_graph2(GrandChildren, V, G, NewEdges, MoreEdges),
|
||||
transit_graph(Edges, G, MoreEdges).
|
||||
|
||||
transit_graph2([], _, _, NewEdges, NewEdges).
|
||||
transit_graph2([GC|GrandChildren], V, G, NewEdges, MoreEdges) :-
|
||||
is_edge(V,GC,G), !,
|
||||
transit_graph2(GrandChildren, V, G, NewEdges, MoreEdges).
|
||||
transit_graph2([GC|GrandChildren], V, G, [V-GC|NewEdges], MoreEdges) :-
|
||||
transit_graph2(GrandChildren, V, G, NewEdges, MoreEdges).
|
||||
|
||||
is_edge(V1,V2,G) :-
|
||||
rb_lookup(V1,Children,G),
|
||||
ord_member(Children, V2).
|
||||
|
||||
dgraph_symmetric_closure(G,S) :-
|
||||
dgraph_edges(G, Edges),
|
||||
invert_edges(Edges, InvertedEdges),
|
||||
dgraph_add_edges(InvertedEdges, G, S).
|
||||
|
||||
invert_edges([], []).
|
||||
invert_edges([V1-V2|Edges], [V2-V1|InvertedEdges]) :-
|
||||
invert_edges(Edges, InvertedEdges).
|
||||
|
||||
dgraph_top_sort(G,Q) :-
|
||||
% O(E)
|
||||
rb_visit(G, Vs),
|
||||
% O(E)
|
||||
invert_and_link(Vs, Links, UnsortedInvertedEdges, AllVs, Q),
|
||||
% O(V)
|
||||
rb_clone(G, LinkedG, Links),
|
||||
% O(Elog(E))
|
||||
sort(UnsortedInvertedEdges, InvertedEdges),
|
||||
% O(E)
|
||||
dgraph_vertices(G, AllVs),
|
||||
start_queue(AllVs, InvertedEdges, Q, RQ),
|
||||
continue_queue(Q, LinkedG, RQ).
|
||||
|
||||
invert_and_link([], [], [], [], []).
|
||||
invert_and_link([V-Vs|Edges], [V-NVs|ExtraEdges], UnsortedInvertedEdges, [V|AllVs],[_|Q]) :-
|
||||
inv_links(Vs, NVs, V, UnsortedInvertedEdges, UnsortedInvertedEdges0),
|
||||
invert_and_link(Edges, ExtraEdges, UnsortedInvertedEdges0, AllVs, Q).
|
||||
|
||||
inv_links([],[],_,UnsortedInvertedEdges,UnsortedInvertedEdges).
|
||||
inv_links([V2|Vs],[l(V2,A,B,S,E)|VLnks],V1,[V2-e(A,B,S,E)|UnsortedInvertedEdges],UnsortedInvertedEdges0) :-
|
||||
inv_links(Vs,VLnks,V1,UnsortedInvertedEdges,UnsortedInvertedEdges0).
|
||||
|
||||
dup([], []).
|
||||
dup([_|AllVs], [_|Q]) :-
|
||||
dup(AllVs, Q).
|
||||
|
||||
start_queue([], [], RQ, RQ).
|
||||
start_queue([V|AllVs], [V-e(S,B,S,E)|InvertedEdges], Q, RQ) :- !,
|
||||
link_edges(InvertedEdges, V, B, S, E, RemainingEdges),
|
||||
start_queue(AllVs, RemainingEdges, Q, RQ).
|
||||
start_queue([V|AllVs], InvertedEdges, [V|Q], RQ) :-
|
||||
start_queue(AllVs, InvertedEdges, Q, RQ).
|
||||
|
||||
link_edges([V-e(A,B,S,E)|InvertedEdges], V, A, S, E, RemEdges) :- !,
|
||||
link_edges(InvertedEdges, V, B, S, E, RemEdges).
|
||||
link_edges(RemEdges, _, A, _, A, RemEdges).
|
||||
|
||||
continue_queue([], _, []).
|
||||
continue_queue([V|Q], LinkedG, RQ) :-
|
||||
rb_lookup(V, Links, LinkedG),
|
||||
close_links(Links, RQ, RQ0),
|
||||
% not clear whether I should deleted V from LinkedG
|
||||
continue_queue(Q, LinkedG, RQ0).
|
||||
|
||||
close_links([], RQ, RQ).
|
||||
close_links([l(V,A,A,S,E)|Links], RQ, RQ0) :-
|
||||
( S == E -> RQ = [V| RQ1] ; RQ = RQ1),
|
||||
close_links(Links, RQ1, RQ0).
|
||||
|
||||
|
@ -12,17 +12,48 @@
|
||||
|
||||
|
||||
:- module(rbtrees,
|
||||
[new/1,
|
||||
lookup/3,
|
||||
lookupall/3,
|
||||
insert/4,
|
||||
delete/3]).
|
||||
[rb_new/1,
|
||||
rb_empty/1,
|
||||
rb_lookup/3,
|
||||
rb_update/4,
|
||||
rb_update/5,
|
||||
rb_apply/4,
|
||||
rb_lookupall/3,
|
||||
rb_insert/4,
|
||||
rb_delete/3,
|
||||
rb_delete/4,
|
||||
rb_visit/2,
|
||||
rb_visit/3,
|
||||
rb_keys/2,
|
||||
rb_keys/3,
|
||||
rb_map/2,
|
||||
rb_map/3,
|
||||
rb_partial_map/4,
|
||||
rb_clone/3,
|
||||
rb_min/3,
|
||||
rb_max/3,
|
||||
rb_del_min/4,
|
||||
rb_del_max/4,
|
||||
rb_next/4,
|
||||
rb_previous/4,
|
||||
list_to_rbtree/2,
|
||||
ord_list_to_rbtree/2,
|
||||
is_rbtree/1,
|
||||
rb_size/2,
|
||||
rb_in/3
|
||||
]).
|
||||
|
||||
:- meta_predicate rb_map(+,:,-), rb_apply(+,+,:,-).
|
||||
|
||||
% create an empty tree.
|
||||
new(black([],[],[],[])).
|
||||
rb_new(t(Nil,Nil)) :- Nil = black([],[],[],[]).
|
||||
|
||||
new(K,V,black(Nil,K,V,Nil)) :-
|
||||
Nil = black([],[],[],[]).
|
||||
rb_empty(t(Nil,Nil)) :- Nil = black([],[],[],[]).
|
||||
|
||||
rb_new(K,V,t(Nil,black(Nil,K,V,Nil))) :- Nil = black([],[],[],[]).
|
||||
|
||||
rb_lookup(Key, Val, t(_,Tree)) :-
|
||||
lookup(Key, Val, Tree).
|
||||
|
||||
lookup(_, _, black([],_,_,[])) :- !, fail.
|
||||
lookup(Key, Val, Tree) :-
|
||||
@ -39,6 +70,168 @@ lookup(<, K, V, Tree) :-
|
||||
lookup(=, _, V, Tree) :-
|
||||
arg(3,Tree,V).
|
||||
|
||||
rb_min(t(_,Tree), Key, Val) :-
|
||||
min(Tree, Key, Val).
|
||||
|
||||
min(red(black([],_,_,_),Key,Val,_), Key, Val) :- !.
|
||||
min(black(black([],_,_,_),Key,Val,_), Key, Val) :- !.
|
||||
min(red(Right,_,_,_), Key, Val) :-
|
||||
min(Right,Key,Val).
|
||||
min(black(Right,_,_,_), Key, Val) :-
|
||||
min(Right,Key,Val).
|
||||
|
||||
rb_max(t(_,Tree), Key, Val) :-
|
||||
max(Tree, Key, Val).
|
||||
|
||||
max(red(_,Key,Val,black([],_,_,_)), Key, Val) :- !.
|
||||
max(black(_,Key,Val,black([],_,_,_)), Key, Val) :- !.
|
||||
max(red(_,_,_,Left), Key, Val) :-
|
||||
max(Left,Key,Val).
|
||||
max(black(_,_,_,Left), Key, Val) :-
|
||||
max(Left,Key,Val).
|
||||
|
||||
rb_next(t(_,Tree), Key, Next, Val) :-
|
||||
next(Tree, Key, Next, Val, []).
|
||||
|
||||
next(black([],_,_,[]), _, _, _, _) :- !, fail.
|
||||
next(Tree, Key, Next, Val, Candidate) :-
|
||||
arg(2,Tree,KA),
|
||||
arg(3,Tree,VA),
|
||||
compare(Cmp,KA,Key),
|
||||
next(Cmp, Key, KA, VA, Next, Val, Tree, Candidate).
|
||||
|
||||
next(>, K, KA, VA, NK, V, Tree, _) :-
|
||||
arg(1,Tree,NTree),
|
||||
next(NTree,K,NK,V,KA-VA).
|
||||
next(<, K, _, _, NK, V, Tree, Candidate) :-
|
||||
arg(4,Tree,NTree),
|
||||
next(NTree,K,NK,V,Candidate).
|
||||
next(=, _, _, _, NK, Val, Tree, Candidate) :-
|
||||
arg(4,Tree,NTree),
|
||||
(
|
||||
min(NTree, NK, Val) ->
|
||||
true
|
||||
;
|
||||
Candidate = NK-Val
|
||||
).
|
||||
|
||||
rb_previous(t(_,Tree), Key, Previous, Val) :-
|
||||
previous(Tree, Key, Previous, Val, []).
|
||||
|
||||
previous(black([],_,_,[]), _, _, _, _) :- !, fail.
|
||||
previous(Tree, Key, Previous, Val, Candidate) :-
|
||||
arg(2,Tree,KA),
|
||||
arg(3,Tree,VA),
|
||||
compare(Cmp,KA,Key),
|
||||
previous(Cmp, Key, KA, VA, Previous, Val, Tree, Candidate).
|
||||
|
||||
previous(>, K, _, _, NK, V, Tree, Candidate) :-
|
||||
arg(1,Tree,NTree),
|
||||
previous(NTree,K,NK,V,Candidate).
|
||||
previous(<, K, KA, VA, NK, V, Tree, _) :-
|
||||
arg(4,Tree,NTree),
|
||||
previous(NTree,K,NK,V,KA-VA).
|
||||
previous(=, _, _, _, K, Val, Tree, Candidate) :-
|
||||
arg(1,Tree,NTree),
|
||||
(
|
||||
max(NTree, K, Val) ->
|
||||
true
|
||||
;
|
||||
Candidate = K-Val
|
||||
).
|
||||
|
||||
rb_update(t(Nil,OldTree), Key, OldVal, Val, t(Nil,NewTree)) :-
|
||||
update(OldTree, Key, OldVal, Val, NewTree).
|
||||
|
||||
rb_update(t(Nil,OldTree), Key, Val, t(Nil,NewTree)) :-
|
||||
update(OldTree, Key, _, Val, NewTree).
|
||||
|
||||
update(black(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
|
||||
Left \= [],
|
||||
compare(Cmp,Key0,Key),
|
||||
(Cmp == = ->
|
||||
OldVal = Val0,
|
||||
NewTree = black(Left,Key0,Val,Right)
|
||||
;
|
||||
Cmp == > ->
|
||||
NewTree = black(NewLeft,Key0,Val0,Right),
|
||||
update(Left, Key, OldVal, Val, NewLeft)
|
||||
;
|
||||
NewTree = black(Left,Key0,Val0,NewRight),
|
||||
update(Right, Key, OldVal, Val, NewRight)
|
||||
).
|
||||
update(red(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
|
||||
compare(Cmp,Key0,Key),
|
||||
(Cmp == = ->
|
||||
OldVal = Val0,
|
||||
NewTree = red(Left,Key0,Val,Right)
|
||||
;
|
||||
Cmp == > ->
|
||||
NewTree = red(NewLeft,Key0,Val0,Right),
|
||||
update(Left, Key, OldVal, Val, NewLeft)
|
||||
;
|
||||
NewTree = red(Left,Key0,Val0,NewRight),
|
||||
update(Right, Key, OldVal, Val, NewRight)
|
||||
).
|
||||
|
||||
rb_apply(t(Nil,OldTree), Key, Goal, t(Nil,NewTree)) :-
|
||||
apply(OldTree, Key, Goal, NewTree).
|
||||
|
||||
%apply(black([],_,_,[]), _, _, _) :- !, fail.
|
||||
apply(black(Left,Key0,Val0,Right), Key, Goal, black(NewLeft,Key0,Val,NewRight)) :-
|
||||
Left \= [],
|
||||
compare(Cmp,Key0,Key),
|
||||
(Cmp == (=) ->
|
||||
NewLeft = Left,
|
||||
NewRight = Right,
|
||||
call(Goal,Val0,Val)
|
||||
;
|
||||
Cmp == (>) ->
|
||||
NewRight = Right,
|
||||
apply(Left, Key, Goal, NewLeft)
|
||||
;
|
||||
NewLeft = Left,
|
||||
apply(Right, Key, Goal, NewRight)
|
||||
).
|
||||
apply(red(Left,Key0,Val0,Right), Key, Goal, red(NewLeft,Key0,Val,NewRight)) :-
|
||||
compare(Cmp,Key0,Key),
|
||||
(Cmp == (=) ->
|
||||
NewLeft = Left,
|
||||
NewRight = Right,
|
||||
call(Goal,Val0,Val)
|
||||
;
|
||||
Cmp == (>) ->
|
||||
NewRight = Right,
|
||||
apply(Left, Key, Goal, NewLeft)
|
||||
;
|
||||
NewLeft = Left,
|
||||
apply(Right, Key, Goal, NewRight)
|
||||
).
|
||||
|
||||
rb_in(Key, Val, t(_,T)) :-
|
||||
var(Key), !,
|
||||
enum(Key, Val, T).
|
||||
rb_in(Key, Val, t(_,T)) :-
|
||||
lookup(Key, Val, T).
|
||||
|
||||
|
||||
enum(Key, Val, black(L,K,V,R)) :-
|
||||
L \= [],
|
||||
enum_cases(Key, Val, L, K, V, R).
|
||||
enum(Key, Val, red(L,K,V,R)) :-
|
||||
enum_cases(Key, Val, L, K, V, R).
|
||||
|
||||
enum_cases(Key, Val, L, _, _, _) :-
|
||||
enum(Key, Val, L).
|
||||
enum_cases(Key, Val, _, Key, Val, _).
|
||||
enum_cases(Key, Val, _, _, _, R) :-
|
||||
enum(Key, Val, R).
|
||||
|
||||
|
||||
rb_lookupall(Key, Val, t(_,Tree)) :-
|
||||
lookupall(Key, Val, Tree).
|
||||
|
||||
|
||||
lookupall(_, _, black([],_,_,[])) :- !, fail.
|
||||
lookupall(Key, Val, Tree) :-
|
||||
arg(2,Tree,KA),
|
||||
@ -47,7 +240,7 @@ lookupall(Key, Val, Tree) :-
|
||||
|
||||
lookupall(>, K, V, Tree) :-
|
||||
arg(4,Tree,NTree),
|
||||
lookupall(K, V, NTree).
|
||||
rb_lookupall(K, V, NTree).
|
||||
lookupall(=, _, V, Tree) :-
|
||||
arg(3,Tree,V).
|
||||
lookupall(=, K, V, Tree) :-
|
||||
@ -62,8 +255,12 @@ lookupall(<, K, V, Tree) :-
|
||||
%
|
||||
% We don't use parent nodes, so we may have to fix the root.
|
||||
%
|
||||
insert(Tree0,Key,Val,Tree) :-
|
||||
insert2(Tree0,Key,Val,TreeI,_),
|
||||
rb_insert(t(Nil,Tree0),Key,Val,t(Nil,Tree)) :-
|
||||
insert(Tree0,Key,Val,Nil,Tree).
|
||||
|
||||
|
||||
insert(Tree0,Key,Val,Nil,Tree) :-
|
||||
insert2(Tree0,Key,Val,Nil,TreeI,_),
|
||||
fix_root(TreeI,Tree).
|
||||
|
||||
%
|
||||
@ -96,22 +293,25 @@ fix_root(red(L,K,V,R),black(L,K,V,R)).
|
||||
%
|
||||
% actual insertion
|
||||
%
|
||||
insert2(black([],[],[],[]), K, V, T, Status) :- !,
|
||||
Nil = black([],[],[],[]),
|
||||
insert2(black([],[],[],[]), K, V, Nil, T, Status) :- !,
|
||||
T = red(Nil,K,V,Nil),
|
||||
Status = not_done.
|
||||
insert2(red(L,K0,V0,R), K, V, red(NL,K0,V0,R), Flag) :-
|
||||
K @< K0, !,
|
||||
insert2(L, K, V, NL, Flag).
|
||||
insert2(red(L,K0,V0,R), K, V, red(L,K0,V0,NR), Flag) :-
|
||||
insert2(R, K, V, NR, Flag).
|
||||
insert2(black(L,K0,V0,R), K, V, NT, Flag) :-
|
||||
K @< K0, !,
|
||||
insert2(L, K, V, IL, Flag0),
|
||||
fix_left(Flag0, black(IL,K0,V0,R), NT, Flag).
|
||||
insert2(black(L,K0,V0,R), K, V, NT, Flag) :-
|
||||
insert2(R, K, V, IR, Flag0),
|
||||
fix_right(Flag0, black(L,K0,V0,IR), NT, Flag).
|
||||
insert2(red(L,K0,V0,R), K, V, Nil, red(NL,K0,V0,NR), Flag) :-
|
||||
( K @< K0 ->
|
||||
NR = R,
|
||||
insert2(L, K, V, Nil, NL, Flag)
|
||||
;
|
||||
NL = L,
|
||||
insert2(R, K, V, Nil, NR, Flag)
|
||||
).
|
||||
insert2(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
||||
( K @< K0 ->
|
||||
insert2(L, K, V, Nil, IL, Flag0),
|
||||
fix_left(Flag0, black(IL,K0,V0,R), NT, Flag)
|
||||
;
|
||||
insert2(R, K, V, Nil, IR, Flag0),
|
||||
fix_right(Flag0, black(L,K0,V0,IR), NT, Flag)
|
||||
).
|
||||
|
||||
%
|
||||
% How to fix if we have inserted on the left
|
||||
@ -199,35 +399,69 @@ pretty_print(black(L,K,_,R),D) :-
|
||||
pretty_print(R,DN).
|
||||
|
||||
|
||||
delete(T, K, NT) :-
|
||||
delete(T, K, NT, _).
|
||||
rb_delete(t(Nil,T), K, t(Nil,NT)) :-
|
||||
delete(T, K, _, NT, _).
|
||||
|
||||
rb_delete(t(Nil,T), K, V, t(Nil,NT)) :-
|
||||
delete(T, K, V, NT, _).
|
||||
|
||||
%
|
||||
% I am afraid our representation is not as nice for delete
|
||||
%
|
||||
delete(red(L,K0,V0,R), K, NT, Flag) :-
|
||||
delete(red(L,K0,V0,R), K, V, NT, Flag) :-
|
||||
K @< K0, !,
|
||||
delete(L, K, NL, Flag0),
|
||||
delete(L, K, V, NL, Flag0),
|
||||
fixup_left(Flag0,red(NL,K0,V0,R),NT, Flag).
|
||||
delete(red(L,K0,V0,R), K, NT, Flag) :-
|
||||
delete(red(L,K0,V0,R), K, V, NT, Flag) :-
|
||||
K @> K0, !,
|
||||
delete(R, K, NR, Flag0),
|
||||
delete(R, K, V, NR, Flag0),
|
||||
fixup_right(Flag0,red(L,K0,V0,NR),NT, Flag).
|
||||
delete(red(L,_,_,R), _, OUT, Flag) :-
|
||||
delete(red(L,_,V,R), _, V, OUT, Flag) :-
|
||||
% K == K0,
|
||||
delete_red_node(L,R,OUT,Flag).
|
||||
delete(black(L,K0,V0,R), K, NT, Flag) :-
|
||||
delete(black(L,K0,V0,R), K, V, NT, Flag) :-
|
||||
K @< K0, !,
|
||||
delete(L, K, NL, Flag0),
|
||||
delete(L, K, V, NL, Flag0),
|
||||
fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
|
||||
delete(black(L,K0,V0,R), K, NT, Flag) :-
|
||||
delete(black(L,K0,V0,R), K, V, NT, Flag) :-
|
||||
K @> K0, !,
|
||||
delete(R, K, NR, Flag0),
|
||||
delete(R, K, V, NR, Flag0),
|
||||
fixup_right(Flag0,black(L,K0,V0,NR),NT, Flag).
|
||||
delete(black(L,_,_,R), _, OUT, Flag) :-
|
||||
delete(black(L,_,V,R), _, V, OUT, Flag) :-
|
||||
% K == K0,
|
||||
delete_black_node(L,R,OUT,Flag).
|
||||
|
||||
rb_del_min(t(Nil,T), K, Val, t(Nil,NT)) :-
|
||||
del_min(T, K, Val, Nil, NT, _).
|
||||
|
||||
del_min(red(black([],_,_,_),K,V,R), K, V, Nil, OUT, Flag) :- !,
|
||||
delete_red_node(Nil,R,OUT,Flag).
|
||||
del_min(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
||||
del_min(L, K, V, Nil, NL, Flag0),
|
||||
fixup_left(Flag0,red(NL,K0,V0,R), NT, Flag).
|
||||
del_min(black(black([],_,_,_),K,V,R), K, V, Nil, OUT, Flag) :- !,
|
||||
delete_black_node(Nil,R,OUT,Flag).
|
||||
del_min(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
||||
del_min(L, K, V, Nil, NL, Flag0),
|
||||
fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
|
||||
|
||||
|
||||
rb_del_max(t(Nil,T), K, Val, t(Nil,NT)) :-
|
||||
del_max(T, K, Val, Nil, NT, _).
|
||||
|
||||
del_max(red(L,K,V,black([],_,_,_)), K, V, Nil, OUT, Flag) :- !,
|
||||
delete_red_node(L,Nil,OUT,Flag).
|
||||
del_max(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
||||
del_max(R, K, V, Nil, NR, Flag0),
|
||||
fixup_right(Flag0,red(L,K0,V0,NR),NT, Flag).
|
||||
del_max(black(L,K,V,black([],_,_,_)), K, V, Nil, OUT, Flag) :- !,
|
||||
delete_black_node(L,Nil,OUT,Flag).
|
||||
del_max(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
||||
del_max(R, K, V, Nil, NR, Flag0),
|
||||
fixup_right(Flag0,black(L,K0,V0,NR), NT, Flag).
|
||||
|
||||
|
||||
|
||||
delete_red_node(L,L,L,done) :- !.
|
||||
delete_red_node(black([],[],[],[]),R,R,done) :- !.
|
||||
delete_red_node(L,black([],[],[],[]),L,done) :- !.
|
||||
@ -340,6 +574,171 @@ fixup3(black(black(red(Fi,KE,VE,Ep),KD,VD,C),KB,VB,black(Be,KA,VA,Al)),
|
||||
black(black(Fi,KE,VE,Ep),KD,VD,black(C,KB,VB,black(Be,KA,VA,Al))),
|
||||
done).
|
||||
|
||||
|
||||
%
|
||||
% whole list
|
||||
%
|
||||
rb_visit(t(_,T),Lf) :-
|
||||
visit(T,[],Lf).
|
||||
|
||||
rb_visit(t(_,T),L0,Lf) :-
|
||||
visit(T,L0,Lf).
|
||||
|
||||
visit(black([],_,_,_),L,L) :- !.
|
||||
visit(red(L,K,V,R),L0,Lf) :-
|
||||
visit(L,[K-V|L1],Lf),
|
||||
visit(R,L0,L1).
|
||||
visit(black(L,K,V,R),L0,Lf) :-
|
||||
visit(L,[K-V|L1],Lf),
|
||||
visit(R,L0,L1).
|
||||
|
||||
rb_map(t(Nil,Tree),Goal,t(Nil,NewTree)) :-
|
||||
map(Tree,Goal,NewTree).
|
||||
|
||||
|
||||
map(black([],[],[],[]),_,black([],[],[],[])) :- !.
|
||||
map(red(L,K,V,R),Goal,red(NL,K,NV,NR)) :-
|
||||
call(Goal,V,NV), !,
|
||||
map(L,Goal,NL),
|
||||
map(R,Goal,NR).
|
||||
map(black(L,K,V,R),Goal,black(NL,K,NV,NR)) :-
|
||||
call(Goal,V,NV), !,
|
||||
map(L,Goal,NL),
|
||||
map(R,Goal,NR).
|
||||
|
||||
rb_map(t(_,Tree),Goal) :-
|
||||
map(Tree,Goal).
|
||||
|
||||
|
||||
map(black([],[],[],[]),_) :- !.
|
||||
map(red(L,_,V,R),Goal) :-
|
||||
call(Goal,V), !,
|
||||
map(L,Goal),
|
||||
map(R,Goal).
|
||||
map(black(L,_,V,R),Goal) :-
|
||||
call(Goal,V), !,
|
||||
map(L,Goal),
|
||||
map(R,Goal).
|
||||
|
||||
rb_clone(t(Nil,T),t(Nil,NT),Ns) :-
|
||||
clone(T,NT,Ns,[]).
|
||||
|
||||
rb_clone(t(Nil,T),t(Nil,NT),Ns,Ns0) :-
|
||||
clone(T,NT,Ns,Ns0).
|
||||
|
||||
clone(black([],[],[],[]),black([],[],[],[]),Ns,Ns) :- !.
|
||||
clone(red(L,K,_,R),red(NL,K,NV,NR),NsF,Ns0) :-
|
||||
clone(L,NL,NsF,[K-NV|Ns1]),
|
||||
clone(R,NR,Ns1,Ns0).
|
||||
clone(black(L,K,_,R),black(NL,K,NV,NR),NsF,Ns0) :-
|
||||
clone(L,NL,NsF,[K-NV|Ns1]),
|
||||
clone(R,NR,Ns1,Ns0).
|
||||
|
||||
rb_partial_map(t(Nil,T0), Map, Goal, t(Nil,TF)) :-
|
||||
partial_map(T0, Map, [], Goal, TF).
|
||||
|
||||
rb_partial_map(t(Nil,T0), Map, Map0, Goal, t(Nil,TF)) :-
|
||||
rb_partial_map(T0, Map, Map0, Goal, TF).
|
||||
|
||||
partial_map(T,[],[],_,T) :- !.
|
||||
partial_map(black([],[],[],[]),Map,Map,_,black([],[],[],[])) :- !.
|
||||
partial_map(red(L,K,V,R),Map,MapF,Goal,red(NL,K,NV,NR)) :-
|
||||
partial_map(L,Map,MapI,Goal,NL),
|
||||
(
|
||||
MapI == [] ->
|
||||
NR = R, NV = V
|
||||
;
|
||||
MapI = [K1|MapR],
|
||||
(
|
||||
K == K1 ->
|
||||
once(call(Goal,V,NV)),
|
||||
Map2 = MapR
|
||||
;
|
||||
Map2 = [K1|MapR], NV = V
|
||||
)
|
||||
),
|
||||
partial_map(R,Map2,MapF,Goal,NR).
|
||||
partial_map(black(L,K,V,R),Map,MapF,Goal,black(NL,K,NV,NR)) :-
|
||||
partial_map(L,Map,MapI,Goal,NL),
|
||||
(
|
||||
MapI == [] ->
|
||||
NR = R, NV = V
|
||||
;
|
||||
MapI = [K1|MapR],
|
||||
(
|
||||
K == K1 ->
|
||||
once(call(Goal,V,NV)),
|
||||
Map2 = MapR
|
||||
;
|
||||
Map2 = [K1|MapR], NV = V
|
||||
)
|
||||
),
|
||||
partial_map(R,Goal,Map2,MapF,NR).
|
||||
|
||||
|
||||
%
|
||||
% whole keys
|
||||
%
|
||||
rb_keys(t(_,T),Lf) :-
|
||||
keys(T,[],Lf).
|
||||
|
||||
rb_keys(t(_,T),L0,Lf) :-
|
||||
keys(T,L0,Lf).
|
||||
|
||||
keys(black([],[],[],[]),L,L) :- !.
|
||||
keys(red(L,K,_,R),L0,Lf) :-
|
||||
keys(L,[K|L1],Lf),
|
||||
keys(R,L0,L1).
|
||||
keys(black(L,K,_,R),L0,Lf) :-
|
||||
keys(L,[K|L1],Lf),
|
||||
keys(R,L0,L1).
|
||||
|
||||
list_to_rbtree(List,t(Nil,Tree)) :-
|
||||
Nil = black([], [], [], []),
|
||||
sort(List,Sorted),
|
||||
Ar =.. [seq|Sorted],
|
||||
functor(Ar,_,L),
|
||||
construct_rbtree(1, L, Ar, black, Nil, Tree).
|
||||
|
||||
ord_list_to_rbtree(List,t(Nil,Tree)) :-
|
||||
Nil = black([], [], [], []),
|
||||
Ar =.. [seq|List],
|
||||
functor(Ar,_,L),
|
||||
construct_rbtree(1, L, Ar, black, Nil, Tree).
|
||||
|
||||
construct_rbtree(L, M, _, _, Nil, Nil) :- M < L, !.
|
||||
construct_rbtree(L, L, Ar, Color, Nil, Node) :- !,
|
||||
arg(L, Ar, K-Val),
|
||||
build_node(Color, Nil, K, Val, Nil, Node, _).
|
||||
construct_rbtree(I0, Max, Ar, Color, Nil, Node) :-
|
||||
I is (I0+Max)//2,
|
||||
arg(I, Ar, K-Val),
|
||||
build_node(Color, Left, K, Val, Right, Node, NewColor),
|
||||
I1 is I-1,
|
||||
construct_rbtree(I0, I1, Ar, NewColor, Nil, Left),
|
||||
I2 is I+1,
|
||||
construct_rbtree(I2, Max, Ar, NewColor, Nil, Right).
|
||||
|
||||
build_node(black, Left, K, Val, Right, black(Left, K, Val, Right), red).
|
||||
build_node(red, Left, K, Val, Right, red(Left, K, Val, Right), black).
|
||||
|
||||
rb_size(t(_,T),Size) :-
|
||||
size(T,0,Size).
|
||||
|
||||
size(black([],_,_,_),Sz,Sz) :- !.
|
||||
size(red(L,_,_,R),Sz0,Szf) :-
|
||||
Sz1 is Sz0+1,
|
||||
size(L,Sz1,Sz2),
|
||||
size(R,Sz2,Szf).
|
||||
size(black(L,_,_,R),Sz0,Szf) :-
|
||||
Sz1 is Sz0+1,
|
||||
size(L,Sz1,Sz2),
|
||||
size(R,Sz2,Szf).
|
||||
|
||||
is_rbtree(t(Nil,Nil)) :- !.
|
||||
is_rbtree(t(_,T)) :-
|
||||
catch(rbtree1(T), msg(_,_), fail).
|
||||
|
||||
%
|
||||
% This code checks if a tree is ordered and a rbtree
|
||||
%
|
||||
|
133
library/undgraphs.yap
Normal file
133
library/undgraphs.yap
Normal file
@ -0,0 +1,133 @@
|
||||
% File : dgraphs.yap
|
||||
% Author : Vitor Santos Costa
|
||||
% Updated: 2006
|
||||
% Purpose: Directed Graph Processing Utilities.
|
||||
|
||||
:- module( undgraphs,
|
||||
[
|
||||
undgraph_new/1,
|
||||
undgraph_add_edge/4,
|
||||
undgraph_add_edges/3,
|
||||
undgraph_add_vertex/3,
|
||||
undgraph_add_vertices/3,
|
||||
undgraph_del_edge/4,
|
||||
undgraph_del_edges/3,
|
||||
undgraph_del_vertex/3,
|
||||
undgraph_del_vertices/3,
|
||||
undgraph_edges/2,
|
||||
undgraph_vertices/2,
|
||||
undgraph_neighbors/2,
|
||||
undgraph_neighbours/2,
|
||||
undgraph_complement/2]).
|
||||
|
||||
:- use_module( library(dgraphs),
|
||||
[
|
||||
dgraph_new/1,
|
||||
dgraph_add_edge/4,
|
||||
dgraph_add_edges/3,
|
||||
dgraph_add_vertex/3,
|
||||
dgraph_add_vertices/3,
|
||||
dgraph_del_edge/4,
|
||||
dgraph_del_edges/3,
|
||||
dgraph_del_vertex/3,
|
||||
dgraph_del_vertices/3,
|
||||
dgraph_edges/2,
|
||||
dgraph_vertices/2,
|
||||
dgraph_neighbors/2,
|
||||
dgraph_neighbours/2,
|
||||
dgraph_complement/2]).
|
||||
|
||||
:- use_module(library(ordsets),
|
||||
[ ord_del_element/3,
|
||||
ord_union/3,
|
||||
ord_subtract/3]).
|
||||
|
||||
:- use_module(library(rbtrees),
|
||||
[ rb_delete/4]).
|
||||
|
||||
undgraph_new(Vertices) :-
|
||||
dgraph_new(Vertices).
|
||||
|
||||
undgraph_add_edge(V1,V2,Vs0,Vs2) :-
|
||||
dgraphs:dgraph_new_edge(V1,V2,Vs0,Vs1),
|
||||
dgraphs:dgraph_new_edge(V2,V1,Vs1,Vs2).
|
||||
|
||||
undgraph_add_edges(Edges) -->
|
||||
{ dup_edges(Edges, DupEdges) },
|
||||
dgraph_add_edges(Edges).
|
||||
|
||||
dup_edges([],[]).
|
||||
dup_edges([E1-E2|Edges], [E1-E2,E2-E1|DupEdges]) :-
|
||||
dup_edges(Edges, DupEdges).
|
||||
|
||||
undgraph_add_vertices([]) --> [].
|
||||
undgraph_add_vertices([V|Vs]) -->
|
||||
dgraph_add_vertex(V),
|
||||
undgraph_add_vertices(Vs).
|
||||
|
||||
undgraph_add_vertex(V) -->
|
||||
dgraph_add_vertex(V).
|
||||
|
||||
undgraph_edges(Vs,Edges) :-
|
||||
dgraph_edges(Vs,DupEdges),
|
||||
remove_dups(DupEdges,Edges).
|
||||
|
||||
remove_dups([],[]).
|
||||
remove_dups([V1-V2|DupEdges],NEdges) :- V1 @< V2, !,
|
||||
NEdges = [V1-V2|Edges],
|
||||
remove_dups(DupEdges,Edges).
|
||||
remove_dups([_|DupEdges],Edges) :-
|
||||
remove_dups(DupEdges,Edges).
|
||||
|
||||
undgraph_vertices(Vs,Vertices) :-
|
||||
dgraph_vertices(Vs,Vertices).
|
||||
|
||||
undgraph_neighbours(V,Vertices,Children) :-
|
||||
dgraph_neighbours(V,Vertices,Children0),
|
||||
ord_del_element(V,Children0,Children).
|
||||
undgraph_neighbors(V,Vertices,Children) :-
|
||||
dgraph_neighbors(V,Vertices,Children0),
|
||||
ord_del_element(V,Children0,Children).
|
||||
|
||||
undgraph_complement(Vs0,VsF) :-
|
||||
dgraph_complement(Vs0,VsF).
|
||||
|
||||
undgraph_del_edge(V1,V2,Vs0,VsF) :-
|
||||
dgraph_del_edge(V1,V2,Vs0,Vs1),
|
||||
dgraph_del_edge(V2,V1,Vs1,VsF).
|
||||
|
||||
undgraph_del_edges(Edges) -->
|
||||
{
|
||||
dup_edges(Edges,DupEdges)
|
||||
},
|
||||
dgraph_del_edges(DupEdges).
|
||||
|
||||
undgraph_del_vertex(V, Vs0, Vsf) :-
|
||||
rb_delete(Vs0, V, BackEdges, Vsi),
|
||||
ord_del_element(BackEdges,V,RealBackEdges),
|
||||
rb_partial_map(Vsi, RealBackEdges, del_edge(V), Vsf).
|
||||
|
||||
undgraph_del_vertices(Vs) -->
|
||||
{ sort(Vs,SortedVs) },
|
||||
delete_all(SortedVs, [], BackEdges),
|
||||
{ ord_subtract(BackEdges, SortedVs, TrueBackEdges) },
|
||||
delete_remaining_edges(Vs, TrueBackEdges, SortedVs).
|
||||
|
||||
% it would be nice to be able to delete a set of elements from an RB tree
|
||||
% but I don't how to do it yet.
|
||||
delete_all([], BackEdges, BackEdges) --> [].
|
||||
delete_all([V|Vs], BackEdges0, BackEdgesF, Vs0,Vsf) :-
|
||||
rb_delete(Vs0, V, NewEdges, Vsi),
|
||||
ord_union(NewEdges,BackEdges0,BackEdgesI),
|
||||
delete_all(Vs, BackEdgesI ,BackEdgesF, Vsi,Vsf).
|
||||
|
||||
delete_remaining_edges(SortedVs, TrueBackEdges, Vs0,Vsf) :-
|
||||
rb_partial_map(Vs0, TrueBackEdges, del_edges(SortedVs), Vsf).
|
||||
|
||||
del_edges(ToRemove,E0,E) :-
|
||||
ord_subtract(E0,ToRemove,E).
|
||||
|
||||
del_edges(ToRemove,E0,E) :-
|
||||
ord_del_element(E0,ToRemove,E).
|
||||
|
||||
|
@ -11,8 +11,11 @@
|
||||
* File: errors.yap *
|
||||
* comments: error messages for YAP *
|
||||
* *
|
||||
* Last rev: $Date: 2006-04-05 00:16:55 $,$Author: vsc $ *
|
||||
* Last rev: $Date: 2006-04-10 19:24:52 $,$Author: vsc $ *
|
||||
* $Log: not supported by cvs2svn $
|
||||
* Revision 1.76 2006/04/05 00:16:55 vsc
|
||||
* Lots of fixes (check logfile for details
|
||||
*
|
||||
* Revision 1.75 2006/02/24 14:26:37 vsc
|
||||
* fix informational_messages
|
||||
*
|
||||
@ -859,9 +862,8 @@ print_message(Level, Mss) :-
|
||||
[Where]).
|
||||
|
||||
|
||||
'$dump_syntax_error_line'(Start,Position) :-
|
||||
Pos is Start+Position,
|
||||
format(user_error,', near line ~d:~n',[Pos]).
|
||||
'$dump_syntax_error_line'(Position,_) :-
|
||||
format(user_error,', near line ~d:~n',[Position]).
|
||||
|
||||
'$dump_syntax_error_term'(0,J,L) :- !,
|
||||
format(user_error,'~n', []),
|
||||
|
Reference in New Issue
Block a user