Exemple #1
0
    public override UpdateInfo Make(Model m, TruthValue.T v)
    {
        Function wrappers = (Function)m.Get(GetSemanticType(), Model.WRAPPERS_ID);
        Wrapper  w        = new Wrapper(this);

        // if this logical form is already in the model
        if (wrappers.HasInput(w))
        {
            TruthValue oldValue = (TruthValue)wrappers.Apply(w);
            if (oldValue.Get() == v)
            {
                return(UpdateInfo.NoChange);
            }

            if (oldValue.Get() == TruthValue.T.Unknown)
            {
                return(oldValue.Add(v));
            }

            return(UpdateInfo.Warning);
        }

        // if this logical form isn't defined yet
        wrappers.Set(w, new TruthValue(v));
        return(UpdateInfo.Updated);
    }
Exemple #2
0
        /**
         * {A} |- (--A)
         * /param v1 Truth value of the premise
         * /return Truth value of the conclusion
         */
        public static TruthValue negation(TruthValue v1)
        {
            float f = 1 - v1.frequency;
            float c = v1.confidence;

            return(TruthValue.make(f, c));
        }
 public ExpressionTree(TruthValue constant)
 {
     @operator     = Operator.CONSTANT;
     children      = null;
     this.leaf     = -1;
     this.constant = constant;
 }
Exemple #4
0
        public static TruthValue not(this TruthValue left)
        {
            switch (left)
            {
            case TruthValue.NO:
                return(TruthValue.YES);

            case TruthValue.YES:
                return(TruthValue.NO);

            case TruthValue.NULL:
            case TruthValue.YES_NO:
            case TruthValue.YES_NO_NULL:
                return(left);

            case TruthValue.NO_NULL:
                return(TruthValue.YES_NULL);

            case TruthValue.YES_NULL:
                return(TruthValue.NO_NULL);

            default:
                throw new ArgumentException("Unknown value: " + left);
            }
        }
Exemple #5
0
        // https://github.com/opennars/opennars/blob/master/nars_core/nars/inference/TemporalRules.java#L502

        /**
         * Evaluate the quality of the judgment as a solution to a problem
         *
         * \param problem A goal or question
         * \param solution The solution to be evaluated
         * \return The quality of the judgment as the solution
         */
        public static float solutionQuality(EnumRateByConfidence rateByConfidence, ClassicalTask problemTask, ClassicalSentence solution, Memory memory, CompoundAndTermContext compoundAndTermContext)
        {
            ClassicalSentence problem = problemTask.sentence;

            /* TODO< implement TEMPORAL
             * if (!matchingOrder(problem.temporalOrder, solution.temporalOrder)) {
             *  return 0.0F;
             * }
             */

            TruthValue truth = solution.truth;

            if (problem.stamp.occurrenceTime != solution.stamp.occurrenceTime)
            {
                truth = solution.projectionTruth(problem.stamp.occurrenceTime, memory.time);
            }

            //when the solutions are comparable, we have to use confidence!! else truth expectation.
            //this way negative evidence can update the solution instead of getting ignored due to lower truth expectation.
            //so the previous handling to let whether the problem has query vars decide was wrong.
            if (rateByConfidence == EnumRateByConfidence.NO)
            {
                return((float)(truth.expectation / Math.Sqrt(Math.Sqrt(Math.Sqrt(compoundAndTermContext.getTermComplexityOfAndByTermReferer(solution.term) * Parameters.COMPLEXITY_UNIT)))));
            }
            else
            {
                return(truth.confidence);
            }
        }
 public ExpressionTree(TruthValue constant)
 {
     @operator = Operator.CONSTANT;
     children = null;
     this.leaf = -1;
     this.constant = constant;
 }
            public SearchArgument.Builder literal(TruthValue truth)
            {
                ExpressionTree parent = currentTree.Peek();

                parent.getChildren().Add(new ExpressionTree(truth));
                return(this);
            }
Exemple #8
0
        public TruthValue projectionTruth(long targetTime, long currentTime)
        {
            TruthValue newTruth = null;

            if (!stamp.isEternal)
            {
                newTruth = TruthFunctions.eternalize(truth);
                if (targetTime != Stamp.ETERNAL)
                {
                    long   occurrenceTime      = stamp.occurrenceTime;
                    double factor              = TruthFunctions.temporalProjection(occurrenceTime, targetTime, currentTime);
                    float  projectedConfidence = (float)(factor * truth.confidence);
                    if (projectedConfidence > newTruth.confidence)
                    {
                        newTruth = TruthValue.make(truth.frequency, projectedConfidence);
                    }
                }
            }

            if (newTruth == null)
            {
                newTruth = truth.clone();
            }

            return(newTruth);
        }
