Related
I have a function f that takes a list of items as it's single parameter and returns true if the ordering of the items is accepted or false if the ordering of the items is not accepted.
There exists at least one or more permutations of list l which f(l) returns true.
Function f is a black box (we don't have it's source code) and the type of the elements held by list l are also unknown or generic.
p is a permutation of list l according to user preferences. The most preferred item has index 0 the least preferred item has index l.size()-1
list p will always contain all elements of list l.
The goal is to find a permutation of l let's call it p_accepted where f(p_accepted) returns true and preference p is maximized.
Here's an example
given l = [a, b, c, d, e, f]
given p = [c, a, f, b, e, d]
given f([ a, b, c, d, e, f ]) = false
given f([ c, a, f, b, e, d ]) = false
given f([ d, e, b, f, a, c ]) = true
given f([ f, e, d, c, b, a ]) = true
given f([ c, b, f, a, d, e ]) = true
given f([ a, c, f, b, e, d ]) = true
given f([ anything else ]) = false
the expected output for p_accepted is [c, b, f, a, d, e]
it is accepted because f(p_accepted) returns true and no other permutation of l ranks the item 'c' as high. item 'c' is the most preferred by the user since it has index 0
Implementations in pseudo code or any language are accepted.
[EDIT]
Clarifications
list p will always contain all elements of list l
list l items can only be compared by identity, i.e.: by reference
so an item in list p can be found in list l by l[i] == p[j]
list l items cannot always be compared like in the example where a compare function c might determine that a < b i.e.: c('a', 'b') = 1.
[EDIT 2]
To understand preferences better
Imagine Alice and Bob being forced to do 4 tasks together at the same time in order. [task a, task b, task c, task d].
Alice has one preferred order for doing the tasks [a,b,c,d]. Bob has two preferred orders for doing the tasks [a,c,b,d], [a,d,b,c]. If you are Alice, the function f would return true only for [a,c,b,d] and [a,d,b,c] which are Bob's preferences, since both like to do task a first p_accepted should start with a.
Note that this is an analogy function f does not accept permutations based on multiple user's order preference.
This is a prolog problem that I have to solve. I can't seem to find a starting point.
In a MCQ test where:
each question has 4 choices [a,b,c,d]
each question has only one correct answer (choice)
there are 10 questions
all questions have the same grade value (1 point, totalling 10 points)
4 students have taken this test and we have their grades:
student1: [b, c, b, a, c, c, c, d, c, c] Grade: 7/10
student2: [b, d, c, a, d, d, c, c, a, b] Grade: 6/10
student3: [d, a, b, b, d, d, c, d, a, b] Grade: 5/10
student4: [c, d, c, b, d, b, b, c, a, a] Grade: 3/10
From the informations above I need to write a prolog script that can determine the set of questions that are correct to get a 10/10 grade
We can branch over the possible choices, and do bookkeeping on the score of the students. When we reach the end of the list, then the users need to have the correct score.
We thus can generate lists of choices with:
option(a).
option(b).
option(c).
option(d).
sequence(N, L) :-
length(L, N),
maplist(option, L).
For example for a sequence of two items, we get:
?- sequence(2, L).
L = [a, a] ;
L = [a, b] ;
L = [a, c] ;
L = [a, d] ;
L = [b, a] ;
L = [b, b] ;
L = [b, c] ;
L = [b, d] ;
L = [c, a] ;
L = [c, b] ;
L = [c, c] ;
L = [c, d] ;
L = [d, a] ;
L = [d, b] ;
L = [d, c] ;
L = [d, d].
Next we can make a predicate mark/3 that calculates the score given the hypothetical correct sequence, and the sequence of a student. We thus need to implement something like:
mark([], [], 0).
mark(…, …, …) :-
….
I leave the implementation of mark/3 as an exercise.
Then we thus can find the sequence of correct answers with:
correct(C) :-
sequence(10, C),
mark(C, [b, c, b, a, c, c, c, d, c, c], 7),
mark(C, [b, d, c, a, d, d, c, c, a, b], 6),
mark(C, [d, a, b, b, d, d, c, d, a, b], 5),
mark(C, [c, d, c, b, d, b, b, c, a, a], 3).
You can later optimize the approach to an interleaved generate-and-test and not first generating sequences and then testing these. But I would first start with a simple solution that works.
When I implement this myself, there is exactly one solution. That solution has b as first answer.
You can use library(clfd) and reification, everything is here : https://www.swi-prolog.org/pldoc/man?section=clpfd-reification-predicates
(as already explain on another forum !)
I'm new to constraint-programming (coming from c#) and I'm trying to solve this problem. Unfortunately I don't have a name for this kind of puzzle so I'm not sure what to search for. The closest examples I can find are Nonogram and Tomography puzzles.
Puzzle description:
The player is given an empty game board (varying size) that they must fill with n-colors, using clue patterns for the rows and columns. Each clue pattern is the sequence of colors in that row/col but with consecutive duplicates removed.
Here is an example easy small 4x4 grid with 3 colors:
rbg,rbr,grb,bgbg <- (top-to-bottom column constraints)
_,_,_,_ rgb <- (row constraints)
_,_,_,_ brg
_,_,_,_ b
_,_,_,_ grbg
Solutions (2):
r,r,g,b
b,?,r,g
b,b,b,b
g,r,b,g
? Can be either red or blue but not green.
Pattern examples below.
Examples given 6-length sequences to pattern:
aaaaaa -> a
aabbcc -> abc
abbbbc -> abc
cabbbc -> cabc
bbbaac -> bac
abbaab -> abab
abcabc -> abcabc
Examples given pattern to potential solution sequences:
abc -> abc (3 length solution)
abc -> abcc, abbc, aabc (4 length solutions)
abc -> abccc, abbcc, abbbc, aabbc, aaabc (5 length solutions)
I've tried to solve it in C# or-tools and MiniZinc but the biggest problem I have is building the constraints. I can generate the patterns from a sequence (in c# imperative way) but then how to turn that into a constraint?
How I'm thinking about it: generate all potential sequences from each clue pattern. Then make a constraint for the corresponding row/col that says it must be one of those sequences.
Example from top row in above puzzle: rgb to [4-length sequences] -> rgbb, rggb, rrgb, and then add a constraint for that row: must equal one of these sequences.
Am I thinking about this right? Any smarter ways to do it?
Thanks for any advice.
=====================================
Edit after some progress:
This MiniZinc correctly solves the top row for the pattern abc which has 3 solutions of 4 length: aabc, abbc, abcc.
include "globals.mzn";
array [1..4, 1..4] of var 1..3: colors;
constraint regular(row(colors, 1), 4, 3,
[|
% a, b, c
2,0,0| % accept 'a'
2,3,0| % accept 'a' or 'b' ?
0,3,4| % accept 'b' or 'c' ?
0,0,4| % accept 'c'
|], 1, {4});
% Don't care about rest of grid for now.
constraint forall(i,j in 1..4 where i > 1) (row(colors, i)[j] = 1);
solve satisfy;
output [show(colors)];
However I'm not sure how to handle larger grids with many patterns other than hardcoding everything like this. I will experiment a bit more.
The constraints you are talking about seem to be easily represented as regular expressions. For example your abc example with varying length can be caught using the regular expression abc.*, which requires one a then one b, and then one c, it will accept anything else afterwards.
In MiniZinc these kinds of constraints are expressed using the regular predicate. The regular predicate simulates an automaton with accepting states. By providing the allowed state-transitions the model is constraint.
The example expression abc.* would be enforced by the following constraint item:
% variables considered, nr states, input values
constraint regular(VARS, 4, 1..3, [|
% a, b, c
2,0,0| % accept 'a'
0,3,0| % accept 'b'
0,0,4| % accept 'c'
4,4,4| % accept all
|], 1, {4}); % initial state, accepting states
In Prolog(language), I use DCG form to describe such problems. It is extended BNF form.
So I suggest finding approach with Extended BNF Form in your environment.
SWI-Prolog example:
color_chunk_list(Encoded,Decoded):-
phrase(chunk_list(Encoded),Decoded),
chk_continuity(Encoded).
chunk_list([])-->[].
chunk_list([First|Rest])-->colorrow(First),chunk_list(Rest).
colorrow(Color)-->[Color],colorrow(Color).
colorrow(Color)-->[Color].
chk_continuity([First,Second|Rest]):-First \= Second,chk_continuity([Second|Rest]).
chk_continuity([_]).
In this program, encodings and decodings are bidirectional.
Tests:
?- length(L,4),color_chunk_list([r,g],L).
L = [r, r, r, g] ;
L = [r, r, g, g] ;
L = [r, g, g, g] ;
false.
?- length(L,6),color_chunk_list([a,b,c],L).
L = [a, a, a, a, b, c] ;
L = [a, a, a, b, b, c] ;
L = [a, a, a, b, c, c] ;
L = [a, a, b, b, b, c] ;
L = [a, a, b, b, c, c] ;
L = [a, a, b, c, c, c] ;
L = [a, b, b, b, b, c] ;
L = [a, b, b, b, c, c] ;
L = [a, b, b, c, c, c] ;
L = [a, b, c, c, c, c] ;
false.
?- color_chunk_list(L,[a,a,b,b,c,c]).
L = [a, b, c] ;
false.
?- color_chunk_list(L,[b,r,b,r,r,g,g,b]).
L = [b, r, b, r, g, b] ;
false.
In ECLiPSe, which is prolog based CLP system (not IDE one),
above predicate(color_chunk_list) can be turned into clp constraint
with propia mechanism and can genarate clp propagation.
I'm new to Prolog and trying to figure out how it works. So could anyone help me with the following code:
whatisthis([]).
whatisthis([_, b| L]):- whatisthis(L).
So when would Prolog return 'True' if the query would have the following format:
?- whatisthis(X).
I experimented with some different inputs and the only X that returned 'True' was X = [].
This query is even that declarative that you can query what X will be true:
?- whatisthis(X).
X = [] ;
X = [_G1242, b] ;
X = [_G1242, b, _G1248, b] ;
X = [_G1242, b, _G1248, b, _G1254, b] ;
X = [_G1242, b, _G1248, b, _G1254, b, _G1260, b] ;
X = [_G1242, b, _G1248, b, _G1254, b, _G1260, b, _G1266|...]
If you hit the semicolon ; it will emit the next result. The _Gxxxx parts are unbound variables. You can write anything there.
So every X that is a list of even length where every second element is a b. So the following examples will succeed:
[]
[a, b]
[2, b]
[1, b, 4, b]
[a, b, 1, b]
[f(a,b), b, b(f,a), b]
[1, b, 4, b, 2, b, 5, b]
I have a simple grammar such as
S::=a S b
S::=[] (empty string)
Now i want to write a parser for the above grammar like
cfg('S', [a,'S',b])
which generates a sentence aaabbb by left most derivation.
I'm not good enough to handle dcg/cfg in prolog.
So pls help me with this example so that i can go ahead and try something bigger.
Consider this DCG code:
s-->[].
s-->[a],s,[b].
to run a predicate you defined by DCG you should add two more arguments at the end: the "input" and what it's left. If you want to recognize the whole list you simply put []. So, when you run it you get:
38 ?- s(C,[]).
C = [] ;
C = [a, b] ;
C = [a, a, b, b] ;
C = [a, a, a, b, b, b] ;
C = [a, a, a, a, b, b, b, b] ;
...
If you wanted some sort of "return" string you could add it as an extra arg. To write prolog code in a dcg clause you use {}:
s('')-->[].
s(S)-->
[a],s(SI),[b],
{ atomic_list_concat([a,SI,b],S)}.
and you get:
40 ?- s(R,X,[]).
R = '',
X = [] ;
R = ab,
X = [a, b] ;
R = aabb,
X = [a, a, b, b] ;
R = aaabbb,
X = [a, a, a, b, b, b] ;
R = aaaabbbb,
X = [a, a, a, a, b, b, b, b] ;
R = aaaaabbbbb,
...
we generated all the strings that are recognized by this grammar; usually you just want to check if a string is recognized by the grammar. to do that you simply put it as input:
41 ?- s([a,b],[]).
true
42 ?- s([a,b,b],[]).
false.
note that we put the S::=[] rule first otherwise prolog would fall in a infinite loop if you asked to generate all the solutions. This problem might not be trivial to solve in more complex grammars. To get the solutions you can use length/2:
?- length(X,_),s(X,[]).
X = [] ;
X = [a, b] ;
X = [a, a, b, b] ;
X = [a, a, a, b, b, b] ;
X = [a, a, a, a, b, b, b, b]
even if your code is:
s-->[].
s-->[a],s,[b].