Outputting prolog in Mac - prolog

I have a problem using prolog on a Mac, I figured out how to run it using SWI-Prolog but when I run it, it gives an error and does not give the expected output
Expected output: homer, bart
male(homer).
male(bart).
female(marge).
female(lisa).
female(maggie).
parent(homer, bart).
parent(homer, lisa).
parent(homer, maggie).
parent(marge, bart).
parent(marge, lisa).
parent(marge, maggie).
mother(X, Y) :- parent(X, Y), female(X).
father(X, Y) :- parent(X, Y), male(X).
son(X, Y) :- parent(Y, X), male(X).
daughter(X, Y) :- parent(Y, X), female(X).
?- male(X).
Here is the error I was speaking about earlier
Warning: /Users/[username]/Desktop/simpsons.pl:19:
Warning: Singleton variables: [X]
true.
And instead of outputting homer, bart it outputs true

When programming in Prolog, you put definitions and queries in different places. Definitions go into source files. Queries do not go into source files. You enter them while interacting with the Prolog system in something called the "toplevel" or "prompt" or "shell" or maybe "REPL" (read-eval-print loop).
For example, these are definitions:
male(homer).
male(bart).
female(marge).
female(lisa).
female(maggie).
You have put them in a source file called simpsons.pl. This is correct.
This is not a definition but a query:
?- male(X).
This does not go in a source file. Do not put it in simpsons.pl. Rather, you:
start your Prolog system
load the simpsons.pl file somehow
enter the query male(X). and observe answers
This video: https://www.youtube.com/watch?v=t6L7O7KiE-Q shows these steps with SWI-Prolog on a Mac.
If you are comfortable using a command line, you might also be able to do this simpler. For example, on my (Linux) machine, I can start SWI-Prolog with a command line argument naming a file to be loaded:
$ swipl simpsons.pl
Welcome to SWI-Prolog (threaded, 64 bits, version 7.6.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?-
See that ?-? That is the prompt meaning that the toplevel is now waiting for your input. Here is where you enter your male(X) query. You can use ; or Space to cycle through the various answers:
?- male(X).
X = homer ;
X = bart.

Related

Separating Knowledge Base from Predicates, get "undefined procedure"

Why isn't father/2 recognized and why can't I load a file that calls father/2?
theogony.pl
father(kronos, zeus).
father(zeus, ares).
mythos.pl
consult('theogony.pl').
%% --
%% X is an ancestor of Y
%% --
ancestor(X,Y) :-
father(X,Y).
ancestor(X,Y) :-
ancestor(X,Z),
ancestor(Z,Y).
swipl
?- consult('mythos.pl').
false.
?- consult('theogony.pl').
true.
?- father(X,zeus).
ERROR: Unknown procedure: father/2 (DWIM could not correct goal)
As noted there are two Prolog files with the file type pl. This code works with both files in the same directory, e.g. 'C:/Users/Groot/Example_01'. You can use another directory but be consistent with the directory name.
Directory: 'C:/Users/Groot/Example_01'
File: 'theogony.pl'
:- module(theogony,
[
father/2
]).
father(kronos, zeus).
father(zeus, ares).
Directory: 'C:/Users/Groot/Example_01'
File: 'mythos.pl'
:- module(mythos,
[
ancestor/2
]).
ancestor(X,Y) :-
father(X,Y).
ancestor(X,Y) :-
ancestor(X,Z),
ancestor(Z,Y).
Start SWI-Prolog
Welcome to SWI-Prolog (threaded, 64 bits, version 8.5.15)
...
?-
I know, there is a newer version but this is so basic even the really old versions should work.
Change the working directory.
?- working_directory(_,'C:/Users/Groot/Example_01').
true.
Use consult which is also done using [] to load the Prolog files.
?- [theogony].
true.
?- [mythos].
true.
Run your query.
?- father(X,zeus).
X = kronos.

How to run prolog queries from within the prolog file in swi-prolog?

If I have a prolog file defining the rules, and open it in a prolog terminal in windows, it loads the facts. However, then it shows the ?- prompt for me to manually type something. How can I add code to the file, so that it will actually evaluate those specific statements as if I typed them in?
something like this
dog.pl
dog(john).
dog(ben).
% execute this and output this right away when I open it in the console
dog(X).
Does anyone know how to do this?
Thanks
There is an ISO directive on this purpose (and more): initialization
If you have a file, say dog.pl in a folder, with this content
dog(john).
dog(ben).
:- initialization forall(dog(X), writeln(X)).
when you consult the file you get
?- [dog].
john
ben
true.
Note that just asserting dog(X). doesn't call dog(X) as a query, but rather attempts to assert is as a fact or rule, which it will do and warn about a singleton variable.
Here's a way to cause the execution the way you're describing (this works for SWI Prolog, but not GNU Prolog):
foo.pl contents:
dog(john).
dog(ben).
% execute this and output this right away when I open it in the console
% This will write each successful query for dog(X)
:- forall(dog(X), (write(X), nl)).
What this does is write out the result of the dog(X) query, and then force a backtrack, via the false call, back to dog(X) which will find the next solution. This continues until there are no more dog(X) solutions which ultimately fails. The ; true ensures that true is called when dog(X) finally fails so that the entire expression succeeds after writing out all of the successful queries to dog(X).
?- [foo].
john
ben
true.
You could also encapsulate it in a predicate:
start_up :-
forall(dog(X), (write(X), nl)).
% execute this and output this right away when I open it in the console
:- start_up.
If you want to run the query and then exit, you can remove the :- start_up. from the file and run it from the command line:
$ swipl -l foo.pl -t start_up
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.2.3)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.
For help, use ?- help(Topic). or ?- apropos(Word).
john
ben
% halt
$
dog.pl:
dog(john).
dog(ben).
run :- dog(X), write(X).
% OR:
% :- dog(X), write(X).
% To print only the first option automatically after consulting.
Then:
$ swipl
1 ?- [dog].
% dog compiled 0.00 sec, 4 clauses
true.
2 ?- run.
john
true ; # ';' is pressed by the user
ben
true.
3 ?-

