XPCE Prolog GUI - user-interface

I am working on my first prolog - GUI with XPCE consisting of 10 columns of text items.
However, not all elements of the GUI can be seen: The right two columns are cut off!
I tried adjusting the dialog size, but the size of the dialog does not change. I tried changing the size of the text items, but XPCE seems to reserve the same amount of space for each column regardless of the text item width.
Below is my code:
:- use_module(library(pce)).
t1:-new(D,dialog('GUI', size(200, 200))),
new(H1, dialog_group(' Caption1 ')),
new(HN1, text_item('cn1','')),
send(HN1, width,40),
send(HN1,show_label,false),
send(H1, append, HN1,right),
send(D, append, H1),
new(H2, dialog_group(' Caption2 ')),
column(C1,0,group,"Cpt1",'test1'),
column(C2,1,group,"Cpt2",'test2'),
column(C3,1,group,"Cpt3",'test3'),
column(C4,1,group,"Cpt4",'test4'),
column(C5,1,group,"Cpt5",'test5'),
column(C6,1,group,"Cpt6",'test6'),
column(C7,1,group,"Cpt7",'test7'),
column(C8,1,group,"Cpt8",'test8'),
column(C9,1,group,"Cpt9",'test9'),
column(C10,1,group,"Cpt10",'test10'),
row(RowAll,group,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10),
send(H2,append,RowAll),
send(D, append, H2, below),
send(D,open).
column(C,0,Type,Labeltext1,Labeltext2) :-
new(C,dialog_group('Col1',Type)),
new(Lab1,label(lab_1_0,Labeltext1)),
%send(Lab1,alignment,right),
%get(Lab1,alignment,right),
send(C, append, Lab1),
%send(lab_1_0, alignment, right),
send(C, append, label(lab_1_1,Labeltext2), below),
send(C,gap,size(1,0)),
new(CN1, text_item('cn1','')),
send(CN1, width,20),
send(CN1,show_label,false),
send(C, append, CN1,below),
new(CN2, text_item('cn2','')),
send(CN2, width,20),
send(CN2,show_label,false),
send(C, append, CN2,below),
new(CN3, text_item('cn3','')),
send(CN3, width,20),
send(CN3,show_label,false),
send(C, append, CN3,below),
new(CN4, text_item('cn4','')),
send(CN4, width,20),
send(CN4,show_label,false),
send(C, append, CN4,below),
new(CN5, text_item('cn4','')),
send(CN5, width,20),
send(CN5,show_label,false),
send(C, append, CN5,below),
new(CN6, text_item('cn4','')),
send(CN6, width,20),
send(CN6,show_label,false),
send(C, append, CN6,below).
column(C,1,Type,Labeltext1,Labeltext2) :-
new(C,dialog_group('Col1',Type)),
send(C,gap,size(1,0)),
new(Lab1,label(lab_1_0,Labeltext1)),
send(C, append, Lab1),
send(C, append, label(lab_1_1,Labeltext2), below),
new(CN1, text_item('cn1','')),
send(CN1, width,10),
send(CN1,show_label,false),
send(C, append, CN1,below),
new(CN2, text_item('cn2','')),
send(CN2, width,10),
send(CN2,show_label,false),
send(C, append, CN2,below),
new(CN3, text_item('cn3','')),
send(CN3, width,10),
send(CN3,show_label,false),
send(C, append, CN3,below),
new(CN4, text_item('cn4','')),
send(CN4, width,10),
send(CN4,show_label,false),
send(C, append, CN4,below),
new(CN5, text_item('cn4','')),
send(CN5, width,10),
send(CN5,show_label,false),
send(C, append, CN5,below),
new(CN6, text_item('cn4','')),
send(CN6, width,10),
send(CN6,show_label,false),
send(C, append, CN6,below).
row(R,Type,Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8,Column9,Column10) :-
new(R,dialog_group('ColAll',Type)),
%send(R,gap,size(1,1)),
send(R, append, Column1, right),
send(R, append, Column2, right),
send(R, append, Column3, right),
send(R, append, Column4, right),
send(R, append, Column5, right),
send(R, append, Column6, right),
send(R, append, Column7, right),
send(R, append, Column8, right),
send(R, append, Column9, right),
send(R, append, Column10, right).
Can anyone help me: How may I make everything fit to the screen? Alternatively is there a way to have a horizontal scroll bar for the cases where not everything fits to the screen?
I hope, someone can help me with this! :)
Best regards,
Malo

Related

adjacent involving first and last element, Prolog

