I also happen to have a question, I'm working on a project that requires going through rules and at some point having several choices (2-30 but possibly one choice leads to more choices down the line). I would like to be able to let the engine start from the current state and "trying" multiple solutions. I'm trying to figure out a way a simple and hopefully efficient way to do this. Here's what I experimented with/considered so far:
1) Considered using LinkedFacts, and while that handles new facts retraction, updates to existing facts wouldn't be reverted. So make a log of updates and revert manually?
2) Deep-copy all facts, make choice, continue execution. Once run is over, retract all, insert all fact copies, make new choice, repeat.
3) Deep-copy all facts, halt current session, create new session for each choice, starting with the fact copies.
I have the impression I'm missing a clever way to use the framework to help me. Additionally, doing this in a way where I can leverage already calculated fact combinations would be great as there are combinations that would be repeated.
The reason I'm trying to use NRules for this is that new and updated facts tend to trigger a limited number of rules and fact changes. For reference the "scale" I'm working with is along the lines of ~50-200 facts and probably ~50-200 rules.
Thanks!
Thanks for the previous answer. Now I'm trying to figure out how to deal with ActionTrigger
. Consider the following CODE
When I run it, I get the expected output:
Activated Baz
Reactivated Zab
Deactivated Zab
But if I remove Action
with ActionTrigger.Reactivated
, only the first line is printed. The engine doesn't react to retraction. Why is that happening?
1 argumentsList)
at NRules.RuleSharp.PrimaryExpressionBuilder.Method(List
1 argumentsList)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitUnary_expression(Unary_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Unary_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitMultiplicative_expression(Multiplicative_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Multiplicative_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitAdditive_expression(Additive_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Additive_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.VisitChildren(IRuleNode node)
at NRules.RuleSharp.Parser.RuleSharpParserBaseVisitor
1.VisitShift_expression(Shift_expressionContext context)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitRelational_expression(Relational_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Relational_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitEquality_expression(Equality_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Equality_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitAnd_expression(And_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.And_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitExclusive_or_expression(Exclusive_or_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Exclusive_or_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitInclusive_or_expression(Inclusive_or_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Inclusive_or_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)1.Visit(IParseTree tree)
at NRules.RuleSharp.ExpressionParser.VisitConditional_and_expression(Conditional_and_expressionContext context)
at NRules.RuleSharp.Parser.RuleSharpParser.Conditional_and_expressionContext.Accept[TResult](IParseTreeVisitor
1 visitor)
import model.LineItem;
import model.Brand;
import model.Market;
import model.Seller;
global java.util.List coupons;
rule "Rule 1"
when
exists LineItem(category == "PC", market in (Market.MARKETPLACE1), brand in (Brand.ACER))
then
coupons.add("#PC0001");
end
Then()
.Do(ctx => SendEmailNotification(currentCartItem));
Is there a way to properly remove a fact from the sessions memory once inserted?
Simply calling Remove
/ TryRemove
doesn't actually free any memory...
Minimized example of what I am currently trying to do:
using System;
using NRules;
using NRules.Fluent;
using NRules.Fluent.Dsl;
namespace Playground
{
class Fact
{
public int data { get; set; }
}
public class TestRule : Rule
{
public override void Define()
{
Fact fact = null;
When()
.Match<Fact>(() => fact);
Then()
.Do(ctx => Console.WriteLine("fact " + fact.data));
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("press any key to start...");
Console.ReadKey();
var repository = new RuleRepository();
repository.Load(x => x.From(typeof(Program).Assembly));
var factory = repository.Compile();
var session = factory.CreateSession();
Console.WriteLine("inserting facts...\n");
for (int i = 0; i < 1000000; ++i)
{
session.Insert(new Fact { data = i });
}
// memory usage has now grown to ~800 MB
Console.WriteLine("press any key to retract facts...");
Console.ReadKey();
foreach (var fact in session.Query<Fact>())
{
if (!session.TryRetract(fact))
{
Console.WriteLine("retracting " + fact.data + " failed"); // no output -> no errors
}
}
foreach (var fact in session.Query<Fact>())
{
Console.WriteLine("still in memory: " + fact.data + ")"); // no output -> no facts in session
}
// memory usage hasn't dropped down again
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey();
}
}
}