In: Computer Science
Sets can be though of as lists that don't contain any repeated elements. For example, [a,4,6] is a set, but [a,4,6,a] is not (as it contains 2 occurrences of a). Write a Prolog program, powerset/2 that generates the set of all subsets of a list in sorted order. (Note the input list may not, itself, be a set.) Example1: powerset([a,b],X). should yield: X = [[],[a],[a,b],[b],[b,a]]. Example2: powerset([a,b,a],X). should also yield (note input list is not actually a set): X = [[],[a],[a,b],[b],[b,a]]. Example3: powerset([a,b,a,c],X). should yield: X = [[], [a], [a, b], [a, b, c], [a, c], [a, c, b], [b], [b, a], [b, a, c], [b, c], [b, c, a], [c], [c, a], [c, a, b], [c, b], [c, b, a]]. Also, the predicate should terminate execution immediately after producing its first (and only) solution.
| %% ?- subset([a,b],[a,b,c]) | |
| %% yes | |
| %% ?- subset([c,b],[a,b,c]) | |
| %% yes | |
| %% ?- subset([],[a,b,c]) | |
| %% yes | |
| %% Your program should be capable of generating all subsets of an input set by | |
| %% backtracking. For example, if you give it as input | |
| %% ?- subset(X,[a,b,c]) | |
| %% it should successively generate all eight subsets of [a,b,c]. | |
| %% Generates all subsets of the given set (once each) | |
| %% base case | |
| subset_gen([], []). | |
| %% inductive case | |
| subset_gen(Subset, [H | Set]) :- subset_gen(Subset, Set). | |
| subset_gen([H |Subset], [H | Set]) :- subset_gen(Subset, Set). | |
| %% Checks if the first argument is a subset of the second | |
| %% base case | |
| subset_check([], _). | |
| %% inductive case | |
| subset_check([H | Subset], Set) :- | |
| member(H, Set), | |
| subset_check(Subset, Set). | |
| %% main | |
| subset(Subset, Set) :- | |
| var(Subset), | |
| subset_gen(Subset, Set). | |
| subset(Subset, Set) :- | |
| nonvar(Subset), | |
| subset_check(Subset, Set). | |
| %% 2. Using the subset predicate you have just written, and findall/3 , write a | |
| %% predicate powerset/2 that takes a set as its first argument, and returns the | |
| %% powerset of this set as the second argument. (The powerset of a set is the | |
| %% set of all its subsets.) For example: | |
| %% ?- powerset([a,b,c],P) | |
| %% should return | |
| %% P = [[],[a],[b],[c],[a,b],[a,c],[b,c],[a,b,c]] | |
| %% It doesn’t matter if the sets are returned in some other order. For example, | |
| %% P = [[a],[b],[c],[a,b,c],[],[a,b],[a,c],[b,c]] | |
| %% is fine too | |
| %% main | |
| powerset(Set, Powerset) :- setof(Subset, subset(Subset, Set), Powerset). |