def _alternation_int_example(self, qe): # Alternation of quantifiers p, q = Symbol("p", INT), Symbol("q", INT) f = ForAll([p], Exists([q], Equals(p, Plus(q, Int(1))))) qf = qe.eliminate_quantifiers(f).simplify() self.assertEqual(qf, TRUE())
def create_microservices_possibilities(microservices_on_nodes): """ :return: a SMT encoding containing all microservice mapping possibilities. """ microservices_possibilities = [] for m, nodes in microservices_on_nodes.items(): microservices_possibilities.append( Or(Equals(microservice(m), Int(int(n))) for n in nodes)) return And(microservices_possibilities)
def resolve_constant(self, c: Constant, sort: Sort = None): if sort is None: sort = c.sort if sort == self.smtlang.Integer: return Int(c.symbol) if sort == self.smtlang.Real: return Real(c.symbol) if isinstance(sort, Interval): return self.resolve_constant(c, parent(sort)) if isinstance(sort, Set): return self.resolve_constant(c, parent(sort)) # Otherwise we must have an enumerated type and simply return the object ID return Int(self.object_ids[symref(c)])
def test_bdd_simplify_bool_abs(self): s = BddSimplifier() for (f, _, _, logic) in get_example_formulae(): if not logic.theory.linear: continue if logic != QF_BOOL: with self.assertRaises(ConvertExpressionError): s.simplify(f) s = BddSimplifier(bool_abstraction=True) for (f, _, _, logic) in get_example_formulae(): if logic.quantifier_free: fprime = s.simplify(f) self.assertValid(Iff(fprime, f)) s = BddSimplifier(bool_abstraction=True) f = And(Equals(Plus(Int(5), Int(1)), Int(6)), Symbol("x")) fs = s.simplify(f) self.assertEqual(fs, Symbol("x"))
def test_simplifying_int_plus_changes_type_of_expression(self): varA = Symbol("At", INT) varB = Symbol("Bt", INT) get_type = get_env().stc.get_type f = Plus(varB, Int(1)) old_type = get_type(f) f = f.simplify() new_type = get_type(f) self.assertEqual(new_type, old_type)
def SMT_solver(rule, a, b, feature_num, con_num, data): letters = [] letters1 = [] for i in range(feature_num): letters.append(Symbol('x' + str(i), REAL)) letters1.append(Symbol('x_' + str(i), INT)) domains = And([ And(GE(letters[i], Real(float(a[i]))), LE(letters[i], Real(float(b[i])))) for i in range(feature_num) ]) problem_rule = [] for node in rule: if node[1] == ">": problem_rule.append(GT(letters[node[0]], Real(float(node[2])))) else: problem_rule.append(LE(letters[node[0]], Real(float(node[2])))) problem = And(problem_rule) constraint = And([ And( Implies(Equals(letters[i], Real(float(data[i]))), Equals(letters1[i], Int(0))), Implies(NotEquals(letters[i], Real(float(data[i]))), Equals(letters1[i], Int(1)))) for i in range(feature_num) ]) sum_letters1 = Plus(letters1) problem1 = LE(sum_letters1, Int(con_num)) formula = And([domains, problem, constraint, problem1]) test_case = [] with Solver(name='z3', random_seed=23) as solver: solver.add_assertion(formula) if solver.solve(): for l in letters: ans = solver.get_py_value(l) test_case.append(float(ans)) print("find a solution") # else: # print("No solution found") return test_case
def test_const_leaf(self): f = Int(0) self.assertEqual(f.size(), 1) self.assertEqual(f.size(SizeOracle.MEASURE_TREE_NODES), 1) self.assertEqual(f.size(SizeOracle.MEASURE_DAG_NODES), 1) self.assertEqual(f.size(SizeOracle.MEASURE_LEAVES), 1) self.assertEqual(f.size(SizeOracle.MEASURE_DEPTH), 1) self.assertEqual(f.size(SizeOracle.MEASURE_SYMBOLS), 0)
def IsPlan(plan, gridsize, starts, goals, obstacles): # Begin by snapping all coordinates to N x N space. This is correct # according to the problem formulation given in Definition 1 starts = IntifyCoords(starts) goals = IntifyCoords(goals) obstacles = IntifyCoords(obstacles) # (1) A i in N_R : x_i^1 = S_i init = And( [SamePosition(path[0], starts[i]) for i, path in enumerate(plan)]) # (2) A i in N_r : A t in N_T : x_i^t in W = Z_n x Z_n bounds = And( [And([IsOnGrid(step, gridsize) for step in path]) for path in plan]) # (3) A i in N_R : A t in N_{T-1} : E u in U : delta(x_i^t, u) = x_i^{t+1} # Note this isn't exactly the same, but it's morally equivalent, just # modulo the knowledge of the function delta. adjacency = And([IsConnected(path) for path in plan]) # (4) A i in N_R : E t in N_T : G_i in x_i^T reach = And([ Or([SamePosition(coord, goals[i]) for coord in path]) for i, path in enumerate(plan) ]) # (5) A (i, j) in N_R x N_R : A t in N_T : # x_i^t \cap x_j^t \neq \emptyset => i = j avoid = And([ Implies(SamePosition(plan[i][k], plan[j][k]), Equals(Int(i), Int(j))) for k in range(len(plan[0])) for i in range(len(plan)) for j in range(len(plan)) ]) # (6) A i in N_R : A t in N_T : x_i^t \cap \Omega = \emptyset obstacles = And([ Not(SamePosition(coord, obstacle)) for path in plan for coord in path for obstacle in obstacles ]) # valid(x) = (1) ^ (2) ^ (3) ^ (4) ^ (5) ^ (6) return And(init, bounds, adjacency, reach, avoid, obstacles)
def create_quantified_variable(self, v): # First deal with the two unbound cases: if v.sort == self.smtlang.Integer: return Symbol(v.symbol, INT), TRUE() if v.sort == self.smtlang.Real: return Symbol(v.symbol, REAL), TRUE() # Otherwise assume we have a bounded type (including Enumerated types) smtvar = Symbol(v.symbol, INT) lb, up = self.get_expression_bounds(v) if lb >= up: raise TransformationError( f"SMT variable corresponding to sort '{v.sort}' has cardinality 0" ) bounds = And(GE(smtvar, Int(lb)), LT(smtvar, Int(up))) return smtvar, bounds
def test_minus_0(self): x = Symbol("x", INT) y = Symbol("y", INT) i_0 = Int(0) src = Plus(x, y) src = Minus(x, src) src = LT(src, i_0) td = TimesDistributor() res = td.walk(src) self.assertValid(Iff(src, res))
def task_precedence_contraints(constraints, frameSetSortByTask, taskA, taskB): ''' 任务A优先于任务B:任务A必须先于任务B完成。 ''' frameSetA = frameSetSortByTask[taskA] frameSetB = frameSetSortByTask[taskB] lastFrameOfA = frameSetA[len(frameSetA) - 1] fisrtFrameOfB = frameSetB[0] linkA = taskA.selfLink linkB = taskB.selfLink # aCon = linkB.macrotick * fisrtFrameOfB.offset >= linkA.macrotick * \ # (lastFrameOfA.offset + lastFrameOfA.L) aCon = GE( Times(Int(linkB.macrotick), fisrtFrameOfB.offset), Times(Int(linkA.macrotick), Plus(lastFrameOfA.offset, Int(lastFrameOfA.L)))) #print(aCon) constraints.append(aCon) return True
def test_int(self): p, q = Symbol("p", INT), Symbol("q", INT) f = ForAll([p], Implies(LT(Int(0), p), LT(q, p))) with Solver(name='cvc4', logic=LIA) as s: s.add_assertion(f) try: res = s.solve() self.assertTrue(res) except SolverReturnedUnknownResultError: pass
def virtual_link_constraints(constraints, frameSet, vlinkSet, g): ''' 生产者虚帧先于网络链路帧先于消费者的虚帧 参数: solver:求解器实例 frameSet: 帧集合(vlid_t -> link -> [frame],两层字典) vlinkSet: 包含虚链路信息的集合 g: 模型中的时间同步精度,单位:us ''' # 首先取出同一条虚链路的所有帧 for vlid_t in frameSet: frameSameVLink = frameSet[vlid_t] # 取出VLink类中的链路集合 vl = vlinkSet[vlid_t].vl # 任意两条不同的相邻的Link满足: for i in range(len(vl) - 1): # 取出前一个集合的最后一个帧和后一个集合的第一个帧 linkI = vl[i] linkJ = vl[i + 1] frameListLinkI = frameSameVLink[linkI] frameListLinkJ = frameSameVLink[linkJ] # 最后一个帧 frameLastLinkI = frameListLinkI[len(frameListLinkI) - 1] # 第一个帧 frameFirstLinkJ = frameListLinkJ[0] # aCon = (linkJ.macrotick * frameFirstLinkJ.offset - linkI.delay - # g >= linkI.macrotick * (frameLastLinkI.offset + frameLastLinkI.L)) aCon = GE( Minus(Times(Int(linkJ.macrotick), frameFirstLinkJ.offset), Int(linkI.delay + g)), Times(Int(linkI.macrotick), Plus(frameLastLinkI.offset, Int(frameLastLinkI.L)))) #print(aCon) constraints.append(aCon) # print(solver) #time_start = time.time() # print(solver.check()) # print(solver.model()) #time_end = time.time() # print('#计算用时:{} s'.format(time_end-time_start)) # pdb.set_trace() return True
def test_msat_back_simple(self): from pysmt.solvers.msat import MathSAT5Solver, MSatConverter env = get_env() msat = MathSAT5Solver(environment=env, logic=QF_UFLIRA) new_converter = MSatConverter(env, msat.msat_env) r, s = FreshSymbol(REAL), FreshSymbol(INT) f1 = GT(r, Real(1)) f2 = LE(Plus(s, Int(2)), Int(3)) f3 = LE(Int(2), Int(3)) f = And(f1, f2, f3) term = new_converter.convert(f) res = new_converter.back(term) # Checking equality is not enough: MathSAT can change the # shape of the formula into a logically equivalent form. self.assertTrue(is_valid(Iff(f, res), logic=QF_UFLIRA))
def test_str_replace(self): s1 = Symbol("s1", STRING) s2 = Symbol("s2", STRING) s3 = Symbol("s3", STRING) f = Equals(StrReplace(s1, s2, s3), s3) self.assertSat(f) f = And(GT(StrLength(s1), Int(0)), GT(StrLength(s2), Int(0)), GT(StrLength(s3), Int(0)), Not(StrContains(s1, s2)), Not(StrContains(s1, s3)), Not(Equals(StrReplace(StrReplace(s1, s2, s3), s3, s2), s1))) self.assertUnsat(f) # Replace first v Replace First f = Implies( And(Equals(s1, String("Hello")), Equals(s2, StrReplace(s1, String("l"), String(" ")))), Equals(s2, String("He lo"))) self.assertValid(f, logic="QF_SLIA")
def sum_m(tau): return Plus([Int(0)] + [ Plus( Ite(Equals(delta_chi_eq_i[e][i], Int(1)), Int(LAMBDA(i)[0]), Int(0)), Plus([ Ite( Equals(delta_chi_eq_i[len(logical_edges) + r][i], Int(1)), Ite(Equals(delta_e_in_r[e][r], Int(1)), Int(LAMBDA(i)[0]), Int(0)), Int(0)) for r in range(len(logical_edges)) ])) for i in range(JUMPTABLE_MAX) for e in range(len(logical_edges)) if logical_edges[e].source() in tc.get_in_neighbors(tau) ])
def solveDecisionProblem(filename): global robots_info global task_info global task_utilities global k robots_info = {} task_info = {} task_utilities = {} k=0 file = open(filename, "r") mode = 0 for line in file: if line=='\n': mode+=1 elif mode==0: k = int(line.strip()) elif mode==1: task_line = line.split() task_info[task_line[0]] = [int(resource) for resource in task_line[2:]] task_utilities[task_line[0]] = int(task_line[1]) elif mode == 2: robot_line = line.split() robots_info[robot_line[0]] = [int(resource) for resource in robot_line[1:]] file.close() # Each robot may be assigned to at most one task # runs in time |Robots||Tasks||Tasks| oneTask = And([Symbol(robot+taskAssigned).Implies(Not(Symbol(robot+task))) for robot in robots_info.keys() for taskAssigned in task_info.keys() for task in task_info.keys() if (taskAssigned != task)]) # A task is satisfied if and only if all of its resource requirements are met # runs in time |Robots||Tasks||ResourceTypes| tasksSatisfied = And([Iff(Symbol(task +"Sat"), And([GE(Plus([Times(Ite(Symbol(robot+task),Int(1), Int(0)), Int(robots_info[robot][i])) for robot in robots_info.keys()]), Int(task_info[task][i])) for i in range(len(task_info[task]))])) for task in task_info.keys()]) # Is the decision problem satisfied # runs in time |Tasks| decisionProb = GE(Plus([Times(Ite(Symbol(task+"Sat"), Int(1), Int(0)), Int(task_utilities[task])) for task in task_info.keys()]), Int(k)) prob = And(oneTask, tasksSatisfied, decisionProb) model = get_model(prob) return model
def test_functions(self): vi = Symbol("At", INT) vr = Symbol("Bt", REAL) f = Symbol("f", FunctionType(INT, [REAL])) g = Symbol("g", FunctionType(REAL, [INT])) tc = get_env().stc self.assertEqual(tc.walk(Function(f, [vr])), INT) self.assertEqual(tc.walk(Function(g, [vi])), REAL) self.assertEqual(tc.walk(Function(f, [Function(g, [vi])])), INT) self.assertEqual(tc.walk(LE(Plus(vi, Function(f, [Real(4)])), Int(8))), BOOL) self.assertEqual(tc.walk(LE(Plus(vr, Function(g, [Int(4)])), Real(8))), BOOL) with self.assertRaises(PysmtTypeError): LE(Plus(vr, Function(g, [Real(4)])), Real(8)) with self.assertRaises(PysmtTypeError): LE(Plus(vi, Function(f, [Int(4)])), Int(8))
def printOutput(model, outfile): # format and print output file = open(outfile, "w") if model == None: file.write("0\n") file.close() return total = model.get_py_value(Plus([Times(Ite(Symbol(task+"Sat"), Int(1), Int(0)), Int(task_utilities[task])) for task in task_info.keys()])) file.write(str(total)+"\n\n") for task in task_info.keys(): if (model.get_py_value(Symbol(task+"Sat"))): ret = task + " " + str(task_utilities[task]) for robot in robots_info.keys(): if (model.get_py_value(Symbol(robot+task))): ret+= " " + robot ret+="\n" file.write(ret) else: file.write(task +" 0\n") file.close()
def min_K(tau): return Min([Int(K_MAX)] + [ Min( Ite(Equals(delta_chi_eq_i[e][i], Int(1)), Int(LAMBDA(i)[1]), Int(K_MAX)), Min([ Ite( Equals(delta_chi_eq_i[len(logical_edges) + r][i], Int(1)), Ite(Equals(delta_e_in_r[e][r], Int(1)), Int(LAMBDA(i)[1]), Int(K_MAX)), Int(K_MAX)) for r in range(len(logical_edges)) ])) for i in range(JUMPTABLE_MAX) for r in range(len(logical_edges)) for e in range(len(logical_edges)) if logical_edges[e].source() in tc.get_in_neighbors(tau) ])
def test_lia_qe_requiring_modulus(self): x = Symbol("x", INT) y = Symbol("y", INT) f = Exists([x], Equals(y, Times(x, Int(2)))) with self.assertRaises(ConvertExpressionError): qelim(f) try: qelim(f) except ConvertExpressionError as ex: # The modulus operator must be there self.assertIn("%2", str(ex.expression))
def main(): # Example Transition System (SMV-like syntax) # # VAR x: integer; # y: integer; # # INIT: x = 1 & y = 2; # # TRANS: next(x) = x + 1; # TRANS: next(y) = y + 2; x, y = [Symbol(s, INT) for s in "xy"] nx, ny = [next_var(Symbol(s, INT)) for s in "xy"] example = TransitionSystem(variables=[x, y], init=And(Equals(x, Int(1)), Equals(y, Int(2))), trans=And(Equals(nx, Plus(x, Int(1))), Equals(ny, Plus(y, Int(2))))) # A true invariant property: y = x * 2 true_prop = Equals(y, Times(x, Int(2))) # A false invariant property: x <= 10 false_prop = LE(x, Int(10)) for prop in [true_prop, false_prop]: check_property(example, prop) print("")
def test_constant(self): b1 = Bool(True) b2 = Bool(False) r1 = Real(5.5) r2 = Real(5) r3 = Real(-5.5) i1 = Int(4) i2 = Int(-4) self.assertEqual(b1.to_smtlib(daggify=True), "true") self.assertEqual(b2.to_smtlib(daggify=True), "false") self.assertEqual(r1.to_smtlib(daggify=True), "(/ 11 2)") self.assertEqual(r2.to_smtlib(daggify=True), "5.0") self.assertEqual(r3.to_smtlib(daggify=True), "(- (/ 11 2))") self.assertEqual(i1.to_smtlib(daggify=True), "4") self.assertEqual(i2.to_smtlib(daggify=True), "(- 4)") self.assertEqual(b1.to_smtlib(daggify=False), "true") self.assertEqual(b2.to_smtlib(daggify=False), "false") self.assertEqual(r1.to_smtlib(daggify=False), "(/ 11 2)") self.assertEqual(r2.to_smtlib(daggify=False), "5.0") self.assertEqual(r3.to_smtlib(daggify=False), "(- (/ 11 2))") self.assertEqual(i1.to_smtlib(daggify=False), "4") self.assertEqual(i2.to_smtlib(daggify=False), "(- 4)")
def virtual_frame_sequence_constraints(constraints, frameSet, vlinkSet): ''' 链路约束规定了不同任务的虚帧不会重叠,同样同一个任务的不同虚帧也不同重叠 注意不同的是,同一节点上不会有精度问题 参数: solver: frameSet: ''' # 首先选择一个条虚链路 for vlid_t in frameSet: frameSameVLink = frameSet[vlid_t] vl = vlinkSet[vlid_t].vl firstSelfLink = vl[0] frameList = frameSameVLink[firstSelfLink] # 1.生成生成者约束 for frameId in range(len(frameList) - 1): frameI = frameList[frameId] frameJ = frameList[frameId + 1] #aCon = (frameJ.offset >= frameI.offset + frameI.L) aCon = GE(frameJ.offset, Plus(frameI.offset, Int(frameI.L))) #print(aCon) constraints.append(aCon) # 2.如果虚链路不是SelfLink,有消费者 if len(vl) > 2: lastSelfLink = vl[len(vl) - 1] frameList = frameSameVLink[lastSelfLink] for frameId in range(len(frameList) - 1): frameI = frameList[frameId] frameJ = frameList[frameId + 1] #aCon = (frameJ.offset >= frameI.offset + frameI.L) aCon = GE(frameJ.offset, Plus(frameI.offset, Int(frameI.L))) #print(aCon) constraints.append(aCon) # print(solver) # pdb.set_trace() return True
def test_infix_extended(self): p, r, x, y = self.p, self.r, self.x, self.y get_env().enable_infix_notation = True self.assertEqual(Plus(p, Int(1)), p + 1) self.assertEqual(Plus(r, Real(1)), r + 1) self.assertEqual(Times(r, Real(1)), r * 1) self.assertEqual(Minus(p, Int(1)), p - 1) self.assertEqual(Minus(r, Real(1)), r - 1) self.assertEqual(Times(r, Real(1)), r * 1) self.assertEqual(Plus(r, Real(1.5)), r + 1.5) self.assertEqual(Minus(r, Real(1.5)), r - 1.5) self.assertEqual(Times(r, Real(1.5)), r * 1.5) self.assertEqual(Plus(r, Real(1.5)), 1.5 + r) self.assertEqual(Times(r, Real(1.5)), 1.5 * r) with self.assertRaises(TypeError): foo = p + 1.5 self.assertEqual(Not(x), ~x) self.assertEqual(Times(r, Real(-1)), -r) self.assertEqual(Times(p, Int(-1)), -p) self.assertEqual(Xor(x, y), x ^ y) self.assertEqual(And(x, y), x & y) self.assertEqual(Or(x, y), x | y) self.assertEqual(Or(x, TRUE()), x | True) self.assertEqual(Or(x, TRUE()), True | x) self.assertEqual(And(x, TRUE()), x & True) self.assertEqual(And(x, TRUE()), True & x) get_env().enable_infix_notation = False
def test_simplification(self): constA, constB = String("Hello"), String("World") test_set = [ (StrLength(constA), Int(5)), (StrConcat(constA, constB), String("HelloWorld")), (StrContains(constA, String("H")), TRUE()), (StrContains(constB, String("H")), FALSE()), (StrIndexOf(constA, String("e"), Int(0)), Int(1)), (StrReplace(constA, String("l"), String(" ")), String("He lo")), (StrSubstr(constA, Int(1), Int(2)), String("el")), (StrPrefixOf(constA, constB), FALSE()), (StrPrefixOf(String("He"), constA), TRUE()), (StrSuffixOf(constA, constB), FALSE()), (StrSuffixOf(String("lo"), constB), FALSE()), (StrToInt(constA), Int(-1)), (StrToInt(String("55")), Int(55)), (IntToStr(Int(10)), String("10")), (IntToStr(Int(-1)), String("")), (StrCharAt(constA, Int(2)), String("l")), ] for (f, simplified) in test_set: self.assertEqual(f.simplify(), simplified)
def end_to_end_latency_constraints(constraints, frameSet, vlinkSet): ''' 端到端延迟不能超过允许的最大延迟,即小于等于tt-message的周期。 参数: solver: frameSet: ''' # 首先选择一条虚链路 for vlid_t in frameSet: frameSameVLink = frameSet[vlid_t] vl = vlinkSet[vlid_t].vl # 取Link firstLink = vl[0] lastLink = vl[len(vl) - 1] # 取Frame firstFrame = frameSameVLink[firstLink][0] lastFrame = frameSameVLink[lastLink][len(frameSameVLink[lastLink]) - 1] # 约束 # aCon = (lastLink.macrotick * (lastFrame.offset + lastFrame.L) # <= (firstLink.macrotick * firstFrame.offset + vlinkSet[vlid_t].max_latency)) aCon = LE( Times(Int(lastLink.macrotick), Plus(lastFrame.offset, Int(lastFrame.L))), Plus(Times(Int(firstLink.macrotick), firstFrame.offset), Int(vlinkSet[vlid_t].max_latency))) #print(aCon) constraints.append(aCon) # print(solver) #time_start = time.time() # print(solver.check()) # print(solver.model()) #time_end = time.time() # print('#计算用时:{} s'.format(time_end-time_start)) # pdb.set_trace() return True
def scheduler(chip_power): total_power = 0 mem = [Symbol(M, INT) for M in mem_list] # print(mem_power_list.get(str(mem[0]))) domain = And([And(GE(l, Int(0)), LT(l, Int(2))) for l in mem]) # print(domain) sum_power = Plus([l * mem_power_list.get(str(l)) for l in mem]) # print(sum_power) problem = Equals(sum_power, Int(chip_power)) formula = And(domain, problem) # print(formula) model = get_model(formula) # print(model) if model != None: for l in mem: mem_test_time_list[str(l)] = mem_test_time_list[str(l)] - int( model.get_value(l).constant_value()) if int(model.get_value(l).constant_value()) == 1: print(str(l)) total_power = total_power + mem_power_list[str(l)] print("total power:", total_power) return True else: return False
def test_named_unsat_core_with_assumptions(self): i0 = Int(0) a = GT(Symbol("a", INT), i0) b = GT(Symbol("b", INT), i0) c = GT(Symbol("c", INT), i0) n_a = Not(a) n_b = Not(b) n_c = Not(c) formulae = [Or(b, n_a), Or(c, n_a), Or(n_a, n_b, n_c)] with UnsatCoreSolver(logic=QF_LIA, unsat_cores_mode="named") as solver: for i, f in enumerate(formulae): solver.add_assertion(f, named=f"f{i}") sat = solver.solve([a]) self.assertFalse(sat)
def create_microservice_facts(dependencies, microservices_on_nodes, latency_dict): """ :param dependencies: :param microservices_on_nodes: a dictionary containing a solution where key is a microservice and value is a list of nodes :param latency_dict: a dictionary containing the latency between dependent microservices :return: a SMT encoding containing the latency between two microservices. """ microservice_facts = [] for grp in dependencies: if grp[0] in microservices_on_nodes and grp[ 1] in microservices_on_nodes: for n1 in microservices_on_nodes[grp[0]]: for n2 in microservices_on_nodes[grp[1]]: microservice_facts.append( And(Equals(microservice(grp[0]), Int(int(n1))), Equals(microservice(grp[1]), Int( int(n2)))).Implies( Equals( latency(grp[0], grp[1]), Int(get_latency(n1, n2, latency_dict))))) return And(microservice_facts)
def create_replication(replicas, microservice, nodes): """ :param replicas: the total number of replicas of the current microservice :param microservice: the microservice that is allocated to the network :param nodes: a dictionary where a key represents a microservice having the value a list of possible mapping nodes :return: an encoding to map exactly one replica on a node and a list of replicas """ replicas_list = list() encoding = list() for i in range(replicas): replicas_list.append(replica(microservice, i)) replica_len = len(replicas_list) for n in nodes[microservice]: for i in range(replica_len): encoding.append( Equals(replicas_list[i], Int(int(n))).Implies( Not( Or( Equals(replicas_list[j], Int(int(n))) for j in range(i + 1, replica_len))))) micro_constraint = And( ExactlyOne(Equals(r, Int(int(n))) for n in nodes[microservice]) for r in replicas_list) return And(encoding), replicas_list, micro_constraint
def availability_encoding(replicas, nodes): """ :param replicas: a list of all replicas symbols of a microservice :param nodes: a tuple containing all nodes and their availability :return: an encoding for discovering the availability of a microservice based on its allocation """ encoding = list() avail_obj = list() for r in replicas: avail_obj.append(availability(r)) for n in nodes: encoding.append( Equals(r, Int(int(n[0]))).Implies( Equals(availability(r), Real(float(1 - n[1]))))) return And(encoding), avail_obj