masfaraud / BMSpy

Python Block-Model Simulator. An alternative to simulink in python.
GNU Lesser General Public License v3.0
222 stars 36 forks source link

Evaluate called once per output #26

Open pjadzinsky opened 5 years ago

pjadzinsky commented 5 years ago

I'm building Blocks with multiple outputs and I think I found a few issues (see #25)

  1. When more than one output, evaluate is called once per output. See the code below, the simplest case I could come up with. I would expect the print statements at the bottom to be all 0s. If implementing a block with more than one output Evaluate should be called only once per iteration and it should be the implementation's responsibility to compute all the outputs.
  2. BTW, evaluate should return a list with Block.n_outputs elements, right now this is not enforced.
class CountBlock(Block):
    def __init__(self, inputs, outputs):
        super(CountBlock, self).__init__(inputs, outputs, 1, 0)
        self.last_it = -1
        self.cnt = 0

    def Evaluate(self, it, ts):
        if it != self.last_it:
            # first time we see this 'it', reset counter
            self.cnt = 0
            self.last_it = it
        else:
            self.cnt += 1
        outputs = [self.cnt for _ in range(self.n_outputs)]
        return outputs

    def Label(self):
        return 'identity'

def test_count():
    input_1 = SignalFunction('input_1', lambda x: np.random.randn())
    input_2 = SignalFunction('input_2', lambda x: np.random.randn())

    output_1 = Variable('output_1')
    output_2 = Variable('output_2')
    output_3 = Variable('output_3')
    output_4 = Variable('output_4')
    output_5 = Variable('output_5')
    output_6 = Variable('output_6')

    counter_1 = CountBlock([input_1, input_2], [output_1])
    counter_2 = CountBlock([input_1, input_2], [output_2, output_3])
    counter_3 = CountBlock([input_1, input_2], [output_4, output_5, output_6])

    te = 10
    ns = 10
    model_1 = bms.DynamicSystem(te, ns, [counter_1])
    model_1.Simulate()
    model_2 = bms.DynamicSystem(te, ns, [counter_2])
    model_2.Simulate()
    model_3 = bms.DynamicSystem(te, ns, [counter_3])
    model_3.Simulate()
    print output_1.values
    print output_2.values
    print output_3.values
    print output_4.values
    print output_5.values
    print output_6.values