Exemplo n.º 1
0
def exact_match(test_expr, target_expr):
    """Test if the entered expression exactly matches the known expression.

       This equality checking does not expand brackets or perform much simplification,
       so is useful for checking if the submitted answer requires simplifying.
       Testing is first done using '==' which checks that the order of symbols
       matches and will not recognise 'x + 1' as equal to '1 + x'.
       The 'srepr' method outputs sympy's internal representation in a canonical form
       and thus, while performing no simplification, it allows ordering to be ignored
       in exact match checking. These two forms are treated equivalently as 'exact'
       matching.

       Returns True if the sympy expressions have the same internal structure,
       and False if not.

        - 'test_expr' should be the untrusted sympy expression to check.
        - 'target_expr' should be the trusted sympy expression to match against.
    """
    print "[EXACT TEST]"
    if test_expr == target_expr:
        print "Exact Match (with '==')"
        return True
    elif sympy.srepr(test_expr) == sympy.srepr(target_expr):
        print "Exact Match (with 'srepr')"
        return True
    else:
        return False
Exemplo n.º 2
0
 def __str__(self):
     asstr = "Objective: "
     asstr += srepr(self.objective)
     asstr += "\n\n"
     asstr += "Subject to:\n"
     for c in self._constraints:
         asstr += srepr(c)
         asstr += "\n"
     return asstr
Exemplo n.º 3
0
def test_complex_space():
    c1 = ComplexSpace(2)
    assert isinstance(c1, ComplexSpace)
    assert c1.dimension == 2
    assert sstr(c1) == "C(2)"
    assert srepr(c1) == "ComplexSpace(Integer(2))"

    n = Symbol("n")
    c2 = ComplexSpace(n)
    assert isinstance(c2, ComplexSpace)
    assert c2.dimension == n
    assert sstr(c2) == "C(n)"
    assert srepr(c2) == "ComplexSpace(Symbol('n'))"
    assert c2.subs(n, 2) == ComplexSpace(2)
Exemplo n.º 4
0
def test_create_f():
    i, j, n, m = symbols('i,j,n,m')
    o = Fd(i)
    assert isinstance(o, CreateFermion)
    o = o.subs(i, j)
    assert o.atoms(Symbol) == {j}
    o = Fd(1)
    assert o.apply_operator(FKet([n])) == FKet([1, n])
    assert o.apply_operator(FKet([n])) == -FKet([n, 1])
    o = Fd(n)
    assert o.apply_operator(FKet([])) == FKet([n])

    vacuum = FKet([], fermi_level=4)
    assert vacuum == FKet([], fermi_level=4)

    i, j, k, l = symbols('i,j,k,l', below_fermi=True)
    a, b, c, d = symbols('a,b,c,d', above_fermi=True)
    p, q, r, s = symbols('p,q,r,s')

    assert Fd(i).apply_operator(FKet([i, j, k], 4)) == FKet([j, k], 4)
    assert Fd(a).apply_operator(FKet([i, b, k], 4)) == FKet([a, i, b, k], 4)

    assert Dagger(B(p)).apply_operator(q) == q*CreateBoson(p)
    assert repr(Fd(p)) == 'CreateFermion(p)'
    assert srepr(Fd(p)) == "CreateFermion(Symbol('p'))"
    assert latex(Fd(p)) == r'a^\dagger_{p}'
Exemplo n.º 5
0
def save_sympy_matrix(matrix, filename):
    """Writes a matrix to file in the SymPy representation (srepr)."""
    num_rows, num_cols = matrix.shape
    with open(filename, 'w') as f:
        f.write(str(num_rows) + "\n")
        f.write(str(num_cols) + "\n")
        for expr in matrix:
            f.write(srepr(expr) + "\n")
Exemplo n.º 6
0
def test_fixed_bosonic_basis():
    b = FixedBosonicBasis(2, 2)
    # assert b == [FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]
    state = b.state(1)
    assert state == FockStateBosonKet((1, 1))
    assert b.index(state) == 1
    assert b.state(1) == b[1]
    assert len(b) == 3
    assert str(b) == '[FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]'
    assert repr(b) == '[FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]'
    assert srepr(b) == '[FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]'
Exemplo n.º 7
0
def test_annihilate_f():
    i, j, n, m = symbols('i,j,n,m')
    o = F(i)
    assert isinstance(o, AnnihilateFermion)
    o = o.subs(i, j)
    assert o.atoms(Symbol) == {j}
    o = F(1)
    assert o.apply_operator(FKet([1, n])) == FKet([n])
    assert o.apply_operator(FKet([n, 1])) == -FKet([n])
    o = F(n)
    assert o.apply_operator(FKet([n])) == FKet([])

    i, j, k, l = symbols('i,j,k,l', below_fermi=True)
    a, b, c, d = symbols('a,b,c,d', above_fermi=True)
    p, q, r, s = symbols('p,q,r,s')
    assert F(i).apply_operator(FKet([i, j, k], 4)) == 0
    assert F(a).apply_operator(FKet([i, b, k], 4)) == 0
    assert F(l).apply_operator(FKet([i, j, k], 3)) == 0
    assert F(l).apply_operator(FKet([i, j, k], 4)) == FKet([l, i, j, k], 4)
    assert str(F(p)) == 'f(p)'
    assert repr(F(p)) == 'AnnihilateFermion(p)'
    assert srepr(F(p)) == "AnnihilateFermion(Symbol('p'))"
    assert latex(F(p)) == 'a_{p}'
def findForwarBackward(formula):
    fragments = findBrackets(formula)
    
    for i in range(len(fragments)):
        #formula = re.sub("(\w)"+re.escape(fragments[0]),r"\1_fragmentNb%d_"%i,formula)
        formula = formula.replace(fragments[i],"_fragmentNb%d_"%i)
    variables = unique(re.findall("_?[A-Za-z]\w*",formula))
    command = ",".join(variables)+" = sympy.symbols(\"" + ",".join(variables) + "\")"
    exec(command)
    formula = sympy.expand(formula)
    
    backward = []
    forward = []
    additiveBlocks = sympy.srepr(formula)
    if additiveBlocks[0:3] == "Add":
        additiveBlocks = sympy.sympify(additiveBlocks[4:len(additiveBlocks)-1])
    else:
        additiveBlocks = [sympy.sympify(additiveBlocks)]
    for ee in additiveBlocks:
        ee = str(sympy.simplify(ee))
        ee = str(ee)
        if ee[0] == "-":
            ee = re.sub("^-","",ee)
            backward.append(ee)        
        else:
            forward.append(ee)
    backward = "+".join(backward)
    forward = "+".join(forward)
    for i in range(len(fragments)):
        backward = backward.replace("_fragmentNb%d_"%i,fragments[i])
        forward = forward.replace("_fragmentNb%d_"%i,fragments[i])

        
        # backward = re.sub("(?<!\w)fragmentNb%d(?!\w)"%i,fragments[i],backward)
        # forward = re.sub("(?<!\w)fragmentNb%d(?!\w)"%i,fragments[i],forward)
    return(forward,backward)
Exemplo n.º 9
0
 def __eq__(self, other):
     from sympy import srepr
     return (isinstance(other, ParameterExpression)
             and self.parameters == other.parameters
             and srepr(self._symbol_expr) == srepr(other._symbol_expr))
Exemplo n.º 10
0
        g = self.g
        g_inv = self.g.inv()
        scalar_curv = sympy.simplify(g_inv*Ricci)
        scalar_curv = sympy.trace(scalar_curv)
        self.scalar_curv = scalar_curv
        return self.scalar_curv
           

