Get Agenda in CLIPS - rule-engine

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");
}

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)");

Related

"map.getOrDefault" equivalent in Dart

I'm working on a friend suggestion algorithm for a flutter social media application. I'm still an amateur when it comes to Dart so I'm stuck on the following line of code:
class FriendSuggestionAlgorithm {
User friendSuggestion(User user) {
int max = -1;
User suggestion;
Map<User, int> map = new HashMap();
for (User friend in user.friends) {
for (User mutualFriend in friend.friends) {
if (mutualFriend.id != user.id && !user.friends.contains(mutualFriend)) {
map.putIfAbsent(mutualFriend, map.getOrDefault(mutual, 0) + 1);
}
}
}
for (MapEntry<User, int> mutualFriend in map.entries) {
if (mutualFriend.value > max) {
max = mutualFriend.value;
suggestion = mutualFriend.key;
}
}
return suggestion;
}
}
map.getOrDefault is underlined (I know the method doesn't exist in Dart). Do you know what the equivalent is in Dart? (PS, I'm just translating Java code into Dart.
Any help is appreciated!
Your code doesn't make sense. map.putIfAbsent will do work only if the key doesn't exist, so the hypothetical map.getOrDefault call with the same key would always return the default value anyway. That is, your logic would be the equivalent of map.putIfAbsent(mutual, () => 1), where nothing happens if the key already exists.
Map.putifAbsent takes a callback as its argument to avoid evaluating it unless it's actually necessary. I personally prefer using ??= when the Map values are non-nullable.
I presume that you actually want to increment the existing value, if one exists. If so, I'd replace the map.putIfAbsent(...) call with:
map[mutual] = (map[mutual] ?? 0) + 1;
Also see: Does Dart have something like defaultdict in Python?
You could do it like this:
map.putIfAbsent(mutual, (map.containsKey(mutual) ? map[mutual] : 0) + 1)
Maybe take a look at this for more info: https://dart.dev/guides/language/language-tour#conditional-expressions
Edit:
This code should work
class FriendSuggestionAlgorithm {
User? friendSuggestion(User user) {
int max = -1;
User? suggestion;
Map<User, int> map = {};
for (User friend in user.friends) {
for (User mutualFriend in friend.friends) {
if (mutualFriend.id != user.id && !user.friends.contains(mutualFriend)) {
map.putIfAbsent(mutualFriend, () => (map[mutualFriend] ?? 0) + 1);
}
}
}
for (MapEntry<User, int> mutualFriend in map.entries) {
if (mutualFriend.value > max) {
max = mutualFriend.value;
suggestion = mutualFriend.key;
}
}
return suggestion;
}
}
Note that suggestion nullable because it could happen that suggestion is never assigned. And therefore friendSuggestion(user) can return null;
To come back to your question
the correct code is
map.putIfAbsent(mutualFriend, () => (map[mutualFriend] ?? 0) + 1);
My mistake on my original answer, the ifAbsent part of this is a function. In the function the value of mutualFriend is retrieved. If that is null use 0.

Backtracking results in same repeating course

I am trying to solve a puzzle, and it has been suggested that I use backtracking - I did not know the term so did some investigation, and found the following in Wikipedia:
In order to apply backtracking to a specific class of problems, one must provide the data P for the particular instance of the problem that is to be solved, and six procedural parameters, root, reject, accept, first, next, and output. These procedures should take the instance data P as a parameter and should do the following:
root(P): return the partial candidate at the root of the search tree.
reject(P,c): return true only if the partial candidate c is not worth completing.
accept(P,c): return true if c is a solution of P, and false otherwise.
first(P,c): generate the first extension of candidate c.
next(P,s): generate the next alternative extension of a candidate, after the extension s.
output(P,c): use the solution c of P, as appropriate to the application.
The backtracking algorithm reduces the problem to the call backtrack(root(P)), where backtrack is the following recursive procedure:
procedure backtrack(c) is
if reject(P, c) then return
if accept(P, c) then output(P, c)
s ← first(P, c)
while s ≠ NULL do
backtrack(s)
s ← next(P, s)
I have attempted to use this method for my solution, but after the method finds a rejected candidate it just starts again and finds the same route, rather than the next possible one.
I now don't think I have used the next(P,s) correctly, because I don't really understand the wording 'after the extension s'.
I've tried 2 methods:
(a) in the first() function, generating all possible extensions, storing them in a list, then using the first. The next() function then uses the other extensions from the list in turn. But this maybe can't work because of the calls to backtrack() in between the calls to next().
(b) adding a counter to the data (i.e. the class that includes all the grid info) and incrementing this for each call of next(). But can't work out where to reset this counter to zero.
Here's the relevant bit of code for method (a):
private PotentialSolution tryFirstTrack(PotentialSolution ps)
{
possibleTracks = new List<PotentialSolution>();
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(ps);
}
}
return tryNextTrack(ps);
}
private PotentialSolution tryNextTrack(PotentialSolution ps)
{
if (possibleTracks.Count == 0)
{
ps.SetCell(Track.Empty);
return null;
}
ps = possibleTracks.First();
// don't use same one again
possibleTracks.Remove(ps);
return ps;
}
private bool backtrackTracks(PotentialSolution ps)
{
if (canExit)
{
return true;
}
if (checkOccupiedCells(ps))
{
ps = tryFirstTrack(ps);
while (ps != null)
{
// 'testCells' is a copy of the grid for use with graphics - no need to include graphics in the backtrack stack
testCells[ps.h, ps.w].DrawTrack(g, ps.GetCell());
if (ps.TestForExit(endColumn, ref canExit) != Track.MaxVal)
{
drawRowColTotals(ps);
return true;
}
ps.nextSide = findNextSide(ps.nextSide, ps.GetCell(), ref ps.h, ref ps.w);
if (ps.h >= 0 && ps.h < cellsPerSide && ps.w >= 0 && ps.w < cellsPerSide)
{
backtrackTracks(ps);
ps = tryNextTrack(ps);
}
else
return false;
}
return false;
}
return false;
}
and here's some code using random choices. This works fine, so I conclude that the methods checkOccupiedCells() and findNextSide() are working correctly.
private bool backtrackTracks(PotentialSolution ps)
{
if (canExit)
{
return true;
}
if (checkOccupiedCells(ps))
{
Track track = createRandomTrack(ps);
if (canExit)
return true;
if (track == Track.MaxVal)
return false;
ps.SetCell(track);
ps.nextSide = findNextSide(ps.nextSide, track, ref ps.h, ref ps.w);
if (ps.h >= 0 && ps.h < cellsPerSide && ps.w >= 0 && ps.w < cellsPerSide)
backtrackTracks(ps);
else
return false;
}
}
If it helps, there's more background info in the puzzle itself here

