Пример #1
0
    def test_exactly_one_unpacking(self):
        s1,s2 = Symbol("x"), Symbol("y")
        f1 = ExactlyOne((s for s in [s1,s2]))
        f2 = ExactlyOne([s1,s2])
        f3 = ExactlyOne(s1,s2)

        self.assertEqual(f1,f2)
        self.assertEqual(f2,f3)
Пример #2
0
    def test_exactlyone_w_generator(self):
        x, y = Symbol("x"), Symbol("y")

        elems = [x,y]
        f1 = ExactlyOne(elems)
        f2 = ExactlyOne(e for e in elems)

        self.assertEqual(f1, f2)
Пример #3
0
    def test_smart_serialize(self):
        x, y = Symbol("x"), Symbol("y")
        f1 = And(x,y)
        f = Implies(x, f1)
        substitutions = {f1: "f1"}  # Mapping FNode -> String
        res = smart_serialize(f, subs=substitutions)
        self.assertEquals("(x -> f1)", res)

        # If no smarties are provided, the printing is compatible
        # with standard one
        res = smart_serialize(f)
        self.assertIsNotNone(res)
        self.assertEquals(str(f), res)

        fvars = [Symbol("x%d" % i) for i in xrange(5)]
        ex = ExactlyOne(fvars)
        substitutions = {ex: "ExactlyOne(%s)" % ",".join(str(v) for v in fvars)}
        old_str = ex.serialize()
        smart_str = smart_serialize(ex, subs=substitutions)
        self.assertTrue(len(old_str) > len(smart_str))
        self.assertEquals("ExactlyOne(x0,x1,x2,x3,x4)", smart_str)
Пример #4
0
    def test_smart_serialize(self):
        x, y = Symbol("x"), Symbol("y")
        f1 = And(x, y)
        f = Implies(x, f1)
        substitutions = {f1: "f1"}  # Mapping FNode -> String
        res = smart_serialize(f, subs=substitutions)
        self.assertEqual("(x -> f1)", res)

        # If no smarties are provided, the printing is compatible
        # with standard one
        res = smart_serialize(f)
        self.assertIsNotNone(res)
        self.assertEqual(str(f), res)

        fvars = [Symbol("x%d" % i) for i in range(5)]
        ex = ExactlyOne(fvars)
        substitutions = {
            ex: "ExactlyOne(%s)" % ",".join(str(v) for v in fvars)
        }
        old_str = ex.serialize()
        smart_str = smart_serialize(ex, subs=substitutions)
        self.assertTrue(len(old_str) > len(smart_str))
        self.assertEqual("ExactlyOne(x0,x1,x2,x3,x4)", smart_str)
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
Пример #6
0
    def encode(self):
        """
            Do the job.
        """

        self.enc = []

        # getting a tree ensemble
        self.ensemble = TreeEnsemble(
            self.model,
            self.xgb.extended_feature_names_as_array_strings,
            nb_classes=self.nofcl)

        # introducing class score variables
        csum = []
        for j in range(self.nofcl):
            cvar = Symbol('class{0}_score'.format(j), typename=REAL)
            csum.append(tuple([cvar, []]))

        # if targeting interval-based encoding,
        # traverse all trees and extract all possible intervals
        # for each feature
        if self.optns.encode == 'smtbool':
            self.compute_intervals()

        # traversing and encoding each tree
        for i, tree in enumerate(self.ensemble.trees):
            # getting class id
            clid = i % self.nofcl

            # encoding the tree
            tvar = Symbol('tr{0}_score'.format(i + 1), typename=REAL)
            self.traverse(tree, tvar, prefix=[])

            # this tree contributes to class with clid
            csum[clid][1].append(tvar)

        # encoding the sums
        for pair in csum:
            cvar, tvars = pair
            self.enc.append(Equals(cvar, Plus(tvars)))

        # enforce exactly one of the feature values to be chosen
        # (for categorical features)
        categories = collections.defaultdict(lambda: [])
        for f in self.xgb.extended_feature_names_as_array_strings:
            if '_' in f:
                categories[f.split('_')[0]].append(
                    Symbol(name=f, typename=BOOL))
        for c, feats in six.iteritems(categories):
            self.enc.append(ExactlyOne(feats))

        # number of assertions
        nof_asserts = len(self.enc)

        # making conjunction
        self.enc = And(self.enc)

        # number of variables
        nof_vars = len(self.enc.get_free_variables())

        if self.optns.verb:
            print('encoding vars:', nof_vars)
            print('encoding asserts:', nof_asserts)

        return self.enc, self.intvs, self.imaps, self.ivars
