Jan 4, 2021

Mastering conditional feeders in TM1

This article gathers everything you should know about conditional feeders in IBM Planning Analytics powered by TM1.

What are Conditional Feeders?

Conditional Feeders is a broad term for describing a TM1 feeder statement that contains a condition or cube reference. Conditional Feeders can be used to reduce overfeeding.

Conditional feeders can be split into five different types:

  1. Conditional Feeders
  2. Attribute Directional Feeders
  3. Data Directional Feeders
  4. Feeding From Consolidations
  5. Feeding To Consolidations

Conditional Feeders

Binary conditional feeders can be used to restrict feeding for rules where a particular condition is met. This is normally achieved by including an If statement within the right hand side of a feeder statement resulting in an invalid reference.

For example consider the following rule:

[‘Postage’] = N: IF( [‘Weight’] < 25, 0, 10 );

A feeder from Weight would therefore overfeed where weight is less than 25g (shown here as a full DB reference for comparison):

['Weight'] => DB ('Price', !Version, !Year, !Release, 'Postage' );

And a conditional feeder can be used to eliminate the overfeeding, in this example the cube reference in the DB formula returns ‘ ‘ (null) if the weight is below 25g and a feeder is not set.

['Weight'] =>  DB (     If ( DB ('Price', !Version, !Year, !Release, 'Weight') >= 25,           'Price', ' ' ), !Version, !Year, !Release, 'Postage' );

Additionally the If statement in the feeder could be used to feed a different element in the same cube – or a null element:

 ['Weight'] => DB ( 'Price', !Version, !Year, !Release, If ( DB ('Price', !Version, !Year, !Release, 'Weight') >= 25, 'Postage', 'Free Delivery' ) );

Attribute Directional Feeders

In most models there is a need to write a feeder statement where the right hand side of the feeder ‘looks up’ a value in an attribute cube. That lookup value determines the cells to be fed and therefore it can be understood to be a conditional feeder.

A common application of this, is to feed ‘Next Month’ or ‘Next Year’ for a rolling balance calculation for example:

['Opening Stock'] = N:   DB ('Stock', AttrS ('Year', !Year, 'Previous'), !Store, !Release, 'Closing Stock' );

Feeders would be:

 ['Closing Stock'] =>   DB ('Stock', AttrS ('Year', !Year 'Next'), !Store, !Release, 'Opening Stock' );

Data Directional Feeders

Much like Attribute Directional Feeders it is common for the target to be determined by data in the source cell or any cell in the model.

Consider the following rule:

 ['Headcount'] = N:  If ( !Department @= DB ( 'Employee Details', 'Actual', !Year, !Month, !Employee, 'Department' ),   1,   0);

The feeder from the Staffing cube would need to reference the ‘department’ entered as a string value to only feed the leaf level departments.

This example is different from the attribute feeders in that the string data is used as the right hand side for the feeder statement and is expected to change over time.

['Actual', 'Department'] => DB ('HR', !Version, !Year, !Month, !Employee,                                 DB ( 'Employee Details', 'Actual', !Year, !Month, !Employee, 'Department' ),                                 'Headcount' );

In almost all other ways feeding from a cube and feeding from an attribute value are the same.

Feeding From a Consolidation

Where a feeder statement contains a consolidated element in the left hand side (Area Statement) the effect is that all of the leaf level descendants of that consolidation are included in the left hand side. This is the same as writing out a separate feeder statement for each leaf level element.

Consider the following feeder statement:

 ['The Beatles', 'Writing Credits'] =>  DB('Writer Credits',!Release, DB( 'Release Info', !Release, 'Writing Credits' ),'Credits');

This means that all the descendants of ‘The Beatles’ will feed the ‘Artist’ as detailed in the Release Info cube.

If we were to add another element to the ‘The Beatles’ consolidation, the feeder would not set. This is because at the time the feeder was set (when the rule was saved or the string measure input in the source cube) the element was not part of the consolidation (the ‘condition’ is the feeder is set for the structure of the dimension at that point in time).

Feeding To a Consolidation

Where a feeder statement contains a consolidated element in the right hand side (Target) the effect is that all of the leaf level descendants of that consol element are fed. This would be the same as writing out separate statements for all of the descendants of the consolidation. This can be helpful when you want to restrict the amount of elements in a dimension that are fed.

Consider the following rule:

[{'Units', 'Revenue'}] = N: If ( ElIsAnC ( 'Version', 'Fed Forecast Versions', !Version) = 1,    If ( AttrS ( 'Month', !Month, 'Forecast') @= 'Y' & AttrS ( 'Year', !Year, 'Forecast') @= 'Y',     ['Actual'],     Continue),   Continue);

Here the actualization rule will only apply where a ‘Version’ element is a descendant of the ‘Fed Forecast Versions’ consolidation.

For the feeder we could use the same If statement or we could write the feeder as follows, feeding the consolidation and therefore all of the descendants of that consolidation.

['Actual', {'Units', 'Revenue'}] => ['Fed Forecast Versions'];

