How to iterate through structure? - prolog

If I have a list like: [atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)], how could I 'iterate' through the elements of one of the atm structures?
For example, for atm(abd, bubu, ha), I would like to write abd, bubu and ha.
The problem is that the structures have variable length.
Is there a way to transform the structure into a list? Thanks.

Using (=..)/2
#TopologicalSort has already given a nice answer, using (=..)/2 to convert a term to a list of functor and arguments.
This obviously solves the immediate problem very generally.
However, it comes with its own drawbacks too: First and most importantly, (=..)/2 is not a general relation. For example, we have:
?- X =.. Y.
ERROR: Arguments are not sufficiently instantiated
This means that we cannot use this construct to generate solutions. It works only if its arguments are sufficiently instantiated.
Second, using (=..)/2 also comes with the time and memory overhead of constructing and representing a list in addition to the term that is already there in a different form. (And, mutatis mutandis, in the other direction too of course.)
Thus, it may be worth to ask: Are there different ways to solve this task? Are they better suited?
Alternative 1: Doing it manually
How do I convert thee? Let me count the ways.
From the example you cite, we must be able to handle—in order of their appearance—terms of the following forms:
atm/3
atm/1
atm/2
atm/4
The point here is that the number of shown cases is finite, and so we can easily handle them all like this:
atm_list(atm(A), [A]).
atm_list(atm(A,B), [A,B]).
atm_list(atm(A,B,C), [A,B,C]).
atm_list(atm(A,B,C,D), [A,B,C,D]).
To convert a list of such terms, you can use maplist/2:
?- Ls = [atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)],
maplist(atm_list, Ls, Lists).
Ls = [atm(abd, bubu, ha), atm(aei), atm(xyz, huhu), atm(aabb, a, e, x)],
Lists = [[abd, bubu, ha], [aei], [xyz, huhu], [aabb, a, e, x]].
A major advantage is that this relation is very general and can also be used to generate answers:
?- atm_list(A, Ls).
A = atm(_27464, _27466, _27468),
Ls = [_27464, _27466, _27468] ;
A = atm(_27464),
Ls = [_27464] ;
A = atm(_27464, _27466),
Ls = [_27464, _27466] ;
A = atm(_27464, _27466, _27468, _27470),
Ls = [_27464, _27466, _27468, _27470].
This is also more efficient than using (=..)/2. Clearly, it can only be done if the number of arising cases is finite. (Exercise: Write a Prolog program that generates clauses for all integers 1..N).
Alternative 2: Using lists
There are several well-known criteria for judging whether lists are an appropriate data structure. For example:
Does the empty list make sense in your use case?
Are there sensible cases for all possible lengths?
etc.
Only you can answer this question for your particular use case, so I only show what it could look like: Suppose you represent your whole initial list as follows:
[[abd,bubu,ha],[aei],[xyz,huhu],[aab,a,e,x]]
Then the whole issue does not even arise, because the elements are already specified as lists. Thus, there is no more need to convert anything.

Sure.
If First is atm(abd,bubu,ha) (for example), this code will split it into a list you can go through.
First =.. List.
Then, List will be [atm, abd, bubu, ha].
IDK if this works in your particular version of PROLOG. I'm using SWI-PROLOG. If not, maybe your version has a similar predicate.
For more information, see http://www.swi-prolog.org/pldoc/doc_for?object=(%3D..)/2 .

Related

Predicate for removing certain terms from compound term in Prolog