if __name__ == "__main__":
    import find_metric
    k = -1
    g,diff_form = find_metric.analytical(k) # k=0 gives flat space
    R = Riemann(g,dim=3,sys_title="analytical")
    print R.metric
    from sympy import srepr
    print srepr(R.system)
    RC = R.find_Christoffel_tensor()
    RR = R.find_Ricci_tensor()
    scalarRR = R.find_scalar_curvature()

    print "\nThe analytical curve element has the following metric for k=%.1f"%k
    print g
    print "\nThe Ricci tensor is given as"
    print RR
    print "\nand the scalar curvature is"
    print scalarRR 
    
    """
    from sympy.abc import r,theta, phi, u,v
    g,diff_form = find_metric.flat_sphere()
    diff = [['dv*dv','dv*dw'],['dw*dv','dw*dw']]
Exemplo n.º 11
0
def test_issue1689():
    assert srepr(S(1.0 + 0J)) == srepr(S(1.0)) == srepr(Float(1.0))
    assert srepr(Float(1)) != srepr(Float(1.0))
Exemplo n.º 12
0
def test_hilbert_space():
    hs = HilbertSpace()
    assert isinstance(hs, HilbertSpace)
    assert sstr(hs) == "H"
    assert srepr(hs) == "HilbertSpace()"
def d(obj):
    print("WTF", type(obj), srepr(obj))
Exemplo n.º 14
0
def print_conversions(*modules):
    for mod in modules:
        for x in module_conversions(mod):
            print '("' + mod.NAME + '", "%s", "%s"): "%s"' % (x[0], x[1],
                                                              srepr(x[2]))
Exemplo n.º 15
0
def print_conversions(*modules):
    for mod in modules:
        for x in module_conversions(mod):
            print '("' + mod.NAME + '", "%s", "%s"): "%s"' % (
                x[0], x[1], srepr(x[2]))
Exemplo n.º 16
0
def _get_srepr(expr):
    s = srepr(expr)
    s = re.sub(r"WildDot\('(\w+)'\)", r"\1", s)
    s = re.sub(r"WildPlus\('(\w+)'\)", r"*\1", s)
    s = re.sub(r"WildStar\('(\w+)'\)", r"*\1", s)
    return s
 def exprstrout(key, expr):
     return srepr(expr) + " " + PolynomialOutput.messages.get(key, None)
Exemplo n.º 18
0
 def octoutput(x, et):
     OCTCODE_INT = 1001
     OCTCODE_DOUBLE = 1002
     OCTCODE_STR = 1003
     OCTCODE_BOOL = 1005
     OCTCODE_COMPLEX = 1006
     OCTCODE_DICT = 1010
     OCTCODE_SYM = 1020
     x = objectfilter(x)
     if isinstance(x, bool):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_BOOL)
         f = ET.SubElement(a, "f")
         f.text = str(x)
     elif x is None or isinstance(x, (sp.Basic, sp.MatrixBase)):
         # FIXME: is it weird to pretend None is a SymPy object?
         if isinstance(x, (sp.Matrix, sp.ImmutableMatrix)):
             _d = x.shape
         elif isinstance(x, sp.MatrixExpr):
             # nan for symbolic size
             _d = [float(r) if (isinstance(r, sp.Basic) and r.is_Integer)
                   else float('nan') if isinstance(r, sp.Basic)
                   else r for r in x.shape]
         elif x is None:
             _d = (1,1)
         else:
             _d = (1, 1)
         try:
             pretty_ascii = sp.pretty(x, use_unicode=False)
         except:
             # e.g., SymPy issue #10414
             pretty_ascii = str(x)
         pretty_unicode = sp.pretty(x, use_unicode=True)
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_SYM)
         f = ET.SubElement(a, "f")
         f.text = sympy.srepr(x)
         f = ET.SubElement(a, "f")
         f.text = str(_d[0])
         f = ET.SubElement(a, "f")
         f.text = str(_d[1])
         f = ET.SubElement(a, "f")
         f.text = str(x)  # esc?
         f = ET.SubElement(a, "f")
         f.text = myesc(pretty_ascii)
         f = ET.SubElement(a, "f")
         f.text = myesc(pretty_unicode)
     elif isinstance(x, (list, tuple)):
         c = ET.SubElement(et, "list")
         for y in x:
             octoutput(y, c)
     elif isinstance(x, sp.compatibility.integer_types):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_INT)
         f = ET.SubElement(a, "f")
         f.text = str(x)
     elif isinstance(x, float):
         # We pass IEEE doubles using the exact hex representation
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_DOUBLE)
         f = ET.SubElement(a, "f")
         f.text = d2hex(x)
     elif isinstance(x, complex):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_COMPLEX)
         f = ET.SubElement(a, "f")
         f.text = d2hex(x.real)
         f = ET.SubElement(a, "f")
         f.text = d2hex(x.imag)
     elif isinstance(x, sp.compatibility.string_types):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_STR)
         f = ET.SubElement(a, "f")
         f.text = myesc(x)
     elif isinstance(x, dict):
         # Note: the dict cannot be too complex, keys must convert to
         # strings for example.  Values can be dicts, lists.
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_DICT)
         # Convert keys to strings
         keystr = [str(y) for y in x.keys()]
         c = ET.SubElement(a, "list")
         octoutput(keystr, c)
         c = ET.SubElement(a, "list")
         # FIXME: bit of a kludge, use iterable instead of list, tuple above?
         if sys.version_info >= (3, 0):
             octoutput(list(x.values()), c)
         else:
             octoutput(x.values(), c)
     else:
         raise ValueError("octoutput does not know how to export type " + str(type(x)))
Exemplo n.º 19
0
def latexParsing(token, tokenPos):
    '''
    LateX parsing function for DIM files
    '''
    lastPos = 0

    # Each line gets stored as a separate list item in the list
    l_depTokens = []
    l_posTokens = []
    l_morTokens = []
    stringRep = ''

    # Try parsing the latex code as is
    if len(token) == 14:
        try:
            expr = parse_latex(LATEXMAP[token])
            stringRep = srepr(expr)

        except (LaTeXParsingError, SympifyError, TypeError):
            # Good chance the problem is the leading and trailing parens -
            # remove them and try again
            try:
                expr = parse_latex(LATEXMAP[token].lstrip('(').rstrip(')'))
                stringRep = srepr(expr)
            except (LaTeXParsingError, ValueError, TypeError):
                pass

    # If we have a sympy string representation...
    if stringRep != '':

        # Problematic artefacts from sympy parsing
        stringRep = stringRep.replace(", precision=53", "")
        stringRep = stringRep.replace("oo", "Symbol(inf)")

        # Call gov_dep function to get list of dependencies, objects
        l_dependencies = (gov_dep(stringRep))

        # This will store each dependency item
        dictAll = {}

        # If we actually have a list of items rather than a single
        # symbol/integer
        if len(l_dependencies) > 0:

            # Do the D in DIM
            for li in l_dependencies:

                head = li[0]
                tail = li[1]
                dictAll[head[1]] = head[0]
                dictAll[tail[1]] = tail[0]

                l_depTokens.append(
                    (get_rel(head[0]), (head[0], head[1] + tokenPos - 1),
                     (tail[0], tail[1] + tokenPos - 1)))

                if head[1] > lastPos:
                    lastPos = head[1]

                if tail[1] > lastPos:
                    lastPos = tail[1]

        # We're dealing with just a symbol or integer
        else:

            # Keep track of govs for debugging
            dictAll[1] = stringRep
            lastPos = 1

        # Do the I and M in DIM
        for key, val in dictAll.items():

            # IF it's a symbol/integer
            if '(' in val:
                symbol, symbolType = get_symbol_and_type(val)
                l_posTokens.append('{}_{}'.format(val, symbolType.upper()))
                l_morTokens.append(val)
            else:
                thisPos = get_rel(val)
                thisPos = thisPos.upper()

                l_posTokens.append('{}_{}'.format(val, thisPos))
                l_morTokens.append(val)

    return l_depTokens, l_posTokens, l_morTokens
Exemplo n.º 20
0
 def octoutput(x, et):
     OCTCODE_INT = 1001
     OCTCODE_DOUBLE = 1002
     OCTCODE_STR = 1003
     OCTCODE_BOOL = 1005
     OCTCODE_COMPLEX = 1006
     OCTCODE_DICT = 1010
     OCTCODE_SYM = 1020
     x = objectfilter(x)
     if isinstance(x, bool):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_BOOL)
         f = ET.SubElement(a, "f")
         f.text = str(x)
     elif x is None or isinstance(x, (sp.Basic, sp.MatrixBase)):
         # FIXME: is it weird to pretend None is a SymPy object?
         if isinstance(x, (sp.Matrix, sp.ImmutableMatrix)):
             _d = x.shape
         elif isinstance(x, sp.MatrixExpr):
             # nan for symbolic size
             _d = [float(r) if (isinstance(r, sp.Basic) and r.is_Integer)
                   else float('nan') if isinstance(r, sp.Basic)
                   else r for r in x.shape]
         elif x is None:
             _d = (1,1)
         else:
             _d = (1, 1)
         try:
             pretty_ascii = sp.pretty(x, use_unicode=False)
         except:
             # e.g., SymPy issue #10414
             pretty_ascii = str(x)
         pretty_unicode = sp.pretty(x, use_unicode=True)
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_SYM)
         f = ET.SubElement(a, "f")
         f.text = sympy.srepr(x)
         f = ET.SubElement(a, "f")
         f.text = str(_d[0])
         f = ET.SubElement(a, "f")
         f.text = str(_d[1])
         f = ET.SubElement(a, "f")
         f.text = str(x)  # esc?
         f = ET.SubElement(a, "f")
         f.text = myesc(pretty_ascii)
         f = ET.SubElement(a, "f")
         f.text = myesc(pretty_unicode)
     elif isinstance(x, (list, tuple)):
         c = ET.SubElement(et, "list")
         for y in x:
             octoutput(y, c)
     elif isinstance(x, int):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_INT)
         f = ET.SubElement(a, "f")
         f.text = str(x)
     elif isinstance(x, float):
         # We pass IEEE doubles using the exact hex representation
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_DOUBLE)
         f = ET.SubElement(a, "f")
         f.text = d2hex(x)
     elif isinstance(x, complex):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_COMPLEX)
         f = ET.SubElement(a, "f")
         f.text = d2hex(x.real)
         f = ET.SubElement(a, "f")
         f.text = d2hex(x.imag)
     elif isinstance(x, str) or (sys.version_info < (3, 0) and isinstance(x, unicode)):
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_STR)
         f = ET.SubElement(a, "f")
         f.text = myesc(x)
     elif isinstance(x, dict):
         # Note: the dict cannot be too complex, keys must convert to
         # strings for example.  Values can be dicts, lists.
         a = ET.SubElement(et, "item")
         f = ET.SubElement(a, "f")
         f.text = str(OCTCODE_DICT)
         # Convert keys to strings
         keystr = [str(y) for y in x.keys()]
         c = ET.SubElement(a, "list")
         octoutput(keystr, c)
         c = ET.SubElement(a, "list")
         # FIXME: bit of a kludge, use iterable instead of list, tuple above?
         if sys.version_info >= (3, 0):
             octoutput(list(x.values()), c)
         else:
             octoutput(x.values(), c)
     else:
         raise ValueError("octoutput does not know how to export type " + str(type(x)))
Exemplo n.º 21
0
 def __str__(self):
     return "%s.%s %s %s" % (self.ibits, self.q, self.scale, srepr(
         self.expr))
def varExprNames(expression):
    variables_Str = list(set(findall(r"Symbol\(\'(\w+)\'\)", srepr(expression))))
    return [var_name for var_name in variables_Str]
Exemplo n.º 23
0
    def __init__(self, file, name, noise=None, seed=0, preprocess=None,
                 function_lib=None, extra_data_dir=None, 
                 dataset_size_multiplier=None, **kwargs):

        # Read in benchmark dataset information
        root = resource_filename("dsr", "data/")
        benchmark_path = os.path.join(root, file)
        df = pd.read_csv(benchmark_path, index_col=0, encoding="ISO-8859-1")

        # Random number generator used for sampling X values
        seed += zlib.adler32(name.encode("utf-8")) # Different seed for each name, otherwise two benchmarks with the same domain will always have the same X values
        self.rng = np.random.RandomState(seed)

        self.dataset_size_multiplier = dataset_size_multiplier if dataset_size_multiplier is not None else 1.0

        # Load raw dataset from external directory
        root_changed = False
        if extra_data_dir is not None:
            root = os.path.join(extra_data_dir,"")
            root_changed = True

        # Raw dataset
        if name not in df.index:

            if noise is not None and noise != 0:
                print("Warning: Noise will not be applied to real-world dataset.")

            dataset_path = os.path.join(root, name + ".csv")
            data = pd.read_csv(dataset_path)
            data = data.sample(frac=1, random_state=self.rng).reset_index(drop=True) # Shuffle rows
            data = data.values
            if preprocess == "standardize_y":
                mean = np.mean(data[:, -1])
                std = np.std(data[:, -1])
                data[:, -1] = (data[:, -1] - mean) / std
            elif preprocess == "standardize_all":
                data = (data - np.mean(data, axis=0)) / np.std(data, axis=0)
            elif preprocess == "shift_y":
                mean = np.mean(data[:, -1])
                data[:, -1] = data[:, -1] - mean
            elif preprocess == "shift_all":
                data = data - np.mean(data, axis=0)
            elif preprocess == "rescale_y":
                min_ = min(data[:, -1])
                max_ = max(data[:, -1])
                data[:, -1] = (data[:, -1] - min_) / (max_ - min_)
            elif preprocess == "rescale_all":
                min_ = np.min(data, axis=0)
                max_ = np.max(data, axis=0)
                data = (data - min_) / (max_ - min_)
            
            self.n_input_var = data.shape[1] - 1

            n_train = int(0.8 * data.shape[0]) # 80-20 train-test split

            self.X_train = data[:n_train, :-1]
            self.y_train = data[:n_train, -1]
            self.X_test = data[n_train:, :-1]
            self.y_test = data[n_train:, -1]

            self.y_train_noiseless = self.y_train.copy()
            self.y_test_noiseless = self.y_test.copy()

            self.sympy_expr = None
            self.numpy_expr = None
            self.fp_constant = None
            self.int_constant = None
            self.train_spec = None
            self.test_spec = None

            function_set = "Real" # Default value of library

        # Expression dataset
        else:
            row = df.loc[name]
            function_set = row["function_set"]
            self.n_input_var = row["variables"]

            # Create symbolic expression        
            self.sympy_expr = parse_expr(row["sympy"])
            self.numpy_expr = self.make_numpy_expr(row["numpy"])
            self.fp_constant = "Float" in srepr(self.sympy_expr)
            self.int_constant = "Integer" in srepr(self.sympy_expr)        

            # Create X values
            train_spec = ast.literal_eval(row["train_spec"])
            test_spec = ast.literal_eval(row["test_spec"])
            if test_spec is None:
                test_spec = train_spec
            self.X_train = self.make_X(train_spec)
            self.X_test = self.make_X(test_spec)
            self.train_spec = train_spec
            self.test_spec = test_spec

            # Compute y values
            self.y_train = self.numpy_expr(self.X_train)
            self.y_test = self.numpy_expr(self.X_test)
            self.y_train_noiseless = self.y_train.copy()
            self.y_test_noiseless = self.y_test.copy()

            # Add Gaussian noise
            if noise is not None:
                assert noise >= 0, "Noise must be non-negative."
                y_rms = np.sqrt(np.mean(self.y_train**2))
                scale = noise * y_rms
                self.y_train += self.rng.normal(loc=0, scale=scale, size=self.y_train.shape)
                self.y_test += self.rng.normal(loc=0, scale=scale, size=self.y_test.shape)

        # If root has changed
        if root_changed:
            root = resource_filename("dsr", "data/")
            
        # Create the function set (list of str)
        function_set_path = os.path.join(root, "function_sets.csv")
        df = pd.read_csv(function_set_path, index_col=0)
        self.function_set = df.loc[function_set].tolist()[0].strip().split(',')

        # Overwrite the function set
        if function_lib is not None:
            self.function_set = function_lib.strip().split(',')
 def exprstrout(key, expr):
     return srepr(expr) + " " + SingletonOutput.messages.get(key, None)
Exemplo n.º 25
0
def expr_convert_to_SIMD_intrins(expr,  SIMD_const_varnms,SIMD_const_values,SIMD_const_suffix="",debug="False"):

    # Declare all variables, so we can eval them in the next (AddSIMD & MulSIMD) step
    for item in preorder_traversal(expr):
        for i in range(len(item.args)):
            if isinstance(item.args[i],Symbol):
                var(str(item.args[i]))

    expr_orig = expr

    AbsSIMD = Function("AbsSIMD")
    AddSIMD = Function("AddSIMD")
    SubSIMD = Function("SubSIMD")
    MulSIMD = Function("MulSIMD")
    FusedMulAddSIMD = Function("FusedMulAddSIMD")
    FusedMulSubSIMD = Function("FusedMulSubSIMD")
    DivSIMD = Function("DivSIMD")
    SignSIMD = Function("SignSIMD")

    PowSIMD = Function("PowSIMD")
    SqrtSIMD = Function("SqrtSIMD")
    CbrtSIMD = Function("CbrtSIMD")
    ExpSIMD = Function("ExpSIMD")
    LogSIMD = Function("LogSIMD")
    SinSIMD = Function("SinSIMD")
    CosSIMD = Function("CosSIMD")

    # Step 1: Replace transcendental, power, and division functions with SIMD equivalents
    #         Note that due to how SymPy expresses rational numbers, the following does not
    #         affect fractional expressions of integers
    for item in preorder_traversal(expr):
        if item.func == Abs:
            expr = expr.xreplace({item: AbsSIMD(item.args[0])})
        elif item.func == exp:
            expr = expr.xreplace({item: ExpSIMD(item.args[0])})
        elif item.func == log:
            expr = expr.xreplace({item: LogSIMD(item.args[0])})
        elif item.func == sin:
            expr = expr.xreplace({item: SinSIMD(item.args[0])})
        elif item.func == cos:
            expr = expr.xreplace({item: CosSIMD(item.args[0])})
        elif item.func == sign:
            expr = expr.xreplace({item: SignSIMD(item.args[0])})

    # Fun little recursive function for constructing integer powers:
    def IntegerPowSIMD(a, n):
        if n == 2:
            return MulSIMD(a, a)
        elif n > 2:
            return MulSIMD(IntegerPowSIMD(a, n - 1), a)
        elif n <= -2:
            return DivSIMD(1, IntegerPowSIMD(a, -n))
        elif n == -1:
            return DivSIMD(1, a)

    for item in preorder_traversal(expr):
        if item.func == Pow:
            if item.args[1] == 0.5:
                expr = expr.xreplace({item: SqrtSIMD(item.args[0])})
            elif item.args[1] == -0.5:
                expr = expr.xreplace({item: DivSIMD(1,SqrtSIMD(item.args[0]))})
            elif item.args[1] == Rational(1,3):
                expr = expr.xreplace({item: CbrtSIMD(item.args[0])})
            elif item.args[1] == int(item.args[1]):
                expr = expr.xreplace({item: IntegerPowSIMD(item.args[0], item.args[1])})
            else:
                expr = expr.xreplace({item:        PowSIMD(item.args[0], item.args[1])})

    # Step 2: Replace all rational numbers (expressed as Rational(a,b))
    #         and integers with the new functions RationalTMP and
    #         IntegerTMP, where Rational(a,b) -> RationalTMP(a,b)
    #         and Integer(a) -> IntegerTMP(a)
    RationalTMP = Function("RationalTMP")
    IntegerTMP = Function("IntegerTMP")

    string = str(srepr(expr))
    string2 = re.sub(r'Integer\(([+\-0-9]+)\)',
                     "(Function('IntegerTMP')('\\1'))", string)
    expr = eval(string2)

    string = str(srepr(expr))
    string2 = re.sub(r'Rational\(([-0-9]+), ([0-9]+)\)',
                     "(Function('RationalTMP')(('\\1'),('\\2')))", string)
    expr = eval(string2)

    # Step 3: The pattern Mul(-1,Rational(a,b)) is often seen. Replace with Rational(-a,b).
    for item in preorder_traversal(expr):
        if item.func == Mul:
            idx_has_Negative1 = -10
            for i in range(len(item.args)):
                if item.args[i].func == IntegerTMP and item.args[i].args[0] == -1:
                    idx_has_Negative1 = i
            if idx_has_Negative1 >= 0:
                for i in range(len(item.args)):
                    if item.args[i].func==RationalTMP:
                        tempitem_orig = Mul(IntegerTMP(-1),RationalTMP(item.args[i].args[0], item.args[i].args[1]))
                        tempitem_new  = RationalTMP(-item.args[i].args[0], item.args[i].args[1])
                        expr = expr.subs(tempitem_orig, tempitem_new )
                        break

    # Step 4: SIMD multiplication and addition compiler intrinsics read in
    #         only two arguments at once, where SymPy's Mul() and Add()
    #         operators can read an arbitrary number of arguments.
    #         Here, we split e.g., Mul(a,b,c,d) into
    #         MulSIMD(a,MulSIMD(b,MulSIMD(c,d))),
    #         To accomplish this easily, we construct a string
    #         'MulSIMD(A,MulSIMD(B,...', where MulSIMD(a,b) is some user-
    #         defined function that takes in only two arguments, and then
    #         evaluate the string using the eval() function.
    # Implementation detail: If we did not perform Step 2 above, the eval
    #         function would automatically evaluate all Rational expressions
    #         as though they were input as integers: e.g., 1/2 evaluates to 0.
    #         This is undesirable, so we instead define new, temporary
    #         functions IntegerTMP and RationalTMP that are undisturbed by
    #         the eval()
    for item in preorder_traversal(expr):
        if item.func == Mul:
            blahtmp = symbols('blahtmp')
            tempitem = blahtmp
            for i in range(len(item.args)-1):
                tempitem = MulSIMD(item.args[i],tempitem)
            tempitem = tempitem.xreplace({blahtmp: item.args[len(item.args)-1]})
            expr = expr.xreplace({item: tempitem})
    for item in preorder_traversal(expr):
        if item.func == Add:
            blahtmp = symbols('blahtmp')
            tempitem = blahtmp
            for i in range(len(item.args)-1):
                tempitem = AddSIMD(item.args[i],tempitem)
            tempitem = tempitem.xreplace({blahtmp: item.args[len(item.args)-1]})
            expr = expr.xreplace({item: tempitem})

    # Step 5: Simplification patterns:
    # Step 5a: Replace the pattern Mul(Div(1,b),a) or Mul(a,Div(1,b)) with Div(a,b):
    for item in preorder_traversal(expr):
        if item.func == MulSIMD:
            if item.func == MulSIMD and (item.args[0].func == DivSIMD and item.args[0].args[0].func == IntegerTMP and item.args[0].args[0].args[0] == 1):
                expr = expr.xreplace({item: DivSIMD(item.args[1],item.args[0].args[1])})
            if item.func == MulSIMD and (item.args[1].func == DivSIMD and item.args[1].args[0].func == IntegerTMP and item.args[1].args[0].args[0] == 1):
                expr = expr.xreplace({item: DivSIMD(item.args[0],item.args[1].args[1])})

    # Step 5: Subtraction intrinsics. SymPy replaces all a-b with a + (-b) = Add(a,Mul(-1,b))
    #         Here, we replace
    #         a) AddSIMD(a,MulSIMD(-1,b)),
    #         b) AddSIMD(a,MulSIMD(b,-1)),
    #         c) AddSIMD(MulSIMD(-1,b),a), and
    #         d) AddSIMD(MulSIMD(b,-1),a)
    #         with SubSIMD(a,b)
    for item in preorder_traversal(expr):
        tempitem = item
        # First match patterns a) and b): AddSIMD(a,MULSIMD(.,.)):
        if item.func == AddSIMD and item.args[1].func == MulSIMD:
            # Pattern a) AddSIMD(a,MulSIMD(-1,b)) --> SubSIMD(a,b):
            if item.args[1].args[0].func == IntegerTMP and item.args[1].args[0].args[0] == -1:
                tempitem = SubSIMD(item.args[0],item.args[1].args[1])
            # Pattern b) AddSIMD(a,MulSIMD(b,-1)) --> SubSIMD(a,b):
            elif item.args[1].args[1].func == IntegerTMP and item.args[1].args[1].args[0] == -1:
                tempitem = SubSIMD(item.args[0],item.args[1].args[0])
        # Next match patterns c) and d): AddSIMD(MulSIMD(.,.),a):
        elif item.func == AddSIMD and item.args[0].func == MulSIMD:
            # Pattern c) AddSIMD(MulSIMD(-1,b),a) --> SubSIMD(a,b):
            if item.args[0].args[0].func == IntegerTMP and item.args[0].args[0].args[0] == -1:
                tempitem = SubSIMD(item.args[1],item.args[0].args[1])
            # Pattern d) AddSIMD(MulSIMD(b,-1,a)) --> SubSIMD(a,b):
            elif item.args[0].args[1].func == IntegerTMP and item.args[0].args[1].args[0] == -1:
                tempitem = SubSIMD(item.args[1],item.args[0].args[0])
        expr = expr.subs(item,tempitem)

    # Step 6: Now that all multiplication and addition functions only take two
    #         arguments, we can now easily define fused-multiply-add functions,
    #         where AddSIMD(a,MulSIMD(b,c)) = b*c + a = FusedMulAddSIMD(b,c,a),
    #         or    AddSIMD(MulSIMD(b,c),a) = b*c + a = FusedMulAddSIMD(b,c,a).
    # Fused multiply add (FMA3) is standard on Intel CPUs with the AVX2
    #         instruction set, starting with Haswell processors in 2013:
    #         https://en.wikipedia.org/wiki/Haswell_(microarchitecture)
    for item in preorder_traversal(expr):
        tempitem = item
        # If the pattern is a*b + c, replace with FMA(a,b,c)
        if item.func == AddSIMD and item.args[0].func == MulSIMD:
            tempitem = FusedMulAddSIMD(item.args[0].args[0],item.args[0].args[1],item.args[1])
        # If the pattern is c + a*b, replace with FMA(a,b,c)
        if item.func == AddSIMD and item.args[1].func == MulSIMD:
            tempitem = FusedMulAddSIMD(item.args[1].args[0],item.args[1].args[1],item.args[0])

        # If the pattern is a*b - c, replace with FMS(a,b,c)
        if item.func == SubSIMD and item.args[0].func == MulSIMD:
            tempitem = FusedMulSubSIMD(item.args[0].args[0],item.args[0].args[1],item.args[1])

        if item != tempitem: expr = expr.subs(item, tempitem)

    # Step 7: SIMD intrinsics cannot take integers or rational numbers as arguments.
    #         Therefore we must declare all integers & rational numbers as
    #         const vector doubles (e.g., const _m256d ...). To make the code
    #         more human readable, we adopt the convention
    #         RationalTMP(1,3) = 1/3 = "Rational_1_3
    #         RationalTMP(-1,3) = -1/3 = "Rational_m1_3
    # TODO: Keep track of all integers and rationals, so repeats are not computed?

    # Step 7a: Set all variable names and corresponding values.
    for item in preorder_traversal(expr):
        if item.func == RationalTMP:
            # Set variable name
            if item.args[0]*item.args[1] < 0:
                SIMD_const_varnms.extend(["_Rational_m"+str(abs(item.args[0]))+"_"+str(abs(item.args[1]))+SIMD_const_suffix])
            elif item.args[0] > 0 and item.args[1] > 0:
                SIMD_const_varnms.extend(["_Rational_"+str(item.args[0])+"_"+str(item.args[1])+SIMD_const_suffix])
            else:
                # E.g., doesn't make sense to have -1/-3. SymPy should have simplified this.
                print("Found a weird Rational(a,b) expression, where a<0 and b<0. Report to SymPy devels")
                print("Specifically, found that a="+str(item.args[0])+" and b="+str(item.args[1]))
                sys.exit(1)
            # Set variable value, to 34 digits of precision
            SIMD_const_values.extend([str(N(Float(item.args[0],34)/Float(item.args[1],34),34))])
        elif item.func == IntegerTMP:
            # Set variable name
            if item.args[0] < 0:
                SIMD_const_varnms.extend(["_Integer_m"+str(-item.args[0])+SIMD_const_suffix])
            else:
                SIMD_const_varnms.extend(["_Integer_" + str(item.args[0])+SIMD_const_suffix])
            # Set variable value, to 34 digits of precision
            SIMD_const_values.extend([str((Float(item.args[0],34)))])

    # Step 7b: Replace all integers and rationals with the appropriate variable names:
    for item in preorder_traversal(expr):
        tempitem = item
        if item.func == RationalTMP:
            if item.args[0]*item.args[1] < 0:
                tempitem = var("_Rational_m" + str(abs(item.args[0])) + "_" + str(abs(item.args[1]))+SIMD_const_suffix)
            elif item.args[0] > 0 and item.args[1] > 0:
                tempitem = var("_Rational_" + str(item.args[0]) + "_" + str(item.args[1])+SIMD_const_suffix)
            else:
                # E.g., doesn't make sense to have -1/-3. SymPy should have simplified this.
                print("Found a weird Rational(a,b) expression, where a<0 and b<0. Report to SymPy devels")
                print("Specifically, found that a=" + str(item.args[0]) + " and b=" + str(item.args[1]))
                sys.exit(1)
        elif item.func == IntegerTMP:
            if item.args[0] < 0:
                tempitem = var("_Integer_m" + str(-item.args[0])+SIMD_const_suffix)
            else:
                tempitem = var("_Integer_" + str(item.args[0])+SIMD_const_suffix)
        if item != tempitem: expr = expr.subs(item, tempitem)

    def lookup_name_output_idx(name, list_of_names):
        for i in range(len(list_of_names)):
            if list_of_names[i] == name:
                return i
        print("I SHOULDN'T BE HERE!",name,list_of_names)
        sys.exit(1)

    if debug=="True":
        expr_check = expr
        if "SIMD" in str(expr):
            expr_check = eval(str(expr).replace("SIMD","SIMD_check"))

        for item in preorder_traversal(expr_check):
            tempitem = item
            if item.is_Symbol and str(item)[0]=="_":
                if str(item)[:9]=="_Integer_" or str(item)[:10]=="_Rational_":
                    tempitem = SIMD_const_values[lookup_name_output_idx(str(item), SIMD_const_varnms)]
            if item != tempitem: expr_check = expr_check.subs(item, tempitem)

        expr_diff = expr_check - expr_orig
        # Some variables do not want to cancel in SymPy ~0.7.4. The eval(str(srepr())) below normalizes the expression.
        expr_diff = eval(str(srepr(expr_diff)))
        for item in preorder_traversal(expr_diff):
            if item.func == Float:
                if abs(item - Integer(item)) < 1.0e-14:
                    expr_diff = expr_diff.xreplace({item:Integer(item)})

        # Only simplify if expr_diff != 0:
        if expr_diff != 0:
            simp_expr_diff = simplify(expr_diff)
            if simp_expr_diff != 0:
                print("Warning: found possible diff",(simp_expr_diff))
    return(expr)
Exemplo n.º 26
0
def custom_serializer(obj: Any) -> JSON:
    """
    Serializes objects that are not JSON-serializable by default.
    Fallback is ``obj.__dict__``, if this does not exist
    the input object is returned unchanged.
    Numpy arrays and pandas DataFrames are handled separately.

    Custom classes can use a method named ``to_json()`` or
    a property named ``json`` that returns a ``dict`` or
    a string representation of a ``dict``.
    The class name is stored in the ``type`` attribute in the output JSON.

    If these attributes are not found, ``__dict__`` or ``str()`` is used.

    Parameters
    ----------
    obj : Any
        Input object

    Returns
    -------
    JSON
        Serializable representation of the input that
        preserves the nested structure.
    """

    if isinstance(obj, Path):
        return {'type': 'Path', 'data': str(obj.absolute())}

    if isinstance(obj, Quantity):

        return {
            'type': 'Quantity',
            'data': [serialize(obj.m), str(obj.u._units)]
        }

    if isinstance(obj, pd.Series):

        return {
            'type': 'Series',
            'data': obj.to_json(orient='split',
                                default_handler=custom_serializer)
        }

    if isinstance(obj, pd.DataFrame):

        return {
            'type': 'DataFrame',
            'data': obj.to_json(orient='split',
                                default_handler=custom_serializer)
        }

    if isinstance(obj, np.ndarray):

        return {
            'type': 'ndarray',
            'data': [serialize(x) for x in obj.tolist()]
        }

    if isinstance(obj, Decimal):

        return {'type': 'Decimal', 'data': str(obj)}

    if isinstance(obj, AffineScalarFunc):

        return {
            'type': 'AffineScalarFunc',
            'data': [obj.nominal_value, obj.std_dev]
        }

    if isinstance(obj, sp.Basic):

        return {'type': 'Sympy', 'data': sp.srepr(obj)}

    # method named "to_json" or @property named "json"
    if hasattr(obj, 'to_json') or hasattr(obj, 'json'):

        # this method can return a dict or a string
        # JSON representation
        if hasattr(obj, 'json'):
            json_repr = getattr(obj, 'json')
        else:
            json_repr = obj.to_json()

        # make sure the object's dict representation is serializable
        # if this is a string this is not necessary
        if not isinstance(json_repr, str):
            json_repr = serialize(json_repr)

        obj_type = obj.__class__.__name__

        # the custom class must implement classmethod
        # from_dict, which takes json_repr as input and
        # returns a class instance
        return {'type': obj_type, 'data': json_repr}

    if hasattr(obj, '__dict__'):
        return obj.__dict__

    if is_serializable(obj):
        return obj

    # fallback, this cannot be deserialized
    return str(obj)
Exemplo n.º 27
0
 def __str__(self):
     return "FORALL " + str(self.query_symbols) + " in " + str(self.query) + ": " + srepr(self.relation)
Exemplo n.º 28
0
def general_symbolic(target, eqn=None, arg_map=None):
    r'''
    A general function to interpret a sympy equation and evaluate the linear
    components of the source term.

    Parameters
    ----------
    target : OpenPNM object
        The OpenPNM object where the result will be applied.

    eqn : sympy symbolic expression for the source terms
        e.g. y = a*x**b + c

    arg_map : Dict mapping the symbols in the expression to OpenPNM data
        on the target. Must contain 'x' which is the independent variable.
        e.g. arg_map={'a':'pore.a', 'b':'pore.b', 'c':'pore.c', 'x':'pore.x'}

    Example
    ----------
    >>> import openpnm as op
    >>> from openpnm.models.physics import generic_source_term as gst
    >>> import scipy as sp
    >>> import sympy as _syp
    >>> pn = op.network.Cubic(shape=[5, 5, 5], spacing=0.0001)
    >>> water = op.phases.Water(network=pn)
    >>> water['pore.a'] = 1
    >>> water['pore.b'] = 2
    >>> water['pore.c'] = 3
    >>> water['pore.x'] = sp.random.random(water.Np)
    >>> a, b, c, x = _syp.symbols('a,b,c,x')
    >>> y = a*x**b + c
    >>> arg_map = {'a':'pore.a', 'b':'pore.b', 'c':'pore.c', 'x':'pore.x'}
    >>> water.add_model(propname='pore.general',
    ...                 model=gst.general_symbolic,
    ...                 eqn=y, arg_map=arg_map,
    ...                 regen_mode='normal')
    >>> assert 'pore.general.rate' in water.props()
    >>> assert 'pore.general.S1' in water.props()
    >>> assert 'pore.general.S1' in water.props()
    '''
    # First make sure all the symbols have been allocated dict items
    for arg in _syp.postorder_traversal(eqn):
        if _syp.srepr(arg)[:6] == 'Symbol':
            key = _syp.srepr(arg)[7:].strip('(').strip(')').strip("'")
            if key not in arg_map.keys():
                raise Exception('argument mapping incomplete, missing '+key)
    if 'x' not in arg_map.keys():
        raise Exception('argument mapping must contain "x" for the ' +
                        'independent variable')
    # Get the data
    data = {}
    args = {}
    for key in arg_map.keys():
        data[key] = target[arg_map[key]]
        # Callable functions
        args[key] = _syp.symbols(key)
    r, s1, s2 = _build_func(eqn, **args)
    r_val = r(*data.values())
    s1_val = s1(*data.values())
    s2_val = s2(*data.values())
    values = {'S1': s1_val, 'S2': s2_val, 'rate': r_val}
    return values
Exemplo n.º 29
0
def general_symbolic(target, eqn=None, arg_map=None):
    r'''
    A general function to interpret a sympy equation and evaluate the linear
    components of the source term.

    Parameters
    ----------
    target : OpenPNM object
        The OpenPNM object where the result will be applied.

    eqn : sympy symbolic expression for the source terms
        e.g. y = a*x**b + c

    arg_map : Dict mapping the symbols in the expression to OpenPNM data
        on the target. Must contain 'x' which is the independent variable.
        e.g. arg_map={'a':'pore.a', 'b':'pore.b', 'c':'pore.c', 'x':'pore.x'}

    Example
    ----------
    >>> import openpnm as op
    >>> from openpnm.models.physics import generic_source_term as gst
    >>> import scipy as sp
    >>> import sympy
    >>> pn = op.network.Cubic(shape=[5, 5, 5], spacing=0.0001)
    >>> water = op.phases.Water(network=pn)
    >>> water['pore.a'] = 1
    >>> water['pore.b'] = 2
    >>> water['pore.c'] = 3
    >>> water['pore.x'] = sp.random.random(water.Np)
    >>> a, b, c, x = sympy.symbols('a,b,c,x')
    >>> y = a*x**b + c
    >>> arg_map = {'a':'pore.a', 'b':'pore.b', 'c':'pore.c', 'x':'pore.x'}
    >>> water.add_model(propname='pore.general',
    ...                 model=gst.general_symbolic,
    ...                 eqn=y, arg_map=arg_map,
    ...                 regen_mode='normal')
    >>> assert 'pore.general.rate' in water.props()
    >>> assert 'pore.general.S1' in water.props()
    >>> assert 'pore.general.S1' in water.props()
    '''
    from sympy import postorder_traversal, srepr, symbols
    # First make sure all the symbols have been allocated dict items
    for arg in postorder_traversal(eqn):
        if srepr(arg)[:6] == 'Symbol':
            key = srepr(arg)[7:].strip('(').strip(')').strip("'")
            if key not in arg_map.keys():
                raise Exception('argument mapping incomplete, missing ' + key)
    if 'x' not in arg_map.keys():
        raise Exception('argument mapping must contain "x" for the ' +
                        'independent variable')
    # Get the data
    data = {}
    args = {}
    for key in arg_map.keys():
        data[key] = target[arg_map[key]]
        # Callable functions
        args[key] = symbols(key)
    r, s1, s2 = _build_func(eqn, **args)
    r_val = r(*data.values())
    s1_val = s1(*data.values())
    s2_val = s2(*data.values())
    values = {'S1': s1_val, 'S2': s2_val, 'rate': r_val}
    return values
Exemplo n.º 30
0
def listToValueList(lst, first_time):

    precision = trustedValuesDict["precision"]

    mpm.mp.dps = precision

    # Replace all integer fractions with the correct floating point representation:
    index = 0
    for expr in lst:
        string = srepr(expr)
        string2 = re.sub(
            'Rational\(([0-9]+), ([0-9]+)\)',
            "((Float('\\1'," + str(2 * precision) + "))/(Float('\\2'," +
            str(2 * precision) + ")))", string)
        string3 = re.sub(
            'Rational\((-[0-9]+), ([0-9]+)\)',
            "((Float('\\1'," + str(2 * precision) + "))/(Float('\\2'," +
            str(2 * precision) + ")))", string2)
        newexpr = eval(string3)
        lst[index] = newexpr
        index += 1

    # List all the free symbols in the expressions in [lst].
    #   These variables will be automatically set to random
    #   values in the range [0,1) below.
    list_free_symbols = sum(lst).free_symbols

    # To ensure the random values are consistent for testing purposes, we will
    #    sort the list of free symbols. This requires that we first convert
    #    all SymPy symbols to strings, storing to list_symbol_strings,
    #    and then we'll use zip() to sort both lists in alphabetical order,
    #    based on the strings in the first list:
    list_symbol_strings = []
    for var in list_free_symbols:
        list_symbol_strings.append(str(var))

    # https://stackoverflow.com/questions/13668393/python-sorting-two-lists
    list_symbol_strings, list_free_symbols = (list(x) for x in zip(
        *sorted(zip(list_symbol_strings, list_free_symbols))))

    # Set the random seed according to trustedValues.seed:
    random.seed(trustedValuesDict["seed"])

    # Next we will write a short Python code that first declares all
    # of the free variables in the "everything" expression
    # to random values with 30 significant digits of precision.
    # (This is accomplished by calling random.random() to get
    # a 16-significant-digit random number between 0 and 1,
    # and then taking the 30-significant-digit square root
    # of that number.)
    stringexec = """
