public override bool CheckCriteria(IRegistry registry, IRegistryResolver resolver) { HookInvokeCriteria baseCriteria = ParameterRegistry.Get <HookInvokeCriteria>("base_criteria"); long targetRepetitions = ParameterRegistry.Get <long>("target_repetitions"); long currentRepititions = ParameterRegistry.Get <long>("current_repetitions"); bool withoutInterruption = ParameterRegistry.Get <bool>("without_interruption"); if (baseCriteria.CheckCriteria(registry, resolver)) { currentRepititions++; } else if (withoutInterruption) { currentRepititions = 0; } bool fire = currentRepititions >= targetRepetitions; if (fire) { currentRepititions = 0; } ParameterRegistry["current_repetitions"] = currentRepititions; return(fire); }
/// <summary> /// End a validation scoring session. /// Write out results here. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> protected override void ScoreEnd(IRegistry registry, IRegistryResolver resolver) { string resultKey = ParameterRegistry.Get <string>("result_key"); double accuracy = (double)ParameterRegistry.Get <int>("correct_classifications") / ParameterRegistry.Get <int>("total_classifications"); resolver.ResolveSet(resultKey, accuracy, true); }
/// <summary> /// Score an intermediate result (part of the entire validation dataset was used as specified by the validation iterator). /// </summary> /// <param name="predictions">The predictions.</param> /// <param name="targets">The targets.</param> /// <param name="handler">The computation handler.</param> protected override void ScoreIntermediate(INDArray predictions, INDArray targets, IComputationHandler handler) { predictions = handler.FlattenTimeAndFeatures(predictions); targets = handler.FlattenTimeAndFeatures(targets); if (predictions.Shape[1] != 1) { throw new InvalidOperationException($"Cannot score uni-class classification accuracy on targets with != 1 feature shape (feature shape length was {predictions.Shape[1]})."); } int totalClassifications = ParameterRegistry.Get <int>("total_classifications"); int correctClassifications = ParameterRegistry.Get <int>("correct_classifications"); double lowerThreshold = ParameterRegistry.Get <double>("lower_threshold"); double upperThreshold = ParameterRegistry.Get <double>("upper_threshold"); for (int i = 0; i < predictions.Shape[0]; i++) { double value = predictions.GetValue <double>(i, 0); int target = targets.GetValue <int>(i, 0); if (value < lowerThreshold && target == 0 || value > upperThreshold && target == 1) { correctClassifications++; } } totalClassifications += (int)predictions.Shape[0]; ParameterRegistry["total_classifications"] = totalClassifications; ParameterRegistry["correct_classifications"] = correctClassifications; }
/// <summary> /// Invoke this hook with a certain parameter registry. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { string registryEntry = ParameterRegistry.Get <string>("registry_entry"); string resultEntry = ParameterRegistry.Get <string>("shared_result_entry"); double value = resolver.ResolveGetSingle <double>(registryEntry); double previousAccumulatedValue = ParameterRegistry.Get <double>("accumulated_value"); int currentInterval = HookUtils.GetCurrentInterval(registry, TimeStep.TimeScale); int resetInterval = ParameterRegistry.Get <int>("reset_interval"); int resetEvery = ParameterRegistry.Get <int>("reset_every"); int countSinceReset = ParameterRegistry.Get <int>("count_since_reset"); if (currentInterval == resetInterval || resetEvery > 0 && currentInterval % resetEvery == 0) { previousAccumulatedValue = 0.0; countSinceReset = 0; } countSinceReset++; double result = value + previousAccumulatedValue; if (ParameterRegistry.Get <bool>("average_mode")) { result /= countSinceReset; } ParameterRegistry["count_since_reset"] = countSinceReset; ParameterRegistry["accumulated_value"] = value + previousAccumulatedValue; resolver.ResolveSet(resultEntry, result, addIdentifierIfNotExists: true); }
/// <summary> /// Invoke this hook with a certain parameter registry if optional conditional criteria are satisfied. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { IValueModifier modifier = ParameterRegistry.Get <IValueModifier>("modifier"); string identifier = ParameterRegistry.Get <string>("parameter_identifier"); object parameter = resolver.ResolveGetSingle <object>(identifier); INumber asNumber = parameter as INumber; INDArray asArray = parameter as INDArray; if (asNumber != null) { parameter = modifier.Modify(identifier, asNumber, asNumber.AssociatedHandler); } else if (asArray != null) { parameter = modifier.Modify(identifier, asArray, asArray.AssociatedHandler); } else { throw new InvalidOperationException($"Cannot apply modifier {modifier} to parameter \"{identifier}\" with value {parameter}, " + $"parameter is neither {nameof(INumber)} nor {nameof(INDArray)}."); } resolver.ResolveSet(identifier, parameter); }
/// <summary> /// Score an intermediate result (part of the entire validation dataset was used as specified by the validation iterator). /// </summary> /// <param name="predictions">The predictions.</param> /// <param name="targets">The targets.</param> /// <param name="handler">The computation handler.</param> protected override void ScoreIntermediate(INDArray predictions, INDArray targets, IComputationHandler handler) { predictions = handler.FlattenTimeAndFeatures(predictions); if (predictions.Shape[1] <= 1) { throw new InvalidOperationException($"Cannot score multi-class classification accuracy on targets with less than 2 feature indices (there were {predictions.Shape[1]}."); } int[] tops = ParameterRegistry.Get <int[]>("tops"); predictions = handler.RowWise(predictions, handler.SoftMax); var perRowTopPredictions = handler.RowWiseTransform(predictions, row => row.GetDataAs <double>().Data.Select((x, i) => new KeyValuePair <double, int>(x, i)).OrderByDescending(x => x.Key).Select(p => p.Value).ToArray()).ToList(); int[] targetIndices = handler.RowWiseTransform(handler.FlattenTimeAndFeatures(targets), handler.MaxIndex); foreach (int top in tops) { int correctClassifications = perRowTopPredictions.Where((rowPredictions, rowIndex) => rowPredictions.Take(top).Any(predicted => predicted == targetIndices[rowIndex])).Count(); ParameterRegistry[$"correct_classifications_top{top}"] = ParameterRegistry.Get <int>($"correct_classifications_top{top}") + correctClassifications; } ParameterRegistry["total_classifications"] = ParameterRegistry.Get <int>("total_classifications") + targetIndices.Length; }
/// <summary> /// Internal constructor for custom training hook derivatives with additional requirements. /// </summary> /// <param name="timeStep"></param> protected StopTrainingHook(TimeStep timeStep) : base(timeStep) { DefaultTargetMode = TargetMode.Global; InvokePriority = 10000; // typically the training should be stopped after all other hooks have been invoked // (hooks would be invoked anyway, it just looks cleaner) ParameterRegistry.Set("requested_stop", false, typeof(bool)); }
private void Initialise() { IRegistry reg = new Registry(); reg.Add(RegistryResolver, new RegistryResolver(reg)); ParameterRegistry.Add(ValueIdentifier, reg); }
/// <summary> /// Invoke this hook with a certain parameter registry if optional conditional criteria are satisfied. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { string baseResultKey = ParameterRegistry.Get <string>("base_result_key"); long lastTime = resolver.ResolveGetSingleWithDefault(baseResultKey + "_last", -1L); long averageTime = resolver.ResolveGetSingleWithDefault(baseResultKey + "_average", -1L); Report(TimeStep.TimeScale, lastTime, averageTime); }
public ApplyModifierHook(string parameter, IValueModifier modifier, TimeStep timeStep) : base(timeStep, parameter) { if (modifier == null) { throw new ArgumentNullException(nameof(modifier)); } ParameterRegistry.Set("parameter_identifier", parameter, typeof(string)); ParameterRegistry.Set("modifier", modifier, typeof(string)); }
/// <summary> /// Create a hook with a certain time step and a set of required global registry entries. /// </summary> /// <param name="timeStep">The time step.</param> /// <param name="averageSpan">The interval span to average over.</param> public RunningTimeReporter(ITimeStep timeStep, int averageSpan = 4) : base(timeStep) { DefaultTargetMode = TargetMode.Global; string baseResultKey = $"shared.time_{timeStep.TimeScale}"; RequireHook(new RunningTimeProcessorHook(timeStep.TimeScale, averageSpan, baseResultKey)); ParameterRegistry.Set("base_result_key", baseResultKey, typeof(string)); }
/// <summary> /// Begin a validation scoring session. /// Reset the scoring here. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> protected override void ScoreBegin(IRegistry registry, IRegistryResolver resolver) { int[] tops = ParameterRegistry.Get <int[]>("tops"); foreach (int t in tops) { ParameterRegistry[$"correct_classifications_top{t}"] = 0; } ParameterRegistry["total_classifications"] = 0; }
public ShadowConfig(SceneManager scene) { this.scene = scene; GetShaderSupport(); shadowTechnique = ShadowTechnique.None; ParameterRegistry.RegisterSubsystemHandlers("Shadows", setShadowParameterHandler, getShadowParameterHandler); }
/// <summary> /// Invoke this hook with a certain parameter registry. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { int[] tops = ParameterRegistry.Get <int[]>("tops"); IDictionary <int, double> topDictionary = new Dictionary <int, double>(); foreach (int top in tops) { topDictionary[top] = resolver.ResolveGetSingle <double>("shared.classification_accuracy_top" + top); } Report(topDictionary); }
/// <summary> /// Check if this hook's functionality is equal to that of another. /// Used when deciding which hooks can be omitted (optimised out). /// Note: Different parameters typically infer different functionalities, here only the parameters in the <see cref="ParameterRegistry"/> are checked. /// If your custom hook for any reason requires any additional parameters that alter its behaviour you should add your own checks to this method. /// </summary> /// <param name="other">The hook to check.</param> /// <returns>A boolean indicating whether or not the other hook does the same that this one does.</returns> public bool FunctionallyEquals(IHook other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } BaseHook otherAsBaseHook = other as BaseHook; bool otherParametersEqual = otherAsBaseHook == null || ParameterRegistry.RegistryContentEquals(otherAsBaseHook.ParameterRegistry); return(GetType() == other.GetType() && TimeStep.StepEquals(other.TimeStep) && otherParametersEqual); }
public override bool CheckCriteria(IRegistry registry, IRegistryResolver resolver) { string parameter = ParameterRegistry.Get <string>("parameter_identifier"); object rawValue = SimpleDirectEntries[0] ? registry.Get(parameter) : resolver.ResolveGetSingle <object>(parameter); double value = (double)Convert.ChangeType(rawValue, typeof(double)); bool thresholdReached = _InternalThresholdReached(value, ParameterRegistry.Get <double>("threshold_value"), ParameterRegistry.Get <ComparisonTarget>("target")); bool fire = thresholdReached && (!ParameterRegistry.Get <bool>("last_check_met") || ParameterRegistry.Get <bool>("fire_continously")); ParameterRegistry["last_check_met"] = thresholdReached; return(fire); }
public override RepeatCriteria Repeated(long times, bool withoutInterruption = false) { // only stack if both check for the exact same criteria if (withoutInterruption != ParameterRegistry.Get <bool>("without_interruption")) { return(base.Repeated(times, withoutInterruption)); } ParameterRegistry["target_repetitions"] = checked (ParameterRegistry.Get <long>("target_repetitions") * times); return(this); }
/// <summary> /// Invoke this hook with a certain parameter registry if optional conditional criteria are satisfied. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { if (ParameterRegistry.ContainsKey("last_time")) { bool removeExtremas = ParameterRegistry.Get <bool>("remove_extremas"); long lastTime = ParameterRegistry.Get <long>("last_time"); long currentTime = Operator.RunningTimeMilliseconds; long elapsedTime = currentTime - lastTime; LinkedList <long> lastRunningTimes = ParameterRegistry.Get <LinkedList <long> >("last_running_times"); string sharedResultBaseKey = ParameterRegistry.Get <string>("shared_result_base_key"); int averageSpan = ParameterRegistry.Get <int>("average_span"); lastRunningTimes.AddLast(elapsedTime); int numberRunningTimes = lastRunningTimes.Count; if (numberRunningTimes > averageSpan) { lastRunningTimes.RemoveFirst(); numberRunningTimes--; } long averageTime = lastRunningTimes.Sum(); if (removeExtremas) { LinkedList <long> runningTimesCopy = new LinkedList <long>(lastRunningTimes); int timesToRemove = (int)Math.Sqrt(lastRunningTimes.Count / 2.0f); // TODO magic number while (timesToRemove-- > 0) { long removedTime = timesToRemove % 2 == 0 ? runningTimesCopy.Max() : runningTimesCopy.Min(); runningTimesCopy.Remove(removedTime); } averageTime = runningTimesCopy.Sum(); numberRunningTimes = runningTimesCopy.Count; } averageTime /= numberRunningTimes; resolver.ResolveSet(sharedResultBaseKey + "_last", elapsedTime, addIdentifierIfNotExists: true); resolver.ResolveSet(sharedResultBaseKey + "_average", averageTime, addIdentifierIfNotExists: true); resolver.ResolveSet(sharedResultBaseKey + "_min", lastRunningTimes.Min(), addIdentifierIfNotExists: true); resolver.ResolveSet(sharedResultBaseKey + "_max", lastRunningTimes.Max(), addIdentifierIfNotExists: true); } ParameterRegistry["last_time"] = Operator.RunningTimeMilliseconds; }
public override bool CheckCriteria(IRegistry registry, IRegistryResolver resolver) { IList <HookInvokeCriteria> criterias = ParameterRegistry.Get <IList <HookInvokeCriteria> >("criterias"); for (int i = 0; i < criterias.Count; i++) { if (!criterias[i].CheckCriteria(registry, resolver)) { return(false); } } return(true); }
/// <summary> /// Create a hook with a certain time step and a set of required global registry entries. /// </summary> /// <param name="timeScale">The time scale.</param> /// <param name="averageSpan">The interval span to average over.</param> /// <param name="sharedResultBaseKey">The shared result base key (under which results will be available).</param> /// <param name="removeExtremas"></param> public RunningTimeProcessorHook(TimeScale timeScale, int averageSpan, string sharedResultBaseKey, bool removeExtremas = true) : base(Utils.TimeStep.Every(1, timeScale)) { if (sharedResultBaseKey == null) { throw new ArgumentNullException(nameof(sharedResultBaseKey)); } DefaultTargetMode = TargetMode.Global; ParameterRegistry.Set("average_span", averageSpan, typeof(int)); ParameterRegistry.Set("shared_result_base_key", sharedResultBaseKey, typeof(string)); ParameterRegistry.Set("last_running_times", new LinkedList <long>()); ParameterRegistry.Set("remove_extremas", removeExtremas, typeof(bool)); }
/// <summary> /// Invoke this hook with a certain parameter registry if optional conditional criteria are satisfied. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { if (!ParameterRegistry.Get <bool>("requested_stop")) // TODO should there be a flag to always stop / reset this parameter (e.g. if training is restarted with the same hooks)? { _logger.Info($"Stopping training because condition {InvokeCriteria} was met."); Operator.SignalStop(); ParameterRegistry["requested_stop"] = true; } else { _logger.Debug($"Should stop training but stop signal was already sent."); } }
/// <summary> /// End a validation scoring session. /// Write out results here. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> protected override void ScoreEnd(IRegistry registry, IRegistryResolver resolver) { int[] tops = ParameterRegistry.Get <int[]>("tops"); foreach (int top in tops) { string resultBaseKey = ParameterRegistry.Get <string>("result_base_key"); int totalClassifications = ParameterRegistry.Get <int>("total_classifications"); int correctClassifications = ParameterRegistry.Get <int>($"correct_classifications_top{top}"); double score = ((double)correctClassifications) / totalClassifications; resolver.ResolveSet(resultBaseKey + top, score, addIdentifierIfNotExists: true); } }
////////////////////////////////////////////////////////////////////// // // The external interface to the collision library // ////////////////////////////////////////////////////////////////////// public CollisionAPI(bool logCollisions) { if (logCollisions) #if NOT { MO.InitLog(true); } #else { MO.DoLog = true; } #endif sphereTree = new SphereTree(); sphereTree.Initialize(); topLevelCalls = 0; partCalls = 0; topLevelCollisions = 0; collisionTestCount = 0; ParameterRegistry.RegisterSubsystemHandlers("CollisionAPI", setParameterHandler, getParameterHandler); }
/// <inheritdoc /> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { IComputationHandler handler = Operator.Handler; string registryEntryToProcess = ParameterRegistry.Get <string>("registry_entry_to_process"); Func <T, IComputationHandler, INumber> metricFunction = ParameterRegistry.Get <Func <T, IComputationHandler, INumber> >("metric_function"); string metricSharedResultIdentifier = ParameterRegistry.Get <string>("metric_shared_result_identifier"); object[] entries = resolver.ResolveGet <object>(registryEntryToProcess); double totalMetric = 0.0; int count = 0; foreach (object entry in entries) { T entryAsT = entry as T; IEnumerable <T> entryAsEnumerable = entry as IEnumerable <T>; IDictionary <string, T> entryAsDictionary = entry as IDictionary <string, T>; if (entryAsDictionary != null) { entryAsEnumerable = entryAsDictionary.Values; } if (entryAsT != null) { totalMetric += metricFunction.Invoke(entryAsT, handler).GetValueAs <double>(); count++; } else if (entryAsEnumerable != null) { foreach (T value in entryAsEnumerable) { totalMetric += metricFunction.Invoke(value, handler).GetValueAs <double>(); count++; } } else { throw new InvalidOperationException($"Cannot process metric for entry of type {entry.GetType()} with identifier \"{registryEntryToProcess}\", must be {typeof(T)} or enumerable thereof."); } } double resultMetric = totalMetric / count; resolver.ResolveSet(metricSharedResultIdentifier, resultMetric, addIdentifierIfNotExists: true); }
/// <summary> /// Create a command that sets multiple registry kess to multiple different values. /// Both arrays may not be <c>null</c>, nor empty, nor differ in length. /// </summary> /// <param name="keys">The registry keys that will be modified. They have to be fully resolved.</param> /// <param name="values">The values that will be set to the registry. The first key will receive the first value and so on.</param> /// <param name="onFinish">The function that will be called when the execution has been finished. If <c>null</c>, no function will be called.</param> public SetValueCommand(string[] keys, T[] values, Action onFinish = null) : base(onFinish, keys) { if (keys == null) { throw new ArgumentNullException(nameof(keys)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (keys.Length == 0) { throw new ArgumentException("Value cannot be an empty collection.", nameof(keys)); } if (values.Length == 0) { throw new ArgumentException("Value cannot be an empty collection.", nameof(values)); } // if there is only one value, all keys will receive this value // if the lengths are different, we don't know what to do if (values.Length != 1 && keys.Length != values.Length) { throw new ArgumentException($"{nameof(keys)} and {nameof(values)} have different lengths.", nameof(keys)); } // set default values AddItentifierIfNotExists = false; // expand the values if (values.Length == 1 && keys.Length != 1) { T[] expandedValues = new T[keys.Length]; for (int i = 0; i < expandedValues.Length; i++) { expandedValues[i] = values[0]; } values = expandedValues; } //store keys and values in the parameter registry ParameterRegistry.Add(KeyIdentifier, keys); ParameterRegistry.Add(ValueIdentifier, values); }
/// <summary> /// Invoke this hook with a certain parameter registry. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { INetwork network = resolver.ResolveGetSingle <INetwork>("network.self"); ITrainer trainer = resolver.ResolveGetSingle <ITrainer>("trainer.self"); string validationIteratorName = ParameterRegistry.Get <string>("validation_iterator_name"); string finalExternalOutputAlias = ParameterRegistry.Get <string>("final_external_output_alias"); string activationsAlias = ParameterRegistry.Get <string>("output_activations_alias"); string targetsAlias = ParameterRegistry.Get <string>("targets_alias"); if (!trainer.AdditionalNameDataIterators.ContainsKey(validationIteratorName)) { throw new InvalidOperationException($"Additional named data iterator for validation with name \"{validationIteratorName}\" does not exist in referenced trainer {trainer} but is required."); } IDataIterator validationIterator = trainer.AdditionalNameDataIterators[validationIteratorName]; ScoreBegin(registry, resolver); foreach (var block in validationIterator.Yield(Operator.Handler, Operator.Sigma)) { trainer.ProvideExternalInputData(network, block); network.Run(Operator.Handler, trainingPass: false); INDArray finalOutputPredictions = null; foreach (ILayerBuffer layerBuffer in network.YieldExternalOutputsLayerBuffers()) { foreach (string outputAlias in layerBuffer.ExternalOutputs) { if (outputAlias.Equals(finalExternalOutputAlias)) { finalOutputPredictions = Operator.Handler.ClearTrace(layerBuffer.Outputs[outputAlias].Get <INDArray>(activationsAlias)); goto FoundOutput; } } ; } throw new InvalidOperationException($"Cannot find final output with alias \"{finalExternalOutputAlias}\" in the current network (but is required to score validation)."); FoundOutput: ScoreIntermediate(finalOutputPredictions, block[targetsAlias], Operator.Handler); } ScoreEnd(registry, resolver); }
public override bool CheckCriteria(IRegistry registry, IRegistryResolver resolver) { ExtremaTarget target = ParameterRegistry.Get <ExtremaTarget>("target"); string parameter = ParameterRegistry.Get <string>("parameter_identifier"); double value = SimpleDirectEntries[0] ? registry.Get <double>(parameter) : resolver.ResolveGetSingle <double>(parameter); double currentExtremum = ParameterRegistry.Get <double>("current_extremum"); bool reachedExtremum = target == ExtremaTarget.Min && value <currentExtremum || target == ExtremaTarget.Max && value> currentExtremum; if (double.IsNaN(currentExtremum) || reachedExtremum) { ParameterRegistry["current_extremum"] = value; return(true); } return(false); }
/// <summary> /// Invoke this hook with a certain parameter registry. /// </summary> /// <param name="registry">The registry containing the required values for this hook's execution.</param> /// <param name="resolver">A helper resolver for complex registry entries (automatically cached).</param> public override void SubInvoke(IRegistry registry, IRegistryResolver resolver) { string[] accumulatedIdentifiers = ParameterRegistry.Get <string[]>("accumulated_identifiers"); string[] valueIdentifiers = ParameterRegistry.Get <string[]>("value_identifiers"); IDictionary <string, object> valuesByIdentifier = ParameterRegistry.Get <IDictionary <string, object> >("value_buffer"); for (int i = 0; i < valueIdentifiers.Length; i++) { // TODO let callee decide if it's a number (double) / something else object value = resolver.ResolveGetSingle <double>(accumulatedIdentifiers[i]); valuesByIdentifier[valueIdentifiers[i]] = value; } ReportValues(valuesByIdentifier, ParameterRegistry.Get <bool>("report_epoch_iteration"), registry.Get <int>("epoch"), registry.Get <int>("iteration")); }
/// <summary> /// The external toggle function. Invoke this to toggle this criteria. /// </summary> public void ExternalToggle() { lock (ParameterRegistry) { int state = ParameterRegistry.Get <int>("state"); if (state < 0) { state = int.MaxValue; } else { state = int.MinValue; } ParameterRegistry["state"] = state; } }
/// <summary> /// The external hold function. Invoke this to hold this criteria active for +1 check. /// </summary> public void ExternalHold() { lock (ParameterRegistry) { int state = ParameterRegistry.Get <int>("state"); if (state < 0) { state = 0; } if (state < int.MaxValue) { state++; } ParameterRegistry["state"] = state; } }