HI I would like to know how a method that finds out if two members of a list in Prolog are adjacent as the catch is that the first and the last elements are checked if they are adjacent something like
(b,c,[b,a,d,c])
would give yes they are adjacent. I already have this code
adjacent(X, Y, [X,Y|_]).
adjacent(X, Y, [_|Tail]) :-
adjacent(X, Y, Tail).
but I do not know how to include the head of the list and the last elments as well being compared for being adjacent. If you are really good maybe you can tell me also how it is possible to make something like this
(c,b,[a,b,c,d])
to be true I mean the elements are adjacent no matter which exactly is first.
You can make use of last/2 predicate [swi-doc] to obtain the last element of the list. But you can not use this in the recursive call, since otherwise it will each element in the list pair with the last element as well.
The trick is to make a helper predicate for the recursive part, and then make the adjacent/3 predicate to call the recursive one you wrote yourself, or one where we match with the last element:
adjacent(X, Y, L) :-
adj(X, Y, L).
adjacent(X, Y, [Y|T]) :-
last(T, X).
adj(X, Y, [X,Y|_]).
adj(X, Y, [_|T]) :-
adj(X, Y, T).
Relations about lists can often be described with a Definite Clause Grammar dcg.
A first attempt might be:
adjacent(A, B, L) :-
phrase(adjacent(A, B), L). % interface to DCG
adjacent(A,B) -->
..., ( [A,B] | [B,A] ), ... .
... --> [] | [_], ... .
Yet, this leaves out cases like adjacent(a,d,[a,b,c,d]). One possibility would be to add another rule, or maybe simply extend the list to be considered.
adjacent(A, B, L) :-
L = [E,_|_],
append(L, [E], M),
phrase(adjacent(A, B), L).

Prolog: Why is there a vertical line and underscore in the output [x,y|_]?

