private FluentString GetPropReport(ISolver solver, SolverState commandState) { Report.WriteLine("Solver: {0}", SolverHelper.Describe(solver)); var propsReport = new FluentString(); propsReport.Append(solver.TypeDescriptor); try { var typeDescriptorProps = solver.GetTypeDescriptorProps(commandState); if (typeDescriptorProps != null) { foreach (var(name, text) in typeDescriptorProps) { propsReport.AppendLine($"-> {name,20}: {text}"); Report.WriteLine($"-> {name,20}: {text}"); } } } catch (NotSupportedException) { var msg = $"Solver [{solver.GetType().Name}] does not support {typeof(IExtendedFunctionalityDescriptor).Name}"; Report.WriteLine(msg); propsReport.AppendLine(msg); } catch (NotImplementedException) { var msg = $"Solver [{solver.GetType().Name}] does not support {typeof(IExtendedFunctionalityDescriptor).Name}"; Report.WriteLine(msg); propsReport.AppendLine(msg); } return(propsReport); }
public PlainUtils CreatePlainerType() { var cloned = new PlainUtils(); cloned.FluentString = FluentString.CreatePlainerType(); return(cloned); }
public void RenderToGraphVis() { var sample = new int[] { 23, 5, 12, 55, 67, 34, 33 }; var bst = new BinarySearchTree <int>(new IntComparer()); foreach (var val in sample) { var n = bst.Add(val); } var sb = new FluentString(); sb.AppendLine("digraph g {"); sb.AppendLine("rankdir=TB;"); foreach (var node in bst.GetNodes()) { if (node.Left != null) { sb.AppendLine($"\t{node.Value}->{node.Left.Value}[label=\"L\"]"); } if (node.Right != null) { sb.AppendLine($"\t{node.Value}->{node.Right.Value}[label=\"R\"]"); } // if (node.Parent != null) sb.AppendLine($"\t{node.Value}->{node.Parent.Value}"); } sb.AppendLine("}"); outp.WriteLine(sb); }
/// <summary> /// dot .\Exhause.dot -o file.svg -T svg /// </summary> public void Render(IEnumerable <SolverNode> items, TextWriter tw) { var sb = FluentString.Create() .AppendLine("digraph{ rankdir=BT;") .ForEach(items, (fb, x) => { string lbl = x.SolverNodeId.ToString(); string bg = null; var shape = ""; if (x.Parent == null) { shape = "doublecircle"; } else if (x.Status == SolverNodeStatus.Dead || x.Status == SolverNodeStatus.DeadRecursive) { shape = "square"; bg = "gray"; } else if (x.Status == SolverNodeStatus.Solution) { shape = "tripleoctagon"; } else if (x.Status == SolverNodeStatus.SolutionPath) { shape = "doubleoctagon"; } else if (x.Status == SolverNodeStatus.Evaluted || x.Status == SolverNodeStatus.Evaluted) { shape = "diamond"; } else if (x.Status == SolverNodeStatus.Duplicate) { shape = "tab"; if (x is ISolverNodeDuplicateLink dupLink) { lbl += "->" + dupLink.Duplicate?.SolverNodeId ?? "?"; } } else { shape = "cylinder"; } fb.Append($"{x.SolverNodeId} [label=\"{lbl}\" shape=\"{shape}\""); if (bg != null) { fb.Append($" style=\"filled\", fillcolor=\"{bg}\""); } fb.AppendLine("]"); }) .AppendLine("") .ForEach(items.Where(x => x.Parent != null), (fb, x) => fb.AppendLine($"{x.SolverNodeId} -> {x.Parent?.SolverNodeId.ToString() ?? "null"}")) .Append("}"); tw.WriteLine(sb); }
/// <summary> /// Method that compares a Fluent string to a Fluent number /// </summary> /// <param name="scope">Scope of Fluent Bundle</param> /// <param name="fs1"></param> /// <param name="fn2"></param> /// <returns></returns> public static bool MatchByPluralCategory(this IScope scope, FluentString fs1, FluentNumber fn2) { if (!fs1.TryGetPluralCategory(out var strCategory)) { return(false); } var numCategory = scope.GetPluralRules(RuleType.Cardinal, fn2); return(numCategory == strCategory); }
internal static ILocValue ToLocValue(this IFluentType arg) { return(arg switch { FluentNone => new LocValueNone(""), FluentNumber number => new LocValueNumber(number), FluentString str => new LocValueString(str), FluentLocWrapperType value => value.WrappedValue, _ => throw new ArgumentOutOfRangeException(nameof(arg)), });
public void TestFluentString() { var str = new FluentString("test string"); var ctx = new MessageContext("en-US"); str.Match(ctx, new FluentString("test string")).Should().BeTrue(); str.Match(ctx, "fifty").Should().BeFalse(); str.Match(ctx, "test string").Should().BeTrue(); str.Match(ctx, 45).Should().BeFalse(); }
public static bool TryWrite(this IExpression expression, TextWriter writer, Scope scope) { var errors = new List <FluentError>(); if (expression is IInlineExpression inlineExpression) { inlineExpression.Write(writer, scope); } else if (expression is SelectExpression selectExpression) { var selector = selectExpression.Selector.Resolve(scope); if (selector is FluentString or FluentNumber) { foreach (var variant in selectExpression.Variants) { IFluentType key; switch (variant.Type) { case VariantType.NumberLiteral: key = FluentNumber.TryNumber(variant.Key.Span); break; default: key = new FluentString(variant.Key.Span); break; } if (key.Matches(selector, scope)) { variant.Value.Write(writer, scope); return(scope.Errors.Count == 0); } } } for (var i = 0; i < selectExpression.Variants.Count; i++) { var variant = selectExpression.Variants[i]; if (variant.IsDefault) { variant.Value.Write(writer, scope); return(errors.Count == 0); } } errors.Add(ResolverFluentError.MissingDefault()); } return(scope.Errors.Count == 0); }
public ConsoleProgressNotifier(TextWriter tele) : base(TextWriter.Null) // we want a different format to go to file { this.tele = tele; var telText = new FluentString(",") .Append("DurationInSec").Sep() .Append("TotalNodes").Sep() .Append("NodesPerSec").Sep() .Append("NodesDelta").Sep() .Append("MemoryUsed") ; tele.WriteLine(telText); }
protected override string Render(ISolver caller, SolverState state, SolverStatistics global, string txt) { if (global == null) { return(null); } var totalMemory = System.GC.GetTotalMemory(false); var delta = (prev != null) ? global.TotalNodes - prev.TotalNodes : global.TotalNodes; var sb = new FluentString() .Append(txt) .Sep() .Append($"delta:{delta:#,##0}") .Sep() .Append($"mem({Humanise.SizeSuffix((ulong) totalMemory)} used") .Block(b => { if (DevHelper.TryGetTotalMemory(out var avail)) { b.Sep(); b.Append($"{Humanise.SizeSuffix(avail)} avail"); } }) .Append(")"); var telText = new FluentString(",") .Append(global.DurationInSec.ToString()).Sep() .Append(global.TotalNodes.ToString()).Sep() .Append(global.NodesPerSec.ToString()).Sep() .Append(delta.ToString()).Sep() .Append(totalMemory.ToString()).Sep() ; tele.WriteLine(telText); prev = new SolverStatistics(global); return(sb); }
public string ToString(bool verbose, bool skipName = false) { var builder = new FluentString() .If(Name != null && !skipName, $"{Name,-40}"); if (DurationInSec <= 0d || TotalNodes <= 0) { return(builder.Append($"{TotalNodes,12:#,##0} nodes")); } builder.When(verbose, then => then.If(TotalDead >= 0, () => $" Dead={TotalDead:#,##0}:{TotalDead * 100 / TotalNodes:0}%") .If(Duplicates >= 0, () => $" Dup={Duplicates:#,##0}:{Duplicates * 100 / TotalNodes:0}%") .If(DepthCurrent >= 0, () => $" Depth={DepthCurrent:#,##0}:{DepthMax:#,##0}") .If(DepthCompleted >= 0, () => $" DepthComplete={DepthCompleted:#,##0}") ) .Append($"{TotalNodes,11:#,##0} nodes at {TotalNodes / DurationInSec,7:#,##0}/s in {Elapsed.Humanize()}"); return(builder); }
protected PlainUtils CreatePlainerType(PlainUtils cloned) { cloned.FluentString = FluentString.CreatePlainerType(); return(cloned); }
public void LazyShadowToOnline() { FluentString.LazyShadowToOnline(); }
public void LazyOnlineToShadow() { FluentString.LazyOnlineToShadow(); }
public ExitConditions.Conditions Solve(SolverState state) { var full = (MultiThreadedSolverState)state; var allTasks = full.Workers.Select(x => (Task)x.Task).ToArray(); var cancel = state.Command.CancellationToken; // Start and wait full.IsRunning = true; foreach (var worker in full.Workers) { worker.Task.Start(); } Task statisticsTick = null; if (state.Command.AggProgress != null) { // Setup global/aggregate statistics and updates statisticsTick = Task.Run(() => { while (full.IsRunning) { Thread.Sleep(1000); state.Statistics.TotalNodes = current.PoolForward.Statistics.TotalNodes + current.PoolReverse.Statistics.TotalNodes; var txt = new FluentString() .Append($"==> {state.Statistics.ToString(false, true)}") .Append($" Fwd({current.PoolForward.Statistics.TotalNodes:#,##0}|{current.QueueForward.Statistics.TotalNodes:#,##0})") .Append($" Rev({current.PoolReverse.Statistics.TotalNodes:#,##0}|{current.QueueReverse.Statistics.TotalNodes:#,##0})"); state.Command.AggProgress.Update(this, state, state.Statistics, txt); } if (state.Command.AggProgress is IDisposable dp) { dp.Dispose(); } }); } if (!Task.WaitAll(allTasks, (int)state.Command.ExitConditions.Duration.TotalMilliseconds, cancel)) { // Close down the workers as gracefully as possible state.Command.ExitConditions.ExitRequested = true; // Allow them to process the ExitRequested Thread.Sleep((int)TimeSpan.FromSeconds(1).TotalMilliseconds); // Close down any outlyers foreach (var task in allTasks) { if (task.Status == TaskStatus.Running) { if (!task.Wait((int)TimeSpan.FromSeconds(1).TotalMilliseconds)) { task.Dispose(); } } } state.Exit = ExitConditions.Conditions.TimeOut; } full.IsRunning = false; statisticsTick?.Wait(); state.Statistics.Completed = DateTime.Now; foreach (var stat in current.StatsInner) { stat.Completed = state.Statistics.Completed; } // Get solutions & Exit Conditions & Errors var errors = full.Workers.Select(x => x.WorkerState.Exception).Where(x => x != null).ToList(); if (errors.Any()) { throw new AggregateException(errors); } foreach (var worker in full.Workers) { worker.WorkerState.Statistics.Completed = state.Statistics.Completed; // Bubble up exit to owner state.Command.Report?.WriteLine($"WorkerExit: {worker.Name} -> {worker.WorkerState.Exit}"); if (state.Exit == ExitConditions.Conditions.InProgress && (worker.WorkerState.Exit != ExitConditions.Conditions.InProgress && worker.WorkerState.Exit != ExitConditions.Conditions.Aborted)) { state.Exit = worker.WorkerState.Exit; } if (worker.WorkerState.HasSolution) { if (worker.WorkerState.SolutionsNodes != null) { full.SolutionsNodes ??= new List <SolverNode>(); full.SolutionsNodes.AddRange(worker.WorkerState.SolutionsNodes); state.Exit = ExitConditions.Conditions.Solution; } if (worker.WorkerState.SolutionsNodesReverse != null) { full.SolutionsNodesReverse ??= new List <SolutionChain>(); full.SolutionsNodesReverse.AddRange(worker.WorkerState.SolutionsNodesReverse); state.Exit = ExitConditions.Conditions.Solution; } } } // Update stats state.Statistics.TotalNodes = current.PoolForward.Statistics.TotalNodes + current.PoolReverse.Statistics.TotalNodes; SolverHelper.GetSolutions(state, true); if (state.Exit == ExitConditions.Conditions.Continue) { state.Exit = full.Workers.Select(x => x.WorkerState.Exit) .GroupBy(x => x) .OrderBy(x => x.Count()) .First().Key; } return(state.Exit); }
public int SolverRun(BatchArgs batchArgs, SolverRun run) { var args = new FluentString(" ") .Append(batchArgs.Puzzle).Sep() .Append($"--solver {batchArgs.Solver}").Sep() .Append($"--pool {batchArgs.Pool}").Sep() .If(batchArgs.Min > 0, $"--min {batchArgs.Min}").Sep() .If(batchArgs.Sec > 0, $"--sec {batchArgs.Sec}").Sep() .If(batchArgs.MinR > 0, $"--min-rating {batchArgs.MinR}").Sep() .If(batchArgs.MaxR < 2000, $"--min-rating {batchArgs.MaxR}"); batchArgs.Console.WriteLine($"Arguments: {args}"); var exitRequested = false; SolverCommand?executing = null; // Setup: Report and cancellation var benchId = DateTime.Now.ToString("s").Replace(':', '-'); var outFile = $"./benchmark--{benchId}.txt"; var outTele = $"./telemetry--{benchId}.csv"; var outFolder = "./results/"; if (!Directory.Exists(outFolder)) { Directory.CreateDirectory(outFolder); } var info = new FileInfo(System.IO.Path.Combine(outFolder, outFile)); var tele = new FileInfo(System.IO.Path.Combine(outFolder, outTele)); using var report = File.CreateText(info.FullName); using var repTele = File.CreateText(tele.FullName); System.Console.CancelKeyPress += (o, e) => { report.Flush(); batchArgs.Console.WriteLine("Ctrl+C detected; cancel requested"); if (executing != null) { executing.ExitConditions.ExitRequested = true; } exitRequested = true; }; ISokobanSolutionRepository?solutionRepo = File.Exists("./solutions.json") && !DevHelper.IsDebug() ? new JsonSokobanSolutionRepository("./solutions.json") : null; ISolverRunTracking?runTracking = null; var results = new List <(Strategy, List <SolverResultSummary>)>(); var perm = GetPermutations(batchArgs.Solver, batchArgs.Pool).ToList(); var countStrat = 0; foreach (var strat in perm) { countStrat++; batchArgs.Console.WriteLine($"(Strategy {countStrat}/{perm.Count}) {strat}"); var ioc = new SolverContainerByType(new Dictionary <Type, Func <Type, object> >() { { typeof(ISolverPool), _ => PoolFactory(strat.Pool) }, { typeof(ISolverQueue), _ => new SolverQueueConcurrent() }, { typeof(ISolverRunTracking), _ => runTracking }, { typeof(ISokobanSolutionRepository), _ => solutionRepo }, }); var solverCommand = new SolverCommand { ServiceProvider = ioc, ExitConditions = new ExitConditions() { Duration = TimeSpan.FromMinutes(batchArgs.Min).Add(TimeSpan.FromSeconds(batchArgs.Sec)), MemAvail = DevHelper.GiB_1 / 2, // Stops the machine hanging / swapping to death StopOnSolution = true, }, AggProgress = new ConsoleProgressNotifier(repTele), CheckAbort = x => exitRequested, }; var runner = new SingleSolverBatchSolveComponent( new TextWriterAdapter(report), batchArgs.Console, solutionRepo, runTracking, 5, false); var solverInstance = SolverFactory(strat.Solver, ioc); var summary = runner.Run(run, solverCommand, solverInstance, false, batchArgs); results.Add((strat, summary)); } // Header var extras = new Dictionary <string, string>() { { "Args", args }, { "Report", info.FullName } }; DevHelper.WriteFullDevelopmentContext(report, extras); DevHelper.WriteFullDevelopmentContext(System.Console.Out, extras); // Body var reportRow = GenerateReport(results).ToList(); MapToReporting.Create <SummaryLine>() .AddColumn("Solver", x => x.Strategy.Solver) .AddColumn("Pool", x => x.Strategy.Pool) .AddColumn("Puzzle", x => x.Result.Puzzle.Ident) .AddColumn("State", x => x.Result.Exited) .AddColumn("Solutions", x => (x.Result.Solutions?.Count ?? 0) == 0 ? null : (int?)x.Result.Solutions.Count) .AddColumn("Statistics", x => x.Result.Exited == ExitConditions.Conditions.Error ? x.Result.Exited.ToString() : x.Result.Statistics?.ToString(false, true) ) .RenderTo(reportRow, new MapToReportingRendererText(), report) .RenderTo(reportRow, new MapToReportingRendererText(), System.Console.Out); return(results.Any(x => x.Item2.Any(y => y.Exited == ExitConditions.Conditions.Error)) ? -1 : 0); // All exceptions }