Exemple #9
0
 public TruthDesirabilityGoalValue
     (TruthValue truth, TruthValue desirability, TruthValue goal)
 {
     this.truth        = truth;
     this.desirability = desirability;
     this.goal         = goal;
 }
Exemple #10
0
        /// <summary>
        /// Evaluate the tree using a provided assignment of values.
        /// </summary>
        /// <param name="Assignment">A dictionary of values which must
        /// contain at least the symbols present in the tree, additional
        /// sybols within the dicitonary will not be used. </param>
        /// <returns>Truth value of expression using provided assignment.</returns>
        public TruthValue Evaluate(Dictionary <string, TruthValue> Assignment)
        {
            TruthValue result = TruthValue.Unknown;
            Dictionary <string, TruthValue> Old = new Dictionary <string, TruthValue>();
            string s = "";

            try
            {
                foreach (string sym in _symbolTable.Keys)
                {
                    s = sym;
                    Old.Add(sym, _symbolTable[sym][0].Value.Value);
                    //We can make this assumption because no empty list is every
                    //added to the dictionary.
                    AssignValue(sym, Assignment[sym]);
                }
            }
            catch (KeyNotFoundException)
            {
                throw new ArgumentException("Assignment did not contain a definition for {0}.", s);
            }

            result = Evaluate();

            foreach (string sym in _symbolTable.Keys)
            {
                AssignValue(sym, Old[sym]);
            }

            return(result);
        }
Exemple #11
0
        /**
         * {M, <M ==> P>} |- P
         * /param v1 Truth value of the first premise
         * /param reliance Confidence of the second (analytical) premise
         * /return Truth value of the conclusion
         */
        public static TruthValue deduction(TruthValue v1, float reliance)
        {
            float f1 = v1.frequency;
            float c1 = v1.confidence;
            float c  = UtilityFunctions.and(f1, c1, reliance);

            return(TruthValue.make(f1, c, true));
        }
Exemple #12
0
        /**
         * {(&&, <#x() ==> M>, <#x() ==> P>), S ==> M} |- <S ==> P>
         * /param v1 Truth value of the first premise
         * /param v2 Truth value of the second premise
         * /return Truth value of the conclusion
         */
        public static TruthValue anonymousAnalogy(TruthValue v1, TruthValue v2)
        {
            float      f1 = v1.frequency;
            float      c1 = v1.confidence;
            TruthValue v0 = TruthValue.make(f1, UtilityFunctions.w2c(c1));

            return(analogy(v2, v0));
        }
Exemple #13
0
 /// <summary>
 /// Assign a value to a variable within the expression.
 /// </summary>
 /// <param name="Symbol">Variable name. </param>
 /// <param name="Value">Desired truth value.</param>
 public void AssignValue(string Symbol, TruthValue Value)
 {
     Debug.Assert(_symbolTable.ContainsKey(Symbol), "Cannot assign value to non-symbol!");
     foreach (ParseNode n in _symbolTable[Symbol])
     {
         n.Value = Value;
     }
 }
Exemple #14
0
        /**
         * From one moment to eternal
         * \param v1 Truth value of the premise
         * \return Truth value of the conclusion
         */
        public static EternalizedTruthValue eternalize(TruthValue v1)
        {
            float f1 = v1.frequency;
            float c1 = v1.confidence;
            float c  = UtilityFunctions.w2c(c1);

            return(EternalizedTruthValue.make(f1, c));
        }