I would like to write a Prolog predicate that takes in a compound term as its argument and outputs this compound term with some of the nested terms removed. For example, let's say that I have a compound term:
outer_term(level_one(level_two_a(X), level_two_b(Y)), level_one(level_two_b(Z))).
And I would like to write a predicate extract_terms/2 which would take this term and returned it without occurences of level_two_a/1.
extract_terms(Term, ExtractedTerm) :-
*** Prolog Magic ***.
Is there a built-in (or semi-built-in) way to do this in Prolog? If not, how would I go about doing this? One way that occurs to me would be to use =../2 operator to convert the Term into a list and then somehow use some built-in predicate like subtract/3 to get rid of the predicates that I want. The trouble I have is making this work with list that has nested terms as its items.
I would appreciate any ideas, thank you.
First, a general guideline:
Everything that can be expressed by pattern matching should be expressed by pattern matching.
You have asked a similar question previously, although it was a bit simpler. Still, let us consider the simpler case first: You said a possible instance of a verb phrase would be:
VP = vp(vp(verb(making), adj(quick), np2(noun(improvements))))
and you want to extract the verb. Well, the simplest approach is to use pattern matching, or more generally, unification, like this:
?- VP = vp(vp(verb(making), adj(quick), np2(noun(improvements)))),
VP = vp(vp(Verb, _, _)).
This yields:
Verb = verb(making).
Thus, we have successfully "extracted" verb(making) from such a phrase by virtue of unification.
Now to the slightly more complex task you are considering in this question: At this point, you may wonder whether you have chosen a good representation of your data. Frequent use or even the very necessity of (=..)/2 typically indicates a problem with your representation, since it may mean that you have lost track or control of the possible shapes of your data.
In this concrete case, you state as an example:
outer_term(level_one(level_two_a(X), level_two_b(Y)), level_one(level_two_b(Z))).
and you want to remove occurrences of level_two_a. You can now of course begin to mess with (=..)/2, which requires a conversion of such terms to lists, then some reasoning on these lists, and a second conversion from lists back to such structures. That's not how we want to work with our data. In addition to other drawbacks, it would preclude more general usage patterns that we expect from relations.
Instead, let us fix the data representation so that we can cleanly distinguish the different cases. For example, instead of "hardcoding" the very parameter we need to distinguish the cases inside of a functor, let us make the distinction explicit: We want to be able to distinguish, by pattern matching, level 1 from level 2.
So, the following representation suggests itself:
outer_term([level(1, [level(2, X),
level(2, Y)]),
level(1, [level(2, Z)])]).
This may need some additional attributes, such as a and b, and I leave extending this representation to represent such attributes as an easy exercise. The general idea should be clear though: We have thus achieved a uniform representation about which we can easily reason symbolically.
It is now easy to describe the relation between a (potentially nested) list of such levels and the levels without the "level 2" elements:
without_level_2(Ls0, Ls) :-
phrase(no_level_2(Ls0), Ls).
no_level_2([]) --> [].
no_level_2([L|Ls]) -->
no_level_2_(L),
no_level_2(Ls).
no_level_2_(level(2,_)) --> [].
no_level_2_(level(L,Ls0)) --> [level(L,Ls)],
{ dif(L, 2),
without_level_2(Ls0, Ls) }.
See dcg for more information about this formalism.
Sample query:
?- outer_term(Ts0),
without_level_2(Ts0, Ts).
Yielding:
Ts = [level(1, []), level(1, [])] .
Note that to truly benefit from this representation, you need to obtain it in the first place by using or generating terms of such shapes. Once you have this ensured, you can conveniently stick to pattern matching to distinguish the cases. Among the main benefits of this approach we find convenience, performance and generality. For example, we can use the DCG shown above not only to extract but also to generate terms of this form:
?- length(Ls0, _), without_level_2(Ls0, Ls).
Ls0 = Ls, Ls = [] ;
Ls0 = [level(2, _56)],
Ls = [] ;
Ls0 = Ls, Ls = [level(_130, [])],
dif(_130, 2) ;
Ls0 = [level(_150, [level(2, _164)])],
Ls = [level(_150, [])],
dif(_150, 2) .
This is truly a relation, usable in all directions. For this reason, I have avoided imperative names like "extract", "remove" etc. in the predicate name, because these always suggest a particular direction of use, not doing justice to the generality of the predicate.

How to use member predicate to specify constraints in prolog

