Example #1
0
        public Sequent Apply(Sequent sequent)
        {
            UnaryFormula implicationFormula = (UnaryFormula)sequent.RightHandSide.Formulas.Where(
                x => x is UnaryFormula formula && formula.Connective == UnaryConnective.Necessity
                ).FirstOrDefault();

            if (implicationFormula == null)
            {
                return(null);
            }


            var formula = implicationFormula.Formula.Clone();

            if (formula.WorldIndex.IsGround && formula.FreeVariables.Count == 0)
            {
                formula.WorldIndex.AddSymbol(LogicSolver.WorldService.GetNewWorldConstant());
            }
            else
            {
                var skolemVariables = new List <WorldSymbol>(formula.WorldIndex.Symbols);
                skolemVariables.AddRange(formula.FreeVariables.Select(x => x.ToWorldSymbol()));
                formula.WorldIndex.AddSymbol(LogicSolver.WorldService.GetNewWorldFunction(skolemVariables));
            }
            sequent.RightHandSide.Formulas.Remove(implicationFormula);
            sequent.RightHandSide.Formulas.Add(formula);

            sequent.Justification = "R7 (" + sequent.Name + ")";

            return(sequent);
        }
Example #2
0
        public Sequent Apply(Sequent sequent)
        {
            QuantifierFormula implicationFormula = (QuantifierFormula)sequent.RightHandSide.Formulas.Where
                                                   (
                x => x is QuantifierFormula formula && formula.Quantifier == QuantifierConnective.ForAll
                                                   ).FirstOrDefault();

            if (implicationFormula == null)
            {
                return(null);
            }

            var formula = implicationFormula.Formula.Clone();

            Terminal a;

            if (implicationFormula.FreeVariables.Count == 0 && implicationFormula.WorldIndex.IsGround)
            {
                a = termNamer.GetNewConstant();
            }
            else
            {
                var skolemVariables = new List <Terminal>(formula.WorldIndex.Symbols.Select(x => x.ToTerminal()));
                skolemVariables.AddRange(implicationFormula.FreeVariables);
                a = termNamer.GetNewFunction(skolemVariables);
            }

            formula.ApplySubstitution(new Substitution(implicationFormula.Variable, a));

            sequent.RightHandSide.Formulas.Remove(implicationFormula);
            sequent.RightHandSide.Formulas.Add(formula);

            sequent.Justification = "R9 (" + sequent.Name + ")";
            return(sequent);
        }
Example #3
0
        public List <Sequent> Apply(Sequent leftS, Sequent rightS, bool recurse = true)
        {
            leftS  = leftS.Clone();
            rightS = rightS.Clone();

            var ps = leftS.LeftHandSide.Formulas;
            var qs = rightS.RightHandSide.Formulas;

            //if ((leftS.LeftHandSide.Count == 0 && leftS.RightHandSide.Count != 0) &&
            //    (rightS.RightHandSide.Count == 0 && rightS.LeftHandSide.Count != 0))
            //{
            //    ps = rightS.LeftHandSide.Formulas;
            //    qs = leftS.RightHandSide.Formulas;
            //}

            foreach (var formulaP in ps)
            {
                relation.AddWorldIndex(formulaP.WorldIndex);
                foreach (var formulaQ in qs)
                {
                    relation.AddWorldIndex(formulaQ.WorldIndex);

                    var unification = formulaP.MUnify(relation, formulaQ);
                    if (unification == null)
                    {
                        continue;
                    }

                    leftS.LeftHandSide.Formulas.ForEach(x => x.ApplySubstitution(unification));
                    rightS.LeftHandSide.Formulas.ForEach(x => x.ApplySubstitution(unification));

                    leftS.RightHandSide.Formulas.ForEach(x => x.ApplySubstitution(unification));
                    rightS.RightHandSide.Formulas.ForEach(x => x.ApplySubstitution(unification));

                    var result = new Sequent();

                    result.LeftHandSide.Formulas.AddRange(leftS.LeftHandSide.Formulas);
                    result.LeftHandSide.Formulas.AddRange(rightS.LeftHandSide.Formulas);

                    result.RightHandSide.Formulas.AddRange(leftS.RightHandSide.Formulas);
                    result.RightHandSide.Formulas.AddRange(rightS.RightHandSide.Formulas);

                    result.LeftHandSide.Formulas.Remove(formulaP);
                    result.RightHandSide.Formulas.Remove(formulaQ);

                    result.Name = "R1 (" + leftS.Name + ", " + rightS.Name + ") with " + unification.ToString();
                    return(new List <Sequent>()
                    {
                        result
                    });
                }
            }

            if (recurse)
            {
                return(Apply(rightS, leftS, false));
            }

            return(null);
        }
