Virtual Storyteller overzicht Java Theorem Prover (JTP) JTP is een object-geörienteerd redeneer systeem, geïmplementeerd in Java. In dit document wordt het opzetten van een simpel redeneersysteem in JTP behandeld. De onderdelen van het systeem worden een voor een behandeld. Verder wordt een aantal problemen die voor zouden kunnen komen op een rijtje gezet. Een beknopte javadocbeschrijving bij de klassen kan gevonden worden via de JTP website: http://www.ksl.stanford.edu/software/jtp/api/ De basisklasse voor een redeneersysteem is de Reasoning Context. Elke Reasoning Context in JTP stamt af van de basisklasse jtp.context.basicreasoningcontext. Representatie van kennis Kennis wordt gerepresenteerd in de Conjunctieve Normaal Vorm (Conjunctive Normal Form, CNF). Een stukje kennis in CNF bestaat uit een aantal clausules (Clauses), die allemaal waar zijn. Een clausule wordt intern gerepresenteerd als een verzameling van Literals en de logische operatoren NOT en OR. Kennis wordt geïmplementeerd in KIFzinnen (KIF: Knowledge Interchange Format). De kennis (A => B), (B => C) bestaat dus uit twee clausules, (A => B) en (B => C). De clausule A => B wordt in JTP gerepresenteerd als (NOT(B) OR (A)). A en B zijn beide een Literal. Een Literal bestaat uit een relatie en de argumenten waartussen die relatie geldt. Neem bijvoorbeeld de Literal (ancestor Mary Sue). ancestor is hier de relatie. De argumenten zijn Mary en Sue. Argumenten van een Literal kunnen ook variabelen zijn. Een variabele begint met een vraagteken (? ), met daar op volgend een aantal karakters. Op deze manier kan bijvoorbeeld transitiviteit worden uitgedrukt: (=> ((ancestor?x?y) (ancestor?y?z)) (ancestor?x?z) ) Kennisrepresentatie concreet in Java klassen: CNFSentence is een rijtje conjuncte Clauses, dus impliciet gecombineerd met een AND. Dus de CNFSentence met Clause A, B en C heeft een KIF-representatie (and (A) (B) (C)) Clause is een rijtje disjuncte Literals, dus impliciet gecombineerd met een OR. Dus de Clause met Literals A en B heeft een KIF-representatie (or (A) (B)) Literal is een simpele Clause die bestaat uit een relatie en argumenten waartussen de relatie geldt, in de vorm van Symbols. Bijvoorbeeld (father Jan Piet) definieert de
father relatie tussen Jan en Piet. Een Literal heeft ook een polariteit; is de polariteit van een Literal L false, dan is NOT(L) waar. Symbol is een (symbool-)element, met een package (die ook leeg kan zijn) en een name. owl:inverseof kan gerepresenteerd worden als een Symbol met package owl (of eigenlijk http://www.w3.org/.../owl#) en name inverseof. Variable is een variabele, bijvoorbeeld?loc. Reasoning Context In JTP zijn verschillende omgevingen om te redeneren geimplementeerd. Elk van deze omgevingen biedt de mogelijkheid om kennis op te slaan (telling) en op te vragen (asking). Deze kennis wordt ingegeven d.m.v. KIF-zinnen, en worden door de reasoning context omgezet naar CNF. Intern worden deze CNF-feiten gebruikt om andere feiten af te leiden. Een Reasoning Context bestaat uit Reasoners en Dispatchers. Dispatchers ontvangen een query of een assertion en spelen die door naar een geschikte Reasoner. Telling reasoners verwerken kennis op een forward-chaining manier; ze verwerken consequenties van aangenomen kennis. Asking reasoners op hun beurt, verwerken kennis via backwardchaining; er worden steeds bewijzen gezocht bij queries. De meest simpele Reasoning Context is geimplementeerd in de klasse jtp.context.basicreasoningcontext. Deze context biedt mogelijkheden om assertions en queries te verwerken: - Assertions worden door een jtp.modelim.breadthfirstforwardreasoner reasoner uitbesteed aan een jtp.disp.sequentialdispatcher. - Queries worden door een jtp.context.iterativedeepening reasoner uitbesteed aan een jtp.disp.sequentialdispatcher. Om kennis op te kunnen slaan moet aan een BasicReasoningContext een jtp.gmp.clauseorientationkb worden toegevoegd. De feitelijke opslag van kennis gebeurt in deze klasse in de private-velden pos en neg. Gespecialiseerde contexten Binnen JTP bestaan er 2 uitbreidingen op de door de BasicReasoningContext geleverde basis context: De klassen jtp.frame.fc.context en jtp.frame.listen.context. Beide klassen bieden ondersteuning voor forward-chaining rules door middel van speciale reasoners, maar de manier waarop rules worden ondersteund verschilt in beide klassen. Een overzicht van de reasoners die worden gebruikt door jtp.frame.listen.context: - Telling reasoners: o jtp.frame.linkasserter o jtp.frame.listen.vclistenercreator o jtp.frame.slotvaluetellingreasoner (gekoppeld aan een FrameKB)
- Asking reasoners: o jtp.frame.slotvalueaskingreasoner (gekoppeld aan een FrameKB) De klasse jtp.frame.listen.context vormt de basis voor de klasse jtp.context.rdf.rdfcontext. Een RDFContext voegt de volgende reasoners toe aan de reeds over geërfde reasoners: o Asking reasoners: o jtp.frame.holdsreasoner o jtp.frame.enumeratingreasoner o jtp.func.inequal De klasse jtp.context.owl.owlcontext vormt een verdere specialisatie van de RDFContext. Een OWLContext voegt de volgende reasoners toe: o Telling reasoners: o jtp.frame.listen.dl.intersectiontypereasoner o jtp.classifier.classifiertellingreasoner
RDF/OWL functionaliteit zoals beschreven in http://www.ksl.stanford.edu/software/jtp/doc/owl-reasoning.html wordt door JTP bereikt door de volgende bestanden te laden tijdens het opzetten van een RDF of OWL reasoning context: %JTP%/src/jtp/context/owl/owl-assumptions.kif %JTP%/src/jtp/context/owl/owl-rules.xml %JTP%/src/jtp/context/rdf/rdf-assumptions.kif %JTP%/src/jtp/context/rdf/rdf-rules.xml In de xml-bestanden zijn de zogenaamde forward-chaining regels gedefinieerd, de kifbestanden bevatten KIF-definities van OWL en RDF zoals: (rdfs:domain rdf:type rdfs:resource) (rdfs:range rdf:type rdfs:class) (rdf:type owl:thing owl:class) (owl:complementof owl:thing owl:nothing) Toevoegen van kennis Het toevoegen van kennis aan een reasoning context gebeurt middels het aannemen (assert-en) van feiten. Aangenomen feiten kunnen ervoor zorgen dat er forward-chaining regels worden geactiveerd, daarom zijn er twee manieren om kennis aan te nemen: de ene levert een ReasoningStepIterator als resultaat, de andere een integer. De Iterator kan gebruikt worden om handmatig door de forward-chained informatie te lopen, de integer geeft simpelweg het aantal nieuw geïmpliceerde feiten. Verder kan het feit dat aangenomen dient te worden op 2 manieren worden aangegeven: middels een codering als tekst, of als object-representatie. Dit leidt tot de volgende 4 methodes om een feit aan te nemen: int BasicReasoningContext.tell( Object assertion ) ReasoningStepIterator BasicReasoningContext.getAssertionResults( DirectAssertion assertion ) int BasicReasoningContext.tellString( String assertion, URL url ) ReasoningStepIterator BasicReasoningContext.getStringAssertionResults( String assertion ) Het verschil tussen het meegeven van een Object of String is dat wanneer een Stringrepresentatie wordt meegegeven, deze door de reasoning context eerst zal worden vertaald naar een DirectAssertion-object. Het verschil tussen de get... -methodes en de andere methodes, is het wel of niet doorgeven van de kennis aan de undo-manager. De methodes die een ReasoningStepIterator retourneren slaan het aangenomen feit niet op in de undo-manager. Een consequentie hiervan is dat feiten die via de get -methodes zijn toegevoegd aan de KB op een later tijdstip niet meer op te sommen zijn.
Opvragen van kennis Het opvragen van kennis gaat via het doen van een query aan de kennisbank. De context BasicReasoningContext biedt hiervoor de methode ask( String query ). De query wordt intern vertaald door de FirstOrderLogicTranslator van de context, die weer gebruik maakt van de parser die op dat moment in de context (zie setparser()) is ingesteld. JTP wijzigt soms intern de gebruikte parser (bijvoorbeeld wanneer een KB wordt geladen via loadrdfkb(), die een RDFParser instelt), vandaar dat het aan te raden is om ofwel direct de AskingReasoner van de context aan te roepen: getaskingreasoner().process(translator.translate( query )) Queries die uit een simpele Literal bestaan (bijvoorbeeld (fatherof?x?y)), worden afgehandeld door de model elimination theorem prover, die geimplementeerd is in de klasse jtp.modelim.modeleliminationreasoner. Wanneer een query echter meer complex vormgegeven is, komt deze via de AskingDispatcher terecht bij de jtp.modelim.askingqueryreasoner. Deze reasoner gaat op een bijzonder wijze om met de query: Er wordt een tijdelijke Literal aangemaakt die bestaat uit een hulp-naam $aux, en waarvan de variabelen de verzameling is van ongebonden variabelen uit de oorspronkelijke query. Er wordt een hulpregel toegevoegd aan de kennisbank. Deze hulpregel ziet eruit als: (query => $aux). Vervolgens wordt ($aux) als query aan de kennisbank gegeven. Op deze manier kan toch weer de model elimination theorem prover worden gebruikt. Een voorbeeld: stel, de query is (a?x => b?y). De vrije variabelen in deze query zijn?x en?y. Er wordt dus een hulp-literal aangemaakt: ($aux?x?y). Verder wordt deze regel toegevoegd aan de KB: ((a?x => b?y) => $aux?x?y). Intern wordt nu de query ($aux?x?y) doorgegeven aan de ModelEliminationReasoner. Een bijkomstigheid van het gebruik van de AskingQueryProcessor is dat de hulp-regels die toegevoegd worden aan de KB niet worden verwijderd. Wanneer hier geen rekening mee wordt gehouden, zal een groot aantal complexe queries dus leiden tot een steeds hogen geheugen-gebruik. Het is daarom raadzaam om vóór het stellen van een query een snapshot te maken via de UndoManager (zie hieronder). Antwoord op een query Het resultaat van een query is een ReasoningStepIterator, wat een belangrijke klasse is binnen JTP. Een instantie van de klasse jtp.reasoningstep is in wezen een bewijs van de query. Een ReasoningStep bestaat uit de volgende attributen: goal: de te bewijzen Literal. subgoals: wanneer de query geen literal is, maar een conjunctie van literals, vormt elke literal in de conjunctie een subgoal. subproofs: elke subgoal wordt bewezen in een eigen bewijs.
bindings: de vrije variabelen die in de stap voorkomen plus de waarden waarvoor ze gesubstitueerd zijn bij het vormen van het bewijs. Itereren van de kennisbank De kennis in een JTP reasoning context wordt opgeslagen in private velden in de klasse ClauseOrientationKB, en is dus niet direct opvraagbaar. In plaats daarvan kan kennis worden geïtereerd via de UndoManager klasse. Kennis die is aangenomen via de tell- methoden wordt door de undo-manager bijgehouden, zodat feiten later weer via untell kunnen worden ingetrokken. Deze functionaliteit is geëncapsuleerd in de klasse jtp.undo.snapshotundomanager. Het via deze klasse ophalen van aangenomen kennis gaat als volgt: 1. Via BasicReasoningContext.getUndoManager() wordt de undo-manager opgehaald. 2. Er wordt een snapshot shot gemaakt via SnapshotUndoManager.getSnapshot() 3. Kennis die sinds het maken van de snapshot via tell-methoden is aangenomen kan worden opgevraagd met de methode SnapshotUndoManager.getObjectsToldSinceSnapshot(). Packages De verschillende packages binnen JTP: jtp.cache voor cachen van een Knowledge Store (wordt niet gebruikt in JTP) jtp.classifier voor classificatie algoritmes (OWL) ( x heeft 4 muren en een dak dus x is een gebouw ) jtp.context Reasoning contexts (daml, rdf, owl) jtp.demod Lijkt iets te zijn met het kunnen transformeren van kennis (bv vervangen van literals en variabelen) jtp.disp Dispatchers (besteden queries uit naar reasoners) jtp.fol First order logic: de klassen waar kennis uit bestaat zoals CNFSentences, Clauses, Literals, Variables etc. Bevat ook parsers voor deze kennis (van String naar Java objecten) jtp.frame Alles voor frame-based reasoning -- jtp.frame.vocab Vocabulaire voor RDF, OWL etc. -- jtp.frame.fc Voor forward chaining (rules) -- jtp.frame.listen luistert naar binnenkomende kennis om gevolgen te trekken -- jtp.frame.vc Value collection, voor het zoeken erin en werken ermee jtp.func Functional reasoners -- jtp.func.math Mathematical reasoners jtp.gmp Modus Ponens reasoners jtp.iw InferenceWeb reasoners jtp.modelim Model elimination reasoners jtp.proof Afhandelen van bewijzen: goals, subgoals, en redeneer-regels zoals and-introduction jtp.rs ReasoningSteps
jtp.time jtp.ui jtp.undo jtp.util jtp Time reasoners User interface voor JTP Voor het retracten van knowledge Verschillende hulpklassen Basis-interfaces van veel klassen die in de subpackages uitgeweid worden JTP Gebruiken Bij het schrijven van een java-applicatie die gebruik maakt van JTP dienen de volgende files worden meegenomen in de classpath-parameter van java en javac: Antlr.jar Base64.jar http.jar icu4j.jar iiop.jar jade.jar jadetools.jar jakarta-oro-2.0.5.jar jdom.jar jena.jar jtp.jar log4j.jar xercesimpl.jar xmlparserapis.jar