Exemple #15
0
    void VisualizeStatement(string statement)
    {
        Statement parsedStatement = new Statement(statement);

        if (parsedStatement.type == Statement.StatementType.Unsupported)
        {
            return;
        }                                                                            //failed to create statement; unsupported statement

        SubjectPredicate subjectPredicate = parsedStatement.subjectPredicate;
        TruthValue       truthValue       = parsedStatement.truthValue;

        //visualize subject, predicate as terms

        QueueVisualizeNewConcept(subjectPredicate._subject);
        QueueVisualizeNewConcept(subjectPredicate._predicate);

        string statementKey = "";

        //visualize inheritance relation
        if (parsedStatement.type == Statement.StatementType.Inheritance)
        {
            statementKey = GetInheritanceString(subjectPredicate);
            QueueVisualizeNewConcept(statementKey);
            if (inheritTable.ContainsKey(statementKey) && inheritTable[statementKey].GetTruthValue().GetHashCode() == truthValue.GetHashCode())
            {
                return;
            }

            QueueVisualizeNewInherit(parsedStatement);
        }
        else if (parsedStatement.type == Statement.StatementType.Similarity)
        {
            statementKey = GetSimilarityString(subjectPredicate);
            QueueVisualizeNewConcept(statementKey);

            Statement parsedReverseStatement = NarseseParser.GetReverseStatement(statement);

            string forwardStatementKey = GetInheritanceString(subjectPredicate);
            string reverseStatementKey = GetInheritanceString(parsedReverseStatement.subjectPredicate);

            if (inheritTable.ContainsKey(forwardStatementKey) && inheritTable[forwardStatementKey].GetTruthValue().GetHashCode() == truthValue.GetHashCode())
            {
                return;
            }
            QueueVisualizeNewInherit(parsedStatement);

            if (inheritTable.ContainsKey(reverseStatementKey) && inheritTable[reverseStatementKey].GetTruthValue().GetHashCode() == parsedReverseStatement.truthValue.GetHashCode())
            {
                return;
            }
            QueueVisualizeNewInherit(parsedReverseStatement);
        }
        else
        {
            return;
        }
    }
Exemple #16
0
        /**
         * {<A ==> B>} |- <B ==> A>
         * /param v1 Truth value of the premise
         * /return Truth value of the conclusion
         */
        public static TruthValue conversion(TruthValue v1)
        {
            float f1 = v1.frequency;
            float c1 = v1.confidence;
            float w  = UtilityFunctions.and(f1, c1);
            float c  = UtilityFunctions.w2c(w);

            return(TruthValue.make(1, c));
        }
Exemple #17
0
        /**
         * A function specially designed for desire value [To be refined]
         * /param v1 Truth value of the first premise
         * /param v2 Truth value of the second premise
         * /return Truth value of the conclusion
         */
        public static TruthValue desireInd(TruthValue v1, TruthValue v2)
        {
            float f1 = v1.frequency;
            float f2 = v2.frequency;
            float c1 = v1.confidence;
            float c2 = v2.confidence;
            float w  = UtilityFunctions.and(f2, c1, c2);
            float c  = UtilityFunctions.w2c(w);

            return(TruthValue.make(f1, c));
        }
Exemple #18
0
        /**
         * {<S ==> M>, <M ==> P>} |- <S ==> P>
         * /param v1 Truth value of the first premise
         * /param v2 Truth value of the second premise
         * /return Truth value of the conclusion
         */
        public static TruthValue deduction(TruthValue v1, TruthValue v2)
        {
            float f1 = v1.frequency;
            float f2 = v2.frequency;
            float c1 = v1.confidence;
            float c2 = v2.confidence;
            float f  = UtilityFunctions.and(f1, f2);
            float c  = UtilityFunctions.and(c1, c2, f);

            return(TruthValue.make(f, c));
        }
Exemple #19
0
        public static TruthValue revision(TruthValue v1, TruthValue v2, TruthValue result)
        {
            float f1 = v1.frequency;
            float f2 = v2.frequency;
            float w1 = UtilityFunctions.c2w(v1.confidence);
            float w2 = UtilityFunctions.c2w(v2.confidence);
            float w  = w1 + w2;

            result.frequency  = (w1 * f1 + w2 * f2) / w;
            result.confidence = UtilityFunctions.w2c(w);
            return(result);
        }
Exemple #20
0
        /**
         * {<M ==> S>, <M ==> P>} |- <S <=> P>
         * /param v1 Truth value of the first premise
         * /param v2 Truth value of the second premise
         * /return Truth value of the conclusion
         */
        public static TruthValue comparison(TruthValue v1, TruthValue v2)
        {
            float f1 = v1.frequency;
            float f2 = v2.frequency;
            float c1 = v1.confidence;
            float c2 = v2.confidence;
            float f0 = UtilityFunctions.or(f1, f2);
            float f  = (f0 == 0) ? 0 : (UtilityFunctions.and(f1, f2) / f0);
            float w  = UtilityFunctions.and(f0, c1, c2);
            float c  = UtilityFunctions.w2c(w);

            return(TruthValue.make(f, c));
        }