Decoding delimited frames from byte arrays

I have frames that are delimited by bytes to start and stop the frame (they do not appear in the stream).
I read a chunk from disk or network socket, i then need to pass to a deserializer but only after I have de-framed the packet first.
Frames may span multiple chunks that have been read, note how frame 3 is split across array 1 and array 2.
Rather than reinvent the wheel for this common problem, do any github or similar projects exist?
I am investigating ReadOnlySequenceSegment<T> from https://www.codemag.com/article/1807051/Introducing-.NET-Core-2.1-Flagship-Types-Span-T-and-Memory-T and will post updates as I work out the requirements.
Update
Further to Stephen Cleary link (thank you!!) to https://github.com/davidfowl/TcpEcho/blob/master/src/Server/Program.cs I have the below.
My data is json, so unlike the original question the delimiter tokens will appear in the stream. Therefore I have to count the array delimitator and only declare a frame when i have found the outermost [ and ] characters.
The below code works, and less manual copies done (not sure if still done behind the scenes - code is quite neater using David Fowl approach).
However I am casting to array instead of using buffer.PositionOf((byte)'[') since I was unable to see how I could call the PositionOf with an offset applied (i.e. scan deeper into the frame past previously found delimiter tokens).
Am i using/butchering the library in a brute force way, or is the below good to go with the array cast?
class Program
{
static async Task Main(string[] args)
{
using var stream = File.Open(args[0], FileMode.Open);
var reader = PipeReader.Create(stream);
while (true)
{
ReadResult result = await reader.ReadAsync();
ReadOnlySequence<byte> buffer = result.Buffer;
while (TryDeframe(ref buffer, out ReadOnlySequence<byte> line))
{
// Process the line.
var str = System.Text.Encoding.UTF8.GetString(line.ToArray());
Console.WriteLine(str);
}
// Tell the PipeReader how much of the buffer has been consumed.
reader.AdvanceTo(buffer.Start, buffer.End);
// Stop reading if there's no more data coming.
if (result.IsCompleted)
{
break;
}
}
// Mark the PipeReader as complete.
await reader.CompleteAsync();
}
private static bool TryDeframe(ref ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> frame)
{
int frameCount = 0;
int start = -1;
int end = -1;
var bytes = buffer.ToArray();
for (var i = 0; i < bytes.Length; i++)
{
var b = bytes[i];
if (b == (byte)'[')
{
if (start == -1)
start = i;
frameCount++;
}
else if (b == (byte)']')
{
frameCount--;
if (frameCount == 0)
{
end = i;
break;
}
}
}
if (start == -1 || end == -1) // no frame found
{
frame = default;
return false;
}
frame = buffer.Slice(start, end+1);
buffer = buffer.Slice(frame.Length);
return true;
}
}
do any github or similar projects exist?
David Fowler has an echo server that uses Pipelines to implement delimited frames.

