public CondensorSentenceDomainModel(ISentenceForm newForm, ISentenceFormDomain newFormDomain, ISentenceDomain oldModel) { _newForm = newForm; _newFormDomain = newFormDomain; _oldModel = oldModel; }
private static bool GoodCondensationSetByHeuristic(ICollection<Expression> minSet, Implication rule, ISentenceDomain model, IConstantChecker checker, UnusedSentenceNameSource sentenceNameSource) { //We actually want the sentence model here so we can see the domains //also, if it's a constant, ... //Anyway... we want to compare the heuristic for the number of assignments //and/or links that will be generated with or without the condensation set //Heuristic for a rule is A*(L+1), where A is the number of assignments and //L is the number of literals, unless L = 1, in which case the heuristic is //just A. This roughly captures the number of links that would be generated //if this rule were to be generated. //Obviously, there are differing degrees of accuracy with which we can //represent A. //One way is taking the product of all the variables in all the domains. //However, we can do better by actually asking the Assignments class for //its own heuristic of how it would implement the rule as-is. //The only tricky aspect here is that we need an up-to-date SentenceModel, //and in some cases this could be expensive to compute. Might as well try //it, though... //Heuristic for the rule as-is: long assignments = AssignmentsImpl.GetNumAssignmentsEstimate(rule, SentenceDomainModels.GetVarDomains(rule, model, SentenceDomainModels.VarDomainOpts.IncludeHead), checker); int literals = rule.Consequent.Arity; if (literals > 1) literals++; //We have to "and" the literals together //Note that even though constants will be factored out, we're concerned here //with getting through them in a reasonable amount of time, so we do want to //count them. TODO: Not sure if they should be counted in L, though... long curRuleHeuristic = assignments * literals; //And if we split them up... List<Implication> newRules = ApplyCondensation(minSet, rule, sentenceNameSource); Implication r1 = newRules[0], r2 = newRules[1]; //Augment the model ISentenceDomain newModel = AugmentModelWithNewForm(model, newRules); long a1 = AssignmentsImpl.GetNumAssignmentsEstimate(r1, SentenceDomainModels.GetVarDomains(r1, newModel, SentenceDomainModels.VarDomainOpts.IncludeHead), checker); long a2 = AssignmentsImpl.GetNumAssignmentsEstimate(r2, SentenceDomainModels.GetVarDomains(r2, newModel, SentenceDomainModels.VarDomainOpts.IncludeHead), checker); int l1 = r1.Consequent.Arity; if (l1 > 1) l1++; int l2 = r2.Consequent.Arity; if (l2 > 1) l2++; //Whether we split or not depends on what the two heuristics say long newRulesHeuristic = a1 * l1 + a2 * l2; return newRulesHeuristic < curRuleHeuristic; }
private static ISet<Expression> GetCondensationSet(Implication rule, ISentenceDomain model, IConstantChecker checker, UnusedSentenceNameSource sentenceNameSource) { //We use each variable as a starting point List<TermVariable> varsInRule = rule.VariablesOrEmpty.ToList(); List<TermVariable> varsInHead = rule.Consequent.VariablesOrEmpty.ToList(); var varsNotInHead = new List<TermVariable>(varsInRule); varsNotInHead.RemoveAll(varsInHead.Contains); foreach (TermVariable var in varsNotInHead) { var minSet = new HashSet<Expression>(); foreach (Expression literal in rule.Antecedents.Conjuncts) if (literal.VariablesOrEmpty.Contains(var)) minSet.Add(literal); //#1 is already done //Now we try #2 var varsNeeded = new HashSet<TermVariable>(); var varsSupplied = new HashSet<TermVariable>(); foreach (Expression literal in minSet) { if (literal is Negation) { foreach (var variable in literal.VariablesOrEmpty) varsNeeded.Add(variable); } else if (literal is Fact) { if (((Fact)literal).RelationName == GameContainer.Parser.TokDistinct) foreach (var variable in literal.VariablesOrEmpty) varsNeeded.Add(variable); else foreach (var variable in literal.VariablesOrEmpty) varsSupplied.Add(variable); } } varsNeeded.RemoveWhere(varsSupplied.Contains); if (varsNeeded.Any()) continue; var candidateSuppliersList = new List<ISet<Expression>>(); foreach (TermVariable varNeeded in varsNeeded) { var suppliers = new HashSet<Expression>(); foreach (Expression literal in rule.Antecedents.Conjuncts) if (literal is Fact) if (literal.VariablesOrEmpty.Contains(varNeeded)) suppliers.Add(literal); candidateSuppliersList.Add(suppliers); } //TODO: Now... I'm not sure if we want to minimize the number of literals added, or the number of variables added //Right now, I don't have time to worry about optimization. Currently, we pick one at random //TODO: Optimize this var literalsToAdd = new HashSet<Expression>(); foreach (ISet<Expression> suppliers in candidateSuppliersList) if (!suppliers.Intersect(literalsToAdd).Any()) literalsToAdd.Add(suppliers.First()); minSet.UnionWith(literalsToAdd); if (GoodCondensationSetByHeuristic(minSet, rule, model, checker, sentenceNameSource)) return minSet; } return null; }
private static ISentenceFormDomain GetNewFormDomain(Implication condensingRule, ISentenceDomain oldModel, ISentenceForm newForm) { var varDomains = SentenceDomainModels.GetVarDomains(condensingRule, oldModel, SentenceDomainModels.VarDomainOpts.BodyOnly); var domainsForSlots = new List<ISet<TermObject>>(); foreach (Term term in condensingRule.Consequent.NestedTerms) { if (!(term is TermVariable)) throw new Exception("Expected all slots in the head of a condensing rule to be variables, but the rule was: " + condensingRule); domainsForSlots.Add(varDomains[(TermVariable)term]); } return new CartesianSentenceFormDomain(newForm, domainsForSlots); }
private static ISentenceDomain AugmentModelWithNewForm(ISentenceDomain oldModel, List<Implication> newRules) { var newForm = new SimpleSentenceForm(newRules[0].Consequent); ISentenceFormDomain newFormDomain = GetNewFormDomain(newRules[0], oldModel, newForm); return new CondensorSentenceDomainModel(newForm, newFormDomain, oldModel); }