// fixme: Not sure yet how to handle real-time issues. Don't want this loop to spin endlessly, will need it to yield so other processes
        // can run. For a simple lexeme-based CSA, the presenter could be where the yield lives. Another option is to not have Execute() be a loop.
        // Instead use an event-based architecture where changes to the blackboard trigger the controller. For now, just select a single KS and
        // execute it. Punt looping to the enclosing application.
        public void Execute()
        {
            UpdateAgenda();
            IKnowledgeSourceActivation selectedKSA = SelectKSForExecution();

            if (selectedKSA != null)
            {
                selectedKSA.Execute();
                m_Agenda.Remove(selectedKSA);
            }
        }
コード例 #2
0
        // fixme: selects the highest priority KSA for execution. More generally, would want to select KSs probabilistically based on priority.
        // Consider implementing controllers with KSAs on their own blackboard. There's a regress where the KSs that implement a controller need
        // their own meta-controller to decide what to do. This regress can be broken by having "eager" KSs that execute immediately when their
        // preconditions are satisfied (like a forward-chaining rule).
        protected override IKnowledgeSourceActivation SelectKSForExecution()
        {
            IKnowledgeSourceActivation highestPriorityKSA = null;
            int highestPriority = int.MinValue;

            foreach (IKnowledgeSourceActivation KSA in m_Agenda)
            {
                Debug.Assert(KSA.Properties.ContainsKey(Priority));
                int curPriority = (int)KSA.Properties[Priority];
                if (curPriority > highestPriority)
                {
                    highestPriorityKSA = KSA;
                    highestPriority    = curPriority;
                }
            }
            return(highestPriorityKSA); // returns null if there are no KSs in the agenda
        }
コード例 #3
0
        public override IKnowledgeSourceActivation[] Precondition()
        {
            // Use LINQ to create a collection of the requested U_PrologEvalQueries on the blackboard.
            var requests = from request in m_blackboard.LookupUnits <U_PrologEvalRequest>() // Lookup ID select requests
                           where                                                            // where the request has not been previously matched by this knowledge source precondition
                           (!request.Slots.ContainsKey(KSPreconditionMatched)) ||
                           (!((ISet <ReactiveKnowledgeSource>)request.Slots[KSPreconditionMatched]).Contains(this))
                           select request;

            IKnowledgeSourceActivation[] activations = new IKnowledgeSourceActivation[requests.Count()];

            // Currently only support one prolog KB
            // fixme: eventually may want to support multiple prolog KBs so will need mechanism for supporting them as well as inheritance

            var prologKB = m_blackboard.LookupSingleton <U_PrologKB>(); // Lookup prolog kbs.

            // Iterate through each of the requests, creating KnowledgeSourceActivations
            int i = 0;

            foreach (var request in requests)
            {
                var boundVars = new Dictionary <string, object>
                {
                    [PrologEvalRequest] = request,
                    [PrologKB]          = prologKB
                };

                activations[i++] = new KnowledgeSourceActivation(this, boundVars);

                // fixme: this bit of boilerplate code for marking a knowledge unit as having already participated in a matched precondition
                // should be baked into the infrastructure somewhere so knowledge source implementers don't always have to do this.
                // A good place to add this would be on Unit (and declare a method on IUnit).
                if (request.Slots.ContainsKey(KSPreconditionMatched))
                {
                    ((HashSet <ReactiveKnowledgeSource>)request.Slots[KSPreconditionMatched]).Add(this);
                }
                else
                {
                    request.Slots[KSPreconditionMatched] = new HashSet <ReactiveKnowledgeSource> {
                        this
                    };
                }
            }

            return(activations);
        }
コード例 #4
0
        public override IKnowledgeSourceActivation[] Precondition()
        {
            // Use LINQ to create a collection of the requested U_IDQueries on the blackboard.
            var requests = from request in m_blackboard.LookupUnits <U_IDSelectRequest>() // Lookup ID queries
                           where                                                          // where the query has not been previously matched by this knowledge source precondition
                           (!request.Slots.ContainsKey(KSPreconditionMatched)) ||
                           (!((ISet <ReactiveKnowledgeSource>)request.Slots[KSPreconditionMatched]).Contains(this))
                           select request;

            IKnowledgeSourceActivation[] activations = new IKnowledgeSourceActivation[requests.Count()];

            // Iterate through each of the queries, creating KnowledgeSourceActivations
            int i = 0;

            foreach (var request in requests)
            {
                var boundVars = new Dictionary <string, object>
                {
                    [IDSelectRequest] = request
                };

                activations[i++] = new KnowledgeSourceActivation(this, boundVars);

                // fixme: this bit of boilerplate code for marking a knowledge unit as having already participated in a matched precondition
                // should be baked into the infrastructure somewhere so knowledge source implementers don't always have to do this.
                // A good place to add this would be on Unit (and declare a method on IUnit).
                if (request.Slots.ContainsKey(KSPreconditionMatched))
                {
                    ((HashSet <ReactiveKnowledgeSource>)request.Slots[KSPreconditionMatched]).Add(this);
                }
                else
                {
                    request.Slots[KSPreconditionMatched] = new HashSet <ReactiveKnowledgeSource> {
                        this
                    };
                }
            }

            return(activations);
        }
        /*public*/
        void TestSelectKSForExecution_PriorityController()
        {
            PriorityController_PublicMethods controller = new PriorityController_PublicMethods();
            IBlackboard blackboard        = new Blackboard();
            KS_Old_ReactiveIDSelector ks1 = new KS_Old_ReactiveIDSelector(blackboard);
            KS_Old_ReactiveIDSelector ks2 = new KS_Old_ReactiveIDSelector(blackboard);
            KS_Old_ReactiveIDSelector ks3 = new KS_Old_ReactiveIDSelector(blackboard);

            ks1.Properties[Priority] = 10;
            ks2.Properties[Priority] = 30;
            ks3.Properties[Priority] = 20;
            controller.AddKnowledgeSource(ks1);
            controller.AddKnowledgeSource(ks2);
            controller.AddKnowledgeSource(ks3);
            blackboard.AddUnit(new U_IDSelectRequest("foo"));

            controller.UpdateAgenda();
            Assert.Equal(3, controller.Agenda.Count);

            IKnowledgeSourceActivation KSA = controller.SelectKSForExecution();

            Assert.Equal(30, KSA.Properties[KSProps.Priority]);
        }