Prolog - reload source files - prolog

I just finished creating a game in Prolog using Sicstus.
During the game I use assert's and retract's to update the values of some variables I use.
When the game finishes, if I don't reconsult the source files, and re-run the game, those variables have the same content of the past game, which makes sense.
So what I am asking is if exists some sort of built-in predicate that I can call at the end of the game so it reconsults the source files, establishing the original data of the game. (I know it is a lazy way to do it.)

Perhaps you can remove the default facts from the file and write an initializer predicate that asserts them instead. Then you could retract all of them on a restart and rerun your initializer to set the defaults
– lurker
This was the answer.
Thank you Lurker.

Related

ECLiPSe CLP : Pause between subresults found by search/6 in ic library

(This question regards search/6.)
I was wondering if there is a way -rather than manual tracing- to pause the execution of search/6 every time a new solution for a single variable was found?
I would like to accomplish this to further investigate what is happening during search in constrained models.
For example, if you are trying to solve the classic sudoku problem, and you have written a set of constraints and a print method for your board, it can be useful to print the board after setting the constraints, but before searching, in order to evaluate the strongness of your constraints. However, once search is called to solve the sudoku, you don't really have an overview of the single results being built underneath unless you do a trace.
It would be very useful if something was possible in the likes of:
(this is just an abstract example)
% Let's imagine this is a (very poorly) constrained sudoku board
?- problem(Sudoku),constraint(Sudoku),print(Sudoku).
[[1,3,_,2,_,_,7,4,_],
[_,2,5,_,1,_,_,_,_],
[4,8,_,_,6,_,_,5,_],
[_,_,_,7,8,_,2,1,_],
[5,_,_,_,9,_,3,7,_],
[9,_,_,_,3,_,_,_,5],
[_,4,_,_,_,6,8,9,_],
[_,5,3,_,_,1,4,_,_],
[6,_,_,_,_,_,_,_,_]]
Now for the search:
?- problem(Sudoku),constraint(Sudoku),search_pause(Sudoku,BT),print(Sudoku,BT).
[[1,3,6,2,_,_,7,4,_],
[_,2,5,_,1,_,_,_,_],
[4,8,_,_,6,_,_,5,_],
[_,_,_,7,8,_,2,1,_],
[5,_,_,_,9,_,3,7,_],
[9,_,_,_,3,_,_,_,5],
[_,4,_,_,_,6,8,9,_],
[_,5,3,_,_,1,4,_,_],
[6,_,_,_,_,_,_,_,_]]
Board[1,3] = 6
Backtracks = 1
more ;
Using existing Visualization tools
Have a look at the Visualization Tools Manual. You can get the kind of matrix display you want by adding a viewable_create/2 annotation to your code, and launching a Visualisation Client from TkECLiPSe's Tools-menu.
Using your own instrumented search routine
You can replace the indomain_xxx choice methods in search/6 with a user-defined one where you can print information before and/or after propagation.
If that is not enough, you can replace the whole built-in search/6 with your own, which is not too difficult, see e.g. the ECLiPSe Tutorial chapter on tree search or my answer to this question.
Tracing using data-driven facilities
Using ECLiPSe's data-driven control facilities, you can quite easily display information when certain things happen to your variables. In the simplest case you do something on variable instantiation:
?- suspend(printf("X was instantiated to %w%n",[X]), 1, X->inst),
writeln(start), X=3, writeln(end).
start
X was instantiated to 3
end
Based on this idea, you can write code that allows you to follow labeling and propagation steps even when they happen inside a black-box search routine. See the link for details.

How to set a break-point to a line in debugging prolog?

In Yap, I'm debugging a program and it reads a lot data from a file. I would like to ask whether there are some ways to set a break-point to a LINE in prolog file. I know there is a predicate called spy which allows you to set the program stop at an expected predicate, however if this predicate calls sub-predicates, how can I set a break-point to the sub-predicates? For example:
pA :-
pB,
pC.
How can I set a break-point to stop at pC(in case pC is a built-in predicate) since spy only allows me to set break-point at pA. Thanks very much for your answer.
The current Logtalk git version supports the definition of file line number spy points. YAP is one Prolog backend compilers supported by Logtalk. The feasibility of using the Logtalk debugger for debugging your program depends, however, if it's structured using Prolog modules. If so, it should be possible to compile your Prolog modules as objects by simply changing the file name extensions from Prolog to Logtalk (i.e. from .pl or .yap to .lgt) and using the Logtalk compiling and loading predicates.

