diff --git a/src/Informedica.GenSolver.Lib/Equation.fs b/src/Informedica.GenSolver.Lib/Equation.fs
index a08eed0..0c8cc52 100644
--- a/src/Informedica.GenSolver.Lib/Equation.fs
+++ b/src/Informedica.GenSolver.Lib/Equation.fs
@@ -241,12 +241,13 @@ module Equation =
else true
- let calculationToString b op1 op2 x y xs =
+ let calculationToString b op1 op2 y xs =
let varToStr = Variable.toString b
let opToStr op = $" {op |> Variable.Operators.toString} "
- let filter x xs = xs |> List.filter (Variable.eqName x >> not)
+ let cost = xs |> List.map Variable.count |> List.reduce (*)
+ let x1 = xs |> List.head
- $"""{x |> varToStr} = {y |> varToStr}{op2 |> opToStr}{xs |> filter x |> List.map varToStr |> String.concat (op1 |> opToStr)} """
+ $"""{y |> varToStr} = {x1 |> varToStr}{op2 |> opToStr}{xs |> List.map varToStr |> String.concat (op1 |> opToStr)} (cost: {cost})"""
/// Solve an equation **e**, return a list of
@@ -275,12 +276,13 @@ module Equation =
| _ ->
if x |> Variable.isSolved then x
else
+ let xs = xs |> without x
// log the calculation
- (op1, op2, x, y, xs)
+ (op1, op2, x, y::xs)
|> Events.EquationStartCalculation
|> Logging.logInfo log
// recalculate x
- x <== (y |> op2 <| (xs |> without x |> List.reduce op1))
+ x <== (y |> op2 <| (xs |> List.reduce op1))
(xChanged || (x.Values |> ValueRange.eqs newX.Values |> not))
|> calcXs op1 op2 y (xs |> replAdd newX) tail
@@ -290,7 +292,7 @@ module Equation =
y, false
else
// log the calculation
- (op1, op1, y, (xs |> List.head), (xs |> List.tail))
+ (op1, op1, y, xs)
|> Events.EquationStartCalculation
|> Logging.logInfo log
// recalculate y
diff --git a/src/Informedica.GenSolver.Lib/Scripts/Tests.fsx b/src/Informedica.GenSolver.Lib/Scripts/Tests.fsx
index 4781eb3..ff56498 100644
--- a/src/Informedica.GenSolver.Lib/Scripts/Tests.fsx
+++ b/src/Informedica.GenSolver.Lib/Scripts/Tests.fsx
@@ -714,7 +714,7 @@ module Tests =
| Some min', Some max' ->
let min = min' |> BigRational.fromInt |> ValueUnit.singleWithUnit Units.Count.times |> Minimum.create minIncl
let max = max' |> BigRational.fromInt |> ValueUnit.singleWithUnit Units.Count.times |> Maximum.create maxIncl
- min |> ValueRange.minSTEmax max
+ min |> minSTEmax max
let min1Options = [None, false; Some -2, true; Some -2, false; Some 0, true; Some 0, false; Some 2, true; Some 2, false]
let max1Options = [None, false; Some -1, true; Some -1, false; Some 0, true; Some 0, false; Some 3, true; Some 3, false]
@@ -745,10 +745,10 @@ module Tests =
|> List.distinct
- let mult = Variable.ValueRange.MinMaxCalculator.multiplication
- let div = Variable.ValueRange.MinMaxCalculator.division
- let add = Variable.ValueRange.MinMaxCalculator.addition
- let sub = Variable.ValueRange.MinMaxCalculator.subtraction
+ let mult = MinMaxCalculator.multiplication
+ let div = MinMaxCalculator.division
+ let add = MinMaxCalculator.addition
+ let sub = MinMaxCalculator.subtraction
let createVuOpt (intOpt, b) =
@@ -772,7 +772,7 @@ module Tests =
(min2 |> createVuOpt)
(max2 |> createVuOpt)
|> fun (min, max) -> Variable.ValueRange.create true min None max None
- |> Variable.ValueRange.toString true
+ |> toString true
|> String.replace "x" ""
|> String.replace "<" "< "
|> String.replace ">" " >"
@@ -1358,7 +1358,7 @@ module Tests =
|> Expect.isTrue "should all be Zero"
}
- test "when add/, sub is applied to x1 = Zero and x2 = Unrestricted" {
+ test "when add, sub is applied to x1 = Zero and x2 = Unrestricted" {
let x1 = 0N |> ValueUnit.singleWithUnit Units.Count.times |> ValueRange.createValSet
let x2 = ValueRange.Unrestricted
[
@@ -1732,7 +1732,6 @@ Tests.tests
module MinMaxTestScenarios =
- open Informedica.Utils.Lib
open Informedica.Utils.Lib.BCL
open Informedica.GenUnits.Lib
open Informedica.GenSolver.Lib
diff --git a/src/Informedica.GenSolver.Lib/SolverLogging.fs b/src/Informedica.GenSolver.Lib/SolverLogging.fs
index 2b706ed..33296c6 100644
--- a/src/Informedica.GenSolver.Lib/SolverLogging.fs
+++ b/src/Informedica.GenSolver.Lib/SolverLogging.fs
@@ -124,8 +124,8 @@ module SolverLogging =
| EquationStartedSolving eq ->
$"=== Start solving Equation ===\n{eq |> toString}"
- | EquationStartCalculation (op1, op2, y, x, xs) ->
- $"start calculating: {Equation.calculationToString true op1 op2 y x xs}"
+ | EquationStartCalculation (op1, op2, y, xs) ->
+ $"start calculating: {Equation.calculationToString true op1 op2 y xs}"
| EquationFinishedCalculation (xs, changed) ->
if not changed then "No Changes"
diff --git a/src/Informedica.GenSolver.Lib/Types.fs b/src/Informedica.GenSolver.Lib/Types.fs
index 425a4c0..36aa15a 100644
--- a/src/Informedica.GenSolver.Lib/Types.fs
+++ b/src/Informedica.GenSolver.Lib/Types.fs
@@ -169,7 +169,6 @@ module rec Types =
| EquationStartCalculation of
op1: (Variable -> Variable -> Variable) *
op2: (Variable -> Variable -> Variable) *
- x: Variable *
y: Variable *
xs: Variable List
| EquationFinishedCalculation of Variable list * changed : bool
diff --git a/src/Informedica.GenSolver.Lib/Variable.fs b/src/Informedica.GenSolver.Lib/Variable.fs
index 74017d8..01f4d1d 100644
--- a/src/Informedica.GenSolver.Lib/Variable.fs
+++ b/src/Informedica.GenSolver.Lib/Variable.fs
@@ -2747,6 +2747,19 @@ module Variable =
/// The infix operator
/// The first `ValueRange`
/// The second `ValueRange`
+ /// The resulting `ValueRange`
+ ///
+ ///
+ /// let vs1 = [| 1N; 2N; 3N |] |> ValueUnit.withUnit Units.Count.times |> ValueSet.create
+ /// let vs2 = [| 4N; 5N; 6N |] |> ValueUnit.withUnit Units.Count.times |> ValueSet.create
+ /// let vr1 = create true None None None (Some vs1)
+ /// let vr2 = create true None None None (Some vs2)
+ /// calc true (*) (vr1, vr2)
+ /// // returns a ValueRange with a Minimum = 4 and a Maximum = 18
+ /// calc false (*) (vr1, vr2)
+ /// // returns a ValueRange [|4N; 5N; 6N; 8N; 10N; 12N; 15N; 18N|]
+ ///
+ ///
let calc onlyMinIncrMax op (vr1, vr2) =
let calcMinMax min1 max1 min2 max2 =
@@ -2837,14 +2850,50 @@ module Variable =
| _ -> create onlyMinIncrMax min incr max None
+ ///
/// Checks whether a `ValueRange` vr1 is a subset of
/// `ValueRange` vr2.
+ ///
+ /// The first `ValueRange`
+ /// The second `ValueRange`
+ ///
+ /// Only checks whether the `ValueSet` of vr1 is a subset of
+ /// the `ValueSet` of vr2.
+ ///
+ ///
+ ///
+ /// let vs1 = [| 1N; 2N; 3N |] |> ValueUnit.withUnit Units.Count.times |> ValueSet.create
+ /// let vs2 = [| 2N; 3N |] |> ValueUnit.withUnit Units.Count.times |> ValueSet.create
+ /// let vr1 = create true None None None (Some vs1)
+ /// let vr2 = create true None None None (Some vs2)
+ /// vr1 |> isSubSetOf vr2 // returns false
+ /// vr2 |> isSubSetOf vr1 // returns true
+ ///
+ ///
let isSubSetOf vr2 vr1 =
match vr1, vr2 with
| ValSet s1, ValSet s2 -> s2 |> ValueSet.isSubsetOf s1
| _ -> false
+ ///
+ /// Create a set of `Properties` from a `ValueRange`.
+ ///
+ ///
+ ///
+ ///
+ /// let min = 2N |> ValueUnit.singleWithUnit Units.Count.times |> Minimum.create true
+ /// let incr = 2N |> ValueUnit.singleWithUnit Units.Count.times |> Increment.create
+ /// let max = 8N |> ValueUnit.singleWithUnit Units.Count.times |> Maximum.create false
+ /// let vr = create true (Some min) (Some incr) (Some max) None
+ /// vr |> toProperties
+ /// // returns
+ /// // set
+ /// // [MinProp (MinIncl (ValueUnit ([|2N|], Count (Times 1N))));
+ /// // MaxProp (MaxIncl (ValueUnit ([|6N|], Count (Times 1N))));
+ /// // IncrProp (Increment (ValueUnit ([|2N|], Count (Times 1N))))]
+ ///
+ ///
let toProperties vr =
let unr = set []
@@ -2877,14 +2926,51 @@ module Variable =
|> apply unr nonZero fMin fMax fMinMax fIncr fMinIncr fIncrMax fMinIncrMax fVs
+ ///
+ /// Get the difference between two `ValueRange`s.
+ ///
+ /// The first ValueRange
+ /// The second ValueRange
+ /// The difference between the two ValueRanges
+ ///
+ ///
+ /// let min = 2N |> ValueUnit.singleWithUnit Units.Count.times |> Minimum.create true
+ /// let incr = 2N |> ValueUnit.singleWithUnit Units.Count.times |> Increment.create
+ /// let max = 8N |> ValueUnit.singleWithUnit Units.Count.times |> Maximum.create false
+ /// let vr1 = create true (Some min) (Some incr) None None
+ /// let vr2 = create true None None (Some max) None
+ /// vr1 |> diffWith vr2
+ ///
+ ///
let diffWith vr1 vr2 =
vr1
|> toProperties
|> Set.difference (vr2 |> toProperties)
+ ///
/// Set a `ValueRange` expr to a `ValueRange` y.
/// So, the result is equal to or more restrictive than the original `y`.
+ ///
+ /// Whether only min incr max are calculated
+ /// The `ValueRange` to apply to
+ /// The `ValueRange` to apply
+ /// The resulting (restricted) `ValueRange`
+ ///
+ ///
+ /// let min = 2N |> ValueUnit.singleWithUnit Units.Count.times |> Minimum.create true
+ /// let incr = 2N |> ValueUnit.singleWithUnit Units.Count.times |> Increment.create
+ /// let max = 8N |> ValueUnit.singleWithUnit Units.Count.times |> Maximum.create false
+ /// let vr1 = create true (Some min) (Some incr) None None
+ /// let vr2 = create true None None (Some max) None
+ /// vr1 |> applyExpr true vr2
+ /// // returns
+ /// // MinIncrMax
+ /// // (MinIncl (ValueUnit ([|2N|], Count (Times 1N))),
+ /// // Increment (ValueUnit ([|2N|], Count (Times 1N))),
+ /// // MaxIncl (ValueUnit ([|6N|], Count (Times 1N))))
+ ///
+ ///
let applyExpr onlyMinIncrMax y expr =
let appl _ get set vr =
//printfn $"{s}"
@@ -2943,6 +3029,7 @@ module Variable =
let createSucc = create id
+ /// A Variable with a Unrestricted `ValueRange`
let empty n = Unrestricted |> createSucc n
@@ -2962,6 +3049,7 @@ module Variable =
let get = apply id
+ /// Get the string representation of a `Variable`.
let toString exact ({ Name = n; Values = vs }: Variable) =
vs
|> ValueRange.toString exact
@@ -2976,6 +3064,8 @@ module Variable =
let getValueRange v = (v |> get).Values
+ /// Check whether a `Variable` **v** contains
+ /// a value **v**.
let contains v vr =
vr |> getValueRange |> ValueRange.contains v
@@ -3024,6 +3114,8 @@ module Variable =
let eqName v1 v2 = v1 |> getName = (v2 |> getName)
+ /// Check whether the `ValueRange` of **v1**
+ /// and **v2** are equal.
let eqValues var1 var2 =
var1 |> getValueRange = (var2 |> getValueRange)
@@ -3047,6 +3139,8 @@ module Variable =
getValueRange >> ValueRange.isUnrestricted
+ /// Checks whether the ValueRange of a Variable
+ /// is a MinIncrMax
let isMinIncrMax = getValueRange >> ValueRange.isMinIncrMax
@@ -3081,6 +3175,12 @@ module Variable =
Values = var.Values |> ValueRange.increaseIncrement lim incr
}
+ ///
+ /// Calculate a ValueSet for a Variable if the Value of the
+ /// Variable is a MinIncrMax
+ ///
+ ///
+ /// A Variable with a ValueSet if this can be calculated
let minIncrMaxToValues var =
if var |> isMinIncrMax |> not then var
else
@@ -3099,12 +3199,19 @@ module Variable =
raise e
+ ///
+ /// 'Prunes' the ValueRange of a Variable
+ ///
+ ///
let prune var =
{ var with
Values = var.Values |> ValueRange.prune
}
+ ///
+ /// Set the unit of a Variable
+ ///
let setUnit unit var =
{ var with
Values = var.Values |> ValueRange.setUnit unit
diff --git a/tests/Informedica.GenSolver.Tests/Tests.fs b/tests/Informedica.GenSolver.Tests/Tests.fs
index e6666b1..f85a693 100644
--- a/tests/Informedica.GenSolver.Tests/Tests.fs
+++ b/tests/Informedica.GenSolver.Tests/Tests.fs
@@ -97,8 +97,8 @@ module TestSolver =
open Informedica.GenUnits.Lib
open Informedica.GenSolver.Lib
- module Api = Informedica.GenSolver.Lib.Api
- module Solver = Informedica.GenSolver.Lib.Solver
+ module Api = Api
+ module Solver = Solver
module Name = Variable.Name
module ValueRange = Variable.ValueRange
module Minimum = ValueRange.Minimum
@@ -118,12 +118,12 @@ module TestSolver =
let printEqs = function
| Ok eqs -> eqs |> Solver.printEqs true procss
- | Error errs -> failwith "errors"
+ | Error _ -> failwith "errors"
let printEqsWithUnits = function
| Ok eqs -> eqs |> Solver.printEqs false procss
- | Error errs -> failwith "errors"
+ | Error _ -> failwith "errors"
let setProp n p eqs =
@@ -160,7 +160,7 @@ module TestSolver =
let setValues u n vals = vals |> createValSet u |> ValsProp |> setProp n
let logger =
- fun (s : string) ->
+ fun (_ : string) ->
() //File.AppendAllLines("examples.log", [s])
|> SolverLogging.logger
@@ -701,7 +701,7 @@ module Tests =
| Some min', Some max' ->
let min = min' |> BigRational.fromInt |> ValueUnit.singleWithUnit Units.Count.times |> Minimum.create minIncl
let max = max' |> BigRational.fromInt |> ValueUnit.singleWithUnit Units.Count.times |> Maximum.create maxIncl
- min |> ValueRange.minSTEmax max
+ min |> minSTEmax max
let min1Options = [None, false; Some -2, true; Some -2, false; Some 0, true; Some 0, false; Some 2, true; Some 2, false]
let max1Options = [None, false; Some -1, true; Some -1, false; Some 0, true; Some 0, false; Some 3, true; Some 3, false]
@@ -732,10 +732,10 @@ module Tests =
|> List.distinct
- let mult = Variable.ValueRange.MinMaxCalculator.multiplication
- let div = Variable.ValueRange.MinMaxCalculator.division
- let add = Variable.ValueRange.MinMaxCalculator.addition
- let sub = Variable.ValueRange.MinMaxCalculator.subtraction
+ let mult = MinMaxCalculator.multiplication
+ let div = MinMaxCalculator.division
+ let add = MinMaxCalculator.addition
+ let sub = MinMaxCalculator.subtraction
let createVuOpt (intOpt, b) =
@@ -759,7 +759,7 @@ module Tests =
(min2 |> createVuOpt)
(max2 |> createVuOpt)
|> fun (min, max) -> Variable.ValueRange.create true min None max None
- |> Variable.ValueRange.toString true
+ |> toString true
|> String.replace "x" ""
|> String.replace "<" "< "
|> String.replace ">" " >"