diff --git a/benchmark/BenchmarkDotNet.Artifacts/results/Program.Benchmarks-report-github.md b/benchmark/BenchmarkDotNet.Artifacts/results/Program.Benchmarks-report-github.md index f247d2d..1bcb8f7 100644 --- a/benchmark/BenchmarkDotNet.Artifacts/results/Program.Benchmarks-report-github.md +++ b/benchmark/BenchmarkDotNet.Artifacts/results/Program.Benchmarks-report-github.md @@ -1,27 +1,27 @@ ``` -BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, macOS Monterey 12.6.9 (21G726) [Darwin 21.6.0] -Intel Core i7-6700K CPU 4.00GHz (Skylake), 1 CPU, 8 logical and 4 physical cores -.NET SDK 6.0.403 - [Host] : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2 DEBUG - DefaultJob : .NET 6.0.11 (6.0.1122.52304), X64 RyuJIT AVX2 +BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, macOS Ventura 13.5 (22G74) [Darwin 22.6.0] +Apple M2 Max, 1 CPU, 12 logical and 12 physical cores +.NET SDK 6.0.415 + [Host] : .NET 6.0.23 (6.0.2323.48002), Arm64 RyuJIT AdvSIMD DEBUG + DefaultJob : .NET 6.0.23 (6.0.2323.48002), Arm64 RyuJIT AdvSIMD ``` -| Method | Mean | Error | StdDev | -|-------------------- |-------------:|------------:|------------:| -| AllPairesInt_100 | 200.5 μs | 2.35 μs | 1.96 μs | -| AllPairsInt_200 | 1,351.2 μs | 13.08 μs | 10.92 μs | -| AllPairsBR_100 | 994.5 μs | 4.76 μs | 4.22 μs | -| AllPairsBR_200 | 5,406.7 μs | 22.60 μs | 18.87 μs | -| AllPairsBR_Rand_100 | 3,571.2 μs | 15.51 μs | 13.75 μs | -| AllPairsBR_Rand_200 | 16,147.1 μs | 158.76 μs | 140.73 μs | -| SolveCountMinIncl | 281.5 μs | 1.07 μs | 0.89 μs | -| Solve_1_Eqs_100 | 44,174.2 μs | 870.02 μs | 854.48 μs | -| Solve_1_Eqs_200 | 177,626.8 μs | 3,524.22 μs | 4,582.48 μs | -| Solve_3_Eqs_100 | 45,644.5 μs | 724.51 μs | 642.26 μs | -| Solve_3_Eqs_200 | 179,394.1 μs | 3,491.76 μs | 4,779.56 μs | -| Solve_1_Eqs_Rand_10 | 24,787.3 μs | 93.87 μs | 78.39 μs | -| Solve_1_Eqs_Rand_20 | 271,758.6 μs | 3,096.51 μs | 2,896.48 μs | -| Solve_3_Eqs_Rand_10 | 25,649.5 μs | 89.37 μs | 69.78 μs | -| Solve_3_Eqs_Rand_20 | 269,382.4 μs | 1,385.37 μs | 1,295.88 μs | +| Method | Mean | Error | StdDev | Median | +|-------------------- |-------------:|------------:|------------:|-------------:| +| AllPairesInt_100 | 126.3 μs | 1.33 μs | 1.24 μs | 126.3 μs | +| AllPairsInt_200 | 1,076.4 μs | 6.78 μs | 6.01 μs | 1,074.6 μs | +| AllPairsBR_100 | 639.7 μs | 12.69 μs | 33.89 μs | 628.6 μs | +| AllPairsBR_200 | 3,585.7 μs | 7.39 μs | 6.91 μs | 3,583.7 μs | +| AllPairsBR_Rand_100 | 2,068.7 μs | 5.88 μs | 5.50 μs | 2,071.2 μs | +| AllPairsBR_Rand_200 | 10,738.3 μs | 95.29 μs | 74.40 μs | 10,724.1 μs | +| SolveCountMinIncl | 153.3 μs | 2.28 μs | 2.13 μs | 153.8 μs | +| Solve_1_Eqs_100 | 28,284.4 μs | 255.51 μs | 239.01 μs | 28,372.7 μs | +| Solve_1_Eqs_200 | 105,200.0 μs | 1,523.82 μs | 1,425.38 μs | 105,116.0 μs | +| Solve_3_Eqs_100 | 29,274.8 μs | 585.01 μs | 518.60 μs | 29,154.9 μs | +| Solve_3_Eqs_200 | 107,030.6 μs | 1,688.19 μs | 1,579.14 μs | 107,266.9 μs | +| Solve_1_Eqs_Rand_10 | 16,717.6 μs | 183.67 μs | 171.81 μs | 16,639.5 μs | +| Solve_1_Eqs_Rand_20 | 177,293.1 μs | 1,016.90 μs | 901.46 μs | 177,328.1 μs | +| Solve_3_Eqs_Rand_10 | 16,968.0 μs | 60.90 μs | 53.99 μs | 16,959.7 μs | +| Solve_3_Eqs_Rand_20 | 177,484.6 μs | 828.61 μs | 775.08 μs | 177,584.3 μs | diff --git a/src/Informedica.GenSolver.Lib/Equation.fs b/src/Informedica.GenSolver.Lib/Equation.fs index 7cadc72..b6706f1 100644 --- a/src/Informedica.GenSolver.Lib/Equation.fs +++ b/src/Informedica.GenSolver.Lib/Equation.fs @@ -22,6 +22,9 @@ module Equation = module Property = Variable.ValueRange.Property + /// + /// Get the string representation of a SolveResult + /// let toString = function | Unchanged -> "Unchanged" | Changed cs -> @@ -38,11 +41,13 @@ module Equation = |> String.concat ", " + /// /// Create an `Equation` with an **y** and /// **xs**. Fails if a variable is added more /// than one time using the **fail** function. /// The type of Equation product or sum /// is determined by the constructor **c**. + /// let create c succ fail (y, xs) = y::xs |> List.filter (fun v -> @@ -55,44 +60,73 @@ module Equation = |> Exceptions.EquationDuplicateVariables |> fail + + /// /// Create an `ProductEquation` with an **y** and /// **xs**. Fails if a variable is added more /// than one time using the **fail** function. + /// let createProductEq = create ProductEquation + + /// /// Create an `SumEquation` with an **y** and /// **xs**. Fails if a variable is added more /// than one time using the **fail** function. + /// let createSumEq = create SumEquation + + /// /// Create an `ProductEquation` with an **y** and /// **xs**. Fails if a variable is added more /// than one time raising an exception. + /// let createProductEqExc = createProductEq id (Exceptions.raiseExc None []) + + /// /// Create an `SumEquation` with an **y** and /// **xs**. Fails if a variable is added more /// than one time raising an exception. + /// let createSumEqExc = createSumEq id (Exceptions.raiseExc None []) + + /// /// Apply **fp** to a `ProductEquation` and /// **fs** to a `SumEquation`. + /// let apply fp fs = function | ProductEquation (y,xs) -> fp y xs | SumEquation (y, xs) -> fs y xs + + /// /// Check whether an `Equation` is a product equation + /// let isProduct = apply (fun _ _ -> true) (fun _ _ -> false) + + /// /// Check whether an `Equation` is a sum equation + /// let isSum = apply (fun _ _ -> true) (fun _ _ -> false) + + /// /// Turn an `Equation` into a list of `Variable` + /// let toVars = let f y xs = y::xs apply f f + /// + /// Get the count of `Variable`s in an `Equation` + /// + /// Whether only min max is used + /// The equation let count onlyMinMax eq = let vars = eq |> toVars let b = @@ -119,6 +153,9 @@ module Equation = ) 0 + /// + /// Get product of the `Variable`s in an `Equation` + /// let countProduct eq = //match eq with //| SumEquation _ -> -1 @@ -131,6 +168,9 @@ module Equation = ) 1 + /// + /// Get the string representation of an `Equation` + /// let toString exact eq = let op = if eq |> isProduct then " * " else " + " let varToString = Variable.toString exact @@ -142,9 +182,11 @@ module Equation = $"""{y |> varToString} = {xs |> List.map varToString |> String.concat op}""" + /// /// Make sure that the `Variables` in the /// `Equation` can only contain positive /// non zero values. + /// let nonZeroOrNegative eq = let set c y xs = let y = y |> Variable.setNonZeroOrNegative @@ -154,12 +196,18 @@ module Equation = let fs = set SumEquation eq |> apply fp fs + + /// /// Check whether an `Equation` contains /// a `Variable` **v** + /// let contains v = toVars >> (List.exists (Variable.eqName v)) + + /// /// Check whether `Equation`s /// **eq1** and **eq2** are equal + /// let equals eq1 eq2 = let vrs1 = eq1 |> toVars let vrs2 = eq2 |> toVars @@ -168,24 +216,33 @@ module Equation = ((eq1 |> isProduct) && (eq2 |> isProduct) || (eq1 |> isSum) && (eq2 |> isSum)) + + /// /// Find a `Variable` **vr** in /// an `Equation` **eq** and return /// the result in a list + /// let find var eq = eq |> toVars |> List.filter (fun v -> v |> Variable.getName = (var |> Variable.getName)) + + /// /// Find a `Variable` with `Name` /// **n** in an `Equation` **eq** /// and return the result as a list + /// let findName n eq = eq |> toVars |> List.filter (fun vr -> vr |> Variable.getName = n) + + /// /// Replace a `Variable` **v** in the /// `Equation` **e**. + /// let replace var eq = let r c v vs = let vs = vs |> List.replace (Variable.eqName v) v @@ -195,17 +252,22 @@ module Equation = eq |> apply fp fs - // Check whether an equation is solved + + /// + /// Check whether an equation is solved + /// let isSolved = function | ProductEquation (y, xs) | SumEquation (y, xs) -> y::xs |> List.forall Variable.isSolved - // Check whether an equation will change by calc - // This is not the same as `isSolved`!! If all - // the variables are unrestricted than the equation - // is not solvable but is also not solved. + /// + /// Check whether an equation will change by calc + /// This is not the same as `isSolved`!! If all + /// the variables are unrestricted than the equation + /// is not solvable but is also not solved. + /// let isSolvable = function | ProductEquation (y, xs) | SumEquation (y, xs) -> @@ -216,6 +278,10 @@ module Equation = |> not + /// + /// Check whether an equation is valid + /// + /// The equation let check eq = let isSub op (y : Variable) (xs : Variable list) = match xs with @@ -241,6 +307,9 @@ module Equation = else true + /// + /// Get the string representation of a calculation + /// let calculationToString b op1 op2 y xs = let varToStr = Variable.toString b let opToStr op = $" {op |> Variable.Operators.toString} " @@ -251,8 +320,10 @@ module Equation = $"""{y |> varToStr} = {x1 |> varToStr}{op2 |> opToStr}{xs |> List.map varToStr |> String.concat (op1 |> opToStr)} (cost: {cost})""" + /// /// Solve an equation **e**, return a list of /// changed `Variable`s. + /// let solve onlyMinIncrMax log eq = // helper functions let without x xs = xs |> List.filter (Variable.eqName x >> not)