Migrate from Markdown to Djot
This commit is contained in:
@@ -172,7 +172,7 @@ gen_assoc_(Key, t(_,_,_,_,R), Val) :-
|
|||||||
%
|
%
|
||||||
% True if Key-Value is an association in Assoc.
|
% True if Key-Value is an association in Assoc.
|
||||||
%
|
%
|
||||||
% Throws error: type_error(assoc, Assoc) if Assoc is not an association list.
|
% Throws error: type\_error(assoc, Assoc) if Assoc is not an association list.
|
||||||
|
|
||||||
get_assoc(Key, Assoc, Val) :-
|
get_assoc(Key, Assoc, Val) :-
|
||||||
must_be(assoc, Assoc),
|
must_be(assoc, Assoc),
|
||||||
@@ -218,7 +218,7 @@ get_assoc(>, Key, V, L, R, Val, V, L, NR, NVal) :-
|
|||||||
% Create an association from a list Pairs of Key-Value pairs. List
|
% Create an association from a list Pairs of Key-Value pairs. List
|
||||||
% must not contain duplicate keys.
|
% must not contain duplicate keys.
|
||||||
%
|
%
|
||||||
% Throws error: domain_error(unique_key_pairs, List) if List contains duplicate keys
|
% Throws error: domain\_error(unique\_key\_pairs, List) if List contains duplicate keys
|
||||||
|
|
||||||
list_to_assoc(List, Assoc) :-
|
list_to_assoc(List, Assoc) :-
|
||||||
( List = [] -> Assoc = t
|
( List = [] -> Assoc = t
|
||||||
@@ -249,7 +249,7 @@ list_to_assoc(N, List, More, Depth, t(K,V,Balance,L,R)) :-
|
|||||||
% pairs. The pairs must occur in strictly ascending order of
|
% pairs. The pairs must occur in strictly ascending order of
|
||||||
% their keys.
|
% their keys.
|
||||||
%
|
%
|
||||||
% Throws error: domain_error(key_ordered_pairs, List) if pairs are not ordered.
|
% Throws error: domain\_error(key\_ordered\_pairs, List) if pairs are not ordered.
|
||||||
|
|
||||||
ord_list_to_assoc(Sorted, Assoc) :-
|
ord_list_to_assoc(Sorted, Assoc) :-
|
||||||
( Sorted = [] -> Assoc = t
|
( Sorted = [] -> Assoc = t
|
||||||
|
|||||||
@@ -105,41 +105,48 @@ goal_expansion(del_attr(Var, Module), (var(Var) -> put_atts(Var, -Access);true))
|
|||||||
Access =.. [Module,_].
|
Access =.. [Module,_].
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/**
|
||||||
Each CLP(B) variable belongs to exactly one BDD. Each CLP(B)
|
Each CLP(B) variable belongs to exactly one BDD. Each CLP(B)
|
||||||
variable gets an attribute (in module "clpb") of the form:
|
variable gets an attribute (in module "clpb") of the form:
|
||||||
|
|
||||||
|
```
|
||||||
index_root(Index,Root)
|
index_root(Index,Root)
|
||||||
|
```
|
||||||
|
|
||||||
where Index is the variable's unique integer index, and Root is the
|
where Index is the variable's unique integer index, and Root is the
|
||||||
root of the BDD that the variable belongs to.
|
root of the BDD that the variable belongs to.
|
||||||
|
|
||||||
Each CLP(B) variable also gets an attribute in module clpb_hash: an
|
Each CLP(B) variable also gets an attribute in module `clpb_hash`: an
|
||||||
association table node(LID,HID) -> Node, to keep the BDD reduced.
|
association table node(LID,HID) -> Node, to keep the BDD reduced.
|
||||||
The association table of each variable must be rebuilt on occasion
|
The association table of each variable must be rebuilt on occasion
|
||||||
to remove nodes that are no longer reachable. We rebuild the
|
to remove nodes that are no longer reachable. We rebuild the
|
||||||
association tables of involved variables after BDDs are merged to
|
association tables of involved variables after BDDs are merged to
|
||||||
build a new root. This only serves to reclaim memory: Keeping a
|
build a new root. This only serves to reclaim memory: Keeping a
|
||||||
node in a local table even when it no longer occurs in any BDD does
|
node in a local table even when it no longer occurs in any BDD does
|
||||||
not affect the solver's correctness. However, apply_shortcut/4
|
not affect the solver's correctness. However, `apply_shortcut/4`
|
||||||
relies on the invariant that every node that occurs in the relevant
|
relies on the invariant that every node that occurs in the relevant
|
||||||
BDDs is also registered in the table of its branching variable.
|
BDDs is also registered in the table of its branching variable.
|
||||||
|
|
||||||
A root is a logical variable with a single attribute ("clpb_bdd")
|
A root is a logical variable with a single attribute ("clpb\_bdd")
|
||||||
of the form:
|
of the form:
|
||||||
|
|
||||||
|
```
|
||||||
Sat-BDD
|
Sat-BDD
|
||||||
|
```
|
||||||
|
|
||||||
where Sat is the SAT formula (in original form) that corresponds to
|
where Sat is the SAT formula (in original form) that corresponds to
|
||||||
BDD. Sat is necessary to rebuild the BDD after variable aliasing,
|
BDD. Sat is necessary to rebuild the BDD after variable aliasing,
|
||||||
and to project all remaining constraints to a list of sat/1 goals.
|
and to project all remaining constraints to a list of `sat/1` goals.
|
||||||
|
|
||||||
Finally, a BDD is either:
|
Finally, a BDD is either:
|
||||||
|
|
||||||
*) The integers 0 or 1, denoting false and true, respectively, or
|
* The integers 0 or 1, denoting false and true, respectively, or
|
||||||
*) A node of the form
|
* A node of the form
|
||||||
|
|
||||||
|
```
|
||||||
node(ID, Var, Low, High, Aux)
|
node(ID, Var, Low, High, Aux)
|
||||||
|
```
|
||||||
|
|
||||||
Where ID is the node's unique integer ID, Var is the
|
Where ID is the node's unique integer ID, Var is the
|
||||||
node's branching variable, and Low and High are the
|
node's branching variable, and Low and High are the
|
||||||
node's low (Var = 0) and high (Var = 1) children. Aux
|
node's low (Var = 0) and high (Var = 1) children. Aux
|
||||||
@@ -151,7 +158,7 @@ goal_expansion(del_attr(Var, Module), (var(Var) -> put_atts(Var, -Access);true))
|
|||||||
|
|
||||||
You should think of CLP(B) as a potentially vast collection of BDDs
|
You should think of CLP(B) as a potentially vast collection of BDDs
|
||||||
that can range from small to gigantic in size, and which can merge.
|
that can range from small to gigantic in size, and which can merge.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
*/
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Type checking.
|
Type checking.
|
||||||
@@ -1108,7 +1115,7 @@ indomain(1).
|
|||||||
%
|
%
|
||||||
% Examples:
|
% Examples:
|
||||||
%
|
%
|
||||||
% ==
|
% ```
|
||||||
% ?- sat(A =< B), Vs = [A,B], sat_count(+[1|Vs], Count).
|
% ?- sat(A =< B), Vs = [A,B], sat_count(+[1|Vs], Count).
|
||||||
% Vs = [A, B],
|
% Vs = [A, B],
|
||||||
% Count = 3,
|
% Count = 3,
|
||||||
@@ -1120,7 +1127,7 @@ indomain(1).
|
|||||||
% Vs = [...],
|
% Vs = [...],
|
||||||
% CountOr = 1329227995784915872903807060280344575,
|
% CountOr = 1329227995784915872903807060280344575,
|
||||||
% CountAnd = 1.
|
% CountAnd = 1.
|
||||||
% ==
|
% ```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1248,7 +1255,7 @@ random_bindings(VNum, Node) -->
|
|||||||
% linear objective function over Boolean variables Vs with integer
|
% linear objective function over Boolean variables Vs with integer
|
||||||
% coefficients Weights. This predicate assigns 0 and 1 to the
|
% coefficients Weights. This predicate assigns 0 and 1 to the
|
||||||
% variables in Vs such that all stated constraints are satisfied, and
|
% variables in Vs such that all stated constraints are satisfied, and
|
||||||
% Maximum is the maximum of sum(Weight_i*V_i) over all admissible
|
% Maximum is the maximum of `sum(Weight_i*V_i)` over all admissible
|
||||||
% assignments. On backtracking, all admissible assignments that
|
% assignments. On backtracking, all admissible assignments that
|
||||||
% attain the optimum are generated.
|
% attain the optimum are generated.
|
||||||
%
|
%
|
||||||
@@ -1257,10 +1264,10 @@ random_bindings(VNum, Node) -->
|
|||||||
%
|
%
|
||||||
% Example:
|
% Example:
|
||||||
%
|
%
|
||||||
% ==
|
% ```
|
||||||
% ?- sat(A#B), weighted_maximum([1,2,1], [A,B,C], Maximum).
|
% ?- sat(A#B), weighted_maximum([1,2,1], [A,B,C], Maximum).
|
||||||
% A = 0, B = 1, C = 1, Maximum = 3.
|
% A = 0, B = 1, C = 1, Maximum = 3.
|
||||||
% ==
|
% ```
|
||||||
|
|
||||||
weighted_maximum(Ws, Vars, Max) :-
|
weighted_maximum(Ws, Vars, Max) :-
|
||||||
must_be(list(integer), Ws),
|
must_be(list(integer), Ws),
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/** Predicates for reasoning about files and directories.
|
/** Predicates for reasoning about files and directories.
|
||||||
|
|
||||||
In this library, directories and files are represented as
|
In this library, directories and files are represented as
|
||||||
*lists of characters*. This is an ideal representation:
|
_lists of characters_. This is an ideal representation:
|
||||||
|
|
||||||
* Lists of characters can be conveniently reasoned about with DCGs
|
* Lists of characters can be conveniently reasoned about with DCGs
|
||||||
and built-in Prolog predicates from library(lists). This alone
|
and built-in Prolog predicates from `library(lists)`. This alone
|
||||||
is already a very compelling argument to use them.
|
is already a very compelling argument to use them.
|
||||||
* Other Scryer libraries such as library(http/http_open) also already
|
* Other Scryer libraries such as `library(http/http_open)` also already
|
||||||
use lists of characters to represent paths.
|
use lists of characters to represent paths.
|
||||||
* File names are mostly ephemeral, so it is good for efficiency
|
* File names are mostly ephemeral, so it is good for efficiency
|
||||||
that they can quickly allocated transiently on the heap, leaving the
|
that they can quickly allocated transiently on the heap, leaving the
|
||||||
@@ -123,14 +123,14 @@ directory_exists(Directory) :-
|
|||||||
%% make_directory(+Directory).
|
%% make_directory(+Directory).
|
||||||
%
|
%
|
||||||
% Succeeds if it creates a new directory named Directory in the current system.
|
% Succeeds if it creates a new directory named Directory in the current system.
|
||||||
% If you want to create a nested directory, use make\_directory\_path/1.
|
% If you want to create a nested directory, use `make_directory_path/1`.
|
||||||
make_directory(Directory) :-
|
make_directory(Directory) :-
|
||||||
must_be(chars, Directory),
|
must_be(chars, Directory),
|
||||||
'$make_directory'(Directory).
|
'$make_directory'(Directory).
|
||||||
|
|
||||||
%% make_directory_path(+Directory).
|
%% make_directory_path(+Directory).
|
||||||
%
|
%
|
||||||
% Similar to make\_directory/1 but recursively creates directories if they're missing.
|
% Similar to `make_directory/1` but recursively creates directories if they're missing.
|
||||||
% Equivalent to mkdir -p in Unix.
|
% Equivalent to mkdir -p in Unix.
|
||||||
make_directory_path(Directory) :-
|
make_directory_path(Directory) :-
|
||||||
must_be(chars, Directory),
|
must_be(chars, Directory),
|
||||||
@@ -182,8 +182,8 @@ directory_must_exist(Directory, Context) :-
|
|||||||
%
|
%
|
||||||
% Dir0 is the current working directory, and the working directory
|
% Dir0 is the current working directory, and the working directory
|
||||||
% is changed to Dir.
|
% is changed to Dir.
|
||||||
|
%
|
||||||
% Use `working\_directory(Ds, Ds)` to determine the current working directory,
|
% Use `working_directory/2` to determine the current working directory,
|
||||||
% and leave it as is.
|
% and leave it as is.
|
||||||
|
|
||||||
working_directory(Dir0, Dir) :-
|
working_directory(Dir0, Dir) :-
|
||||||
@@ -220,7 +220,7 @@ path_canonical(Ps, Cs) :-
|
|||||||
%
|
%
|
||||||
% For a file File that must exist, it returns a time stamp T with the modification time
|
% For a file File that must exist, it returns a time stamp T with the modification time
|
||||||
%
|
%
|
||||||
% T is a time stamp compatible with library(time).
|
% T is a time stamp compatible with `library(time)`.
|
||||||
file_modification_time(File, T) :-
|
file_modification_time(File, T) :-
|
||||||
file_time_(File, modification, T).
|
file_time_(File, modification, T).
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ file_modification_time(File, T) :-
|
|||||||
%
|
%
|
||||||
% For a file File that must exist, it returns a time stamp T with the access time
|
% For a file File that must exist, it returns a time stamp T with the access time
|
||||||
%
|
%
|
||||||
% T is a time stamp compatible with library(time).
|
% T is a time stamp compatible with `library(time)`.
|
||||||
file_access_time(File, T) :-
|
file_access_time(File, T) :-
|
||||||
file_time_(File, access, T).
|
file_time_(File, access, T).
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ file_access_time(File, T) :-
|
|||||||
%
|
%
|
||||||
% For a file File that must exist, it returns a time stamp T with the creation time
|
% For a file File that must exist, it returns a time stamp T with the creation time
|
||||||
%
|
%
|
||||||
% T is a time stamp compatible with library(time).
|
% T is a time stamp compatible with `library(time)`.
|
||||||
file_creation_time(File, T) :-
|
file_creation_time(File, T) :-
|
||||||
file_time_(File, creation, T).
|
file_time_(File, creation, T).
|
||||||
|
|
||||||
@@ -258,15 +258,19 @@ file_time_(File, Which, T) :-
|
|||||||
%
|
%
|
||||||
% Examples:
|
% Examples:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- path_segments("/hello/there", Segments).
|
% ?- path_segments("/hello/there", Segments).
|
||||||
% Segments = [[],"hello","there"].
|
% Segments = [[],"hello","there"].
|
||||||
% ?- path_segments(Path, ["hello","there"]).
|
% ?- path_segments(Path, ["hello","there"]).
|
||||||
% Path = "hello/there".
|
% Path = "hello/there".
|
||||||
|
% ```
|
||||||
%
|
%
|
||||||
% To obtain the platform-specific directory separator, you can use:
|
% To obtain the platform-specific directory separator, you can use:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- path_segments(Separator, ["",""]).
|
% ?- path_segments(Separator, ["",""]).
|
||||||
% Separator = "/".
|
% Separator = "/".
|
||||||
|
% ```
|
||||||
|
|
||||||
path_segments(Path, Segments) :-
|
path_segments(Path, Segments) :-
|
||||||
'$directory_separator'(Sep),
|
'$directory_separator'(Sep),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
/** Make HTTP requests.
|
/** Make HTTP requests.
|
||||||
|
|
||||||
This library contains the predicate http\_open/3 which allows you to perform HTTP(S) calls.
|
This library contains the predicate `http_open/3` which allows you to perform HTTP(S) calls.
|
||||||
Useful for making API calls, or parsing websites. It uses Hyper underneath.
|
Useful for making API calls, or parsing websites. It uses Hyper underneath.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -30,8 +30,10 @@ Useful for making API calls, or parsing websites. It uses Hyper underneath.
|
|||||||
%
|
%
|
||||||
% Example:
|
% Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- http_open("https://www.example.com", S, []), get_n_chars(S, N, HTML).
|
% ?- http_open("https://www.example.com", S, []), get_n_chars(S, N, HTML).
|
||||||
% S = '$stream'(0x7fb548001be8), N = 1256, HTML = "<!doctype html>\n<ht ...".
|
% S = '$stream'(0x7fb548001be8), N = 1256, HTML = "<!doctype html>\n<ht ...".
|
||||||
|
% ```
|
||||||
http_open(Address, Response, Options) :-
|
http_open(Address, Response, Options) :-
|
||||||
parse_http_options(Options, OptionValues),
|
parse_http_options(Options, OptionValues),
|
||||||
( member(method(Method), OptionValues) -> true; Method = get),
|
( member(method(Method), OptionValues) -> true; Method = get),
|
||||||
|
|||||||
@@ -34,8 +34,10 @@ but they're not part of the ISO Prolog standard at the moment.
|
|||||||
%
|
%
|
||||||
% In this example, it checks that all numbers are even:
|
% In this example, it checks that all numbers are even:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- Ns = [2,4,6], forall(member(N, Ns), 0 is N mod 2).
|
% ?- Ns = [2,4,6], forall(member(N, Ns), 0 is N mod 2).
|
||||||
% Ns = [2,4,6].
|
% Ns = [2,4,6].
|
||||||
|
% ```
|
||||||
forall(Generate, Test) :-
|
forall(Generate, Test) :-
|
||||||
\+ (Generate, \+ Test).
|
\+ (Generate, \+ Test).
|
||||||
|
|
||||||
@@ -44,20 +46,25 @@ forall(Generate, Test) :-
|
|||||||
%% bb_put(+Key, +Value).
|
%% bb_put(+Key, +Value).
|
||||||
%
|
%
|
||||||
% Sets a global variable named Key (must be an atom) with value Value.
|
% Sets a global variable named Key (must be an atom) with value Value.
|
||||||
% The global variable isn't backtrackable. Check bb\_b\_put/2 for the
|
% The global variable isn't backtrackable. Check `bb_b_put/2` for the
|
||||||
% backtrackable version.
|
% backtrackable version.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- bb_put(city, "Valladolid").
|
% ?- bb_put(city, "Valladolid").
|
||||||
% true.
|
% true.
|
||||||
% ?- bb_get(city, X).
|
% ?- bb_get(city, X).
|
||||||
% X = "Valladolid".
|
% X = "Valladolid".
|
||||||
% In this example one can understand the difference between bb\_put/2 and
|
% ```
|
||||||
% bb\_b\_put/2:
|
|
||||||
%
|
%
|
||||||
|
% In this example one can understand the difference between `bb_put/2` and
|
||||||
|
% `bb_b_put/2`:
|
||||||
|
%
|
||||||
|
% ```
|
||||||
% ?- bb_put(city, "Valladolid"), (bb_put(city, "Salamanca"), false);(bb_get(city, X)).
|
% ?- bb_put(city, "Valladolid"), (bb_put(city, "Salamanca"), false);(bb_get(city, X)).
|
||||||
% X = "Salamanca".
|
% X = "Salamanca".
|
||||||
% ?- bb_put(city, "Valladolid"), (bb_b_put(city, "Salamanca"), false);(bb_get(city, X)).
|
% ?- bb_put(city, "Valladolid"), (bb_b_put(city, "Salamanca"), false);(bb_get(city, X)).
|
||||||
% X = "Valladolid".
|
% X = "Valladolid".
|
||||||
|
% ```
|
||||||
bb_put(Key, Value) :-
|
bb_put(Key, Value) :-
|
||||||
( atom(Key) ->
|
( atom(Key) ->
|
||||||
'$store_global_var'(Key, Value)
|
'$store_global_var'(Key, Value)
|
||||||
@@ -69,20 +76,25 @@ bb_put(Key, Value) :-
|
|||||||
%% bb_b_put(+Key, +Value).
|
%% bb_b_put(+Key, +Value).
|
||||||
%
|
%
|
||||||
% Sets a global variable named Key (must be an atom) with value Value.
|
% Sets a global variable named Key (must be an atom) with value Value.
|
||||||
% The global variable is backtrackable. Check bb\_put/2 for the
|
% The global variable is backtrackable. Check `bb_put/2` for the
|
||||||
% non-backtrackable version.
|
% non-backtrackable version.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- bb_b_put(city, "Valladolid").
|
% ?- bb_b_put(city, "Valladolid").
|
||||||
% true.
|
% true.
|
||||||
% ?- bb_get(city, X).
|
% ?- bb_get(city, X).
|
||||||
% X = "Valladolid".
|
% X = "Valladolid".
|
||||||
% In this example one can understand the difference between bb\_put/2 and
|
% ```
|
||||||
% bb\_b\_put/2:
|
|
||||||
%
|
%
|
||||||
|
% In this example one can understand the difference between `bb_put/2` and
|
||||||
|
% `bb_b_put/2`:
|
||||||
|
%
|
||||||
|
% ```
|
||||||
% ?- bb_put(city, "Valladolid"), (bb_put(city, "Salamanca"), false);(bb_get(city, X)).
|
% ?- bb_put(city, "Valladolid"), (bb_put(city, "Salamanca"), false);(bb_get(city, X)).
|
||||||
% X = "Salamanca".
|
% X = "Salamanca".
|
||||||
% ?- bb_put(city, "Valladolid"), (bb_b_put(city, "Salamanca"), false);(bb_get(city, X)).
|
% ?- bb_put(city, "Valladolid"), (bb_b_put(city, "Salamanca"), false);(bb_get(city, X)).
|
||||||
% X = "Valladolid".
|
% X = "Valladolid".
|
||||||
|
% ```
|
||||||
bb_b_put(Key, Value) :-
|
bb_b_put(Key, Value) :-
|
||||||
( atom(Key) ->
|
( atom(Key) ->
|
||||||
'$store_backtrackable_global_var'(Key, Value)
|
'$store_backtrackable_global_var'(Key, Value)
|
||||||
@@ -119,7 +131,9 @@ call_cleanup(G, C) :- setup_call_cleanup(true, G, C).
|
|||||||
%
|
%
|
||||||
% In this example, we use the predicate to always close an open file:
|
% In this example, we use the predicate to always close an open file:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- setup_call_cleanup(open(File, read, Stream), do_something_with_stream(Stream), close(Stream)).
|
% ?- setup_call_cleanup(open(File, read, Stream), do_something_with_stream(Stream), close(Stream)).
|
||||||
|
% ```
|
||||||
setup_call_cleanup(S, G, C) :-
|
setup_call_cleanup(S, G, C) :-
|
||||||
'$get_b_value'(B),
|
'$get_b_value'(B),
|
||||||
'$call_with_inference_counting'(call(S)),
|
'$call_with_inference_counting'(call(S)),
|
||||||
@@ -329,13 +343,13 @@ call_nth_nesting(C, ID) :-
|
|||||||
|
|
||||||
%% copy_term_nat(Source, Dest)
|
%% copy_term_nat(Source, Dest)
|
||||||
%
|
%
|
||||||
% Similar to copy\_term/2 but without attribute variables
|
% Similar to `copy_term/2` but without attribute variables
|
||||||
copy_term_nat(Source, Dest) :-
|
copy_term_nat(Source, Dest) :-
|
||||||
'$copy_term_without_attr_vars'(Source, Dest).
|
'$copy_term_without_attr_vars'(Source, Dest).
|
||||||
|
|
||||||
%% asserta(Module, Rule_Fact).
|
%% asserta(Module, Rule_Fact).
|
||||||
%
|
%
|
||||||
% Similar to asserta/1 but allows specifying a Module
|
% Similar to `asserta/1` but allows specifying a Module
|
||||||
asserta(Module, (Head :- Body)) :-
|
asserta(Module, (Head :- Body)) :-
|
||||||
!,
|
!,
|
||||||
'$asserta'(Module, Head, Body).
|
'$asserta'(Module, Head, Body).
|
||||||
@@ -344,7 +358,7 @@ asserta(Module, Fact) :-
|
|||||||
|
|
||||||
%% assertz(Module, Rule_Fact).
|
%% assertz(Module, Rule_Fact).
|
||||||
%
|
%
|
||||||
% Similar to assertz/1 but allows specifying a Module
|
% Similar to `assertz/1` but allows specifying a Module
|
||||||
assertz(Module, (Head :- Body)) :-
|
assertz(Module, (Head :- Body)) :-
|
||||||
!,
|
!,
|
||||||
'$assertz'(Module, Head, Body).
|
'$assertz'(Module, Head, Body).
|
||||||
|
|||||||
@@ -66,12 +66,14 @@ resource_error(Resource, Context) :-
|
|||||||
% Relates a list to its length (number of items). It can be used to count the elements of a current list or
|
% Relates a list to its length (number of items). It can be used to count the elements of a current list or
|
||||||
% to create a list full of free variables with N length.
|
% to create a list full of free variables with N length.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- length([a,b,c], 3).
|
% ?- length([a,b,c], 3).
|
||||||
% true.
|
% true.
|
||||||
% ?- length([a,b,c], N).
|
% ?- length([a,b,c], N).
|
||||||
% N = 3.
|
% N = 3.
|
||||||
% ?- length(Xs, 3).
|
% ?- length(Xs, 3).
|
||||||
% Xs = [_A, _B, _C].
|
% Xs = [_A, _B, _C].
|
||||||
|
% ```
|
||||||
|
|
||||||
length(Xs0, N) :-
|
length(Xs0, N) :-
|
||||||
'$skip_max_list'(M, N, Xs0,Xs),
|
'$skip_max_list'(M, N, Xs0,Xs),
|
||||||
@@ -115,10 +117,11 @@ length_addendum([_|Xs], N, M) :-
|
|||||||
%
|
%
|
||||||
% Succeeds when X unifies with an item of the list Xs, which can be at any position.
|
% Succeeds when X unifies with an item of the list Xs, which can be at any position.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- member(X, "hello world").
|
% ?- member(X, "hello world").
|
||||||
% X = h
|
% X = h
|
||||||
% ; ... .
|
% ; ... .
|
||||||
%
|
% ```
|
||||||
member(X, [X|_]).
|
member(X, [X|_]).
|
||||||
member(X, [_|Xs]) :- member(X, Xs).
|
member(X, [_|Xs]) :- member(X, Xs).
|
||||||
|
|
||||||
@@ -126,9 +129,10 @@ member(X, [_|Xs]) :- member(X, Xs).
|
|||||||
%
|
%
|
||||||
% Succeeds when the list Xs1 is the list Xs0 without the item X
|
% Succeeds when the list Xs1 is the list Xs0 without the item X
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- select(c, "abcd", X).
|
% ?- select(c, "abcd", X).
|
||||||
% X = "abd".
|
% X = "abd".
|
||||||
%
|
% ```
|
||||||
select(X, [X|Xs], Xs).
|
select(X, [X|Xs], Xs).
|
||||||
select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
|
select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
|
||||||
|
|
||||||
@@ -136,9 +140,10 @@ select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
|
|||||||
%
|
%
|
||||||
% Concatenates a list of lists
|
% Concatenates a list of lists
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- append([[1, 2], [3]], Xs).
|
% ?- append([[1, 2], [3]], Xs).
|
||||||
% Xs = [1, 2, 3].
|
% Xs = [1, 2, 3].
|
||||||
%
|
% ```
|
||||||
append([], []).
|
append([], []).
|
||||||
append([L0|Ls0], Ls) :-
|
append([L0|Ls0], Ls) :-
|
||||||
append(L0, Rest, Ls),
|
append(L0, Rest, Ls),
|
||||||
@@ -148,15 +153,16 @@ append([L0|Ls0], Ls) :-
|
|||||||
%
|
%
|
||||||
% List Xs is the concatenation of Xs0 and Xs1
|
% List Xs is the concatenation of Xs0 and Xs1
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- append([1,2,3], [4,5,6], Xs).
|
% ?- append([1,2,3], [4,5,6], Xs).
|
||||||
% Xs = [1, 2, 3, 4, 5, 6].
|
% Xs = [1, 2, 3, 4, 5, 6].
|
||||||
%
|
% ```
|
||||||
append([], R, R).
|
append([], R, R).
|
||||||
append([X|L], R, [X|S]) :- append(L, R, S).
|
append([X|L], R, [X|S]) :- append(L, R, S).
|
||||||
|
|
||||||
%% memberchk(?X, +Xs).
|
%% memberchk(?X, +Xs).
|
||||||
%
|
%
|
||||||
% This predicate is similar to member/2, but it only provides a single answer
|
% This predicate is similar to `member/2`, but it only provides a single answer
|
||||||
memberchk(X, Xs) :- member(X, Xs), !.
|
memberchk(X, Xs) :- member(X, Xs), !.
|
||||||
|
|
||||||
%% reverse(?Xs, ?Ys).
|
%% reverse(?Xs, ?Ys).
|
||||||
@@ -179,9 +185,10 @@ reverse([_|Xs], [Y1|Ys], YsPreludeRev, Xss) :-
|
|||||||
%
|
%
|
||||||
% This is a metapredicate that applies predicate to each element of the list Xs0
|
% This is a metapredicate that applies predicate to each element of the list Xs0
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- maplist(write, [1,2,3]).
|
% ?- maplist(write, [1,2,3]).
|
||||||
% 123 true.
|
% 123 true.
|
||||||
%
|
% ```
|
||||||
maplist(_, []).
|
maplist(_, []).
|
||||||
maplist(Cont1, [E1|E1s]) :-
|
maplist(Cont1, [E1|E1s]) :-
|
||||||
call(Cont1, E1),
|
call(Cont1, E1),
|
||||||
@@ -191,9 +198,10 @@ maplist(Cont1, [E1|E1s]) :-
|
|||||||
%
|
%
|
||||||
% This is a metapredicate that applies predicate to each element of the lists Xs0 and Xs1.
|
% This is a metapredicate that applies predicate to each element of the lists Xs0 and Xs1.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- maplist(length, ["hello", "prolog", "marseille"], Xs1).
|
% ?- maplist(length, ["hello", "prolog", "marseille"], Xs1).
|
||||||
% Xs1 = [5,6,9].
|
% Xs1 = [5,6,9].
|
||||||
%
|
% ```
|
||||||
maplist(_, [], []).
|
maplist(_, [], []).
|
||||||
maplist(Cont2, [E1|E1s], [E2|E2s]) :-
|
maplist(Cont2, [E1|E1s], [E2|E2s]) :-
|
||||||
call(Cont2, E1, E2),
|
call(Cont2, E1, E2),
|
||||||
@@ -251,8 +259,10 @@ maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7
|
|||||||
%
|
%
|
||||||
% Takes a lists of numbers and unifies Sum with the result of summing all the elements of the list.
|
% Takes a lists of numbers and unifies Sum with the result of summing all the elements of the list.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- sum_list([2,2,2], 6).
|
% ?- sum_list([2,2,2], 6).
|
||||||
% true.
|
% true.
|
||||||
|
% ```
|
||||||
sum_list(Ls, S) :-
|
sum_list(Ls, S) :-
|
||||||
foldl(lists:sum_, Ls, 0, S).
|
foldl(lists:sum_, Ls, 0, S).
|
||||||
|
|
||||||
@@ -274,12 +284,15 @@ same_length([_|As], [_|Bs]) :-
|
|||||||
%
|
%
|
||||||
% For example, if we define sum_ as:
|
% For example, if we define sum_ as:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% sum_(L, S0, S) :- S is S0 + L.
|
% sum_(L, S0, S) :- S is S0 + L.
|
||||||
|
% ```
|
||||||
%
|
%
|
||||||
% Then we can define sum\_list/2 as the following:
|
% Then we can define `sum_list/2` as the following:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% sum_list(Ls, S) :- foldl(sum_, Ls, 0, S).
|
% sum_list(Ls, S) :- foldl(sum_, Ls, 0, S).
|
||||||
%
|
% ```
|
||||||
|
|
||||||
foldl(Goal_3, Ls, A0, A) :-
|
foldl(Goal_3, Ls, A0, A) :-
|
||||||
foldl_(Ls, Goal_3, A0, A).
|
foldl_(Ls, Goal_3, A0, A).
|
||||||
@@ -291,7 +304,7 @@ foldl_([L|Ls], G_3, A0, A) :-
|
|||||||
|
|
||||||
%% foldl(+Predicate, ?Ls0, ?Ls1, +A0, ?A).
|
%% foldl(+Predicate, ?Ls0, ?Ls1, +A0, ?A).
|
||||||
%
|
%
|
||||||
% Same as foldl/4 but with an extra list
|
% Same as `foldl/4` but with an extra list
|
||||||
foldl(Goal_4, Xs, Ys, A0, A) :-
|
foldl(Goal_4, Xs, Ys, A0, A) :-
|
||||||
foldl_(Xs, Ys, Goal_4, A0, A).
|
foldl_(Xs, Ys, Goal_4, A0, A).
|
||||||
|
|
||||||
@@ -305,9 +318,10 @@ foldl_([X|Xs], [Y|Ys], G_4, A0, A) :-
|
|||||||
%
|
%
|
||||||
% If Ls is a list of lists, Ts contains the transposition
|
% If Ls is a list of lists, Ts contains the transposition
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- transpose([[1,1],[2,2]], Ts).
|
% ?- transpose([[1,1],[2,2]], Ts).
|
||||||
% Ts = [[1,2],[1,2]].
|
% Ts = [[1,2],[1,2]].
|
||||||
%
|
% ```
|
||||||
transpose(Ls, Ts) :-
|
transpose(Ls, Ts) :-
|
||||||
lists_transpose(Ls, Ts).
|
lists_transpose(Ls, Ts).
|
||||||
|
|
||||||
@@ -325,9 +339,10 @@ list_first_rest([L|Ls], L, Ls).
|
|||||||
%
|
%
|
||||||
% Takes a list Ls0 and returns a list Set that doesn't contain any repeated element
|
% Takes a list Ls0 and returns a list Set that doesn't contain any repeated element
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- list_to_set([2,3,4,4,1,2], Set).
|
% ?- list_to_set([2,3,4,4,1,2], Set).
|
||||||
% Set = [2,3,4,1].
|
% Set = [2,3,4,1].
|
||||||
%
|
% ```
|
||||||
list_to_set(Ls0, Ls) :-
|
list_to_set(Ls0, Ls) :-
|
||||||
maplist(lists:with_var, Ls0, LVs0),
|
maplist(lists:with_var, Ls0, LVs0),
|
||||||
keysort(LVs0, LVs),
|
keysort(LVs0, LVs),
|
||||||
@@ -359,8 +374,10 @@ unify_same(E-V, Prev-Var, E-V) :-
|
|||||||
%
|
%
|
||||||
% Succeeds if in the N position of the list Ls, we found the element E. The elements start counting from zero.
|
% Succeeds if in the N position of the list Ls, we found the element E. The elements start counting from zero.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- nth0(2, [1,2,3,4], 3).
|
% ?- nth0(2, [1,2,3,4], 3).
|
||||||
% true.
|
% true.
|
||||||
|
% ```
|
||||||
nth0(N, Es0, E) :-
|
nth0(N, Es0, E) :-
|
||||||
nonvar(N),
|
nonvar(N),
|
||||||
'$skip_max_list'(Skip, N, Es0,Es1),
|
'$skip_max_list'(Skip, N, Es0,Es1),
|
||||||
@@ -399,8 +416,10 @@ nth0_el(N0,N, _,E, [E0|Es0]) :-
|
|||||||
%
|
%
|
||||||
% Succeeds if in the N position of the list Ls, we found the element E. The elements start counting from one.
|
% Succeeds if in the N position of the list Ls, we found the element E. The elements start counting from one.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- nth1(2, [1,2,3,4], 2).
|
% ?- nth1(2, [1,2,3,4], 2).
|
||||||
% true.
|
% true.
|
||||||
|
% ```
|
||||||
nth1(N, Es0, E) :-
|
nth1(N, Es0, E) :-
|
||||||
N \== 0,
|
N \== 0,
|
||||||
nth0(N, [_|Es0], E),
|
nth0(N, [_|Es0], E),
|
||||||
@@ -419,8 +438,10 @@ skipn(0, Es,Es, Xs,Xs).
|
|||||||
%
|
%
|
||||||
% Succeeds if in the N position of the list Ls, we found the element E and the rest of the list is Rs. The elements start counting from zero.
|
% Succeeds if in the N position of the list Ls, we found the element E and the rest of the list is Rs. The elements start counting from zero.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- nth0(2, [1,2,3,4], 3, [1,2,4]).
|
% ?- nth0(2, [1,2,3,4], 3, [1,2,4]).
|
||||||
% true.
|
% true.
|
||||||
|
% ```
|
||||||
nth0(N, Es0, E, Es) :-
|
nth0(N, Es0, E, Es) :-
|
||||||
integer(N),
|
integer(N),
|
||||||
N >= 0,
|
N >= 0,
|
||||||
@@ -449,8 +470,10 @@ nth0_elx(N0,N, E0,E, [E1|Es0], [E0|Es]) :-
|
|||||||
%
|
%
|
||||||
% Succeeds if in the N position of the list Ls, we found the element E and the rest of the list is Rs. The elements start counting from one.
|
% Succeeds if in the N position of the list Ls, we found the element E and the rest of the list is Rs. The elements start counting from one.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- nth1(2, [1,2,3,4], 2, [1,3,4]).
|
% ?- nth1(2, [1,2,3,4], 2, [1,3,4]).
|
||||||
% true.
|
% true.
|
||||||
|
% ```
|
||||||
nth1(N, Es0, E, Es) :-
|
nth1(N, Es0, E, Es) :-
|
||||||
N \== 0,
|
N \== 0,
|
||||||
nth0(N, [_|Es0], E, [_|Es]),
|
nth0(N, [_|Es0], E, [_|Es]),
|
||||||
@@ -478,7 +501,7 @@ list_min_(N, Min0, Min) :-
|
|||||||
%
|
%
|
||||||
% True when Xs is a permutation of Ys. This can solve for Ys given
|
% True when Xs is a permutation of Ys. This can solve for Ys given
|
||||||
% Xs or Xs given Ys, or even enumerate Xs and Ys together. The
|
% Xs or Xs given Ys, or even enumerate Xs and Ys together. The
|
||||||
% predicate permutation/2 is primarily intended to generate
|
% predicate `permutation/2` is primarily intended to generate
|
||||||
% permutations. Note that a list of length N has N! permutations,
|
% permutations. Note that a list of length N has N! permutations,
|
||||||
% and unbounded permutation generation becomes prohibitively
|
% and unbounded permutation generation becomes prohibitively
|
||||||
% expensive, even for rather short lists (10! = 3,628,800).
|
% expensive, even for rather short lists (10! = 3,628,800).
|
||||||
@@ -486,12 +509,14 @@ list_min_(N, Min0, Min) :-
|
|||||||
% The example below illustrates that Xs and Ys being proper lists
|
% The example below illustrates that Xs and Ys being proper lists
|
||||||
% is not a sufficient condition to use the above replacement.
|
% is not a sufficient condition to use the above replacement.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- permutation([1,2], [X,Y]).
|
% ?- permutation([1,2], [X,Y]).
|
||||||
% X = 1, Y = 2
|
% X = 1, Y = 2
|
||||||
% ; X = 2, Y = 1
|
% ; X = 2, Y = 1
|
||||||
% ; false.
|
% ; false.
|
||||||
|
% ```
|
||||||
%
|
%
|
||||||
% Throws type\_error(list, Arg) if either argument is not a proper
|
% Throws `type_error(list, Arg)` if either argument is not a proper
|
||||||
% or partial list.
|
% or partial list.
|
||||||
|
|
||||||
permutation(Xs, Ys) :-
|
permutation(Xs, Ys) :-
|
||||||
|
|||||||
@@ -57,22 +57,22 @@
|
|||||||
/** Ordered set manipulation
|
/** Ordered set manipulation
|
||||||
|
|
||||||
Ordered sets are lists with unique elements sorted to the standard order
|
Ordered sets are lists with unique elements sorted to the standard order
|
||||||
of terms (see sort/2). Exploiting ordering, many of the set operations
|
of terms (see `sort/2`). Exploiting ordering, many of the set operations
|
||||||
can be expressed in order N rather than N^2 when dealing with unordered
|
can be expressed in order N rather than N^2 when dealing with unordered
|
||||||
sets that may contain duplicates. The library(ordsets) is available in a
|
sets that may contain duplicates. The library(ordsets) is available in a
|
||||||
number of Prolog implementations. Our predicates are designed to be
|
number of Prolog implementations. Our predicates are designed to be
|
||||||
compatible with common practice in the Prolog community.
|
compatible with common practice in the Prolog community.
|
||||||
Some of these predicates match directly to corresponding list
|
Some of these predicates match directly to corresponding list
|
||||||
operations. It is advised to use the versions from this library to make
|
operations. It is advised to use the versions from this library to make
|
||||||
clear you are operating on ordered sets. An exception is member/2. See
|
clear you are operating on ordered sets. An exception is `member/2`. See
|
||||||
ord\_memberchk/2.
|
`ord_memberchk/2`.
|
||||||
|
|
||||||
The ordsets library is based on the standard order of terms. This
|
The ordsets library is based on the standard order of terms. This
|
||||||
implies it can handle all Prolog terms, including variables. Note
|
implies it can handle all Prolog terms, including variables. Note
|
||||||
however, that the ordering is not stable if a term inside the set is
|
however, that the ordering is not stable if a term inside the set is
|
||||||
further instantiated. Also note that variable ordering changes if
|
further instantiated. Also note that variable ordering changes if
|
||||||
variables in the set are unified with each other or a variable in the
|
variables in the set are unified with each other or a variable in the
|
||||||
set is unified with a variable that is `older' than the newest variable
|
set is unified with a variable that is _older_ than the newest variable
|
||||||
in the set. In practice, this implies that it is allowed to use
|
in the set. In practice, this implies that it is allowed to use
|
||||||
member(X, OrdSet) on an ordered set that holds variables only if X is a
|
member(X, OrdSet) on an ordered set that holds variables only if X is a
|
||||||
fresh variable. In other cases one should cease using it as an ordset
|
fresh variable. In other cases one should cease using it as an ordset
|
||||||
@@ -84,8 +84,8 @@ because the order it relies on may have been changed.
|
|||||||
% True if Term is an ordered set. All predicates in this library
|
% True if Term is an ordered set. All predicates in this library
|
||||||
% expect ordered sets as input arguments. Failing to fullfil this
|
% expect ordered sets as input arguments. Failing to fullfil this
|
||||||
% assumption results in undefined behaviour. Typically, ordered
|
% assumption results in undefined behaviour. Typically, ordered
|
||||||
% sets are created by predicates from this library, sort/2 or
|
% sets are created by predicates from this library, `sort/2` or
|
||||||
% setof/3.
|
% `setof/3`.
|
||||||
|
|
||||||
is_ordset(Term) :-
|
is_ordset(Term) :-
|
||||||
'$skip_max_list'(_, _, Term, Tail), Tail == [], %% is_list(Term),
|
'$skip_max_list'(_, _, Term, Tail), Tail == [], %% is_list(Term),
|
||||||
@@ -112,7 +112,7 @@ ord_empty([]).
|
|||||||
%% ord_seteq(+Set1, +Set2) is semidet.
|
%% ord_seteq(+Set1, +Set2) is semidet.
|
||||||
%
|
%
|
||||||
% True if Set1 and Set2 have the same elements. As both are
|
% True if Set1 and Set2 have the same elements. As both are
|
||||||
% canonical sorted lists, this is the same as ==/2.
|
% canonical sorted lists, this is the same as `==/2`.
|
||||||
|
|
||||||
ord_seteq(Set1, Set2) :-
|
ord_seteq(Set1, Set2) :-
|
||||||
Set1 == Set2.
|
Set1 == Set2.
|
||||||
@@ -148,7 +148,7 @@ ord_intersect__(>, H1, T1, _H2, T2) :-
|
|||||||
%% ord_disjoint(+Set1, +Set2) is semidet.
|
%% ord_disjoint(+Set1, +Set2) is semidet.
|
||||||
%
|
%
|
||||||
% True if Set1 and Set2 have no common elements. This is the
|
% True if Set1 and Set2 have no common elements. This is the
|
||||||
% negation of ord\_intersect/2.
|
% negation of `ord_intersect/2`.
|
||||||
|
|
||||||
ord_disjoint(Set1, Set2) :-
|
ord_disjoint(Set1, Set2) :-
|
||||||
\+ ord_intersect(Set1, Set2).
|
\+ ord_intersect(Set1, Set2).
|
||||||
@@ -158,7 +158,7 @@ ord_disjoint(Set1, Set2) :-
|
|||||||
%
|
%
|
||||||
% Intersection holds the common elements of Set1 and Set2.
|
% Intersection holds the common elements of Set1 and Set2.
|
||||||
%
|
%
|
||||||
% This predicate is **deprecated**. Use ord\_intersection/3
|
% This predicate is *deprecated*. Use `ord_intersection/3`
|
||||||
|
|
||||||
ord_intersect(Set1, Set2, Intersection) :-
|
ord_intersect(Set1, Set2, Intersection) :-
|
||||||
oset_int(Set1, Set2, Intersection).
|
oset_int(Set1, Set2, Intersection).
|
||||||
@@ -188,7 +188,7 @@ l_int([_-H|T], S0, S) :-
|
|||||||
%% ord_intersection(+Set1, +Set2, -Intersection) is det.
|
%% ord_intersection(+Set1, +Set2, -Intersection) is det.
|
||||||
%
|
%
|
||||||
% Intersection holds the common elements of Set1 and Set2. Uses
|
% Intersection holds the common elements of Set1 and Set2. Uses
|
||||||
% ord\_disjoint/2 if Intersection is bound to `[]` on entry.
|
% `ord_disjoint/2` if Intersection is bound to `[]` on entry.
|
||||||
|
|
||||||
ord_intersection(Set1, Set2, Intersection) :-
|
ord_intersection(Set1, Set2, Intersection) :-
|
||||||
( Intersection == []
|
( Intersection == []
|
||||||
@@ -201,7 +201,7 @@ ord_intersection(Set1, Set2, Intersection) :-
|
|||||||
%
|
%
|
||||||
% Intersection and difference between two ordered sets.
|
% Intersection and difference between two ordered sets.
|
||||||
% Intersection is the intersection between Set1 and Set2, while
|
% Intersection is the intersection between Set1 and Set2, while
|
||||||
% Difference is defined by ord\_subtract(Set2, Set1, Difference).
|
% Difference is defined by `ord_subtract(Set2, Set1, Difference)`.
|
||||||
|
|
||||||
ord_intersection([], L, [], L) :- !.
|
ord_intersection([], L, [], L) :- !.
|
||||||
ord_intersection([_|_], [], [], []) :- !.
|
ord_intersection([_|_], [], [], []) :- !.
|
||||||
@@ -220,7 +220,7 @@ ord_intersection2(>, H1, T1, H2, T2, Intersection, [H2|HDiff]) :-
|
|||||||
%% ord_add_element(+Set1, +Element, ?Set2) is det.
|
%% ord_add_element(+Set1, +Element, ?Set2) is det.
|
||||||
%
|
%
|
||||||
% Insert an element into the set. This is the same as
|
% Insert an element into the set. This is the same as
|
||||||
% ord\_union(Set1, [Element], Set2).
|
% `ord_union(Set1, [Element], Set2)`.
|
||||||
|
|
||||||
ord_add_element(Set1, Element, Set2) :-
|
ord_add_element(Set1, Element, Set2) :-
|
||||||
oset_addel(Set1, Element, Set2).
|
oset_addel(Set1, Element, Set2).
|
||||||
@@ -229,7 +229,7 @@ ord_add_element(Set1, Element, Set2) :-
|
|||||||
%% ord_del_element(+Set, +Element, -NewSet) is det.
|
%% ord_del_element(+Set, +Element, -NewSet) is det.
|
||||||
%
|
%
|
||||||
% Delete an element from an ordered set. This is the same as
|
% Delete an element from an ordered set. This is the same as
|
||||||
% ord\_subtract(Set, [Element], NewSet).
|
% `ord_subtract(Set, [Element], NewSet)`.
|
||||||
|
|
||||||
ord_del_element(Set, Element, NewSet) :-
|
ord_del_element(Set, Element, NewSet) :-
|
||||||
oset_delel(Set, Element, NewSet).
|
oset_delel(Set, Element, NewSet).
|
||||||
@@ -237,13 +237,13 @@ ord_del_element(Set, Element, NewSet) :-
|
|||||||
|
|
||||||
%% ord_selectchk(+Item, ?Set1, ?Set2) is semidet.
|
%% ord_selectchk(+Item, ?Set1, ?Set2) is semidet.
|
||||||
%
|
%
|
||||||
% Selectchk/3, specialised for ordered sets. Is true when
|
% `selectchk/3`, specialised for ordered sets. Is true when
|
||||||
% select(Item, Set1, Set2) and Set1, Set2 are both sorted lists
|
% select(Item, Set1, Set2) and Set1, Set2 are both sorted lists
|
||||||
% without duplicates. This implementation is only expected to work
|
% without duplicates. This implementation is only expected to work
|
||||||
% for Item ground and either Set1 or Set2 ground. The "chk" suffix
|
% for Item ground and either Set1 or Set2 ground. The "chk" suffix
|
||||||
% is meant to remind you of memberchk/2, which also expects its
|
% is meant to remind you of `memberchk/2`, which also expects its
|
||||||
% first argument to be ground. ord\_selectchk(X, S, T) =>
|
% first argument to be ground. `ord_selectchk(X, S, T) =>
|
||||||
% ord\_memberchk(X, S) & \\+ ord\_memberchk(X, T).
|
% ord_memberchk(X, S) & \+ ord_memberchk(X, T).`
|
||||||
%
|
%
|
||||||
% Author: Richard O'Keefe
|
% Author: Richard O'Keefe
|
||||||
|
|
||||||
@@ -263,13 +263,13 @@ ord_selectchk(Item, [Item|Set1], Set1) :-
|
|||||||
%
|
%
|
||||||
% True if Element is a member of OrdSet, compared using ==. Note
|
% True if Element is a member of OrdSet, compared using ==. Note
|
||||||
% that _enumerating_ elements of an ordered set can be done using
|
% that _enumerating_ elements of an ordered set can be done using
|
||||||
% member/2.
|
% `member/2`.
|
||||||
%
|
%
|
||||||
% Some Prolog implementations also provide ord\_member/2, with the
|
% Some Prolog implementations also provide `ord_member/2`, with the
|
||||||
% same semantics as ord\_memberchk/2. We believe that having a
|
% same semantics as `ord_memberchk/2`. We believe that having a
|
||||||
% semidet ord\_member/2 is unacceptably inconsistent with the \*\_chk
|
% semidet `ord_member/2` is unacceptably inconsistent with the \*\_chk
|
||||||
% convention. Portable code should use ord\_memberchk/2 or
|
% convention. Portable code should use `ord_memberchk/2` or
|
||||||
% member/2.
|
% `member/2`.
|
||||||
%
|
%
|
||||||
% Author: Richard O'Keefe
|
% Author: Richard O'Keefe
|
||||||
|
|
||||||
@@ -356,8 +356,8 @@ ord_union(Set1, Set2, Union) :-
|
|||||||
|
|
||||||
%% ord_union(+Set1, +Set2, -Union, -New) is det.
|
%% ord_union(+Set1, +Set2, -Union, -New) is det.
|
||||||
%
|
%
|
||||||
% True iff ord\_union(Set1, Set2, Union) and
|
% True iff `ord_union(Set1, Set2, Union)` and
|
||||||
% ord\_subtract(Set2, Set1, New).
|
% `ord_subtract(Set2, Set1, New)`.
|
||||||
|
|
||||||
ord_union([], Set2, Set2, Set2).
|
ord_union([], Set2, Set2, Set2).
|
||||||
ord_union([H|T], Set2, Union, New) :-
|
ord_union([H|T], Set2, Union, New) :-
|
||||||
@@ -389,14 +389,18 @@ ord_union_2([H|T], H2, T2, Union, New) :-
|
|||||||
% sequence below (but the actual implementation requires only a
|
% sequence below (but the actual implementation requires only a
|
||||||
% single scan).
|
% single scan).
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ord_union(Set1, Set2, Union),
|
% ord_union(Set1, Set2, Union),
|
||||||
% ord_intersection(Set1, Set2, Intersection),
|
% ord_intersection(Set1, Set2, Intersection),
|
||||||
% ord_subtract(Union, Intersection, Difference).
|
% ord_subtract(Union, Intersection, Difference).
|
||||||
|
% ```
|
||||||
%
|
%
|
||||||
% For example:
|
% For example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- ord_symdiff([1,2], [2,3], X).
|
% ?- ord_symdiff([1,2], [2,3], X).
|
||||||
% X = [1,3].
|
% X = [1,3].
|
||||||
|
% ```
|
||||||
|
|
||||||
ord_symdiff([], Set2, Set2).
|
ord_symdiff([], Set2, Set2).
|
||||||
ord_symdiff([H1|T1], Set2, Difference) :-
|
ord_symdiff([H1|T1], Set2, Difference) :-
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ random(R) :-
|
|||||||
%
|
%
|
||||||
% Generates a random integer number between Lower (inclusive) and Upper (exclusive).
|
% Generates a random integer number between Lower (inclusive) and Upper (exclusive).
|
||||||
%
|
%
|
||||||
% Throws instantiation\_error if Lower or Upper are variables.
|
% Throws `instantiation_error` if Lower or Upper are variables.
|
||||||
%
|
%
|
||||||
% Throws type\_error if Lower or Upper aren't integers.
|
% Throws `type_error` if Lower or Upper aren't integers.
|
||||||
random_integer(Lower, Upper, R) :-
|
random_integer(Lower, Upper, R) :-
|
||||||
var(R),
|
var(R),
|
||||||
( (var(Lower) ; var(Upper)) ->
|
( (var(Lower) ; var(Upper)) ->
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
Predicates for handling network sockets, both as a server and as a client.
|
Predicates for handling network sockets, both as a server and as a client.
|
||||||
As a server, you should open a socket an call socket\_server\_accept/4 to get a stream for each connection.
|
As a server, you should open a socket an call `socket_server_accept/4` to get a stream for each connection.
|
||||||
As a client, you should just open a socket and you will receive a stream.
|
As a client, you should just open a socket and you will receive a stream.
|
||||||
In both cases, with a stream, you can use the usual predicates to read and write to the stream.
|
In both cases, with a stream, you can use the usual predicates to read and write to the stream.
|
||||||
*/
|
*/
|
||||||
@@ -18,10 +18,10 @@ In both cases, with a stream, you can use the usual predicates to read and write
|
|||||||
%
|
%
|
||||||
% The following options are available:
|
% The following options are available:
|
||||||
%
|
%
|
||||||
% * alias(+Alias): Set an alias to the stream
|
% * `alias(+Alias)`: Set an alias to the stream
|
||||||
% * eof_action(+Action): Defined what happens if the end of the stream is reached. Values: `error`, `eof_code` and `reset`.
|
% * `eof_action(+Action)`: Defined what happens if the end of the stream is reached. Values: `error`, `eof_code` and `reset`.
|
||||||
% * reposition(+Boolean): Specifies whether repositioning is required for the stream. `false` is the default.
|
% * `reposition(+Boolean)`: Specifies whether repositioning is required for the stream. `false` is the default.
|
||||||
% * type(+Type): Type can be `text` or `binary`. Defines the type of the stream, if it's optimized for plain text
|
% * `type(+Type)`: Type can be `text` or `binary`. Defines the type of the stream, if it's optimized for plain text
|
||||||
% or just binary
|
% or just binary
|
||||||
%
|
%
|
||||||
socket_client_open(Addr, Stream, Options) :-
|
socket_client_open(Addr, Stream, Options) :-
|
||||||
@@ -47,7 +47,7 @@ socket_client_open(Addr, Stream, Options) :-
|
|||||||
%% socket_server_open(+Addr, -ServerSocket).
|
%% socket_server_open(+Addr, -ServerSocket).
|
||||||
%
|
%
|
||||||
% Open a server socket, returning a ServerSocket. Use that ServerSocket to accept incoming connections in
|
% Open a server socket, returning a ServerSocket. Use that ServerSocket to accept incoming connections in
|
||||||
% socket\_server\_accept/4. Addr must satisfy `Addr = Address:Port`. Depending on the operating system
|
% `socket_server_accept/4`. Addr must satisfy `Addr = Address:Port`. Depending on the operating system
|
||||||
% configuration, some ports might be reserved for superusers.
|
% configuration, some ports might be reserved for superusers.
|
||||||
socket_server_open(Addr, ServerSocket) :-
|
socket_server_open(Addr, ServerSocket) :-
|
||||||
must_be(var, ServerSocket),
|
must_be(var, ServerSocket),
|
||||||
@@ -67,10 +67,10 @@ socket_server_open(Addr, ServerSocket) :-
|
|||||||
%
|
%
|
||||||
% The following options are available:
|
% The following options are available:
|
||||||
%
|
%
|
||||||
% * alias(+Alias): Set an alias to the stream
|
% * `alias(+Alias)`: Set an alias to the stream
|
||||||
% * eof_action(+Action): Defined what happens if the end of the stream is reached. Values: `error`, `eof_code` and `reset`.
|
% * `eof_action(+Action)`: Defined what happens if the end of the stream is reached. Values: `error`, `eof_code` and `reset`.
|
||||||
% * reposition(+Boolean): Specifies whether repositioning is required for the stream. `false` is the default.
|
% * `reposition(+Boolean)`: Specifies whether repositioning is required for the stream. `false` is the default.
|
||||||
% * type(+Type): Type can be `text` or `binary`. Defines the type of the stream, if it's optimized for plain text
|
% * `type(+Type)`: Type can be `text` or `binary`. Defines the type of the stream, if it's optimized for plain text
|
||||||
% or just binary
|
% or just binary
|
||||||
%
|
%
|
||||||
socket_server_accept(ServerSocket, Client, Stream, Options) :-
|
socket_server_accept(ServerSocket, Client, Stream, Options) :-
|
||||||
|
|||||||
@@ -61,14 +61,14 @@ neighbours of each vertex are also in standard order (as produced by
|
|||||||
sort). This form is convenient for many calculations.
|
sort). This form is convenient for many calculations.
|
||||||
|
|
||||||
A new UGraph from raw data can be created using
|
A new UGraph from raw data can be created using
|
||||||
vertices\_edges\_to\_ugraph/3.
|
`vertices_edges_to_ugraph/3`.
|
||||||
|
|
||||||
Adapted to support some of the functionality of the SICStus ugraphs
|
Adapted to support some of the functionality of the SICStus ugraphs
|
||||||
library by Vitor Santos Costa.
|
library by Vitor Santos Costa.
|
||||||
|
|
||||||
Ported from YAP 5.0.1 to SWI-Prolog by Jan Wielemaker.
|
Ported from YAP 5.0.1 to SWI-Prolog by Jan Wielemaker.
|
||||||
|
|
||||||
Ported from SWI-Prolog to Scryer by Adrián Arroyo Calle
|
Ported from SWI-Prolog to Scryer by [Adrián Arroyo Calle](https://adrianistan.eu)
|
||||||
|
|
||||||
License: BSD-2 or Artistic 2.0
|
License: BSD-2 or Artistic 2.0
|
||||||
*/
|
*/
|
||||||
@@ -81,8 +81,10 @@ License: BSD-2 or Artistic 2.0
|
|||||||
%
|
%
|
||||||
% Unify Vertices with all vertices appearing in Graph. Example:
|
% Unify Vertices with all vertices appearing in Graph. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], L).
|
% ?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], L).
|
||||||
% L = [1, 2, 3, 4, 5]
|
% L = [1, 2, 3, 4, 5]
|
||||||
|
% ```
|
||||||
|
|
||||||
vertices([], []) :- !.
|
vertices([], []) :- !.
|
||||||
vertices([Vertex-_|Graph], [Vertex|Vertices]) :-
|
vertices([Vertex-_|Graph], [Vertex|Vertices]) :-
|
||||||
@@ -97,14 +99,18 @@ vertices([Vertex-_|Graph], [Vertex|Vertices]) :-
|
|||||||
% edges will appear in Vertices but not in Edges. Moreover, it is
|
% edges will appear in Vertices but not in Edges. Moreover, it is
|
||||||
% sufficient for a vertice to appear in Edges.
|
% sufficient for a vertice to appear in Edges.
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- vertices_edges_to_ugraph([],[1-3,2-4,4-5,1-5], L).
|
% ?- vertices_edges_to_ugraph([],[1-3,2-4,4-5,1-5], L).
|
||||||
% L = [1-[3,5], 2-[4], 3-[], 4-[5], 5-[]]
|
% L = [1-[3,5], 2-[4], 3-[], 4-[5], 5-[]]
|
||||||
|
% ```
|
||||||
%
|
%
|
||||||
% In this case all vertices are defined implicitly. The next
|
% In this case all vertices are defined implicitly. The next
|
||||||
% example shows three unconnected vertices:
|
% example shows three unconnected vertices:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- vertices_edges_to_ugraph([6,7,8],[1-3,2-4,4-5,1-5], L).
|
% ?- vertices_edges_to_ugraph([6,7,8],[1-3,2-4,4-5,1-5], L).
|
||||||
% L = [1-[3,5], 2-[4], 3-[], 4-[5], 5-[], 6-[], 7-[], 8-[]]
|
% L = [1-[3,5], 2-[4], 3-[], 4-[5], 5-[], 6-[], 7-[], 8-[]]
|
||||||
|
% ```
|
||||||
|
|
||||||
vertices_edges_to_ugraph(Vertices, Edges, Graph) :-
|
vertices_edges_to_ugraph(Vertices, Edges, Graph) :-
|
||||||
sort(Edges, EdgeSet),
|
sort(Edges, EdgeSet),
|
||||||
@@ -119,8 +125,10 @@ vertices_edges_to_ugraph(Vertices, Edges, Graph) :-
|
|||||||
% Unify NewGraph with a new graph obtained by adding the list of
|
% Unify NewGraph with a new graph obtained by adding the list of
|
||||||
% Vertices to Graph. Example:
|
% Vertices to Graph. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- add_vertices([1-[3,5],2-[]], [0,1,2,9], NG).
|
% ?- add_vertices([1-[3,5],2-[]], [0,1,2,9], NG).
|
||||||
% NG = [0-[], 1-[3,5], 2-[], 9-[]]
|
% NG = [0-[], 1-[3,5], 2-[], 9-[]]
|
||||||
|
% ```
|
||||||
|
|
||||||
% replace with real msort/2 when available
|
% replace with real msort/2 when available
|
||||||
msort_(List, Sorted) :-
|
msort_(List, Sorted) :-
|
||||||
@@ -158,10 +166,12 @@ add_empty_vertices([V|G], [V-[]|NG]) :-
|
|||||||
% Vertices and all the edges that start from or go to a vertex in
|
% Vertices and all the edges that start from or go to a vertex in
|
||||||
% Vertices to the Graph. Example:
|
% Vertices to the Graph. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- del_vertices([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[2,6],8-[]],
|
% ?- del_vertices([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[2,6],8-[]],
|
||||||
% [2,1],
|
% [2,1],
|
||||||
% NL).
|
% NL).
|
||||||
% NL = [3-[],4-[5],5-[],6-[],7-[6],8-[]]
|
% NL = [3-[],4-[5],5-[],6-[],7-[6],8-[]]
|
||||||
|
% ```
|
||||||
|
|
||||||
del_vertices(Graph, Vertices, NewGraph) :-
|
del_vertices(Graph, Vertices, NewGraph) :-
|
||||||
sort(Vertices, V1), % JW: was msort
|
sort(Vertices, V1), % JW: was msort
|
||||||
@@ -195,12 +205,14 @@ split_on_del_vertices(=, _, _, [_|Vs], Vs, _, NG, NG).
|
|||||||
% Unify NewGraph with a new graph obtained by adding the list of Edges
|
% Unify NewGraph with a new graph obtained by adding the list of Edges
|
||||||
% to Graph. Example:
|
% to Graph. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- add_edges([1-[3,5],2-[4],3-[],4-[5],
|
% ?- add_edges([1-[3,5],2-[4],3-[],4-[5],
|
||||||
% 5-[],6-[],7-[],8-[]],
|
% 5-[],6-[],7-[],8-[]],
|
||||||
% [1-6,2-3,3-2,5-7,3-2,4-5],
|
% [1-6,2-3,3-2,5-7,3-2,4-5],
|
||||||
% NL).
|
% NL).
|
||||||
% NL = [1-[3,5,6], 2-[3,4], 3-[2], 4-[5],
|
% NL = [1-[3,5,6], 2-[3,4], 3-[2], 4-[5],
|
||||||
% 5-[7], 6-[], 7-[], 8-[]]
|
% 5-[7], 6-[], 7-[], 8-[]]
|
||||||
|
% ```
|
||||||
|
|
||||||
add_edges(Graph, Edges, NewGraph) :-
|
add_edges(Graph, Edges, NewGraph) :-
|
||||||
p_to_s_graph(Edges, G1),
|
p_to_s_graph(Edges, G1),
|
||||||
@@ -210,8 +222,10 @@ add_edges(Graph, Edges, NewGraph) :-
|
|||||||
%
|
%
|
||||||
% NewGraph is the union of Graph1 and Graph2. Example:
|
% NewGraph is the union of Graph1 and Graph2. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- ugraph_union([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
|
% ?- ugraph_union([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
|
||||||
% L = [1-[2], 2-[3,4], 3-[1,2,4]]
|
% L = [1-[2], 2-[3,4], 3-[1,2,4]]
|
||||||
|
% ```
|
||||||
|
|
||||||
ugraph_union(Set1, [], Set1) :- !.
|
ugraph_union(Set1, [], Set1) :- !.
|
||||||
ugraph_union([], Set2, Set2) :- !.
|
ugraph_union([], Set2, Set2) :- !.
|
||||||
@@ -232,10 +246,12 @@ ugraph_union(>, Head1, Tail1, Head2, Tail2, [Head2|Union]) :-
|
|||||||
% Unify NewGraph with a new graph obtained by removing the list of
|
% Unify NewGraph with a new graph obtained by removing the list of
|
||||||
% Edges from Graph. Notice that no vertices are deleted. Example:
|
% Edges from Graph. Notice that no vertices are deleted. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- del_edges([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]],
|
% ?- del_edges([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]],
|
||||||
% [1-6,2-3,3-2,5-7,3-2,4-5,1-3],
|
% [1-6,2-3,3-2,5-7,3-2,4-5,1-3],
|
||||||
% NL).
|
% NL).
|
||||||
% NL = [1-[5],2-[4],3-[],4-[],5-[],6-[],7-[],8-[]]
|
% NL = [1-[5],2-[4],3-[],4-[],5-[],6-[],7-[],8-[]]
|
||||||
|
% ```
|
||||||
|
|
||||||
del_edges(Graph, Edges, NewGraph) :-
|
del_edges(Graph, Edges, NewGraph) :-
|
||||||
p_to_s_graph(Edges, G1),
|
p_to_s_graph(Edges, G1),
|
||||||
@@ -243,7 +259,7 @@ del_edges(Graph, Edges, NewGraph) :-
|
|||||||
|
|
||||||
%% graph_subtract(+Set1, +Set2, ?Difference)
|
%% graph_subtract(+Set1, +Set2, ?Difference)
|
||||||
%
|
%
|
||||||
% Is based on ord_subtract
|
% Is based on `ord_subtract/3`
|
||||||
|
|
||||||
graph_subtract(Set1, [], Set1) :- !.
|
graph_subtract(Set1, [], Set1) :- !.
|
||||||
graph_subtract([], _, []).
|
graph_subtract([], _, []).
|
||||||
@@ -263,8 +279,10 @@ graph_subtract(>, Head1, Tail1, _, Tail2, Difference) :-
|
|||||||
%
|
%
|
||||||
% Unify Edges with all edges appearing in Graph. Example:
|
% Unify Edges with all edges appearing in Graph. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- edges([1-[3,5],2-[4],3-[],4-[5],5-[]], L).
|
% ?- edges([1-[3,5],2-[4],3-[],4-[5],5-[]], L).
|
||||||
% L = [1-3, 1-5, 2-4, 4-5]
|
% L = [1-3, 1-5, 2-4, 4-5]
|
||||||
|
% ```
|
||||||
|
|
||||||
edges(Graph, Edges) :-
|
edges(Graph, Edges) :-
|
||||||
s_to_p_graph(Graph, Edges).
|
s_to_p_graph(Graph, Edges).
|
||||||
@@ -309,8 +327,10 @@ s_to_p_graph([Neib|Neibs], Vertex, [Vertex-Neib|P], Rest_P) :-
|
|||||||
% Generate the graph Closure as the transitive closure of Graph.
|
% Generate the graph Closure as the transitive closure of Graph.
|
||||||
% Example:
|
% Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- transitive_closure([1-[2,3],2-[4,5],4-[6]],L).
|
% ?- transitive_closure([1-[2,3],2-[4,5],4-[6]],L).
|
||||||
% L = [1-[2,3,4,5,6], 2-[4,5,6], 4-[6]]
|
% L = [1-[2,3,4,5,6], 2-[4,5,6], 4-[6]]
|
||||||
|
% ```
|
||||||
|
|
||||||
transitive_closure(Graph, Closure) :-
|
transitive_closure(Graph, Closure) :-
|
||||||
warshall(Graph, Graph, Closure).
|
warshall(Graph, Graph, Closure).
|
||||||
@@ -336,12 +356,14 @@ warshall([], _, _, []).
|
|||||||
%
|
%
|
||||||
% Unify NewGraph with a new graph obtained from Graph by replacing
|
% Unify NewGraph with a new graph obtained from Graph by replacing
|
||||||
% all edges of the form V1-V2 by edges of the form V2-V1. The cost
|
% all edges of the form V1-V2 by edges of the form V2-V1. The cost
|
||||||
% is O(|V|*log(|V|)). Notice that an undirected graph is its own
|
% is O(|V|\*log(|V|)). Notice that an undirected graph is its own
|
||||||
% transpose. Example:
|
% transpose. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- transpose([1-[3,5],2-[4],3-[],4-[5],
|
% ?- transpose([1-[3,5],2-[4],3-[],4-[5],
|
||||||
% 5-[],6-[],7-[],8-[]], NL).
|
% 5-[],6-[],7-[],8-[]], NL).
|
||||||
% NL = [1-[],2-[],3-[1],4-[2],5-[1,4],6-[],7-[],8-[]]
|
% NL = [1-[],2-[],3-[1],4-[2],5-[1,4],6-[],7-[],8-[]]
|
||||||
|
% ```
|
||||||
|
|
||||||
transpose_ugraph(Graph, NewGraph) :-
|
transpose_ugraph(Graph, NewGraph) :-
|
||||||
edges(Graph, Edges),
|
edges(Graph, Edges),
|
||||||
@@ -358,8 +380,10 @@ flip_edges([Key-Val|Pairs], [Val-Key|Flipped]) :-
|
|||||||
% Compose NewGraph by connecting the _drains_ of LeftGraph to the
|
% Compose NewGraph by connecting the _drains_ of LeftGraph to the
|
||||||
% _sources_ of RightGraph. Example:
|
% _sources_ of RightGraph. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- compose([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
|
% ?- compose([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
|
||||||
% L = [1-[4], 2-[1,2,4], 3-[]]
|
% L = [1-[4], 2-[1,2,4], 3-[]]
|
||||||
|
% ```
|
||||||
|
|
||||||
compose(G1, G2, Composition) :-
|
compose(G1, G2, Composition) :-
|
||||||
vertices(G1, V1),
|
vertices(G1, V1),
|
||||||
@@ -401,8 +425,10 @@ compose1(=, V1, Vs1, V1, N2, G2, SoFar, Comp) :-
|
|||||||
% acyclic. In the example we show how topological sorting works
|
% acyclic. In the example we show how topological sorting works
|
||||||
% for a linear graph:
|
% for a linear graph:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- top_sort([1-[2], 2-[3], 3-[]], L).
|
% ?- top_sort([1-[2], 2-[3], 3-[]], L).
|
||||||
% L = [1, 2, 3]
|
% L = [1, 2, 3]
|
||||||
|
% ```
|
||||||
|
|
||||||
top_sort(Graph, Sorted) :-
|
top_sort(Graph, Sorted) :-
|
||||||
vertices_and_zeros(Graph, Vertices, Counts0),
|
vertices_and_zeros(Graph, Vertices, Counts0),
|
||||||
@@ -412,8 +438,8 @@ top_sort(Graph, Sorted) :-
|
|||||||
|
|
||||||
%% top_sort(+Graph, -Sorted, ?Tail) is semidet.
|
%% top_sort(+Graph, -Sorted, ?Tail) is semidet.
|
||||||
%
|
%
|
||||||
% The predicate top\_sort/3 is a difference list version of
|
% The predicate `top_sort/3` is a difference list version of
|
||||||
% top\_sort/2.
|
% `top_sort/2`.
|
||||||
|
|
||||||
top_sort(Graph, Sorted0, Sorted) :-
|
top_sort(Graph, Sorted0, Sorted) :-
|
||||||
vertices_and_zeros(Graph, Vertices, Counts0),
|
vertices_and_zeros(Graph, Vertices, Counts0),
|
||||||
@@ -496,13 +522,15 @@ decr_list(Neibs, [_|Vertices], [N|Counts1], [N|Counts2], Zi, Zo) :-
|
|||||||
% Neigbours is a sorted list of the neighbours of Vertex in Graph.
|
% Neigbours is a sorted list of the neighbours of Vertex in Graph.
|
||||||
% Example:
|
% Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- neighbours(4,[1-[3,5],2-[4],3-[],
|
% ?- neighbours(4,[1-[3,5],2-[4],3-[],
|
||||||
% 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
% 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
||||||
% NL = [1,2,7,5]
|
% NL = [1,2,7,5]
|
||||||
|
% ```
|
||||||
|
|
||||||
%% neighbors(+Vertex, +Graph, -Neigbours) is det.
|
%% neighbors(+Vertex, +Graph, -Neigbours) is det.
|
||||||
%
|
%
|
||||||
% Same as neighbours/3
|
% Same as `neighbours/3`.
|
||||||
|
|
||||||
neighbors(Vertex, Graph, Neig) :-
|
neighbors(Vertex, Graph, Neig) :-
|
||||||
neighbours(Vertex, Graph, Neig).
|
neighbours(Vertex, Graph, Neig).
|
||||||
@@ -523,6 +551,7 @@ neighbours(V,[_|G],Neig) :-
|
|||||||
%
|
%
|
||||||
% Can be used to order a not-connected graph as follows:
|
% Can be used to order a not-connected graph as follows:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% top_sort_unconnected(Graph, Vertices) :-
|
% top_sort_unconnected(Graph, Vertices) :-
|
||||||
% ( top_sort(Graph, Vertices)
|
% ( top_sort(Graph, Vertices)
|
||||||
% -> true
|
% -> true
|
||||||
@@ -530,6 +559,7 @@ neighbours(V,[_|G],Neig) :-
|
|||||||
% top_sort(Connected, Ordered0),
|
% top_sort(Connected, Ordered0),
|
||||||
% Ordered0 = [Start|Vertices]
|
% Ordered0 = [Start|Vertices]
|
||||||
% ).
|
% ).
|
||||||
|
% ```
|
||||||
|
|
||||||
connect_ugraph([], 0, []) :- !.
|
connect_ugraph([], 0, []) :- !.
|
||||||
connect_ugraph(Graph, Start, [Start-Vertices|Graph]) :-
|
connect_ugraph(Graph, Start, [Start-Vertices|Graph]) :-
|
||||||
@@ -542,7 +572,7 @@ connect_ugraph(Graph, Start, [Start-Vertices|Graph]) :-
|
|||||||
% Unify Before to a term that comes before Term in the standard
|
% Unify Before to a term that comes before Term in the standard
|
||||||
% order of terms.
|
% order of terms.
|
||||||
%
|
%
|
||||||
% Throws instantiation_error if Term is unbound.
|
% Throws `instantiation_error` if Term is unbound.
|
||||||
|
|
||||||
before(X, _) :-
|
before(X, _) :-
|
||||||
var(X),
|
var(X),
|
||||||
@@ -561,12 +591,13 @@ before(_, 0).
|
|||||||
% _not_ connected in UGraphIn and all edges from UGraphIn removed.
|
% _not_ connected in UGraphIn and all edges from UGraphIn removed.
|
||||||
% Example:
|
% Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- complement([1-[3,5],2-[4],3-[],
|
% ?- complement([1-[3,5],2-[4],3-[],
|
||||||
% 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
% 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
||||||
% NL = [1-[2,4,6,7,8],2-[1,3,5,6,7,8],3-[1,2,4,5,6,7,8],
|
% NL = [1-[2,4,6,7,8],2-[1,3,5,6,7,8],3-[1,2,4,5,6,7,8],
|
||||||
% 4-[3,5,6,8],5-[1,2,3,4,6,7,8],6-[1,2,3,4,5,7,8],
|
% 4-[3,5,6,8],5-[1,2,3,4,6,7,8],6-[1,2,3,4,5,7,8],
|
||||||
% 7-[1,2,3,4,5,6,8],8-[1,2,3,4,5,6,7]]
|
% 7-[1,2,3,4,5,6,8],8-[1,2,3,4,5,6,7]]
|
||||||
%
|
% ```
|
||||||
|
|
||||||
|
|
||||||
% TODO: Simple two-step algorithm. You could be smarter, I suppose.
|
% TODO: Simple two-step algorithm. You could be smarter, I suppose.
|
||||||
@@ -586,8 +617,10 @@ complement([V-Ns|G], Vs, [V-INs|NG]) :-
|
|||||||
% True when Vertices is an ordered set of vertices reachable in
|
% True when Vertices is an ordered set of vertices reachable in
|
||||||
% UGraph, including Vertex. Example:
|
% UGraph, including Vertex. Example:
|
||||||
%
|
%
|
||||||
|
% ```
|
||||||
% ?- reachable(1,[1-[3,5],2-[4],3-[],4-[5],5-[]],V).
|
% ?- reachable(1,[1-[3,5],2-[4],3-[],4-[5],5-[]],V).
|
||||||
% V = [1, 3, 5]
|
% V = [1, 3, 5]
|
||||||
|
% ```
|
||||||
|
|
||||||
reachable(N, G, Rs) :-
|
reachable(N, G, Rs) :-
|
||||||
reachable([N], G, [N], Rs).
|
reachable([N], G, [N], Rs).
|
||||||
|
|||||||
@@ -9,19 +9,21 @@ This library provides reasoning and working with [UUID](https://en.wikipedia.org
|
|||||||
(only version 4 right now).
|
(only version 4 right now).
|
||||||
|
|
||||||
There are three predicates:
|
There are three predicates:
|
||||||
* uuidv4/1, to generate a new UUIDv4
|
|
||||||
* uuidv4\_string/1, to generate a new UUIDv4 in string hex representation
|
* `uuidv4/1`, to generate a new UUIDv4
|
||||||
* uuid\_string/2, to converte between UUID list of bytes and UUID hex representation
|
* `uuidv4_string/1`, to generate a new UUIDv4 in string hex representation
|
||||||
|
* `uuid_string/2`, to converte between UUID list of bytes and UUID hex representation
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
?- uuidv4(X).
|
```
|
||||||
|
?- uuidv4(X).
|
||||||
X = [42,147,248,242,117,196,79,2,129,159|...].
|
X = [42,147,248,242,117,196,79,2,129,159|...].
|
||||||
?- uuidv4_string(X).
|
?- uuidv4_string(X).
|
||||||
X = "428499fc-76e3-4240- ...".
|
X = "428499fc-76e3-4240- ...".
|
||||||
?- uuidv4(X), uuid_string(X, S).
|
?- uuidv4(X), uuid_string(X, S).
|
||||||
X = [173,12,244,152,139,118,64,139,137,4|...], S = "ad0cf498-8b76-408b- ...".
|
X = [173,12,244,152,139,118,64,139,137,4|...], S = "ad0cf498-8b76-408b- ...".
|
||||||
?- uuid_string(X, "61ae692e-eaf6-4199-8dd3-9f01db70a20b").
|
?- uuid_string(X, "61ae692e-eaf6-4199-8dd3-9f01db70a20b").
|
||||||
X = [97,174,105,46,234,246,65,153,141,211|...].
|
X = [97,174,105,46,234,246,65,153,141,211|...].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ uuidv4(Uuid) :-
|
|||||||
%% uuidv4_string(-UuidString).
|
%% uuidv4_string(-UuidString).
|
||||||
%
|
%
|
||||||
% Generates a new UUID v4 (random). It unifies with a string representation of the UUID.
|
% Generates a new UUID v4 (random). It unifies with a string representation of the UUID.
|
||||||
% It is equivalent of calling uuidv4/1 followed by uuid\_string/2.
|
% It is equivalent of calling `uuidv4/1` followed by `uuid_string/2`.
|
||||||
uuidv4_string(String) :- uuidv4(Uuid), uuid_string(Uuid, String).
|
uuidv4_string(String) :- uuidv4(Uuid), uuid_string(Uuid, String).
|
||||||
|
|
||||||
%% uuid_string(?UuidBytes, ?UuidString).
|
%% uuid_string(?UuidBytes, ?UuidString).
|
||||||
|
|||||||
Reference in New Issue
Block a user