I'm trying to write a Prolog program which does the following:
I have some relations defined in the Relations list. (For example: [f1,s1] means f1 needs s1) Depending on what features(f1,f2,f3) are selected in the TargetFeat list, I would like to create Result list using constraint programming.
Here is a sample code:
Relations =[[f1, s1], [f2, s2], [f3, s3], [f3, s4]],
TargetFeat = [f3, f1],
Result = [],
member(f3,TargetFeat) #= member(s3,Result), %One of the constraints
labeling(Result).
This doesn't work because #= works only with arithmetic expressions as operands. What are the alternatives to achieve something like this ?
There are many possible ways to model such dependencies with constraints. I consider in this post CLP(FD) and CLP(B) constraints, because they are most commonly used for solving combinatorial tasks.
Consider first CLP(FD), which is more frequently used and more convenient in many ways. When using CLP(FD) constraints, you again have several options to represent your task. However, no matter which model you eventually choose, you must first switch all items in your representation to suitable entitites that the constraint solver can actually reason about. In the case of CLP(FD), this means switching your entities to integers.
Translating your entities to corresponding integers is very straight-forward, and it is one of the reasons why CLP(FD) constraints also suffice to model tasks over domains that actually do not contain integers, but can be mapped to integers. So, let us suppose you are not reasoning about features f1, f2 and f3, but about integers 0, 1, and 2, or any other set of integers that suits you.
You can directly translate your requirements to this new domain. For example, instead of:
[f1,s1] means: f1 needs s1
we can say for example:
0 -> 3 means: 0 needs 3
And this brings us already very close to CLP(FD) constraints that let us model the whole problem. We only need to make one more mental leap to obtain a representation that lets us model all requirements. Instead of concrete integers, we now use CLP(FD) variables to indicate whether or not a specific requirement must be met to obtain the desired features. We shall use the variables R1, R2, R3, ... to denote which requirements are needed, by using either 0 (not needed) or 1 (needed) for each of the possible requirements.
At this point, you must develop a clear mental model of what you actually want to describe. I explain what I have in mind: I want to describe a relation between three things:
a list Fs of features
a list Ds of dependencies between features and requirements
a list Rs of requirements
We have already considered how to represent all these entitites: (1) is a list of integers that represent the features we want to obtain. (2) is a list of F -> R pairs that mean "feature F needs requirement R", and (3) is a list of Boolean variables that indicate whether or not each requirement is eventually needed.
Now let us try to relate all these entitites to one another.
First things first: If no features are desired, it all is trivial:
features_dependencies_requirements([], _, _).
But what if a feature is actually desired? Well, it's simple: We only need to take into account the dependencies of that feature:
features_dependencies_requirements([F|Fs], Ds, Rs) :-
member(F->R, Ds),
so we have in R the requirement of feature F. Now we only need to find the suitable variable in Rs that denotes requirement R. But how do we find the right variable? After all, a Prolog variable "does not have a bow tie", or—to foreigners—lacks a mark by which we could distinguish it from others. So, at this point, we would actually find it convenient to be able to nicely pick a variable out of Rs given the name of its requirement. Let us hence suppose that we represent Rs as a list of pairs of the form I=R, where I is the integer that defines the requirement, and R is the Boolean indicator that denotes whether that requirement is needed. Given this representation, we can define the clause above in its entirety as follows:
features_dependencies_requirements([F|Fs], Ds, Rs) :-
member(F->I, Ds),
member(I=1, Rs),
features_dependencies_requirements(Fs, Ds, Rs).
That's it. This fully relates a list of features, dependencies and requirements in such a way that the third argument indicates which requirements are necessary to obtain the features.
At this point, the attentive reader will see that no CLP(FD) constraints whatsoever were actually used in the code above, and in fact the translation of features to integers was completely unnecessary. We can as well use atoms to denote features and requirements, using the exact same code shown above.
Sample query and answers:
?- features_dependencies_requirements([f3,f1],
[f1->s1,f2->s2,f3->s3,f3->s4],
[s1=S1,s2=S2,s3=S3,s4=S4]).
S1 = S3, S3 = 1 ;
S1 = S4, S4 = 1 ;
false.
Obviously, I have made the following assumption: The dependencies are disjunctive, which means that the feature can be implemented if at least one of the requirements is satisifed. If you want to turn this into a conjunction, you will obviously have to change this. You can start by representing dependencies as F -> [R1,R2,...R_n].
Other than that, can it still be useful to translate your entitites do integers? Yes, because many of your constraints can likely be formulated also with CLP(FD) constraints, and you need integers for this to work.
To get you started, here are two ways that may be usable in your case:
use constraint reification to express what implies what. For example: F #==> R.
use global constraints like table/2 that express relations.
Particularly in the first case, CLP(B) constraints may also be useful. You can always use Boolean variables to express whether a requirement must be met.
Not a solution but some observations that would not fit a comment.
Don't use lists to represent relations. For example, instead of [f1, s1], write requires(f1, s1). If these requirement are fixed, then define requires/2 as a predicate. If you need to identify or enumerate features, consider a feature/1 predicate. For example:
feature(f1).
feature(f2).
...
Same for s1, s2, ... E.g.
support(s1).
support(s2).
...

Prolog manual or custom labeling

