Unit-based Scaling

Scaled versus unscaled values

With each identifier for which you have specified a Unit attribute, AIMMS associates two values:

  • the scaled value (i.e. expressed in terms of the unit specified), and

  • the unscaled value (i.e. expressed in terms of the associated atomic unit expression).

The transformation between scaled and nonscaled values is completely determined by the product of explicit and implicit scale factors associated with the various quantity and unit definitions.

When used

As mentioned in Unit Analysis, AIMMS uses internally unscaled values for all storage and arithmetic computations. This guarantees automatic scale consistency. However, for external use, scaled values are more natural when exchanging data with components outside the AIMMS execution system. Specifically, AIMMS uses scaled values when

  • displaying the data of an identifier in the (end-)user interface,

  • exchanging data for a particular identifier with files and databases using the READ and WRITE statements,

  • passing arguments to external procedures and functions,

  • storing the result value(s) of an external function, and

  • communicating the variables and constraints of a mathematical program to a solver.

Units in displays

When displaying data in either the graphical user interface or in PUT and DISPLAY statements, AIMMS will transfer data using the scaled unit specified in the definition of the identifier. For example, if you have specified kton as the unit attribute of an identifier while the underlying atomic unit is kg, AIMMS will still display the identifier values in kton.

…and data entry

Similarly, when reading data from or writing data to scalar numerical constants, lists, tables, composite tables (either graphical or in data files), or tables (in databases) using the READ and WRITE statements, AIMMS assumes that this data is provided in the (scaled) units that you have specified in the identifier declarations in your model, and will transform all data to the corresponding unscaled values for internal storage.

Override default scaling

You can override the default scaling based on the content of the Unit attribute either locally within the graphical end-user interface or model source, or globally using Conventions. Local and global overrides are discussed in complete detail in Locally Overriding Units and Globally Overriding Units Through Conventions.

Unit-based Scaling of Mathematical Programs

Automatic scaling for solvers

During communications with a solver, AIMMS will scale all variables and constraints (including variable definitions) in accordance with the scale factor associated with the Unit attribute in their declaration. This choice is based on the assumption that the specified units reflect the expected order of magnitude of the numbers associated with the variables, parameters and constraints, and that these numbers will neither be very large nor very small. As a result, the values of all rows and columns in the generated mathematical program are expected to be of the same, reasonable, order of magnitude. Especially nonlinear solvers may greatly benefit from this choice.

Main example revisited

In the main example of Unit Analysis, the scale factors are \(10^3\) for the identifier WeightOfItem(i), \(1/3.6\) for VelocityOfItem(i), and \(10^6\) for KineticEnergyOfItem(i). The entire constraint associated with the defined variable is then scaled according to the scale factor of the unit of the definition variable KineticEnergyOfItem(i), MJ. This corresponds with dividing the left- and right-hand side of the constraint by \(10^6\). Thus, the resulting expression communicated to the solver by AIMMS will be:

KineticEnergyOfItemColumn(i) =
    1/2 * (1/10^3) * WeightofItemColumn(i) * ((1/3.6) * VelocityOfItemColumn(i))^2 ;

Notice that each variable shown in this expression has a suffix Column to indicate that it corresponds to a column in the matrix underlying the mathematical program.

Units of reduced cost and shadow price

Some care is needed when you have requested sensitivity information associated with a mathematical program, such as the reduced costs of variables and shadow prices of constraints. The basic rules with respect to retrieving sensitivity information are as follows:

  • All sensitivity suffices in AIMMS, such as the .ReducedCost and .ShadowPrice suffix, are unitless.

  • All sensitivity suffices hold the exact numerical value as computed by the solver, i.e. expressed with respect to the scaled values that are communicated to the solver by AIMMS.

Motivating the choice of unitless

The reason for not associating units with the sensitivity suffices is that a single variable or constraint may be used in multiple mathematical programs, each with its own objective. As each objective may have a different associated unit, and the reduced costs and shadow prices express properties of a variable or constraint with respect to the objective, it is inherently impossible to associate a single unit with the .ReducedCost and .ShadowPrice suffices.

Unitand scale consistent sensitivity data

You may encounter scaling problems when you want to perform direct computations with the sensitivity suffices of variables and constraints. Using the .Unit suffix and AIMMS’ capabilities to override units of subexpressions (see Unit Expressions and Locally Overriding Units), however, it is easy to formulate expressions that

  • result in the correct unscaled numerical values that can be used directly in AIMMS computations, and

  • have an associated unit that is consistent with their interpretation.

Example with unit overrides

Assuming that ExampleVariable and ExampleConstraint are part of a mathematical program, with ObjectiveVariable as its objective function, one can obtain the correct values by locally overriding the units of the .ReducedCost and .ShadowPrice suffices through the expressions:

(ExampleVariable.ReducedCost  ) [ObjectiveVariable.Unit / ExampleVariable.Unit  ]
(ExampleConstraint.ShadowPrice) [ObjectiveVariable.Unit / ExampleConstraint.Unit]

Example with unit functions

Alternatively, you can use the function EvaluateUnit (see Converting Unit Expressions to Numerical Expressions) to obtain the same result

ExampleVariable.ReducedCost *
        EvaluateUnit( ObjectiveVariable.Unit / ExampleVariable.Unit )
ExampleConstraint.ShadowPrice *
        EvaluateUnit( ObjectiveVariable.Unit / ExampleConstraint.Unit )

Introducing new parameters

If you need to perform multiple computations with these expressions, or want to display them in the graphical end-user interface, you are advised to assign these expressions to additional parameters in your model with the appropriate associated units.

Example with convention

When you have used a Convention to override the default scaling during the SOLVE statement, the expressions above should be augmented by applying the functions ConvertUnit and EvaluateUnit (see Unit-valued Functions):

ExampleVariable.ReducedCost *
        EvaluateUnit( ConvertUnit(ObjectiveVariable.Unit, ConventionUsed) /
                      ConvertUnit(ExampleVariable.Unit, ConventionUsed)    )
ExampleConstraint.ShadowPrice *
        EvaluateUnit( ConvertUnit(ObjectiveVariable.Unit, ConventionUsed) /
                      ConvertUnit(ExampleConstraint.Unit, ConventionUsed)  )

This will result in a scaling factor that is consistent with the variable and constraint scaling convention passed to the solver. You cannot obtain the same result by locally overriding the units of the .ReducedCost and .ShadowPrice suffices, as unit local overrides only accept simple unit expressions (see Unit Expressions).

Use of unit parameters

If your model contains multiple computations concerning the .ReducedCost and .ShadowPrice suffices, each with identical scale factors, you may consider assigning the unit expressions required for scaling these suffices to unit parameters (see Unit-valued Parameters). You can then directly use such unit parameters in a local unit override, rather than having to repeat possibly complex unit expressions time and again. For instance, if ScaledUnit is a unit parameter defined by

ScaledUnit := ConvertUnit(ObjectiveVariable.Unit, ConventionUsed) /
              ConvertUnit(ExampleVariable.Unit, ConventionUsed) ;

then the correctly scaled expression for the reduced cost of ExampleVariable can be simplified to

(ExampleVariable.ReducedCost) [ScaledUnit]

You can use a local override, because a reference to a scalar unit parameter again forms a valid simple unit expression (see Unit Expressions).