Exemple #21
0
        /**
         * Does the RecordReader need to include this set of records?
         * @return true unless none of the rows qualify
         */
        public static bool isNeeded(this TruthValue value)
        {
            switch (value)
            {
            case TruthValue.NO:
            case TruthValue.NULL:
            case TruthValue.NO_NULL:
                return(false);

            default:
                return(true);
            }
        }
Exemple #22
0
        /**
         * {M, <P ==> M>} |- P
         * /param v1 Truth value of the first premise
         * /param reliance Confidence of the second (analytical) premise
         * /return Truth value of the conclusion
         */
        public static TruthValue abduction(TruthValue v1, float reliance)
        {
            if (v1.analytic)
            {
                return(TruthValue.make(0.5f, 0f));
            }
            float f1 = v1.frequency;
            float c1 = v1.confidence;
            float w  = UtilityFunctions.and(c1, reliance);
            float c  = UtilityFunctions.w2c(w);

            return(TruthValue.make(f1, c, true));
        }
Exemple #23
0
        static void testNars()
        {
            CompoundAndTermContext compoundAndTermContext = new CompoundAndTermContext();

            RuleDispatcher.compoundAndTermContext = compoundAndTermContext; // for debugging

            PrototypingInput prototypingInput = new PrototypingInput(compoundAndTermContext);

            Nar nar = Nar.make(compoundAndTermContext, new MetaNix.nars.config.RuntimeParameters());

            CompoundIndex compoundIndex1 = prototypingInput.makeInheritance("a", "b");

            ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters task1SentenceParameters = new ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters();
            task1SentenceParameters.term       = compoundAndTermContext.accessCompoundByIndex(compoundIndex1).thisTermReferer;
            task1SentenceParameters.truth      = TruthValue.make(1.0f, 0.5f);
            task1SentenceParameters.stamp      = Stamp.makeWithPresentTense(nar.memory);
            task1SentenceParameters.punctation = ClassicalSentence.EnumPunctation.JUDGMENT;
            ClassicalSentence task1Sentence = ClassicalSentence.makeByTermPunctuationTruthStampNormalize(task1SentenceParameters);

            ClassicalTask.MakeParameters task1MakeParameters = new ClassicalTask.MakeParameters();
            task1MakeParameters.sentence = task1Sentence;
            task1MakeParameters.budget   = new ClassicalBudgetValue(0.5f, 0.5f, 0.5f);

            nar.inputTask(ClassicalTask.make(task1MakeParameters));



            CompoundIndex compoundIndex2 = prototypingInput.makeInheritance("b", "c");

            ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters task2SentenceParameters = new ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters();
            task2SentenceParameters.term       = compoundAndTermContext.accessCompoundByIndex(compoundIndex2).thisTermReferer;
            task2SentenceParameters.truth      = TruthValue.make(1.0f, 0.5f);
            task2SentenceParameters.stamp      = Stamp.makeWithPresentTense(nar.memory);
            task2SentenceParameters.punctation = ClassicalSentence.EnumPunctation.JUDGMENT;
            ClassicalSentence task2Sentence = ClassicalSentence.makeByTermPunctuationTruthStampNormalize(task2SentenceParameters);

            ClassicalTask.MakeParameters task2MakeParameters = new ClassicalTask.MakeParameters();
            task2MakeParameters.sentence = task2Sentence;
            task2MakeParameters.budget   = new ClassicalBudgetValue(0.5f, 0.5f, 0.5f);

            nar.inputTask(ClassicalTask.make(task2MakeParameters));

            for (;;)
            {
                nar.cycle();
            }

            int here = 5;
        }
Exemple #24
0
 /// <summary>
 /// Propositional Logic Operator
 /// And
 /// A AND B
 /// </summary>
 /// <param name="A"></param>
 /// <param name="B"></param>
 /// <returns>See summary</returns>
 public static TruthValue AND(TruthValue A, TruthValue B)
 {
     if (A == TruthValue.False || B == TruthValue.False)
     {
         return(TruthValue.False);
     }
     else if (A == TruthValue.Unknown || B == TruthValue.Unknown)
     {
         return(TruthValue.Unknown);
     }
     else
     {
         return(TruthValue.True);
     }
 }