Example #4
0
        private static void AddSequent(Hashtable cases, Sequent s)
        {
            object key = s.head.Predicate;

            if (key is Variable)
            {
                key = "WILDCARD";
            }
            ArrayList list = (ArrayList)cases[key];

            if (list == null)
            {
                list       = new ArrayList();
                cases[key] = list;
            }
            list.Add(s);
        }
Example #5
0
        public Sequent Apply(Sequent sequent)
        {
            UnaryFormula implicationFormula = (UnaryFormula)sequent.LeftHandSide.Formulas.Where(
                x => x is UnaryFormula formula && formula.Connective == UnaryConnective.Negation
                ).FirstOrDefault();

            if (implicationFormula == null)
            {
                return(null);
            }

            sequent.LeftHandSide.Formulas.Remove(implicationFormula);

            var formula = implicationFormula.Formula.Clone();

            sequent.RightHandSide.Formulas.Add(formula);
            sequent.Justification = "R5 (" + sequent.Name + ")";

            return(sequent);
        }
Example #6
0
        public Sequent Apply(Sequent sequent)
        {
            QuantifierFormula implicationFormula = (QuantifierFormula)sequent.LeftHandSide.Formulas.Where
                                                   (
                x => x is QuantifierFormula formula && formula.Quantifier == QuantifierConnective.ForAll
                                                   ).FirstOrDefault();

            if (implicationFormula == null)
            {
                return(null);
            }

            var formula = implicationFormula.Formula.Clone();

            formula.ApplySubstitution(new Substitution(implicationFormula.Variable, LogicSolver.TermNamer.GetNewVariable()));

            sequent.LeftHandSide.Formulas.Remove(implicationFormula);
            sequent.LeftHandSide.Formulas.Add(formula);
            sequent.Justification = "R10 (" + sequent.Name + ")";

            return(sequent);
        }
Example #7
0
        public Sequent Apply(Sequent sequent)
        {
            UnaryFormula implicationFormula = (UnaryFormula)sequent.LeftHandSide.Formulas.Where
                                              (
                x => x is UnaryFormula formula && formula.Connective == UnaryConnective.Necessity
                                              ).FirstOrDefault();

            if (implicationFormula == null)
            {
                return(null);
            }

            sequent.LeftHandSide.Formulas.Remove(implicationFormula);

            var formula = implicationFormula.Formula.Clone();


            formula.WorldIndex.AddSymbol(LogicSolver.WorldService.GetNewWorldVariable());
            sequent.LeftHandSide.Formulas.Add(formula);

            sequent.Justification = "R8 (" + sequent.Name + ")";

            return(sequent);
        }
