def test_adjacencies(self): network = MAS.Network(*generate_uniform(4)) reachable_1 = np.array([[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]]) reachable_2 = np.array([[0, 1, 1, 1], [1, 0, 1, 1], [1, 1, 0, 1], [1, 1, 1, 0]]) network.adjacency_1 = reachable_1 self.assertTrue(is_equal(reachable_1.flatten(), network.get_adjacencies(1).flatten())) self.assertTrue(is_equal(reachable_2.flatten(), network.get_adjacencies(2).flatten()))
def test_throughputs(self): # compute and check throughputs for uniform network network = MAS.Network(*generate_uniform()) # check throughputs self.assertTrue(is_equal(network.throughputs(), (1.0 / 3) * np.ones((3,)))) # check availabilities self.assertTrue(is_equal(network.availabilities(), np.ones((3,))))
def test_throughputs(self): # compute and check throughputs for uniform network network = MAS.Network(*generate_uniform()) # check throughputs self.assertTrue( is_equal(network.throughputs(), (1. / 3) * np.ones((3, )))) # check availabilities self.assertTrue(is_equal(network.availabilities(), np.ones((3, ))))
def test_balance(self): # test if the balance strategy effectively balance the network network = MAS.Network(*generate_asymmetric()) tmp = np.array([0.5, 0.5, 1.0]) self.assertTrue(is_equal(network.new_availabilities(), tmp)) opt_rates, opt_routing = network.balance() tmp = np.array([1.0, 1.0, 1.0]) self.assertTrue(is_equal(network.new_availabilities(), tmp))
def test_balance(self): # test if the balance strategy effectively balance the network network = MAS.Network(*generate_asymmetric()) tmp = np.array([.5, .5, 1.]) self.assertTrue(is_equal(network.new_availabilities(), tmp)) opt_rates, opt_routing = network.balance() tmp = np.array([1., 1., 1.]) self.assertTrue(is_equal(network.new_availabilities(), tmp))
def test_min_attack_solver(self): # generate asymmetric network network = MAS.Network(*generate_asymmetric()) target = np.ones((3,)) cost = np.ones((3,3)) opt_rates, opt_routing = MinAttackSolver(network, target, cost).solve() self.assertTrue(is_equal(opt_rates, np.array([0.,0.,1.]))) tmp = .5 * np.ones((3, 3)) tmp[range(3), range(3)] = 0.0 self.assertTrue(is_equal(opt_routing, tmp))
def test_adjacencies(self): network = MAS.Network(*generate_uniform(4)) reachable_1 = np.array([[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]]) reachable_2 = np.array([[0, 1, 1, 1], [1, 0, 1, 1], [1, 1, 0, 1], [1, 1, 1, 0]]) network.adjacency_1 = reachable_1 self.assertTrue( is_equal(reachable_1.flatten(), network.get_adjacencies(1).flatten())) self.assertTrue( is_equal(reachable_2.flatten(), network.get_adjacencies(2).flatten()))
def test_min_cost_flow_init(self): # generate asymmetric network network = MAS.Network(*generate_asymmetric()) # target for the availabilities target = np.array([.5, 1., 1.]) # cost is uniform cost = np.ones((3,3)) coeff, sources = MinAttackSolver(network, target, cost).min_cost_flow_init() # check coefficients tmp = np.ones((3,3)) tmp[0,:] = np.array([2., 2., 2.]) self.assertTrue(is_equal(coeff, tmp)) # check sources self.assertTrue(is_equal(sources, np.array([.0, .5, -.5])))
def test_availabilities(self): # compute and check availabilities for asymmetric network rates, routing, travel_times = generate_asymmetric() rates[0] = 2. network = MAS.Network(rates, routing, travel_times) self.assertTrue( is_equal(network.availabilities(), np.array([.25, .5, 1.])))
def test_flow_to_rates_routing(self): network = MAS.Network(*generate_asymmetric()) flow = np.zeros((3, 3)) flow[0,1] = .25 flow[0,2] = .25 flow[1,0] = .5 flow[1,2] = .5 cost = np.ones((3,3)) target = np.array([.5, 1., 1.]) rates, routing = MinAttackSolver(network, target, cost).flow_to_rates_routing(flow) # check rates self.assertTrue(is_equal(rates, np.array([1., 1., 0.]))) # check routing tmp = .5 * np.ones((3, 3)) tmp[range(3), range(3)] = 0.0 self.assertTrue(is_equal(routing, tmp))
def test_cplex_attack_routing_small_network(self): # trying with CPLEX, see test_attack_routing_2() above for more details network = MAS.Network(*generate_uniform()) attack_rates = np.array([1.0, 1.0, 0.0]) k = 2 a, routing = network.opt_attack_routing(attack_rates, k, cplex=True) self.assertTrue(is_equal(a, network.new_availabilities())) self.assertTrue(abs(np.sum(a) - 5.0 / 3))
def test_cplex_attack_routing_small_network(self): # trying with CPLEX, see test_attack_routing_2() above for more details network = MAS.Network(*generate_uniform()) attack_rates = np.array([1., 1., 0.]) k = 2 a, routing = network.opt_attack_routing(attack_rates, k, cplex=True) self.assertTrue(is_equal(a, network.new_availabilities())) self.assertTrue(abs(np.sum(a) - 5. / 3))
def test_cplex_attack_routing_full_network(self): network = MAS.load_network("data/queueing_params.mat") k = np.where(network.new_availabilities() - 1.0 == 0.0)[0][0] print "availabilities before attacks", np.sum(network.new_availabilities()) attack_rates = 5.0 * np.ones((network.size,)) a, routing = network.opt_attack_routing(attack_rates, k, cplex=True) self.assertTrue(is_equal(a, network.new_availabilities())) print "availabilities after attacks", np.sum(network.new_availabilities())
def test_cplex_attack_routing_full_network(self): network = MAS.load_network('data/queueing_params.mat') k = np.where(network.new_availabilities() - 1. == 0.0)[0][0] print 'availabilities before attacks', np.sum( network.new_availabilities()) attack_rates = 5. * np.ones((network.size, )) a, routing = network.opt_attack_routing(attack_rates, k, cplex=True) self.assertTrue(is_equal(a, network.new_availabilities())) print 'availabilities after attacks', np.sum( network.new_availabilities())
def check(self): # check if the attack_routing 'kappa' is valid assert self.kappa.shape[0] == self.N, \ 'attack_routing has {} rows but N = {}'.format(self.kappa.shape[0], self.N) assert self.kappa.shape[1] == self.N, \ 'attack_routing has {} rows but N = {}'.format(self.kappa.shape[1], self.N) assert np.min(self.kappa) >= 0.0 assert is_equal(np.sum(self.kappa, axis=1), 1.0, self.eps), \ 'attack_routing not stochastic {}'.format(np.sum(self.kappa, axis=1)) self.check_nu(self.nu)
def test_single_destination_attack(self): # generate asymmetric MAS_network with availabilities [0.5 0.5 1.0] # and attack on station 2 with budget = 1.0 (default) network = MAS.Network(*generate_asymmetric()) sol = SingleDestinationAttack(network, 2).apply() attack_rates, attack_routing = sol['attack_rates'], sol['attack_routing'] network.update(attack_rates, attack_routing) self.assertTrue(is_equal(network.new_availabilities(), np.array([1./3, 1./3, 1.]))) self.assertTrue(is_equal(sol['alpha'], 1.5)) # now attack on station 1 sol = SingleDestinationAttack(network, 1).apply() attack_rates, attack_routing = sol['attack_rates'], sol['attack_routing'] network.update(attack_rates, attack_routing) self.assertTrue(is_equal(network.new_availabilities(), np.array([1./3, 1., 2./3]))) self.assertTrue(is_equal(sol['alpha'], 1.5)) # now attack on station 1 with 0.49 budget -> inefficient attack network.budget = 0.49 sol = SingleDestinationAttack(network, 1).apply() attack_rates, attack_routing = sol['attack_rates'], sol['attack_routing'] network.update(attack_rates, attack_routing) self.assertTrue(is_equal(network.new_availabilities(), np.array([.5, .5, 1.])))
def test_attack_routing_2(self): # test if the routing of attacks works given fixed attack rates network = MAS.Network(*generate_uniform()) # attack rates are fixed attack_rates = np.array([1.0, 1.0, 0.0]) # find routing minimizing the weighted sum of availabilities # fix the availability at station 2 to be equal to 1 k = 2 # get the availabilities 'a' and routing that led to 'a' a, routing = network.opt_attack_routing(attack_rates, k) self.assertTrue(is_equal(a, network.new_availabilities(), 1e-7)) self.assertTrue(abs(np.sum(a) - 5.0 / 3))
def test_attack_routing_2(self): # test if the routing of attacks works given fixed attack rates network = MAS.Network(*generate_uniform()) # attack rates are fixed attack_rates = np.array([1., 1., 0.]) # find routing minimizing the weighted sum of availabilities # fix the availability at station 2 to be equal to 1 k = 2 # get the availabilities 'a' and routing that led to 'a' a, routing = network.opt_attack_routing(attack_rates, k) self.assertTrue(is_equal(a, network.new_availabilities(), 1e-7)) self.assertTrue(abs(np.sum(a) - 5. / 3))
def check(self, eps=1e-8): assert eps > 0., "eps too small" # check that dimensions match assert self.routing.shape == (self.size, self.size), \ "sizes of rates and routing do not match" assert self.travel_times.shape == (self.size, self.size), \ "sizes of rates and travel_times don't match" # check that we have probabilities for routing assert np.min(self.routing) >= 0.0, "negative probabilities" assert np.sum(self.routing.diagonal()) == 0.0, \ "diagonal of routing matrix not null" assert is_equal(np.sum(self.routing, axis=1), 1.0, eps), \ "routing matrix are not probabilities" # make sure that the Jackson network is not ill-defined assert np.min(self.rates) > eps, "rates too small" assert float(np.min(self.rates)) / np.max(self.rates) > eps, \ "ratio min(rates) / max(rates) too small" # check travel times tmp = self.travel_times tmp[range(self.size), range(self.size)] = np.max(self.travel_times) assert np.sum(tmp > eps) == self.size * self.size, \ "travel times too small" assert float(np.min(tmp)) / np.max(tmp) > eps, \ "ratio min(travel_times) / max(travel_times) too small" # check the weights assert len(self.weights) == self.size, 'weights wrong size' assert np.sum(self.weights > eps) == self.size, 'weights not positive' # check the adjacency matrix if self.adjacency is not None: assert self.adjacency.shape == (self.size, self.size) tmp = (self.adjacency == 0.) + (self.adjacency == 1.) assert np.sum( tmp) == self.size * self.size, "entries in adj not in 0, 1" assert np.sum(self.adjacency.diagonal()) == 0.0, \ "diagonal of routing matrix not null"
def check(self, eps=1e-8): assert eps > 0., "eps too small" # check that dimensions match assert self.routing.shape == (self.size, self.size), \ "sizes of rates and routing do not match" assert self.travel_times.shape == (self.size, self.size), \ "sizes of rates and travel_times don't match" # check that we have probabilities for routing assert np.min(self.routing) >= 0.0, "negative probabilities" assert np.sum(self.routing.diagonal()) == 0.0, \ "diagonal of routing matrix not null" assert is_equal(np.sum(self.routing, axis=1), 1.0, eps), \ "routing matrix are not probabilities" # make sure that the Jackson network is not ill-defined assert np.min(self.rates) > eps, "rates too small" assert float(np.min(self.rates)) / np.max(self.rates) > eps, \ "ratio min(rates) / max(rates) too small" # check travel times tmp = self.travel_times tmp[range(self.size), range(self.size)] = np.max(self.travel_times) assert np.sum(tmp > eps) == self.size * self.size, \ "travel times too small" assert float(np.min(tmp)) / np.max(tmp) > eps, \ "ratio min(travel_times) / max(travel_times) too small" # check the weights assert len(self.weights) == self.size, 'weights wrong size' assert np.sum(self.weights > eps) == self.size, 'weights not positive' # check the adjacency matrix if self.adjacency is not None: assert self.adjacency.shape == (self.size, self.size) tmp = (self.adjacency == 0.) + (self.adjacency == 1.) assert np.sum(tmp) == self.size * self.size, "entries in adj not in 0, 1" assert np.sum(self.adjacency.diagonal()) == 0.0, \ "diagonal of routing matrix not null"
def test_simplex_projection(self): v = np.array([1, 0, 0, 0, 0, 0]) self.assertTrue(is_equal(simplex_projection(v), v)) v = np.array([0.1, 0.2, 0.3, 0.4]) self.assertTrue(is_equal(simplex_projection(v), v)) v = np.array([10, 10]) w = np.array([0.5, 0.5]) self.assertTrue(is_equal(simplex_projection(v), w)) v = np.array([-10, -10]) w = np.array([0.5, 0.5]) self.assertTrue(is_equal(simplex_projection(v), w)) v = np.array([-10, 10]) w = np.array([0, 1]) self.assertTrue(is_equal(simplex_projection(v), w)) for _ in range(20): v = (np.random.rand(20) - np.ones(20) * 0.5) * 100 self.assertTrue(is_equal(np.sum(simplex_projection(v)), 1)) self.assertTrue(is_equal(np.sum(simplex_projection(v, 5)), 5))
def test_objective(self): obj, a = self.generate_solver().objective(nu = np.array([1., 0., 0.])) self.assertTrue(is_equal(obj, 1.75)) self.assertTrue(is_equal(a, np.array([.25, .5, 1.])))
def test_cplex_balance_small_network(self): network = MAS.Network(*generate_asymmetric()) tmp = np.array([.5, .5, 1.]) self.assertTrue(is_equal(network.new_availabilities(), tmp)) network.balance(cplex=True) self.assertTrue(is_equal(network.new_availabilities(), np.ones((3, ))))
def test_cplex_balance_full_network(self): # loading the full network network = MAS.load_network('data/queueing_params.mat') network.balance(cplex=True) self.assertTrue( is_equal(network.new_availabilities(), np.ones((network.size, ))))
def test_single_destination_attack(self): network = MAS.Network(*generate_asymmetric()) network.single_destination_attack(2) self.assertTrue( is_equal(network.new_availabilities(), np.array([1. / 3, 1. / 3, 1.])))
def test_throughputs_2(self): # compute and check throughputs for asymmetric network network = MAS.Network(*generate_asymmetric()) self.assertTrue( is_equal(network.throughputs(), np.array([.25, .25, .5])))
def test_min_attack(self): # test if the attacks affectively achieve the target availabilities target = np.array([.25, .5, 1.]) network = MAS.Network(*generate_asymmetric()) opt_rates, opt_routing = network.min_attack(target) self.assertTrue(is_equal(network.new_availabilities(), target))
def test_min_attack(self): # test if the attacks affectively achieve the target availabilities target = np.array([0.25, 0.5, 1.0]) network = MAS.Network(*generate_asymmetric()) opt_rates, opt_routing = network.min_attack(target) self.assertTrue(is_equal(network.new_availabilities(), target))
def test_cplex_balance_small_network(self): network = MAS.Network(*generate_asymmetric()) tmp = np.array([0.5, 0.5, 1.0]) self.assertTrue(is_equal(network.new_availabilities(), tmp)) network.balance(cplex=True) self.assertTrue(is_equal(network.new_availabilities(), np.ones((3,))))
def test_cplex_balance_full_network(self): # loading the full network network = MAS.load_network("data/queueing_params.mat") network.balance(cplex=True) self.assertTrue(is_equal(network.new_availabilities(), np.ones((network.size,))))
def test_availabilities(self): # compute and check availabilities for asymmetric network rates, routing, travel_times = generate_asymmetric() rates[0] = 2.0 network = MAS.Network(rates, routing, travel_times) self.assertTrue(is_equal(network.availabilities(), np.array([0.25, 0.5, 1.0])))
def test_throughputs_2(self): # compute and check throughputs for asymmetric network network = MAS.Network(*generate_asymmetric()) self.assertTrue(is_equal(network.throughputs(), np.array([0.25, 0.25, 0.5])))
def test_gradient_computation(self): g = self.generate_solver().gradient() self.assertTrue(is_equal(g, np.array([-.125, -.375, .75])))
def get_question_by_id(id): if id <= 2: a = np.random.randint(1, 51) b = np.random.randint(1, 51) if id == 2: a = get_str_value(np.random.randint(1, 100) / 10) b = get_str_value(np.random.randint(1, 100) / 10) all = ['{} - {}'.format(a, b), '-{} - {}'.format(a, b), '-{} + {}'.format(a, b), '-{} + (-{})'.format(a, b), '{} + (-{})'.format(a, b), '-{} - (-{})'.format(a, b), '{} - (-{})'.format(a, b), '-{} - (-{})'.format(a, b), '-(-{}) + {}'.format(a, b), '-(-{}) - {}'.format(a, b), '-(-{}) + (-{})'.format(a, b), '-(-{}) - (-{})'.format(a, b)] res = np.random.choice(all, 1)[0] return 'Вычисли: {}'.format(res), '{}'.format(get_str_value(eval(res), n=5)) elif id <= 4: l, r = -9, 10 if id == 4: l, r = -5, 5 def get_coefficient(): if np.random.rand() < 0.2: return np.random.choice([-1, 1]) return np.random.randint(l, r) a = [get_coefficient(), get_coefficient(), np.random.randint(l, r)] while a[0] == 0: a[0] = get_coefficient() res = get_square_equation(a) if id == 3: return 'Последовательно выпиши три числа: коэффициенты <b>a, b, c</b> квадратного уравнения.\n\n{} = 0'.format(res), \ '{}, {}, {}'.format(get_str_value(a[0], n=5), get_str_value(a[1], n=5), get_str_value(a[2], n=5)) else: D = a[1] ** 2 - 4 * a[0] * a[2] roots = 2 if D == 0: roots = 1 elif D < 0: roots = 0 return 'Последовательно выпиши два числа: дискриминант и количество различных корней квадратного уравнения.\n\n{} = 0'.format(res), \ '{}, {}'.format(get_str_value(D, n=5), get_str_value(roots, n=5)) elif id == 5: max_sqrt_d = 15 if np.random.random() < 0.15: while True: a = [np.random.randint(-5, 6), np.random.randint(-15, 16), np.random.randint(-20, 20)] D = a[1] * a[1] - 4 * a[0] * a[2] if D < 0: break else: while True: x1 = np.random.randint(-15, 16) x2 = np.random.randint(-15, 16) if abs(x1 - x2) <= max_sqrt_d: break a = [1, -x1 - x2, x1 * x2] D = a[1] * a[1] - 4 * a[0] * a[2] while True: coef = np.random.choice([0.1, 0.5, 1, 2, 3, 4, 5, -0.1, -0.5, -1, -2, -3, -4, -5]) if is_equal(abs(coef), 0.5) and D % 4 != 0 and D * 25 > max_sqrt_d * max_sqrt_d: continue if abs(a[1] * coef) <= 100 and D * coef * coef <= max_sqrt_d * max_sqrt_d: break a[0] *= coef a[1] *= coef a[2] *= coef D *= coef * coef res = get_square_equation(a) ans = 's ' if D < 0: ans += '0 корней' elif D == 0: ans += '1 корень, x = {}'.format(get_str_value(x1)) else: if x1 > x2: x1, x2 = x2, x1 ans += '2 корня, x₁ = {}, x₂ = {}'.format(get_str_value(x1), get_str_value(x2)) return 'Последовательно выпиши количество различных корней квадратного уравнения и сами корни.\n\n{} = 0\n\nИспользуй тот факт, что дискриминант D = {}'.format(res, get_str_value(D)), ans elif 6 <= id and id <= 11: def get_all_primes(n): is_prime = [True for i in range(n)] res = [] for i in range(2, n): if is_prime[i]: res.append(i) for j in range(2 * i, n, i): is_prime[j] = False return res if id == 6: mods = get_all_primes(51) probs = np.array(mods) ** 0.5 probs /= np.sum(probs) mod = np.random.choice(mods, p=probs) a = np.random.randint(mod) b = np.random.randint(mod) return f'Вычисли {a} + {b} в поле по модулю {mod}', (a + b) % mod elif id == 7: mods = get_all_primes(51) probs = np.array(mods) ** 0.5 probs /= np.sum(probs) mod = np.random.choice(mods, p=probs) if np.random.rand() < 0.1: a = np.random.randint(1, mod) return f'Вычисли {-a} в поле по модулю {mod}', (-a) % mod a = np.random.randint(mod) b = np.random.randint(mod) return f'Вычисли {a} - {b} в поле по модулю {mod}', (a - b) % mod elif id == 8: mods = get_all_primes(14) probs = np.array(mods) ** 0.5 probs /= np.sum(probs) mod = np.random.choice(mods, p=probs) a = np.random.randint(mod) b = np.random.randint(mod) return f'Вычисли {a} * {b} в поле по модулю {mod}', (a * b) % mod else: def inverse(x, mod): def power(x, n, mod): res = 1 while n > 0: if n % 2 == 1: res = (res * x) % mod x = (x * x) % mod n //= 2 return res return power(x, mod - 2, mod) mods = get_all_primes(12) probs = np.array(mods) ** 1.0 probs /= np.sum(probs) mod = np.random.choice(mods, p=probs) if id == 9: a = np.random.randint(1, mod) return f'Вычисли обратный элемент к числу {a} в поле по модулю {mod}', inverse(a, mod) elif id == 10: a = np.random.randint(mod) b = np.random.randint(1, mod) return f'Вычисли {a} / {b} в поле по модулю {mod}', (a * inverse(b, mod)) % mod else: a = np.random.randint(mod) b = np.random.randint(1, mod) c = np.random.randint(mod) d = np.random.randint(1, mod) sign = np.random.choice(['+', '-']) return f'Вычисли {a}/{b} {sign} {c}/{d} в поле по модулю {mod}', eval(f'a * inverse(b, mod) {sign} c * inverse(d, mod)') % mod
def test_init_solver(self): ars_solver = self.generate_solver() ars_solver.init_solver() self.assertTrue(is_equal(ars_solver.obj_values[0], 1.75)) self.assertTrue(is_equal(ars_solver.a, np.array([.25, .5, 1.]))) self.assertTrue(ars_solver.iter == 0)
def test_single_destination_attack(self): network = MAS.Network(*generate_asymmetric()) network.single_destination_attack(2) self.assertTrue(is_equal(network.new_availabilities(), np.array([1.0 / 3, 1.0 / 3, 1.0])))