Esempio n. 1
0
def get_constraint(idpool: IDPool, id2varmap,
                   constraint: tConstraint) -> CNFPlus:
    """ Generate formula for a given cardinality constraint"""
    validate_constraint(constraint)
    lits = []
    for ta in constraint.tas:
        t1 = tuple((constraint.course_name, ta))
        if t1 not in id2varmap.keys():
            id1 = idpool.id(t1)
            id2varmap[t1] = id1
        else:
            id1 = id2varmap[t1]
        lits.append(id1)

    if constraint.type == tCardType.GREATEROREQUALS:
        if (constraint.bound == 1):
            cnf = CNFPlus()
            cnf.append(lits)
        elif (constraint.bound > len(lits)):
            msg = "Num TAs available for constraint:" + constraint.con_str + "is more than the bound in the constraint. \
            Changing the bound to " + str(len(lits)) + ".\n"
            print(msg, file=sys.stderr)
            constraint.bound = len(lits)

        cnf = CardEnc.atleast(lits, vpool=idpool, bound=constraint.bound)
    elif constraint.type == tCardType.LESSOREQUALS:
        cnf = CardEnc.atmost(lits, vpool=idpool, bound=constraint.bound)
    return cnf
Esempio n. 2
0
class MinimalSubset_2:
    def __init__(self, k):
        self.map_atoms = {}
        self.atoms_counter = 1
        self.cnf = CNFPlus()
        self.min_card = math.inf
        self.number_of_diagnoses = 0
        self.time = 0
        self.k = k
        self.atmost_cluse = []

    def add_soft(self, c):
        if self.map_atoms.get(c) is None:
            self.map_atoms[c] = self.atoms_counter
            self.atoms_counter += 1
        self.cnf.append([self.map_atoms[c], self.k])

    def add_atmost(self, ls):
        self.atmost_cluse = ls

    def create_dictionary(self, statement):
        atoms = statement.atoms()
        for letter in atoms:
            if self.map_atoms.get(str(letter)) is None:
                self.map_atoms[str(letter)] = self.atoms_counter
                self.atoms_counter = self.atoms_counter + 1

    def convert_letters_to_integer(self, atom):
        key = atom.replace('~', '')
        int_value = self.map_atoms[key]
        if '~' in atom:
            return int_value * -1
        return int_value

    def convert_integer_to_letters(self, integer):
        for k, v in self.map_atoms.items():
            if v == abs(integer):
                if integer < 0:
                    return '~' + k
                else:
                    return k

    def convert_statement(self, statement):
        statement_cnf = str(statement)
        statement_cnf = statement_cnf.replace('(', "")
        statement_cnf = statement_cnf.replace(')', "")
        list_statements = statement_cnf.split('&')
        literals_list = []
        res = []
        for s in list_statements:
            literals_list.append(s.split('|'))
        for k in literals_list:
            clu = []
            for x_temp in k:
                x_temp = x_temp.replace(" ", "")
                clu.append(self.convert_letters_to_integer(x_temp))
            res.append(clu)
            self.cnf.append(clu)
        return res

    def find_mini_card(self):
        solver = Minicard(bootstrap_with=self.cnf)
        solver.add_atmost(self.atmost_cluse, self.k)
        flag = True
        while flag:
            flag = solver.solve()
            ans = solver.get_model()
            if self.k == 0:
                self.k += 1
                self.min_card = self.k
                break
            if not flag:
                self.k += 1
                self.min_card = self.k + 1
                break
            if flag:
                self.k = self.k - 1
                solver = Minicard(bootstrap_with=self.cnf)
                solver.add_atmost(self.atmost_cluse, self.k)

    def run_solver(self):
        start_time = time.time()
        current_time = None
        self.find_mini_card()
        solver = Minicard(bootstrap_with=self.cnf)
        solver.add_atmost(self.atmost_cluse, self.k)
        while solver.solve():
            ans = solver.get_model()
            ans = [self.convert_integer_to_letters(x) for x in ans]
            counter = 0
            for x in ans:
                if x.startswith('~') and 'gate' in x:
                    counter = counter + 1
                    solver.add_clause(
                        [abs(self.convert_letters_to_integer(x))])
            if counter == 0:
                break
            self.number_of_diagnoses = self.number_of_diagnoses + 1
            current_time = time.time()
            if (current_time - start_time) >= 60:
                print('finish run out of time')
                self.time = np.nan
                self.min_card = np.nan
                self.number_of_diagnoses = np.nan
                return
        if current_time is None:
            current_time = time.time()
        self.time = current_time - start_time