Define calculations
  • 26 Nov 2024
  • 13 Minutes to read
  • Dark
    Light

Define calculations

  • Dark
    Light

Article summary

Use calculations to compute new information during the configuration process. Defined as arithmetic equations or formulas, they handle tasks such as cost estimation based on user input and calculating other dependent parameters.

For example, for a product made of metal, calculations can determine the area based on its length and width. Then, the pricing engine can use this calculated area to estimate the metal product cost.

Tip

The pricing engine calculates the cost, while the calculation engine calculates the area.

Calculations are defined in the product knowledge base and compute the values of Dynamic Data Attributes (DDA) and Dynamic Symbolic Attributes (DSA) of the numeric type. However, you can perform assignments only on numeric DDAs.

Using basic BODMAS principles combined with arithmetic functions, calculations can handle anything from simple estimations to complex computations.

Tip

IMCScript offers a more powerful tool set to set up custom calculations in the model. However, IMCScript applies to the whole system, while calculations apply only to a specific knowledge base.

Create a calculation

  1. Create a dynamic data attribute (DDA) of the numeric type.

  2. Add the DDA to the product knowledge base.

  3. Group the attributes in the product knowledge base.

  4. In the knowledge base, go to the Calculations tab by following these steps:

    1. From the application left navigation area, select Products.
    2. Select a product.
    3. From the top navigation bar, select Knowledge Base.
    4. Select a knowledge base, then go to the Calculations tab.
  5. Select to create a calculation.

  6. On the Create New Calculation dialog, enter the following information:

    • Name—Enter a name for the calculation, for example the name of your dynamic attribute.
    • Arithmetic Expression—Enter an arithmetic expression including one or multiple numeric dynamic attributes. Use the $() syntax to add a dynamic attribute.
  7. Create a knowledge base snapshot.

In the product configurator, users can't edit the value of the dynamic attribute, whose value is computed based on a calculation.

Calculation features

  • Includes various checks such as cyclic dependency detection, cast exceptions, divide-by-zero exceptions, and unacceptable syntax validation.
  • Includes several built-in functions from the Jexl library, such as substring() for strings and size() for various objects.
  • Supports basic mathematical operators (+, -, *, /, %) and includes additional constants and custom functions.
  • Allows nested function calls, for example, min(max(5, 2, pow(2, 3)), 20, 30).
  • Unlike the conventional Java math library, we support dynamic variable lengths for custom functions. For example, you can calculate GCD, LCM, or AVG for multiple variables in a single function call, such as gcd(12, 24, 36, 40).

Calculation performance

All functions execute with an average duration of less than 0.1 ms.

We conducted the performance tests on a system with the following specifications:

  • Processor: Core i5
  • Memory: 8 GB RAM
  • Operating system: Windows 10 Pro, 64-bit

We used a typical machine after startup, parameters, for example arrays, of up to 5 elements and relatively small integers and strings. Actual performance may vary based on specific use cases and system configurations.

Libraries

Constant library

The Math. prefix can use defined here functions, for example, Math.PIE, Math.E, or Math.EQ.

Standard constants

ConstantValue
PIE π3.14159265358979323846, ratio of circumference to its diameter.
E e2.7182818284590452354, the base of natural algorithms.

Conditional constants

ConstantFunction
EQDefines Equivalence relation (==) between 2 operands.
NEQDefines Not-equivalence relation (!=) between 2 operands.
LTDefines Less than relation (<) between 2 operands.
LTEDefines Less than and equals to relation (<=) between 2 operands.
GTDefines Greater than relation (>) between 2 operands.
GTEDefines Greater than and equals to relations (>=) between 2 operands.

Directional constants

ConstantFunctions
ASCDepending on the use case context, defines ascending direction for any operation.
DESCDepending on the use case context, defines descending direction for any operation.

Standard functions

FunctionDescriptionExample
Summationsum(Number... nVals) : Double
Computes the sum of all provided values.
sum([10, 20, 30]) = 60.0

sum([5, 15, 25, 100]) = 145.0
Multiplicationmul(Number... nVals) : Double
Computes the multiplication of all provided values.
mul([1, 2, 3]) = 6.0

mul(2, 3, 5, 1) = 30.0
Absoluteabs(Number n) : Double
Returns the absolute value of the provided number.
abs(-7) = 7.0
Countcount(Number... nVals) : Integer
Counts the number of provided arguments or elements in an array.
This function is similar to Jexl's default size method.
count([4, 5]) = 2