I don't understand the output of the following example:
isSpaceCode(32).
makeTerms([], Y, [Y|_].
makeTerms([A|X], Y, Terms) :-
\+(isSpaceCode(A)),
char_code(Out, A),
atom_concat(Y, Out, Neu),
makeTerms(X, Neu, Terms).
makeTerms([A|X], Y, [Y|Terms]) :-
isSpaceCode(A),
makeTerms(X, '', Terms).
When I do the call makeTerms("Foo Too", '', Z) I get the output Z = ['Foo', 'Too'|_]. Why is there a vertical line and an underline after the right output and what does is mean?
Because your makeTerms will, when the list is exhausted, construct an [Y|_], so a "cons" with a variable as tail.
In case the list is exhausted, you should wrap the thus far yielded list in a singleton list:
makeTerms([], Y, [Y]).
makeTerms([A|X], Y, Terms) :-
\+ isSpaceCode(A),
char_code(Out, A),
atom_concat(Y, Out, Neu),
makeTerms(X, Neu, Terms).
makeTerms([A|X], Y, [Y|Terms]) :-
isSpaceCode(A),
makeTerms(X, '', Terms).
You however might want to check if the atom is empty, since in that case, you probably want to yield the empty list:
makeTerms([], '', []).
makeTerms([], Y, [Y]) :-
Y \= ''.
makeTerms([A|X], Y, Terms) :-
\+ isSpaceCode(A),
char_code(Out, A),
atom_concat(Y, Out, Neu),
makeTerms(X, Neu, Terms).
makeTerms([A|X], Y, [Y|Terms]) :-
isSpaceCode(A),
makeTerms(X, '', Terms).
It might be better here to make two predicates: one where there is an atom that is constructed (thus far), and one without. By decoupling the two, you can construct more simple predicates, and use mutual recursion.

Prolog get list from different relations

i´d like to get a list from a graph. The variables with two letters are the points and the one letter is a line. Each line can contain multiple points.
conn(bs, oc, c).
conn(oc, tc, c).
conn(bs, gp, j).
conn(gp, cc, j).
conn(gp, pc, p).
conn(pc, ls, p).
conn(gp, oc, v).
conn(oc, pc, b).
conn(pc, cc, b).
conn(tc, ls, n).
conn(ls, cc, n).
link(X, Y, Z) :- conn(X, Y, Z), !.
link(X, Y, Z) :- conn(Y, X, Z).
Now i want to get a list with all points belonging to a line. By typing:
getpoints(c, X).
i would expect
X = [bs, oc, tc]
This is how i tried to get my result:
getpoints(Line, [First|[]]) :- not(link(First, _Second, Line)).
getpoints(Line, [First|Rest]) :- link(First, _Second, Line), getpoints(Line, Rest).
Does anybody has an idea?
If you aren't interested in a particular order of points, you could use setof/3
By example
getpoints(Line, Points) :-
setof(X, Y^(conn(X, Y, Line) ; conn(Y, X, Line)), Points).
--- EDIT ---
Is it very complicadet to get the order of the points?
If you're point are really a line (not a more general graph), you can write something like
nextLine(Line, EndLine, []) :-
\+ conn(EndLine, _, Line).
nextLine(Line, Start, [NextPoint | NextLine]) :-
conn(Start, NextPoint, Line),
nextLine(Line, NextPoint, NextLine).
getpoints(Line, [Start, NextPoint | NextLine]) :-
conn(Start, NextPoint, Line),
\+ conn(_, Start, Line),
nextLine(Line, NextPoint, NextLine).
The idea is find, in getpoints/2, the Start point of the line, that is the point that is on the left of a conn/3 (conn(Start, NextPoint, Line)) but isn't on the right of a conn/3 (\+ conn(_, Start, Line)).
In this way you have the first two point of the line and, calling nextLine/3 recursively, you detect the following points in the correct order.

Prolog Queue of Tuples/Pairs using List without Duplicates

I am attempting to implement a queue of tuples/pairs for use with an AI in SWI-Prolog. The goal is to first fill the structure with data and then evaluate each element. Each unique (X, Y) pair should be evaluated only once.
Currently, the problem is that my implementation is not a queue but a stack. The function dequeue is also evaluating to false prematurely. Here is a simplified portion of the code I am working with.
:- dynamic([queue/1, destination/2]).
enqueue(X, Y):-
retract(queue(List)),
\+member((X, Y), List),
assert(queue([(X, Y)|List])).
enqueue(_,_).
dequeue:-
retract(queue([(X, Y)|List])),
retractall(destination(_, _)),
assert(queue(List)),
assert(destination(X, Y)).
.........................Actual Code Below.............................
add_to_list_of_dest(X, Y):-
retract(list_of_dest(Stuff)),
\+member((X, Y), Stuff),
assert(list_of_dest([(X, Y)|Stuff])),
format("List of Dest Added : (~d, ", X),
format("~d)~n", Y).
add_to_list_of_dest(X, Y):-
format("Duplicate Element Not Added : (~d, ", X),
format("~d)~n", Y).
choose_destination:-
current_pos(X, Y),
destination(DestX, DestY),
\+(X = DestX),
\+(Y = DestY),
format("Choosing Desination : Currently Travelling~n").
choose_destination:-
retract(list_of_dest([(X, Y)|Stuff])),
retractall(destination(_, _)),
assert(list_of_dest(Stuff)),
assert(destination(X, Y)),
format("Choosing Desination : (~d, ", X),
format("~d)~n", Y).
#ChristianF's answer is fine (+1), though appending to the end of a list will become burdensome for large queues. A well-known alternative uses two stacks. Doing so gives you O(1) insertion and amortized O(1) popping. The trick is having an input stack and an output stack. Assuming the output stack is in the right order, you just return the top item when it's non-empty to pop. If it is empty, take the input stack and reverse it onto the output stack.
% empty_queue(-Queue) is det.
empty_queue(queue([], [])).
% enqueue(+Item, +Queue, -NewQueue) is det.
enqueue(Item, queue(InStack, OutStack), queue([Item|InStack], OutStack)).
% dequeue(+Queue, -Item, -NewQueue) is det.
% Handle the case where the output stack is ready to be used.
dequeue(queue(InStack, [Top|OutStack]), Top, queue(InStack, OutStack)).
% Handle the case where the input and output stacks must be swapped.
dequeue(queue(InStack, []), Top, OutStack) :-
reverse(InStack, NewOutStack),
dequeue(queue([], NewOutStack), Top, OutStack).
You can take advantage of Prolog's non-determinism to make a single predicate with both calling conventions. This makes it work more similarly to append/3:
% queue(+Item, +QueueWithoutItem, -QueueWithItem) is det.
queue(Item, QueueWithoutItem, QueueWithItem) :-
nonvar(Item), nonvar(QueueWithoutItem),
enqueue(Item, QueueWithoutItem, QueueWithItem).
% queue(-Item, -QueueWithoutItem, +QueueWithItem) is semidet.
queue(Item, QueueWithoutItem, QueueWithItem) :-
nonvar(QueueWithItem),
dequeue(QueueWithItem, Item, QueueWithoutItem).
Making a queue is really not hard if you know lists:
%% enqueue(+Queue, +Element, -NewQueue)
enqueue(L, E, L2) :- append(L, [E], L2).
%% dequeue(+Queue, -Element, -NewQueue)
dequeue([H|T], H, T).
Example use:
?- enqueue([], (2,3), L), enqueue(L, (4,5), L2), dequeue(L2, _Ignore, L3).
L = [ (2, 3)],
L2 = [ (2, 3), (4, 5)],
_Ignore = (2, 3),
L3 = [ (4, 5)].
You can use difference_list, wich append in O(1) :
init_queue(U-U).
en_queue(Q, Elem, New_Q) :-
append_dl(Q, [Elem|U]-U, New_Q).
de_queue([H|T]-U, H, T-U).
check_queue(Elem, Q) :-
Q = A-[],
member(Elem, A).
append_dl(A-B, B-C, A-C).

How to connect a button to a function in xpce/prolog

This is a button:
new(B,button(solve, message(#prolog, solve))),
send(D,display,B),
send(D, open),
This is a function:
solve(D, Row, Column) :-
assert(path([[0, 0], [-1, 0]])),
track(Row, Column),
path(P),
show_track(D,P).
How should I do?
Here goes a sample to get you started:
:- use_module(library(pce)).
test:-
new(D, dialog),
new(W, window('Test', size(100, 100))),
send(D, append, new(B,button(solve, message(#prolog, solve, D, 10, 20)))),
send(D, below, W),
send(D, open),
!.
solve(D, Row, Column) :-
writeln(solve(D, Row, Column)).
Basically you have to add the arguments to the message, in this case I used D for the dialog and the constants 10 and 20 for Row and Column, and just print them to console in the solve/3 procedure.

Resources