In general you will find that logic-bases are generally 'flat'. This means that most rules won't depend on multiple layers of distilled facts. So debugging the rules is generally straight-forward.
The most common problem you will encounter is typing errors in your logic-base. The two most likely will be missing the period at the end of a rule or output function, and forgetting to quote facts and values that do not start with a lowercase letter, or contain characters other than letters, numbers and underscores.
Syntax errors are reported by WebLS in your browser. The indicator <- NEAR HERE -> will give you an idea of where the error is in the text of your logic-base.
WebLS includes a trace facility to assist in testing and debugging logic-bases. The trace lists all the known facts, and then shows each rule being tried, indicating which facts match, and which rule or hypothesis matches. When tracing is enabled (by defining a log file at the top of your logic-base), a URL pointing to the output is included on the bottom of each page generated by WebLS. This allows you to examine the trace directly in your browser.
A typical debugging session has you fill-in the answers on the form (in the same manner your users would), then see the trace to determine how the answer was reached, or why another set of facts is being asked for.
Below is a small logic-base and the trace of a particular run of liltech.lb.
% ------------------------------------------------------------------- % % The Logic-Base % % ------------------------------------------------------------------- % :- op(790, fx, if). % prefix operator :- op(780, xfx, then). % infix operator :- op(775, xfy, or). % infix that can be linked :- op(770, xfy, and). % infix that can be linked :- op(700, xfx, <=). % infix operator :- op(700, xfx, include). % infix operator :- op(700, xfx, exclude). % infix operator :- asserta(system('Body Args', $bgcolor=#CEFAFF text=#000000$)). :- asserta(system('Title', $Amzi! Problem Resolver$)). :- asserta(system('Header', $<H2>Amzi! Problem Resolver</H2>$)). :- asserta(system('Footer', $<FONT SIZE=-1>Copyright ©1996 Amzi! inc. All Rights Reserved.$)). :- asserta(system('Form Action', 'Executable Path')). :- asserta(system('Goal', ['problem'])). question(errorCode, [ firstForm, prompt = $What error code was displayed or 'none'?$, ask = field, length = 5 ]). question(programType, [ firstForm, prompt = $What program are you running?$, ask = menu(['other', 'Amzi! Hello Program', 'Amzi! Sample Program', 'Amzi! IDE', 'My Program', 'Windows Application']) ]). if errorCode = '600' and programType = 'Amzi! Hello Program' then problem = helloXPL. if errorCode = '600' and programType = 'Amzi! Sample Program' then problem = sampleXPL. if errorCode = '600' and programType = 'My Program' then problem = missingXPL. answer(helloXPL, [ text = [$The program is unable to locate the Amzi! Prolog object module, an XPL file. $, $Make sure the AMZI installation directory is in your path, and that HELLO.XPL file $, $exists in the path or the current directory.$] ]). answer(sampleXPL, [ text = [$The program is unable to locate the Amzi! Prolog object module, an XPL file. $, $Some of the Amzi! samples include source only, $, $and the PRO file needs to be compiled and linked $, $into an XPL file.$, $<P>If the XPL file exists, then it must be in your $, $path or the current directory.$] ]). answer(missingXPL, [ text = [$The program is unable to locate the Amzi! Prolog object module, an XPL file. $, $Make sure the the XPL file exists in your path $, $or the current directory.$, $<P>Note: Some development environments such as Visual Basic and $, $Delphi set the current directory to a directory you might not $, $have expected.$] ]). |
Figure: A Sample Logic-Base
You can see in the listing above the three main parts of the logic-base. There are the question, the rules and the answers.
Logic-Base Debugging Trace system($Input File$,$C:\WEBSITE\CGI-TEMP\287WS.INI$). system('Content File','C:\WEBSITE\CGI-TEMP\287WS.INP'). system('Output File','C:\WebSite\cgi-temp\287ws.out'). . . . system('Log File','C:\AmziCGI\logs\lilrun.htm'). system('Title',$Amzi! Problem Resolver$). system('Initial Form',$C:\AmziCGI\html\rptprob.htm$). system('AmziCGI Directory',$C:\AmziCGI$). system('Form Action','Executable Path'). system('Goal',problem). cgi('Content Length','191'). cgi('Content Type','application/x-www-form-urlencoded'). . . . cgi('Executable Path','/cgi-win/cgirun.exe'). cgi('Request Method','POST'). cgi('Request Protocol','HTTP/1.0'). fact(submitForm,Submit) fact(programType,Amzi! Sample Program) fact(errorCode,600) Processing input file C:\WEBSITE\CGI-TEMP\8AAWS.INI Processing POST method (subsequent times through) ---> Calling logic-base to find hypotheses for goal problem if errorCode = 600 and programType = Amzi! Hello Program then problem = helloXPL Checking then problem = helloXPL Checking if errorCode = 600 Matching errorCode = 600 Checking if programType = Amzi! Hello Program if errorCode = 600 and programType = Amzi! Sample Program then problem = sampleXPL Checking then problem = sampleXPL Checking if errorCode = 600 Matching errorCode = 600 Checking if programType = Amzi! Sample Program Matching programType = Amzi! Sample Program Matching problem = sampleXPL if errorCode = 600 and programType = My Program then problem = missingXPL Checking then problem = missingXPL Checking if errorCode = 600 Matching errorCode = 600 Checking if programType = My Program ---> Calling logic-base to find answers for goal problem if errorCode = 600 and programType = Amzi! Hello Program then problem = helloXPL Checking then problem = helloXPL Checking if errorCode = 600 Matching errorCode = 600 Checking if programType = Amzi! Hello Program if errorCode = 600 and programType = Amzi! Sample Program then problem = sampleXPL Checking then problem = sampleXPL Checking if errorCode = 600 Matching errorCode = 600 Checking if programType = Amzi! Sample Program Matching programType = Amzi! Sample Program Matching problem = sampleXPL if errorCode = 600 and programType = My Program then problem = missingXPL Checking then problem = missingXPL Checking if errorCode = 600 Matching errorCode = 600 Checking if programType = My Program ---> Logic-base found answers [sampleXPL] |
Figure: Trace of the Sample Logic-Base
This trace illuminates the 'backtracking' search that is inherent in the Prolog language and implemented in the WebLS inference engine. You can see the first rule matches on the errorCode ('600') but fails on the programType. The second rules matches on both and succeeds; that is, it identifies the problem as 'sampleXPL.'
In addition to the trace facility, WebLS reports when question is not defined for a needed fact and when answer is not defined for a reached conclusion. These errors are returned on an HTML error page designed for the purpose.
Here are the error messages returned by WebLS and their explanations: