Download
language Essence 1.3

$ Problem Wagner-Whitin Distribution
$
$ Problem details available at http://www.csplib.org/Problems/prob040/
$
$ Based on the Essence model 'DistributionWagnerWhitin.essence' by Andrew Martin, modified by Peter Nightingale
$
$ Licenced under CC-BY-4.0 : http://creativecommons.org/licenses/by/4.0/

$ in this model, rather than define multiple levels, children of each node are defined explicitly

given numNodes : int(1..)

$ leaves are always first numLeaves nodes
$ leaves cannot have any children
given numLeaves : int(1..)

$ period 0 is empty, all stock is 0
given numPeriods : int(1..)

$ used to provide bound to output
given maxStock : int(1..)

letting dNodes be domain int(1..numNodes)
letting dLeaves be domain int(1..numLeaves)
letting dAllPeriods be domain int(0..numPeriods)
letting dPeriods be domain int(1..numPeriods)

given holdingCost : matrix indexed by [dNodes] of int(0..)

given procCost : matrix indexed by [dNodes] of int(0..)

given demand : matrix indexed by [dLeaves, dPeriods] of int(0..)

$ used to determine where supply comes goes to
given children : matrix indexed by [dNodes] of set of dNodes

$  Where orders is defined it has a value 1..maxStock. When not defined, no order is made. 
find orders : function (dNodes, dPeriods) --> int(1..maxStock)

$ Auxiliary total function to keep track of stock at each node and period. 
find stock : function (total) (dNodes, dAllPeriods) --> int(0..maxStock)

$ minimising the cost
$ holding*stock per period per node plus proc if any orders were placed per period per node
minimising
    sum([ (holdingCost[i] * stock((i,t))) | t : dPeriods, i : dNodes]) +
    sum([ procCost[i] | (i,t) <- defined(orders)])

$ stock starts at 0 for all nodes. 
such that
    forAll i : dNodes .
        stock((i,0)) = 0

$ non-leaf constraints - orders coming from children must be fulfilled
such that
    forAll t : dPeriods .
        forAll i : int(numLeaves+1..numNodes) .
            stock((i,t)) = stock((i,t-1))
                            + sum([ orders((i,t)) | (i,t) in defined(orders) ])
                            - sum([ orders((m,t)) | m <- children[i], (m,t) in defined(orders) ])


$ leaf constraints - demands must be fullfilled
such that
    forAll t : dPeriods .
        forAll i : dLeaves .
            stock((i,t)) = stock((i,t-1))
                            + sum([ orders((i,t)) | (i,t) in defined(orders) ])
                            - demand[i][t]