Пример #7
0
    # The Norwegian lives next to the blue house.
    # Careful with this!!!
    And(
        Iff(nat(i, "norwegian"), Or(color(i - 1, "blue"), color(i +
                                                                1, "blue")))
        for i in Houses),

    # The owner who smokes Blends lives next to the one who drinks water.
    And(
        Iff(smoke(i, "blends"), Or(drink(i -
                                         1, "water"), drink(i + 1, "water")))
        for i in Houses))

domain = And(
    And(ExactlyOne(color(i, c) for i in Houses) for c in Color),
    And(ExactlyOne(nat(i, c) for i in Houses) for c in Nat),
    And(ExactlyOne(pet(i, c) for i in Houses) for c in Pet),
    And(ExactlyOne(drink(i, c) for i in Houses) for c in Drink),
    And(ExactlyOne(smoke(i, c) for i in Houses) for c in Smoke),
    #
    And(ExactlyOne(color(i, c) for c in Color) for i in Houses),
    And(ExactlyOne(nat(i, c) for c in Nat) for i in Houses),
    And(ExactlyOne(pet(i, c) for c in Pet) for i in Houses),
    And(ExactlyOne(drink(i, c) for c in Drink) for i in Houses),
    And(ExactlyOne(smoke(i, c) for c in Smoke) for i in Houses),
)

problem = And(domain, facts)

model = get_model(problem)
    def build_formula(self):

        t_list = []
        l_facts = []
        domain = []
        latencies = []
        task_constraints = []

        offers = dict()

        # the SLA of our application
        SLA = int(self.app_dict["IoTapplication"]["SLA"])

        # find the dependencies between tasks
        depend_list, tasks, prob = self.find_dependencies(self.app_dict)

        # encodes the domain constraints in the SAT formula
        # checks on what nodes every two tasks are mapped and save their
        # latency
        ln = len(self.node_list)
        for i in range(ln):
            d = {}
            for j in range(i, ln):
                for t in depend_list:
                    if i == j:
                        d[str(t[0]) + "_" + str(t[1])] = And(
                            Equals(self.task(t[0]), Int(i)),
                            Equals(self.task(t[1]), Int(j)))
                    else:
                        d[str(t[0]) + "_" + str(t[1])] = Or(
                            And(Equals(self.task(t[0]), Int(i)),
                                Equals(self.task(t[1]), Int(j))),
                            And(Equals(self.task(t[0]), Int(j)),
                                Equals(self.task(t[1]), Int(i))))
                for k, v in d.items():
                    t_tasks = k.split("_")
                    domain.append(
                        v.Implies(
                            self.get_latency(t_tasks[0], t_tasks[1]).Equals(
                                Int(self.getLatency(i, j)))))

        # find the offers for each individual task
        # RETURN: a dictionary containing as a key the tasks and the value a
        # list of nodes which sent a bid for that particular task
        for k in self.node_offers:
            ln = len(self.node_offers[k])
            for i in range(ln):
                aTask = self.node_offers[k][i]
                offerSize = len(aTask)
                for j in range(offerSize):
                    theTask = aTask[j]
                    if theTask in offers:
                        offers[str(theTask)].add(int(k))
                    else:
                        aSet = set()
                        offers[theTask] = aSet
                        aSet.add(int(k))
        # check if all tasks have received an offer, if not the tasks will receive an offer from cloud, i.e., node 0
        if len(offers) != len(tasks):
            for t in tasks:
                if str(t) in offers:
                    continue
                else:
                    aSet = set()
                    offers[str(t)] = aSet
                    aSet.add(0)
        """creates a list of constraints that ensure a solution found by SMT does not exceed the available resources
        of a node. It is dependent on the bids received from each participant"""
        for node, bid in self.node_offers.items():
            bid_len = len(bid)
            task_c = []
            tasks_pos = []
            task_r = []
            neg_dict = {}
            diff_dict = {}
            for t in range(bid_len):
                tasks_cst = set()
                tmp_list = set()
                diff_list = []
                for n in bid[t]:
                    diff_list.append(n)
                diff_dict[t] = diff_list
                if len(bid[t]) == 0:
                    continue
                else:
                    tasks_pos.append(
                        Or(
                            Equals(self.task(tn), Int(int(node)))
                            for tn in bid[t]))
                    for j in range(bid_len):
                        if j == t:
                            continue
                        else:
                            for tsk in bid[j]:
                                tasks_cst.add(tsk)
                            common_elem = list(set(bid[t]) & set(bid[j]))
                            if len(common_elem) != 0:
                                tt = set(bid[j]) - set(bid[t])
                                for et in tt:
                                    tmp_list.add(et)
                                neg_dict[t] = list((tasks_cst - set(bid[t])))
                                for e in common_elem:
                                    if e in diff_dict[t]:
                                        diff_dict[t].remove(e)
                    temp_list = list((tasks_cst - set(bid[t])) - tmp_list)
                task_c.append(
                    Or(Equals(self.task(tn), Int(int(node)))
                       for tn in bid[t]).Implies(
                           Not(
                               Or(
                                   Equals(self.task(temp_list[tn]),
                                          Int(int(node)))
                                   for tn in range(len(temp_list))))))
            for t in range(bid_len):
                if t in neg_dict and t in diff_dict:
                    if len(diff_dict[t]) > 0:
                        task_c.append(
                            Or(
                                Equals(self.task(tn), Int(int(node)))
                                for tn in diff_dict[t]).Implies(
                                    Not(
                                        Or(
                                            Equals(self.task(neg_dict[t][tn]),
                                                   Int(int(node))) for tn in
                                            range(len(neg_dict[t]))))))
            task_r.append(Or(tasks_pos))
            task_r.append(And(task_c))

            task_constraints.append(And(task_r))

        # creates the encoding for the tasks facts, i.e., where a task can be mapped
        task_facts = And(
            ExactlyOne(Equals(self.task(t), Int(n)) for n in offers[t])
            for t in offers.keys())
        # encodes the facts related to the latency between nodes
        latency_domain = And(domain)  # encodes the domain
        # encode the latency constraint for our problem
        problem = Plus(p for p in prob)
        # ensure that the solution does not exceed the available resources of a participant
        tasks_const = And(task_constraints)

        # put everything together into one sat formula
        facts = And(task_facts, tasks_const)
        f1 = facts.And(latency_domain)
        formula = f1.And(LE(problem, Int(SLA)))

        return formula, tasks, prob, latencies, task_facts, tasks_const, latency_domain