Example #8
0
        public bool Solve(Formula formula)
        {
            formula.Simplify();
            var initialSequent = new Sequent(formula);

            var queue = new Queue <Sequent>();

            var sequentCounter = 0;

            initialSequent.Name = sequentCounter.ToString();
            sequentCounter++;

            Console.WriteLine();
            Console.WriteLine(initialSequent.Name + " :|: " + initialSequent);
            Console.WriteLine();

            queue.Enqueue(initialSequent);
            var sequentList = new List <Sequent>();

            while (queue.Count != 0)
            {
                var sequent = queue.Dequeue();

                Parallel.ForEach(rules, x =>
                {
                    var result = x.Apply(sequent.Clone());
                    if (result != null)
                    {
                        result.Name = sequentCounter.ToString();
                        sequentCounter++;
                        queue.Enqueue(result);

                        Log.Add(result.ToString());
                        Console.WriteLine(result.Name + " :|: " + result);

                        if (result.IsReduced)
                        {
                            sequentList.Add(result);
                        }
                    }
                });
            }


            try
            {
                var res = resolutionRule.Apply(sequentList[0], sequentList[1]);
                Console.WriteLine();

                if (res == null)
                {
                    return(false);
                }

                else if (res[0].IsEmpty)
                {
                    Console.WriteLine("Found Proof: " + res[0].Name);
                    return(true);
                }
                return(false);
            } catch
            {
                return(false);
            }
        }