How do I access command line arguments in SICStus Prolog?

I'm trying to create a cmd (batch) file that will compile and build a Prolog program using SICStus.
I have the cmd code here:
call "c:\Program Files (x86)\SICStus Prolog VC12 4.3.2\bin\sicstus.exe" -l build_program.pl
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat"
call "C:\Program Files (x86)\SICStus Prolog VC12 4.3.2\bin\spld.exe" --output="program.exe" --static "program.sav"
And the build_program.pl is:
:- set_prolog_flag(unknown, fail).
:- set_prolog_flag(redefine_warnings, off).
:- nl, nl, nl.
:- prolog_flag(argv, Args).
:- write(Args).
:- prolog:set_current_directory('source/program').
:- compile(program).
:- nl, nl, nl.
:- halt.
Now I know I can send arguments to SICStus using -a but I'm not sure what is the correct way to send them or to access them.
As you can see in build_program.pl I have tried ...
:- prolog_flag(argv, Args).
:- write(Args).
... but the output was _282447 so I don't think I'm doing it the right way.
How about the following?
:- current_prolog_flag(argv, Arguments), writeq(Arguments), nl.
Make sure you use the same variable twice in one clause! So far, you are having a scoping issue: you have two clauses using distinct variables having the same name.
If you want to access the first item of list Args, add an additional goal Args = [A1|_] like so:
:- current_prolog_flag(argv, Args), Args = [A1|_], writeq(first_arg = A1), nl.

Redirect SWI-Prolog console output to a file

I'm trying to write output from make_tests to a file, but nothing I've tried seems to insert the correct information in the output file.
I've looked at SWI documentaion at http://www.complang.tuwien.ac.at/SWI-Prolog/Manual/IO.html and have tried a whole bunch of those predicates but none have worked.
Here's what I'm trying to do:
:- use_module(library(test_wizard)).
init_test_file(FILE) :-
set_prolog_flag(log_query_file, FILE).
gen_test_in(FILE) :-
make_tests(lists, FILE, current_output).
So running this (in console) for example:
init_test_file('mytest.pro').
member(a, [a,b]).
gen_test_in('mytest.pro').
I get the following output (in console):
true.
6 ?- gen_test_in('r.pro').
:- begin_tests(lists).
test(member, [nondet]) :-
member(a, [a, b]).
:- end_tests(lists).
true.
How do I get this same output (starting at begin_tests and ending at end_tests in a text file?
I tried doing things like modifying gen_test_in to:
gen_test_in(FILE) :-
open(FILE, write, Out),
make_tests(lists, FILE, Out),
close(Out).
But I just get an empty text file.
You are messing up the arguments here. The library you are using, library(test_wizard), is meant for generating tests from queries. In the predicate you are using, make_tests/3, you have the following three arguments:
The module
The file from which the queries are read
The stream to which the generated tests are written
In the examples you use, you either set your output stream to be current_output (so standard output if you are on the top level), or, in the last example you give, you are opening the file you want to read for writing, and then pass the file and its handle to make_tests/3. Instead, if you have a file called queries.pl:
$ cat queries.pl
member(a, [a,b]).
member(X, [a,b]).
Then:
$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.16-36-g42820df)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.
For help, use ?- help(Topic). or ?- apropos(Word).
?- use_module(library(test_wizard)).
true.
?- setup_call_cleanup(open('lists.plt', write, Out),
make_tests(lists, 'queries.pl', Out),
close(Out)).
Out = <stream>(0xe59ef0).
?- halt.
$ cat lists.plt
:- begin_tests(lists).
test(member, [nondet]) :-
member(a, [a, b]).
test(member, [all(A==[a, b])]) :-
member(A, [a, b]).
:- end_tests(lists).

SWI-Prolog - Fail to Assert

I define an operator as follows:
:- op(500, xfx, =>).
When I try something like:
assert(a => b).
Prolog raises an error that says 'No permission to modify static_procedure (=>)/2'.
Any solution?
As a security, you have to warn SWI that you are going to modify a predicate at runtime:
:- dynamic (=>)/2.
put at the top of the file should do it.
You must have meant another symbol in place of (=>)/2. Probably (->)/2 which is a control construct that cannot be modified.
Welcome to SWI-Prolog (Multi-threaded, 32 bits, Version 6.1.3-116-gf1c7e06)
...
?- asserta((a -> b)).
ERROR: asserta/1: No permission to modify static procedure `(->)/2'
ERROR: Defined at /opt/gupu/pl-devel/lib/swipl-6.1.3/boot/init.pl:194
?- op(500, xfx, =>).
true.
?- asserta(a => b).
true.

Resources