Esempio n. 1
0
    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))
Esempio n. 2
0
    def fbp(self, symbols, steps, context_given=set(),
            context_not_given=set()):
        symbolSet = Reaction._create_symbol_set(symbols)
        if not isinstance(steps, int) or steps < 0:
            raise ExceptionReactionSystem.InvalidNumber()
        if (not isinstance(context_given, set)
                or not isinstance(context_not_given, set)):
            raise ExceptionReactionSystem.InvalidContextSet()

        self._cg = context_given
        self._cng = context_not_given

        self._calculated_items = {}

        if 'time' in sys.argv:
            start = time.time()

        formula = ONE
        for symbol in symbolSet:
            formula = And(formula, self.cause(symbol))
            formula = formula.to_dnf()

        formula = self._fbs_iterative(formula, steps)

        if not isinstance(formula, Atom) and formula.is_dnf():
            formula = espresso_exprs(formula)[0]

        if 'time' in sys.argv:
            print(time.time() - start)

        return formula
Esempio n. 3
0
 def eval_espresso(self):
     """
     Minimize this puzzle's formula using espresso
     :return Expr: the minimized form of this puzzle
     """
     esp_form, = espresso_exprs(self.formula.to_dnf())
     return esp_form
Esempio n. 4
0
def minimize_rule(rule):
    """
    Given a rule in string form 'a | b & c',
    return (as strings)
        the espresso minimized form of the rule
        and the support (set of variables in the minimized rule)
    Why don't we just return the minimized rule? There can be problems
    converting the minimized rule back to an expression due to recursion depth.
    """
    f1 = expr(rule)
    if f1.is_one() or f1.is_zero():
        reduced_rule = str(bool(f1))
        return reduced_rule, set()
    else:
        f1_min, = espresso_exprs(f1.to_dnf())
        return str(f1_min), set(str(x) for x in f1_min.support)
Esempio n. 5
0
def perform_bin_expr_min(base_tokens: list, wildcard='*'):
    """ Perform binary expression minimization for a list of base tokens

    :param list base_tokens: list of base tokens that have same length.
        Each base token is a list of '0' or '1'.
    :param wildcard: the element to denote "do not care" character

    :returns: list of minimized tokens of '0', '1' or 'wildcard'
    """
    if not base_tokens:
        return []

    dim = len(base_tokens[0])
    X = exprvars('x', dim)
    f = expr(0)  # start of an OR
    for baseToken in base_tokens:
        prod = expr(1)  # start of an AND
        for i in range(dim):
            if baseToken[i] == 1:
                prod = prod & X[i]
            else:
                prod = prod & ~X[i]
        f = f | prod

    # minimize
    fm, = espresso_exprs(f.to_dnf())

    min_tokens = []
    for s in fm.cover:
        min_token = []
        for i in range(dim):
            if X[i] in s:
                min_token.append(1)
            elif ~X[i] in s:
                min_token.append(0)
            else:
                min_token.append(wildcard)

        min_tokens.append(min_token)

    return min_tokens
Esempio n. 6
0
    def simplify(expression):

        simplified_expr, = eda.espresso_exprs(eda.expr(expression).to_dnf())

        return EspressoSimplifier.convert(simplified_expr)