from sympy import Integer,Symbol,symbols,simplify,Rational,Function,srepr,sin,cos,exp,log,Abs,Add,Mul,Pow,preorder_traversal,N,Float,S,var,sympify
import mpmath as mpm
mpm.mp.dps = """ + str(precision) + "\n"

    for var in list_free_symbols:
        # BE CAREFUL: You must declare all variables using mpm.mpf('string')!
        #   http://mpmath.org/doc/1.1.0/basics.html#providing-correct-input
        # First make sure M_PI is set to its correct value, pi, to the desired number of significant digits:
        if str(var) == "M_PI":
            stringexec += str(var) + " = mpm.pi\n"
        # Then make sure M_SQRT1_2 is set to its correct value, 1/sqrt(2), to the desired number of significant digits:
        elif str(var) == "M_SQRT1_2":
            stringexec += str(var) + " = mpm.mpf(1/mpm.sqrt(2))\n"
        # All other free variables are set to random numbers
        else:
            stringexec += str(var) + " = mpm.mpf(\'" + str(
                mpm.sqrt(mpm.mpf(random.random()))) + "\')\n"

    # Then it creates the code that evaluates the result
    #    to 30 significant digits.
    stringexec += "lst = " + str(lst)

    # https://stackoverflow.com/questions/38817962/python-3-need-from-exec-to-return-values
    # Finally we execute stringexec to a local namespace "loc", and store the
    #    result of the evaluated "everything" expression to "result".
    #
    loc = {}
    exec(stringexec, {}, loc)
    evaled_lst = loc['lst']

    if first_time == True:
        index = 0
        for result in evaled_lst:
            if result != 0 and mpm.fabs(result) < 100 * 10**(-precision):
                print("Found |result| (" + str(mpm.fabs(result)) +
                      ") close to zero. Checking if indeed it should be zero.")
                # Now double the precision and redo. If number drops in magnitude
                loc2xprec = {}
                stringexec = stringexec.replace(
                    "mpm.mp.dps = " + str(precision),
                    "mpm.mp.dps = " + str(2 * precision))
                exec(stringexec, {}, loc2xprec)
                evaled_lst2xprec = loc2xprec['lst']
                if mpm.fabs(
                        evaled_lst2xprec[index]) < 100 * 10**(-2 * precision):
                    print(
                        "After re-evaluating with twice the digits of precision, |result| dropped to "
                        + str(evaled_lst2xprec[index]) +
                        ". Setting value to zero")
                    evaled_lst[index] = 0
            index += 1

    # Make sure that all results in evaled_lst *except* zeros are mpm.mpf type!
    for i in range(len(evaled_lst)):
        if evaled_lst[i] != 0:
            evaled_lst[i] = mpm.mpf(str(evaled_lst[i]))

    return evaled_lst
Exemplo n.º 31
0
 def _sympyrepr(self, printer, *args):
     return "RlpSum(" + str(self.query_symbols) + " in " + str(self.query) + ", " + srepr(self.expression) + ")"
Exemplo n.º 32
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from sympy import init_printing, Integral, latex, pretty, pprint, sqrt, symbols, srepr
init_printing(use_unicode=True)
x, y, z = symbols('x y z')
print(Integral(sqrt(1 / x), x))

print(srepr(Integral(sqrt(1 / x), x)))
pprint(Integral(sqrt(1 / x), x), use_unicode=False)

print(pretty(Integral(sqrt(1 / x), x), use_unicode=False))

print(latex(Integral(sqrt(1 / x), x)))
from sympy.printing.mathml import print_mathml
print_mathml(Integral(sqrt(1 / x), x))

from sympy.printing.dot import dotprint
from sympy.abc import x
print(dotprint(x + 2))
Exemplo n.º 33
0

def parsed_math(xml_expr, nsp='', func=None):
    if func is None:
        return parse_expr(pmml_to_srepr(xml_expr, nsp=nsp))
    else:
        return parse_expr(func(pmml_to_srepr(xml_expr, nsp=nsp)))


if __name__ == '__main__':
    import sympy as sy
    import lxml.etree as et

    expr = sy.sympify('rho*V*(H + C_p*(T_f-T_i))')
    # expr = sy.sympify('L*((0.75)*mu_l*mu_h + g*t + (mu_l-g)*(t-mu_e)*0.5)')
    print('The result should look like this: \n\n\t', sy.srepr(expr))
    print('\nwhich parses to this: \n\t', parse_expr(sy.srepr(expr)), '\n----')
    # sy.parsing.sympy_parser.parse_expr(sy.srepr(expr))

    xml_expr = """
    <StaticValue>
                  <Apply function="*">
                    <FieldRef field="V"/>
                    <FieldRef field="rho"/>
                    <Apply function="+">
                      <FieldRef field="H"/>
                      <Apply function="*">
                        <FieldRef field="C_p"/>
                        <Apply function="+">
                          <FieldRef field="T_f"/>
                          <Apply function="*">