If we were to add another element to the ‘Fed Forecast Versions’ consolidation – in the example below element Forecast3 we can see that the feeder is not set . This is because at the time the feeder was set (when the rule was saved or the string measure input in the source cube) the element was not part of the consolidation.

Conditional Feeders Summary

Conditional feeders is therefore a broad term that can be used to describe feeders that contain one (or more) of the following:

  • An IF clause in a feeder statement to determine an element or cube name
  • A lookup to an attribute or cube value to determine an element or cube to be the fed
  • A feeder to or from a consolidated element

Conditional feeders are generally used to reduce overfeeding but should be used with caution as there are a number of significant drawbacks and risks involved. When building a model, care should be taken to weigh up the benefits and risks of conditional feeders.

When Does A Feeder Get Set?

It is important to understand, especially so when dealing with conditional feeders, when a feeder is set and when the ‘chain’ of feeders is re-evaluated.

There are a number of triggers for a feeder to be set:

  • When the rule file is updated and saved
  • When the turbo integrator function ‘CubeProcessFeeders’ is executed for a specified cube
  • When a TM1 Server is started (and persistent feeders is turned off or valid feeder file is not found)
  • When numeric data is entered into a numeric cell for the first time (i.e. the cell goes from NULL to a value)
  • When string data is entered or changed in a string cell

Note the difference between numeric and string feeders. Numeric cells only ‘fire’ once while string cells can ‘fire’ multiple times.

Common Issues With Conditional Feeders

Underfeeding

As can be seen from the simple examples above there are a number of instances when conditional feeders can result in underfeeding and incorrect consolidation calculations.

The most common issues being:

  • Attributes or lookup values are not the ‘source’ of the feeder and changes in those values do not cause the feeder to be re-set
  • Once a numeric cell has ben used for a feeder it is not evaluated again, re-entering data does not cause the feeder to be re-set
  • A change in dimension structure does not cause a feeder statement to be re-evaluated
  • If one link in a feeder chain is already fed the chain will stop at that cell

Overfeeding⚠️

Where Conditional Feeders are traditionally used to reduce overfeeding care must be taken not to inadvertently overfeed. Where conditional (directional) based on attributes or data is used it is possible for an end user to change data which results in an inefficient feeder and overfeeding.

In the following article, you will learn a technique to quickly troubleshoot overfeeding and underfeeding:

Config Settings related to feeders

There are a number of tm1s.cfg settings that effect feeders, and specifically conditional feeders.

Persistent Feeders

This setting improves server load times by storing feeders in file on disk. When a server loads this file is read rather than evaluating all feeder statements, this saves time during a server load.

The interaction with conditional feeders is such that a server restart does not remove and reset all feeders (as detailed above) and therefore a server restart cannot be used as a process to re-evaluate conditional feeders based on current data – the feeders will be the same as when the server was shut down.

If there is a requirement to re-evaluate all feeders you must delete the .feeder files during a server restart to force feeders to be re-evaluated on start up. This can increase the start up time for a server with a large number of feeders.

Turning on the tm1s.cfg setting will improve server load times for TM1 instances with a large amount of feeders (IBM estimate servers with load times of over 5 minutes would benefit). The trade off is Persistent Feeders do not get removed when a server restarts and so, over time, the number of fed cells will only increase and could lead to overfeeding.

Force Reevaluation Of Feeders For Fed Cells On Data Change

This setting changes the behaviour of fed cells for conditional and chain feeders. The tm1s.cfg setting ForceReevaluationOfFeedersForFedCellsOnDataChange=T will force more feeder evaluations for cells and will have a performance impact when data is loaded or input.

MTFeeders

Turning on the tm1s.cfg setting will apply multi threaded processing of feeders when a rule file is saved or the turbo integrator function CubeProcessFeeders is called. When MTFeeders.AtStartup is also enabled multi threaded processing of feeders is also applied on server start up.

MTFeeders.AtStartup is required to enable multi threaded processing of feeders on a server restart. Using this configuration setting will disable the tm1s.cfg setting MaximumCubeLoadThreads during start up.

MTFeeders improves the time taken to process feeders – on a rule save or turbo integrator function (or start up as described above) but as the feeders are processed in parallel the processing order may result in dependencies and conditions being incorrectly evaluated and feeders set incorrectly. It also increases memory usage significantly.

When MTFeeders is enabled the order in which feeders are processed is not managed – and as such enabling MTFeeders is not supported when conditional feeders are present in a model.

Parallel Loading

Where data is loaded into a cube through a turbo integrator process TM1 traditionally used a single thread to load and commit data – and process feeders associated with that data entry. Since parallel loading – executing TI processes on multiple threads – is available (through RunProcess, Hustle or RushTI) care should be taken to ensure the integrity of the order data input with regards to conditional feeders.

Where conditional feeders rely on attributes or cube data to inform the feeder of the target for the feeder that information must be present at the time of data entry in the source cell. In instances where data is loaded in parallel it may not be possible to ensure that data is loaded and committed before the feeder is evaluated.

READ MORE:

Related content

Loading related content