def __init__(self, dimacs_cnf, mct_mode='basic'): self.validate(locals()) super().__init__() self._mct_mode = mct_mode ls = [ l.strip() for l in dimacs_cnf.split('\n') if len(l) > 0 and not l.strip()[0] == 'c' ] headers = [l for l in ls if l[0] == 'p'] if len(headers) == 1: p, sig, nv, nc = headers[0].split() assert p == 'p' and sig == 'cnf' else: raise ValueError('Invalid cnf format for SAT.') h_nv, h_nc = int(nv), int(nc) cs = [ c.strip() for c in ' '.join([l for l in ls if not l[0] == 'p']).split(' 0') if len(c) > 0 ] cnf_expr = [[int(v) for v in c.split() if not int(v) == 0] for c in cs if (len(c.replace('0', '')) > 0) and ( '0' <= c[0] <= '9' or c[0] == '-')] self._cnf = CNF(cnf_expr) if not h_nv == self._cnf.num_variables: logger.warning( 'Inaccurate variable count {} in cnf header, actual count is {}.' .format(h_nv, nv)) if not h_nc == self._cnf.num_clauses: logger.warning( 'Inaccurate clause count {} in cnf header, actual count is {}.' .format(h_nc, nc))
def _process_expr(self): self._num_vars = self._expr.degree ast = self._expr.to_cnf().to_ast() ast = LogicExpressionOracle._normalize_literal_indices( ast, self._expr.usupport) if self._optimization == 'off': self._nf = CNF(ast, num_vars=self._num_vars) else: # self._optimization == 'espresso': expr_dnf = self._expr.to_dnf() if expr_dnf.is_zero() or expr_dnf.is_one(): self._nf = CNF(('const', 0 if expr_dnf.is_zero() else 1), num_vars=self._num_vars) else: expr_dnf_m = espresso_exprs(expr_dnf)[0] expr_dnf_m_ast = LogicExpressionOracle._normalize_literal_indices( expr_dnf_m.to_ast(), expr_dnf_m.usupport) if isinstance(expr_dnf_m, AndOp): self._nf = CNF(expr_dnf_m_ast, num_vars=self._num_vars) elif isinstance(expr_dnf_m, OrOp): self._nf = DNF(expr_dnf_m_ast, num_vars=self._num_vars) else: raise AquaError( 'Unexpected espresso optimization result expr: {}'. format(expr_dnf_m))
class SAT(Oracle): CONFIGURATION = { 'name': 'SAT', 'description': 'Satisfiability Oracle', 'input_schema': { '$schema': 'http://json-schema.org/schema#', 'id': 'sat_oracle_schema', 'type': 'object', 'properties': { 'dimacs_cnf': { 'type': 'string', }, 'mct_mode': { 'type': 'string', 'default': 'basic', 'oneOf': [{ 'enum': ['basic', 'advanced'] }] }, }, 'additionalProperties': False } } def __init__(self, dimacs_cnf, mct_mode='basic'): self.validate(locals()) super().__init__() self._mct_mode = mct_mode ls = [ l.strip() for l in dimacs_cnf.split('\n') if len(l) > 0 and not l.strip()[0] == 'c' ] headers = [l for l in ls if l[0] == 'p'] if len(headers) == 1: p, sig, nv, nc = headers[0].split() assert p == 'p' and sig == 'cnf' else: raise ValueError('Invalid cnf format for SAT.') h_nv, h_nc = int(nv), int(nc) cs = [ c.strip() for c in ' '.join([l for l in ls if not l[0] == 'p']).split(' 0') if len(c) > 0 ] cnf_expr = [[int(v) for v in c.split() if not int(v) == 0] for c in cs if (len(c.replace('0', '')) > 0) and ( '0' <= c[0] <= '9' or c[0] == '-')] self._cnf = CNF(cnf_expr) if not h_nv == self._cnf.num_variables: logger.warning( 'Inaccurate variable count {} in cnf header, actual count is {}.' .format(h_nv, nv)) if not h_nc == self._cnf.num_clauses: logger.warning( 'Inaccurate clause count {} in cnf header, actual count is {}.' .format(h_nc, nc)) @property def variable_register(self): return self._cnf.qr_variable @property def ancillary_register(self): return self._cnf.qr_ancilla @property def outcome_register(self): return self._cnf.qr_outcome def construct_circuit(self): return self._cnf.construct_circuit(mct_mode=self._mct_mode) def evaluate_classically(self, assignment): assignment_set = set(assignment) for clause in self._cnf.expr: if assignment_set.isdisjoint(clause): return False return True def interpret_measurement(self, top_measurement=None): return [(var + 1) * (int(tf) * 2 - 1) for tf, var in zip( top_measurement[::-1], range(len(top_measurement)))]