Exemplo n.º 34
0
    A_expr_dummy, A_expr_dummy_syms = sympyutils.dummify(A_expr, x_syms)
    A_dot_expr_dummy, A_dot_expr_dummy_syms = sympyutils.dummify(
        A_dot_expr, x_syms)
    dqdotdot_dq_expr_dummy, dqdotdot_dq_expr_dummy_syms = sympyutils.dummify(
        dqdotdot_dq_expr, x_and_u_syms)
    dqdotdot_dqdot_expr_dummy, dqdotdot_dqdot_expr_dummy_syms = sympyutils.dummify(
        dqdotdot_dqdot_expr, x_and_u_syms)

    print "Saving sympy expressions..."

    current_source_file_path = pathutils.get_current_source_file_path()

    with open(
            current_source_file_path +
            "/data/sympy/quadrotor3d_A_expr_dummy.dat", "w") as f:
        f.write(sympy.srepr(A_expr_dummy))
    with open(
            current_source_file_path +
            "/data/sympy/quadrotor3d_A_dot_expr_dummy.dat", "w") as f:
        f.write(sympy.srepr(A_dot_expr_dummy))
    with open(
            current_source_file_path +
            "/data/sympy/quadrotor3d_dqdotdot_dq_expr_dummy.dat", "w") as f:
        f.write(sympy.srepr(dqdotdot_dq_expr_dummy))
    with open(
            current_source_file_path +
            "/data/sympy/quadrotor3d_dqdotdot_dqdot_expr_dummy.dat", "w") as f:
        f.write(sympy.srepr(dqdotdot_dqdot_expr_dummy))

    with open(
            current_source_file_path +
Exemplo n.º 35
0
def apply_z_rule_2(clause, known_expressions, verbose=False):
    # Example: p_1 + q_1 - 2*z_1_2 = 0
    # p1 and z_1_2 must be equal to q1, otherwise the equation can't be satisfied.
    # For more examples please refer to tests.
    new_known_expressions = {}
    even_positive_terms = []
    even_negative_terms = []
    odd_terms = []
    if clause.func == Add:
        for term in clause.args:
            if term.func == Symbol:
                odd_terms.append(term)
            if isinstance(term, Number):
                if term % 2 == 0 and term > 0:
                    even_positive_terms.append(term)
                elif term % 2 == 0 and term < 0:
                    even_negative_terms.append(term)
                else:
                    odd_terms.append(term)
            if term.func == Mul:
                first_argument = term.args[0]
                if isinstance(first_argument, Number):
                    if first_argument % 2 == 0 and first_argument > 0:
                        even_positive_terms.append(term)
                    elif first_argument % 2 == 0 and first_argument < 0:
                        even_negative_terms.append(term)
                    else:
                        odd_terms.append(term)
                else:
                    odd_terms.append(term)

    if len(odd_terms) == 1:
        if type(odd_terms[0]) == Symbol:
            new_known_expressions[odd_terms[0]] = 0
        elif type(odd_terms[0]) == Mul:
            term = odd_terms[0]
            if isinstance(term.args[0], Number):
                term = term / term.args[0]
            new_known_expressions[term] = 0
        else:
            print("TODO: Z rule 2: don't know this type!")
            pdb.set_trace()

    if len(odd_terms) == 2:
        non_number_index = None
        if isinstance(odd_terms[0], Number):
            non_number_index = 1
        elif isinstance(odd_terms[1], Number):
            non_number_index = 0
        if non_number_index is not None:
            term = odd_terms[non_number_index]
            if type(term) == Symbol:
                new_known_expressions[term] = 1
            elif type(term) == Mul:
                for arg in term.args:
                    if not isinstance(arg, Number):
                        new_known_expressions[arg] = 1
            else:
                # TODO: Example of clause which results in this case:
                # 2*q_2 + z_4_6 + z_5_6 - 4
                # (p=23, q=23, m=529)
                # This should be handled by rule 5
                # print("TODO: Z rule 2: don't know this type!")
                # pdb.set_trace()
                pass

        else:
            if 'q' in str(odd_terms[0]):
                non_q_index = 1
            else:
                non_q_index = 0
            variable_0 = odd_terms[1 - non_q_index]
            variable_1 = odd_terms[non_q_index]

            if type(variable_0) == Mul:
                if isinstance(variable_0.args[0], Number):
                    variable_0 = variable_0 / variable_0.args[0]

            if type(variable_1) == Mul:
                if isinstance(variable_1.args[0], Number):
                    variable_1 = variable_1 / variable_1.args[0]

            new_known_expressions[variable_1] = variable_0

            if len(even_negative_terms) == 1:
                term = even_negative_terms[0]
                if isinstance(term, Number):
                    # TODO: Example of clause which results in this case:
                    # q_2 + z_5_6 + 2*z_7_8 - 2
                    # (p=29, q=23, m=667)
                    # pdb.set_trace()
                    pass
                elif type(term) == Mul:
                    if len(even_positive_terms) == 0:
                        term = term / term.args[0]
                        new_known_expressions[term] = variable_0
                    else:
                        pass
                        # pdb.set_trace()
                else:
                    print("TODO: Z rule 2: don't know this type!")
                    pdb.set_trace()

    if len(odd_terms) == 3:
        number_index = None
        if isinstance(odd_terms[0], Number):
            number_index = 0
        elif isinstance(odd_terms[1], Number):
            number_index = 1
        elif isinstance(odd_terms[2], Number):
            number_index = 2
        if number_index is not None:
            indices = [0, 1, 2]
            indices.remove(number_index)
            new_term = odd_terms[indices[0]] * odd_terms[indices[1]]
            if isinstance(new_term.args[0], Number):
                new_term = new_term / new_term.args[0]
            if 'Pow' in srepr(new_term):
                new_term = simplify_clause(new_term, {})
            new_known_expressions[new_term] = 0

    if len(new_known_expressions) != 0:
        known_expressions = {**known_expressions, **new_known_expressions}
        if verbose:
            print("Z rule 2 applied:", new_known_expressions)

    return known_expressions
Exemplo n.º 36
0
        [ omega_x_terms_expr[theta_dot_expr], omega_x_terms_expr[psi_dot_expr], omega_x_terms_expr[phi_dot_expr] ] ] )

    A_dot_expr = sympy.trigsimp(A_expr.diff(t_expr))

    syms = [ theta_expr, psi_expr, phi_expr, theta_dot_expr, psi_dot_expr, phi_dot_expr ]

    print "Dummifying sympy expressions..."

    A_expr_dummy,     A_expr_dummy_syms     = sympyutils.dummify( A_expr,     syms )
    A_dot_expr_dummy, A_dot_expr_dummy_syms = sympyutils.dummify( A_dot_expr, syms )

    print "Saving sympy expressions..."

    current_source_file_path = pathutils.get_current_source_file_path()

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy.dat",     "w") as f: f.write(sympy.srepr(A_expr_dummy))
    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_dot_expr_dummy.dat", "w") as f: f.write(sympy.srepr(A_dot_expr_dummy))

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy_syms.dat",     "w") as f: f.write(sympy.srepr(sympy.Matrix(A_expr_dummy_syms)))
    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_dot_expr_dummy_syms.dat", "w") as f: f.write(sympy.srepr(sympy.Matrix(A_dot_expr_dummy_syms)))

