Skip to content

Commit

Permalink
fix: moved prune to order and only one at a time
Browse files Browse the repository at this point in the history
  • Loading branch information
Casper Bollen authored and Casper Bollen committed Oct 28, 2023
1 parent 6139862 commit c9ef84b
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ Apple M2 Max, 1 CPU, 12 logical and 12 physical cores
```
| Method | Mean | Error | StdDev |
|-------------------- |------------:|----------:|------------:|
| AllPairesInt_100 | 127.0 μs | 0.26 μs | 0.25 μs |
| AllPairsInt_200 | 751.4 μs | 3.80 μs | 3.55 μs |
| SolveCountMinIncl | 101.7 μs | 0.78 μs | 0.69 μs |
| Solve_1_Eqs_100 | 12,681.1 μs | 143.63 μs | 134.35 μs |
| Solve_1_Eqs_200 | 50,893.2 μs | 892.15 μs | 991.62 μs |
| Solve_3_Eqs_100 | 13,256.2 μs | 122.22 μs | 114.32 μs |
| Solve_3_Eqs_200 | 52,605.5 μs | 989.61 μs | 1,058.87 μs |
| Solve_1_Eqs_Rand_10 | 9,373.4 μs | 22.58 μs | 20.02 μs |
| Solve_1_Eqs_Rand_20 | 90,342.7 μs | 292.40 μs | 273.51 μs |
| Solve_3_Eqs_Rand_10 | 9,707.7 μs | 22.19 μs | 19.67 μs |
| Solve_3_Eqs_Rand_20 | 94,725.7 μs | 210.39 μs | 196.80 μs |
| Method | Mean | Error | StdDev |
|-------------------- |------------:|------------:|------------:|
| AllPairesInt_100 | 124.4 μs | 0.50 μs | 0.46 μs |
| AllPairsInt_200 | 740.2 μs | 4.20 μs | 3.93 μs |
| SolveCountMinIncl | 100.3 μs | 0.56 μs | 0.49 μs |
| Solve_1_Eqs_100 | 12,808.2 μs | 123.12 μs | 115.17 μs |
| Solve_1_Eqs_200 | 51,027.0 μs | 1,018.90 μs | 2,034.85 μs |
| Solve_3_Eqs_100 | 13,494.7 μs | 140.81 μs | 131.72 μs |
| Solve_3_Eqs_200 | 52,360.1 μs | 997.85 μs | 1,109.10 μs |
| Solve_1_Eqs_Rand_10 | 9,078.6 μs | 23.49 μs | 20.82 μs |
| Solve_1_Eqs_Rand_20 | 89,190.0 μs | 441.00 μs | 412.51 μs |
| Solve_3_Eqs_Rand_10 | 9,599.2 μs | 28.00 μs | 26.19 μs |
| Solve_3_Eqs_Rand_20 | 90,438.7 μs | 358.47 μs | 335.31 μs |
24 changes: 19 additions & 5 deletions src/Informedica.GenOrder.Lib/Order.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,7 @@ module Order =
module Property = ValueRange.Property
module Quantity = OrderVariable.Quantity
module Frequency = OrderVariable.Frequency
module PerTime = OrderVariable.PerTime
module PerTimeAdjust = OrderVariable.PerTimeAdjust
module Concentration = OrderVariable.Concentration
module Rate = OrderVariable.Rate
Expand Down Expand Up @@ -1438,17 +1439,30 @@ module Order =


let minIncrMaxToValues (ord: Order) =
let mutable flag = false
let ovars =
ord
|> toOrdVars
|> List.map OrderVariable.minIncrMaxToValues
|> List.map (fun ovar ->
if flag || ovar.Constraints.Incr |> Option.isNone then ovar
else
flag <- true
let n =
match ord.Prescription with
| Continuous -> 100
| Discontinuous _ -> 50
| Timed _ -> 5

ovar
|> OrderVariable.minIncrMaxToValues n
)

ord
|> fromOrdVars ovars
|> fun ord ->
let s = ord |> toString |> String.concat "\n"
printfn $"min incr max to values:\n{s}"
ord
// |> fun ord ->
// let s = ord |> toString |> String.concat "\n"
// printfn $"min incr max to values:\n{s}"
// ord


module Print =
Expand Down
4 changes: 2 additions & 2 deletions src/Informedica.GenOrder.Lib/OrderVariable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,13 @@ module OrderVariable =
|> String.replace "*" "/"


let minIncrMaxToValues (ovar: OrderVariable) =
let minIncrMaxToValues n (ovar: OrderVariable) =
{ ovar with
Variable =
if ovar.Variable |> Variable.isMinIncrMax |> not then ovar.Variable
else
ovar.Variable
|> Variable.minIncrMaxToValues
|> Variable.minIncrMaxToValues n
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<None Include="Scripts\Tests.fsx" />
<None Include="Scripts\Increment.fsx" />
<None Include="Scripts\Equation.fsx" />
<None Include="Scripts\Solver.fsx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Informedica.Utils.Lib\Informedica.Utils.Lib.fsproj" />
Expand Down
15 changes: 9 additions & 6 deletions src/Informedica.GenSolver.Lib/Scripts/Equation.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ open Informedica.GenUnits.Lib

let eqs =
[
"a = b + c + e"
"a = b + c"
"d = e * a"
"d = f * b"
]
Expand Down Expand Up @@ -380,10 +380,13 @@ eqs


eqs
|> TestSolver.setValues Units.Count.times "a" [| 1N; 2N; 3N |]
|> TestSolver.setValues Units.Count.times "b" [| 1N; 2N; 3N |]
|> TestSolver.setValues Units.Count.times "c" [| 1N..1N..3N |]
|> TestSolver.setValues Units.Count.times "e" [| 1N..1N..30N |]
//|> TestSolver.setValues Units.Count.times "a" [| 1N..2N..100N |]
|> TestSolver.setValues Units.Count.times "b" [| 1N..1N..100N |]
|> TestSolver.setValues Units.Count.times "c" [| 2N..1N..300N |]
|> fun eqs -> eqs[2]
|> Equation.solve2 false TestSolver.logger
|> Equation.solve true TestSolver.logger
|> fst
|> Equation.solve false TestSolver.logger
|> (fst >> (Equation.toString true) >> printfn "%s")


139 changes: 139 additions & 0 deletions src/Informedica.GenSolver.Lib/Scripts/Solver.fsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@

#load "load.fsx"

#time


module TestSolver =

open Informedica.GenUnits.Lib
open Informedica.GenSolver.Lib

module Api = Api
module Solver = Solver
module Name = Variable.Name
module ValueRange = Variable.ValueRange
module Minimum = ValueRange.Minimum
module Maximum = ValueRange.Maximum
module Increment = ValueRange.Increment
module ValueSet = ValueRange.ValueSet


let (|>>) r f =
match r with
| Ok x -> x |> f
| Error _ -> r


let procss s = printfn $"%s{s} "


let printEqs = function
| Ok eqs -> eqs |> Solver.printEqs true procss
| Error _ -> failwith "errors"


let printEqsWithUnits = function
| Ok eqs -> eqs |> Solver.printEqs false procss
| Error _ -> failwith "errors"


let setProp n p eqs =
let n = n |> Name.createExc
match eqs |> Api.setVariableValues true n p with
| Some var ->
eqs
|> List.map (fun e ->
e |> Equation.replace var
)
| None -> eqs

let create c u v =
[|v|]
|> ValueUnit.create u
|> c

let createMinIncl = create (Minimum.create true)
let createMinExcl = create (Minimum.create false)
let createMaxIncl = create (Maximum.create true)
let createMaxExcl = create (Maximum.create false)
let createIncr = create Increment.create
let createValSet u v =
v
|> Array.ofSeq
|> ValueUnit.create u
|> ValueSet.create

let setIncr u n vals = vals |> createIncr u |> IncrProp |> setProp n
let setMinIncl u n min = min |> createMinIncl u |> MinProp|> setProp n
let setMinExcl u n min = min |> createMinExcl u |> MinProp |> setProp n
let setMaxIncl u n max = max |> createMaxIncl u |> MaxProp |> setProp n
let setMaxExcl u n max = max |> createMaxExcl u |> MaxProp |> setProp n
let setValues u n vals = vals |> createValSet u |> ValsProp |> setProp n

let logger =
fun (s : string) ->
printfn $"{s}"
|> SolverLogging.logger

let solve n p eqs =
let n = n |> Name.createExc
Api.solve true id logger n p eqs

let solveAll = Api.solveAll false logger

let solveMinMax = Api.solveAll true logger

let solveMinIncl u n min = solve n (min |> createMinIncl u |> MinProp)
let solveMinExcl u n min = solve n (min |> createMinExcl u |> MinProp)
let solveMaxIncl u n max = solve n (max |> createMaxIncl u |> MaxProp)
let solveMaxExcl u n max = solve n (max |> createMaxExcl u |> MaxProp)
let solveIncr u n incr = solve n (incr |> createIncr u |> IncrProp)
let solveValues u n vals = solve n (vals |> createValSet u |> ValsProp)

let init = Api.init
let nonZeroNegative = Api.nonZeroNegative


let solveCountMinIncl = solveMinIncl Units.Count.times
let solveCountMaxExcl = solveMaxExcl Units.Count.times
let solveCountValues u n vals = solveValues Units.Count.times u n vals



open MathNet.Numerics

open Informedica.GenSolver.Lib
open Informedica.GenUnits.Lib

let eqs =
[
"a = b + c"
"d = e * a"
"d = f * b"
]
|> Api.init


eqs
//|> TestSolver.setValues Units.Count.times "a" [| 1N..2N..100N |]
|> TestSolver.setMinIncl Units.Count.times "b" 1N
|> TestSolver.setMaxIncl Units.Count.times "b" 1000N
|> TestSolver.setMinIncl Units.Count.times "c" 1N
|> TestSolver.setMaxIncl Units.Count.times "c" 1000N
|> Solver.solveAll true TestSolver.logger
|> function
| Ok eqs ->
eqs |> Solver.printEqs true (fun s -> printfn $"{s}") |> ignore

eqs
|> TestSolver.setValues Units.Count.times "a" [| 1N..2N..10_000N |]
|> TestSolver.setValues Units.Count.times "b" [| 1N..2N..10_000N |]
|> Solver.solveAll false TestSolver.logger
|> function
| Ok eqs ->
eqs |> Solver.printEqs true (fun s -> printfn $"{s}") |> ignore
| Error _ -> failwith "errors"
|> ignore
| Error _ -> failwith "errors"
|> ignore
29 changes: 26 additions & 3 deletions src/Informedica.GenSolver.Lib/Solver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ module Solver =

open Types

/// <summary>
/// Sort a list of equations by the name of the
/// first variable in the equation.
/// </summary>
/// <param name="eqs">The list of Equations</param>
let sortByName eqs =
eqs
|> List.sortBy (fun e ->
Expand All @@ -20,9 +25,14 @@ module Solver =
|> Variable.getName)


/// <summary>
/// Format a set of equations to print.
/// Using **f** to allow additional processing
/// of the string.
/// </summary>
/// <param name="exact">Whether to print the exact value</param>
/// <param name="pf">The print function</param>
/// <param name="eqs">The equations to print</param>
let printEqs exact pf eqs =

"equations result:\n" |> pf
Expand All @@ -35,18 +45,26 @@ module Solver =
eqs


/// <summary>
/// Checks whether a list of `Equation` **eqs**
/// contains an `Equation` **eq**
/// </summary>
/// <param name="eq">The `Equation` to check for</param>
/// <param name="eqs">The list of `Equation` to check in</param>
let contains eq eqs = eqs |> List.exists ((=) eq)


/// <summary>

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

This XML comment is invalid: unknown parameter 'vs'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

This XML comment is invalid: unknown parameter 'es'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

This XML comment is incomplete: no documentation for parameter 'vars'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

This XML comment is incomplete: no documentation for parameter 'eqs'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

This XML comment is invalid: unknown parameter 'vs'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

This XML comment is invalid: unknown parameter 'es'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

This XML comment is incomplete: no documentation for parameter 'vars'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

This XML comment is incomplete: no documentation for parameter 'eqs'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (macOS-latest)

This XML comment is invalid: unknown parameter 'vs'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (macOS-latest)

This XML comment is invalid: unknown parameter 'es'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (macOS-latest)

This XML comment is incomplete: no documentation for parameter 'vars'

Check warning on line 57 in src/Informedica.GenSolver.Lib/Solver.fs

View workflow job for this annotation

GitHub Actions / build (macOS-latest)

This XML comment is incomplete: no documentation for parameter 'eqs'
/// Replace a list of `Variable` **vs**
/// in a list of `Equation` **es**, return
/// a list of replaced `Equation` and a list
/// of unchanged `Equation`
let replace vars es =
/// </summary>
/// <param name="vs">The list of `Variable` to replace</param>
/// <param name="es">The list of `Equation` to replace in</param>
let replace vars eqs =
let rpl, rst =
es
eqs
|> List.partition (fun e ->
vars
|> List.exists (fun v -> e |> Equation.contains v)
Expand All @@ -70,6 +88,7 @@ module Solver =
cache.Value <- cache.Value.Add(e, r)
r


let sortQue onlyMinMax que =
if que |> List.length = 0 then que
else
Expand Down Expand Up @@ -228,8 +247,12 @@ module Solver =
//TODO: need to clean up the number check
let solveAll onlyMinIncrMax log eqs =
let n1 = eqs |> List.length
// TODO: need to test this using BenchmarkDotNet
let solve =
solve onlyMinIncrMax log (sortQue onlyMinIncrMax) None
|> memSolve

match solve onlyMinIncrMax log (sortQue onlyMinIncrMax) None eqs with
match solve eqs with
| Error (eqs, errs) -> Error (eqs, errs)
| Ok eqs ->
let n2 = eqs |> List.length
Expand Down
4 changes: 2 additions & 2 deletions src/Informedica.GenSolver.Lib/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ module Utils =
/// a Variable calculation.
let MAX_CALC_COUNT = 300

/// Reduce a set of values to a maximum of 20 for a Variable
let PRUNE = 40
/// Reduce a set of values to a maximum of 100 for a Variable
let PRUNE = 4

/// Maximum quantity of a numerator or denominator to prevent
/// infinite loops calculating a minimum or maximum.
Expand Down
Loading

0 comments on commit c9ef84b

Please sign in to comment.