/// <summary> /// Indicates whether a rule condition has been activated at the time provided /// </summary> /// <param name="ruleCondition">The rule condition that should be activated</param> /// <param name="time">the time when the rule condition should be activated</param> /// <param name="variable">The variable impacted by this rule condition, if any</param> /// <returns>True if the provided rule condition has been activated</returns> public bool RuleActivatedAtTime(Rules.RuleCondition ruleCondition, double time, IVariable variable) { bool retVal = false; if (variable != null) { foreach (ModelEvent modelEvent in Events) { RuleFired ruleFired = modelEvent as RuleFired; if (modelEvent.Time == time && ruleFired != null) { if (ruleFired.RuleCondition == ruleCondition) { retVal = ruleFired.ImpactVariable(variable); if (retVal) { break; } } } } } return(retVal); }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="updates"></param> public void ApplyActivations(HashSet <Activation> activations) { foreach (Activation activation in activations) { if (activation.RuleCondition.Actions.Count > 0) { // Register the fact that a rule has been triggered Events.RuleFired ruleFired = new Events.RuleFired(activation.RuleCondition); EventTimeLine.AddModelEvent(ruleFired); // Registers all model updates due to this rule triggering foreach (Rules.Action action in activation.RuleCondition.Actions) { if (action.Statement != null) { Events.VariableUpdate variableUpdate = new Events.VariableUpdate(action, activation.Instance); EventTimeLine.AddModelEvent(variableUpdate); ruleFired.AddVariableUpdate(variableUpdate); } else { action.AddError("Cannot parse action statement"); } } } } CheckExpectationsState(); }
/// <summary> /// Gets the list of activated rules within the interval [start, end] /// </summary> /// <param name="rule"></param> /// <param name="time"></param> /// <returns></returns> public List <DataDictionary.Rules.RuleCondition> GetActivatedRulesInRange(double start, double end) { List <DataDictionary.Rules.RuleCondition> retVal = new List <DataDictionary.Rules.RuleCondition>(); foreach (ModelEvent modelEvent in Events) { if (modelEvent is RuleFired && (modelEvent.Time >= start && modelEvent.Time < end)) { RuleFired ruleFired = modelEvent as RuleFired; retVal.Add(ruleFired.RuleCondition); } } return(retVal); }
/// <summary> /// Gets the set of activated rules /// </summary> /// <param name="rule"></param> /// <param name="time"></param> /// <returns></returns> public HashSet <DataDictionary.Rules.RuleCondition> GetActivatedRules() { HashSet <DataDictionary.Rules.RuleCondition> retVal = new HashSet <DataDictionary.Rules.RuleCondition>(); foreach (ModelEvent modelEvent in Events) { if (modelEvent is RuleFired) { RuleFired ruleFired = modelEvent as RuleFired; retVal.Add(ruleFired.RuleCondition); } } return(retVal); }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="activations"></param> /// <param name="updates"></param> /// <param name="priority"></param> public void EvaluateActivations(HashSet<Activation> activations, acceptor.RulePriority priority, ref List<VariableUpdate> updates) { Dictionary<IVariable, Change> changes = new Dictionary<IVariable, Change>(); Dictionary<Change, VariableUpdate> traceBack = new Dictionary<Change, VariableUpdate>(); foreach (Activation activation in activations) { if (activation.RuleCondition.Actions.Count > 0) { // Register the fact that a rule has been triggered RuleFired ruleFired = new RuleFired(activation, priority); EventTimeLine.AddModelEvent(ruleFired, this, true); ExplanationPart changesExplanation = ExplanationPart.CreateSubExplanation(activation.Explanation, "Changes"); // Registers all model updates due to this rule triggering foreach (Action action in activation.RuleCondition.Actions) { if (action.Statement != null) { VariableUpdate variableUpdate = new VariableUpdate(action, activation.Instance, priority); variableUpdate.ComputeChanges(false, this); EventTimeLine.AddModelEvent(variableUpdate, this, false); ruleFired.AddVariableUpdate(variableUpdate); if (changesExplanation != null) { changesExplanation.SubExplanations.Add(variableUpdate.Explanation); } updates.Add(variableUpdate); if (CheckForCompatibleChanges) { ChangeList actionChanges = variableUpdate.Changes; if (variableUpdate.Action.Statement is ProcedureCallStatement) { Dictionary<IVariable, Change> procedureChanges = new Dictionary<IVariable, Change>(); foreach (Change change in variableUpdate.Changes.Changes) { procedureChanges[change.Variable] = change; } actionChanges = new ChangeList(); foreach (Change change in procedureChanges.Values) { actionChanges.Add(change, false, this); } } foreach (Change change in actionChanges.Changes) { IVariable variable = change.Variable; if (changes.ContainsKey(change.Variable)) { Change otherChange = changes[change.Variable]; Action otherAction = traceBack[otherChange].Action; if (!variable.Type.CompareForEquality(otherChange.NewValue, change.NewValue)) { string action1 = ((INamable) action.Enclosing).FullName + " : " + variableUpdate.Action.FullName; string action2 = ((INamable) otherAction.Enclosing).FullName + " : " + traceBack[otherChange].Action.FullName; variableUpdate.Action.AddError( "Simultaneous change of the variable " + variable.FullName + " with different values. Conflit between\n" + action1 + "\n and \n" + action2); } } else { changes.Add(change.Variable, change); traceBack.Add(change, variableUpdate); } } } } else { action.AddError("Cannot parse action statement"); } } } } // Handles the leave & enter state rules List<VariableUpdate> updatesToProcess = updates; updates = new List<VariableUpdate>(); // Avoid considering twice the same transition List<Tuple<State, State>> transitions = new List<Tuple<State, State>>(); while (updatesToProcess.Count > 0) { List<VariableUpdate> newUpdates = new List<VariableUpdate>(); foreach (VariableUpdate update in updatesToProcess) { updates.Add(update); foreach (Change change in update.Changes.Changes) { if (change.Variable.Type is StateMachine) { State leavingState = (State) change.PreviousValue; State enteringState = (State) change.NewValue; bool transitionFound = false; foreach (Tuple<State, State> transition in transitions) { if ((transition.Item1 == leavingState) && (transition.Item2 == enteringState)) { transitionFound = true; break; } } if (! transitionFound) { Tuple<State, State> transition = new Tuple<State, State>(leavingState, enteringState); transitions.Add(transition); HandleLeaveState(priority, newUpdates, change.Variable, leavingState, enteringState); HandleEnterState(priority, newUpdates, change.Variable, leavingState, enteringState); } } } } updatesToProcess = newUpdates; } }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="updates"></param> public void ApplyActivations(HashSet<Activation> activations) { foreach (Activation activation in activations) { if (activation.RuleCondition.Actions.Count > 0) { // Register the fact that a rule has been triggered Events.RuleFired ruleFired = new Events.RuleFired(activation.RuleCondition); EventTimeLine.AddModelEvent(ruleFired); // Registers all model updates due to this rule triggering foreach (Rules.Action action in activation.RuleCondition.Actions) { if (action.Statement != null) { Events.VariableUpdate variableUpdate = new Events.VariableUpdate(action, activation.Instance); EventTimeLine.AddModelEvent(variableUpdate); ruleFired.AddVariableUpdate(variableUpdate); } else { action.AddError("Cannot parse action statement"); } } } } CheckExpectationsState(); }