/code/ClauseBody.java
Java | 1285 lines | 1095 code | 42 blank | 148 comment | 387 complexity | fbc76c0e1dde9c536ea157bf3957f540 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- import java.util.*;
- import java.io.*;
- import java.text.*;
- /** A ClauseBody is just a list of literals, constituting one complete
- definition of the (predicate in the ClauseHead of the) kinship term.
- Multiple clause bodies comprise a disjunctive definition.
- @author Gary Morris, Northern Virginia Community College garymorris2245@verizon.net
- */
- public class ClauseBody implements Serializable, Comparator {
- public static int seq = 0, seqTotal = 0, dups = 0, dupTotal = 0;
- public static String priorPred = "";
- public static int distanceLimit = 0;
- public static String[] arg0Guys = {"father", "husband", "son", "male", "brother", "half_brother",
- "step_brother", "step_father", "step_son"},
- arg0Gals = {"mother", "wife", "daughter", "female", "sister", "half_sister",
- "step_sister", "step_mother", "step_daughter"},
- exempts = {"male", "female", "equal", "not", "divorced", "dead", "gender",
- "lessThan", "greaterThan", "lessOrEql ", "greaterOrEql", "contains",
- "allowCreation", "parents", "siblings", "brother", "sister",
- "half_brother", "half_sister", "step_brother", "step_sister",
- "step_father", "step_mother", "children", "step_son",
- "step_daughter", "spice"},
- yin = {"male", "female", "elder", "younger", "brother", "sister"},
- yan = {"female", "male", "younger", "elder", "sister", "brother"};
- public static ArrayList<Object> arg0Males = loadMales(),
- arg0Females = loadFemales(),
- exemptPreds = loadExempt(),
- ying = loadYing(),
- yang = loadYang();
- /** <code>body</code> is an ArrayList<Object> of literals that make up the Right Hand Side of a Horn Clause.
- <code>expansionPath</code> is an ArrayList<Object> of strings that document the sequence of cultural
- kinTerms that were expanded into their all-Primitive meanings in the course of expanding THIS
- ClauseBody into its all-Primitive form.
- */
- ArrayList<Object> body, expansionPath, duplications;
- int seqNmbr;
- String genderOfAlter = "", pcString, pcStringStructural;
- KinTermDef ktd; // points to the enclosing KinTerm Definition
- /** During Example-Generation, this becomes true if recursion is encountered while
- interpreting this clause. Direct, indirect, and mutual recursion are detected. */
- boolean recursive = false;
- /** If the interpretation of this clause leads to the same node in a family tree as
- some other clause for the same kinTerm, then <code>duplicative</code> = true. */
- boolean duplicative = false;
- /** In Active Learning, we want to note which CBs matched postive examples of a kinTerm.
- true = 1 or more hits for the current kinTerm.*/
- boolean posHit = false;
- /** Contains all flags (strings within square brackets) found in the clauseBody during parsing. */
- public ArrayList<Object> flags;
- /** Level indicates the generation to which Alter belongs: 0 = Ego's generation, +1 = her father's generation,
- and -1 = her child's generation, etc. pcCounter is the count of all parent and child links traversed
- in reaching Alter. sCounter is the count of spouse links traversed to reach Alter, etc.*/
- int level = 0, pcCounter = 0, sCounter = 0, starCounter = 0, egoNum = -99;
- Library.BaseCB_Ptr baseCB_Ptr;
- public static ArrayList<Object> loadMales() {
- ArrayList<Object> result = new ArrayList<Object>();
- for (int i = 0; i < arg0Guys.length; i++) {
- result.add(arg0Guys[i]);
- }
- return result;
- } // end of static method loadMales
- public static ArrayList<Object> loadFemales() {
- ArrayList<Object> result = new ArrayList<Object>();
- for (int i = 0; i < arg0Gals.length; i++) {
- result.add(arg0Gals[i]);
- }
- return result;
- } // end of static method loadFemales
- public static ArrayList<Object> loadExempt() {
- ArrayList<Object> result = new ArrayList<Object>();
- for (int i = 0; i < exempts.length; i++) {
- result.add(exempts[i]);
- }
- return result;
- } // end of static method loadExempt
- public static ArrayList<Object> loadYing() {
- ArrayList<Object> result = new ArrayList<Object>();
- for (int i = 0; i < yin.length; i++) {
- result.add(yin[i]);
- }
- return result;
- } // end of static method loadYing
- public static ArrayList<Object> loadYang() {
- ArrayList<Object> result = new ArrayList<Object>();
- for (int i = 0; i < yan.length; i++) {
- result.add(yan[i]);
- }
- return result;
- } // end of static method loadYang
- ClauseBody() {
- body = new ArrayList<Object>();
- expansionPath = new ArrayList<Object>();
- flags = new ArrayList<Object>();
- } // end of constructor with no args
- /** Construct a new ClauseBody with one Literal in the body.
- @param lit the Literal to be placed in the body.
- */
- ClauseBody(Literal lit) {
- body = new ArrayList<Object>();
- expansionPath = new ArrayList<Object>();
- body.add(lit);
- flags = new ArrayList<Object>();
- } // end of constructor with one literal as arg
- /** Make a shallow copy of this ClauseBody. The new ClauseBody's fields will
- contain shallow copies of this one's fields.
- */
- public ClauseBody copy() {
- ClauseBody newCB = new ClauseBody();
- newCB.body = new ArrayList<Object>(body);
- newCB.genderOfAlter = genderOfAlter;
- newCB.duplications = duplications;
- newCB.duplicative = duplicative;
- newCB.pcString = pcString;
- newCB.pcStringStructural = pcStringStructural;
- newCB.recursive = recursive;
- newCB.ktd = ktd;
- newCB.level = level;
- newCB.egoNum = egoNum;
- newCB.pcCounter = pcCounter;
- newCB.sCounter = sCounter;
- newCB.starCounter = starCounter;
- newCB.flags = new ArrayList<Object>(flags);
- if (expansionPath == null) {
- newCB.expansionPath = new ArrayList<Object>();
- } else {
- newCB.expansionPath = new ArrayList<Object>(expansionPath);
- }
- newCB.baseCB_Ptr = baseCB_Ptr;
- return newCB;
- } // end of copy method
- /** Make a deep copy of this ClauseBody. The new ClauseBody's body will
- contain a deep copy of this one's.
- */
- public ClauseBody deepCopy() {
- ClauseBody newCB = new ClauseBody();
- newCB.body = new ArrayList<Object>();
- for (int i = 0; i < body.size(); i++) {
- Literal lit = (Literal) body.get(i);
- newCB.body.add(lit.copy());
- }
- newCB.genderOfAlter = genderOfAlter;
- newCB.duplications = duplications;
- newCB.duplicative = duplicative;
- newCB.pcString = pcString;
- newCB.pcStringStructural = pcStringStructural;
- newCB.recursive = recursive;
- newCB.ktd = ktd;
- newCB.level = level;
- newCB.egoNum = egoNum;
- newCB.pcCounter = pcCounter;
- newCB.sCounter = sCounter;
- newCB.starCounter = starCounter;
- newCB.flags = new ArrayList<Object>(flags);
- if (expansionPath == null) {
- newCB.expansionPath = new ArrayList<Object>();
- } else {
- newCB.expansionPath = new ArrayList<Object>(expansionPath);
- }
- newCB.baseCB_Ptr = baseCB_Ptr;
- return newCB;
- } // end of deepCopy method
- /** Add this Literal to the body of this ClauseBody.
- @param lit the Literal to be added to the body.
- */
- public void addLiteral(Literal lit) {
- body.add(lit);
- }
- // probably someday I'll need a "remove" method. Not Yet!
- /** Create a string representing this Horn Clause, in loose Prolog syntax.
- @return a String suitable for display or printing.
- */
- public String toString() {
- int size = body.size();
- String display = "", flagList = "", path = "", dups, prior, curr;
- for (int i = 0; i < size; i++) {
- display += body.get(i).toString();
- if (i < (size - 1)) {
- display += ", ";
- }
- }
- display += ".\n";
- if (flags.size() > 0) {
- Iterator flagIter = flags.iterator();
- while (flagIter.hasNext()) {
- flagList += "[" + (String) flagIter.next() + "], ";
- }
- } // end of if-there-are-flags
- if ((pcCounter + sCounter + starCounter) > 0) {
- path += ".\n Lvl=" + level + ", PC=" + pcCounter + ", S=" + sCounter + ", *=" + starCounter + ". ";
- }
- if (pcString != null && pcString.length() > 0) {
- path += "{" + pcString + "} ";
- }
- if (expansionPath.size() > 0) {
- Iterator pathIter = expansionPath.iterator();
- prior = (String) pathIter.next();
- if (path.length() > 5) {
- path += "[Expansion Path: " + prior;
- } else {
- path = ".\n [Expansion Path: " + prior;
- }
- while (pathIter.hasNext()) {
- curr = (String) pathIter.next();
- if (prior.equals("(not:")) {
- path += " ";
- } else if (!curr.equals(")")) {
- path += ", ";
- }
- prior = curr;
- path += prior;
- }
- path += "]";
- } // end of if-expansion-path-is-not-empty
- return flagList + display + path;
- } // end of over-riding toString method
- /** Create a string representing this Horn Clause, in strict Prolog syntax.
- @return a String suitable for parsing.
- */
- public String toThyString() throws KSInternalErrorException {
- int size = body.size();
- String display = " ", flagList = "", path = "", prior;
- for (int i = 0; i < size; i++) {
- display += body.get(i).toString() + (i < (size - 1) ? ", " : ".");
- }
- if (flags.size() > 0) {
- Iterator flagIter = flags.iterator();
- while (flagIter.hasNext()) {
- flagList += "[" + (String) flagIter.next() + "], ";
- }
- } // end of if-there-are-flags
- if (expansionPath.size() > 0) {
- Iterator pathIter = expansionPath.iterator();
- prior = (String) pathIter.next();
- path = ";; " + seqNmbr + "\n%" + prior;
- while (pathIter.hasNext()) {
- if (prior.equals("(not:")) {
- path += " ";
- } else {
- path += ", ";
- }
- prior = (String) pathIter.next();
- if (prior.equals(")")) {
- path = path.substring(0, path.length() - 2);
- }
- path += prior;
- }
- path += "%\n";
- path += " Lvl=" + level + ", PC=" + pcCounter + ", S=" + sCounter + ", Star=" + starCounter + ", ";
- path += "{" + (pcString == null || pcString.length() == 0 ? "None" : pcString) + "} \n";
- } // end of if-expansion-path-is-not-empty
- return path + flagList + display;
- } // end of method toThyString()
- String toXML(String bacer) {
- String s = bacer + "<clause>\n";
- for (int i=0; i < body.size(); i++) {
- Literal lit = (Literal)body.get(i);
- s += lit.toXML(bacer + "\t");
- }
- s += "\n" + bacer + "</clause>\n";
- return s;
- }
-
- String toSimpleHornClause() {
- String hornClaws = "";
- int last = body.size() - 1;
- for (int i = 0; i < last; i++) {
- Literal lit = (Literal) body.get(i);
- hornClaws += lit + ", ";
- }
- Literal lit = (Literal) body.get(last);
- return hornClaws + lit + ". ";
- }
- String toSILKString(String bacer) {
- String s = bacer + "<clause level=\"" + level + "\">\n",
- dblSpace = "\t\t";
- if (pcString != null && !pcString.isEmpty()) {
- s += bacer + "\t" + "<pc-string>" + pcString + "</pc-string>\n";
- }
- if (pcStringStructural != null && !pcStringStructural.isEmpty()) {
- s += bacer + "\t" + "<pc-string-structural>" + pcStringStructural
- + "</pc-string-structural>\n";
- }
- for (int i=0; i < body.size(); i++) {
- Literal lit = (Literal)body.get(i);
- s += lit.toSILKString(bacer + "\t") + "\n";
- }
- s += bacer + "</clause>\n";
- return s;
- }
- /** Expand this ClauseBody into one or more ClauseBodies that contain only predicates that
- are members of (@link PrimitiveCategory), and place them in <code>expandedDefs</code>.
- For example, assume the current domain theory contains the following definition:
- <p>
- <code>fee(Alter,Ego) :- son(Alter,Ego).
- <p> | daughter(Alter,Ego).</code>
- <p>
- that is: Alter is my 'fee' if he is either my 'son' or my 'daughter'. If this ClauseBody
- contains the literal <code>fee(X,Y)</code> then it will be expanded into 2 ClauseBodies;
- one will contain the "son" definition and one will contain the "daughter" definition.
- Both of them (after all literals have been expanded) will be stored in the <code>expandedDefs</code>
- for the current KinTermDef.
- @param hypo the current context.
- @param expandedDefs the location where completed expansions will be stored.
- @param kinTerm the cultural kinship term which this ClauseBody helps define.
- @param index the clause number of the base clause that we're expanding
- */
- public void expand(Context hypo, ArrayList<Object> expandedDefs, String kinTerm, int index)
- throws KSBadHornClauseException, KSInternalErrorException {
- ArrayList<Object> clauseSoFar = new ArrayList<Object>(), kinTermLst = new ArrayList<Object>(), recursLvlLst = new ArrayList<Object>(),
- save4Last = new ArrayList<Object>(), expPath = new ArrayList<Object>(),
- remainingLits = new ArrayList<Object>(body.subList(1, body.size()));
- kinTermLst.add(kinTerm);
- recursLvlLst.add(new Integer(0));
- expPath.add(kinTerm + ":" + index);
- // System.out.println("Expanding " + kinTerm + ":" + index);
- // if (kinTerm.equals("dad")) Context.breakpoint();
- Literal firstLit = (Literal) body.get(0);
- StackMarkerObj marker = new StackMarkerObj(kinTermLst, recursLvlLst);
- LiteralAbstract1.expansionSerial = 0;
- firstLit.expand(hypo, clauseSoFar, remainingLits, expandedDefs, save4Last, marker, this, expPath);
- return;
- } // end of method expand
- public boolean isExpansionOf(ClauseBody original) {
- if (original == null) {
- return true;
- }
- String origClauseNmbr = String.valueOf(original.seqNmbr);
- String firstExpansion = (String) expansionPath.get(0);
- int where = firstExpansion.indexOf(":");
- return (origClauseNmbr.equals(firstExpansion.substring(where + 1).trim()));
- }
- public int isExpandedFrom(ClauseBody original) {
- if (original == null) {
- return -1;
- }
- String firstExpansion = (String) expansionPath.get(0);
- int where = firstExpansion.indexOf(":");
- int origin = Integer.parseInt(firstExpansion.substring(where + 1).trim());
- return origin;
- }
- public void findAuxPreds(ArrayList<Object> auxPreds)
- throws KSParsingErrorException, KSConstraintInconsistency, KSInternalErrorException {
- // Find any cultural (non-primitive) predicates in the body of this base CB.
- // Retrieve the KTDs for all those, and put deep copies of them in auxPreds.
- // Recursively, find & deep-copy any non-primitives found in those auxPreds. (Compute a closure.)
- for (int i = 0; i < body.size(); i++) {
- Literal lit = (Literal) body.get(i);
- String lang = ktd.domTh.languageName,
- predName = lit.predicate.name;
- boolean duplicate = false;
- for (int j = 0; !duplicate && j < auxPreds.size(); j++) { // no duplicates
- KinTermDef pred = (KinTermDef) auxPreds.get(j);
- if (pred.kinTerm.equals(predName) && pred.domTh.languageName.equals(lang)) {
- duplicate = true;
- }
- }
- if (!duplicate && !DomainTheory.isPrimOrMacro(predName)
- && predName.indexOf("*") == -1) {
- int tagSpot = predName.indexOf("<F_aux>"); // maybe a prior aux was generalized
- String altName = (tagSpot > -1 ? predName.substring(0, tagSpot) : null);
- KinTermDef culturalPred = (KinTermDef) ktd.domTh.theory.get(predName); // look on original DT under predName
- if (culturalPred == null && altName != null) {
- culturalPred = (KinTermDef) ktd.domTh.theory.get(altName); // look on original DT under original name
- }
- if (culturalPred == null && altName != null) {
- culturalPred = (KinTermDef) DomainTheory.current.theory.get(predName); // look on Learner only under <F_aux> name
- } // Hopefully, one of those methods got it.
- if (culturalPred != null && culturalPred.definitions != null
- && culturalPred.definitions.size() > 0 && culturalPred.expandedDefs != null
- && culturalPred.expandedDefs.size() > 0) { // Easy
- KinTermDef culturalPredCopy = culturalPred.deepCopy();
- culturalPredCopy.kinTerm = predName; // Just in case we retrieved it under other name
- auxPreds.add(culturalPredCopy);
- for (int k = 0; k < culturalPred.definitions.size(); k++) {
- ((ClauseBody) culturalPred.definitions.get(k)).findAuxPreds(auxPreds);
- }
- } else {
- String fileName = Library.libraryDirectory + "Domain Theory Files/" + lang + ".thy";
- Linus dtLineServer = new Linus(fileName);
- Parser parzer = new Parser(new Tokenizer(Library.getDFA(), dtLineServer));
- try {
- culturalPred = parzer.parseKinTerm(predName, false);
- } catch (KSParsingErrorException pe) {
- if (altName != null) {
- culturalPred = parzer.parseKinTerm(altName, false);
- } else {
- throw pe;
- }
- }
- KinTermDef culturalPredCopy = culturalPred.deepCopy();
- culturalPredCopy.kinTerm = predName; // Just in case we retrieved it under other name
- try {
- ktd.domTh.addTerm(culturalPredCopy);
- } catch (KSParsingErrorException pe) {
- } // OK to over-write definition with complete KTD
- auxPreds.add(culturalPredCopy);
- for (int k = 0; k < culturalPredCopy.definitions.size(); k++) {
- ((ClauseBody) culturalPredCopy.definitions.get(k)).findAuxPreds(auxPreds);
- }
- } // end of else-parse-it
- } // end of found a cultural predicate
- } // end of loop thru definitions
- } // end of method findAuxPreds
- public void postToBaseSigString() throws KSInternalErrorException {
- // May be called only on an ExpandedDef, not on a base clause
- if (pcString == null) {
- throw new KSInternalErrorException("CB.postToBaseSigString called on CB with no pcString");
- }
- String firstExpansion = (String) expansionPath.get(0);
- int where = firstExpansion.indexOf(":");
- int baseCBNmbr = Integer.parseInt(firstExpansion.substring(where + 1).trim());
- ClauseBody baseCB = (ClauseBody) ktd.definitions.get(baseCBNmbr);
- if (baseCB.pcString == null) {
- baseCB.pcString = pcString;
- } else {
- baseCB.pcString += "_" + pcString;
- }
- } // end of method postToBaseSigString
- public void sortSigString() throws KSInternalErrorException {
- if (pcString == null || pcString.length() < 1) {
- throw new KSInternalErrorException("WARNING: Base clause " + ktd.domTh.languageName
- + ":" + ktd.kinTerm + ":" + seqNmbr + " has no non-duplicative expansions. Remove or fix it.");
- }
- TreeMap sorter = new TreeMap();
- String sigStr;
- int start = 0, end = pcString.indexOf("_");
- while (end > -1) {
- sigStr = pcString.substring(start, end);
- sorter.put(sigStr, sigStr);
- start = end + 1;
- end = pcString.indexOf("_", start);
- } // now get last one
- sigStr = pcString.substring(start);
- sorter.put(sigStr, sigStr);
- // Reassemble the sorted sigString
- Iterator iter = sorter.values().iterator();
- pcString = (String) iter.next();
- while (iter.hasNext()) {
- pcString += "_" + (String) iter.next();
- }
- } // end of method sortSigString()
- public void assignArgNames(Context ctxt) throws KSConstraintInconsistency {
- // Assign argNames to all the args, based on the assumption of a logical chain from Ego to Alter
- int argCodeIndex = 0;
- Variable nextVar = new Variable(LiteralAbstract1.argCodes[argCodeIndex++]);
- for (int i = 0; i < body.size(); i++) {
- Literal lit = (Literal) body.get(i);
- if (i == 0) {
- lit.args.add((body.size() > 1 ? nextVar : new Variable("Alter")));
- lit.args.add(new Variable("Ego"));
- } else if (i == body.size() - 1) {
- lit.args.add(new Variable("Alter"));
- lit.args.add(nextVar);
- } else {
- Variable arg1 = nextVar;
- nextVar = new Variable(LiteralAbstract1.argCodes[argCodeIndex++]);
- lit.args.add(nextVar); // new varName
- lit.args.add(arg1);
- }
- if (lit.predicate.name.equals("*")) { // Special processing for UDPs
- if (ctxt.userDefinedProperties == null || ctxt.userDefinedProperties.isEmpty()) {
- Context.breakpoint();
- }
- // TBA
- } // end of processing for UDPs
- } // end of loop thru body
- unifyVariables();
- } // end of method assignArgNames
- public void reassignArgNames(Context ctxt) throws KSConstraintInconsistency, KSInternalErrorException {
- // This method is like reassignArgNames_NewFront, but it handles the new (empty args) literal anywhere
- int insertionPt = -1;
- for (int i = 0; i < body.size(); i++) {
- Literal lit = (Literal) body.get(i);
- if (lit.args.isEmpty()) {
- if (insertionPt == -1) {
- insertionPt = i;
- } else {
- throw new KSConstraintInconsistency("CB.reassignArgNames got more than one lit with empty args.");
- }
- }
- } // end of i_loop
- if (insertionPt == -1) {
- throw new KSConstraintInconsistency("CB.reassignArgNames got no literals with empty args.");
- }
- if (insertionPt == 0) {
- reassignArgNames_NewFront(ctxt);
- return;
- }
- // Leave the literals ahead of the insertionPt alone. Note the arg names used.
- TreeMap old2New = new TreeMap(); // oldVarName => newVarName
- Literal lit = null;
- int argCodeIndex = 0;
- String nextVarName = LiteralAbstract1.argCodes[argCodeIndex++],
- mostRecentNewVarName = null,
- newVarName;
- for (int i = 0; i < insertionPt; i++) {
- lit = (Literal) body.get(i);
- for (int j = lit.args.size() - 1; j >= 0; j--) {
- String argName = ((Variable) lit.args.get(j)).argName;
- if (argName.equals(nextVarName)) {
- nextVarName = LiteralAbstract1.argCodes[argCodeIndex++];
- }
- old2New.put(argName, argName);
- mostRecentNewVarName = argName;
- } // end of j_loop
- } // end of i_loop
- // Give the inserted literal arg1 = previous end-of-chain, and arg0 = new variable
- lit = (Literal) body.get(insertionPt);
- lit.args.add(new Variable(nextVarName));
- lit.args.add(new Variable(mostRecentNewVarName));
- mostRecentNewVarName = nextVarName;
- nextVarName = LiteralAbstract1.argCodes[argCodeIndex++];
- // Give all following lits new variable argNames
- for (int i = insertionPt + 1; i < body.size(); i++) {
- lit = (Literal) body.get(i);
- Variable arg0Var = (Variable) lit.args.get(0);
- Variable arg1Var = (lit.args.size() == 2 ? (Variable) lit.args.get(1) : null);
- if (arg1Var != null) {
- newVarName = (String) old2New.get(arg1Var.argName);
- if (newVarName != null) {
- arg1Var.argName = newVarName;
- } else { // create a new var name for arg1
- old2New.put(arg1Var.argName, nextVarName);
- arg1Var.argName = nextVarName;
- nextVarName = LiteralAbstract1.argCodes[argCodeIndex++];
- }
- } // end of arg1Var not null
- newVarName = (String) old2New.get(arg0Var.argName);
- if (newVarName != null) {
- arg0Var.argName = newVarName;
- } else { // create a new var name for arg0
- old2New.put(arg0Var.argName, nextVarName);
- arg0Var.argName = nextVarName;
- mostRecentNewVarName = nextVarName;
- nextVarName = LiteralAbstract1.argCodes[argCodeIndex++];
- }
- }
- // Now change the mostRecentNewVarName to 'Alter'
- for (int j = 0; j < body.size(); j++) {
- lit = (Literal) body.get(j);
- for (int k = 0; k < lit.args.size(); k++) {
- Variable var = (Variable) lit.args.get(k);
- if (var.argName.equals(mostRecentNewVarName)) {
- var.argName = "Alter";
- }
- } // end of k_loop
- } // end of j_loop
- } // end of method reassignArgNames
- public void reassignArgNames_NewFront(Context ctxt) throws KSConstraintInconsistency, KSInternalErrorException {
- // Relabel the body literals' argNames into a nice progression
- // This method does NOT handle general negation or new variables introduced AFTER Alter.
- Literal lit = (Literal) body.get(0);
- if (lit.args.size() > 0) // First lit must be binary predicate with empty args
- {
- throw new KSInternalErrorException("CB.reassignArgNames_NewFront got front literal with existing args.");
- }
- int argCodeIndex = 0;
- String nextVarName = LiteralAbstract1.argCodes[argCodeIndex++],
- mostRecentNewVarName = null,
- newVarName;
- TreeMap old2New = new TreeMap(); // oldVarName => newVarName
- Variable arg1Var = new Variable("Ego"),
- arg0Var = ((body.size() == 1 ? new Variable("Alter") : new Variable(nextVarName)));
- lit.args.add(arg0Var);
- lit.args.add(arg1Var);
- if (body.size() == 1) {
- unifyVariables();
- return;
- }
- for (int i = 1; i < body.size(); i++) {
- lit = (Literal) body.get(i);
- arg0Var = (Variable) lit.args.get(0);
- arg1Var = (lit.args.size() == 2 ? (Variable) lit.args.get(1) : null);
- if (arg1Var != null) {
- newVarName = (String) old2New.get(arg1Var.argName);
- if (newVarName != null) {
- arg1Var.argName = newVarName;
- } else { // create a new var name for arg1
- old2New.put(arg1Var.argName, nextVarName);
- arg1Var.argName = nextVarName;
- nextVarName = LiteralAbstract1.argCodes[argCodeIndex++];
- }
- } // end of arg1Var not null
- newVarName = (String) old2New.get(arg0Var.argName);
- if (newVarName != null) {
- arg0Var.argName = newVarName;
- } else { // create a new var name for arg0
- old2New.put(arg0Var.argName, nextVarName);
- arg0Var.argName = nextVarName;
- mostRecentNewVarName = nextVarName;
- nextVarName = LiteralAbstract1.argCodes[argCodeIndex++];
- }
- if (lit.predicate.name.equals("*")) { // Special processing for UDPs
- if (ctxt.userDefinedProperties == null || ctxt.userDefinedProperties.isEmpty()) {
- Context.breakpoint();
- }
- // TBA
- } // end of processing for UDPs
- } // end of i_loop
- // Now change the mostRecentNewVarName to 'Alter'
- for (int j = 0; j < body.size(); j++) {
- lit = (Literal) body.get(j);
- for (int k = 0; k < lit.args.size(); k++) {
- Variable var = (Variable) lit.args.get(k);
- if (var.argName.equals(mostRecentNewVarName)) {
- var.argName = "Alter";
- }
- } // end of k_loop
- } // end of j_loop
- unifyVariables();
- } // end of method reassignArgNames_NewFront
- /** If this ClauseBody's literals contain multiple references to a single
- variable X, make sure that all references to X point to the same {@link Variable} object.
- Then implement all 'equal' predicates by doing global replacements in this ClauseBody. */
- public void unifyVariables() throws KSConstraintInconsistency {
- TreeMap bindery = new TreeMap();
- Counter cntr = new Counter();
- ArrayList<Object> bodyCopy = new ArrayList<Object>(body); // a "shallow copy" which points to the members of body.
- Literal lit = (Literal) bodyCopy.remove(0);
- try {
- lit.unifyVariables(bindery, bodyCopy, cntr);
- } catch (KSConstraintInconsistency ci) {
- throw new KSConstraintInconsistency(ci.toString().substring(39) + " in:\n" + this);
- }
- ArrayList<Object> eqLst = new ArrayList<Object>();
- for (int i = 0; i < body.size(); i++) {
- lit = (Literal) body.get(i);
- if (lit.predicate.name.equals("equal")) {
- eqLst.add(lit);
- }
- if (lit.predicate.name.equals("contains")) {
- checkValidity(lit);
- }
- } // end of for-loop
- if (eqLst.size() > 0) {
- globalReplace(eqLst, body);
- }
- } // end of method unifyVariables()
- public void checkValidity(Literal lit) throws KSConstraintInconsistency {
- // We have a 'contains' predicate. If the MathVar is single-valued, it should be an 'equal' predicate
- MathVariable var0 = (MathVariable) lit.args.get(0);
- String arg0Name = var0.argName, starPredName;
- UserDefinedProperty udp;
- Literal bodyLit;
- for (int i = 0; i < body.size(); i++) {
- bodyLit = (Literal) body.get(i);
- if ((bodyLit.predicate.name.substring(0, 1).equals("*"))
- && (arg0Name.equals(((Argument) bodyLit.args.get(0)).argName))) { // found-a-star-pred-binding-this-var
- starPredName = bodyLit.predicate.name;
- udp = (UserDefinedProperty) Context.current.userDefinedProperties.get(starPredName);
- if (udp == null) {
- String msg = "User-Defined Property '" + starPredName + "' is not defined for this domain.";
- throw new KSConstraintInconsistency(msg);
- } // end of udp-is-null => ERROR
- if (udp.singleValue) {
- String msg = "The variable '" + arg0Name + "' appears in '" + bodyLit + "' and in '"
- + lit + "' in:\n" + this + "\nThe former implies that " + arg0Name + " holds a single " + udp.typ
- + ", while the latter implies it is a list.\nNot permitted.";
- throw new KSConstraintInconsistency(msg);
- }
- } // end of found-a-star-pred-binding-this-var
- } // end of loop thru body
- } // end of method checkValidity
- public void globalReplace(ArrayList<Object> eqLst, ArrayList<Object> target) {
- Literal eqLit, lit2;
- Iterator iter;
- Argument arg1, in, out;
- for (int i = 0; i < eqLst.size(); i++) {
- eqLit = (Literal) eqLst.get(i);
- arg1 = (Argument) eqLit.args.get(1);
- if ((arg1.argName.equals("Alter"))
- || (arg1.argName.equals("Ego"))
- || (arg1 instanceof Constant)) {
- in = (Argument) eqLit.args.get(1); // never replace 'Alter', 'Ego' or a Constant.
- out = (Argument) eqLit.args.get(0);
- } else {
- in = (Argument) eqLit.args.get(0);
- out = (Argument) eqLit.args.get(1);
- }
- iter = target.iterator(); // at the top level, 'target' is really this ClauseBody's body
- while (iter.hasNext()) {
- lit2 = (Literal) iter.next();
- if (eqLit == lit2) {
- iter.remove();
- } else {
- for (int j = 0; j < lit2.args.size(); j++) {
- if (lit2.args.get(j) instanceof Literal) { // e.g. a 'not' predicate
- ArrayList<Object> newEq = new ArrayList<Object>(), newTarget = new ArrayList<Object>();
- newEq.add(eqLit);
- newTarget.add(lit2.args.get(j));
- globalReplace(newEq, newTarget);
- } // end of this-arg-is-a-Literal
- else if (lit2.args.get(j) == out) {
- lit2.args.set(j, in);
- }
- } // end of loop thru args of lit2
- }
- } // end of while-loop thru body
- } // end of for-loop thru eqLst
- } // end of method globalReplace
- /** Generate hypothetical people who have the relationship described in this ClauseBody.
- Add those people to the current context. Label the person called "Alter" in the clause
- with the <code>kinTerm</code> that this ClauseBody helps define.
- <p>
- This method is called only on a ClauseBody in the <code>extendedDefs</code> of a {@link KinTermDef}.
- Therefore, there are only Primitive predicates in the body.
- <p>
- When NOT doing simulatedDataGeneration, try to re-use an Ego from the egoBag, with all attributes assigned by prior clauses.
- If none of them work, try 1 male and 1 female 'fresh' Ego (no pre-existing attributes) & add them to the shared bag.
- If those don't work, give up.
- @param ktd the KinTermDef that this ClauseBody is part of.
- @param hypo the current context.
- @param egoBag collection of hypothetical persons (M & F) who can be 'ego.'
- @throws KSBadHornClauseException if this clause contains literals that are syntactically correct, but have logical flaws.
- @throws KSConstraintInconsistency if the constraints specified or implied in this clause are contradictory.
- @throws KSInternalErrorException if KS system has processed a literal improperly: send Bug Report!
- @throws ClassNotFoundException if an invalid type name is found in a user-defined property
- */
- public void generateExamples(Context hypo, ArrayList<Object> egoBag, Dyad dyad, Oracle orca)
- throws KSBadHornClauseException, KSInternalErrorException, KSConstraintInconsistency, ClassNotFoundException {
- Individual ego = null;
- boolean oKay = false;
- int loops = 0, spares = 2,
- indivReset = hypo.indSerNumGen,
- famReset = hypo.famSerNumGen;
- String pad = "";
- ConstraintObj constraints = null;
- TreeMap bindings = null, badBindings;
- ArrayList<Object> genderStuff, starStuff, starBindings, eBagCopy = new ArrayList<Object>(egoBag), pcStr = null;
- Iterator bagIter = eBagCopy.iterator(), bodyIter;
- // CLAUSE COUNTER
- if (Library.parseClauseCounterOn && !ktd.kinTerm.equals(priorPred)) {
- if (!priorPred.equals("")) {
- pad = "";
- if (++seq < 10) {
- pad = " ";
- } else if (seq < 100) {
- pad = " ";
- }
- System.out.println(priorPred + ": " + pad + seq + " - " + dups + " = " + (seq - dups));
- seqTotal += seq;
- dupTotal += dups;
- }
- priorPred = ktd.kinTerm;
- dups = 0;
- }
- seq = seqNmbr;
- // END OF CLAUSE COUNTER
- // if (ktd.kinTerm.equals("hagaah")) Context.breakpoint();
- // else Context.breakFlag = false;
- // distanceLimit is enforced only during simDataGen for Leave-One-Out
- // Since nearly all PC_String components are 2 or 3 characters, we let
- // (floor(half the length of the PC_String)) -1 = a rough metric of relationship distance
- try {
- int stringDist = 0,
- pcStrLength = (pcString == null ? 0 : pcString.length());
- if (hypo.simDataGen) {
- stringDist = Math.min(Math.max((pcStrLength / 2) - 1, 0), Library.ClauseCounts.maxDist);
- }
- if (hypo.simDataGen && stringDist > distanceLimit) {
- return;
- }
- try {
- while (!oKay // && (loops++ == 0 || ! hypo.simDataGen) // Experimental
- && (bagIter.hasNext() || spares > 0)) { // the Big While Loop
- valRemover(body, new ArrayList<Object>()); // This will remove all "leftover" constraints & values from all variables in this ClauseBody
- if (bagIter.hasNext()) {
- ego = (Individual) bagIter.next();
- } else { // All existing Ego's have failed; make a fresh spare (M or F) for final try.
- if (spares > 1) {
- spares = 1;
- ego = new Individual("Ego", "F");
- } else {
- spares = 0;
- ego = new Individual("Ego", "M");
- }
- if (ktd.domTh.addressTerms) {
- ego.node.kinTermsAddr.add("Ego");
- } else {
- ego.node.kinTermsRef.add("Ego");
- }
- ego.setDateOfBirth("1970-01-01");
- }
- oKay = true;
- constraints = new ConstraintObj();
- genderStuff = new ArrayList<Object>();
- starStuff = new ArrayList<Object>();
- starBindings = new ArrayList<Object>();
- bodyIter = body.iterator();
- // if (loops++ > 0) System.out.println("With Ego = #" + ego.serialNmbr + ", re-trying " + ktd.kinTerm);
- // if (ktd.kinTerm.equals("dad")) System.out.println("With Ego #" + ego.serialNmbr + ", generating " + ktd.kinTerm + ":" + seqNmbr);
- /* if (Context.breakFlag) {
- System.out.println("With Ego = #" + ego.serialNmbr + ", generating " + ktd.kinTerm + ":" + seqNmbr);
- Context.breakpoint();
- } */
- while (oKay && bodyIter.hasNext()) // if any literal specifies ego gender ...
- {
- oKay = ((Literal) bodyIter.next()).constraintCheck(ego.gender, constraints, genderStuff, starStuff);
- }
- // constraintCheck, by side-effect, builds all constraints
- if (oKay) { // 1st OK
- bindings = new TreeMap();
- badBindings = new TreeMap();
- bindings.put("Ego", ego);
- oKay = LiteralAbstract1.finalConstraintCheck(ego.gender, bindings, constraints, body, genderStuff, starStuff);
- // finalConstraintCheck does post-processing & a final conflict-check.
- if (oKay) { // 2nd OK
- ArrayList<Object> bodyCopy = new ArrayList<Object>(body), starStuffCopy = new ArrayList<Object>(starStuff), empties;
- Literal next = null;
- while (((bodyCopy.size() > 0) || (starStuffCopy.size() > 0)) && (next == null)) {
- next = pop(bodyCopy, starStuffCopy, bindings, ktd.kinTerm); // next = first non-constraint literal in body
- }
- if (next == null) {
- throw new KSBadHornClauseException("No processable literals in:\n" + ktd.kinTerm + " :- " + lineBreaker(body));
- }
- // start the process with next. First, find any star-props for Ego
- Variable egoVar = null;
- for (int i = 0; i < next.args.size(); i++) {
- if (((Argument) next.args.get(i)).argName.equals("Ego")) {
- egoVar = (Variable) next.args.get(i);
- }
- }
- // Record which of Ego's star-props was blank before we started this CB.
- // Those are the only ones we can erase or change.
- empties = new ArrayList<Object>();
- UserDefinedProperty udp;
- if (ego.userDefinedProperties != null) {
- Iterator egoUDPiter = ego.userDefinedProperties.values().iterator();
- while (egoUDPiter.hasNext()) {
- udp = (UserDefinedProperty) egoUDPiter.next();
- if (udp.value.isEmpty()) {
- empties.add(udp.starName);
- }
- }
- }
- oKay = next.meetsStarSpecs(ego, egoVar, constraints, starBindings, bindings, "commit", this);
- if (oKay) { // 3rd OK
- // Find/Create will use level, pcCounter & sCounter. Re-initialize them to start.
- resetCounters();
- LiteralAbstract1.negativeConstraintPhase = false; // fresh start
- pcStr = new ArrayList<Object>(); // start with a blank PC-String
- oKay = next.findOrCreate(bodyCopy, starStuffCopy, bindings, badBindings, starBindings, constraints, ktd.kinTerm,
- this, pcStr, dyad);
- if ((!oKay) && (empties.size() > 0)) {
- // Recursive descent or negatedConstraints failed. Empties contains star properties that we are free to change
- // in this effort, and might have caused failure to find a conforming value for a UDP. Try 'em all.
- // If altering each of those doesn't help, then it's hopeless.
- // For each potentially ill-chosen UDP, try to pick a different UDP value for Ego & try again.
- String failure;
- Literal starLit;
- ArrayList<Object> allStars = new ArrayList<Object>(), cumPriorVals = new ArrayList<Object>(), allStarMathVars = new ArrayList<Object>();
- TreeMap thisUDMap = (TreeMap) constraints.userDefined.get(egoVar);
- MathVariable argForUDPVal;
- for (int j = 0; j < starStuff.size(); j++) {
- starLit = (Literal) starStuff.get(j);
- failure = starLit.predicate.name;
- argForUDPVal = (MathVariable) starLit.args.get(0);
- if (failure.substring(0, 1).equals("*") && (!allStars.contains(failure))) {
- allStars.add(failure);
- }
- if (failure.substring(0, 1).equals("*") && (!allStarMathVars.contains(argForUDPVal))) {
- allStarMathVars.add(argForUDPVal);
- }
- } // Now allStars is a list of all possible *-props that might have caused failure & allStarMathVars is the associated variables.
- Iterator starIter = allStars.iterator();
- Object pv = null;
- while ((!oKay) && (starIter.hasNext())) {
- failure = (String) starIter.next();
- if ((thisUDMap != null) && (thisUDMap.get(failure) != null)
- && (empties.contains(failure))
- && (!(thisUDMap.get(failure) instanceof Constant))) {
- // Ego has a constraint on this StarProp, his value was blank before this effort,
- // and the argument defining its constraint is not a Constant (ergo, it's a MathVar)
- argForUDPVal = (MathVariable) thisUDMap.get(failure);
- // If we can try again with a different value for UDP, do it. If not, fall thru to failure.
- LiteralAbstract1.failReason = null;
- boolean newValFound = true;
- cumPriorVals.clear();
- udp = (UserDefinedProperty) ego.userDefinedProperties.get(failure);
- while ((!oKay) && newValFound) {
- bindings.clear();
- starBindings.clear();
- badBindings.clear();
- bindings.put("Ego", ego);
- udp.value.clear();
- argForUDPVal.updatePriorVals(cumPriorVals);
- newValFound = next.newUDPVal(failure, argForUDPVal, "Ego", bindings, starBindings, constraints, this);
- if (newValFound) {
- if (argForUDPVal.priorValues != null) {
- for (int i = 0; i < argForUDPVal.priorValues.size(); i++) {
- pv = argForUDPVal.priorValues.get(i);
- if (!cumPriorVals.contains(pv)) {
- cumPriorVals.add(pv);
- }
- } // Save the PriorVals for the "experimental variable"
- }
- for (int i = 0; i < allStarMathVars.size(); i++) { // Erase PriorVals for all other MathVars
- Variable var = (Variable) allStarMathVars.get(i);
- if (var.priorValues != null) {
- var.priorValues.clear();
- }
- }
- argForUDPVal.updatePriorVals(cumPriorVals); // Restore the record for the "experimental variable."
- ArrayList<Object> pcStr2 = new ArrayList<Object>(); // start with a blank PC-String
- if (next.meetsStarSpecs(ego, egoVar, constraints, starBindings, bindings, "commit", this)) {
- oKay = next.findOrCreate(bodyCopy, starStuffCopy, bindings, badBindings, starBindings,
- constraints, ktd.kinTerm, this, pcStr2, dyad);
- if (oKay) {
- pcStr = pcStr2;
- }
- }
- …
Large files files are truncated, but you can click here to view the full file