count(1, 2, 3, 4, 5) = 5
Maximummax(Number... nVals) : Double
Returns the largest number among the provided numbers.
max(4, 11) = 11.0

max(1, 2, 7, 9) = 9.0
Averageavg(Number... nVals) : Double
Computes the average of the provided values.
This function is equivalent to the Mean function in statistics.
avg(4, 7) = 5.5

avg(6, 4.5, 11.5, 2) = 6.0
Greatest Common Divisor (GCD)gcd(Number... nVals) : Integer
Calculates the greatest common divisor (GCD) of the provided numbers.
gcd(24, 18) = 6

gcd(50, 24, 18) = 2
Least Common Multiple (LCM)lcm(Number... nVals) : Integer
Calculates the least common multiple (LCM) of the provided numbers.
lcm(16, 4) = 16

lcm(32, 12, 16, 2) = 96

Convergence functions

FunctionDescriptionExample
Roundround(Number n, Number decimal) : Double
Rounds the number to the specified decimal digits. If the second argument is not provided, the default decimal digits will be 2.
round(3.1345964, 4) = 3.1346

round(3.1345964) = 3.13
Ceilceil(Number n) : Double
Finds the ceiling value of a number.
ceil(7.345) = 8.0

ceil(-7.345) = -7.0
Floorfloor(Number n) : Double
Finds the floor value of a number.
floor(7.345) = 7.0

floor(-7.345) = -8.0

Statistical functions

FunctionDescriptionExample
Meanmean(Number… nVals) : Double
Finds the mean of the provided numbers. This function is the same as the Average function in the list of standard functions.
mean(4, 7) = 5.5

mean(6, 4.5, 11.5, 2) = 6.0
Medianmedian(Number… nVals) : Double
Finds the median of the provided numbers.
median(3, 2, 7, 1, 9, 2, 10) = 3.0

median(1, 2, 3, 4, 5, 6) = 3.5
Modemode(Number… nVals) : Double
Finds the mode of the provided numbers. This function 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

FunctionDescriptionExample
Powerpow(Number n, Number exponent) : Double
Finds the nth power of the number.
pow(2, 3) = 8.0
pow(5, 2) = 25.0
Rootroot(Number n, Number root) : Double
Finds the nth root of the number. If multiple roots exist, the function returns only the positive root.
root(16, 4) = 2.0

root(3, 2) = 1.7320508075688772
Squaresq(Number n) : Double
Finds the square of a number.
This is a special case of the Power method with an exponent of 2; hence, it’s equivalent to calling pow(n, 2).
sq(3) = 9.0
Cubecube(Number n) : Double
Returns the cube of a number.
This is a special case of the Power method with an exponent of 3; hence, it’s equivalent to calling pow(n, 3).
cube(3) = 27.0
Square-Rootsqrt(Number n) : Double
Returns the positive square root of a number.
This is a special case of the Root method with root 2; hence, it’s equivalent to calling root(n, 2).
sqrt(25) = 5.0
Cube-Rootcbrt(Number n) : Double
Returns the cube root of a number.
This is a special case of the Root method with root 3; hence, it’s equivalent to calling root(n, 3).
cbrt(27) = 3.0

Trigonometric functions

FunctionDescriptionExample
Degree to Radianrad(Number degree) : Double
Converts degrees to radians.
rad(50) = 0.8726646259971648
Radian to Degreedeg(Number radian) : Double
Converts radians to degrees.
deg(0.8726646259971648) = 50
Sinesin(Number radian) : Double
Returns the sine value of a radian.
sin(0) = 0.0

sin(rad(45)) = 0.7071067811865475
Cosinecos(Number radian) : Double
Returns the cosine value of a radian.
cos(0) = 1.0

cos(rad(45)) = 0.7071067811865476
Tangenttan(Number radian) : Double
Returns the tangent value of a radian.
tan(0) = 0.0

tan(rad(45)) = 0.9999999999999999
Arc-Sineasin(Number value) : Double
Returns the arc-sine (inverse of the sine function) of a value.
asin(0.70) = 0.775397496610753

asin(sin(1)) = 1.0
Arc-Cosineacos(Number value) : Double
Returns the arc-cosine of a value (inverse of the cosine function).
acos(0.70) = 0.7953988301841436