else:

    print "Loading sympy expressions..."

    current_source_file_path = pathutils.get_current_source_file_path()

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy.dat",     "r") as f: A_expr_dummy     = sympy.sympify(f.read())
    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_dot_expr_dummy.dat", "r") as f: A_dot_expr_dummy = sympy.sympify(f.read())

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy_syms.dat",     "r") as f: A_expr_dummy_syms     = array(sympy.sympify(f.read())).squeeze()
Exemplo n.º 37
0
def expr_convert_to_SIMD_intrins(expr,
                                 map_sym_to_rat=None,
                                 prefix="",
                                 SIMD_find_more_FMAsFMSs="True",
                                 debug="False"):
    """ Convert expression to SIMD compiler intrinsics

        :arg:    SymPy expression
        :arg:    symbol to rational dictionary
        :arg:    option to find more FMA/FMS patterns
        :arg:    back-substitute and check difference
        :return: expression containing SIMD compiler intrinsics

        >>> from sympy.abc import a, b, c, d
        >>> from cse_helpers import cse_preprocess
        >>> convert = expr_convert_to_SIMD_intrins

        >>> convert(a**2)
        MulSIMD(a, a)

        >>> convert(a**(-2))
        DivSIMD(_Integer_1, MulSIMD(a, a))

        >>> convert(a**(1/2))
        SqrtSIMD(a)

        >>> convert(a**(-1/2))
        DivSIMD(1, SqrtSIMD(a))

        >>> from sympy import Rational
        >>> convert(a**Rational(1, 3))
        CbrtSIMD(a)

        >>> convert(a**b)
        PowSIMD(a, b)

        >>> convert(a - b)
        SubSIMD(a, b)

        >>> convert(a + b - c)
        AddSIMD(b, SubSIMD(a, c))

        >>> convert(a + b + c)
        AddSIMD(a, AddSIMD(b, c))

        >>> convert(a + b + c + d)
        AddSIMD(AddSIMD(a, b), AddSIMD(c, d))

        >>> convert(a*b*c)
        MulSIMD(a, MulSIMD(b, c))

        >>> convert(a*b*c*d)
        MulSIMD(MulSIMD(a, b), MulSIMD(c, d))

        >>> convert(a/b)
        DivSIMD(a, b)

        >>> convert(a*b + c)
        FusedMulAddSIMD(a, b, c)

        >>> convert(a*b - c)
        FusedMulSubSIMD(a, b, c)

        >>> convert(-a*b + c)
        NegFusedMulAddSIMD(a, b, c)

        >>> convert(-a*b - c)
        NegFusedMulSubSIMD(a, b, c)
    """
    for item in preorder_traversal(expr):
        for arg in item.args:
            if isinstance(arg, Symbol):
                var(str(arg))

    def lookup_rational(arg):
        if arg.func == Symbol:
            try:
                arg = map_sym_to_rat[arg]
            except KeyError:
                pass
        return arg

    if map_sym_to_rat is None:
        expr, map_sym_to_rat = cse_preprocess(expr)

    map_rat_to_sym = {map_sym_to_rat[v]: v for v in map_sym_to_rat}

    expr_orig, tree = expr, ExprTree(expr)

    AbsSIMD = Function("AbsSIMD")
    AddSIMD = Function("AddSIMD")
    SubSIMD = Function("SubSIMD")
    MulSIMD = Function("MulSIMD")
    FusedMulAddSIMD = Function("FusedMulAddSIMD")
    FusedMulSubSIMD = Function("FusedMulSubSIMD")
    NegFusedMulAddSIMD = Function("NegFusedMulAddSIMD")
    NegFusedMulSubSIMD = Function("NegFusedMulSubSIMD")
    DivSIMD = Function("DivSIMD")
    SignSIMD = Function("SignSIMD")

    PowSIMD = Function("PowSIMD")
    SqrtSIMD = Function("SqrtSIMD")
    CbrtSIMD = Function("CbrtSIMD")
    ExpSIMD = Function("ExpSIMD")
    LogSIMD = Function("LogSIMD")
    SinSIMD = Function("SinSIMD")
    CosSIMD = Function("CosSIMD")

    # Step 1: Replace transcendental functions, power functions, and division expressions.
    #   Note: SymPy does not represent fractional integers as rationals since
    #         those are explicitly declared using the rational class, and hence
    #         the following algorithm does not affect fractional integers.
    #         SymPy: srepr(a**(-2)) = Pow(a, -2)
    #         NRPy:  srepr(a**(-2)) = DivSIMD(1, MulSIMD(a, a))
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        if func == Abs:
            subtree.expr = AbsSIMD(args[0])
        elif func == exp:
            subtree.expr = ExpSIMD(args[0])
        elif func == log:
            subtree.expr = LogSIMD(args[0])
        elif func == sin:
            subtree.expr = SinSIMD(args[0])
        elif func == cos:
            subtree.expr = CosSIMD(args[0])
        elif func == sign:
            subtree.expr = SignSIMD(args[0])
    tree.reconstruct()

    def IntegerPowSIMD(a, n):
        # Recursive Helper Function: Construct Integer Powers
        if n == 2:
            return MulSIMD(a, a)
        if n > 2:
            return MulSIMD(IntegerPowSIMD(a, n - 1), a)
        if n <= -2:
            one = Symbol(prefix + '_Integer_1')
            try:
                map_rat_to_sym[1]
            except KeyError:
                map_sym_to_rat[one], map_rat_to_sym[1] = S.One, one
            return DivSIMD(one, IntegerPowSIMD(a, -n))
        if n == -1:
            one = Symbol(prefix + '_Integer_1')
            try:
                map_rat_to_sym[1]
            except KeyError:
                map_sym_to_rat[one], map_rat_to_sym[1] = S.One, one
            return DivSIMD(one, a)

    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        if func == Pow:
            exponent = lookup_rational(args[1])
            if exponent == 0.5:
                subtree.expr = SqrtSIMD(args[0])
                subtree.children.pop(1)
            elif exponent == -0.5:
                subtree.expr = DivSIMD(1, SqrtSIMD(args[0]))
                tree.build(subtree)
            elif exponent == Rational(1, 3):
                subtree.expr = CbrtSIMD(args[0])
                subtree.children.pop(1)
            elif isinstance(exponent, Integer):
                subtree.expr = IntegerPowSIMD(args[0], exponent)
                tree.build(subtree)
            else:
                subtree.expr = PowSIMD(*args)
    tree.reconstruct()

    # Step 2: Replace subtraction expressions.
    #   Note: SymPy: srepr(a - b) = Add(a, Mul(-1, b))
    #         NRPy:  srepr(a - b) = SubSIMD(a, b)
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = list(subtree.expr.args)
        if func == Add:
            try:
                # Find the first occurrence of a negative product inside the addition
                i = next(i for i, arg in enumerate(args) if arg.func == Mul and \
                        any(lookup_rational(arg) == -1 for arg in args[i].args))
                # Find the first occurrence of a negative symbol inside the product
                j = next(j for j, arg in enumerate(args[i].args)
                         if lookup_rational(arg) == -1)
                # Find the first non-negative argument of the product
                k = next(k for k in range(len(args)) if k != i)
                # Remove the negative symbol from the product
                subargs = list(args[i].args)
                subargs.pop(j)
                # Build the subtraction expression for replacement
                subexpr = SubSIMD(args[k], Mul(*subargs))
                args = [arg for arg in args if arg not in (args[i], args[k])]
                if len(args) > 0:
                    subexpr = Add(subexpr, *args)
                subtree.expr = subexpr
                tree.build(subtree)
            except StopIteration:
                pass
    tree.reconstruct()

    # Step 3: Replace addition and multiplication expressions.
    #   Note: SIMD addition and multiplication compiler intrinsics can read
    #         only two arguments at once, whereas SymPy's Mul() and Add()
    #         operators can read an arbitrary number of arguments.
    #         SymPy: srepr(a*b*c*d) = Mul(a, b, c, d)
    #         NRPy:  srepr(a*b*c*d) = MulSIMD(MulSIMD(a, b), MulSIMD(c, d))
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        if func in (Mul, Add):
            func = MulSIMD if func == Mul else AddSIMD
            subexpr = func(*args[-2:])
            args, N = args[:-2], len(args) - 2
            for i in range(0, N, 2):
                if N - i > 1:
                    tmpexpr = func(args[i], args[i + 1])
                    subexpr = func(tmpexpr, subexpr, evaluate=False)
                else:
                    subexpr = func(args[i], subexpr, evaluate=False)
            subtree.expr = subexpr
            tree.build(subtree)
    tree.reconstruct()

    # Step 4: Replace the pattern Mul(Div(1, b), a) or Mul(a, Div(1, b)) with Div(a, b).
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # MulSIMD(DivSIMD(1, b), a) >> DivSIMD(a, b)
        if   func == MulSIMD and args[0].func == DivSIMD and \
                lookup_rational(args[0].args[0]) == 1:
            subtree.expr = DivSIMD(args[1], args[0].args[1])
            tree.build(subtree)
        # MulSIMD(a, DivSIMD(1, b)) >> DivSIMD(a, b)
        elif func == MulSIMD and args[1].func == DivSIMD and \
                lookup_rational(args[1].args[0]) == 1:
            subtree.expr = DivSIMD(args[0], args[1].args[1])
            tree.build(subtree)
    tree.reconstruct()

    # Step 5: Now that all multiplication and addition functions only take two
    #         arguments, we can define fused-multiply-add functions,
    #         where AddSIMD(a, MulSIMD(b, c)) = b*c + a = FusedMulAddSIMD(b, c, a),
    #         or    AddSIMD(MulSIMD(b, c), a) = b*c + a = FusedMulAddSIMD(b, c, a).
    #   Note: Fused-multiply-add (FMA3) is standard on Intel CPUs with the AVX2
    #         instruction set, starting with Haswell processors in 2013:
    #         https://en.wikipedia.org/wiki/Haswell_(microarchitecture)

    # Step 5.a: Find double FMA patterns first [e.g. FMA(a, b, FMA(c, d, e))].
    #   Note: Double FMA simplifications do not guarantee a significant performance impact when solving BSSN equations
    if SIMD_find_more_FMAsFMSs == "True":
        for subtree in tree.preorder():
            func = subtree.expr.func
            args = subtree.expr.args
            # a + b*c + d*e -> FMA(b,c,FMA(d,e,a))
            # AddSIMD(a, AddSIMD(MulSIMD(b,c), MulSIMD(d,e))) >> FusedMulAddSIMD(b, c, FusedMulAddSIMD(d,e,a))
            # Validate:
            # x = a + b*c + d*e
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            if (func == AddSIMD and args[1].func == AddSIMD
                    and args[1].args[0].func == MulSIMD
                    and args[1].args[1].func == MulSIMD):
                subtree.expr = FusedMulAddSIMD(
                    args[1].args[0].args[0], args[1].args[0].args[1],
                    FusedMulAddSIMD(args[1].args[1].args[0],
                                    args[1].args[1].args[1], args[0]))
                tree.build(subtree)
            # b*c + d*e + a -> FMA(b,c,FMA(d,e,a))
            # Validate:
            # x = b*c + d*e + a
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            # AddSIMD(AddSIMD(MulSIMD(b,c), MulSIMD(d,e)),a) >> FusedMulAddSIMD(b, c, FusedMulAddSIMD(d,e,a))
            elif func == AddSIMD and args[0].func == AddSIMD and args[0].args[
                    0].func == MulSIMD and args[0].args[1].func == MulSIMD:
                subtree.expr = FusedMulAddSIMD(
                    args[0].args[0].args[0], args[0].args[0].args[1],
                    FusedMulAddSIMD(args[0].args[1].args[0],
                                    args[0].args[1].args[1], args[1]))
                tree.build(subtree)
        tree.reconstruct()

    # Step 5.b: Find single FMA patterns.
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # AddSIMD(MulSIMD(b, c), a) >> FusedMulAddSIMD(b, c, a)
        if func == AddSIMD and args[0].func == MulSIMD:
            subtree.expr = FusedMulAddSIMD(args[0].args[0], args[0].args[1],
                                           args[1])
            tree.build(subtree)
        # AddSIMD(a, MulSIMD(b, c)) >> FusedMulAddSIMD(b, c, a)
        elif func == AddSIMD and args[1].func == MulSIMD:
            subtree.expr = FusedMulAddSIMD(args[1].args[0], args[1].args[1],
                                           args[0])
            tree.build(subtree)
        # SubSIMD(MulSIMD(b, c), a) >> FusedMulSubSIMD(b, c, a)
        elif func == SubSIMD and args[0].func == MulSIMD:
            subtree.expr = FusedMulSubSIMD(args[0].args[0], args[0].args[1],
                                           args[1])
            tree.build(subtree)
        # SubSIMD(a, MulSIMD(b, c)) >> NegativeFusedMulAddSIMD(b, c, a)
        elif func == SubSIMD and args[1].func == MulSIMD:
            subtree.expr = NegFusedMulAddSIMD(args[1].args[0], args[1].args[1],
                                              args[0])
            tree.build(subtree)
        # FMS(-1, MulSIMD(a, b), c) >> NegativeFusedMulSubSIMD(b, c, a)
        func = subtree.expr.func
        args = subtree.expr.args
        if func == FusedMulSubSIMD and args[
                1].func == MulSIMD and lookup_rational(args[0]) == -1:
            subtree.expr = NegFusedMulSubSIMD(args[1].args[0], args[1].args[1],
                                              args[2])
            tree.build(subtree)
    tree.reconstruct()

    # Step 5.c: Remaining double FMA patterns that previously in Step 5.a were difficult to find.
    #   Note: Double FMA simplifications do not guarantee a significant performance impact when solving BSSN equations
    if SIMD_find_more_FMAsFMSs == "True":
        for subtree in tree.preorder():
            func = subtree.expr.func
            args = subtree.expr.args
            # (b*c - d*e) + a -> AddSIMD(a, FusedMulSubSIMD(b, c, MulSIMD(d, e))) >> FusedMulSubSIMD(b, c, FusedMulSubSIMD(d,e,a))
            # Validate:
            # x = (b*c - d*e) + a
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            if func == AddSIMD and args[1].func == FusedMulSubSIMD and args[
                    1].args[2].func == MulSIMD:
                subtree.expr = FusedMulSubSIMD(
                    args[1].args[0], args[1].args[1],
                    FusedMulSubSIMD(args[1].args[2].args[0],
                                    args[1].args[2].args[1], args[0]))
                tree.build(subtree)
            # b*c - (a - d*e) -> SubSIMD(FusedMulAddSIMD(b, c, MulSIMD(d, e)), a) >> FMA(b,c,FMS(d,e,a))
            # Validate:
            # x = b * c - (a - d * e)
            # outputC(x, "x", params="SIMD_enable=True,SIMD_debug=True")
            elif func == SubSIMD and args[0].func == FusedMulAddSIMD and args[
                    0].args[2].func == MulSIMD:
                subtree.expr = FusedMulAddSIMD(
                    args[0].args[0], args[0].args[1],
                    FusedMulSubSIMD(args[0].args[2].args[0],
                                    args[0].args[2].args[1], args[1]))
                tree.build(subtree)
            # (b*c - d*e) - a -> SubSIMD(FusedMulSubSIMD(b, c, MulSIMD(d, e)), a) >> FMS(b,c,FMA(d,e,a))
            # Validate:
            # x = (b*c - d*e) - a
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            elif func == SubSIMD and args[0].func == FusedMulSubSIMD and args[
                    0].args[2].func == MulSIMD:
                subtree.expr = FusedMulSubSIMD(
                    args[0].args[0], args[0].args[1],
                    FusedMulAddSIMD(args[0].args[2].args[0],
                                    args[0].args[2].args[1], args[1]))
                tree.build(subtree)
        tree.reconstruct()

    # Step 5.d: NegFusedMulAddSIMD(a,b,c) = -a*b + c:
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # FMA(a,Mul(-1,b),c) >> NFMA(a,b,c)
        if   func == FusedMulAddSIMD and args[1].func == MulSIMD and \
             lookup_rational(args[1].args[0]) == -1:
            subtree.expr = NegFusedMulAddSIMD(args[0], args[1].args[1],
                                              args[2])
            tree.build(subtree)
        # FMA(a,Mul(b,-1),c) >> NFMA(a,b,c)
        elif func == FusedMulAddSIMD and args[1].func == MulSIMD and \
             lookup_rational(args[1].args[1]) == -1:
            subtree.expr = NegFusedMulAddSIMD(args[0], args[1].args[0],
                                              args[2])
            tree.build(subtree)
        # FMA(Mul(-1,a), b,c) >> NFMA(a,b,c)
        elif func == FusedMulAddSIMD and args[0].func == MulSIMD and \
             lookup_rational(args[0].args[0]) == -1:
            subtree.expr = NegFusedMulAddSIMD(args[0].args[1], args[1],
                                              args[2])
            tree.build(subtree)
        # FMA(Mul(a,-1), b,c) >> NFMA(a,b,c)
        elif func == FusedMulAddSIMD and args[0].func == MulSIMD and \
             lookup_rational(args[0].args[1]) == -1:
            subtree.expr = NegFusedMulAddSIMD(args[0].args[0], args[1],
                                              args[2])
            tree.build(subtree)
    tree.reconstruct()

    # Step 5.e: Replace e.g., FMA(-1,b,c) with SubSIMD(c,b) and similar patterns
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # FMA(-1,b,c) >> SubSIMD(c,b)
        if func == FusedMulAddSIMD and lookup_rational(args[0]) == -1:
            subtree.expr = SubSIMD(args[2], args[1])
            tree.build(subtree)
        # FMA(a,-1,c) >> SubSIMD(c,a)
        elif func == FusedMulAddSIMD and lookup_rational(args[1]) == -1:
            subtree.expr = SubSIMD(args[2], args[0])
            tree.build(subtree)
        # FMS(a,-1,c) >> MulSIMD(-1,AddSIMD(a,c))
        elif func == FusedMulSubSIMD and lookup_rational(args[1]) == -1:
            subtree.expr = MulSIMD(args[1], AddSIMD(args[0], args[2]))
            tree.build(subtree)
        # FMS(-1,b,c) >> MulSIMD(-1,AddSIMD(b,c))
        elif func == FusedMulSubSIMD and lookup_rational(args[0]) == -1:
            subtree.expr = MulSIMD(args[0], AddSIMD(args[1], args[2]))
            tree.build(subtree)
    tree.reconstruct()

    # Step 5.f: NegFusedMulSubSIMD(a,b,c) = -a*b - c:
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # NFMA(a,b,Mul(-1,c)) >> NFMS(a,b,c)
        if   func == NegFusedMulAddSIMD and args[2].func == MulSIMD and \
             lookup_rational(args[2].args[0]) == -1:
            subtree.expr = NegFusedMulSubSIMD(args[0], args[1],
                                              args[2].args[1])
            tree.build(subtree)
        # NFMA(a,b,Mul(c,-1)) >> NFMS(a,b,c)
        elif func == NegFusedMulAddSIMD and args[2].func == MulSIMD and \
             lookup_rational(args[2].args[1]) == -1:
            subtree.expr = NegFusedMulSubSIMD(args[0], args[1],
                                              args[2].args[0])
            tree.build(subtree)
        # FMS(a,Mul(-1,b),c) >> NFMS(a,b,c)
        elif func == FusedMulSubSIMD and args[1].func == MulSIMD and \
             lookup_rational(args[1].args[0]) == -1:
            subtree.expr = NegFusedMulSubSIMD(args[0], args[1].args[1],
                                              args[2])
            tree.build(subtree)
        # FMS(a,Mul(b,-1),c) >> NFMS(a,b,c)
        elif func == FusedMulSubSIMD and args[1].func == MulSIMD and \
             lookup_rational(args[1].args[1]) == -1:
            subtree.expr = NegFusedMulSubSIMD(args[0], args[1].args[0],
                                              args[2])
            tree.build(subtree)
        # FMS(a,Mul([something],Mul(-1,b)),c) >> NFMS(a,Mul([something],b),c)
        elif func == FusedMulSubSIMD and args[1].func == MulSIMD and \
             args[1].args[1].func == MulSIMD and lookup_rational(args[1].args[1].args[0]) == -1:
            subtree.expr = NegFusedMulSubSIMD(
                args[0], MulSIMD(args[1].args[0], args[1].args[1].args[1]),
                args[2])
            tree.build(subtree)
        # FMS(a,Mul([something],Mul(b,-1)),c) >> NFMS(a,Mul([something],b),c)
        elif func == FusedMulSubSIMD and args[1].func == MulSIMD and \
             args[1].args[1].func == MulSIMD and lookup_rational(args[1].args[1].args[1]) == -1:
            subtree.expr = NegFusedMulSubSIMD(
                args[0], MulSIMD(args[1].args[0], args[1].args[1].args[0]),
                args[2])
            tree.build(subtree)
    tree.reconstruct()

    # Step 5.g: Find single FMA patterns again, as some new ones might be found.
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # AddSIMD(MulSIMD(b, c), a) >> FusedMulAddSIMD(b, c, a)
        if func == AddSIMD and args[0].func == MulSIMD:
            subtree.expr = FusedMulAddSIMD(args[0].args[0], args[0].args[1],
                                           args[1])
            tree.build(subtree)
        # AddSIMD(a, MulSIMD(b, c)) >> FusedMulAddSIMD(b, c, a)
        elif func == AddSIMD and args[1].func == MulSIMD:
            subtree.expr = FusedMulAddSIMD(args[1].args[0], args[1].args[1],
                                           args[0])
            tree.build(subtree)
        # SubSIMD(MulSIMD(b, c), a) >> FusedMulSubSIMD(b, c, a)
        elif func == SubSIMD and args[0].func == MulSIMD:
            subtree.expr = FusedMulSubSIMD(args[0].args[0], args[0].args[1],
                                           args[1])
            tree.build(subtree)
    expr = tree.reconstruct()

    if debug == "True":
        expr_check = eval(str(expr).replace("SIMD", "SIMD_check"))
        expr_check = expr_check.subs(-1, Symbol('_NegativeOne_'))

        expr_diff = expr_check - expr_orig
        # The eval(str(srepr())) below normalizes the expression,
        # fixing a cancellation issue in SymPy ~0.7.4.
        expr_diff = eval(str(srepr(expr_diff)))
        tree_diff = ExprTree(expr_diff)
        for subtree in tree_diff.preorder():
            subexpr = subtree.expr
            if subexpr.func == Float:
                if abs(subexpr - Integer(subexpr)) < 1.0e-14 * subexpr:
                    subtree.expr = Integer(subexpr)
        expr_diff = tree_diff.reconstruct()

        if expr_diff != 0:
            simp_expr_diff = simplify(expr_diff)
            if simp_expr_diff != 0:
                raise Warning('Expression Difference: ' + str(simp_expr_diff))
    return (expr)