How can I reuse a Prolog data structure?

I am writing a small program using Prolog. There is a data structure that I want to reuse, so I tried assigning it to a variable:
CitizenProfile = voter_profile(citizen,not_in_prison).
Then I used it like this:
state(alabama, [CitizenProfile]).
However, I am encountering this error when I compile my file from the console:
**[No permission to modify static_procedure `(=)/2'][1]**
==
I even tried declaring the equal sign dynamic, but that didn't solve anything. :(
:- dynamic (=)/2.
The reason for the error is that it looks to Prolog like you're trying to do this:
=(CitizenProfile, voter_profile(citizen,not_in_prison)).
This looks just like any other fact definition. =/2 could just as easily be foobar/2:
foobar(CitizenProfile, voter_profile(citizen,not_in_prison)).
Now, if we were in the middle of some rule body, this might be a legitimate way to establish a variable binding. Then everything would be culminating in this:
foo :- ...,
CitizenProfile = voter_profile(citizen,not_in_prison),
state(alabama, [CitizenProfile]).
That would be the same as saying this:
foo :- ...,
state(alabama, [voter_profile(citizen,not_in_prison)]).
If this expansion is what you're trying to accomplish, there is unfortunately no way to create shorthand in a fact database like this. You could, as #hardmath says, use assertz/1 to accomplish it, which would look like this:
make_database :-
CitizenProfile = voter_profile(citizen,not_in_prison),
assertz(state(alabama, [CitizenProfile])).
This would be kind of sketchy behavior though, because you're putting static information into the dynamic store. In my experience, one doesn't usually want to build up large structures in the database. It's usually cleaner and easier to build several relations and "join" across them in a relational manner. I'm not sure what all you're going to want here, so this is just a sketch, but this is kind of what I'd expect to see:
voter_profile(voter1, alabama, citizen, not_in_prison).
voter_profile(voter2, alabama, citizen, in_prison).
voter_profile(voter3, new_mexico, citizen, not_in_prison).
rather than what I presume you'd be building (eventually), which I picture more like this:
state(alabama, [voter_profile(citizen,not_in_prison), voter_profile(citizen, in_prison)]).
state(new_mexico,[voter_profile(citizen,not_in_prison)]).
The temptation to create a bunch of lists is understandable, but Prolog's database can't really help you with processing them. You'll wind up resorting to a lot of member/2 and O(N) searching which will add up to pretty bad performance. By default, Prolog will index on the first argument, but each implementation defines some indexing declarations you can use to make it index the second or Nth arguments in addition or instead. You can then use bagof/3 or findall/3 to reconstitute the lists if you need all the results.
Probably what you want is to define a dynamic predicate voter_profile/2 and assertz new facts "dynamically" to be remembered by that predicate store (the clause database). I say "probably" because you haven't made it clear how a state (e.g. Alabama) should be related to a particular citizen profile.
See here for the SWI-Prolog builtin assertz/1 documentation and much more on database mechanisms of SWI-Prolog.

Prolog SWI : Logtalk, How do I load my own project files?

so this week consisted of me installing Logtalk, one of the extensions for Prolog. In this case I'm using Prolog SWI, and I've run into a little snag. I'm not sure how to actually consult my own projects using Logtalk. I have taken a look at the examples that Logtalk comes with in order to understand the code itself, and in doing so I've been able to load them and execute them perfectly. What I don't understand though is what is actually going on when logtalk is loading a file, and how I can load my own projects.
I'll take the "hello_world" example as the point of discussion. The file called hello_world, is located in the examples folder of the Logtalk files. and yet it is consulted like so:
| ?- logtalk_load(hello_world(loader)).
First thing I thought was "that is a functor", looking at what it was doing using trace, I found that it was being called from the library and was being told how to get to the examples folder, where it then opened the "hello_world" folder and then the "loader" file. After which normal compiling happened.
I took a look at the library and couldn't figure out what was going on. I also thought that this can't possibly be the practical route to load user created projects in Logtalk. There was another post that was asking how to do this with SWI as well, but it didn't have any replies and didn't look like any effort had been made to figure the problem out.
Now let me be clear on something, I can use the "consult('...')." command just fine, I can even use "consult" to open my projects, however if I do this the logtalk console doesn't seem to be using any of the logtalk extensions and so is just vanilla prolog. I've used an installer for windows to install logtalk and I know that it is working as I've been looking at the examples that it comes with.
I've tried to find a tutorial but it is very difficult to find much of anything for Logtalk, the most I have found is this documentation on loading from within your project:
logtalk_load/1.
logtalk_load/2.
which I understand like so:
logtalk_load(file). % Top level loading
logtalk_load(folder(file). % Bottom level loading
So to save a huge manual load each time I would have a loader file that will load the other components of my project (which is what the examples for Logtalk do). This bit makes sense to me, I think, how I get to my loader file, doesn't.
Whether or not I have been understanding it correctly or not remains to be seen, but even if I have been understanding it correctly, I'm still lost as to how I load my own projects. Thanks for any help you can give, if you could give an example that'll be best as I do learn from examples quite quickly.
LITTLE UPDATE
You asked if I was using a logtalk console for my program running, and I am, I'm using the one that is provided and referred to during the "QUICK_START" file [Start > Programs > Logtalk > "Logtalk - Prolog-SWI (console)"] I thought to double check if the logtalk add ons were working and tested the "birds" example since it uses objects and is a nice familiar example. Yet again, everything works fine when using the logtalk_load/2 functor.
I took a look at what the library path was referring to a bit more given the feedback given so far. Looking into how logtalk loads files. Set up as it is so far, without changing things logtalk consults a folder which contains a prolog file called libpaths. It is basically how the examples are found, all it is is a part way description for where to get a file from. So when I say "logtalk_load/2" from what I can tell at least I'm going to this file and finding where the folder is that I'm asking for.
Now since I have already placed my own project folder in the examples folder, I promptly added my own folder to the list to test if this would at least be a part way solution to help me understand things a bit more. I added the following to the libpaths.pl file.
logtalk_library_path(my_project, examples('my_project/')).
% The path must end in a / so I have done so
So, I've got my folder path declared, got my folder, and the loader file is what I'll be calling when I use the loader. Without thinking about setting my own lib path folder, I should have enough to get things working and do some practical learning. But alas no, seems my investigation failed and I was returned the following:
ERROR: Unhandled exception: existence_error(library,project_aim)
Not what I wanted to see, I'm back to this library error business. I'm missing a reference to my project folder somewhere but I don't know where else it could need referencing. Running trace on the matter didn't help I simply had the following occur:
Call: (17) logtalk_library_path(my_project, _G943) ? creep
Fail: (17) logtalk_library_path(my_project, _G943) ? creep
ERROR: Unhandled exception: existence_error(library,my_project)
The call is failing, I'm simply not finding a reference where ever it is logtalk is looking. And I'm a novice at best when it comes to these sorts of issues, I've been using computers now for only 3 years and programming for the past 2 in visual studios using c# and c++. At least I've shone some more light on the matter, any more helpful advice given this information?
Please use the official Logtalk support channels for help in the future. You will get timely replies there. Daniel, thanks for providing help to this user.
I assume that you're using Logtalk 2.x. Note that Logtalk 3.x supports relative and full source file paths. In Logtalk 2.x, the logtalk_compile/1-2 (compile to disk) and logtalk_load/1-2 (compile and load into memory) predicates take either the name of a source file (without the .lgt extension) OR the location of the source file to be loaded using "library notation". To use the former you need first to change the current working directory to the directory containing the file. This makes the second option more flexible. As you mention, the hello_world example you cite, can be loaded by typing:
?- logtalk_load(hello_world(loader)).
or:
?- {hello_world(loader)}.
Logtalk 2.x and 3.x also provide integration with some SWI-Prolog features such as consult/1, make/0, edit/0-1, the graphical tracer and the graphical profiler. For example:
?- [hello_world(loader)].
********** Hello World! **********
% [ /Users/pmoura/logtalk/examples/hello_world/hello_world.lgt loaded ]
% [ /Users/pmoura/logtalk/examples/hello_world/loader.lgt loaded ]
% (0 warnings)
true.
To load your own examples and projects, the easiest way is to add a library path to the directory holding your files to the $LOGTALKUSER/settings.lgt file (%LOGTALKUSER%\settings.lgt on Windows) as Daniel explained. The location of the Logtalk user directory is defined by you when using the provided installer. The default is My Documents\Logtalk in Windows. Editing the libpaths.pl file is not a good idea. Use the settings.lgt file preferentially to define your own library paths. Assuming, as it seems to be your case, that you have created a %LOGTALKUSER%\examples\project_aim directory, add the following lines to your %LOGTALKUSER%\settings.lgt file:
:- multifile(logtalk_library_path/2).
:- dynamic(logtalk_library_path/2).
logtalk_library_path(project_aim, examples('project_aim/').
If you have a %LOGTALKUSER%\examples\project_aim\loader.lgt file, you can then load it by typing:
?- {project_aim(loader)}.
Hope this helps.
What makes me uncertain of my answer is just that you claim the usual consult works but not logtalk_load. You do have to run a different program to get to Logtalk than Prolog. In Unix it would be something like swilgt for SWI-Prolog or gplgt for GNU Prolog. I don't have Windows so I can't really tell you what you need to do there, other than maybe make sure you're running a binary named Logtalk and not simply Prolog.
Otherwise I think your basic problem is that in Windows it's hard to control your working directory. In a Unix environment, you'd navigate your terminal over to the directory with your files in it and launch Logtalk or Prolog from there. Then when you name your files they would be in the current directory, so Prolog would have no trouble finding them. If you're running a command-line Prolog, you can probably configure the menu item so that it will do this for you, but you have to know where you want to send it.
You can use the functor notation either to get at subdirectories (so, e.g., foo(bar(baz(bat(afile)))) finds foo\bar\baz\bat\afile.lgt). This you seemed to have figured out, and I can at least corroborate it. This will search in its predefined list of functors, and also in the current directory. But you could launch Logtalk from anywhere and then run, say, assertz(logtalk_library_path(foo, 'C:\foo\bar\baz\bat')). after which logtalk_load(foo(afile)) is going to be expanded to C:\foo\bar\baz\bat\afile.lgt.
Building on that technique, you could put your files in the Logtalk user directory and use $LOGTALKUSER as demonstrated in the documentation. I can't find a definitive reference on where the Logtalk user directory will be on Windows, but I would expect it to be in the Documents and Settings folder for your user. So you could put stuff in there and reference it by defining a new logtalk_library_path like this.
It's nice, but it still leaves you high and dry if you have to keep on re-entering these assertions every time you launch. Fortunately, there is a Logtalk settings file named settings.lgt in your Logtalk user directory which has a chunk of commented-out code near the top:
% To define a "library" path for your projects, edit and uncomment the
% following lines (the library path must end with a slash character):
/*
:- multifile(logtalk_library_path/2).
:- dynamic(logtalk_library_path/2).
logtalk_library_path(my_project, '$HOME/my_project/').
logtalk_library_path(my_project_examples, my_project('examples/')).
*/
You can simply uncomment those lines and insert your own stuff to get a persistent shortcut.
You can also write a plrc file for SWI Prolog to define other things to happen at startup. The other option seems cleaner since it's Logtalk-specific, but a plrc is more general.
Once you have that machinery in place, having a loader file will be a lot more helpful.
NOTE: I don't have Windows to test any of this stuff on, so you may need to make either or both of the following changes to the preceeding:
You may need to use / instead of \ in your paths (or maybe either will work, who knows?). I'd probably try / first because that's how all other systems work.
You may need to use %LOGTALKUSER% instead of $LOGTALKUSER, depending on how Logtalk expands variables.
Hope this helps and I hope you stick with Logtalk, it could use some passionate users like yourself!

How can I change a Prolog Database to be dynamic?

I have the following Database which connects streets via switches:
For Example
switch(r2,w52=s).
switch(w52=s,w53=d).
How can it be determined algorithmically, not through explicit deposit in a data base.??
Any suggestions?
You have several options to create and consult dynamically-generated facts in Prolog.
The basic one is to use meta-predicates such as assert and retract. There predicates add and remove facts from the program. E.g., assert(switch(w52=s,w53=d)) will add a switch clause to your program. You have to declare :- dynamic switch/2. in advance. The downside of using assert is that it does not backtrack. That is, if you asserted some fact in some predicate and it backtracked, the fact is not automatically cleaned up.
Another option is to accumulate these facts inside a list, and then use member/2 or memberchk/2 to check if a given fact is in that list, instead of querying the program. E.g.:
L = [switch(w52=s,w53=d), switch(w53=d,w54=d), ...]
member(switch(w53=A, w54=B), L) % Unifies A=d, B=d
Unlike using assertions, this method will work like any other Prolog predicate.
Finally, you can run a two-phase program. During the first phase, print to a file the terms you calculated and want to serve as facts. That's easy because Prolog supports writing complete terms, no need to format them yourself. Afterwards just consult the file. If you read the facts more often than generate them, this is the most efficient method, since Prolog will compile your file.

Resources