diff --git a/src/Informedica.GenSolver.Lib/Scripts/MinMax.fsx b/src/Informedica.GenSolver.Lib/Scripts/MinMax.fsx
index 984cc49..83bc784 100644
--- a/src/Informedica.GenSolver.Lib/Scripts/MinMax.fsx
+++ b/src/Informedica.GenSolver.Lib/Scripts/MinMax.fsx
@@ -23,6 +23,25 @@ open Informedica.Utils.Lib.BCL
open Informedica.GenSolver.Lib
+[1..10]
+|> List.filter (fun x -> x % 2 = 0)
+
+module List =
+
+ let filter _ (xs: 'a list) =
+ printfn "hello world"
+
+
+[1..10]
+|> List.filter (fun x -> x % 2 = 0)
+
+
+module OriginalList =
+
+ let filter = Microsoft.FSharp.Collections.List.filter
+
+OriginalList.filter
+
[|3N/20N; 3N/10N; 1N/2N; 1N; 2N; 5N; 10N|]
|> Array.allPairs [|1N/10N; 1N/5N; 1N/2N; 1N; 2N; 10N/3N; 20N/3N|]
|> Array.map (fun (x1, x2) -> x1 * x2)
diff --git a/src/Informedica.GenSolver.Lib/Variable.fs b/src/Informedica.GenSolver.Lib/Variable.fs
index 53dfcec..8360d18 100644
--- a/src/Informedica.GenSolver.Lib/Variable.fs
+++ b/src/Informedica.GenSolver.Lib/Variable.fs
@@ -1022,7 +1022,9 @@ module Variable =
///
/// Check if the first `ValueSet` is a subset of the second `ValueSet`.
///
- let isSubset (ValueSet vu1) (ValueSet vu2) = ValueUnit.isSubset vu1 vu2
+ let isSubsetOf vs1 vs2 =
+ let ValueSet vu1, ValueSet vu2 = vs1, vs2
+ ValueUnit.isSubset vu1 vu2
///
@@ -1048,8 +1050,11 @@ module Variable =
/// Apply a binary operator to two `ValueSet`s.
///
/// The operator to apply
- let calc op (ValueSet s1) (ValueSet s2) =
- s1 |> op <| s2 |>
+ /// The first `ValueSet`
+ /// The second `ValueSet`
+ let calc op vs1 vs2 =
+ let ValueSet vu1, ValueSet vu2 = vs1, vs2
+ vu1 |> op <| vu2 |>
create
@@ -1099,15 +1104,17 @@ module Variable =
/// Get a string representation of a `ValueSet`.
///
/// Whether values should be printed 'exact'
- let toString exact (ValueSet vs) =
+ /// The `ValueSet`
+ let toString exact vs =
+ let (ValueSet vu) = vs
let count =
ValueUnit.getValue >> Array.length
- if vs |> count <= 10 then
- $"""[{vs |> ValueUnit.toStr exact}]"""
+ if vu |> count <= 10 then
+ $"""[{vu |> ValueUnit.toStr exact}]"""
else
- let first3 = vs |> ValueUnit.takeFirst 3
- let last3 = vs |> ValueUnit.takeLast 3
+ let first3 = vu |> ValueUnit.takeFirst 3
+ let last3 = vu |> ValueUnit.takeLast 3
$"[{first3 |> ValueUnit.toStr exact} .. {last3 |> ValueUnit.toStr exact}]"
@@ -1115,15 +1122,17 @@ module Variable =
/// Get a markdown representation of a `ValueSet`.
///
/// The precision to print values with
- let toMarkdown prec (ValueSet vs) =
+ /// The `ValueSet`
+ let toMarkdown prec vs =
+ let (ValueSet vu) = vs
let count =
ValueUnit.getValue >> Array.length
- if vs |> count <= 10 then
- $"""[{vs |> ValueUnit.toDelimitedString prec}]"""
+ if vu |> count <= 10 then
+ $"""[{vu |> ValueUnit.toDelimitedString prec}]"""
else
- let first3 = vs |> ValueUnit.takeFirst 3
- let last3 = vs |> ValueUnit.takeLast 3
+ let first3 = vu |> ValueUnit.takeFirst 3
+ let last3 = vu |> ValueUnit.takeLast 3
$"[{first3 |> ValueUnit.toDelimitedString prec} .. {last3 |> ValueUnit.toDelimitedString prec}]"
@@ -1184,6 +1193,21 @@ module Variable =
| ValsProp vs -> vs |> ValueSet.toString exact
+ // === START ValueRange ===
+
+ ///
+ /// Map a function over a `ValueRange`.
+ ///
+ /// The function to apply to a `Minimum`
+ /// The function to apply to a `Maximum`
+ /// The function to apply to a `MinMax`
+ /// The function to apply to an `Increment`
+ /// The function to apply to a `MinIncr`
+ /// The function to apply to an `IncrMax`
+ /// The function to apply to a `MinIncrMax`
+ /// The function to apply to a `ValueSet`
+ /// The `ValueRange`
+ /// The mapped `ValueRange`
let map fMin fMax fMinMax fIncr fMinIncr fIncrMax fMinIncrMax fValueSet vr =
match vr with
| Unrestricted -> vr
@@ -1198,10 +1222,23 @@ module Variable =
| ValSet vs -> vs |> fValueSet |> ValSet
+ ///
+ /// Prune, limit the number of values, in a `ValueRange`.
+ ///
+ ///
+ /// Only a `ValueSet` can be pruned. The other `ValueRange`s
+ /// are left untouched.
+ ///
let prune =
map id id id id id id id ValueSet.prune
+ ///
+ /// Map a function to the ValueUnit of a `ValueRange`.
+ ///
+ /// The function to apply to the `ValueUnit`
+ /// The `ValueRange`
+ /// The mapped `ValueRange`
let mapValueUnit f vr =
vr
|> map
@@ -1215,9 +1252,28 @@ module Variable =
(ValueSet.map f)
+ ///
+ /// Convert the unit of a `ValueRange` to **u**.
+ ///
+ /// The unit to convert to
let setUnit u = mapValueUnit (ValueUnit.convertTo u)
+ ///
+ /// Apply a function to a `ValueRange`.
+ ///
+ /// Constant for `Unrestricted`
+ /// Constant for `NonZeroNoneNegative`
+ /// The function to apply to a `Minimum`
+ /// The function to apply to a `Maximum`
+ /// The function to apply to a `MinMax`
+ /// The function to apply to an `Increment`
+ /// The function to apply to a `MinIncr`
+ /// The function to apply to an `IncrMax`
+ /// The function to apply to a `MinIncrMax`
+ /// The function to apply to a `ValueSet`
+ /// The `ValueRange`
+ /// The result of applying the function to the `ValueRange`
let apply unr nonz fMin fMax fMinMax fIncr fMinIncr fIncrMax fMinIncrMax fValueSet =
function
| Unrestricted -> unr
@@ -1232,8 +1288,13 @@ module Variable =
| ValSet vs -> vs |> fValueSet
+ ///
/// Count the number of values in a `ValueRange`.
/// Returns 0 if no count is possible.
+ ///
+ ///
+ /// Only when value range is a ValueSet there can be a count.
+ ///
let cardinality =
let zero _ = 0
apply 0 0 zero zero zero zero zero zero zero ValueSet.count
@@ -1323,6 +1384,7 @@ module Variable =
returnFalse
+ /// Checks whether a `ValueRange` is `Incr`
let isIncr =
let returnFalse = Boolean.returnFalse
@@ -1339,6 +1401,7 @@ module Variable =
returnFalse
+ /// Checks whether a `ValueRange` is `MinIncr`
let isMinIncr =
let returnFalse = Boolean.returnFalse
@@ -1355,6 +1418,7 @@ module Variable =
returnFalse
+ /// Checks whether a `ValueRange` is `IncrMax`
let isIncrMax =
let returnFalse = Boolean.returnFalse
@@ -1371,6 +1435,7 @@ module Variable =
returnFalse
+ /// Checks whether a `ValueRange` is `MinIncrMax`
let isMinIncrMax =
let returnFalse = Boolean.returnFalse
@@ -1387,6 +1452,7 @@ module Variable =
returnFalse
+ /// Checks whether a `ValueRange` is `ValueSet`
let isValueSet =
let returnFalse = Boolean.returnFalse
@@ -1403,8 +1469,26 @@ module Variable =
Boolean.returnTrue
+ ///
/// Checks whether a `BigRational` is between an optional
/// **min** and an optional **max**
+ ///
+ /// The optional minimum
+ /// The optional maximum
+ /// The `BigRational` to check
+ /// True if **br** is between **min** and **max**
+ ///
+ ///
+ /// let min = Minimum.create true ( [| 3N |] |> ValueUnit.create Units.Mass.gram) |> Some
+ /// let max = Maximum.create true ( [| 5N |] |> ValueUnit.create Units.Mass.gram) |> Some
+ /// let br = 4N
+ /// br |> isBetweenMinMax min max // returns true
+ /// let br = 6N
+ /// br |> isBetweenMinMax min max // returns false
+ /// let max = None
+ /// br |> isBetweenMinMax min max // returns true
+ ///
+ ///
let isBetweenMinMax min max br =
let fMin =
function
@@ -1434,6 +1518,23 @@ module Variable =
(fMin min) && (fMax max)
+ ///
+ /// Checks whether a `BigRational` is a multiple of an optional
+ /// **incr**.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// let incr = Increment.create ( [| 2N |] |> ValueUnit.create Units.Mass.gram) |> Some
+ /// let br = 4N
+ /// br |> isMultipleOfIncr incr // returns true
+ /// let br = 5N
+ /// br |> isMultipleOfIncr incr // returns false
+ /// let incr = None
+ /// br |> isMultipleOfIncr incr // returns true
+ ///
+ ///
let isMultipleOfIncr incrOpt br =
let isDiv i = br |> BigRational.isMultiple i
@@ -1442,16 +1543,33 @@ module Variable =
| Some (Increment incr) -> incr |> ValueUnit.getBaseValue |> Seq.exists isDiv
- /// Filter a set of `BigRational` according
+ ///
+ /// Filter a set of `ValueSet` according
/// to **min** **max** and incr constraints
+ ///
+ /// The optional minimum
+ /// The optional increment
+ /// The optional maximum
+ ///
+ /// A `ValueSet` that contains the values that are between **min** and **max**
+ /// and that are a multiple of **incr**.
+ ///
+ ///
+ ///
+ /// let vs = [| 1N; 2N; 3N; 4N; 5N; 6N; 7N; 8N; 9N; 10N |] |> ValueUnit.create Units.Mass.gram |> ValueSet.create
+ /// vs |> filter (Some (Minimum.create true ( [| 3N |] |> ValueUnit.create Units.Mass.gram))) None None
+ /// // returns ValueSet (ValueUnit ([|3N; 4N; 5N; 6N; 7N; 8N; 9N; 10N|], Mass (Gram 1N)))
+ /// vs |> filter None None None // will return the same ValueSet
+ ///
+ ///
let filter minOpt incrOpt maxOpt (ValueSet vs) =
try
- vs
- |> ValueUnit.filter (fun v ->
- v |> isBetweenMinMax minOpt maxOpt
- && v |> isMultipleOfIncr incrOpt
- )
- |> ValueSet.create
+ vs
+ |> ValueUnit.filter (fun v ->
+ v |> isBetweenMinMax minOpt maxOpt
+ && v |> isMultipleOfIncr incrOpt
+ )
+ |> ValueSet.create
with
| e ->
printfn $"filter with {minOpt}, {incrOpt}, {maxOpt} and {vs} gives empty set"
@@ -1477,9 +1595,41 @@ module Variable =
let minSTEmax max min = min |> minGTmax max |> not
+ ///
+ /// Create a `Minimum` that is a multiple of **incr**.
+ ///
+ /// The increment
+ /// The minimum
+ ///
+ ///
+ /// let incr = Increment.create ( [| 2N |] |> ValueUnit.create Units.Mass.gram)
+ /// let min = Minimum.create false ( [| 3N |] |> ValueUnit.create Units.Mass.gram)
+ /// min |> minMultipleOf incr // returns Minimum.MinIncl (ValueUnit ([|4N|], Mass (Gram 1N)))
+ ///
+ ///
+ ///
+ /// Note that the resulting min is always inclusive and greater than
+ /// or equal to the original min.
+ ///
let minMultipleOf incr min = min |> Minimum.multipleOf incr
+ ///
+ /// Create a `Maximum` that is a multiple of **incr**.
+ ///
+ /// The increment
+ /// The maximum
+ ///
+ ///
+ /// let incr = Increment.create ( [| 2N |] |> ValueUnit.create Units.Mass.gram)
+ /// let max = Maximum.create false ( [| 5N |] |> ValueUnit.create Units.Mass.gram)
+ /// max |> maxMultipleOf incr // returns Maximum.MaxIncl (ValueUnit ([|4N|], Mass (Gram 1N)))
+ ///
+ ///
+ ///
+ /// Note that the resulting max is always inclusive and smaller than
+ /// or equal to the original max.
+ ///
let maxMultipleOf incr max = max |> Maximum.multipleOf incr
@@ -1487,12 +1637,19 @@ module Variable =
let unrestricted = Unrestricted
+ /// A `ValueRange` that contains only non-zero, positive values.
let nonZeroOrNegative = NonZeroNoneNegative
+ ///
/// Create a `MinMax` `ValueRange`. If **min** > **max** raises
/// an `MinLargetThanMax` exception. If min equals max, a `ValueSet` with
/// value min (= max).
+ ///
+ /// The minimum
+ /// The maximum
+ /// A `MinMax` `ValueRange`
+ /// When **min** > **max**
let minMaxToValueRange min max =
if min |> minGTmax max then
// printfn $"min:\n{min}\nmax:\n{max}"
@@ -1510,6 +1667,24 @@ module Variable =
(min, max) |> MinMax
+ ///
+ /// Create a `MinIncr` `ValueRange`.
+ ///
+ /// The minimum
+ /// The increment
+ /// A `MinIncr` `ValueRange`
+ ///
+ ///
+ /// let min = Minimum.create false ( [| 3N |] |> ValueUnit.create Units.Mass.gram)
+ /// let incr = Increment.create ( [| 2N |] |> ValueUnit.create Units.Mass.gram)
+ /// minIncrToValueRange min incr
+ /// // returns MinIncr (Minimum.MinIncl (ValueUnit ([|4N|], Mass (Gram 1N))), Increment (ValueUnit ([|2N|], Mass (Gram 1N))))
+ ///
+ ///
+ ///
+ /// Note that the resulting min is always inclusive and greater than
+ /// or equal to the original min and is a multiple of **incr**.
+ ///
let minIncrToValueRange min incr =
if min |> Minimum.hasZeroUnit |> not then
(min |> minMultipleOf incr, incr)
@@ -1522,7 +1697,24 @@ module Variable =
| None -> incr |> Incr
+ ///
/// Create an `IncrMax` `ValueRange`.
+ ///
+ /// The increment
+ /// The maximum
+ /// An `IncrMax` `ValueRange`
+ ///
+ ///
+ /// let incr = Increment.create ( [| 2N |] |> ValueUnit.create Units.Mass.gram)
+ /// let max = Maximum.create false ( [| 5N |] |> ValueUnit.create Units.Mass.gram)
+ /// incrMaxToValueRange incr max
+ /// // returns IncrMax (Increment (ValueUnit ([|2N|], Mass (Gram 1N))), Maximum.MaxIncl (ValueUnit ([|4N|], Mass (Gram 1N))))
+ ///
+ ///
+ ///
+ /// Note that the resulting max is always inclusive and smaller than
+ /// or equal to the original max and is a multiple of **incr**.
+ ///
let incrMaxToValueRange incr max =
(incr, max |> maxMultipleOf incr) |> IncrMax
@@ -2409,7 +2601,7 @@ module Variable =
/// `ValueRange` vr2.
let isSubSetOf vr2 vr1 =
match vr1, vr2 with
- | ValSet s1, ValSet s2 -> s2 |> ValueSet.isSubset s1
+ | ValSet s1, ValSet s2 -> s2 |> ValueSet.isSubsetOf s1
| _ -> false
diff --git a/src/Informedica.GenUnits.Lib/Notebooks/Examples.dib b/src/Informedica.GenUnits.Lib/Notebooks/Examples.dib
index 07a267a..235f6ce 100644
--- a/src/Informedica.GenUnits.Lib/Notebooks/Examples.dib
+++ b/src/Informedica.GenUnits.Lib/Notebooks/Examples.dib
@@ -1,6 +1,6 @@
#!meta
-{"kernelInfo":{"defaultKernelName":"csharp","items":[{"name":"csharp","aliases":["c#","C#"],"languageName":"C#"},{"name":"vscode","languageName":null,"aliases":["frontend"]}]}}
+{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":["C#","c#"],"languageName":"C#","name":"csharp"},{"aliases":["frontend"],"name":"vscode"}]}}
#!markdown