Exemplo n.º 38
0
def test_issue1689():
    assert srepr(S(1.0 + 0J)) == srepr(S(1.0)) == srepr(Float(1.0))
Exemplo n.º 39
0
def apply_parity_rule(clause, known_expressions, verbose=False):
    """
    Extends known_expressions by applying parity rule (see example below).
    
    Example: p_1 + q_1 - 2*z_1_2 = 0
    p1 and z_1_2 must be equal to q1, otherwise the equation can't be satisfied.
    For more examples please refer to the tests.
    This rule turned out to be the most problematic one. 
    There are known cases it doesn't solve (see comments) and it might require
    refactoring/reworking.
    
    Args:
        clause: sympy expression representing a clause.
        known_expressions (dict): See module documentation at the top.
        verbose (bool): See module documentation at the top.

    Returns:
        known_expressions (dict): See module documentation at the top.
    """

    new_known_expressions = {}
    even_positive_terms = []
    even_negative_terms = []
    odd_terms = []
    if clause.func == Add:
        for term in clause.args:
            if term.func == Symbol:
                odd_terms.append(term)
            if isinstance(term, Number):
                if term % 2 == 0 and term > 0:
                    even_positive_terms.append(term)
                elif term % 2 == 0 and term < 0:
                    even_negative_terms.append(term)
                else:
                    odd_terms.append(term)
            if term.func == Mul:
                first_argument = term.args[0]
                if isinstance(first_argument, Number):
                    if first_argument % 2 == 0 and first_argument > 0:
                        even_positive_terms.append(term)
                    elif first_argument % 2 == 0 and first_argument < 0:
                        even_negative_terms.append(term)
                    else:
                        odd_terms.append(term)
                else:
                    odd_terms.append(term)

    if len(odd_terms) == 1:
        if type(odd_terms[0]) == Symbol:
            new_known_expressions[odd_terms[0]] = 0
        elif type(odd_terms[0]) == Mul:
            term = odd_terms[0]
            if isinstance(term.args[0], Number):
                term = term / term.args[0]
            new_known_expressions[term] = 0
        else:
            print("TODO: Z rule 2: don't know this type!")
            pdb.set_trace()

    if len(odd_terms) == 2:
        non_number_index = None
        if isinstance(odd_terms[0], Number):
            non_number_index = 1
        elif isinstance(odd_terms[1], Number):
            non_number_index = 0
        if non_number_index is not None:
            term = odd_terms[non_number_index]
            if type(term) == Symbol:
                new_known_expressions[term] = 1
            elif type(term) == Mul:
                for arg in term.args:
                    if not isinstance(arg, Number):
                        new_known_expressions[arg] = 1
            else:
                # TODO: Example of clause which results in this case:
                # 2*q_2 + z_4_6 + z_5_6 - 4
                # (p=23, q=23, m=529)
                # This should be handled by rule 5
                # print("TODO: Z rule 2: don't know this type!")
                # pdb.set_trace()
                pass

        else:
            if 'q' in str(odd_terms[0]):
                non_q_index = 1
            else:
                non_q_index = 0
            variable_0 = odd_terms[1 - non_q_index]
            variable_1 = odd_terms[non_q_index]

            if type(variable_0) == Mul:
                if isinstance(variable_0.args[0], Number):
                    variable_0 = variable_0 / variable_0.args[0]

            if type(variable_1) == Mul:
                if isinstance(variable_1.args[0], Number):
                    variable_1 = variable_1 / variable_1.args[0]

            new_known_expressions[variable_1] = variable_0

            if len(even_negative_terms) == 1:
                term = even_negative_terms[0]
                if isinstance(term, Number):
                    # TODO: Example of clause which results in this case:
                    # q_2 + z_5_6 + 2*z_7_8 - 2
                    # (p=29, q=23, m=667)
                    # pdb.set_trace()
                    pass
                elif type(term) == Mul:
                    if len(even_positive_terms) == 0:
                        term = term / term.args[0]
                        new_known_expressions[term] = variable_0
                    else:
                        pass
                        # pdb.set_trace()
                else:
                    print("TODO: Z rule 2: don't know this type!")
                    pdb.set_trace()

    if len(odd_terms) == 3:
        number_index = None
        if isinstance(odd_terms[0], Number):
            number_index = 0
        elif isinstance(odd_terms[1], Number):
            number_index = 1
        elif isinstance(odd_terms[2], Number):
            number_index = 2
        if number_index is not None:
            indices = [0, 1, 2]
            indices.remove(number_index)
            new_term = odd_terms[indices[0]] * odd_terms[indices[1]]
            if isinstance(new_term.args[0], Number):
                new_term = new_term / new_term.args[0]
            if 'Pow' in srepr(new_term):
                new_term = simplify_clause(new_term, {})
            new_known_expressions[new_term] = 0

    if len(new_known_expressions) != 0:
        known_expressions = {**known_expressions, **new_known_expressions}
        if verbose:
            print("Z rule 2 applied:", new_known_expressions)

    return known_expressions
 def exprstrout(key, expr):
     return srepr(expr) + " " + ErrorOutput.messages.get(key, None)