Esempio n. 7
0
def general_pcu_search(fInName, str4true, str4false, desiredResponses=None, subsetConstraints=None):
    '''
    Accepts a file containing comma-separated value rows of responses and minimises according to the desiredResponses and constraints imposed
    '''

    # = Read in the header, which creates allResponses, and order our desiredResponses to correspond to that
    a = time.clock()
    print('Started. Obtaining list of unobserveds ...')

    fIn = open(fInName)
    csv_f = csv.reader(fIn)
    allResponses = next(csv_f)
    fIn.close()

    # = Get subsetResponses, so that they're in order of appearance in the file we're using, they are the response outcomes we're including in the minimisation

    if subsetConstraints: 
        fileIdx = [allResponses.index(sR[0]) for sR in subsetConstraints]
        subsetResponses = tuple(zip(*sorted(zip(fileIdx,subsetConstraints))))[1]
        subsetResponses = tuple(zip(*subsetResponses)) #subset responses so it's ( (resp1, resp2, ...), (val1, val2, ...) ) in order of appearance
    else:
        subsetResponses = None

    # = Get desiredResponses, so that they're in order of appearance in the file we're using, they are the responses species we're including in the minimisation

    if desiredResponses:
        # Sort our desiredResponses according to the order they appear in allResponses
        fileIdx = [allResponses.index(dR) for dR in desiredResponses]
        desiredResponses = list(zip(*sorted(zip(fileIdx,desiredResponses))))[1]
    else:
        if subsetResponses:
            # Make sure our subsetted responses aren't included
            desiredResponses = list(filter(lambda r: not r in subsetResponses[0], allResponses))
        else:
            desiredResponses = allResponses

    boolLen = len(desiredResponses)

    # = Create masks

    desiredResponsesMask = [aR in desiredResponses for aR in allResponses]

    if subsetResponses:
        subsetMask = [r in subsetResponses[0] for r in allResponses]
    else:
        subsetMask = None

    # = Get all of our unobserved combinations of desiredResponses as a set of integers

    if subsetConstraints: 
        unobservedInts = getUnobservedInts(fInName, desiredResponsesMask, boolLen, str4true, subsetMask, subsetResponses[1])
    else:
        unobservedInts = getUnobservedInts(fInName, desiredResponsesMask, boolLen, str4true)

    # = Turn our set of unobserveds into a boolean expression =
    b = time.clock()
    print(b-a)
    print('List of unobserved obtained (length=' + str(len(unobservedInts)) + '). Boolean expression being generated ...')

    # Create our boolean variables and some useful dictionaries
    x, x2s, r2idx = getRespvarList2BoolvarList(desiredResponses, str4true, str4false)

    # Turn each integer representing unobserved into a
    # boolean-and into boolean expression 
    unobservedBoolexpr = intList2boolexpr(unobservedInts, x)

    # = Use espresso to minimise the unobservedBoolexpr
    c = time.clock()
    print(c-b)
    print('Boolean expression generated. Minimisation being performed ...')

    boolExprMin, = espresso_exprs(unobservedBoolexpr)

    # Turn boolean expression into list of list of strings
    PCUList = boolexpr2RespvalList(boolExprMin, x2s)


    # = Write a file of the results
    d = time.clock()
    print(d-c)
    print('Minimisation complete.')

    # = Write the PCUs we've found to a file

    fOutName = fInName.split('.c')[0]

    if subsetConstraints:

        # Write the subsetMask as an integer, use as identifier for file
        subsetID = int(''.join(['1' if a else '0' for a in subsetMask]),2)
        fOutName += '_sub' + str(subsetID) 

    # Write the desiredResponseMask as an integer, use as identifier
    drID = int(''.join(['1' if a else '0' for a in desiredResponsesMask]),2) 
    fOutName += '_dr' + str(drID) + '_pcus.py'

    fOut = open(fOutName,'w')
    print('Writing ' + fOutName + ' ...')

    # Write a preamble about the subsetting, if needed
    if subsetConstraints:

        fOut.write('# Minimisation performed on a subset subject to the following constraints\n')
        for sName, sConst in subsetConstraints:
            fOut.write('# ')
            fOut.write(sName + ': ' + sConst + '\n')

    # First write the desiredResponses, so we know on which part the search was done
    fOut.write('searchedResponses = [\'' + '\',\''.join(desiredResponses) + '\']\n')

    # Now write each PCU
    fOut.write('PCUList = [\n')
    for PCU in PCUList:
        fOut.write('[\'' + '\',\''.join(PCU) + '\'],\n')
    fOut.write(']\n')

    fOut.close()
b = time.clock()
print('b')

# Create our boolean variables and some useful dictionaries
x, x2s, r2idx = getRespvarList2BoolvarList(desiredResponses, str4true, str4false)

# Turn each integer representing unobserved into a
# boolean-and into boolean expression 
unobservedBoolexpr = intList2boolexpr(unobservedInts, x)

# = Use espresso to minimise the unobservedBoolexpr
c = time.clock()
print('c')

boolExprMin, = espresso_exprs(unobservedBoolexpr)
PCUList = boolexpr2RespvalList(boolExprMin, x2s)


# = Write a file of the results

d = time.clock()
print('d')

print(d-c)
print(c-b)
print(b-a)

# Write the PCUs we've found to a file
fOutName = fInName.split('.c')[0]
fOutName = fOutName + '_pcus.py'