I am currently writing a solver for a floor planning problem in Prolog and have some issues with the labeling part.
The current problem is my constraints are posted but when I launch the labeling, it takes forever to find a solution. I would like to bring in some heuristics.
My question is, how do I manually label my variables ? I am afraid that after defining a clpfd variable like this :
X in Xinf..Xsup
and constraining it, If I do something like :
fd_sup(X, Xmax),
X = Xmax,
...
in my custom label, I won't be using the backtrack ability of Prolog to test the other values of X's domain. Am I wrong ?
Also, is there a smarter way to label my variables than writing custom labeling procedures ? My idea of heuristics would consist in trying extrema of a variable domain alternatively (like max(X), min(X), max(X-1), min(X-1) etc...)
Hope you can help me :)
It is not difficult to write a custom labeling procedure, and with most real problems you will eventually need one anyway in order to incorporate problem-specific heuristics.
The two main components of a labeling procedure are
variable selection: from all the remaining (i.e. not yet instantiated) problem variables, pick one to consider next.
value selection or branching: explore, via backtracking, two or more alternative sub-problems by reducing the chosen variable's domain in (usually) complementary ways.
Using this scheme, the default labeling procedure can be written as
label(Xs) :-
( select_variable(X, Xs, Xs1) ->
branch(X),
label(Xs1)
;
true % done, no variables left
).
select_variable(X, [X|Xs], Xs). % 'leftmost' strategy
branch(X) :- indomain(X).
You can now redefine select_variable/3 to implement techniques such as "first-fail", and redefine branch/1 to try domain values in different orders. As long as you make sure that branch/1 enumerates all of X's domain values on backtracking, your search remains complete.
Sometimes you want to try just one domain value first (say, one suggested by a heuristics), but, if it is no good, not commit to another value immediately.
Let's say that, as in your example, you want to try the maximum domain value first. You could write this as
branch(X) :-
fd_sup(X, Xmax),
(
X = Xmax % try the maximum
;
X #\= Xmax % otherwise exclude the maximum
).
Because the two cases are complementary and cover all possible values for X, your search is still complete. However, because of the second alternative, branch/1 can now succeed with an uninstantiated X, which means you must make sure in the labeling procedure that you don't lose this variable from your list. One possibility would be:
label(Xs) :-
( select_variable(X, Xs, Xs1) ->
branch(X),
( var(X) -> append(Xs1, [X], Xs2) ; Xs2=Xs1 ),
label(Xs2)
;
true % done, no variables left
).
First, always try built-in heuristics. ff is often a good strategy.
For custom labeling strategies, it is often easiest to first convert the domain to a list, then reorder the list, and then simply use member/2 to assign the values of the domain using the new order.
A good building black is dom_integers/2, relating a finite CLP(FD) domain to a list of integers:
:- use_module(library(clpfd)).
dom_integers(D, Is) :- phrase(dom_integers_(D), Is).
dom_integers_(I) --> { integer(I) }, [I].
dom_integers_(L..U) --> { numlist(L, U, Is) }, Is.
dom_integers_(D1\/D2) --> dom_integers_(D1), dom_integers_(D2).
Your specific strategy is easily expressed on a list of such ordered integers, relating these integers to a second list where the values occur in the order you describe:
outside_in([]) --> [].
outside_in([I]) --> [I].
outside_in([First|Rest0]) --> [First,Last],
{ append(Rest, [Last], Rest0) },
outside_in(Rest).
Sample query and result:
?- phrase(outside_in([1,2,3,4]), Is).
Is = [1, 4, 2, 3] ;
false.
Combining this with fd_dom/2 and dom_integers/2, we get (bindings for variables other than X omitted):
?- X in 10..20,
fd_dom(X, Dom),
dom_integers(Dom, Is0),
phrase(outside_in(Is0), Is),
member(X, Is).
X = 10 ;
X = 20 ;
X = 11 ;
X = 19 ;
X = 12 ;
X = 18 ;
etc.
Nondeterminism is preserved by member/2.
Make sure to distinguish labeling strategies from additional propagation. These two aspects are currently a bit mixed in your question.
In SWI-Prolog, there is a predicate called clpfd:contracting/1. It does what you describe: It tries values from the domain boundaries, and removes values that can be seen as inconsistent, i.e., for which it is known that no solution exists.
Therefore, if you have a list of variables Vs, you can try: clpfd:contracting(Vs), and see if this helps.
Note that this can also significantly slow down the search, though on the other hand, also help significantly to reduce the search space before even trying any labeling!
To complement the other answers (one contrasting labeling and propagation, one showing a dedicated labeling method), I now tackle a further very important aspect of this question:
Very often, when beginners complain about the speed of their code, it turns out that their code in fact doesn't even terminate! More efficiency would not help in that case.
Hence, this answer points you towards first ensuring actual termination of your relation.
The best way to ensure termination of CLP(FD) programs is to separate them into 2 parts:
the first, called the core relation, simply posts all constraints.
the second uses labeling/2 to perform the actual search.
Have you done this in your program? If not, please do. When this is done, make sure that the core relation, say solution/2 (where the arguments are: a term denoting the task instance, and the list of variables to be labeled) terminates universally by querying:
?- solution(Instance, Vs), false.
If this terminates, then the following also terminates:
?- solution(Instance, Vs), label(Vs), false.
Of course, in larger tasks, you have no chance to actually witness the termination of the latter query, but a good chance to witness the termination of the first query, because setting up the constraints is often much faster than actually obtaining even a a single solution.
Therefore, test whether your core relation terminates!
This follows up on this previous answer by #mat.
If you have got some more CPU cycles to burn, try shave_zs/1 as defined in this previous answer.
shave_zs/1 kind of works like the auxiliary library predicate clpfd:contracting/1. Unlike contracting/1, however, all values are "up for grabs"—not just the ones at the boundary. YMMV!

