.. _aggregationcaller-py: #################### aggregationcaller.py #################### ************************************* class AggregationModelCaller(Caller): ************************************* Class for constructing and executing aggregation model calls Attributes: - arg: AggregationArg object def __init__(self, deterministic=False): ======================================== Initialize model caller:: >>> from simo.simulation.caller.aggregationcaller import AggregationModelCaller >>> import numpy >>> from minimock import Mock >>> ac = AggregationModelCaller() >>> ac.arg def execute(self, model, params, sim, depth): ============================================= Execute aggregation model:: >>> def mfunc(arg): ... arg.results = numpy.array([1.0, None], dtype=float) >>> sim = Mock('Sim') >>> class Data(object): ... def __init__(self): ... self.active_data_level = 1 ... self.tind = [numpy.array([[0,0,0,0,3], ... [0,0,1,3,5]], dtype=int), ... numpy.array([[0,0,0,0,1], ... [0,0,1,1,2], ... [0,0,2,2,3], ... [0,0,3,3,4], ... [0,0,4,4,5]], dtype=int), ... numpy.array([[0,0,0,0,1], ... [0,0,1,1,2], ... [0,0,2,2,3], ... [0,0,3,3,4]], dtype=int)] ... self.vals = [numpy.array([[2.1, 2.2, 2.3, 5.1, 5.2]], ... dtype=float), ... numpy.array([[3.1, 3.2, 3.3, 6.2, 6.2]], ... dtype=float), ... numpy.array([[4.1, 4.2, 4.3, 7.2, 7.2]], ... dtype=float)] ... def get_value(self, tind, attrs, forced=False): ... if attrs == [0]: ... return self.vals[0], None ... elif attrs == [1]: ... return self.vals[1], None ... elif attrs == [2]: ... return self.vals[2], None ... else: ... return self.vals[0][0], None ... def get_tind(self, lev, depth, dlev=None, tlev=None, v4all=None, ... valuelevel=None, order=None): ... if dlev is not None: ... tlev = dlev ... else: ... tlev = lev ... self.active_data_level = tlev ... self.active_dataobjects = self.tind[tlev] ... return self.tind[tlev], set([]) ... def get_active(self): ... pass ... def set_active(self, active): ... pass >>> data = Data() >>> data.set_value = Mock('set_value') >>> linkage = Mock('Linkage') >>> linkage.links = {(0,0):{(0,0):{1:[0, 1, 2], 2:[0, 1, 2]}, ... (0,1):{1:[3, 4], 2:[3,4]}, ... (1,0):{0:[0], 2:[0]}, ... (1,1):{0:[0], 2:[1]}, ... (1,2):{0:[0], 2:[2]}, ... (1,3):{0:[0], 2:[3]}, ... (1,4):{0:[0], 2:[]}, ... (2,0):{0:[0], 1:[0]}, ... (2,1):{0:[0], 1:[1]}, ... (2,2):{0:[0], 1:[2]}, ... (2,3):{0:[0], 1:[3]}, ... }} >>> data.linkage = linkage >>> model = Mock('Model') >>> model.name = 'sum' >>> model._v_func = mfunc >>> op1 = Mock('Operand') >>> op1.type = 'variable' >>> op1.variable = (1, 0) >>> op1.weight = None >>> op1.default_value = None >>> op1.default_weight = None >>> op2 = Mock('Operand') >>> op2.type = 'variable' >>> op2.variable = (0, 1) >>> op2.weight = None >>> op2.default_value = None >>> op2.default_weight = None >>> params = Mock('Parameters') >>> params.through_level = 1 >>> params.target_ind = (0,3) >>> params.operands = [op1, op2] >>> params.condition = None >>> params.scalar = True >>> logger = Mock('Logger') >>> sim.level = 1 >>> sim.data = data >>> sim.logger = logger >>> sim.log_name = 'test-log' Execute model with two operands and no weights (only one value set due to hardwiring the model results to [1.0, None] always:: >>> ac.execute(model, params, sim, 0) # doctest: +ELLIPSIS Called set_value(0, array([[0, 0, 0, 0, 3]]), 3, array([ 1.]), 'sum') >>> ac._construct_call() True >>> ac.arg.target_index array([[0, 0, 0, 0, 3], [0, 0, 1, 3, 5]]) >>> ac.arg.oper_target_index # doctest: +NORMALIZE_WHITESPACE deque([array([[0, 0, 0, 0, 1], [0, 0, 1, 1, 2], [0, 0, 2, 2, 3], [0, 0, 3, 3, 4], [0, 0, 4, 4, 5]]), array([[0, 0, 0, 0, 3], [0, 0, 1, 3, 5]])]) >>> ac.arg.oper_data_level deque([1, 0]) >>> ac.arg.values # doctest: +NORMALIZE_WHITESPACE deque([array([ 2.1, 2.2, 2.3, 5.1, 5.2]), array([ 3.1, 3.2, 3.3, 6.2, 6.2])]) Execute a vectorized aggregation model:: >>> op1.scalar = False >>> params.operands = [op1] >>> params.condition = None >>> params.through_level = 1 >>> params.target_ind = (0,[3]) >>> ac.execute(model, params, sim, 0) Called set_value(0, array([[0, 0, 0, 0, 3]]), [3], array([ 1.]), 'sum') Execute a model with one operand and no weights :: >>> params.operands = [op1] >>> ac._construct_call() True >>> ac.arg.target_index array([[0, 0, 0, 0, 3], [0, 0, 1, 3, 5]]) >>> ac.arg.oper_target_index # doctest: +NORMALIZE_WHITESPACE deque([array([[0, 0, 0, 0, 1], [0, 0, 1, 1, 2], [0, 0, 2, 2, 3], [0, 0, 3, 3, 4], [0, 0, 4, 4, 5]])]) >>> ac.arg.oper_data_level deque([1]) >>> ac.arg.values # doctest: +NORMALIZE_WHITESPACE deque([array([ 2.1, 2.2, 2.3, 5.1, 5.2])]) Execute a model with an aggregation condition :: >>> params.condition = [('data', (1, 0, True), (None, None)), ... ('value', 2.3), ... ('eq', (lambda a,b: a==b))] >>> params.lowest_operand_level = 1 >>> ac._construct_call() True >>> ac.arg.target_index array([[0, 0, 0, 0, 3], [0, 0, 1, 3, 5]]) >>> ac.arg.oper_target_index # doctest: +NORMALIZE_WHITESPACE deque([array([[0, 0, 0, 0, 1], [0, 0, 1, 1, 2], [0, 0, 2, 2, 3], [0, 0, 3, 3, 4], [0, 0, 4, 4, 5]])]) >>> ac.arg.oper_data_level deque([1]) >>> ac.arg.values # doctest: +ELLIPSIS deque([array([ ..., 2.3, ...])]) Execute a model with an aggregation condition for a different level from the operand:: >>> op3 = Mock('Operand') >>> op3.type = 'variable' >>> op3.variable = (2, 2) >>> op3.weight = None >>> op3.default_value = None >>> op3.default_weight = None >>> params.operands = [op3] >>> params.condition = [('data', (1, 0, True), (None, None)), ... ('value', 2.3), ... ('eq', (lambda a,b: a==b))] >>> params.lowest_operand_level = 2 NB! The next one is failing although it shoudn't. Make it work... ac._construct_call() True ac.arg.target_index array([[0, 0, 0, 0, 3], [0, 0, 1, 3, 5]]) ac.arg.oper_target_index # doctest: +NORMALIZE_WHITESPACE deque([array([[0, 0, 0, 0, 1], [0, 0, 1, 1, 2], [0, 0, 2, 2, 3], [0, 0, 3, 3, 4]])]) ac.arg.oper_data_level deque([2]) ac.arg.values deque([array([ NaN, NaN, 4.3, NaN, 7.2])]) def _construct_call(self): ========================== Construct an aggregation model call. def _add_operand(self, targetlev, throughlev, tind, oper): ========================================================== Add a single operand to aggregation arguments. Parameters: - targetlev -- target level indice - throughlev -- through level indice - tind -- target index, 2d numpy array - oper -- aggregation operand object def _call_model(self): ====================== Call aggregation model and extract results.