From RxJava2, How can I compare and filter two observables if the values are equal?

I am new to RxJava2.
I am trying to get a list of Transaction object both from cache and from server.
I want to compare the server value to cache value and if the server value is the same, then ignore it.
I was able to do it easily using .scan() because we can return null and when null is returned from the .scan() the value got ignored(filtered).
RxJava 1
private Observable<List<Transaction>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.scan((p1, p2) -> {
if (p1 == null && p2 != null) {
return p2;
} else if (p1 != null && !isListSame(p1, p2)) {
return p2;
} else {
return null;
}
});
}
With RxJava 2, since I cannot return null anymore, things are not easy.
RxJava 2
private Observable<List<Transaction>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.map(FilterObject::new)
.scan((filterObject1, filterObject2) -> {
List<Transaction> p1 = (List<Transaction>)filterObject1.value;
List<Transaction> p2 = (List<Transaction>)filterObject2.value;
if (p1.size() == 0 && p2.size() > 0) {
return filterObject2;
} else if (!isListSame(p1, p2)) {
return filterObject2;
} else {
filterObject2.filter = true;
return filterObject2;
}
})
.filter(filterObject -> !filterObject.filter)
.map(filterObject -> (List<Transaction>)filterObject.value);
}
Where FilterObject is:
public class FilterObject {
public Object value;
public boolean filter;
public FilterObject(Object value) {
this.value = value;
}
}
Even though I can achieve the same thing using above method, it seems very ugly. Also I had to include two maps which might not be so performance friendly.
Is there a simple/clean way to achieve what I want?
I don't think there is a generic solution to this problem, since an empty list and a list that needs to be filtered (which happens to be empty in all cases) are two different things (the output of the scan) and needs to be handled differently.
However, in your particular case you never emit an empty list, except maybe for the first output.
(I am using String instead Transaction, shouldn't matter)
private Observable<List<String>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.filter(list -> !list.isEmpty())
// If you prefer a consistent empty list over the first
// empty list emission getting filtered
.startWith((List<String>) Collections.EMPTY_LIST)
// Newly emitted value cannot be empty, it only depends only on the comparison
.distinctUntilChanged(this::isListSame);
}
That's the closest I could get with as few operators as possible. Hope it solves your problem.
Based on andras' answer, I modified little bit to achieve what I want.
private Observable<List<String>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.filter(list -> !list.isEmpty())
.distinctUntilChanged(this::isListSame)
.switchIfEmpty(Observable.just(new ArrayList<>()));
}
Andreas' answer will always receive an empty list and then a real data.
My solution above will receive:
1. Data from cache (and then data from server if different)
2. Empty list if both cache and server returns Empty list.

Pass a pointer for getting result through CFFI

Here's a function in C:
union Example {
int number;
void *pointer;
};
void return_a_value (union Example *ptr) {
(*ptr).number = 1;
}
Now I want to call it in Common Lisp through CFFI, how can I do it?
(defcunion Example
(number :int)
(ptr :pointer))
(defcfun "return_a_value" :void
(retval :pointer)) ; I'm not very sure here..
Everything's alright up to this point, including your definition of
return_a_value. That's how you may call the function:
(with-foreign-object (arg 'example)
(setf (foreign-slot-value arg 'example 'number) 123)
(return-a-value arg)
(foreign-slot-value arg 'example 'number))