123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2018-2019 The MOPSA Project. *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License as published *)(* by the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(**
InvRelationSig - Signature of relations with access to inverse images.
*)moduletypeOrderedType=MapExtSig.OrderedTypemoduletypeS=sig(** {2 Types} *)typet(** Represents a relation between a domain and a co-domain.
An element of [t] can be see as a set of bindings, i.e.,
a subset of [dom] * [codom], or as a function from [dom] to
subsets of [codom].
Relations are imutable, purely functional data-structures.
This data-type maintains both the relation and its inverse,
so that we can efficiently compute both the image of a domain
element and the inverse image of a codomain element, at the cost
of slower insersion and removal (to keep the maps consistent).
*)typedom(** An element of the domain. *)typecodom(** An element of the codomain. *)moduleDomSet:SetExtSig.S(** Data-type for sets of domain elements. *)moduleCoDomSet:SetExtSig.S(** Data-type for sets of codomain elements. *)typedom_set=DomSet.t(** A set of elements of the domain. *)typecodom_set=CoDomSet.t(** A set of elements of the codomain. *)typebinding=dom*codom(** A binding. *)(** {2 Construction and update} *)valempty:t(** The empty relation. *)valimage:dom->t->codom_set(** [image x r] is the set of codomain elements associated to [x] in [r]
(possibly the empty set).
*)valinverse:codom->t->dom_set(** [inverse y r] is the set of domain elements associated to [y] in [r]
(possibly the empty set).
*)valset_image:dom->codom_set->t->t(** [set_image x ys r] is a new relation where the image of [x]
has been updated to be [ys].
*)valset_inverse:codom->dom_set->t->t(** [set_inverse y xs r] is a new relation where the inverse of [y]
has been updated to be [xs].
*)valis_image_empty:dom->t->bool(** [is_image_empty x r] returns true if there is a codomain element associated
to [x] in [r]
*)valis_inverse_empty:codom->t->bool(** [is_inverse_empty y r] returns true if there is a domain element associated
to [y] in [r].
*)valis_empty:t->bool(** Whether the relation is empty. *)valsingleton:dom->codom->t(** [singleton x y] is the relation with a unique binding ([x],[y]).
*)valadd:dom->codom->t->t(** [add x y r] returns [r] with a new binding ([x],[y]) added.
Previous bindings to [x] are preserved.
*)valadd_image_set:dom->codom_set->t->t(** [add_image_set x ys r] returns [r] with all the bindings ([x],[y]) for
[y] in the set [ys] added.
Others bindings are preserved.
*)valadd_inverse_set:codom->dom_set->t->t(** [add_inverse_set xs y r] returns [r] with all the bindings ([x],[y]) for
[x] in the set [xs] added.
Other bindings are preserved.
*)valremove:dom->codom->t->t(** [remove x y r] returns [r] with the binding ([x],[y]) removed.
Other bindings are preserved.
*)valremove_image_set:dom->codom_set->t->t(** [remove_image_set x ys r] returns [r] with a all bindings ([x],[y]) for
[y] in the set [ys] removed.
Other bindings are preserved.
*)valremove_inverse_set:codom->dom_set->t->t(** [remove_inverse_set xs y r] returns [r] with a all bindings ([x],[y]) for
[x] in the set [xs] removed.
Other bindings are preserved.
*)valremove_image:dom->t->t(** [remove_image x r] returns [r] with all bindings ([x],[y]) removed.
*)valremove_inverse:codom->t->t(** [remove_inverse y r] returns [r] with all bindings ([x],[y]) removed.
*)valmem:dom->codom->t->bool(** [mem x y r] returns [true] if the binding ([x],[y]) is present in [r].
*)valmem_domain:dom->t->bool(** [mem x r] returns [true] if a binding ([x],-) is present in [r].
*)valmem_codomain:codom->t->bool(** [mem x r] returns [true] if a binding (-,[-]) is present in [r].
*)valof_list:bindinglist->t(** [of_list l] returns a relation constructed from the list of bindings. *)valbindings:t->bindinglist(** [bindings r] lists the bindings in the relation. *)valmin_binding:t->binding(** [min_binding r] returns the smallest binding in [r], for the
lexicographic order of domain and codomain.
Raises [Not_found] if the relation is empty.
*)valmax_binding:t->binding(** [max_binding r] returns the largest binding in [r], for the
lexicographic order of domain and codomain.
Raises [Not_found] if the relation is empty.
*)valchoose:t->binding(** [choose r] returns an arbitrary binding in [r].
Raises [Not_found] if the relation is empty.
*)valcardinal:t->int(** [cardinal r] returns the number of bindings in [r]. *)(** {2 Global operations} *)valiter:(dom->codom->unit)->t->unit(** [iter f r] applies [f x y] to every binding ([x],[y]) of [r]. *)valfold:(dom->codom->'a->'a)->t->'a->'a(** [fold f r acc] folds [acc] through every binding ([x],[y]) in [r] through [f]. *)valmap:(dom->codom->binding)->t->t(** [map f r] returns a relation where every binding ([x],[y]) is replaced
with ([x'],[y'])=[f x y].
The bindings are considered in increasing order for the lexicographic
order sorting through dom first, and then codom.
*)valdomain_map:(dom->dom)->t->t(** [domain_map f r] returns a relation where every binding ([x],[y]) is
replaced with ([f x],[y]).
The bindings are considered in increasing order for the lexicographic
order sorting through dom first, and then codom.
*)valcodomain_map:(codom->codom)->t->t(** [codomain_map f r] returns a relation where every binding ([x],[y])
is replaced with ([x],[f y]).
The bindings are considered in increasing order for the dual lexicographic
order sorting through codom first, and then dom.
*)valfor_all:(dom->codom->bool)->t->bool(** [for_all f r] returns true if [f x y] is true for every binding
([x],[y]) in [r].
The bindings are considered in increasing order for the lexicographic
order sorting through dom first, and then codom.
*)valexists:(dom->codom->bool)->t->bool(** [exists f r] returns true if [f x y] is true for at leat one
binding ([x],[y]) in [r].
The bindings are considered in increasing order for the lexicographic
order sorting through dom first, and then codom.
*)valfilter:(dom->codom->bool)->t->t(** [filter f r] returns a relation with only the bindings ([x],[y])
from [r] where [f x y] is true.
*)(** {2 Set operations} *)valcompare:t->t->int(** Total ordering function that returns -1, 0 or 1. *)valequal:t->t->bool(** Whether the two relations have the exact same set of bindings. *)valsubset:t->t->bool(** [subset r1 r2] returns whether the set of bindings in [s1] is
included in the set of bindings in [s2].
*)valunion:t->t->t(** [union r s] is the union of the bindings of [r] and [s]. *)valinter:t->t->t(** [inter r s] is the intersection of the bindings of [r] and [s]. *)valdiff:t->t->t(** [diff r s] is the set difference of the bindings of [r] and [s]. *)(** {2 Binary operations} *)valiter2:(dom->codom->unit)->(dom->codom->unit)->(dom->codom->unit)->t->t->unit(** [iter2 f1 f2 f r1 r2] applies [f1] to the bindings only in [r1],
[f2] to the bindings only in [r2], and [f] to the bindings in both
[r1] and [r2].
The bindings are considered in increasing lexicographic order.
*)valfold2:(dom->codom->'a->'a)->(dom->codom->'a->'a)->(dom->codom->'a->'a)->t->t->'a->'a(** [fold2 f1 f2 f r1 r2] applies [f1] to the bindings only in [r1],
[f2] to the bindings only in [r2], and [f] to the bindings in both
[r1] and [r2].
The bindings are considered in increasing lexicographic order.
*)valfor_all2:(dom->codom->bool)->(dom->codom->bool)->(dom->codom->bool)->t->t->bool(** [for_all2 f1 f2 f r1 r2] is true if [f1] is true on all the bindings
only in [r1], [f2] is true on all the bindings only in [r2], and [f]
is true on all the bindings both in [r1] and [r2].
The bindings are considered in increasing lexicographic order.
*)valexists2:(dom->codom->bool)->(dom->codom->bool)->(dom->codom->bool)->t->t->bool(** [exists2 f1 f2 f r1 r2] is true if [f1] is true on one binding
only in [r1] or [f2] is true on one binding only in [r2], or [f]
is true on one binding both in [r1] and [r2].
The bindings are considered in increasing lexicographic order.
*)valiter2_diff:(dom->codom->unit)->(dom->codom->unit)->t->t->unit(** [iter2_diff f1 f2 r1 r2] applies [f1] to the bindings only in [r1]
and [f2] to the bindings only in [r2].
The bindings both in [r1] and [r2] are ignored.
The bindings are considered in increasing lexicographic order.
It is equivalent to calling [iter2] with [f = fun x y -> ()],
but more efficient.
*)valfold2_diff:(dom->codom->'a->'a)->(dom->codom->'a->'a)->t->t->'a->'a(** [fold2_diff f1 f2 r1 r2] applies [f1] to the bindings only in [r1]
and [f2] to the bindings only in [r2].
The bindings both in [r1] and [r2] are ignored.
The bindings are considered in increasing lexicographic order.
It is equivalent to calling [fold2] with [f = fun x y acc -> acc],
but more efficient.
*)valfor_all2_diff:(dom->codom->bool)->(dom->codom->bool)->t->t->bool(** [for_all2_diff f1 f2 f r1 r2] is true if [f1] is true on all the bindings
only in [r1] and [f2] is true on all the bindings only in [r2].
The bindings both in [r1] and [r2] are ignored.
The bindings are considered in increasing lexicographic order.
It is equivalent to calling [for_all2] with [f = fun x y -> true], but more efficient.
*)valexists2_diff:(dom->codom->bool)->(dom->codom->bool)->t->t->bool(** [exists2_diff f1 f2 f r1 r2] is true if [f1] is true on one binding
only in [r1] or [f2] is true on one binding only in [r2].
The bindings both in [r1] and [r2] are ignored.
The bindings are considered in increasing lexicographic order.
It is equivalent to calling [exists2] with [f = fun x y -> false], but more efficient.
*)(** {2 Multi-map domain operations} *)(** These functions consider the relation as a map from domain elements
to codomain sets.
*)valiter_domain:(dom->codom_set->unit)->t->unit(** [iter_domain f r] applies [f x ys] for every domain element [x] and
its image set [ys] in [r].
The domain elements are considered in increasing order.
*)valfold_domain:(dom->codom_set->'a->'a)->t->'a->'a(** [fold_domain f r acc] applies [f x ys acc] for every domain element
[x] and its image set [ys] in [r].
The domain elements are considered in increasing order.
*)valmap_domain:(dom->codom_set->codom_set)->t->t(** [map_domain f r] returns a new relation where the image set [ys] of
[x] in [r] is replaced with [f x ys].
The domain elements are considered in increasing order.
*)valmap2_domain:(dom->codom_set->codom_set->codom_set)->t->t->t(** [map2_domain f r1 r2] is similar to [map_domain] but applies [f]
to pairs of image sets [ys1] and [ys2] corresponding to the same
domain element [x] in [r1] and [r2] respectively.
[r1] and [r2] must have the same domain set.
The bindings are passed to [f] in increasing order of domain elements.
*)valmap2o_domain:(dom->codom_set->codom_set)->(dom->codom_set->codom_set)->(dom->codom_set->codom_set->codom_set)->t->t->t(** [map2_domain f1 f2 f r1 r2] is similar to [map2_domain] but accepts
relations with different domain sets. To get a new binding, [f1]
is used for domain elements appearing only in [r1], [f2] for
domain elements appearing only in [r2] and [f] for common domain
elements.
The bindings are passed in increasing order of domain elements.
*)valmap2zo_domain:(dom->codom_set->codom_set)->(dom->codom_set->codom_set)->(dom->codom_set->codom_set->codom_set)->t->t->t(** [map2zo_domain f1 f2 f r1 r2] is similar to [map2o_domain] but
[f] is not called on physically equal image sets.
The bindings are passed in increasing order of domain elements.
*)(** [map_domain f r] returns a new relation where the image set [ys] of
[x] in [r] is replaced with [f x ys].
The domain elements are considered in increasing order.
*)valfor_all_domain:(dom->codom_set->bool)->t->bool(** [for_all_domain f r] returns true if [f x ys] is true for every
domain element [x] and its image set [ys] in [r].
The domain elements are considered in increasing order.
*)valexists_domain:(dom->codom_set->bool)->t->bool(** [exists_domain f r] returns true if [f x ys] is true for at least
one domain element [x] and its image set [ys] in [r].
The domain elements are considered in increasing order.
*)valfilter_domain:(dom->codom_set->bool)->t->t(** [filter_domain f r] returns a new relation restricted to the
domain elements [x] with their image [ys] from [r] such that
[f x ys] is true.
*)valmin_domain:t->dom(** [min_domain r] returns the smallest domain element in [r].
Raises [Not_found] if the relation is empty.
*)valmax_domain:t->dom(** [max_domain r] returns the greatest domain element in [r].
Raises [Not_found] if the relation is empty.
*)valchoose_domain:t->dom(** [choose_domain r] returns any domain element in [r].
Raises [Not_found] if the relation is empty.
*)valcardinal_domain:t->int(** [cardinal r] returns the number of distinct domain elements used in [r]. *)valelements_domain:t->domlist(** [elemets_domain r] returns the list of domain elements used in [r].
The elements are returned in increasing order.
*)(** {2 Multi-map codomain operations} *)(** These functions consider the relation as a map from codomain elements
to domain sets.
*)valiter_codomain:(codom->dom_set->unit)->t->unit(** [iter_codomain f r] applies [f y xs] for every codomain element [y] and
its inverse image set [xs] in [r].
The codomain elements are considered in increasing order.
*)valfold_codomain:(codom->dom_set->'a->'a)->t->'a->'a(** [fold_codomain f r acc] applies [f y xs acc] for every codomain element
[y] and its inverse image set [xs] in [r].
The codomain elements are considered in increasing order.
*)valmap_codomain:(codom->dom_set->dom_set)->t->t(** [map_codomain f r] returns a new relation where the inverse image set [xs] of
[y] in [r] is replaced with [f y xs].
The codomain elements are considered in increasing order.
*)valfor_all_codomain:(codom->dom_set->bool)->t->bool(** [for_all_codomain f r] returns true if [f y xs] is true for every
codomain element [y] and its inverse image set [xs] in [r].
The codomain elements are considered in increasing order.
*)valexists_codomain:(codom->dom_set->bool)->t->bool(** [exists_codomain f r] returns true if [f y xs] is true for at least
one codomain element [y] and its inverse image set [xs] in [r].
The codomain elements are considered in increasing order.
*)valfilter_codomain:(codom->dom_set->bool)->t->t(** [filter_codomain f r] returns a new relation restricted to the
codomain elements [y] with their inverse image [xs] from [r] such that
[f y xs] is true.
*)valmin_codomain:t->codom(** [min_codomain r] returns the smallest codomain element in [r].
Raises [Not_found] if the relation is empty.
*)valmax_codomain:t->codom(** [max_codomain r] returns the greatest codomain element in [r].
Raises [Not_found] if the relation is empty.
*)valchoose_codomain:t->codom(** [choose_codomain r] returns any codomain element in [r].
Raises [Not_found] if the relation is empty.
*)valcardinal_codomain:t->int(** [cardinal r] returns the number of distinct codomain elements used in [r]. *)valelements_codomain:t->codomlist(** [elemets_codomain r] returns the list of codomain elements used in [r].
The elements are returned in increasing order.
*)(** {2 Printing} *)typerelation_printer={print_empty:string;(** Special text for empty relations *)print_begin:string;(** Text before the first binding *)print_open:string;(** Text before a domain element *)print_comma:string;(** Text between a domain and a codomain element *)print_close:string;(** Text after a codomain element *)print_sep:string;(** Text between two bindings *)print_end:string;(** Text after the last binding *)}(** Tells how to print a relation. *)valprinter_default:relation_printer(** Print as set: {(dom1,codom1),...,(domN,codomN)} *)valto_string:relation_printer->(dom->string)->(codom->string)->t->string(** String representation. *)valprint:relation_printer->(out_channel->dom->unit)->(out_channel->codom->unit)->out_channel->t->unit(** Prints to an output_channel (for Printf.(f)printf). *)valfprint:relation_printer->(Format.formatter->dom->unit)->(Format.formatter->codom->unit)->Format.formatter->t->unit(** Prints to a formatter (for Format.(f)printf). *)valbprint:relation_printer->(Buffer.t->dom->unit)->(Buffer.t->codom->unit)->Buffer.t->t->unit(** Prints to a string buffer (for Printf.bprintf). *)end