mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 12:53:53 +00:00
Estimated hours taken: 1.75
Branches: main
Delete some unused procedures warned about by --warn-dead-procs.
library/eqvclass.m:
library/integer.m:
library/io.m:
library/list.m:
library/relation.m:
library/string.m:
library/term.m:
Delete the following procedures:
eqvclass.find_partition/3
integer.int_max/0
io.buffer_to_string/3
list.qsort/3
list.partition/4
relation.tsort_2/6
relation.tsort_3/6
string.to_int_list/2,
string.int_list_to_char_list/2,
string.char_list_to_int_list
term.require_equal/2
term.contains_functor/3
term.subterm/2
library/exception.m:
library/set_bbbtree.m:
library/tree234.m:
Comment out unused modes of
exception.wrap_success_or_failure/2
exception.call_goal/2
exception.call_handler/2
Comment out unused di/uo modes of
set_bbbtree.build_node/4
set_bbbtree.{single,double}_rot_{l,r}/4
tree234.insert2/4
tree234.insert3/4
337 lines
12 KiB
Mathematica
337 lines
12 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1995-1997, 1999, 2003 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU Library General
|
|
% Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% File: eqvclass.m.
|
|
% Author: zs.
|
|
% Stability: low.
|
|
%
|
|
% A module for handling equivalence classes.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module eqvclass.
|
|
|
|
:- interface.
|
|
|
|
:- import_module set, list.
|
|
|
|
:- type eqvclass(T).
|
|
|
|
% Create an empty equivalance class.
|
|
|
|
:- pred eqvclass__init(eqvclass(T)).
|
|
:- mode eqvclass__init(out) is det.
|
|
|
|
:- func eqvclass__init = eqvclass(T).
|
|
|
|
% Is this item known to the equivalence class?
|
|
|
|
:- pred eqvclass__is_member(eqvclass(T), T).
|
|
:- mode eqvclass__is_member(in, in) is semidet.
|
|
|
|
% Make an element known to the equivalence class.
|
|
% The element may already be known to the class;
|
|
% if it isn't, it is created without any equivalence relationships.
|
|
|
|
:- pred eqvclass__ensure_element(eqvclass(T), T, eqvclass(T)).
|
|
:- mode eqvclass__ensure_element(in, in, out) is det.
|
|
|
|
:- func eqvclass__ensure_element(eqvclass(T), T) = eqvclass(T).
|
|
|
|
% Make an element known to the equivalence class.
|
|
% The element must not already be known to the class;
|
|
% it is created without any equivalence relationships.
|
|
|
|
:- pred eqvclass__new_element(eqvclass(T), T, eqvclass(T)).
|
|
:- mode eqvclass__new_element(in, in, out) is det.
|
|
|
|
:- func eqvclass__new_element(eqvclass(T), T) = eqvclass(T).
|
|
|
|
% Make two elements of the equivalence class equivalent.
|
|
% It is ok if they already are.
|
|
|
|
:- pred eqvclass__ensure_equivalence(eqvclass(T), T, T, eqvclass(T)).
|
|
:- mode eqvclass__ensure_equivalence(in, in, in, out) is det.
|
|
|
|
:- func eqvclass__ensure_equivalence(eqvclass(T), T, T) = eqvclass(T).
|
|
|
|
% Make two elements of the equivalence class equivalent.
|
|
% It is an error if they are already equivalent.
|
|
|
|
:- pred eqvclass__new_equivalence(eqvclass(T), T, T, eqvclass(T)).
|
|
:- mode eqvclass__new_equivalence(in, in, in, out) is det.
|
|
|
|
:- func eqvclass__new_equivalence(eqvclass(T), T, T) = eqvclass(T).
|
|
|
|
% Test if two elements are equivalent.
|
|
|
|
:- pred eqvclass__same_eqvclass(eqvclass(T), T, T).
|
|
:- mode eqvclass__same_eqvclass(in, in, in) is semidet.
|
|
|
|
% Test if a list of elements are equivalent.
|
|
|
|
:- pred eqvclass__same_eqvclass_list(eqvclass(T), list(T)).
|
|
:- mode eqvclass__same_eqvclass_list(in, in) is semidet.
|
|
|
|
% Return the set of the partitions of the equivalence class.
|
|
|
|
:- pred eqvclass__partition_set(eqvclass(T), set(set(T))).
|
|
:- mode eqvclass__partition_set(in, out) is det.
|
|
|
|
:- func eqvclass__partition_set(eqvclass(T)) = set(set(T)).
|
|
|
|
% Return a list of the partitions of the equivalence class.
|
|
|
|
:- pred eqvclass__partition_list(eqvclass(T), list(set(T))).
|
|
:- mode eqvclass__partition_list(in, out) is det.
|
|
|
|
:- func eqvclass__partition_list(eqvclass(T)) = list(set(T)).
|
|
|
|
% Create an equivalence class from a partition set.
|
|
% It is an error if the sets are not disjoint.
|
|
|
|
:- pred eqvclass__partition_set_to_eqvclass(set(set(T)), eqvclass(T)).
|
|
:- mode eqvclass__partition_set_to_eqvclass(in, out) is det.
|
|
|
|
:- func eqvclass__partition_set_to_eqvclass(set(set(T))) = eqvclass(T).
|
|
|
|
% Create an equivalence class from a list of partitions.
|
|
% It is an error if the sets are not disjoint.
|
|
|
|
:- pred eqvclass__partition_list_to_eqvclass(list(set(T)), eqvclass(T)).
|
|
:- mode eqvclass__partition_list_to_eqvclass(in, out) is det.
|
|
|
|
:- func eqvclass__partition_list_to_eqvclass(list(set(T))) = eqvclass(T).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module map, int, require, set.
|
|
|
|
:- type eqvclass(T) --->
|
|
eqvclass(
|
|
partition_id,
|
|
map(partition_id, set(T)),
|
|
map(T, partition_id)
|
|
).
|
|
|
|
:- type partition_id == int.
|
|
|
|
eqvclass__init(EqvClass) :-
|
|
map__init(PartitionMap),
|
|
map__init(ElementMap),
|
|
EqvClass = eqvclass(0, PartitionMap, ElementMap).
|
|
|
|
eqvclass__is_member(EqvClass, Element) :-
|
|
EqvClass = eqvclass(_NextId, _PartitionMap, ElementMap),
|
|
map__search(ElementMap, Element, _).
|
|
|
|
eqvclass__ensure_element(EqvClass0, Element, EqvClass) :-
|
|
eqvclass__ensure_element_2(EqvClass0, Element, _, EqvClass).
|
|
|
|
:- pred eqvclass__ensure_element_2(eqvclass(T), T, partition_id, eqvclass(T)).
|
|
:- mode eqvclass__ensure_element_2(in, in, out, out) is det.
|
|
|
|
eqvclass__ensure_element_2(EqvClass0, Element, Id, EqvClass) :-
|
|
EqvClass0 = eqvclass(_NextId0, _PartitionMap0, ElementMap0),
|
|
( map__search(ElementMap0, Element, OldId) ->
|
|
EqvClass = EqvClass0,
|
|
Id = OldId
|
|
;
|
|
eqvclass__add_element(EqvClass0, Element, Id, EqvClass)
|
|
).
|
|
|
|
eqvclass__new_element(EqvClass0, Element, EqvClass) :-
|
|
EqvClass0 = eqvclass(_NextId0, _PartitionMap0, ElementMap0),
|
|
( map__search(ElementMap0, Element, _OldId) ->
|
|
error("new element is already in equivalence class")
|
|
;
|
|
eqvclass__add_element(EqvClass0, Element, _, EqvClass)
|
|
).
|
|
|
|
:- pred eqvclass__add_element(eqvclass(T), T, partition_id, eqvclass(T)).
|
|
:- mode eqvclass__add_element(in, in, out, out) is det.
|
|
|
|
eqvclass__add_element(EqvClass0, Element, Id, EqvClass) :-
|
|
EqvClass0 = eqvclass(NextId0, PartitionMap0, ElementMap0),
|
|
Id = NextId0,
|
|
NextId = NextId0 + 1,
|
|
map__det_insert(ElementMap0, Element, Id, ElementMap),
|
|
set__singleton_set(Partition, Element),
|
|
map__det_insert(PartitionMap0, NextId0, Partition, PartitionMap),
|
|
EqvClass = eqvclass(NextId, PartitionMap, ElementMap).
|
|
|
|
eqvclass__ensure_equivalence(EqvClass0, Element1, Element2, EqvClass) :-
|
|
eqvclass__ensure_element_2(EqvClass0, Element1, Id1, EqvClass1),
|
|
eqvclass__ensure_element_2(EqvClass1, Element2, Id2, EqvClass2),
|
|
( Id1 = Id2 ->
|
|
EqvClass = EqvClass2
|
|
;
|
|
eqvclass__add_equivalence(EqvClass2, Id1, Id2, EqvClass)
|
|
).
|
|
|
|
eqvclass__new_equivalence(EqvClass0, Element1, Element2, EqvClass) :-
|
|
eqvclass__ensure_element_2(EqvClass0, Element1, Id1, EqvClass1),
|
|
eqvclass__ensure_element_2(EqvClass1, Element2, Id2, EqvClass2),
|
|
( Id1 = Id2 ->
|
|
error("two elements are already equivalent")
|
|
;
|
|
eqvclass__add_equivalence(EqvClass2, Id1, Id2, EqvClass)
|
|
).
|
|
|
|
:- pred eqvclass__add_equivalence(eqvclass(T), partition_id, partition_id,
|
|
eqvclass(T)).
|
|
:- mode eqvclass__add_equivalence(in, in, in, out) is det.
|
|
|
|
eqvclass__add_equivalence(EqvClass0, Id1, Id2, EqvClass) :-
|
|
EqvClass0 = eqvclass(NextId0, PartitionMap0, ElementMap0),
|
|
map__det_remove(PartitionMap0, Id2, Partition2, PartitionMap1),
|
|
map__lookup(PartitionMap1, Id1, Partition1),
|
|
set__union(Partition1, Partition2, Partition),
|
|
map__set(PartitionMap1, Id1, Partition, PartitionMap),
|
|
set__to_sorted_list(Partition2, Elements2),
|
|
eqvclass__change_partition(Elements2, Id1, ElementMap0, ElementMap),
|
|
EqvClass = eqvclass(NextId0, PartitionMap, ElementMap).
|
|
|
|
:- pred eqvclass__change_partition(list(T), partition_id,
|
|
map(T, partition_id), map(T, partition_id)).
|
|
:- mode eqvclass__change_partition(in, in, in, out) is det.
|
|
|
|
eqvclass__change_partition([], _Id, ElementMap, ElementMap).
|
|
eqvclass__change_partition([Element | Elements], Id, ElementMap0, ElementMap) :-
|
|
map__set(ElementMap0, Element, Id, ElementMap1),
|
|
eqvclass__change_partition(Elements, Id, ElementMap1, ElementMap).
|
|
|
|
eqvclass__same_eqvclass(EqvClass0, Element1, Element2) :-
|
|
EqvClass0 = eqvclass(_NextId0, _PartitionMap0, ElementMap0),
|
|
map__search(ElementMap0, Element1, Id1),
|
|
map__search(ElementMap0, Element2, Id2),
|
|
Id1 = Id2.
|
|
|
|
eqvclass__same_eqvclass_list(_, []).
|
|
eqvclass__same_eqvclass_list(EqvClass, [Element | Elements]) :-
|
|
EqvClass = eqvclass(_NextId, _PartitionMap, ElementMap),
|
|
map__search(ElementMap, Element, Id),
|
|
eqvclass__same_eqvclass_list_2(ElementMap, Elements, Id).
|
|
|
|
:- pred eqvclass__same_eqvclass_list_2(map(T, partition_id),
|
|
list(T), partition_id).
|
|
:- mode eqvclass__same_eqvclass_list_2(in, in, in) is semidet.
|
|
|
|
eqvclass__same_eqvclass_list_2(_, [], _).
|
|
eqvclass__same_eqvclass_list_2(ElementMap, [Element | Elements], Id) :-
|
|
map__search(ElementMap, Element, Id),
|
|
eqvclass__same_eqvclass_list_2(ElementMap, Elements, Id).
|
|
|
|
eqvclass__partition_set(EqvClass0, PartitionSet) :-
|
|
eqvclass__partition_ids(EqvClass0, Ids),
|
|
eqvclass__partitions(EqvClass0, Ids, PartitionList),
|
|
set__list_to_set(PartitionList, PartitionSet).
|
|
|
|
eqvclass__partition_list(EqvClass0, PartitionList) :-
|
|
eqvclass__partition_ids(EqvClass0, Ids),
|
|
eqvclass__partitions(EqvClass0, Ids, PartitionList).
|
|
|
|
% Convert a list of partition ids to a list of partitions.
|
|
|
|
:- pred eqvclass__partitions(eqvclass(T), list(partition_id), list(set(T))).
|
|
:- mode eqvclass__partitions(in, in, out) is det.
|
|
|
|
eqvclass__partitions(_EqvClass0, [], []).
|
|
eqvclass__partitions(EqvClass0, [Id | Ids], [Partition | Partitions]) :-
|
|
eqvclass__id_to_partition(EqvClass0, Id, Partition),
|
|
eqvclass__partitions(EqvClass0, Ids, Partitions).
|
|
|
|
% Get the ids of all the partitions.
|
|
|
|
:- pred eqvclass__partition_ids(eqvclass(T), list(partition_id)).
|
|
:- mode eqvclass__partition_ids(in, out) is det.
|
|
|
|
eqvclass__partition_ids(EqvClass0, Ids) :-
|
|
EqvClass0 = eqvclass(_NextId0, PartitionMap0, _ElementMap0),
|
|
map__keys(PartitionMap0, Ids).
|
|
|
|
% Given an element, get the id of the partition containing that element.
|
|
|
|
% Given a partition id, get the elements of the partition.
|
|
|
|
:- pred eqvclass__id_to_partition(eqvclass(T), partition_id, set(T)).
|
|
:- mode eqvclass__id_to_partition(in, in, out) is det.
|
|
|
|
eqvclass__id_to_partition(EqvClass0, Id, Partition) :-
|
|
EqvClass0 = eqvclass(_NextId0, PartitionMap0, _ElementMap0),
|
|
( map__search(PartitionMap0, Id, PartitionPrime) ->
|
|
Partition = PartitionPrime
|
|
;
|
|
error("partition id not known to equivalence class")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
eqvclass__partition_set_to_eqvclass(SetSet, EqvClass) :-
|
|
set__to_sorted_list(SetSet, ListSet),
|
|
eqvclass__partition_list_to_eqvclass(ListSet, EqvClass).
|
|
|
|
eqvclass__partition_list_to_eqvclass([], EqvClass) :-
|
|
eqvclass__init(EqvClass).
|
|
eqvclass__partition_list_to_eqvclass([Partition | Ps], EqvClass) :-
|
|
eqvclass__partition_list_to_eqvclass(Ps, EqvClass0),
|
|
EqvClass0 = eqvclass(NextId0, PartitionMap0, ElementMap0),
|
|
set__to_sorted_list(Partition, Elements),
|
|
( Elements = [] ->
|
|
NextId = NextId0,
|
|
ElementMap0 = ElementMap,
|
|
PartitionMap0 = PartitionMap
|
|
;
|
|
Id = NextId0,
|
|
NextId = NextId0 + 1,
|
|
eqvclass__make_partition(Elements, Id, ElementMap0, ElementMap),
|
|
map__det_insert(PartitionMap0, Id, Partition, PartitionMap)
|
|
),
|
|
EqvClass = eqvclass(NextId, PartitionMap, ElementMap).
|
|
|
|
:- pred eqvclass__make_partition(list(T), partition_id,
|
|
map(T, partition_id), map(T, partition_id)).
|
|
:- mode eqvclass__make_partition(in, in, in, out) is det.
|
|
|
|
eqvclass__make_partition([], _Id, ElementMap, ElementMap).
|
|
eqvclass__make_partition([Element | Elements], Id, ElementMap0, ElementMap) :-
|
|
map__det_insert(ElementMap0, Element, Id, ElementMap1),
|
|
eqvclass__make_partition(Elements, Id, ElementMap1, ElementMap).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
% Ralph Becket <rwab1@cl.cam.ac.uk> 29/04/99
|
|
% Function forms added.
|
|
|
|
eqvclass__init = EC :-
|
|
eqvclass__init(EC).
|
|
|
|
eqvclass__ensure_element(EC1, X) = EC2 :-
|
|
eqvclass__ensure_element(EC1, X, EC2).
|
|
|
|
eqvclass__new_element(EC1, X) = EC2 :-
|
|
eqvclass__new_element(EC1, X, EC2).
|
|
|
|
eqvclass__ensure_equivalence(EC1, X, Y) = EC2 :-
|
|
eqvclass__ensure_equivalence(EC1, X, Y, EC2).
|
|
|
|
eqvclass__new_equivalence(EC1, X, Y) = EC2 :-
|
|
eqvclass__new_equivalence(EC1, X, Y, EC2).
|
|
|
|
eqvclass__partition_set(EC) = S :-
|
|
eqvclass__partition_set(EC, S).
|
|
|
|
eqvclass__partition_list(EC) = Xs :-
|
|
eqvclass__partition_list(EC, Xs).
|
|
|
|
eqvclass__partition_set_to_eqvclass(S) = EC :-
|
|
eqvclass__partition_set_to_eqvclass(S, EC).
|
|
|
|
eqvclass__partition_list_to_eqvclass(Xs) = EC :-
|
|
eqvclass__partition_list_to_eqvclass(Xs, EC).
|