In Prolog how can I cut redundant answers

I am working on a dictionary-like program with prolog, and my code goes like this:
define(car,vehicle).
define(car,that).
define(car,has).
define(car,four).
define(car,wheels).
define(wheels,round).
define(wheels,object).
define(wheels,used).
define(wheels,in).
define(wheels,transportation).
defined(X):-define(X,_).
anotherdefined(X):- \+ undefined(X).
undefined(X):- \+define(X,_).
I am trying to write a defined/1 predicate which will give me:
?-defined(X).
X = car ;
X = wheels ;
false.
Yet, my defined/1 gives me X=car. five times (naturally) for everytime it counters define(car,_).
and my anotherdefined/1 gives me only true. What is the method to stop prolog backtracking to the other instances of define(car,_).,and skip to define(wheels,_).?
Edit: I have written the following lines to get the result I want with givedefinedword/1,
listdefined(X):-findall(Y,defined(Y),Z),sort(Z,X).
givedefinedword(X):-listdefined(List),member(X,List).
However since I wanted an efficient predicate (which I will use in many others) it beats the purpose. This predicate does too much process.
Or, Would it be better to use a predicate that modifies the code? say prepares a list of defined words, and modifies it when new definitions are added.
Thanks.
If you change define to relate items and lists, like
definelist(car, [vehicle, that, has, four, wheels]).
% etc.
defined(X) :- definelist(X, _).
then defined will no longer produce duplicates, nor require linear space.
Of course, a query define(X, Y) must now be performed as definelist(X, L), member(Y, L). If you want this to be efficient as well, you may need to duplicate all definitions.
What are you trying to achieve with your program? It seems that you want to have facts in the form:
"A car is a vehicle that has four wheels"
"Wheels are round objects used in transportation" (a bit vague)
How are you going to use these facts? #larsmans suggestion if perfectly fine, if you want to just have your statement as a "sentence". It really depends what you will do with the information though.
Consider structuring the information in your database:
is(car, vehicle).
is(bicycle, vehicle).
is(boat, vehicle).
has(car, wheel(four)).
has(car, motor).
has(bicycle, wheel(two)).
Given this database, you can at least ask a question like, "what vehicles are there?", "does a bicycle have a motor?", or maybe, "how many wheels does a car have?", or "which vehicles have no wheels?"
?- is(X, vehicle).
?- has(bicycle, motor).
?- has(car, wheel(N)).
?- is(X, vehicle), \+ has(X, wheel(_)).
and so on.
Once you have defined your problem better, you can define your data structures better, which will make writing a program to solve your problem easier.

gprolog - Simple way to determine whether one list is a permutation of another