Example #9
0
        private static ArrayList prove(Hashtable cases, SelectableSource world, Statement[] goal, int maxNumberOfSteps)
        {
            // This is the main routine from euler.js.

            // cases: Resource (predicate) => IList of Sequent

            if (world != null)             // cache our queries to the world, if a world is provided
            {
                world = new SemWeb.Stores.CachedSource(world);
            }

            StatementMap cached_subproofs = new StatementMap();

            // Create the queue and add the first item.
            ArrayList queue = new ArrayList();
            {
                QueueItem start = new QueueItem();
                start.env    = new Hashtable();
                start.rule   = new Sequent(Statement.All, goal, null);
                start.src    = null;
                start.ind    = 0;
                start.parent = null;
                start.ground = new ArrayList();
                queue.Add(start);
                if (Debug)
                {
                    Console.Error.WriteLine("Euler: Queue: " + start);
                }
            }

            // The evidence array holds the results of this proof.
            ArrayList evidence = new ArrayList();

            // Track how many steps we take to not go over the limit.
            int step = 0;

            // Process the queue until it's empty or we reach our step limit.
            while (queue.Count > 0)
            {
                // deal with the QueueItem at the top of the queue
                QueueItem c = (QueueItem)queue[queue.Count - 1];
                queue.RemoveAt(queue.Count - 1);
                ArrayList g = new ArrayList(c.ground);

                // have we done too much?
                step++;
                if (maxNumberOfSteps != -1 && step >= maxNumberOfSteps)
                {
                    if (Debug)
                    {
                        Console.Error.WriteLine("Euler: Maximum number of steps exceeded.  Giving up.");
                    }
                    return(null);
                }

                // if each statement in the body of the sequent has been proved
                if (c.ind == c.rule.body.Length)
                {
                    // if this is the top-level sequent being proved; we've found a complete evidence for the goal
                    if (c.parent == null)
                    {
                        EvidenceItem ev = new EvidenceItem();
                        ev.head = new Statement[c.rule.body.Length];
                        bool canRepresentHead = true;
                        for (int i = 0; i < c.rule.body.Length; i++)
                        {
                            ev.head[i] = evaluate(c.rule.body[i], c.env);
                            if (ev.head[i].AnyNull)                             // can't represent it: literal in subject position, for instance
                            {
                                canRepresentHead = false;
                            }
                        }

                        ev.body = c.ground;
                        ev.env  = c.env;

                        if (Debug)
                        {
                            Console.Error.WriteLine("Euler: Found Evidence: " + ev);
                        }

                        if (!canRepresentHead)
                        {
                            continue;
                        }

                        evidence.Add(ev);

                        // this is a subproof of something; whatever it is a subgroup for can
                        // be incremented
                    }
                    else
                    {
                        // if the rule had no body, it was just an axiom and we represent that with Ground
                        if (c.rule.body.Length != 0)
                        {
                            g.Add(new Ground(c.rule, c.env));
                        }

                        // advance the parent being proved and put the advanced
                        // parent into the queue; unify the parent variable assignments
                        // with this one's
                        QueueItem r = new QueueItem();
                        r.rule   = c.parent.rule;
                        r.src    = c.parent.src;
                        r.ind    = c.parent.ind;
                        r.parent = c.parent.parent;
                        r.env    = (Hashtable)c.parent.env.Clone();
                        r.ground = g;
                        unify(c.rule.head, c.env, r.rule.body[r.ind], r.env, true);
                        r.ind++;
                        queue.Add(r);
                        if (Debug)
                        {
                            Console.Error.WriteLine("Euler: Queue Advancement: " + r);
                        }

                        // The number of live children for this parent is decremented since we are
                        // done with this subproof, but we store the result for later.
                        if (c.parent.solutions == null)
                        {
                            c.parent.solutions = new StatementList();
                        }
                        c.parent.solutions.Add(evaluate(r.rule.body[r.ind - 1], r.env));
                        decrementLife(c.parent, cached_subproofs);
                    }

                    // this sequent still has parts of the body left to be proved; try to
                    // find evidence for the next statement in the body, and if we find
                    // evidence, queue up that evidence
                }
                else
                {
                    // this is the next part of the body that we need to try to prove
                    Statement t = c.rule.body[c.ind];

                    // Try to process this predicate with a user-provided custom
                    // function that resolves things like mathematical relations.
                    // euler.js provides similar functionality, but the system
                    // of user predicates is completely different here.
                    RdfRelation b = FindUserPredicate(t.Predicate);
                    if (b != null)
                    {
                        Resource[] args;
                        Variable[] unifyResult;
                        Resource   value = evaluate(t.Object, c.env);

                        if (!c.rule.callArgs.ContainsKey(t.Subject))
                        {
                            // The array of arguments to this relation is just the subject of the triple itself
                            args        = new Resource[] { evaluate(t.Subject, c.env) };
                            unifyResult = new Variable[1];
                            if (t.Subject is Variable)
                            {
                                unifyResult[0] = (Variable)t.Subject;
                            }
                        }
                        else
                        {
                            // The array of arguments to this relation comes from a pre-grouped arg list.
                            args        = (Resource[])c.rule.callArgs[t.Subject];
                            unifyResult = new Variable[args.Length];

                            for (int i = 0; i < args.Length; i++)
                            {
                                if (args[i] is Variable)
                                {
                                    unifyResult[i] = (Variable)args[i];
                                    args[i]        = evaluate(args[i], c.env);
                                }
                            }
                        }

                        // Run the user relation on the array of arguments (subject) and on the object.
                        if (b.Evaluate(args, ref value))
                        {
                            // If it succeeds, we press on.

                            // The user predicate may update the 'value' variable and the argument
                            // list array, and so we want to unify any variables in the subject
                            // or object of this user predicate with the values given to us
                            // by the user predicate.
                            Hashtable newenv = (Hashtable)c.env.Clone();
                            if (t.Object is Variable)
                            {
                                unify(value, null, t.Object, newenv, true);
                            }
                            for (int i = 0; i < args.Length; i++)
                            {
                                if (unifyResult[i] != null)
                                {
                                    unify(args[i], null, unifyResult[i], newenv, true);
                                }
                            }

                            Statement grnd = evaluate(t, newenv);
                            if (grnd != Statement.All)                             // sometimes not representable, like if literal as subject
                            {
                                g.Add(new Ground(new Sequent(grnd, new Statement[0], null), new Hashtable()));
                            }

                            QueueItem r = new QueueItem();
                            r.rule   = c.rule;
                            r.src    = c.src;
                            r.ind    = c.ind;
                            r.parent = c.parent;
                            r.env    = newenv;
                            r.ground = g;
                            r.ind++;
                            queue.Add(r);

                            // Note: Since we are putting something back in for c, we don't touch the life counter on the parent.
                        }
                        else
                        {
                            // If the predicate fails, decrement the life of the parent.
                            decrementLife(c.parent, cached_subproofs);
                        }
                        continue;
                    }

                    // t can be proved either by the use of a rule
                    // or if t literally exists in the world

                    Statement t_resolved = evaluate(t, c.env);

                    // If resolving this statement requires putting a literal in subject or predicate position, we
                    // can't prove it.
                    if (t_resolved == Statement.All)
                    {
                        decrementLife(c.parent, cached_subproofs);
                        continue;
                    }

                    ArrayList tcases = new ArrayList();

                    // See if we have already tried to prove this.
                    if (cached_subproofs.ContainsKey(t_resolved))
                    {
                        StatementList cached_solutions = (StatementList)cached_subproofs[t_resolved];
                        if (cached_solutions == null)
                        {
                            if (Debug)
                            {
                                Console.Error.WriteLine("Euler: Dropping queue item because we have already failed to prove it: " + t_resolved);
                            }
                        }
                        else
                        {
                            foreach (Statement s in cached_solutions)
                            {
                                if (Debug)
                                {
                                    Console.Error.WriteLine("Euler: Using Cached Axiom:  " + s);
                                }
                                Sequent seq = new Sequent(s);
                                tcases.Add(seq);
                            }
                        }
                    }
                    else
                    {
                        // get all of the rules that apply to the predicate in question
                        if (t_resolved.Predicate != null && cases.ContainsKey(t_resolved.Predicate))
                        {
                            tcases.AddRange((IList)cases[t_resolved.Predicate]);
                        }

                        if (cases.ContainsKey("WILDCARD"))
                        {
                            tcases.AddRange((IList)cases["WILDCARD"]);
                        }

                        // if t has no unbound variables and we've matched something from
                        // the axioms, don't bother looking at the world, and don't bother
                        // proving it any other way than by the axiom.
                        bool lookAtWorld = true;
                        foreach (Sequent seq in tcases)
                        {
                            if (seq.body.Length == 0 && seq.head == t_resolved)
                            {
                                lookAtWorld = false;
                                tcases.Clear();
                                tcases.Add(seq);
                                break;
                            }
                        }

                        // if there is a seprate world, get all of the world
                        // statements that witness t
                        if (world != null && lookAtWorld)
                        {
                            MemoryStore w = new MemoryStore();

                            if (Debug)
                            {
                                Console.Error.WriteLine("Running " + c);
                            }
                            if (Debug)
                            {
                                Console.Error.WriteLine("Euler: Ask World: " + t_resolved);
                            }
                            world.Select(t_resolved, w);
                            foreach (Statement s in w)
                            {
                                if (Debug)
                                {
                                    Console.Error.WriteLine("Euler: World Select Response:  " + s);
                                }
                                Sequent seq = new Sequent(s);
                                tcases.Add(seq);
                            }
                        }
                    }

                    // If there is no evidence or potential evidence (i.e. rules)
                    // for t, then we will dump this QueueItem by not queuing any
                    // subproofs.

                    // Otherwise we try each piece of evidence in turn.
                    foreach (Sequent rl in tcases)
                    {
                        ArrayList g2 = (ArrayList)c.ground.Clone();
                        if (rl.body.Length == 0)
                        {
                            g2.Add(new Ground(rl, new Hashtable()));
                        }

                        QueueItem r = new QueueItem();
                        r.rule   = rl;
                        r.src    = rl;
                        r.ind    = 0;
                        r.parent = c;
                        r.env    = new Hashtable();
                        r.ground = g2;

                        if (unify(t, c.env, rl.head, r.env, true))
                        {
                            QueueItem ep = c;                              // euler path
                            while ((ep = ep.parent) != null)
                            {
                                if (ep.src == c.src && unify(ep.rule.head, ep.env, c.rule.head, c.env, false))
                                {
                                    break;
                                }
                            }
                            if (ep == null)
                            {
                                // It is better for caching subproofs to work an entire proof out before
                                // going on, which means we want to put the new queue item at the
                                // top of the stack.
                                queue.Add(r);
                                c.liveChildren++;
                                if (Debug)
                                {
                                    Console.Error.WriteLine("Euler: Queue from Axiom: " + r);
                                }
                            }
                        }
                    }

                    // If we did not add anything back into the queue for this item, then
                    // we decrement the life of the parent.
                    if (c.liveChildren == 0)
                    {
                        decrementLife(c.parent, cached_subproofs);
                    }
                }
            }

            return(evidence);
        }