Exemplo n.º 41
0
    #    tt = np.random.randint(2, size=8, dtype=bool)
    tt = np.array([False, True, True, True, False, False, True, True])
    print(tt.tolist())
    print(tt.tolist(), file=logfile)
    g = GP(
        num_vars=int(np.log2(tt.shape[0])),
        unique_pop=opt.unique_pop,
        bin_ops=(sympy.And, sympy.Or),
        target_tt=tt,
        pop_size=opt.pop_size,
        size_next_gen=opt.size_next_gen,
        lucky_per=opt.lucky_per,
        weight_num_gates=opt.weight_num_gates,
        weight_num_agree=opt.weight_num_agree,
        add_naive=opt.add_naive,
    )
    fn = g.util.syms[0] | (g.util.syms[1] & (~g.util.syms[2] | g.util.syms[0]))
    srepr = sympy.srepr(fn)
    mt = tt_to_sympy_minterms(g.util.target_tt)
    sop_form = SOPform(g.util.syms, mt)

    try:
        g.run(num_generations=opt.num_generations,
              init_pop_size=opt.init_pop_size)
        # g.run()
    except KeyboardInterrupt:
        pass
    g.print_best(logfile)

    # g.util.pool.terminate()  # terminated on this process's death, or so it seems
Exemplo n.º 42
0
    def _getDiffList(self):

        """
        Set the list for each of the occurences of Derivative objects that appear in the equations of the model

        :return:
            List of derivatives
        :rtype list(str) diff_list:
        """

        diff_list = []

        for eqi in self._equation_groups['differential']:

            eq = eqi._getSymbolicObject('residual','rhs')

            _ = [diff_list.append(abs(i).args[0]) for i in eq.args if 'Derivative' in sp.srepr(i)]

        return diff_list
Exemplo n.º 43
0
def test_hilbert_space():
    hs = HilbertSpace()
    assert isinstance(hs, HilbertSpace)
    assert sstr(hs) == 'H'
    assert srepr(hs) == 'HilbertSpace()'
Exemplo n.º 44
0
 def get_sqrt_g(self):
     """Return square root of determinant of covariant metric tensor"""
     g = self.get_g()
     return sp.simplify(sp.srepr(sp.sqrt(g)).replace('Abs', ''))
Exemplo n.º 45
0
def test_issue_4788():
    assert srepr(S(1.0 + 0J)) == srepr(S(1.0)) == srepr(Float(1.0))
Exemplo n.º 46
0
def test_issue1689():
    assert srepr(S(1.0 + 0j)) == srepr(S(1.0)) == srepr(Real(1.0))
    assert srepr(Real(1)) != srepr(Real(1.0))
Exemplo n.º 47
0
        [ omega_x_terms_expr[theta_dot_expr], omega_x_terms_expr[psi_dot_expr], omega_x_terms_expr[phi_dot_expr] ] ] )

    A_dot_expr = sympy.trigsimp(A_expr.diff(t_expr))

    syms = [ theta_expr, psi_expr, phi_expr, theta_dot_expr, psi_dot_expr, phi_dot_expr ]

    print("Dummifying sympy expressions...")

    A_expr_dummy,     A_expr_dummy_syms     = sympyutils.dummify( A_expr,     syms )
    A_dot_expr_dummy, A_dot_expr_dummy_syms = sympyutils.dummify( A_dot_expr, syms )

    print( "Saving sympy expressions...")

    current_source_file_path = pathutils.get_current_source_file_path()

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy.dat",     "w") as f: f.write(sympy.srepr(A_expr_dummy))
    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_dot_expr_dummy.dat", "w") as f: f.write(sympy.srepr(A_dot_expr_dummy))

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy_syms.dat",     "w") as f: f.write(sympy.srepr(sympy.Matrix(A_expr_dummy_syms)))
    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_dot_expr_dummy_syms.dat", "w") as f: f.write(sympy.srepr(sympy.Matrix(A_dot_expr_dummy_syms)))

else:

    print("Loading sympy expressions...")

    current_source_file_path = pathutils.get_current_source_file_path()

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy.dat",     "r") as f: A_expr_dummy     = sympy.sympify(f.read())
    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_dot_expr_dummy.dat", "r") as f: A_dot_expr_dummy = sympy.sympify(f.read())

    with open(current_source_file_path+"/data/sympy/quadrotorcamera3d_A_expr_dummy_syms.dat",     "r") as f: A_expr_dummy_syms     = array(sympy.sympify(f.read())).squeeze()