Пример #9
0
    def encode_shape(self):
        
        #[@TODO]If p in {Operators} support to perform selective formula creation.
        
        logging.debug('Encoding (Prop) Shape Rules...')

        #a) Each node is labeled with exactly (At Least, At Most) one label (Operator or variable).
        c_1_a = [] # At least constraints
        logging.debug('c_1_a: Each node is labeled with at least one label:')
        
        for i in range(1, self.d + 1):
            c_1_a.append(And([Or(self.x[i, label] for label in self.L)]))
        logging.debug('c_1_a:%s'%(c_1_a))

        c_1_b = [] # At Most Constraints
        #product of label, not reflex and not commutative 
        prod_labels = list(filter(lambda t: t[0] < t[1], product(self.L,self.L)))
        
        logging.debug('c_1_b: Each node is labeled with at most one label:')        
        
        for i in range(1, self.d + 1):
            
            or_cls = []
            for (l,l1) in prod_labels:
                or_cls.append(Or(Not(self.x[i,l]), Not(self.x[i,l1])))
            c_1_b.append(And(or_cls))    

        logging.debug('c_1_b:%s'%(c_1_b))    
    

        c_2 = []
        logging.debug('c_2: Each node is labeled with a binary operator has always (exactly) two outgoing edges:')
        for i in range(2, self.d + 1):
            out_edges = self.aux_out_egdes(i)
            and_cls = []                            
            for label in self.binaryOp:
                or_cls = []
                for (u,v) in out_edges:
