def test_unsigned_fractional_formats(): format_ = Format(msb=0, lsb=-8, signed=False) assert format_.msb == 0 assert format_.lsb == -8 assert not format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(0, 255) assert format_.value_interval == interval(0.0, 0.99609375) assert format_.value_epsilon == 0.00390625 assert format_.to_qnotation() == 'uQ0.8' assert format_.to_pnotation() == 'u(0,-8)' with pytest.raises(ValueError): format_.represent(-0.1) mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.5) assert mantissa == 128 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1) assert not underflow assert overflow
def test_signed_fractional_formats(): format_ = Format(msb=0, lsb=-7, signed=True) assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(-128, 127) assert format_.value_interval == interval(-1.0, 0.9921875) assert format_.value_epsilon == 0.0078125 assert format_.to_qnotation() == 'Q1.7' assert format_.to_pnotation() == '(0,-7)' mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.5) assert mantissa == 64 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1) assert not underflow assert overflow
def test_unsigned_fixed_point_formats(): format_ = Format(msb=4, lsb=-4, signed=False) assert format_.msb == 4 assert format_.lsb == -4 assert not format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(0, 255) assert format_.value_interval == interval(0.0, 15.9375) assert format_.value_epsilon == 0.0625 assert format_.to_qnotation() == 'uQ4.4' assert format_.to_pnotation() == 'u(4,-4)' with pytest.raises(ValueError): format_.represent(-1) mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(8) assert mantissa == 128 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(16) assert not underflow assert overflow
def test_signed_fixed_point_formats(): format_ = Format(msb=3, lsb=-4, signed=True) assert format_.msb == 3 assert format_.lsb == -4 assert format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(-128, 127) assert format_.value_interval == interval(-8.0, 7.9375) assert format_.value_epsilon == 0.0625 assert format_.to_qnotation() == 'Q4.4' assert format_.to_pnotation() == '(3,-4)' mantissa, (underflow, overflow) = format_.represent(-2.25) assert mantissa == -36 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1e-6) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.5) assert mantissa == 8 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(8) assert not underflow assert overflow
def test_unsigned_integer_formats(): format_ = Format(msb=8, lsb=0, signed=False) assert format_.msb == 8 assert format_.lsb == 0 assert not format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(0, 255) assert format_.value_interval == interval(0, 255) assert format_.value_epsilon == 1 assert format_.to_qnotation() == 'uQ8.0' assert format_.to_pnotation() == 'u(8,0)' with pytest.raises(ValueError): format_.represent(-1) mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.1) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(256) assert not underflow assert overflow
def test_signed_scaled_integer_formats(): format_ = Format(msb=7, lsb=2, signed=True) assert format_.msb == 7 assert format_.lsb == 2 assert format_.signed assert format_.wordlength == 6 assert format_.mantissa_interval == interval(-32, 31) assert format_.value_interval == interval(-128, 124) assert format_.value_epsilon == 4 assert format_.to_qnotation() == 'Q8.-2' assert format_.to_pnotation() == '(7,2)' mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(1) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent( -17, rounding_method=rounding.nearest_integer ) assert mantissa == -4 # i.e. -16 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(128) assert not underflow assert overflow
def test_represent(): alu = FixedFormatArithmeticLogicUnit(format_=Q(7), rounding_method=nearest_integer, overflow_behavior=wraparound, allows_overflow=False, allows_underflow=False) assert alu.rinfo().eps == 0.0078125 assert alu.rinfo().min == -1 assert alu.rinfo().max == 0.9921875 r = alu.represent(0) assert r.mantissa == 0 assert r.format_ == alu.format_ r = alu.represent(0.25) assert r.mantissa == 32 assert r.format_ == alu.format_ r = alu.represent(-0.25) assert r.mantissa == -32 assert r.format_ == alu.format_ r = alu.represent(0.3) assert r.mantissa == 38 assert r.format_ == alu.format_ r = alu.represent(-0.3) assert r.mantissa == -38 assert r.format_ == alu.format_ r = alu.represent(interval(-0.75, 0.75)) assert r.mantissa == interval(-96, 96) assert r.format_ == alu.format_
def test_interval_membership(scalar): iv_a = interval(scalar(-1), scalar(1)) assert iv_a in iv_a iv_b = interval(scalar(-2), scalar(2)) assert iv_a in iv_b assert iv_b not in iv_a iv_c = interval(scalar(0), scalar(2)) assert iv_c not in iv_a assert iv_c in iv_b iv_d = interval(scalar(-5), scalar(0)) assert iv_d not in iv_a assert iv_d not in iv_b assert iv_d not in iv_c s_a = scalar(0) assert s_a in iv_a assert s_a in iv_b assert s_a in iv_c assert s_a in iv_d s_b = scalar(2) assert s_b not in iv_a assert s_b in iv_b assert s_b in iv_c assert s_b not in iv_d s_c = scalar(5) assert s_c not in iv_a assert s_c not in iv_b assert s_c not in iv_c assert s_c not in iv_d
def computation_error_bounds(self, input_ranges, state_ranges): state_ranges = state_ranges or [] domain = self.algorithm.define( inputs=tuple(error_bounded(fixed(r)) for r in input_ranges), states=tuple(error_bounded(fixed(r)) for r in state_ranges), parameters=tuple(self.parameters)) error_bounds = [] unit = ProcessingUnit.active() with unit.trace() as trace: scope = dict(domain) compare = type(unit).compare for change in self.algorithm.step(scope): if len(trace) > 0: if any(func is not compare for func, *_ in trace): for value in change.values(): if isinstance(value, tuple): error_bounds.extend(elem.error_bounds for elem in value) else: error_bounds.append(value.error_bounds) trace.clear() scope.update(change) scope.update(domain) if not error_bounds: return interval(0) if len(error_bounds) == 1: return error_bounds[0] return interval( lower_bound=np.c_[[eb.lower_bound for eb in error_bounds]], upper_bound=np.c_[[eb.upper_bound for eb in error_bounds]])
def value_interval(self): with mpmath.workprec(self.wordlength + 1): # wl bits is enough if self.signed: return interval( -mpmath.ldexp(1, self.msb), mpmath.ldexp(1, self.msb) - mpmath.ldexp(1, self.lsb)) return interval( 0, mpmath.ldexp(1, self.msb) - mpmath.ldexp(1, self.lsb))
def test_best_formats(): mantissa, format_ = Format.best( 0, wordlength=8, signed=True ) assert mantissa == 0 assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed mantissa, format_ = Format.best( 0.5, wordlength=8, signed=True ) assert mantissa == 64 assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed mantissa, format_ = Format.best( 1.0, wordlength=8, signed=True ) assert mantissa == 64 assert format_.msb == 1 assert format_.lsb == -6 assert format_.signed mantissa, format_ = Format.best( -1.0, wordlength=8, signed=True ) assert mantissa == -128 assert format_.msb == 0 assert format_.lsb == -7 assert format_.signed mantissa, format_ = Format.best( 12.0, wordlength=8, signed=True ) assert mantissa == 96 assert format_.msb == 4 assert format_.lsb == -3 assert format_.signed mantissa, format_ = Format.best( 1200.0, wordlength=8, signed=True ) assert mantissa == 75 assert format_.msb == 11 assert format_.lsb == 4 assert format_.signed mantissa, format_ = Format.best( interval(-16, 16), wordlength=8, signed=True ) assert mantissa == interval(-64, 64) assert format_.msb == 5 assert format_.lsb == -2 assert format_.signed
def test_represent(): alu = MultiFormatArithmeticLogicUnit( wordlength=8, rounding_method=nearest_integer, overflow_behavior=wraparound, allows_overflow=False, allows_underflow=False ) assert alu.rinfo(signed=True).eps == 0.0078125 assert alu.rinfo(signed=True).min == -128 assert alu.rinfo(signed=True).max == 127 assert alu.rinfo(signed=False).eps == 0.00390625 assert alu.rinfo(signed=False).min == 0 assert alu.rinfo(signed=False).max == 256 r = alu.represent(0.5) assert r.mantissa == 64 assert r.format_ == Q(7) r = alu.represent(0) assert r.mantissa == 0 assert r.format_ == Q(7) r = alu.represent(1.25) assert r.mantissa == 80 assert r.format_ == Q(2, 6) r = alu.represent(1.25, format_=Q(3, 4)) assert r.mantissa == 20 assert r.format_ == Q(3, 4) r = alu.represent(1.25, format_=uQ(3, 5)) assert r.mantissa == 40 assert r.format_ == uQ(3, 5) r = alu.represent(12.5) assert r.mantissa == 100 assert r.format_ == Q(5, 3) r = alu.represent(12.5, format_=Q(6, 2)) assert r.mantissa == 50 assert r.format_ == Q(6, 2) r = alu.represent(12.5, format_=uQ(4, 4)) assert r.mantissa == 200 assert r.format_ == uQ(4, 4) r = alu.represent(15.6) assert r.mantissa == 125 assert r.format_ == Q(5, 3) r = alu.represent(interval(-1, 1)) assert r.mantissa == interval(-64, 64) assert r.format_ == Q(2, 6)
def test_error_bounded_substraction(): a = error_bounded(1., interval(-0.1, 0.3)) b = error_bounded(1., interval(-0.3, 0.2)) c = a - b assert c.number == 0. assert math.isclose(c.error_bounds.lower_bound, -0.4) assert math.isclose(c.error_bounds.upper_bound, 0.5) d = a - 2 assert d.number == -1. assert d.error_bounds == a.error_bounds e = 1 - b assert e.number == 0. assert e.error_bounds == b.error_bounds
def test_realization_error_bounds(realization_type): model = signal.dlti([1], [1, -0.5]) # y[n] = x[n - 1] - 0.5 y[n - 1] block = realization_type.from_model(model) with FixedFormatArithmeticLogicUnit( format_=Q(7), allows_overflow=False, rounding_method=nearest_integer, ): assert block.computation_error_bounds(interval(-0.25, 0.25)) in \ 10 * nearest_integer.error_bounds(-7) # reasonable tolerance
def computation_error_bounds(self, input_range, state_ranges=None): if state_ranges is None and self.states: state_ranges = [] for model in self.state_observer_models: state_range = output_range(model, mpfloat(input_range)) state_range = interval( lower_bound=asvector_if_possible(state_range.lower_bound), upper_bound=asvector_if_possible(state_range.upper_bound), ) state_ranges.append(state_range) return super().computation_error_bounds([input_range], state_ranges)
def test_error_bounded_addition(): a = error_bounded(1., interval(-0.1, 0.3)) b = error_bounded(1., interval(-0.3, 0.2)) c = a + b assert c.number == 2. assert math.isclose(c.error_bounds.lower_bound, -0.4) assert math.isclose(c.error_bounds.upper_bound, 0.5) d = a + 2 assert d.number == 3. assert d.error_bounds == a.error_bounds e = 1 + b assert e.number == 2. assert e.error_bounds == b.error_bounds f = error_bounded(interval(-1, 1), interval(-0.1, 0.2)) g = a + f assert g.number == interval(0, 2) assert g.error_bounds == interval(-0.2, 0.5) with FixedFormatArithmeticLogicUnit( format_=Q(7), rounding_method=nearest_integer ): h = (a + (-0.5)) + fixed(0.2) assert h.number == fixed(0.7) assert a.error_bounds in h.error_bounds
def test_signed_integer_formats(): format_ = Format(msb=7, lsb=0, signed=True) assert format_.msb == 7 assert format_.lsb == 0 assert format_.signed assert format_.wordlength == 8 assert format_.mantissa_interval == interval(-128, 127) assert format_.value_interval == interval(-128, 127) assert format_.value_epsilon == 1 assert format_.to_qnotation() == 'Q8.0' assert format_.to_pnotation() == '(7,0)' mantissa, (underflow, overflow) = format_.represent( -127.5, rounding_method=rounding.nearest_integer ) assert mantissa == -128 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent( -127.5, rounding_method=rounding.ceil ) assert mantissa == -127 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0) assert mantissa == 0 assert not underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(0.1) assert mantissa == 0 assert underflow assert not overflow mantissa, (underflow, overflow) = format_.represent(256) assert not underflow assert overflow
def test_error_bounded_multiplication(): a = error_bounded(0.5, interval(-0.1, 0.2)) b = error_bounded(-4., interval(-0.2, 0.3)) c = a * b assert c.number == -2. assert math.isclose(c.error_bounds.lower_bound, -0.94) assert math.isclose(c.error_bounds.upper_bound, 0.52) d = a * 2 assert d.number == 1. assert math.isclose(d.error_bounds.lower_bound, -0.2) assert math.isclose(d.error_bounds.upper_bound, 0.4) e = 0.25 * b assert e.number == -1. assert math.isclose(e.error_bounds.lower_bound, -0.05) assert math.isclose(e.error_bounds.upper_bound, 0.075) f = error_bounded(interval(-1, 1), interval(-0.1, 0.2)) g = a * f assert g.number == interval(-0.5, 0.5) assert math.isclose(g.error_bounds.lower_bound, -0.27) assert math.isclose(g.error_bounds.upper_bound, 0.34)
def test_saturate(): value, overflow = saturate(32, range_=interval(0, 127)) assert value == 32 assert not overflow value, overflow = saturate(128, range_=interval(0, 127)) assert value == 127 assert overflow value, overflow = saturate(-1, range_=interval(0, 127)) assert value == 0 assert overflow value, overflow = saturate(-32, range_=interval(0, 127)) assert value == 0 assert overflow value, overflow = saturate(32, range_=interval(-128, 127)) assert value == 32 assert not overflow value, overflow = saturate(128, range_=interval(-128, 127)) assert value == 127 assert overflow value, overflow = saturate(-1, range_=interval(-128, 127)) assert value == -1 assert not overflow value, overflow = saturate(-32, range_=interval(-128, 127)) assert value == -32 assert not overflow value, overflow = saturate(-129, range_=interval(-128, 127)) assert value == -128 assert overflow
def test_wraparound(): value, overflow = wraparound(32, range_=interval(0, 127)) assert value == 32 assert not overflow value, overflow = wraparound(128, range_=interval(0, 127)) assert value == 0 assert overflow value, overflow = wraparound(-1, range_=interval(0, 127)) assert value == 127 assert overflow value, overflow = wraparound(-32, range_=interval(0, 127)) assert value == 96 assert overflow value, overflow = wraparound(32, range_=interval(-128, 127)) assert value == 32 assert not overflow value, overflow = wraparound(128, range_=interval(-128, 127)) assert value == -128 assert overflow value, overflow = wraparound(-1, range_=interval(-128, 127)) assert value == -1 assert not overflow value, overflow = wraparound(-32, range_=interval(-128, 127)) assert value == -32 assert not overflow value, overflow = wraparound(-129, range_=interval(-128, 127)) assert value == 127 assert overflow
def test_interval_construction(scalar): with pytest.raises(TypeError): interval() with pytest.raises(TypeError): interval(upper_bound=scalar(0)) iv = interval(scalar(0)) assert iv.lower_bound == scalar(0) assert iv.lower_bound == iv.upper_bound assert type(iv.lower_bound) is scalar assert type(iv.upper_bound) is scalar iv = interval(scalar(-1), scalar(1)) assert iv.lower_bound == scalar(-1) assert type(iv.lower_bound) is scalar assert iv.upper_bound == scalar(1) assert type(iv.upper_bound) is scalar
def test_add(): alu = FixedFormatArithmeticLogicUnit(format_=Q(4, 4), rounding_method=nearest_integer, overflow_behavior=wraparound, allows_overflow=True, allows_underflow=False) x = alu.represent(1) y = alu.represent(2) z = alu.add(x, y) assert z.mantissa == 48 assert z.format_ == alu.format_ x = alu.represent(4) z = alu.add(x, x) assert z.mantissa == -128 assert z.format_ == alu.format_ y = alu.represent(-2) z = alu.add(x, y) assert z.mantissa == 32 assert z.format_ == alu.format_ x = alu.represent(interval(-1, 1)) y = alu.represent(interval(3, 5)) z = alu.add(x, y) assert z.mantissa == interval(32, 96) assert z.format_ == alu.format_ x = alu.represent(interval(-1, 3)) y = alu.represent(interval(3, 5)) z = alu.add(x, y) # NOTE(hidmic): this ALU handles overflow # in interval arithmetic by assuming the # value may be anywhere (how many cycles # does e.g. [32, -32] imply?) # TODO(hidmic): revisit result assert z.mantissa == interval(-128, 127) assert z.format_ == alu.format_
def test_add(): alu = MultiFormatArithmeticLogicUnit( wordlength=8, rounding_method=nearest_integer, overflow_behavior=wraparound, allows_overflow=False, allows_underflow=False ) x = alu.represent(1, format_=Q(4, 4)) y = alu.represent(2, format_=Q(4, 4)) z = alu.add(x, y) assert z.mantissa == 48 assert z.format_ == Q(4, 4) x = alu.represent(1, format_=Q(2, 6)) y = alu.represent(2, format_=Q(3, 5)) z = alu.add(x, y) assert z.mantissa == 96 assert z.format_ == Q(3, 5) x = alu.represent(1, format_=Q(2, 6)) y = alu.represent(-2, format_=Q(3, 5)) z = alu.add(x, y) assert z.mantissa == -32 assert z.format_ == Q(3, 5) x = alu.represent(interval(-1, 1), format_=Q(2, 6)) y = alu.represent(interval(3, 5), format_=Q(4, 4)) z = alu.add(x, y) assert z.mantissa == interval(32, 96) assert z.format_ == Q(4, 4) x = alu.represent(interval(-1, 1), format_=Q(2, 6)) y = alu.represent(interval(3, 5), format_=Q(4, 4)) z = alu.add(x, y) assert z.mantissa == interval(32, 96) assert z.format_ == Q(4, 4)
def test_interval_bitwise(): iv = interval(2, 3) assert iv << 1 == interval(4, 6) assert iv >> 1 == 1 assert iv >> 2 == 0
def mantissa_interval(self): if self.signed: return interval(lower_bound=-2**(self.wordlength - 1), upper_bound=2**(self.wordlength - 1) - 1) return interval(lower_bound=0, upper_bound=2**self.wordlength - 1)
def main(): random.seed(7) np.random.seed(7) fs = 200 # Hz fo = 40 # Hz rp = 1 # dB rs = 80 # dB fpass = fo - 5 # Hz fstop = fo + 5 # Hz # N, fo = signal.cheb1ord(fpass, fstop, rp, rs, fs=fs) # N, fo = signal.cheb2ord(fpass, fstop, rp, rs, fs=fs) # N, fo = signal.buttord(fpass, fstop, rp, rs, fs=fs) N, fo = signal.ellipord(fpass, fstop, rp, rs, fs=fs) wp = 2 * fs * np.tan(np.pi * fo / fs) # prototype = signal.lti(*signal.cheb1ap(N, rp)) # prototype = signal.lti(*signal.cheb2ap(N, rs)) # prototype = signal.lti(*signal.buttap(N)) prototype = signal.lti(*signal.ellipap(N=N, rp=rp, rs=rs)) model = lowpass_to_lowpass(prototype, wo=wp) model = discretize(model, dt=1 / fs) print(model) # Use PSD output to white noise input PSD ratio as response window = signal.get_window('blackman', 256) psd = functools.partial(signal.welch, scaling='density', window=window, fs=fs) input_range = interval(lower_bound=-0.5, upper_bound=0.5) input_noise_power_density = 0.0005 input_noise = np.random.normal(scale=np.sqrt(input_noise_power_density * fs / 2), size=512) assert np.max(input_noise) < ProcessingUnit.active().rinfo().max assert np.min(input_noise) > ProcessingUnit.active().rinfo().min input_noise = np.array([fixed(n) for n in input_noise]) _, outputs = model.output(input_noise.astype(float), t=None) output_noise = outputs.T[0] freq, output_noise_power_density = psd(output_noise) expected_response = 10 * np.log10(output_noise_power_density / input_noise_power_density + 1 / inf) # Take quantization noise into account noise_floor = -6.02 * (ProcessingUnit.active().wordlength - 1) - 1.76 expected_response = np.maximum(expected_response, noise_floor) # Formulate GP problem toolbox = solvers.gp.formulate( prototype, transforms=[ functools.partial(lowpass_to_lowpass, wo=wp), functools.partial(discretize, dt=1 / fs) ], evaluate=functools.partial( evaluate, input_range=input_range, input_noise=input_noise, input_noise_power_density=input_noise_power_density, psd=psd, expected_response=expected_response), weights=(1., 1., 1., 1., -1., -1., -1., -1.), forms=[DirectFormI, DirectFormII], variants=range(1000), dtype=fixed, tol=1e-6) # Solve GP problem only_visualize = False if not only_visualize: with multiprocessing.Pool() as pool: try: toolbox.register('map', pool.map) stats = deap.tools.Statistics( key=lambda code: code.fitness.values) stats.register('avg', np.mean, axis=0) stats.register('med', np.median, axis=0) stats.register('min', np.min, axis=0) pareto_front = deap.tools.ParetoFront() population = toolbox.population(512) population, logbook = solvers.gp.nsga2(population, toolbox, mu=512, lambda_=128, cxpb=0.5, mutpb=0.05, ngen=25, stats=stats, halloffame=pareto_front, verbose=True) finally: toolbox.register('map', map) with open('front.pkl', 'wb') as f: pickle.dump(pareto_front, f) with open('logbook.pkl', 'wb') as f: pickle.dump(logbook, f) else: with open('front.pkl', 'rb') as f: pareto_front = pickle.load(f) with open('logbook.pkl', 'rb') as f: logbook = pickle.load(f) codes = [] criteria = [] for code in pareto_front: crt = Criteria(*code.fitness.values) if crt.frequency_response_error >= inf: continue if crt.stability_margin <= 0: continue if crt.overflow_margin < 0: continue if crt.underflow_margin < 0: continue codes.append(code) criteria.append(crt) frequency_response_error = np.array( [crt.frequency_response_error for crt in criteria]) arithmetic_snr = np.array([crt.arithmetic_snr for crt in criteria]) stability_margin = np.array([crt.stability_margin for crt in criteria]) memory_size = np.array([crt.size_of_memory for crt in criteria]) memory_size_in_bytes = memory_size * ProcessingUnit.active().wordlength / 8 plt.figure() gen, med = logbook.select('gen', 'med') crt = Criteria(*np.array(med).T) def fit_most_within_unit_interval(values): values = np.asarray(values) med = np.median(values) mad = np.median(np.absolute(values - med)) if not mad: return values return (values - med) / (4. * mad) plt.plot(gen, fit_most_within_unit_interval(crt.overflow_margin), label='Med[$M_o$]') plt.plot(gen, fit_most_within_unit_interval(crt.underflow_margin), label='Med[$M_u$]') plt.plot(gen, fit_most_within_unit_interval(crt.stability_margin), label='Med[$M_s$]') plt.plot(gen, fit_most_within_unit_interval(crt.arithmetic_snr), label='Med[$SNR_{arit}$]') plt.plot(gen, fit_most_within_unit_interval(crt.frequency_response_error), label='Med[$E_2$]') plt.plot(gen, fit_most_within_unit_interval(crt.number_of_adders), label='Med[$N_a$]') plt.plot(gen, fit_most_within_unit_interval(crt.number_of_multipliers), label='Med[$N_m$]') plt.plot(gen, fit_most_within_unit_interval(crt.size_of_memory), label='Med[$N_e$]') plt.ylabel('Normalized evolution') plt.xlabel('Generations') plt.ylim([-10, 10]) plt.legend(loc='upper right') plt.savefig('population_evolution.png') plt.figure() plt.plot(*logbook.select('gen', 'nunfeas')) plt.ylabel('Unfeasibles') plt.xlabel('Generations') plt.savefig('unfeasibles.png') def pareto2d(ax, x, y): ax.scatter(x, y, marker='o', facecolors='none', edgecolors='r') idx = np.argsort(x) ax.plot(x[idx], y[idx], 'k--') fig = plt.figure() ax = fig.add_subplot(3, 1, 1) idx = solvers.gp.argnondominated(-frequency_response_error, stability_margin) pareto2d(ax, frequency_response_error[idx], stability_margin[idx]) ax.set_ylabel('Margin $M_s$') ax.invert_xaxis() ax = fig.add_subplot(3, 1, 2) idx = solvers.gp.argnondominated(-frequency_response_error, arithmetic_snr) pareto2d(ax, frequency_response_error[idx], arithmetic_snr[idx]) ax.set_ylabel('$SNR_{arit}$ [dBr]') ax.invert_xaxis() ax = fig.add_subplot(3, 1, 3) idx = solvers.gp.argnondominated(-frequency_response_error, -memory_size_in_bytes) pareto2d(ax, frequency_response_error[idx], memory_size_in_bytes[idx]) ax.set_xlabel('Error $E_2$ [dBr]') ax.set_ylabel('Total $N_e$ @ Q15 [bytes]') ax.invert_xaxis() ax.invert_yaxis() plt.savefig('pareto_fronts.png') fig = plt.figure() ax = fig.add_subplot(projection='3d') idx = solvers.gp.argnondominated(-frequency_response_error, arithmetic_snr, -memory_size_in_bytes) scatter = ax.scatter(frequency_response_error[idx], arithmetic_snr[idx], memory_size_in_bytes[idx], c=stability_margin[idx], cmap='jet_r') fig.colorbar(scatter, ax=ax, label='Margin $M_s$') ax.set_xlabel('Error $E_2$ [dBr]') ax.set_ylabel('$SNR_{arit}$ [dBr]') ax.set_zlabel('Total $N_e$ @ Q15 [bytes]') ax.invert_xaxis() ax.invert_zaxis() plt.savefig('pareto_sampling.png') index = np.argsort(frequency_response_error)[0] implement = toolbox.compile(codes[index]) optimized_implementation_a = implement(prototype) index = np.argsort(frequency_response_error)[3] implement = toolbox.compile(codes[index]) optimized_implementation_b = implement(prototype) print(memory_size_in_bytes[np.argsort(frequency_response_error)]) print(stability_margin[np.argsort(frequency_response_error)]) print(arithmetic_snr[np.argsort(frequency_response_error)]) pretty(optimized_implementation_a).draw('optimized_a.png') pretty(optimized_implementation_b).draw('optimized_b.png') func = signal_processing_function(optimized_implementation_a) output_noise = func(input_noise).T[0].astype(float) _, output_noise_power_density = psd(output_noise) optimized_implementation_a_response = \ 10 * np.log10(output_noise_power_density / input_noise_power_density + 1/inf) func = signal_processing_function(optimized_implementation_b) output_noise = func(input_noise).T[0].astype(float) _, output_noise_power_density = psd(output_noise) optimized_implementation_b_response = \ 10 * np.log10(output_noise_power_density / input_noise_power_density + 1/inf) show_biquad_cascade = True if show_biquad_cascade: biquad_cascade = series_diagram([ DirectFormI.from_model(signal.dlti( section[:3], section[3:], dt=model.dt), dtype=fixed) for section in signal.zpk2sos(model.zeros, model.poles, model.gain) ], simplify=False) pretty(biquad_cascade).draw('biquad.png') func = signal_processing_function(biquad_cascade) output_noise = func(input_noise).T[0].astype(float) _, output_noise_power_density = psd(output_noise) biquad_cascade_response = \ 10 * np.log10(output_noise_power_density / input_noise_power_density + 1/inf) plt.figure() plt.plot(freq, expected_response, label='Model') if show_biquad_cascade: plt.plot(freq, biquad_cascade_response, label='Biquad cascade') pass plt.plot(freq, optimized_implementation_a_response, label='Optimized realization A') plt.plot(freq, optimized_implementation_b_response, label='Optimized realization B') plt.xlabel('Frecuency $f$ [Hz]') plt.ylabel('Response $|H(f)|$ [dBr]') plt.legend() plt.savefig('response.png') plt.show()
def test_model_output_range(): model = signal.dlti([0.75, 0], [1, -0.5]) input_range = interval(-1, 1) assert output_range(model, input_range) == interval(-1.5, 1.5)
def test_interval_comparison(scalar): iv_a = interval(scalar(-10), scalar(10)) assert iv_a == iv_a assert not iv_a != iv_a assert not (iv_a < iv_a) assert not (iv_a <= iv_a) assert not (iv_a > iv_a) assert not (iv_a >= iv_a) iv_b = interval(scalar(90), scalar(110)) assert not iv_a == iv_b assert iv_a != iv_b assert iv_a < iv_b assert iv_a <= iv_b assert not iv_a > iv_b assert not iv_a >= iv_b iv_c = interval(scalar(-110), scalar(-90)) assert not iv_a == iv_c assert iv_a != iv_c assert iv_a > iv_c assert iv_a >= iv_c assert not iv_a < iv_c assert not iv_a <= iv_c iv_d = interval(scalar(-20), scalar(20)) assert not iv_a == iv_d assert iv_a != iv_d assert not (iv_a < iv_d) assert not (iv_a <= iv_d) assert not (iv_a > iv_d) assert not (iv_a >= iv_d) iv_e = interval(scalar(-1), scalar(1)) assert not iv_a == iv_e assert iv_a != iv_e assert not (iv_a < iv_e) assert not (iv_a <= iv_e) assert not (iv_a > iv_e) assert not (iv_a >= iv_e) iv_f = interval(scalar(10), scalar(20)) assert not iv_a == iv_f assert iv_a != iv_f assert not (iv_a < iv_f) assert iv_a <= iv_f assert not (iv_a > iv_f) assert not iv_a >= iv_f iv_g = interval(scalar(-20), scalar(-10)) assert not iv_a == iv_g assert iv_a != iv_g assert not (iv_a > iv_g) assert iv_a >= iv_g assert not (iv_a < iv_g) assert not iv_a <= iv_g s_h = scalar(5) assert not iv_a == s_h assert iv_a != s_h assert not (iv_a < s_h) assert not (iv_a <= s_h) assert not (iv_a > s_h) assert not (iv_a >= s_h) s_i = scalar(10) assert not iv_a == s_i assert iv_a != s_i assert not (iv_a < s_i) assert iv_a <= s_i assert not (iv_a > s_i) assert not iv_a >= s_i s_j = scalar(-10) assert not iv_a == s_j assert iv_a != s_j assert not (iv_a > s_j) assert iv_a >= s_j assert not (iv_a < s_j) assert not iv_a <= s_j s_k = scalar(20) assert not iv_a == s_k assert iv_a != s_k assert iv_a < s_k assert iv_a <= s_k assert not iv_a > s_k assert not iv_a >= s_k s_l = scalar(-20) assert not iv_a == s_l assert iv_a != s_l assert iv_a > s_l assert iv_a >= s_l assert not iv_a < s_l assert not iv_a <= s_l iv_h = interval(s_h, s_h) assert iv_h == s_h assert not iv_h != s_h assert not (iv_h < s_h) assert iv_h <= s_h assert not (iv_h > s_h) assert iv_h >= s_h
def test_interval_arithmetic(scalar): iv_a = interval(scalar(-1), scalar(1)) iv_b = interval(scalar(-2), scalar(2)) assert -iv_a == interval(scalar(-1), scalar(1)) assert -iv_b == interval(scalar(-2), scalar(2)) assert iv_a + iv_b == interval(scalar(-3), scalar(3)) assert iv_a - iv_b == interval(scalar(-3), scalar(3)) assert iv_a * iv_b == interval(scalar(-2), scalar(2)) assert iv_b / iv_a == interval(scalar(-2), scalar(2)) if scalar is not mpmath.mpf: assert iv_b // iv_a == interval(scalar(-2), scalar(2)) assert iv_b % iv_a == scalar(0) iv_c = interval(scalar(4), scalar(8)) assert -iv_c == interval(scalar(-8), scalar(-4)) assert iv_b + iv_c == interval(scalar(2), scalar(10)) assert iv_b - iv_c == interval(scalar(-10), scalar(-2)) assert iv_b * iv_c == interval(scalar(-16), scalar(16)) assert iv_c / iv_b == interval(scalar(-4), scalar(4)) if scalar is not mpmath.mpf: assert iv_c // iv_b == interval(scalar(-4), scalar(4)) assert iv_c % iv_b == scalar(0)