acos(cos(1)) = 1.0
Arc-Tangentatan(Number value) : Double
Returns the arc-tangent of a value (inverse of the tangent function).
atan(0.70) = 0.6107259643892086

atan(tan(1)) = 1.0

Logarithmic functions

FunctionDescriptionExample
Logarithmlog (Number number, Number base) : Double
Calculates and returns the logarithmic value of a number using the provided base. If the second argument is absent, the default base will be considered as e = 2.718281828459045, which is the base of natural logarithms.
log (100,10) = 2.0

log (100) = 4.605170185988092
Logarithm with base 10log10 (Number number) : Double
Calculates and returns the logarithmic value of a number using base 10. This is a special case of the Logarithm method with base 10, hence it’s the same as calling log(n,10).
log10 (100) = 2.0

Casting functions

FunctionDescriptionExample
To Integer (String)toInteger (String s, Integer default) : Integer
Converts the provided String to Integer type. If any exception occurs during execution (for example, CastException), it will return the default value provided as the second argument.
toInteger (String[] sArray, Integer default) : Integer
Converts the provided String array to an Integer array. If any exception occurs during conversion of any element (for example, CastException), it will return the default value provided as the second argument.
Note: If the second argument is of the Double type, it will consider its Integer part as the default value.
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 (Number)toInteger (Number n, Integer default) : Integer
Converts the provided Number to Integer type. If any exception occurs (for example, unacceptable numbers like NaN/Infinity/-Infinity), it will return the default value provided as the second argument.
toInteger (Number[] nArray, Integer default) : Integer
Converts the provided Number array to Integer array. If any exception occurs (for example, unacceptable numbers like NaN/Infinity/-Infinity), it will return the default value provided as the second argument.
Note: If the second argument is of the Integer type, it will convert it to Double and consider it as the default value.
toInteger(31.3,5) = 31

toInteger(31,5) = 31

toInteger(NaN,0) = 0

toInteger(log(0),0) = 0

toInteger([8.5,3.6],5) = [8,6]

toInteger([8.5,NaN],5) = [8,5]
To Double (String)toDouble (String s, Number default) : Double
Converts the provided String to Double type. If any exception occurs (for example, CastException), it will return the default value provided as the second argument.
toDouble (String[] sArray, Number default) : Double
Converts the provided String array to an array of Double type. If any exception occurs during conversion of any element (for example, CastException), it will return the default value provided as the second argument.
Note: If the second argument is of the Integer type, it will convert it to Double and consider it as the 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 (Number)toDouble (Number… nVals) : Double
Converts the provided Number to Double type.
toDouble(40) = 40.0

toDouble(51.87) = 51.87

toDouble(40,50) = [40.0,50.0]
To StringtoString (Number nVals) : String
Converts the provided Number to String type.
toString(11) = "11.0"

toString(11.3,5.0) = ["11.3", "5.0"]

Check functions

FunctionDescriptionExample
Is FiniteisFinite (Number n) : Boolean
Checks if the number is finite or not. 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-NumberisNaN (Number n) : Boolean
Checks if the number is not a number (NaN) or not. Returns true if the argument is NaN; returns false otherwise.
isNaN(NaN) = true

isNaN(0.70) = false

isNaN(log(0)) = false
Is NullisNull (Number n) : Boolean
Checks if the argument is null or not. Returns true if the argument is null; returns false otherwise.
isNull(null) = true

isNull(log(0)) = false

isNull(NaN) = false

Conditional functions

FunctionDescriptionExample
Ififf(Boolean condition, Number numberIfTrue, Number numberIfFalse) : Number
This conditional function works like a ternary operator, returning a value based on the outcome of the condition (first argument).
iff(10 < 5, 1, 0) = 0

iff(round(sin(rad(45))) == round(cos(rad(45))), 1, 0) = 1
Filter IffilterIf(Number[] nArray, Constant condition, Number compareTo) : Number[]
Filters an array based on the provided mathematical condition, using the last two arguments. Here the second argument is a conditional constant: Math.EQ, Math.NEQ, Math.LT, Math.LTE, Math.GT, Math.GTE.
Note: You can also use strings like ">=" instead of constants for better readability. An incorrect condition results in an empty array.
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 IfcountIf(Number[] nArray, Constant condition, Number compareTo) : Integer
Counts the number of elements in an array that meet the specified condition. Internally, this method calls Filter If and then Count.
Note: An incorrect condition returns 0 as the result.
countIf([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], Math.GT, 5) = 5

