1
votes

i work with CLIPS.NET and wonder how i can access the agenda in clips.

i want to have some input values and let clips run so it can generate a solution based on the input values. But i also want to see what rules exactly are fired. I now have something like this

(deftemplate MAIN::action
  (slot name (default ?NONE)))

(deftemplate MAIN::input
  (slot name)
  (slot value (default ?NONE)))

(defrule MAIN::rule0
  (input (name test-input) (value 1))
=>
  (assert (action (name do-something)))
)

The problem is i cant use (agenda) because that only prints something to the console and gives me no string i can work with or something like that. So how can i get the agenda ? Or do i need to create a new fact in every rule to see what rules where executed (seems a bit inconvenient)? (For now i only need the names of the rules)

UPDATE

my try on function "all-next-activation" (now working):

void AllNextActivationFunction(
    void *theEnv,
    DATA_OBJECT_PTR returnValue)
    {
    unsigned long count;
    struct multifield *theList;
    void *act;


    if (EnvArgCountCheck(theEnv, "all-next-activation", EXACTLY, 0) == -1)
        {
        EnvSetMultifieldErrorValue(theEnv, returnValue);
        return;
        }

    // Count activations
    for (act = EnvGetNextActivation(theEnv, NULL), count = 0;
        act != NULL;
        act = EnvGetNextActivation(theEnv, act), count++)
        { /* Do Nothing */ }

    // Create the multifield
    SetpType(returnValue, MULTIFIELD);
    SetpDOBegin(returnValue, 1);
    SetpDOEnd(returnValue, (long)count);
    theList = (struct multifield *) EnvCreateMultifield(theEnv, count);
    SetpValue(returnValue, (void *)theList);

    // Store values in multifield
    for (act = EnvGetNextActivation(theEnv, NULL), count = 1;
        act != NULL;
        act = EnvGetNextActivation(theEnv, act), count++)
        {
        SetMFType(theList, count, SYMBOL);
        SetMFValue(theList, count, EnvAddSymbol(theEnv, EnvGetActivationName(theEnv, act)));
        }
    }


void EnvUserFunctions(
  void *environment)
  {
    EnvDefineFunction2(environment, "next-activation", 'w', PTIEF NextActivationFunction, "NextActivationFunction", "00");
    EnvDefineFunction2(environment, "all-next-activation", 'm', PTIEF AllNextActivationFunction, "AllNextActivationFunction", "00");
  }
1

1 Answers

2
votes

You'd either have to extend the .NET API to include some of the C functions that allow you to iterate over the activations and grab information from them or add a user-defined function in CLIPS and use the Eval method from .NET to invoke that CLIPS function. For example, here's code you can add to the userfunctions.c that returns the name of the next activation:

void *NextActivationFunction(
  void *theEnv)
  {
   void *act;

   if (EnvArgCountCheck(theEnv,"next-activation",EXACTLY,0) == -1)
     { return EnvFalseSymbol(theEnv); }

   act = EnvGetNextActivation(theEnv,NULL);

   if (act == NULL)
     { return EnvFalseSymbol(theEnv); }
   else
     { return EnvAddSymbol(theEnv,EnvGetActivationName(theEnv,act)); }
  }

void EnvUserFunctions(
  void *environment)
  {
   EnvDefineFunction2(environment,"next-activation", 'w', PTIEF NextActivationFunction, "NextActivationFunction", "00");
  }

Recompiling CLIPS with that code allows you to use this function within CLIPS:

CLIPS> (next-activation)
FALSE
CLIPS> (defrule foo =>)
CLIPS> (defrule bar =>)
CLIPS> (next-activation)
bar
CLIPS> (run 1)
CLIPS> (next-activation)
foo
CLIPS> 

Or from .NET using the Eval method:

clips.Eval("(next-activation)");