Calculations are simple arithmetic formulas that can be used to compute new information in configuration engine. Defined as arithmetic equations/ formulas these calculations draw new data points based on the entered data. Since 1902, IMCScript offers a more powerful toolset to set up custom calculations in the model. Though the calculations are knowledge base specific whereas IMCScripts are system specific. Please also refer to IMC Script for more information.
For example: Based on the metal length and width a simple calculation can find its area. This calculated information can next be used in price engine to get the metal cost*.
Calculations are also defined on the Product Knowledgebase and calculate the values of a dynamic attribute. One can make use simple BODMAS principle and combine it with various arithmetic functions to achieve simple to complex estimation work.
The arithmetic calculation allows users to define Calculations for Dynamic Attributes defined in Knowledge Base. Calculations are supported to use Dynamic Data Attribute (DDA) as well as Dynamic Symbolic Attribute (DSA) of Numeric type. However, assignment can only be done on numeric DDA.
Note: that in such a case getting cost value is responsibility of price engine, whereas getting area calculated is responsibility of Calculation engine.
Steps to Configure
- Define a required Dynamic Attribute in the Model of data type Numeric
- Go to Product -> Knowledge Base.
- Add the DAs to the Knowledge Base.
- Create a Group, Sub Group and select the attributes into the sub group.
- Go to Calculation, create a new calculation, where
Name – List the DDA to calculate and define a calculation for.
Arithmetic Expression – Arithmetic Expression using one or more DA's, where DA must be wrapped with $() and of numeric type. (See image below for example). Please refers Appendix 10.1 Calculations for all the supported calculation libraries
- Create a new KB Snapshot.
Step to Test
- Open latest Snapshot or Go to Quote and add a new line Item by choosing the product with calculation defined. Go to Line item -> Configurator page.
- Fill in the DAs with numeric value. DA calculated by system is Read Only (Note that in case of using Snapshot, even calculated values will become default values once saved).
Features
- Contains several Checks and Validationse. Cyclic Dependency, Cast exception, Divide by Zero exceptions, Unacceptable syntax check etc.
- There are few in built functions, provided by Jexl library (i.e substring on String, size () on various objects).
- Apart from supporting basic mathematical operators (+, -, *, /, %) and built-in Jexl functions, Library has been enriched with several Constants and Functions.
- Nested function calls are supported. i.e. “min(max(5,2, pow(2,3)),20,30)”.
- All the functions have been analyzed and optimized where needed, to perform under 0.1 ms* of average duration.
- Unconventional to Java mathematical library, Dynamic variable lengths have been supported for necessary custom functions i.e. you can find GCD, LCM or AVG for multiple variables using single function i.e gcd (12,24,36,40).
* Performance has been measured under Core-i5 Processor, 8GB Ram, Windows 10 Pro, 64-bit OS and average usage of machine after startup. The parameters provided to functions are relatively as short with array up to length 5, and relatively smaller integers and strings. Hence actual performance may differ slightly, on case by case basis.
Constant Library
All the Function defined here, can be used by ‘Math.’ Prefix. Example: Math.PIE, Math.E, Math.EQ etc.
Standard Constants
- PIE π = 3.14159265358979323846, ratio of circumference to its diameter.
- E e = 2.7182818284590452354, the base of natural algorithms.
Conditional Constants
- EQ
It defines Equivalence relation (“==”) between 2 operands.
- NEQ
It defines Not-equivalence relation (“!=”) between 2 operands.
- LT
It defines Less than relation (“<”) between 2 operands.
- LTE
Defines Less than and equals to relation (“<=”) between 2 operands.
- GT
Defines Greater than relation (“>”) between 2 operands.
- GTE
Defines Greater than and equals to relations (“>=”) between 2 operands.
Directional Constants
- ASC
Defines Ascending direction for any operation (Depends on context of use-case).
- DESC
Defines Descending direction for any operation (Depends on context of use-case).
Function Library
Standard Functions
Function |
Description |
Example |
---|---|---|
Summation |
sum (Number… nVals) : Double Finds summation of all values. |
sum([10,20,30]) = 60.0 sum(5,15,25,100) = 145.0 |
Multiplication |
mul (Number… nVals) : Double Finds multiplication of all values |
mul([1,2,3]) = 6.0 mul(2,3,5,1) = 30.0 |
Absolute |
abs (Number n) : Double Gives absolute value (also called - mode) of the number |
Abs(-7) = 7.0 |
Count |
count (Number… nVals) : Double Counts length of arguments/array. Note: This is convenience method, which is similar to Jexl library’s default size method. |
count([4,5]) = 2 count(1,2,3,4,5) = 5 |
Maximum |
max (Number… nVals) : Double Returns greatest number from the provided numbers |
max(4,11) = 11.0 max(1,2,1,7,9) = 9.0 |
Average |
avg (Number… nVals) : Double Finds average of the provided numbers. Note: This function is same as Mean function under Statistic domain |
avg(4,7) = 5.5 avg(6,4.5,11.5,2) = 6.0 |
Greatest Common Divisor (GCD) |
gcd (Number… nVals) : Double Returns Greatest Common Divisor (GCD) of the provided numbers |
gcd(24,18) = 6.0 gcd(50,24,18) = 2.0 |
Least Common Multiplier (LCM) |
lcm(Number… nVals) : Double Returns Least Common Multiplier (LCM) of the provided numbers |
lcm(16,4) = 16.0 lcm(32,12,16,2) = 96.0 |
Convergence Functions
Function |
Description |
Example |
---|---|---|
Round |
round (Number n, Number decimal) : Double Rounds the number to specified decimal digits. Note: In absence of second argument, default decimal digits will be considered 2 |
round(3.1345964,4) = 3.1346 round(3.1345964) = 3.13 |
Ceil |
ceil (Number n) : Double Finds ceiling value for a number |
ceil(7.345) = 8.0 ceil(-7.345) = -7.0 |
Floor |
floor (Number n) : Double Finds floor value for a number |
floor(7.345) = 7.0 floor(-7.345) = -8.0 |
Statistical Functions
Function |
Description |
Example |
---|---|---|
Mean |
mean (Number… nVals) : Double Finds mean of the provided numbers Note: This function is same as Average function given under general functions. |
mean(4,7) = 5.5 mean(6,4.5,11.5,2) = 6.0 |
Median |
median (Number… nVals) : Double Finds median of the provided numbers |
median(3,2,7,1,9,2,10) = 3.0 median(1,2,3,4,5,6) = 3.5 |
Mode |
mode (Number… nVals) : Double Finds mode of the provided numbers. Note: This method doesn’t guarantee any order of outcomes (modes) |
mode(8,2,7,2,9,2,10) = [2.0] mode(1,3,3,4,2,5,2) = [3.0,2.0] mode(1,2,3,4,5) = [] mode(1,1,2,2,3,3) = [1.0,2.0,3.0] |
Exponential Functions
Function |
Description |
Example |
---|---|---|
Power |
pow (Number n, Number exponent) : Double Finds nth power of the number. |
pow(2,3) = 8.0 pow(5,2) = 25.0 |
Root |
root (Number n, Number root) : Double Finds nth root of the number. If multiple roots exist, function returns only positive root of it |
root(16,4) = 2.0 root(3,2) = 1.7320508075688772 |
Square |
sq (Number n) : Double Finds square of a number. Note: This is special case of Power method with exponent 2, hence it’s same as calling pow(n,2). |
sq(3) = 9.0 |
Cube |
cube (Number n) : Double Returns cube of a number. Note: This is special case of Power method with exponent 3, hence it’s same as calling pow(n,3) |
cube(3) = 27.0 |
Square-Root |
sqrt (Number n) : Double Returns positive square root of a number. Note: This is special case of Root method with root 2, hence it’s same as calling root(n,2) |
sqrt(25) = 5.0 |
Cube-Root |
cbrt (Number n) : Double Returns cube root of a number. Note: This is special case of Root method with root 3, hence it’s same as calling root(n,3) |
cbrt(27) = 3.0 |
Trigonometric Functions
Function |
Description |
Example |
---|---|---|
Degree to Radian |
rad (Number degree) : Double Converts degree to radian and returns it |
rad(50) = 0.8726646259971648 |
Radian to Degree |
deg (Number degree) : Double Converts radian to degree and returns it |
deg(0.8726646259971648) = 50 |
Sine |
sin (Number radian) : Double Returns sine value of a radian |
sin(0) = 0.0 sin(rad(45)) = 0.7071067811865475 |
Cosine |
sin (Number radian) : Double Returns cosine value of a radian |
cos(0) = 1.0 cos(rad(45)) = 0.7071067811865476 |
Tangent |
tan (Number radian) : Double Returns tangent value of a radian |
tan(0) = 0.0 tan(rad(45)) = 0.9999999999999999 |
Arc-Sine |
asin (Number radian) : Double Returns arc-sine value of a number. Note: arc-sin is nothing but inverse of Sine function, hence practically it returns radian for the provided value |
asin(0.70) = 0.775397496610753 asin(sin(1)) = 1.0 |
Arc-Cosine |
acos (Number radian) : Double Returns arc-cosine value of a number. Note: arc-cosine is nothing but inverse of Cosine function, hence practically it returns radian for the provided value |
acos(0.70) = 0.7953988301841436 acos(cos(1)) = 1.0 |
Arc-Tangent |
atan (Number radian) : Double Returns arc-tangent value of a number. Note: arc-tan is nothing but inverse of Tangent function, hence practically it returns radian for the provided value |
atan (0.70) = 0.6107259643892086 atan (tan(1)) = 1.0 |
Logarithmic Functions
Function |
Description |
Function |
---|---|---|
Logarithm |
log (Number number, Number base) : Double Calculates and returns logarithmic value of a number using provided base. Note: In absence of second argument, default base will be considered e = 2.718281828459045, which is the base of natural algorithms. |
log (100,10) = 2.0 log (100) = 4.605170185988092 |
Logarithm with base 10 | deg (0.8726646259971648) à 50
log10 (Number number) : Double Calculates and returns logarithmic value of a number using base 10. Note: This is special case of Logarithm method with base 10, hence it’s same as calling log(n,10) |
log10 (100) = 10 |
Casting Functions
Function |
Description |
Example |
---|---|---|
To Integer |
toInteger (String s, Integer default) : Integer Converts provided String to Integer type. If any exception raises while execution of this function, i.e CastException, it will return the default value provided as a second argument.
Converts provided String array to Integer type of array. If any exception raises while conversion of any of element, i.e CastException, it will return the default value provided as a second argument. Note: In case of second argument is of Double type, it will consider its Integer part as a default value. See last example below.
|
toInteger(“11.3”,5) = 11 toInteger(“11”,5) = 11 toInteger(“abc”,5) = 5 toInteger(“def”) = 0 toInteger(“abc”,5.5) = 5 toInteger([“5”,”6”],5.5) = [5,6] toInteger([“7”,”a”],5.5) = 5.5 |
To Integer |
Converts provided Number to Integer type. If any exception raises while execution of this function, i.e provided unacceptable numbers such as NaN /Infinity/-Infinity (which are not supported to be under Integer type in Java) or null, it will return the default value provided as a second argument. Note: In case of second argument is of Integer type, it will convert it to Double and consider it as a default value.
Converts provided Number array to Integer type of array. If any exception raises while conversion of any of element, i.e provided unacceptable numbers such as NaN /Infinity/-Infinity (which are not supported to be under Integer type in Java) or null, it will return the default value provided as a second argument. Note: In case of second argument is of Integer type, it will convert it to Double and consider it as a default value. |
toInteger(31.3,5) = 31 toInteger(31,5) = 31 toInteger(NaN,0) = 0 toInteger(log(0),0) = 0 (Because log(0) is -Infinity) toInteger([8.5,3.6],5) = [8,6] toInteger([8.5,NaN],5) = [8,5] |
To Double |
Converts provided String to Double type. If any exception raises while execution of this function, i.e CastException, it will return the default value provided as a second argument. Note: In case of second argument is of Integer type, it will convert it to Double and consider it as a default value. See last example below.
Converts provided String array to array of Double type. If any exception raises while conversion of any of element, i.e CastException, it will return the default value provided as a second argument. Note: In case of second argument is of Integer type, it will convert it to Double and consider it as a default value. |
toDouble(“11.3”,5.0) = 11.3 toDouble(“11”,5.0) = 11.0 toDouble(“abc”,5.0) = 5.0 toDouble(“abc”,5) = 5.0 toDouble([“11”,”13”],5.0) = [11.0,13.0] toDouble([“11”,”b”],5.0) = [11.0,5.0] |
To Double | toDouble (Number… nVals) : Double
Converts provided Numbers to Double types. |
toDouble(40) = 40.17 toDouble(51.87) = 51.87 toDouble(40,50) = [40.0,50.0] |
To String |
toString (Number nVals) : String Converts provided Numbers to String types |
toString(11) = “11.0” toString(11.3,5.0) = [“11.3”,”5.0”] |
Check Functions
Function |
Description |
Example |
---|---|---|
Is Finite |
isFinite (Number n) : Boolean Checks if number is finite or not. It returns true if the argument is a finite value; returns false otherwise (For NaN and Infinity arguments) |
isFinite(0.70) = true isFinite(log(0)) = false isFinite(NaN) = false |
Is Not-A-Number |
isNaN (Number n) : Boolean Checks if number is NaN or not. It returns true if the argument is a NaN; returns false otherwise |
isNaN(NaN) = true isNaN(0.70) = false isNaN(log(0)) = false |
Is Null |
isNull (Number n) : Boolean Checks if argument is null or not. It returns true if the argument is a null; returns false otherwise |
isNull(null) = true isNull(log(0)) = false isNull(NaN) = false |
Conditional Functions
Function |
Description |
Example |
---|---|---|
If |
iff (Boolean condition, Number numberIfTrue, Number numberIfFalse) : Number This is conditional function (Just like ternary operator), which returns value based on the outcome of conditional argument (First argument). |
iff(10<5,1,0) = 0 iff(round(sin(rad(45)))== round(cos(rad(45))),1,0) = 1 |
Filter If |
filterIf (Number[] nArray, Constant condition, Number compareTo) : Number[] This method filters array based on provided simple mathematical condition using last two arguments. Here the second argument is Conditional constants: Math.EQ, Math.NEQ, Math. LT, Math. LTE, Math.GT, Math.GTE. See Conditional Constants for more info on these constants. Conditional Constants Note: User can also use simple String instead of Mathematical constant to increase the readability of expression. i.e “>=” instead of Math.GTE; Also, providing incorrect value as a conditional argument will lead to empty array as an outcome |
filterIf([1,2,3,4,5,6,7,8,9,10], Math.GT, 5) = [6,7,8,9,10] filterIf([1,2,3,4,5,6,7,8,9,10], Math.LTE, 5) = [1,2,3,4,5] filterIf([1,2,3,4,5,6,7,8,9,10], “>=”, 8) = [8,9,10] |
Count If |
countIf (Number[] nArray, Constant condition, Number compareTo) : Integer This is a special method for convenience to call Count and Filter If at one go. Internally the method calls Filter If and Count recursively. Note: Providing incorrect value as a conditional argument will lead to 0 value as an outcome |
countIf([1,2,3,4,5,6,7,8,9,10], Math.GT, 5) = 5 |
Special Functions
Function |
Description |
Example |
---|---|---|
Sort |
sort (Number[] nArray, Constant direction) : Boolean This method returns sorted array for the provided one (nArray – First argument), with given direction (direction – Second argument). Here second argument: direction can be one of the Directional constants: Math.ASC or Math.DESC;
It’s good to know how the special cases like +Infinity, -Infinity and NaN will be sorted by this method; Above ‘Number line’ represents it in a simple way, where place of NaN is adapted from standard Java comparator convention. Note: In absence of which Math.ASC is considered as a default value of it. Providing incorrect value as a directional argument will lead to unsorted array as an outcome |
sort([4,3,6,9,5], ASC) = [3,4,5,6,9] sort([4,3,6,9,5], DESC) = [9,6,5,4,3] sort([10,NaN,-log(0),log(0)]) = [-Infinity,10,+Infinity,NaN] |
Distinct |
dist (Number[] nArray) : Number[] Returns array of distinct elements for given array. Note: This function does not guarantee to maintain any specific order of the sequence |
dist([5,3,4,4,5]) = [3,4,5] dist([10,2,3,10,2], DESC) = [2,3,10] |
Concatenate |
concat (String[] sArray1, String[] sArray2) : String[] Concatenate each respective element of both the array and returns as a concatenated array. Note: Any null value in array will be considered as an empty string. The length of returned array is maximum length of both arrays provided in arguments |
concat([“a”,”b”,”c”], [“1”,”2”,null]) = [“a1”,”b2”,”c”] concat([“a”,”b”,”c”], [“1”,”2”]) = [“a1”,”b2”,”c”] concat([“a”,”b”], [“1”,”2”,”3”]) = [“a1”,”b2”,”3”] |
Concatenate |
concat (String… sArgs) : String Concatenate one or more string arguments and returns concatenated String. Note: Any null argument will be considered as an empty string |
concat(“a”,”b”,”c”) = “abc” concat(“a”,”b”,null) = “ab” |
Mapper |
map (String[] sArray, Map<String,String> sMap) : String[] Returns updated array by replacing each element of provided array (sArray) with mapped string, provided by map (sMap). Note: Any missing keys in map will leave the element untouched. |
map([“a”,”b”,”c”], {“a”:”1”,”b”:”2”,”c”:”3”}) = [“1”,” 2”,”3”] map([“a”,”b”,”c”,”d”], {“a”:”1”,”b”:”2”,”c”:”3”}) = [“1”,” 2”,”3”,”d”] |
Mapper |
map (Number[] nArray, Map< Number, Number > nMap) : Double[] Returns updated array of value type Double, by replacing each element of provided array (nArray) with mapped value, provided by map (nMap). Note: Any missing keys in map will leave the element untouched. |
map([1,2,3], {1:11,2:22,3:33}) = [11.0,22.0,33.0] map([1,2,3], {1.0:11,2:22,3:33.0}) = [11.0,22.0,33.0] map([1,2,3,4], {1:11,2:22,3:33}) = [11.0,22.0,33.0,4.0] |
Search Expression |
se (String expression).as<<TYPE>>( TYPE defaultObj) : TYPE This is special function which provides traversing capability between different level of objects (i.e parent SalesItem, children of salesItem, etc). Please refer to SearchExpression documentation for the syntax of expression. However, user is strongly encouraged, to go through important note, given below, before using this function.
This method is combination of 2 parts as shown in syntax: First one is se, which accepts expression (starting with “ConfigItem” always) of type String, whereas Second one as<<TYPE>> is kept explicitly to get expected return type of the result coming from se. Here <<TYPE>> can be replaced by different return types as shown here: Number (Numeric), String (String), SArray (String array) or NArray (Numeric array). The argument in this second part is defaultObject which can be used in case SearchExpression is provided null, or if any exception happens while execution in run time. The examples shown at the end of this will give user better clarity of the overall syntax. Note:
This function has been added as an experimental basis to extend the traversing capability of Calculations. However, it doesn't guarantee on performance, as it highly dependent on the nested level of traversals. Hence, user is highly encouraged to find alternate options first (By creating additional Das, and/or using Triggers). Furthermore, due to dynamic (run time) nature of this function, uncertainty of return type as well as being black-box for Calculations module, several validation features including cyclic dependency, need to be skipped, at the time of creation of calculations; User should take a note of which. |
se(“ConfigItem.configItemIncludedBy.children().getDAValue(‘DA1’)”).asNArray([]) = [10,20,30] (Assumed that DA1 is of type Numeric)
se(“ConfigItem.configItemIncludedBy.objectName”).asString(‘No_Name’) = “SalesItem1” |
Additional Notes:
- User should keep special cases in mind for above functions, i.e NaN, +Infinity, -Infinity, null etc; which may return the answers NaN/+Infinity/-Infinity/Other (Case by case basis).
- Providing one or more null argument(s) will result in NaN (Or Default argument, if any) in most of the cases. However, we highly discourage user to provide NaN and/or null in arguments to avoid unexpected results.
- All the function/constant names are case-sensitive as well as signature-sensitive, hence user is encouraged to follow the syntax and signature accordingly.
- Functions with single parameter of variable argument (i.e Double…, String…) type has flexibility to accept any of this: array or variable arguments. i.e “max (3,4,5)” will return same as “max ([3,4,5])”.
- Calculations are limited under the scope of same KB for now, hence user cannot access DAs from the KB of another product or from parent/child attribute of SI; However, this requirement can be fulfilled by using Search Expressions as an entry point to such things.
- User should try to avoid using SearchExpression method as far as possible, if not, he must keep read the notes mentioned under it, before using it.
- SE note: type v/s types keywords has been simplified under SE. Previously there was difference between them, whereas from now onwards only type keyword exists, which will return collection of all types of object. This has been done to keep the syntax more generic while using it for different use cases. However, it’s still possible to get single type of object using first keyword (See table). At the time of migration, there is a need to change the syntax of such legacy SEs accordingly.
Old Way |
New Way |
---|---|
SalesItem.type.endsWith('Stamping') |
SalesItem.type.first().endsWith('Stamping') |
SalesItem.types.ID |
SalesItem.type.ID |