Special functions

Before you begin

  • Keep special cases in mind when using these functions, such as NaN, +Infinity, -Infinity, and null, as they may return results like NaN, +Infinity, -Infinity, or other values depending on the case.

  • Avoid passing one or more null arguments, as this typically results in NaN (or a default argument, if specified). We do not recommend providing NaN or null in arguments to prevent unexpected results.

  • All function and constant names are case-sensitive and signature-sensitive. Follow the correct syntax and signatures to avoid errors.

  • Functions with a single parameter of variable argument types (for example, Double..., String...) allow flexibility. You can pass either an array or variable arguments. For example, max(3,4,5) returns the same result as max([3,4,5]).

  • Calculations are currently limited to the same knowledge base. You cannot access DAs from another product’s knowledge base or from parent/child attributes of a SalesItem. However, you can use Search Expressions to bridge this gap.

  • Avoid using the SearchExpression method unless absolutely necessary. If you must use it, review the notes associated with it beforehand.

  • The distinction between type and types keywords has been simplified for search expressions. Previously, type and types behaved differently, but now only the type keyword exists. It returns a collection of all object types, making the syntax more generic for various use cases. You can still retrieve a single type of object using the first keyword, as shown in the following table. When migrating legacy search expressions, update their syntax to align with this change.

    Old syntaxNew syntax
    SalesItem.type.endsWith('Stamping')SalesItem.type.first().endsWith('Stamping')
    SalesItem.types.IDSalesItem.type.ID

Functions

FunctionDescriptionExample
Sortsort(Number[] nArray, Constant direction) : Boolean
Sorts the provided array (nArray) in the specified direction (direction). Direction can be one of the constants: Math.ASC (ascending) or Math.DESC (descending). Note: Defaults to Math.ASC if direction is not provided. Invalid direction values result in an unsorted array.
Handles special cases: +Infinity, -Infinity, and NaN based on Java comparator conventions.
sort([4,3,6,9,5], Math.ASC) = [3,4,5,6,9]

sort([4,3,6,9,5], Math.DESC) = [9,6,5,4,3]

sort([10,NaN,-log(0),log(0)]) = [-Infinity, 10, +Infinity, NaN]
Distinctdist(Number[] nArray) : Number[]
Returns an array of distinct elements from the provided array. This function doesn't guarantee any specific order for the output array.
dist([5,3,4,4,5]) = [3,4,5]

dist([10,2,3,10,2]) = [2,3,10]
Concatenateconcat(String[] sArray1, String[] sArray2) : String[]
Concatenates corresponding elements of two arrays and returns the result as a new array. Note: Null values are treated as empty strings. The resulting array length equals the maximum length of the input arrays.
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"]
Concatenateconcat(String... sArgs) : String
Concatenates one or more string arguments into a single string. Note: Null arguments are treated as empty strings.
concat("a","b","c") = "abc"

concat("a","b",null) = "ab"
Mappermap(String[] sArray, Map<String,String> sMap) : String[]
Updates an array (sArray) by replacing each element using a provided map (sMap). Missing keys leave the element unchanged.
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"]
Mappermap(Number[] nArray, Map<Number, Number> nMap) : Double[]
Updates a numeric array (nArray) by replacing elements using a provided map (nMap). Missing keys leave the element unchanged.
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 Expressionse(String expression).as<<TYPE>>(TYPE defaultObj) : TYPE
Enables traversing between object levels (for example, parent SalesItem and its children).
Syntax:
  • se—Accepts a search expression as a string (starts with "ConfigItem").
  • as<<TYPE>>—Specifies the expected return type (Number, String, SArray, or NArray).
If the expression is null or an error occurs, returns defaultObj.
Note: This experimental function has performance limitations and lacks validation for nested dependencies. Consider alternate options like triggers or additional DAs for complex use cases.
se("ConfigItem.configItemIncludedBy.children().getDAValue('DA1')").asNArray([]) = [10,20,30]

se("ConfigItem.configItemIncludedBy.objectName").asString('No_Name') = "SalesItem1"

Was this article helpful?

Changing your password will log you out immediately. Use the new password to log back in.
First name must have atleast 2 characters. Numbers and special characters are not allowed.
Last name must have atleast 1 characters. Numbers and special characters are not allowed.
Enter a valid email
Enter a valid password
Your profile has been successfully updated.