I'm trying to write a prolog program that determines whether one list is a permutation of another. Input is of the form perm(L,M), which will be true if and only if list L is a permutation of list M.
This is for my AI class, so I cannot just use the nifty little permutation predicate that gprolog already provides. Our professor noted that the member predicate might be useful, but any ideas I have that involve it seem to require very tricky and not-so-declarative things (and I'm assuming there is a way to solve this without getting too advanced, since the class is new to prolog.)
Anyway, one way to check would supposedly be to see that L and M are the same size, each L element is in M, and each M element is in L (there's a use of member!). However, this wouldn't be enough for cases like [2,2,4] and [4,4,2], among others.
Another way could be to ensure that the same counts of each element are in the opposite list, but my impression of prolog is that any kind of variable 'memory' is rather difficult business (in fact, it seems that the example programs I see that perform sorts, etc., aren't really manipulating data at all; they're just 'hypothetically' rearranging things and then telling you yes or no...?)
Mentally, one could just sort both lists and check elements side-by-side, but that, among tons of other ways to think of it, seems a little too object-oriented...
Any hints? My biggest trouble seems to be (as mentioned) the fact that doing "operations" seems to be more like asking about them and hoping that things stay true long enough to get where you want.
**UPDATE: gprolog does offer a delete functionality, but it comes with the declarative-related trouble I was expecting, given an attempt like this:
perm([LH|LT], R) :- member(LH,R), delete([LH|LT],LH,R), perm(LT,R).
In the manual, delete is defined like this: "delete(List1, Element, List2) removes all occurrences of Element in List1 to provide List2. A strict term equality is required, cf. (==)/2"
Execution:
{trace}
| ?- perm([1,2,3],[3,1,2]).
1 1 Call: perm([1,2,3],[3,1,2]) ?
2 2 Call: member(1,[3,1,2]) ?
2 2 Exit: member(1,[3,1,2]) ?
3 2 Call: delete([1,2,3],1,[3,1,2]) ?
3 2 Fail: delete([1,2,3],1,[3,1,2]) ?
2 2 Redo: member(1,[3,1,2]) ?
2 2 Fail: member(1,[3,1,2]) ?
1 1 Fail: perm([1,2,3],[3,1,2]) ?
(1 ms) no
**UPDATE 2: I think I might have figured it out! It's kind of verbose, but I have tested it for quite a few cases and haven't found a bad one yet. If someone sees a major issue, please point it out:
perm([],[]).
perm([LH|LT],R) :- length([LH|LT],A), length(R,B), A == B, member(LH,R), select(LH,[LH|LT],X), select(LH,R,Y), perm_recurse(X, Y), !.
perm_recurse([],X). %If we get here, all elements successfully matched
perm_recurse([LH|LT],R) :- member(LH,R), select(LH,[LH|LT],X), select(LH,R,Y), perm_recurse(X, Y), !.
I do like the cut operator..
Always good to define more general predicate and use it in a narrowed fashion:
perm(X,L):- mselect(X,L,[]).
mselect([A|B],L,R):- select(A,L,M), mselect(B,M,R).
mselect([],L,L).
member is no good as it leaves the second list unchanged. delete is no good either as it deletes the multiplicities.
You could use append though. :) It too combines picking and removing:
perm([A|B],L):- length(L,N), between(0,N,I),length(X,I),
append(X,[A],Y), append(Y,Z,L),
append(X,Z,M), perm(B,M).
perm([],[]).
perm(L, M) :- sort(L, X), sort(M, X).
This gets you pretty close and is fully declarative ("two lists are permutations of each other if they have the same sorted representation", but sorting in Prolog removes duplicates). However, it will succeed for cases like perm([1,2], [2,2,2,1]) which I'm not sure if you want. It will handle [2,2,4] and [4,4,2] though, since they both sort to [2,4]. Another solution would be something like this:
perm([], []).
perm([L|Ls], M) :- select(L, M, Ms), !, perm(Ls, Ms).
This version won't succeed for [2,2,4] and [4,4,2], but it will properly fail for [1,2] and [2,2,2,1]. I'm not sure which one you want, but I think one or the other of these is probably correct.
The usual model to follow is inductive.
If you know how to build all permutation of N-1 elements, then all permutations of N elements are obtained inserting the element in all available positions.
A 'trick of the trade' is using the select/3 builtin, that, like member, 'peek' an element, but removes it from the list and 'returns' the smaller list. Those verbs are not really appropriate for Prolog. Let's say that select/3 is a relation among an element, a list containing it, and an identical list where it's missing.
Then let Prolog do all the search... The resulting code is really tiny...
just sort both lists and compare result

Resources