Example #10
0
            public Hashtable env;            // substitution environment: Resource => Resource

            public Ground(Sequent src, Hashtable env)
            {
                this.src = src;
                this.env = env;
            }
Example #11
0
 public List <Sequent> Apply(Sequent leftS, Sequent rightS)
 {
     return(Apply(leftS, rightS, true));
 }
Example #12
0
            public Sequent src; // evidence

            #endregion Fields

            #region Constructors

            public Ground(Sequent src, Hashtable env)
            {
                this.src = src;
                this.env = env;
            }
Example #13
0
        private static ArrayList prove(Hashtable cases, SelectableSource world, Statement[] goal, int maxNumberOfSteps)
        {
            // This is the main routine from euler.js.

            // cases: Resource (predicate) => IList of Sequent

            if (world != null) // cache our queries to the world, if a world is provided
                world = new SemWeb.Stores.CachedSource(world);

            StatementMap cached_subproofs = new StatementMap();

            // Create the queue and add the first item.
            ArrayList queue = new ArrayList();
            {
                QueueItem start = new QueueItem();
                start.env = new Hashtable();
                start.rule = new Sequent(Statement.All, goal, null);
                start.src = null;
                start.ind = 0;
                start.parent = null;
                start.ground = new ArrayList();
                queue.Add(start);
                if (Debug) Console.Error.WriteLine("Euler: Queue: " + start);
            }

            // The evidence array holds the results of this proof.
            ArrayList evidence = new ArrayList();

            // Track how many steps we take to not go over the limit.
            int step = 0;

            // Process the queue until it's empty or we reach our step limit.
            while (queue.Count > 0) {
                // deal with the QueueItem at the top of the queue
                QueueItem c = (QueueItem)queue[queue.Count-1];
                queue.RemoveAt(queue.Count-1);
                ArrayList g = new ArrayList(c.ground);

                // have we done too much?
                step++;
                if (maxNumberOfSteps != -1 && step >= maxNumberOfSteps) {
                    if (Debug) Console.Error.WriteLine("Euler: Maximum number of steps exceeded.  Giving up.");
                    return null;
                }

                // if each statement in the body of the sequent has been proved
                if (c.ind == c.rule.body.Length) {
                    // if this is the top-level sequent being proved; we've found a complete evidence for the goal
                    if (c.parent == null) {
                        EvidenceItem ev = new EvidenceItem();
                        ev.head = new Statement[c.rule.body.Length];
                        bool canRepresentHead = true;
                        for (int i = 0; i < c.rule.body.Length; i++) {
                            ev.head[i] = evaluate(c.rule.body[i], c.env);
                            if (ev.head[i].AnyNull) // can't represent it: literal in subject position, for instance
                                canRepresentHead = false;
                        }

                        ev.body = c.ground;
                        ev.env = c.env;

                        if (Debug) Console.Error.WriteLine("Euler: Found Evidence: " + ev);

                        if (!canRepresentHead)
                            continue;

                        evidence.Add(ev);

                    // this is a subproof of something; whatever it is a subgroup for can
                    // be incremented
                    } else {
                        // if the rule had no body, it was just an axiom and we represent that with Ground
                        if (c.rule.body.Length != 0) g.Add(new Ground(c.rule, c.env));

                        // advance the parent being proved and put the advanced
                        // parent into the queue; unify the parent variable assignments
                        // with this one's
                        QueueItem r = new QueueItem();
                        r.rule = c.parent.rule;
                        r.src = c.parent.src;
                        r.ind = c.parent.ind;
                        r.parent = c.parent.parent;
                        r.env = (Hashtable)c.parent.env.Clone();
                        r.ground = g;
                        unify(c.rule.head, c.env, r.rule.body[r.ind], r.env, true);
                        r.ind++;
                        queue.Add(r);
                        if (Debug) Console.Error.WriteLine("Euler: Queue Advancement: " + r);

                        // The number of live children for this parent is decremented since we are
                        // done with this subproof, but we store the result for later.
                        if (c.parent.solutions == null)
                            c.parent.solutions = new StatementList();
                        c.parent.solutions.Add(evaluate(r.rule.body[r.ind-1], r.env));
                        decrementLife(c.parent, cached_subproofs);
                    }

                // this sequent still has parts of the body left to be proved; try to
                // find evidence for the next statement in the body, and if we find
                // evidence, queue up that evidence
                } else {
                    // this is the next part of the body that we need to try to prove
                    Statement t = c.rule.body[c.ind];

                    // Try to process this predicate with a user-provided custom
                    // function that resolves things like mathematical relations.
                    // euler.js provides similar functionality, but the system
                    // of user predicates is completely different here.
                    RdfRelation b = FindUserPredicate(t.Predicate);
                    if (b != null) {
                        Resource[] args;
                        Variable[] unifyResult;
                        Resource value = evaluate(t.Object, c.env);

                        if (!c.rule.callArgs.ContainsKey(t.Subject)) {
                            // The array of arguments to this relation is just the subject of the triple itself
                            args = new Resource[] { evaluate(t.Subject, c.env) };
                            unifyResult = new Variable[1];
                            if (t.Subject is Variable) unifyResult[0] = (Variable)t.Subject;

                        } else {
                            // The array of arguments to this relation comes from a pre-grouped arg list.
                            args = (Resource[])((ICloneable)c.rule.callArgs[t.Subject]).Clone();
                            unifyResult = new Variable[args.Length];

                            for (int i = 0; i < args.Length; i++) {
                                if (args[i] is Variable) {
                                    unifyResult[i] = (Variable)args[i];
                                    args[i] = evaluate(args[i], c.env);
                                }
                            }
                        }

                        // Run the user relation on the array of arguments (subject) and on the object.
                        if (b.Evaluate(args, ref value)) {
                            // If it succeeds, we press on.

                            // The user predicate may update the 'value' variable and the argument
                            // list array, and so we want to unify any variables in the subject
                            // or object of this user predicate with the values given to us
                            // by the user predicate.
                            Hashtable newenv = (Hashtable)c.env.Clone();
                            if (t.Object is Variable) unify(value, null, t.Object, newenv, true);
                            for (int i = 0; i < args.Length; i++)
                                if (unifyResult[i] != null)
                                    unify(args[i], null, unifyResult[i], newenv, true);

                            Statement grnd = evaluate(t, newenv);
                            if (grnd != Statement.All) // sometimes not representable, like if literal as subject
                                g.Add(new Ground(new Sequent(grnd, new Statement[0], null), new Hashtable()));

                            QueueItem r = new QueueItem();
                            r.rule = c.rule;
                            r.src = c.src;
                            r.ind = c.ind;
                            r.parent = c.parent;
                            r.env = newenv;
                            r.ground = g;
                            r.ind++;
                            queue.Add(r);

                            // Note: Since we are putting something back in for c, we don't touch the life counter on the parent.

                        } else {
                            // If the predicate fails, decrement the life of the parent.
                            if (c.parent != null)
                                decrementLife(c.parent, cached_subproofs);
                        }
                        continue;
                    }

                    // t can be proved either by the use of a rule
                    // or if t literally exists in the world

                    Statement t_resolved = evaluate(t, c.env);

                    // If resolving this statement requires putting a literal in subject or predicate position, we
                    // can't prove it.
                    if (t_resolved == Statement.All) {
                        if (c.parent != null)
                            decrementLife(c.parent, cached_subproofs);
                        continue;
                    }

                    ArrayList tcases = new ArrayList();

                    // See if we have already tried to prove this.
                    if (cached_subproofs.ContainsKey(t_resolved)) {
                        StatementList cached_solutions = (StatementList)cached_subproofs[t_resolved];
                        if (cached_solutions == null) {
                            if (Debug) Console.Error.WriteLine("Euler: Dropping queue item because we have already failed to prove it: " + t_resolved);
                        } else {
                            foreach (Statement s in cached_solutions) {
                                if (Debug) Console.Error.WriteLine("Euler: Using Cached Axiom:  " + s);
                                Sequent seq = new Sequent(s);
                                tcases.Add(seq);
                            }
                        }
                    } else {
                        // get all of the rules that apply to the predicate in question
                        if (t_resolved.Predicate != null && cases.ContainsKey(t_resolved.Predicate))
                            tcases.AddRange((IList)cases[t_resolved.Predicate]);

                        if (cases.ContainsKey("WILDCARD"))
                            tcases.AddRange((IList)cases["WILDCARD"]);

                        // if t has no unbound variables and we've matched something from
                        // the axioms, don't bother looking at the world, and don't bother
                        // proving it any other way than by the axiom.
                        bool lookAtWorld = true;
                        foreach (Sequent seq in tcases) {
                            if (seq.body.Length == 0 && seq.head == t_resolved) {
                                lookAtWorld = false;
                                tcases.Clear();
                                tcases.Add(seq);
                                break;
                            }
                        }

                        // if there is a seprate world, get all of the world
                        // statements that witness t
                        if (world != null && lookAtWorld) {
                            MemoryStore w = new MemoryStore();

                            if (Debug) Console.Error.WriteLine("Running " + c);
                            if (Debug) Console.Error.WriteLine("Euler: Ask World: " + t_resolved);
                            world.Select(t_resolved, w);
                            foreach (Statement s in w) {
                                if (Debug) Console.Error.WriteLine("Euler: World Select Response:  " + s);
                                Sequent seq = new Sequent(s);
                                tcases.Add(seq);
                            }
                        }
                    }

                    // If there is no evidence or potential evidence (i.e. rules)
                    // for t, then we will dump this QueueItem by not queuing any
                    // subproofs.

                    // Otherwise we try each piece of evidence in turn.
                    foreach (Sequent rl in tcases) {
                        ArrayList g2 = (ArrayList)c.ground.Clone();
                        if (rl.body.Length == 0) g2.Add(new Ground(rl, new Hashtable()));

                        QueueItem r = new QueueItem();
                        r.rule = rl;
                        r.src = rl;
                        r.ind = 0;
                        r.parent = c;
                        r.env = new Hashtable();
                        r.ground = g2;

                        if (unify(t, c.env, rl.head, r.env, true)) {
                            QueueItem ep = c;  // euler path
                         	while ((ep = ep.parent) != null)
                          		if (ep.src == c.src && unify(ep.rule.head, ep.env, c.rule.head, c.env, false))
                          			break;
                         	if (ep == null) {
                                // It is better for caching subproofs to work an entire proof out before
                                // going on, which means we want to put the new queue item at the
                                // top of the stack.
                         		queue.Add(r);
                                c.liveChildren++;
                         		if (Debug) Console.Error.WriteLine("Euler: Queue from Axiom: " + r);
                         	}
                        }
                    }

                    // If we did not add anything back into the queue for this item, then
                    // we decrement the life of the parent.
                    if (c.liveChildren == 0 && c.parent != null)
                        decrementLife(c.parent, cached_subproofs);
                }
            }

            return evidence;
        }
Example #14
0
 private static void AddSequent(Hashtable cases, Sequent s)
 {
     object key = s.head.Predicate;
     if (key is Variable) key = "WILDCARD";
     ArrayList list = (ArrayList)cases[key];
     if (list == null) {
         list = new ArrayList();
         cases[key] = list;
     }
     list.Add(s);
 }