def test_order_signals_noreads(): # test with ops that don't have any reads inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i]]) for i in range(5)), tuple(dummies.Op(sets=[inputs[5 + i]]) for i in range(5)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:5], sigs) assert ordered(new_plan[0], sigs)
def test_order_signals_disjoint(): # disjoint reads inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i]]) for i in range(5)), tuple(dummies.Op(reads=[inputs[5 + i]]) for i in range(5))] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:5], sigs) assert contiguous(inputs[5:], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs)
def test_order_signals_partial3(): inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i]]) for i in [0, 1, 2, 3]), tuple(dummies.Op(reads=[inputs[i]]) for i in [0, 4, 7]), tuple(dummies.Op(reads=[inputs[i]]) for i in [5, 6, 7])] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:4], sigs) assert contiguous([inputs[0], inputs[4], inputs[7]], sigs) assert contiguous(inputs[5:8], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs) assert ordered(new_plan[2], sigs)
def test_order_signals_partial(): # partially overlapping reads # two overlapping sets (A, A/B, B) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i]]) for i in range(4)), tuple(dummies.Op(reads=[inputs[2 + i]]) for i in range(4))] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:4], sigs) assert contiguous(inputs[2:6], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs)
def test_order_signals_subset(): # ordering in which one read block is fully nested within another # (A, A/B) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i]]) for i in range(10)), tuple(dummies.Op(reads=[inputs[4 - i]]) for i in range(5)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:5], sigs) assert contiguous(inputs[:10], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs)
def test_order_signals_multiread_complex(): # signal sorting with operators that read from multiple signals # (overlapping) # (C, B/C, A) (where A and B are from the same op) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i], inputs[5 + i]]) for i in range(3)), tuple(dummies.Op(reads=[inputs[i + 5]]) for i in range(5)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:3], sigs) assert contiguous(inputs[5:], sigs) assert contiguous(inputs[5:8], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs)
def test_order_signals_duplicate_read_blocks(): # test that order_signal prioritizes read blocks that are duplicated in # multiple op groups inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i], inputs[5 + i]]) for i in range(3)), tuple(dummies.Op(reads=[inputs[i], inputs[5 + i]]) for i in range(3)), tuple(dummies.Op(reads=[inputs[5 + i], inputs[4 - i]]) for i in range(5))] sigs, new_plan = order_signals(plan) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs) assert (ordered(new_plan[2], sigs, block=0) or ordered(new_plan[2], sigs, block=1)) assert not ordered(new_plan[2], sigs)
def test_order_signals_duplicate_read_blocks(): # test that order_signal prioritizes read blocks that are duplicated in # multiple op groups inputs = [DummySignal(label=str(i)) for i in range(10)] plan = [ tuple(DummyOp(reads=[inputs[i], inputs[5 + i]]) for i in range(3)), tuple(DummyOp(reads=[inputs[i], inputs[5 + i]]) for i in range(3)), tuple(DummyOp(reads=[inputs[5 + i], inputs[4 - i]]) for i in range(5)) ] sigs, new_plan = order_signals(plan) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs) assert (ordered(new_plan[2], sigs, block=0) or ordered(new_plan[2], sigs, block=1)) assert not ordered(new_plan[2], sigs)
def test_order_signals_neuron_states(): # test with neuron states (should be treated as reads) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(SimNeurons(None, inputs[0], inputs[1], states=[x]) for x in inputs[2::2]), tuple(SimNeurons(None, inputs[0], inputs[1], states=[x]) for x in inputs[3::2])] sigs, new_plan = order_signals(plan) assert contiguous(inputs[2::2], sigs) assert contiguous(inputs[3::2], sigs) # note: block=0 is just a single signal, so it's always "ordered" assert ordered(new_plan[0], sigs, block=1) assert ordered(new_plan[1], sigs, block=1)
def test_order_signals_partial2(): # more complex partial overlap # (A, A/B, B/C, C) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i]]) for i in range(5)), tuple(dummies.Op(reads=[inputs[2 + i]]) for i in range(4)), tuple(dummies.Op(reads=[inputs[5 + i]]) for i in range(3)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:5], sigs) assert contiguous(inputs[5:8], sigs) assert contiguous(inputs[2:6], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs) assert ordered(new_plan[2], sigs)
def test_order_signals_duplicates(): # test where read blocks contain duplicate signals inputs = [dummies.Signal(label=str(i)) for i in range(4)] plan = [ tuple(dummies.Op(reads=[inputs[0]]) for _ in range(2)) + (dummies.Op(reads=[inputs[2]]),), tuple(dummies.Op(reads=[inputs[1]]) for _ in range(2)) + (dummies.Op(reads=[inputs[3]]),) ] sigs, new_plan = order_signals(plan) assert contiguous([inputs[0], inputs[2]], sigs) assert contiguous([inputs[1], inputs[3]], sigs) # note: not possible for these to be in increasing order, since they # contain duplicates assert not ordered(new_plan[0], sigs) assert not ordered(new_plan[1], sigs)
def test_order_signals_partial_unsatisfiable(): # this one will be unsatisfied, because after A it will pick A/B (because # B is the next biggest block). technically this could be satisfied if # we picked A/C next, but is there a way we could know that? # (A, A/B, A/C, B) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i]]) for i in range(7)), tuple(dummies.Op(reads=[inputs[5 + i]]) for i in range(5)), tuple(dummies.Op(reads=[inputs[i]]) for i in range(3)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:7], sigs) assert not contiguous(inputs[5:], sigs) assert contiguous(inputs[:3], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[2], sigs)
def test_order_signals_multiread_unsatisfiable(): # unsatisfiable order for block C (conflicts with A, which gets prioritized # because it is in a larger group) # (A, A/C, B, B/D) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[i], inputs[5 + i]]) for i in range(5)), tuple(dummies.Op(reads=[inputs[1 - i], inputs[5 + i]]) for i in range(2)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[:5], sigs) assert contiguous(inputs[5:], sigs) assert contiguous(inputs[:2], sigs) assert contiguous(inputs[5:7], sigs) assert ordered(new_plan[0], sigs) assert (ordered(new_plan[1], sigs, block=0) or ordered(new_plan[1], sigs, block=1)) assert not ordered(new_plan[1], sigs)
def test_order_signals_multiread_complex2(): # (B, B/A, A, A/C, C) (where A and B are from the same op) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[2 + i], inputs[i]]) for i in range(4)), tuple(dummies.Op(reads=[inputs[5 + i]]) for i in range(3)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[5:8], sigs) assert ordered(new_plan[1], sigs) # TODO: technically it is always possible to order both blocks properly, # but it requires you to know which of the two equally sized blocks should # have priority, and I'm not sure there's a way to determine that. assert contiguous(inputs[:4], sigs) or contiguous(inputs[2:6], sigs) assert ordered(new_plan[0], sigs, block=0) or ordered( new_plan[0], sigs, block=1)
def test_order_signals_lowpass(): # test that lowpass outputs are ordered as reads inputs = [dummies.Signal(label=str(i)) for i in range(10)] time = dummies.Signal() plan = [ tuple(SimProcess(Lowpass(0.1), inputs[i], inputs[i + 1], time, mode="update") for i in range(0, 4, 2)), tuple(SimProcess(Lowpass(0.1), inputs[i], inputs[i + 1], time, mode="update") for i in range(5, 9, 2))] sigs, new_plan = order_signals(plan) assert contiguous(inputs[1:5:2], sigs) assert contiguous(inputs[6:10:2], sigs) assert ordered(new_plan[0], sigs, block=1) assert ordered(new_plan[0], sigs, block=2) assert ordered(new_plan[1], sigs, block=1) assert ordered(new_plan[1], sigs, block=2)
def test_order_signals_multiread_complex2(): # (B, B/A, A, A/C, C) (where A and B are from the same op) inputs = [dummies.Signal(label=str(i)) for i in range(10)] plan = [ tuple(dummies.Op(reads=[inputs[2 + i], inputs[i]]) for i in range(4)), tuple(dummies.Op(reads=[inputs[5 + i]]) for i in range(3)), ] sigs, new_plan = order_signals(plan) assert contiguous(inputs[5:8], sigs) assert ordered(new_plan[1], sigs) # TODO: technically it is always possible to order both blocks properly, # but it requires you to know which of the two equally sized blocks should # have priority, and I'm not sure there's a way to determine that. assert (contiguous(inputs[:4], sigs) or contiguous(inputs[2:6], sigs)) assert (ordered(new_plan[0], sigs, block=0) or ordered(new_plan[0], sigs, block=1))
def test_order_signals_views(): base = dummies.Signal(shape=(6,), label="base") sig = dummies.Signal(shape=(7,), label="sig") sig2 = dummies.Signal(shape=(7,), label="sig2") views = [dummies.Signal(shape=(1,), base_shape=(5,), offset=1 + i, label="view_%d" % i) for i in range(5)] for v in views: v.base = base plan = [ (dummies.Op(reads=[base]), dummies.Op(reads=[views[1]]), dummies.Op(reads=[views[0]]), dummies.Op(reads=[sig2])), (dummies.Op(reads=[base]), dummies.Op(reads=[sig])), tuple(dummies.Op(reads=[views[i]]) for i in range(4, 2, -1)), (dummies.Op(reads=[views[4]]), dummies.Op(reads=[sig]))] sigs, new_plan = order_signals(plan) assert contiguous([base, sig, sig2], sigs) assert ordered(new_plan[0], sigs) assert ordered(new_plan[1], sigs) assert ordered(new_plan[2], sigs) assert ordered(new_plan[3], sigs)