Scoring

Currently the following documentation for scoring is available:

Implementing Scoring Functions

Overview

This article describes how originally scoring functions were implemented and how it works now.

Originally, each scoring function needed to implement the ScoringFunction interface. The interface contains the following method signatures: startActivity,endActivity, startLeg, endLeg, agentStuck, addMoney, finish, getScore and reset. The documentation of these methods can be found in the source code of the ScoringFunction interface.

This implementation functions fine, but has a few shortcomings. The most important is, that the scoring functions based on this interface are not resuable and often not extendable.

The New Approach

Inorder not to change the current interface, the following approach was taken to make modular scoring functions possible: Five Interfaces have been introduced, which just subdivide the original ScoringFunction interface. These interface together with the methods are listed:

  • ActivityScoring: startActivity, endActivity
  • AgentStuckScoring: agentStuck
  • BasicScoring: reset, finish, getScore
  • LegScoring: startLeg, endLeg
  • MoneyScoring: addMoney

The basic idea is, that a scoring function can consist of an arbitrary number of summand terms. For example you can have scoring terms just depending on a static properties of agents or depnding on Activities. Furthermore a leg part could consist of several summand terms itself.

Every scoring term must implement the BasicScoring interface. A class called ScoringFunctionAccumulator is at the heart of this approach: The scores of all scoring terms registered with this accumulator, are summed up at the end of the iteration, making both reusable and extensible scoring functions easy to implement.

Scoring Function Example

Please look at the package org.matsim.scoring.charyparNagel for an example, which contains the following elements:

  • All scoring terms which make up the CharyparNagelScoringFunction
  • A ScoringFunctionFactory, for wiring up all scoring terms using the ScoringFunctionAccumulator

Although it would be possible to just put all scoring terms into one class by implementing all scoring term interfaces, this approach is not advisable, as it runs counter to the modularity principle (which was the reason for providing this new approach).

Hints and Pitfalls

  • The final score of an agent is the sum of all scoring terms (all getScoring methods are invoked at the end of the iteration, which are registered with the ScoringFunctionAccumulator).
  • Note: Although all ScoringFunction could have just inherited from this interface, this different approach was choosen for making it explicit what needs to be implemented.