Exemple #25
0
        /**
         * {<M ==> S>, <P ==> M>} |- <S ==> P>
         * /param v1 Truth value of the first premise
         * /param v2 Truth value of the second premise
         * /return Truth value of the conclusion
         */
        public static TruthValue exemplification(TruthValue v1, TruthValue v2)
        {
            if (v1.analytic || v2.analytic)
            {
                return(TruthValue.make(0.5f, 0f));
            }
            float f1 = v1.frequency;
            float f2 = v2.frequency;
            float c1 = v1.confidence;
            float c2 = v2.confidence;
            float w  = UtilityFunctions.and(f1, f2, c1, c2);
            float c  = UtilityFunctions.w2c(w);

            return(TruthValue.make(1, c));
        }
Exemple #26
0
 /// <summary>
 /// Propositional Logic Operator
 /// Not, Negate
 /// NOT A
 /// </summary>
 /// <param name="A"></param>
 /// <returns></returns>
 public static TruthValue NOT(TruthValue A)
 {
     if (A == TruthValue.Unknown)
     {
         return(TruthValue.Unknown);
     }
     else if (A == TruthValue.True)
     {
         return(TruthValue.False);
     }
     else
     {
         return(TruthValue.True);
     }
 }
Exemple #27
0
 /**
  * Compute logical or between the two values.
  * @param right the other argument or null
  * @return the result
  */
 public static TruthValue or(this TruthValue left, TruthValue right)
 {
     if (/* right == null || */ right == left)
     {
         return(left);
     }
     if (right == TruthValue.YES || left == TruthValue.YES)
     {
         return(TruthValue.YES);
     }
     if (right == TruthValue.YES_NULL || left == TruthValue.YES_NULL)
     {
         return(TruthValue.YES_NULL);
     }
     if (right == TruthValue.NO)
     {
         return(left);
     }
     if (left == TruthValue.NO)
     {
         return(right);
     }
     if (left == TruthValue.NULL)
     {
         if (right == TruthValue.NO_NULL)
         {
             return(TruthValue.NULL);
         }
         else
         {
             return(TruthValue.YES_NULL);
         }
     }
     if (right == TruthValue.NULL)
     {
         if (left == TruthValue.NO_NULL)
         {
             return(TruthValue.NULL);
         }
         else
         {
             return(TruthValue.YES_NULL);
         }
     }
     return(TruthValue.YES_NO_NULL);
 }
    public UpdateInfo update(ISemanticValue that)
    {
        if (!(that.GetType() == typeof(TruthValue)))
        {
            return(UpdateInfo.NoChange);
        }
        TruthValue other = (TruthValue)that;

        if (other.IsTrue())
        {
            return(Add(true));
        }
        if (other.IsFalse())
        {
            return(Add(false));
        }
        return(UpdateInfo.NoChange);
    }
Exemple #29
0
        /**
         * project a judgment to a difference occurrence time
         *
         * \param targetTime The time to be projected into
         * \param currentTime The current time as a reference
         * \return The projected belief
         */
        public ClassicalSentence projection(long targetTime, long currentTime)
        {
            TruthValue newTruth = projectionTruth(targetTime, currentTime);

            bool eternalizing = newTruth is EternalizedTruthValue;

            Stamp newStamp = eternalizing ? stamp.cloneWithNewOccurrenceTime(Stamp.ETERNAL) :
                             stamp.cloneWithNewOccurrenceTime(targetTime);

            MakeByTermPunctuationTruthStampNormalizeParameters parameters = new MakeByTermPunctuationTruthStampNormalizeParameters();

            parameters.term       = term;
            parameters.punctation = punctation;
            parameters.truth      = newTruth;
            parameters.stamp      = newStamp;
            parameters.normalize  = false;
            return(makeByTermPunctuationTruthStampNormalize(parameters));
        }