Exemplo n.º 48
0
def expr_convert_to_SIMD_intrins(expr,
                                 map_sym_to_rat,
                                 prefix="",
                                 SIMD_find_more_FMAsFMSs="False",
                                 debug="False"):
    # OVERRIDE; THIS NEW DEFAULT IS FASTER
    SIMD_find_more_FMAsFMSs = "True"

    for item in preorder_traversal(expr):
        for arg in item.args:
            if isinstance(arg, Symbol):
                var(str(arg))

    def lookup_rational(arg):
        if arg.func == Symbol:
            try:
                arg = map_sym_to_rat[arg]
            except KeyError:
                pass
        return arg

    map_rat_to_sym = {map_sym_to_rat[v]: v for v in map_sym_to_rat}

    expr_orig, tree = expr, ExprTree(expr)

    AbsSIMD = Function("AbsSIMD")
    AddSIMD = Function("AddSIMD")
    SubSIMD = Function("SubSIMD")
    MulSIMD = Function("MulSIMD")
    FusedMulAddSIMD = Function("FusedMulAddSIMD")
    FusedMulSubSIMD = Function("FusedMulSubSIMD")
    DivSIMD = Function("DivSIMD")
    SignSIMD = Function("SignSIMD")

    PowSIMD = Function("PowSIMD")
    SqrtSIMD = Function("SqrtSIMD")
    CbrtSIMD = Function("CbrtSIMD")
    ExpSIMD = Function("ExpSIMD")
    LogSIMD = Function("LogSIMD")
    SinSIMD = Function("SinSIMD")
    CosSIMD = Function("CosSIMD")

    # Step 1: Replace transcendental, power, and division functions with SIMD equivalents
    #         Note that due to how SymPy expresses rational numbers, the following does not
    #         affect fractional expressions of integers
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        if func == Abs:
            subtree.expr = AbsSIMD(args[0])
        elif func == exp:
            subtree.expr = ExpSIMD(args[0])
        elif func == log:
            subtree.expr = LogSIMD(args[0])
        elif func == sin:
            subtree.expr = SinSIMD(args[0])
        elif func == cos:
            subtree.expr = CosSIMD(args[0])
        elif func == sign:
            subtree.expr = SignSIMD(args[0])
    expr = tree.reconstruct(evaluate=True)

    # Fun little recursive function for constructing integer powers:
    def IntegerPowSIMD(a, n):
        if n == 2:
            return MulSIMD(a, a)
        elif n > 2:
            return MulSIMD(IntegerPowSIMD(a, n - 1), a)
        elif n <= -2:
            one = Symbol(prefix + '_Integer_1')
            try:
                map_rat_to_sym[1]
            except KeyError:
                map_sym_to_rat[one], map_rat_to_sym[1] = S.One, one
            return DivSIMD(one, IntegerPowSIMD(a, -n))
        elif n == -1:
            one = Symbol(prefix + '_Integer_1')
            try:
                map_rat_to_sym[1]
            except KeyError:
                map_sym_to_rat[one], map_rat_to_sym[1] = S.One, one
            return DivSIMD(one, a)

    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        if func == Pow:
            exponent = lookup_rational(args[1])
            if exponent == 0.5:
                subtree.expr = SqrtSIMD(args[0])
                subtree.children.pop(1)  # Remove 0.5
            elif exponent == -0.5:
                subtree.expr = DivSIMD(1, SqrtSIMD(args[0]))
                tree.build(subtree, clear=True)
            elif exponent == Rational(1, 3):
                subtree.expr = CbrtSIMD(args[0])
                subtree.children.pop(1)  # Remove -0.5
            elif isinstance(exponent, Integer):
                subtree.expr = IntegerPowSIMD(args[0], exponent)
                tree.build(subtree, clear=True)
            else:
                subtree.expr = PowSIMD(*args)
    expr = tree.reconstruct()

    # We must evaluate the expression, otherwise nested multiplications
    # will arise that conflict with the following replacements in Step 3.

    # Step 2: SIMD multiplication and addition compiler intrinsics read in
    #         only two arguments at once, where SymPy's Mul() and Add()
    #         operators can read an arbitrary number of arguments.
    #         Here, we split e.g., Mul(a, b, c, d) into
    #         MulSIMD(a, MulSIMD(b, MulSIMD(c, d))),
    #         To accomplish this easily, we construct a string
    #         'MulSIMD(A, MulSIMD(B, ...', where MulSIMD(a, b) is some user-
    #         defined function that takes in only two arguments, and then
    #         evaluate the string using the eval() function.
    # Implementation detail: If we did not perform Step 2 above, the eval
    #         function would automatically evaluate all Rational expressions
    #         as though they were input as integers: e.g., 1/2 evaluates to 0.
    #         This is undesirable, so we instead define new, temporary
    #         functions IntegerTMP and RationalTMP that are undisturbed by
    #         the eval()
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        if (func == Mul or func == Add):
            func = MulSIMD if func == Mul else AddSIMD
            subexpr = func(*args[-2:])
            for arg in args[:-2]:
                subexpr = func(arg, subexpr, evaluate=False)
            subtree.expr = subexpr
            tree.build(subtree, clear=True)
    expr = tree.reconstruct()

    # Step 3: Simplification patterns:
    # Step 3.a: Replace the pattern Mul(Div(1, b), a) or Mul(a, Div(1, b)) with Div(a, b):
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # MulSIMD(DivSIMD(1, b), a) >> DivSIMD(a, b)
        if   func == MulSIMD and args[0].func == DivSIMD and \
                lookup_rational(args[0].args[0]) == 1:
            subtree.expr = DivSIMD(args[1], args[0].args[1])
            tree.build(subtree, clear=True)
        # MulSIMD(a, DivSIMD(1, b)) >> DivSIMD(a, b)
        elif func == MulSIMD and args[1].func == DivSIMD and \
                lookup_rational(args[1].args[0]) == 1:
            subtree.expr = DivSIMD(args[0], args[1].args[1])
            tree.build(subtree, clear=True)
    expr = tree.reconstruct()

    # Step 3.b: Subtraction intrinsics. SymPy replaces all a - b with a + (-b) = Add(a, Mul(-1, b))
    #         Here, we replace
    #         a) AddSIMD(MulSIMD(-1, b), a),
    #         b) AddSIMD(MulSIMD(b, -1), a),
    #         c) AddSIMD(a, MulSIMD(-1, b)), and
    #         d) AddSIMD(a, MulSIMD(b, -1))
    #         with SubSIMD(a, b)
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # AddSIMD(MulSIMD(-1, b), a) >> SubSIMD(a, b)
        if   func == AddSIMD and args[0].func == MulSIMD and \
                lookup_rational(args[0].args[0]) == -1:
            subtree.expr = SubSIMD(args[1], args[0].args[1])
            tree.build(subtree, clear=True)
        # AddSIMD(MulSIMD(b, -1), a) >> SubSIMD(a, b)
        elif func == AddSIMD and args[0].func == MulSIMD and \
                lookup_rational(args[0].args[1]) == -1:
            subtree.expr = SubSIMD(args[1], args[0].args[0])
            tree.build(subtree, clear=True)
        # AddSIMD(a, MulSIMD(-1, b)) >> SubSIMD(a, b)
        elif func == AddSIMD and args[1].func == MulSIMD and \
                lookup_rational(args[1].args[0]) == -1:
            subtree.expr = SubSIMD(args[0], args[1].args[1])
            tree.build(subtree, clear=True)
        # AddSIMD(a, MulSIMD(b, -1)) >> SubSIMD(a, b)
        elif func == AddSIMD and args[1].func == MulSIMD and \
                lookup_rational(args[1].args[1]) == -1:
            subtree.expr = SubSIMD(args[0], args[1].args[0])
            tree.build(subtree, clear=True)
    expr = tree.reconstruct()

    # Step 4: Now that all multiplication and addition functions only take two
    #         arguments, we can now easily define fused-multiply-add functions,
    #         where AddSIMD(a, MulSIMD(b, c)) = b*c + a = FusedMulAddSIMD(b, c, a),
    #         or    AddSIMD(MulSIMD(b, c), a) = b*c + a = FusedMulAddSIMD(b, c, a).
    # Fused multiply add (FMA3) is standard on Intel CPUs with the AVX2
    #         instruction set, starting with Haswell processors in 2013:
    #         https://en.wikipedia.org/wiki/Haswell_(microarchitecture)

    # Step 4.a: Find double FMA patterns first [e.g., FMA(a,b,FMA(c,d,e))]:
    #           NOTE: Double FMA simplifications do not guarantee a significant performance impact when solving BSSN equations:
    if SIMD_find_more_FMAsFMSs == "True":
        for subtree in tree.preorder():
            func = subtree.expr.func
            args = subtree.expr.args
            # a + b*c + d*e -> FMA(b,c,FMA(d,e,a))
            # AddSIMD(a, AddSIMD(MulSIMD(b,c), MulSIMD(d,e))) >> FusedMulAddSIMD(b, c, FusedMulAddSIMD(d,e,a))
            # Validate:
            # x = a + b*c + d*e
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            if (func == AddSIMD and args[1].func == AddSIMD
                    and args[1].args[0].func == MulSIMD
                    and args[1].args[1].func == MulSIMD):
                subtree.expr = FusedMulAddSIMD(
                    args[1].args[0].args[0], args[1].args[0].args[1],
                    FusedMulAddSIMD(args[1].args[1].args[0],
                                    args[1].args[1].args[1], args[0]))
                tree.build(subtree, clear=True)
            # b*c + d*e + a -> FMA(b,c,FMA(d,e,a))
            # Validate:
            # x = b*c + d*e + a
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            # AddSIMD(AddSIMD(MulSIMD(b,c), MulSIMD(d,e)),a) >> FusedMulAddSIMD(b, c, FusedMulAddSIMD(d,e,a))
            elif func == AddSIMD and args[0].func == AddSIMD and args[0].args[
                    0].func == MulSIMD and args[0].args[1].func == MulSIMD:
                subtree.expr = FusedMulAddSIMD(
                    args[0].args[0].args[0], args[0].args[0].args[1],
                    FusedMulAddSIMD(args[0].args[1].args[0],
                                    args[0].args[1].args[1], args[1]))
                tree.build(subtree, clear=True)
        expr = tree.reconstruct()

    # Step 4.b: Next find single FMA patterns:
    for subtree in tree.preorder():
        func = subtree.expr.func
        args = subtree.expr.args
        # AddSIMD(MulSIMD(b, c), a) >> FusedMulAddSIMD(b, c, a)
        if func == AddSIMD and args[0].func == MulSIMD:
            subtree.expr = FusedMulAddSIMD(args[0].args[0], args[0].args[1],
                                           args[1])
            tree.build(subtree, clear=True)
        # AddSIMD(a, MulSIMD(b, c)) >> FusedMulAddSIMD(b, c, a)
        elif func == AddSIMD and args[1].func == MulSIMD:
            subtree.expr = FusedMulAddSIMD(args[1].args[0], args[1].args[1],
                                           args[0])
            tree.build(subtree, clear=True)
        # SubSIMD(MulSIMD(b, c), a) >> FusedMulSubSIMD(b, c, a)
        elif func == SubSIMD and args[0].func == MulSIMD:
            subtree.expr = FusedMulSubSIMD(args[0].args[0], args[0].args[1],
                                           args[1])
            tree.build(subtree, clear=True)
    expr = tree.reconstruct()

    # Step 4.c: Leftover double FMA patterns that are difficult to find in Step 5.a:
    #           NOTE: Double FMA simplifications do not guarantee a significant performance impact when solving BSSN equations:
    if SIMD_find_more_FMAsFMSs == "True":
        for subtree in tree.preorder():
            func = subtree.expr.func
            args = subtree.expr.args
            # (b*c - d*e) + a -> AddSIMD(a, FusedMulSubSIMD(b, c, MulSIMD(d, e))) >> FusedMulSubSIMD(b, c, FusedMulSubSIMD(d,e,a))
            # Validate:
            # x = (b*c - d*e) + a
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            if func == AddSIMD and args[1].func == FusedMulSubSIMD and args[
                    1].args[2].func == MulSIMD:
                subtree.expr = FusedMulSubSIMD(
                    args[1].args[0], args[1].args[1],
                    FusedMulSubSIMD(args[1].args[2].args[0],
                                    args[1].args[2].args[1], args[0]))
                tree.build(subtree, clear=True)
            # b*c - (a - d*e) -> SubSIMD(FusedMulAddSIMD(b, c, MulSIMD(d, e)), a) >> FMA(b,c,FMS(d,e,a))
            # Validate:
            # x = b * c - (a - d * e)
            # outputC(x, "x", params="SIMD_enable=True,SIMD_debug=True")
            elif func == SubSIMD and args[0].func == FusedMulAddSIMD and args[
                    0].args[2].func == MulSIMD:
                subtree.expr = FusedMulAddSIMD(
                    args[0].args[0], args[0].args[1],
                    FusedMulSubSIMD(args[0].args[2].args[0],
                                    args[0].args[2].args[1], args[1]))
                tree.build(subtree, clear=True)
            # (b*c - d*e) - a -> SubSIMD(FusedMulSubSIMD(b, c, MulSIMD(d, e)), a) >> FMS(b,c,FMA(d,e,a))
            # Validate:
            # x = (b*c - d*e) - a
            # outputC(x,"x", params="SIMD_enable=True,SIMD_debug=True")
            elif func == SubSIMD and args[0].func == FusedMulSubSIMD and args[
                    0].args[2].func == MulSIMD:
                subtree.expr = FusedMulSubSIMD(
                    args[0].args[0], args[0].args[1],
                    FusedMulAddSIMD(args[0].args[2].args[0],
                                    args[0].args[2].args[1], args[1]))
                tree.build(subtree, clear=True)
        expr = tree.reconstruct()

    if debug == "True":
        expr_check = eval(str(expr).replace("SIMD", "SIMD_check"))
        expr_check = expr_check.subs(-1, Symbol('_NegativeOne_'))

        expr_diff = expr_check - expr_orig
        # The eval(str(srepr())) below normalizes the expression,
        # fixing a cancellation issue in SymPy ~0.7.4.
        expr_diff = eval(str(srepr(expr_diff)))
        tree_diff = ExprTree(expr_diff)
        for subtree in tree_diff.preorder():
            subexpr = subtree.expr
            if subexpr.func == Float:
                if abs(subexpr - Integer(subexpr)) < 1.0e-14:
                    subtree.expr = Integer(item)
        expr_diff = tree_diff.reconstruct()

        if expr_diff != 0:
            simp_expr_diff = simplify(expr_diff)
            if simp_expr_diff != 0:
                raise Warning('Expression Difference: ' + str(simp_expr_diff))
    return (expr)
Exemplo n.º 49
0
def test_issue_4788():
    assert srepr(S(1.0 + 0J)) == srepr(S(1.0)) == srepr(Float(1.0))
Exemplo n.º 50
0
def view_tree(expr):
    """Views a sympy expression tree."""
    print(srepr(expr))