#                    logging.debug('%s => %s and %s '%(self.x[i, label], self.l[u], self.r[v]))
                    or_cls.append(And(self.l[u], self.r[v]))
                and_cls.append(Implies(self.x[i, label], ExactlyOne(or_cls)))
            c_2.append(And(and_cls))        
        logging.debug('c_2:%s'%(c_2))


        c_3 = []
        logging.debug('c_3: Each node is labeled with a unary operator has exactly one outgoing edge (Default: Left edge) and no right edge:')            
        # At most constraint
        for i in range(2, self.d + 1):
            out_edges = self.aux_out_egdes(i)
            and_cls = []                            
            for label in self.unaryOp:
                or_cls = []
                right_edge = []                
                for (u,v) in out_edges:
                    if not self.l[u] in or_cls:                     
                        or_cls.append(self.l[u])
                        right_edge.append(Not(self.r[u]))
                and_cls.append(Implies(self.x[i, label], ExactlyOne(or_cls)))
                and_cls.append(Implies(self.x[i, label], And(right_edge)))
#                logging.debug('%s => ExactlyOne(%s) '%(self.x[i, label], ExactlyOne(or_cls)))
            c_3.append(And(and_cls))        
        logging.debug('c_3:%s'%(c_3))
            
            
        #d) each node labeled with AP has no outgoing edge (neither left, nor right)
#        print('****:',self.x)
        logging.debug('c_4: Each node is labeled from AP has no outgoing edge:')                    
        c_4 = []        
        for i in range(2, self.d + 1):
            out_edges = self.aux_out_egdes(i)
            and_cls = []                            
            for label in self.AP:
                or_cls = []                
                for (u,v) in out_edges:
#                    logging.debug('%s => %s and %s '%(self.x[i, label], self.l[u], self.r[v]))
                    or_cls.append(Not(self.l[u]))
                    or_cls.append(Not(self.r[v]))                    
                and_cls.append(Implies(self.x[i, label], And(or_cls)))
            c_4.append(And(and_cls))        
        logging.debug('c_4:%s'%(c_4))

        #e) node 1 is always labeled with AP
        c_5_a = []
        logging.debug('c_5: node 1 is always labeled with at least one label from AP:')
        for label in self.AP:
            c_5_a.append(self.x[1, label])
        logging.debug('c_5_a:%s'%(c_5_a))
        
#        print('++++++++++++++:',c_5_a)
        c_5_b = []
        logging.debug('c_5: node 1 is always labeled with at most one label from AP:')
        prod_labels = list(filter(lambda t: t[0] < t[1], product(self.AP,self.AP)))    

        for (u,v) in prod_labels:
            c_5_b.append(Or(Not(self.x[1, u]), Not(self.x[1,v])))
        
        logging.debug('c_5_b:%s'%(c_5_b))
        
        
        c_6 = []
        #Quite strong replace it with simpler one.
        logging.debug('c_6: Each node labeled with operator has a parent also labeled with the operator:')
        for i in range(2, self.d + 1):
            if i + 1 < self.d+1:
                c_6.append(Implies(self.aux_or_cls(i), self.aux_or_cls(i + 1)))
        logging.debug('c_6: %s'%(c_6))

#        logging('Left', And(c_6))

        c_7 = []
        logging.debug('c_7: Each node has exactly at least incoming edge (except root node):')            
        for i in range(1, self.d+1):
            or_cls = []
            for j in range(i + 1, self.d+1):
                or_cls.append(self.l[j,i])
                or_cls.append(self.r[j,i])
            if len(or_cls) != 0:    
                c_7.append(Or(or_cls))    
        
        logging.debug('c_7: %s'%(c_7))

        #k) Once and Hence rule doesn't come in same succession?
        logging.debug('All rules encoding well-defined pLTL in shape of a (DAG)')            
        
        c_8 = [self.x[self.d,'G']]
        for i in range(1, self.d):
            c_8.append(Not(self.x[i, 'G']))
        
#Verifying particular solution.        
#        c_9 = [self.x[1,'q'], self.x[2,'p'], self.x[3,'Y'], self.x[4,'|'], self.x[5,'O']]   
        
        #Models of ast_enc are pLTL ASTs 
        ast_enc = And(c_1_a) & And(c_1_b) &  And(c_2) & And(c_3) & And(c_4) & Or(c_5_a) & And(c_5_b) & And(c_6)  & And(c_7) & And(c_8) #& And(c_9)
#        ast_enc = ast_enc & self.x[1, 'Top']
        return ast_enc