Table Of Contents

Previous topic

managementcaller.py

Next topic

operationmemory.py

This Page

operationcaller.py

Operation caller - constructs operation model calls, executes the model calls and extracts model results.

class OperationModelCaller(Caller):

Class for executing operation models

Attributes:

  • arg: PredictionArg object:

    >>> execfile('simulation/caller/test/mocks4operationcaller.py')
    Called add_model('parameter_table', 'thinning_preference_order')
    Called add_model('cash_flow_table', 'timber_prices')
    Called add_model('operation', 'thinning')
    

def __init__(self, warnings):

Initialize model caller. Warnings attribute is boolean defining whether warnings will be processed:

>>> from minimock import Mock
>>> from simo.simulation.caller.operationcaller import OperationModelCaller
>>> oc = OperationModelCaller(True)
>>> oc.arg
>>> oc.add_error = Mock('add_error')

def execute(self, model, params, sim, depthind):

Construct and execute operation model call:

>>> oc.arg = dummyarg
>>> oc.execute(dummymodel, dummyparams,
...            dummysim, 0)
... 
Called Lexicon.get_level_name(1)
Called get_id(
    1,
    array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 2, 0, 0]]))
Called Simulator.queue_opres(
    array([[0, 0, 0, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0000'),
    [([{...}, {...}, {...}, {...}, {...}, {...}, {...}], None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])
Called Simulator.queue_opres(
    array([[0, 0, 1, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0001'),
    [([{...}, {...}, {...}, {...}, {...}], None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])
Called Simulator.queue_opres(
    array([[0, 0, 2, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0002'),
    [([{...}, {...}, {...}, {...}, {...},
       {...}, {...}, {...}, {...}], None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])

def _construct_call(self, model, params, sim):

Construct operation model call

Parameters

param -- cash flow table parameters
sim -- Simulator instance

def _assign_cash_flow_table(self, param, sim):

Assign cash flow table to operation arguments

Parameters

param -- cash flow table parameters
sim -- Simulator instance

def _assign_cash_flow_model(self, param, sim, depth):

Assign cash flow model to operation arguments

Parameters

param -- cash flow table parameters
sim -- Simulator instance
depth -- model chain depth, integer

def _assign_result_weights(self, weight):

Assign operation result weight variable values to arguments

Parameters

weight -- weight variable tuple

def _construct_variables(self, model, sim):

Get operation variable values from data and add to arguments

Parameters

model -- OperationModel instance
sim -- Simulator instance

def _construct_parameters(self, model, sim):

Get operation parameter values and add to arguments

Parameters

model -- OperationModel instance
sim -- Simulator instance

def _construct_result_structure(self, model, sim):

Construct operation result structure, which depends on the number of target objects and result variables

Parameters

model -- OperationModel instance
sim -- Simulator instance

def _get_number_of_targets(self, results, sim):

Get number of target objects for current operation

Parameters

results -- operation model result variables
sim -- Simulator instance

def _define_result_variables(self, results, sim):

Define number of operation result variables and construct result labels

Parameters

results -- operation model result variables
sim -- Simulator instance

def _classify_results(self, key, cfiers, sim, depth):

Generate operation result variable names by combining the variable name and the classifier name from the cash_flow table

def _get_classifiers(self, classifiers, table, sim, depthind):

Get values for the operation result classifiers of a single result variable from data or cash flow table classifiers. Return number of result classes for each object, classifier values, classifier names and classifier labels:

>>> dummyarg.target_index, toremove = dummysim.data.get_tind(1,0,1)
>>> dummyarg.num_of_targets = len(dummyarg.target_index)
>>> oc.arg = dummyarg
>>> ret = oc._get_classifiers(dummyclassifiers, dummysim, 0)
>>> nclasses, values, names, labels, torem, errdata = ret
>>> nclasses
array([6, 4, 8])
>>> values  
[([1, 2], True),
 ([array([ 1.,  2.,  3.]), array([ 4.,  5.]),
   array([ 6.,  7.,  8.,  9.])], False)]
>>> names
['assortment', 'SP']
>>> labels
[{1: 'log', 2: 'pulp'}, None]
>>> errdata
>>> dummysim.data = broken_dummydata
>>> ret = oc._get_classifiers(dummyclassifiers, dummysim, 0)
Called Lexicon.get_level_name(2)
>>> nclasses, values, names, labels, torem, errdata = ret
>>> nclasses
>>> values
>>> names
>>> labels
>>> errdata
(1, array([[0, 0, 0, 0, 3],
       [0, 0, 1, 3, 5],
       [0, 0, 2, 5, 9]]))
>>> dummysim.data = dummydata

def _set_labels(self, nc, values, labels, rlabs, i=0, row=[], obj=None):

Set result label keys for each target object. Classifier value can be either from data or from cash flow table classifiers. When some or all of the classifiers are from data, the number of classes between different target objects can be different. If classifiers are only cash flow classifiers, the number of classes between target objects is always the same. Result label data structure works also as operation result structure that is used to pass operation results from operation model to operation caller.

  • nc: number of classifiers
  • values: classifier values
  • labels: classifier value to label mappings in a dictionary
  • rlabs: list of lists for storing the classifier tuples for each object and result
  • i: classifier indice
  • row: label values from the previous classifiers
  • obj: ‘locked’ target object indice

One target object and three cash flow classifiers:

>>> values = [([1,2], True), ([1,2], True), ([1,2], True)]
>>> names = ['assortment', 'quality', 'size']
>>> labels = [{1: 'log', 2: 'pulp'},
...           {1: 'high', 2: 'low'},
...           {1: 'big', 2: 'small'}]
>>> rlabs = [{},{},{},]
>>> oc._set_labels(3, values, labels, rlabs)
>>> for i in rlabs[0]: print i
(1, 2, 1)
(2, 2, 2)
(1, 2, 2)
(2, 1, 1)
(1, 1, 2)
(2, 2, 1)
(2, 1, 2)
(1, 1, 1)

Two target objects and two cash flow classifiers:

>>> values = [([1,2], True), ([1,2,3], True)]
>>> names = ['assortment', 'quality']
>>> labels = [{1: 'log', 2: 'pulp'}, {1: 'high', 2: 'medium', 3: 'low'}]
>>> rlabs = [{},{},]
>>> oc.arg.num_of_targets = 2
>>> oc._set_labels(2, values, labels, rlabs)
>>> for i in rlabs[0]: print i
(1, 2)
(1, 3)
(2, 1)
(2, 3)
(2, 2)
(1, 1)

Two target objects, two cash flow classifiers, and one data classifier:

>>> import numpy
>>> values = [([1, 2], True),
...           ([1, 2], True),
...           ([numpy.array([1, 2, 3]), numpy.array([4, 5])], False)]
>>> names = ['assortment', 'quality', 'species']
>>> labels = [{1: 'log', 2: 'pulp'}, {1: 'high', 2: 'low'}, None]
>>> rlabs = [{},{},]
>>> oc._set_labels(3, values, labels, rlabs)
>>> for i in rlabs[0]: print i
(1, 2, 1)
(2, 2, 2)
(1, 1, 3)
(2, 1, 1)
(1, 2, 3)
(1, 2, 2)
(2, 1, 2)
(2, 2, 3)
(1, 1, 1)
(1, 1, 2)
(2, 1, 3)
(2, 2, 1)
>>> for i in rlabs[1]: print i
(1, 2, 5)
(2, 2, 5)
(1, 1, 5)
(2, 1, 4)
(2, 2, 4)
(2, 1, 5)
(1, 2, 4)
(1, 1, 4)

Two target objects, two data classifiers, and one cash flow classifier:

>>> values = [([1,2],True),
...           ([numpy.array([1,2,3]), numpy.array([4,5])],False),
...           ([numpy.array([7,8]), numpy.array([9,10])],False)]
>>> names = ['assortment', 'species', 'site']
>>> labels = [{1: 'log', 2: 'pulp'}, None, None]
>>> rlabs = [{},{},]
>>> oc._set_labels(3, values, labels, rlabs)
>>> for i in rlabs[0]: print i
(2, 1, 7)
(1, 2, 8)
(1, 3, 8)
(1, 1, 7)
(1, 1, 8)
(1, 2, 7)
(2, 1, 8)
(1, 3, 7)
(2, 3, 7)
(2, 2, 7)
(2, 2, 8)
(2, 3, 8)
>>> for i in rlabs[1]: print i
(2, 4, 9)
(1, 4, 9)
(2, 5, 9)
(2, 5, 10)
(1, 5, 10)
(1, 4, 10)
(2, 4, 10)
(1, 5, 9)

def _assign_param_table(self, sim, depth):

Assign parameter table values to arguments

def _constr_data(self, model, sim):

Construct operation input data structures and add to arguments. Go through each operation input data level and construct one level at a time for all target objects. When constructing data for operation top level (should be the same as current model chain evaluation level), only normal target index is needed. When the data level is different from top level, also a mapping from top level to the current level’s parent level is needed. Also the indices of data level objects is needed. If the current level and top level have data levels in between (at least three data levels total), the values should be get from data with a targetindex that has a mapping from top level to the data level.

def _constr_data_level(self, tind, values, child, oind):

Construct operation input data structure for all target object on given level. Number of rows is the number of target objects on the level. Number of columns is number of data attributes +3 if level is operation top level, and +4 otherwise.

Data columns are as follows: 1. iteration 2. branch 3. object indice 4. parent indice if level is not operation evaluation level, otherwise first attribute 4. or 5. to n - 1. attribute values n. operation treatment tag

Construct data level structure for a level without parent level:

>>> oc.arg.num_of_targets = 3
>>> tind = numpy.array([[0,0,1,0,4],
...                     [0,0,2,4,6],
...                     [0,1,5,6,9]], dtype=int)
>>> values = numpy.array([[1.1,1.2,1.3],
...                       [2.1,2.2,2.3]], dtype=float)
>>> data = oc._constr_data_level(tind, values, False, None)
>>> print data
[[ 0.   0.   1.   1.1  2.1  0. ]
 [ 0.   0.   2.   1.2  2.2  0. ]
 [ 0.   1.   5.   1.3  2.3  0. ]]

Construct data level structure for a level with operation top level as the parent level:

>>> oind = numpy.array([[0,0,5],
...                     [0,0,6],
...                     [0,0,7],
...                     [0,0,8],
...                     [0,0,9],
...                     [0,1,10],
...                     [0,1,15],
...                     [0,2,16],
...                     [0,3,17]], dtype=int)
>>> values = numpy.array([[1.11,1.12,1.13,1.14,1.25,1.26,1.37,1.38,1.39],
...                       [2.11,2.12,2.13,2.14,2.25,2.26,2.37,2.38,2.39]],
...                      dtype=float)
>>> data = oc._constr_data_level(tind, values, True, oind)
>>> print data
[[  0.     0.     5.     1.     1.11   2.11   0.  ]
 [  0.     0.     6.     1.     1.12   2.12   0.  ]
 [  0.     0.     7.     1.     1.13   2.13   0.  ]
 [  0.     0.     8.     1.     1.14   2.14   0.  ]
 [  0.     0.     9.     2.     1.25   2.25   0.  ]
 [  0.     1.    10.     2.     1.26   2.26   0.  ]
 [  0.     1.    15.     5.     1.37   2.37   0.  ]
 [  0.     2.    16.     5.     1.38   2.38   0.  ]
 [  0.     3.    17.     5.     1.39   2.39   0.  ]]

Construct data level structure when level’s parent level is not the operation top level. Pass also pind (mapping to parent objects for the data level) to the method:

>>> tind = numpy.array([[0,0,5,0,3],
...                     [0,0,6,3,8],
...                     [0,0,7,8,10],
...                     [0,0,8,10,15],
...                     [0,0,9,15,16],
...                     [0,0,10,16,20],
...                     [0,0,15,20,22],
...                     [0,0,16,22,27],
...                     [0,0,17,27,29]], dtype=int)
>>> values = numpy.array([numpy.arange(29)], dtype=float)
>>> oind = numpy.transpose([numpy.zeros(29, dtype=int),
...                         numpy.zeros(29, dtype=int),
...                         numpy.arange(3,32)])
>>> data = oc._constr_data_level(tind, values, True, oind)
>>> print data
[[  0.   0.   3.   5.   0.   0.]
 [  0.   0.   4.   5.   1.   0.]
 [  0.   0.   5.   5.   2.   0.]
 [  0.   0.   6.   6.   3.   0.]
 [  0.   0.   7.   6.   4.   0.]
 [  0.   0.   8.   6.   5.   0.]
 [  0.   0.   9.   6.   6.   0.]
 [  0.   0.  10.   6.   7.   0.]
 [  0.   0.  11.   7.   8.   0.]
 [  0.   0.  12.   7.   9.   0.]
 [  0.   0.  13.   8.  10.   0.]
 [  0.   0.  14.   8.  11.   0.]
 [  0.   0.  15.   8.  12.   0.]
 [  0.   0.  16.   8.  13.   0.]
 [  0.   0.  17.   8.  14.   0.]
 [  0.   0.  18.   9.  15.   0.]
 [  0.   0.  19.  10.  16.   0.]
 [  0.   0.  20.  10.  17.   0.]
 [  0.   0.  21.  10.  18.   0.]
 [  0.   0.  22.  10.  19.   0.]
 [  0.   0.  23.  15.  20.   0.]
 [  0.   0.  24.  15.  21.   0.]
 [  0.   0.  25.  16.  22.   0.]
 [  0.   0.  26.  16.  23.   0.]
 [  0.   0.  27.  16.  24.   0.]
 [  0.   0.  28.  16.  25.   0.]
 [  0.   0.  29.  16.  26.   0.]
 [  0.   0.  30.  17.  27.   0.]
 [  0.   0.  31.  17.  28.   0.]]

def _construct_level_data(self, maplevel, depth, datalevel, parent, objs, sim, model):

Collect data for the model from the specified level

>>> oc._construct_level_data(1, 0, None, 0, {0: None}, dummysim,
...                          dummymodel)
Called OperationArg.set_data(
    array([[ 0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  1.,  2.,  0.],
       [ 0.,  0.,  2.,  3.,  0.]]),
    array([[0, 1],
       [1, 2],
       [2, 3]]),
    1,
    [1])
True
>>> # Temporary swap to test no data situation.
>>> orig_get_value = dummysim.data.get_value
>>> def get_value(*args): return None, [[]]
>>> dummysim.data.get_value = get_value
>>> oc._construct_level_data(1, 0, None, 0, {0: None}, dummysim,
...                          dummymodel)
Called Lexicon.get_level_name(1)
Called get_id(
    1,
    array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 2, 0, 0]]))
False
>>> dummysim.data.get_value = orig_get_value

def _call_model(self, model, sim):

Call the operation operation model or the cash_flow function

def _evaluate_cash_flow_operation(self, sim):

Evaluate cash flow operation

def _extract_results(self, objs, model, sim):

Extract operation model results

def _process_cash_flow(self, sim):

Process and store operation cash flow:

>>> oc._process_cash_flow(dummysim)
Called Lexicon.get_level_name(1)
Called OperationArg.get_cash_flow()
Called OperationArg.get_weights()
Called get_id(
    1,
    array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 2, 0, 0]]))
Called Simulator.queue_opres(
    array([[0, 0, 0, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0000'),
    [([{'cash_flow': 3.0}], None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])
Called Simulator.queue_opres(
    array([[0, 0, 1, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0001'),
    [([{'cash_flow': 4.0}], None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])
Called Simulator.queue_opres(
    array([[0, 0, 2, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0002'),
    [([{'cash_flow': 3.0}], None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])

def _process_oper_results(self, sim):

Process operation results and store them to operation result database:

>>> oc.arg.num_of_targets = 3
>>> oc.arg.num_of_results = numpy.array([[4,2,6], [4,2,6]], dtype=int)
>>> oc.arg.result_variables = [('operation_result', 'volume',
...                            ('SP', 'assortment', 'stand_number'), 'scalar', True),
...                            ('operation_result', 'income',
...                            ('SP', 'assortment', 'stand_number'), 'scalar', True)]
>>> oc._process_oper_results(dummysim, False)
... 
Called Lexicon.get_level_name(1)
Called OperationArg.get_weights()
Called OperationArg.get_results()
Called get_id(
    1,
    array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 2, 0, 0]]))
Called Simulator.queue_opres(
    array([[0, 0, 0, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0000'),
    [([{'volume': 9.8..., 'assortment': 1, 'SP': 1, u'stand_number': 'kuvio1', 'income': 99.0},
       {'volume': 10.8..., 'assortment': 2, 'SP': 1, u'stand_number': 'kuvio1', 'income': 108.0},
       {'volume': 12.6..., 'assortment': 2, 'SP': 2, u'stand_number': 'kuvio1', 'income': 126.0},
       {'volume': 11.6..., 'assortment': 1, 'SP': 2, u'stand_number': 'kuvio1', 'income': 117.0}],
       None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])
Called Simulator.queue_opres(
    array([[0, 0, 1, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0001'),
    [([{'volume': 11.1..., 'assortment': 3, 'SP': 2, u'stand_number': 'kuvio2', 'income': 112.0},
       {'volume': 10.6..., 'assortment': 3, 'SP': 1, u'stand_number': 'kuvio2', 'income': 106.0}],
       None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])
Called Simulator.queue_opres(
    array([[0, 0, 2, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0002'),
    [([{'volume': 6.9..., 'assortment': 4, 'SP': 2, u'stand_number': 'kuvio3', 'income': 69.0},
       {'volume': 7.2..., 'assortment': 5, 'SP': 2, u'stand_number': 'kuvio3', 'income': 72.0},
       {'volume': 6.5..., 'assortment': 5, 'SP': 1, u'stand_number': 'kuvio3', 'income': 66.0},
       {'volume': 6.2..., 'assortment': 4, 'SP': 1, u'stand_number': 'kuvio3', 'income': 63.0}],
       None)],
    'dummy_db_name',
    'dummy_db_group',
    'dummy notes',
    ['dummy material 1', 'dummy material 2'])

Process operation results when variable type is ‘date_array’:

>>> oc.arg = dummyarg2
>>> oc._process_oper_results(dummysim, False) 
Called Lexicon.get_level_name(1)
Called OperationArg.get_weights()
Called OperationArg.get_results()
Called get_id(
    1,
    array([[0, 0, 1, 0, 0],
       [0, 0, 2, 0, 0],
       [0, 0, 3, 0, 0]]))
Called Simulator.queue_opres(
    array([[0, 0, 1, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0000'),
    [([{'C_flow': 1000}], 0),
     ([{'C_flow': 1100}], 1),
     ([{'C_flow': 1500}], 5),
     ([{'C_flow': 1700}], 7)],
    'dummy_db_name2',
    'dummy_db_group2',
    'dummy notes2',
    ['dummy material 21', 'dummy material 22'])
Called Simulator.queue_opres(
    array([[0, 0, 2, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0001'),
    [([{'C_flow': 2800}], 8),
     ([{'C_flow': 2900}], 9),
     ([{'C_flow': 2200}], 2),
     ([{'C_flow': 2400}], 4)],
    'dummy_db_name2',
    'dummy_db_group2',
    'dummy notes2',
    ['dummy material 21', 'dummy material 22'])
Called Simulator.queue_opres(
    array([[0, 0, 3, 0, 0]]),
    (0, 0, 'comp_unit', 'UID0002'),
    [([{'C_flow': 3100}], 1),
     ([{'C_flow': 4000}], 10),
     ([{'C_flow': 5000}], 20),
     ([{'C_flow': 3500}], 5)],
    'dummy_db_name2',
    'dummy_db_group2',
    'dummy notes2',
    ['dummy material 21', 'dummy material 22'])

def _process_data_results(self, model, sim):

Process operation results that affect the simulation data

def _process_data(self, model, sim):

Process data objects that are affected by the operation model

def _process_simulation_effects(self, params, sim):

Process simulation effects caused by the operation model