Exemple #30
0
        /**
         * Evaluate the quality of a revision, then de-prioritize the premises
         *
         * \param tTruth The truth value of the judgment in the task
         * \param bTruth The truth value of the belief
         * \param truth The truth value of the conclusion of revision
         * \return The budget for the new task
         */
        static public ClassicalBudgetValue revise(TruthValue tTruth, TruthValue bTruth, TruthValue truth, bool feedbackToLinks, nars.control.DerivationContext nal)
        {
            float         difT = truth.getExpDifAbs(tTruth);
            ClassicalTask task = nal.currentTask;

            task.budget.decPriority(1 - difT);
            task.budget.decDurability(1 - difT);

            /* commented because links are not jet implemented
             * if (feedbackToLinks) {
             *  TaskLink tLink = nal.currentTaskLink;
             *  tLink.decPriority(1 - difT);
             *  tLink.decDurability(1 - difT);
             *  TermLink bLink = nal.currentBeliefLink;
             *  float difB = truth.getExpDifAbs(bTruth);
             *  bLink.decPriority(1 - difB);
             *  bLink.decDurability(1 - difB);
             * } */
            float dif        = truth.confidence - Math.Max(tTruth.confidence, bTruth.confidence);
            float priority   = UtilityFunctions.or(dif, task.budget.priority);
            float durability = UtilityFunctions.aveAri(dif, task.budget.durability);
            float quality    = truthToQuality(truth);

            /*
             * if (priority < 0) {
             *  memory.nar.output(ERR.class,
             *          new RuntimeException("BudgetValue.revise resulted in negative priority; set to 0"));
             *  priority = 0;
             * }
             * if (durability < 0) {
             *  memory.nar.output(ERR.class,
             *          new RuntimeException("BudgetValue.revise resulted in negative durability; set to 0; aveAri(dif=" + dif + ", task.getDurability=" + task.getDurability() +") = " + durability));
             *  durability = 0;
             * }
             * if (quality < 0) {
             *  memory.nar.output(ERR.class,
             *          new RuntimeException("BudgetValue.revise resulted in negative quality; set to 0"));
             *  quality = 0;
             * }
             */

            return(new ClassicalBudgetValue(priority, durability, quality));
        }
        public KarnoughMap()
        {
            //List<IKarnoughComponent> x = new List<IKarnoughComponent>();
            //List<List<IKarnoughComponent>> y = new List<List<IKarnoughComponent>>();

            valueLists = new List <List <List <IKarnoughComponent> > >();
            //y.Add(x);
            //valueLists.Add(y);
            valueNames = new List <string>();

            x_max = 0;
            y_max = 0;
            z_max = 0;
            addX();
            addY();
            addZ();

            default_value  = TruthValue.Null;
            this.dimension = 2;
        }
 public override TruthValue evaluate(TruthValue[] leaves)
 {
     return expression == null ? TruthValue.YES : expression.evaluate(leaves);
 }
 public SearchArgument.Builder literal(TruthValue truth)
 {
     ExpressionTree parent = currentTree.Peek();
     parent.getChildren().Add(new ExpressionTree(truth));
     return this;
 }
 /**
  * Evaluate the entire predicate based on the values for the leaf predicates.
  * @param leaves the value of each leaf predicate
  * @return the value of hte entire predicate
  */
 public abstract TruthValue evaluate(TruthValue[] leaves);
 /**
  * Compute logical or between the two values.
  * @param right the other argument or null
  * @return the result
  */
 public static TruthValue or(this TruthValue left, TruthValue right)
 {
     if (/* right == null || */ right == left)
     {
         return left;
     }
     if (right == TruthValue.YES || left == TruthValue.YES)
     {
         return TruthValue.YES;
     }
     if (right == TruthValue.YES_NULL || left == TruthValue.YES_NULL)
     {
         return TruthValue.YES_NULL;
     }
     if (right == TruthValue.NO)
     {
         return left;
     }
     if (left == TruthValue.NO)
     {
         return right;
     }
     if (left == TruthValue.NULL)
     {
         if (right == TruthValue.NO_NULL)
         {
             return TruthValue.NULL;
         }
         else
         {
             return TruthValue.YES_NULL;
         }
     }
     if (right == TruthValue.NULL)
     {
         if (left == TruthValue.NO_NULL)
         {
             return TruthValue.NULL;
         }
         else
         {
             return TruthValue.YES_NULL;
         }
     }
     return TruthValue.YES_NO_NULL;
 }
 public TruthValue evaluate(TruthValue[] leaves)
 {
     TruthValue result;
     switch (@operator)
     {
         case Operator.OR:
             result = TruthValue.NO;
             foreach (ExpressionTree child in children)
             {
                 result = child.evaluate(leaves).or(result);
             }
             return result;
         case Operator.AND:
             result = TruthValue.YES;
             foreach (ExpressionTree child in children)
             {
                 result = child.evaluate(leaves).and(result);
             }
             return result;
         case Operator.NOT:
             return children[0].evaluate(leaves).not();
         case Operator.LEAF:
             return leaves[leaf];
         case Operator.CONSTANT:
             return constant.Value;
         default:
             throw new InvalidOperationException("Unknown operator: " + @operator);
     }
 }
 private ExpressionTree constant(TruthValue val)
 {
     return new ExpressionTree(val);
 }