colour
again. To save you from typing in the query,
you can use the up-arrow on your keyboard to step back to a previous query.
Type return when colour
appears in the query window again.![]()
Figure 5.2: The Tracer Tool
The tracer tool traces the execution of the program, like the traditional Prolog debugger, it stops at `debug ports' of predicates that are executed.
The trace lines displayed by the tracer has the following:
+(22) 14 *EXIT<3> inform_colour(1, 1) 1 2 3 4 5 6 7
- A '+' displayed here shows that the procedure has a spy point set. For a CALL port, a '#' could be displayed in this position, which shows a breakpoint is set for the call.
- The invocation number of this goal, which uniquely identifies it. The `To Invoc:' button can be used to jump to the next port with the specified invocation number.
- The depth of the goal, i.e. the number of its ancestors. The `To Depth:' button can be used to jump to the next port within the specified depth range.
- An asterisk before an EXIT means that this procedure is nondeterministic and that it might be resatisfied.
- The type of the port. The `To Port:' button can be used to select the type of port to jump to.
- This only appears if the goal is executing at a different priority than 12, the normal priority. The number is the priority that the goal is executed at.
- The goal is printed according to the current instantiations of its variables.
Figure 5.3: Debugger Trace Line
colour
. The buttons in
the middle of the tool are for debugger commands. Try pressing
Creep several times, and you should observe something similar to
Figure 5.2. Unlike the traditional debugger, the execution trace
is shown on two text windows: the bottom `Source Context' view, showing the
execution of the program in the context of the source, highlighting the
body goal that corresponds to the goal at the debug port; and the
top `Call Stack' window, showing the ancestors (`call stack') of the
current goal, which is updated at each debug port. The goals are
displayed with different colours: blue for a call port, green (success) for
an exit port. Red (failure) for a fail port. Note that in the call
stack, the ancestor goals are displayed in black: this indicates that the
goal is not `current', i.e. the bindings shown are as they were when the
goal was called, and not necessarily what they are now. We will show how
these bindings can be `refreshed' later on. Note that the bottom windowc
can ne switched between the source context view, and a more traditional
`Trace Log' view, which shows a log of the debugger ports much as a traditional Prolog debugger does.spy/1
predicate. However, we can also use
the predicate browser tool: start the Predicate Browser tool
from the Tools menu of TkECLiPSe. This tool allows you to observe
and change various properties of the predicates in your program.
A list of predicates are displayed
on the left hand side, and a list of properties on the right.
Currently the predicate list is showing all the predicates defined in our program (i.e. in
the eclipse
module). Looking at this list,
not_same_colour/3
's name suggests that
it checks that neighbouring countries do not have the same colour.
Select it by clicking on it, and now the right
hand side should display the properties of this predicate:
not_same_colour(Solver, C1-C2, Countries) :- % get the colours for the countries C1 and C2 arg(C1, Countries, Colour1), arg(C2, Countries, Colour2), % send constraint to either the fd or ic solver Solver: (Colour1 # |
C1
and C2
do
not have the same colour.
|
The filter tool opens in a new window, as shown in Figure 5.4. This tool allows us to specify a `filter' for the debug ports so that the tracer will only stop at a port with the properties specified by the tool. In our case, we want to see![]()
Figure 5.4: The Tracer Filter Tool
not_same_colour/3
only when countries 3 and 4 are involved. This can be done
with the “Predicate specification” facility, enabled by the
Specific predicate instance: radio button. Pressing this button
will allow us to specify a condition in Prolog syntax which will be
checked at each debug port. For our purpose, we enter the following:not_same_colour/3
goal, when one of the countries in the pair X-Y
is country 4: the Goal template is used to specify the template the debug port goal should
match, and the Condition: can be any ECLiPSe goal, perhaps with variables
from the Goal template, as in our case. The test is done by unifying
the goal with the template, and then executing the condition. Note that any
bindings are undone after the test. not_same_colour/3
goal
involving country 4 as expected. However, there is a gap in the call stack
as we skipped over the tracing of some ancestor goals. We can see these
goals by refreshing the goal stack. This can be done by pressing and
holding down the right mouse button while the mouse cursor is over a goal
in the call stack, which will popup a menu for the goal:not_same_colour/3
, and the
options are for this goal. Various options are available, but for now we
choose the Refresh goal stack option. This will result in the
following goal stack display:not_same_colour/3
, i.e. 3-4
or 4-3
are never passed
to not_same_colour/3
. Looking at the call stack, we can see that the
country pair in not_same_colour/3
seem to appear as an element in a
list of country pairs, as far back as colouring(...)
. Unfortunately,
the debugger does not display the whole list. We see something like:do_colouring(prolog, input_order, indomain, [4 - 2, 4 - 1, ...
do_colouring(...)
goal
to `open' it for inspection.do_colouring
goal. The
inspector displays the term in a hierarchical fashion as a tree, which
allows us to navigate the term. The initial display is shown on the left
panel below. We are interested in examining the full list. We can look at
this list by double clicking on it to expand the node, which results in the
display in the right panel below. You may need to scroll
down to see the whole list:4-3
or
3-4
, which should be there so that not_same_colour
can check that these two countries are not assigned the same colour.do_colouring(prolog,...)
, as the next parent
colouring(prolog,...)
does not have this list. So the list
is created in a body goal of colouring(...)
before do_colouring(...)
is
called. We can look at the source of colouring(...)
to see how this
list is created. To do this, we can
select Display source option from the popup menu for the
colouring(...)
goal:
do_colouring
:
colouring1(Type, Select, Choice0, N, Backtracks) :- .... findall(C1-C2, (neighbour(C1,C2), C1=<N,C2=<N), Neighbours), .... do_colouring(Type, Select, Choice, Neighbours, Countries, CountryList, Backtracks), .... |
neighbour/2
calls. Let's look at the
source for neighbour/2
. We can do this from the predicate browser, by
selecting neighbour/2
and pushing the Show source button. We see
the following:
neighbour / 2 in file buggy_data.map, line 2: %neighbour(4, 3). neighbour(4, 2). neighbour(4, 1). neighbour(4, 2). neighbour(3, 1). neighbour(3, 2). neighbour(1, 2). |
neighbour(4,3)
was indeed missing (it is commented out).
Another way to check neighbour/2
, without looking at the source,
would be using the
Simple Query tool. This tool is again started from TkECLiPSe's
Tools menu. It can be used to send simple queries to ECLiPSe,
even while another query is being executed (as we are here, executing the
colour
query). We can use this tool to check if neighbour(4,3)
or neighbour(3,4)
are defined or not:neighbour(4,3)
, followed by neighbour(3,4)
, and
both failed, indicating that there is no neighbour relationship defined
between countries 3 and 4.buggy_data.map
and adding the neighbour(4, 3) line back.
TkECLiPSe does not provide an integrated editor itself, so you need to use
some external editor, such as emacs, vi, or wordpad to edit the program.
You can tell ECLiPSewhich editor you want to use, so that you can invoke
the editor from within ECLiPSe. For example, from the source context view
window of the tracer, you can invoke an editor to edit the file being
displayed. Holding down your right mouse button in the source context window will popup a menu, as shown in figure 5.5. Select “Edit this file” option will invoke your specified editor to edit the file, and if possible, the file will be opened showing the line where your mouse pointer was when you popup the menu (line 24 in this example).![]()
Figure 5.5: Invoking an editor
|
In TkECLiPSe, you can usually perform these operations on an object while the mouse cursor is over it: Right-mouse button functionality are alternatively available through the left-mouse button with the control key pressed.
- left-click
- selects the object.
- double (left)-click
- `opens' the object. This can mean expanding it (e.g. in the inspector), or calling the inspector on it (e.g. on a goal in the call stack), or showing the source for a goal (e.g. in the source context view).
- Right-click and hold
- Opens a menu which gives further option/information on the object.
Figure 5.6: Mouse Button Operations on Objects
- Compile scratch pad
- allow simple programs to be written and compiled. Equivalent to [user] in command line ECLiPSe.
- Source file manager
- manage source files for this ECLiPSe session.
- Predicate browser
- view/change properties of predicates.
- Delayed goals
- view delayed goals.
- Tracer
- debugger for ECLiPSe programs.
- Inspector
- term inspector. Useful for viewing large terms.
- Visualisation client
- start a visualisation client.
- Global settings
- view/change global ECLiPSe settings.
- Statistics
- show statistics. Information is updated dynamically.
- Simple query
- send simple queries to ECLiPSe.
- Library browser and help
- interface to ECLiPSe documentation.
- TkECLiPSe preference editor
- view/change TkECLiPSe settings.
Figure 5.7: Available Development tools