```python
from sympy import *
init_printing(use_unicode=True)
```


```python
m = Matrix([1, 2, 3])
```


```python
m = Matrix(["c"])
```


```python
m
```




$$\left[\begin{matrix}c\end{matrix}\right]$$




```python
m*m
```




$$\left[\begin{matrix}c^{2}\end{matrix}\right]$$




```python
from sympy.abc import a,b,c
```


```python
m
```




$$\left[\begin{matrix}c\end{matrix}\right]$$




```python
m = ImmutableMatrix([c,c**2])
```


```python
m
```




$$\left[\begin{matrix}c\\c^{2}\end{matrix}\right]$$




```python
m*m.T
```




$$\left[\begin{matrix}c^{2} & c^{3}\\c^{3} & c^{4}\end{matrix}\right]$$




```python
(m*m.T)**2
```




$$\left[\begin{matrix}c^{6} + c^{4} & c^{7} + c^{5}\\c^{7} + c^{5} & c^{8} + c^{6}\end{matrix}\right]$$




```python
m[0,0]
```


```python
q = Matrix([[1,2],[3,4]])
```


```python
q^2
```


```python
q^-1
```


```python
q**-1
```


```python

```


```python

import numpy as np
from bqplot import *
from bqplot.marks import Graph
from ipywidgets import Layout
from relmath import * 
type(M)

fig_layout = Layout(width='960px', height='500px')
def disp(expr):
    
    print(type(expr))
    if type(expr) is MatMul:
        binop = expr
        
        left =  binop.left.simp()
        right = binop.right.simp()
        
        if type(left) is not Rel:
            raise ValueError("Can't simplify left operand to a Rel ! Found %s " % left)

        if type(right) is not Rel:
            raise ValueError("Can't simplify right operand to a Rel ! Found %s " % right)
            
        print(left)
        print(right)
            
        node_data =  left.dom + left.cod + right.cod
        print(node_data)

        link_data = []
        n = len(left.dom)
        m = len(left.cod)
        w = len(right.cod)
        for i in range(n):
            for j in range(m):
                link_data.append({'source': i, 'target': n+j, 'value': left.g[i][j].val})

        for i in range(m):
            for j in range(w):
                link_data.append({'source': n+i, 'target': n+m+j, 'value': right.g[i][j].val})
                
                
        print(link_data)

        xs = LinearScale()
        ys = LinearScale()
        lcs = ColorScale(scheme='Greens')
        x = ([100] * n) + ([200]*m) + ([300]*w)
        y = list(range(n)) + list(range(m)) + list(range(w))
        print(x)
        print(y)
        graph = Graph(node_data=node_data, link_data=link_data, link_type='line',
                      colors=['orange'], directed=False, 
                      scales={'x': xs, 'y': ys, 'link_color': lcs}, 
                      x=x, y=y,  color=np.random.rand(len(node_data)))
        return Figure(marks=[graph], layout=fig_layout)    
        
    
    elif type(expr) is Rel:
        node_data = expr.dom() + expr.cod()
        #print(node_data)

        link_data = []
        for i in range(len(expr.dom)):
            for j in range(len(expr.cod)):
                link_data.append({'source': i, 'target': i+j, 'value': expr.g[i][j].val})

        #print(link_data)

        xs = LinearScale()
        ys = LinearScale()
        lcs = ColorScale(scheme='Greens')
        x = ([100] * len(expr.dom)) + ([200]*len(expr.cod))
        y = list(range(len(expr.dom))) + list(range(len(expr.cod)))
        #print(x)
        #print(y)
        graph = Graph(node_data=node_data, link_data=link_data, link_type='line',
                      colors=['orange'], directed=False, 
                      scales={'x': xs, 'y': ys, 'link_color': lcs}, 
                      x=x, y=y,  color=np.random.rand(len(node_data)))
        return Figure(marks=[graph], layout=fig_layout)    
    else:
        raise ValueError("not supported type: %s" % type(expr) )
    
disp(E)    
```

    M = 
    [[9, 0, 6], [0, 5, 7]]
    ~M = 
    [[9, 0], [0, 5], [6, 7]]
    -M = 
    [[-9, 0, -6], [0, -5, -7]]
    M@~M=
    [[36, 42], [42, 49]]
    MatMul(M, T(M))
    [[9, 0, 6], [0, 5, 7]]@~[[9, 0, 6], [0, 5, 7]]
    MatMul(M, T(M)).simp()
    [[36, 42], [42, 49]]
    <class 'relmath.MatMul'>
    [[9, 0, 6], [0, 5, 7]]
    [[9, 0], [0, 5], [6, 7]]
    ['a', 'b', 'x', 'y', 'z', 'a', 'b']
    [{'source': 0, 'target': 2, 'value': 9}, {'source': 0, 'target': 3, 'value': 0}, {'source': 0, 'target': 4, 'value': 6}, {'source': 1, 'target': 2, 'value': 0}, {'source': 1, 'target': 3, 'value': 5}, {'source': 1, 'target': 4, 'value': 7}, {'source': 2, 'target': 5, 'value': 9}, {'source': 2, 'target': 6, 'value': 0}, {'source': 3, 'target': 5, 'value': 0}, {'source': 3, 'target': 6, 'value': 5}, {'source': 4, 'target': 5, 'value': 6}, {'source': 4, 'target': 6, 'value': 7}]
    [100, 100, 200, 200, 200, 300, 300]
    [0, 1, 0, 1, 2, 0, 1]



    Figure(fig_margin={'right': 60, 'top': 60, 'left': 60, 'bottom': 60}, layout=Layout(height='500px', width='960…



```python

```


```python
X = MatrixSymbol('X', 3, 4)
```


```python
X
```


```python
X[0,0]
```


```python
m
```




$$\left[\begin{matrix}c\\c^{2}\end{matrix}\right]$$




```python
srepr(m*m)
```




    "ImmutableDenseMatrix([[Pow(Symbol('c'), Integer(2)), Pow(Symbol('c'), Integer(3))], [Pow(Symbol('c'), Integer(3)), Pow(Symbol('c'), Integer(4))]])"




```python
sympify("m * m.T", locals={'m':m}, evaluate=False)
```




$$\left[\begin{matrix}c\\c^{2}\end{matrix}\right] \left[\begin{matrix}c & c^{2}\end{matrix}\right]$$




```python
help(sympify)
```

    Help on function sympify in module sympy.core.sympify:
    
    sympify(a, locals=None, convert_xor=True, strict=False, rational=False, evaluate=None)
        Converts an arbitrary expression to a type that can be used inside SymPy.
        
        For example, it will convert Python ints into instances of sympy.Integer,
        floats into instances of sympy.Float, etc. It is also able to coerce symbolic
        expressions which inherit from Basic. This can be useful in cooperation
        with SAGE.
        
        It currently accepts as arguments:
           - any object defined in sympy
           - standard numeric python types: int, long, float, Decimal
           - strings (like "0.09" or "2e-19")
           - booleans, including ``None`` (will leave ``None`` unchanged)
           - lists, sets or tuples containing any of the above
        
        .. warning::
            Note that this function uses ``eval``, and thus shouldn't be used on
            unsanitized input.
        
        If the argument is already a type that SymPy understands, it will do
        nothing but return that value. This can be used at the beginning of a
        function to ensure you are working with the correct type.
        
        >>> from sympy import sympify
        
        >>> sympify(2).is_integer
        True
        >>> sympify(2).is_real
        True
        
        >>> sympify(2.0).is_real
        True
        >>> sympify("2.0").is_real
        True
        >>> sympify("2e-45").is_real
        True
        
        If the expression could not be converted, a SympifyError is raised.
        
        >>> sympify("x***2")
        Traceback (most recent call last):
        ...
        SympifyError: SympifyError: "could not parse u'x***2'"
        
        Locals
        ------
        
        The sympification happens with access to everything that is loaded
        by ``from sympy import *``; anything used in a string that is not
        defined by that import will be converted to a symbol. In the following,
        the ``bitcount`` function is treated as a symbol and the ``O`` is
        interpreted as the Order object (used with series) and it raises
        an error when used improperly:
        
        >>> s = 'bitcount(42)'
        >>> sympify(s)
        bitcount(42)
        >>> sympify("O(x)")
        O(x)
        >>> sympify("O + 1")
        Traceback (most recent call last):
        ...
        TypeError: unbound method...
        
        In order to have ``bitcount`` be recognized it can be imported into a
        namespace dictionary and passed as locals:
        
        >>> from sympy.core.compatibility import exec_
        >>> ns = {}
        >>> exec_('from sympy.core.evalf import bitcount', ns)
        >>> sympify(s, locals=ns)
        6
        
        In order to have the ``O`` interpreted as a Symbol, identify it as such
        in the namespace dictionary. This can be done in a variety of ways; all
        three of the following are possibilities:
        
        >>> from sympy import Symbol
        >>> ns["O"] = Symbol("O")  # method 1
        >>> exec_('from sympy.abc import O', ns)  # method 2
        >>> ns.update(dict(O=Symbol("O")))  # method 3
        >>> sympify("O + 1", locals=ns)
        O + 1
        
        If you want *all* single-letter and Greek-letter variables to be symbols
        then you can use the clashing-symbols dictionaries that have been defined
        there as private variables: _clash1 (single-letter variables), _clash2
        (the multi-letter Greek names) or _clash (both single and multi-letter
        names that are defined in abc).
        
        >>> from sympy.abc import _clash1
        >>> _clash1
        {'C': C, 'E': E, 'I': I, 'N': N, 'O': O, 'Q': Q, 'S': S}
        >>> sympify('I & Q', _clash1)
        I & Q
        
        Strict
        ------
        
        If the option ``strict`` is set to ``True``, only the types for which an
        explicit conversion has been defined are converted. In the other
        cases, a SympifyError is raised.
        
        >>> print(sympify(None))
        None
        >>> sympify(None, strict=True)
        Traceback (most recent call last):
        ...
        SympifyError: SympifyError: None
        
        Evaluation
        ----------
        
        If the option ``evaluate`` is set to ``False``, then arithmetic and
        operators will be converted into their SymPy equivalents and the
        ``evaluate=False`` option will be added. Nested ``Add`` or ``Mul`` will
        be denested first. This is done via an AST transformation that replaces
        operators with their SymPy equivalents, so if an operand redefines any
        of those operations, the redefined operators will not be used.
        
        >>> sympify('2**2 / 3 + 5')
        19/3
        >>> sympify('2**2 / 3 + 5', evaluate=False)
        2**2/3 + 5
        
        Extending
        ---------
        
        To extend ``sympify`` to convert custom objects (not derived from ``Basic``),
        just define a ``_sympy_`` method to your class. You can do that even to
        classes that you do not own by subclassing or adding the method at runtime.
        
        >>> from sympy import Matrix
        >>> class MyList1(object):
        ...     def __iter__(self):
        ...         yield 1
        ...         yield 2
        ...         return
        ...     def __getitem__(self, i): return list(self)[i]
        ...     def _sympy_(self): return Matrix(self)
        >>> sympify(MyList1())
        Matrix([
        [1],
        [2]])
        
        If you do not have control over the class definition you could also use the
        ``converter`` global dictionary. The key is the class and the value is a
        function that takes a single argument and returns the desired SymPy
        object, e.g. ``converter[MyList] = lambda x: Matrix(x)``.
        
        >>> class MyList2(object):   # XXX Do not do this if you control the class!
        ...     def __iter__(self):  #     Use _sympy_!
        ...         yield 1
        ...         yield 2
        ...         return
        ...     def __getitem__(self, i): return list(self)[i]
        >>> from sympy.core.sympify import converter
        >>> converter[MyList2] = lambda x: Matrix(x)
        >>> sympify(MyList2())
        Matrix([
        [1],
        [2]])
        
        Notes
        =====
        
        Sometimes autosimplification during sympification results in expressions
        that are very different in structure than what was entered. Until such
        autosimplification is no longer done, the ``kernS`` function might be of
        some use. In the example below you can see how an expression reduces to
        -1 by autosimplification, but does not do so when ``kernS`` is used.
        
        >>> from sympy.core.sympify import kernS
        >>> from sympy.abc import x
        >>> -2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x))) - 1
        -1
        >>> s = '-2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x))) - 1'
        >>> sympify(s)
        -1
        >>> kernS(s)
        -2*(-(-x + 1/x)/(x*(x - 1/x)**2) - 1/(x*(x - 1/x))) - 1
    



```python
Matrix(['s',3])
```




$$\left[\begin{matrix}s\\3\end{matrix}\right]$$




```python
p
```




$$\left[\begin{matrix}s\\3\end{matrix}\right]$$




```python
Matrix(['s',{'a':'b'}])
```




$$\left[\begin{matrix}s\\\left \{ a : b\right \}\end{matrix}\right]$$




```python
p = Matrix(['s',['a']])
p
```




$$\left[\begin{matrix}s\\\left [ a\right ]\end{matrix}\right]$$




```python
p += Matrix(["c","d"])
```


```python
p = Matrix([[['s'],'r'],['a','e']])
```




$$\left[\begin{matrix}\left [ s\right ] & r\\a & e\end{matrix}\right]$$




```python
p.c = 2
```


```python
p
```




$$\left[\begin{matrix}s\\\left [ a\right ]\end{matrix}\right]$$




```python
p.c
```


```python
p.afdsf = 2
```


```python
m = ImmutableMatrix([2,3])
```


```python
isinstance(4, float)
```




    False




```python
from sympy.core.singleton import S

    
    
        
class Dioid(AtomicExpr):
    
    is_number = True
    
    @cacheit
    def __new__(cls,*args):
        tmp = []
        for a in args:
            a = sympify(a,strict=True)
            if type(a) is cls:
                tmp.extend(a.args)
            else:
                tmp.append(a)
        return super().__new__(cls,*tmp)    
        
    def __mul__(self, other):
        return self._eval_mul(other)
    
    @decorators._sympifyit('other', NotImplemented)    
    def __add__(self, other):
        return self._eval_add(other)

    def __neg__(self):
        return self._eval_neg()

    def s(self):
        """ The set of discourse """
        raise NotImplementedError("IMPLEMENT ME!")    
                
    def zero(self):
        raise NotImplementedError("IMPLEMENT ME!")    
        
    def one(self):
        raise NotImplementedError("IMPLEMENT ME!")    
        
    def __str__(self):
        
        return "%s(%s)" % (self.__class__.__name__, str(self.args[0]))
    
    def __repr__(self):
        return self.__str__()    

    def _eval_neg(self, other):
        """ NOTE: in a dioid, negation is _not_ mandatory. See page 7 of Graphs, Dioids and Semirings book
        """
        raise NotImplemented("Not available for this dioid !")
        
        raise NotImplementedError("")
        
    def _eval_add(self, other):
        raise NotImplementedError("")
    
    def _eval_mul(self, other):
        raise NotImplementedError("")

    def __radd__(self, a):
        """Implementation of reverse add method."""
        return a.__add__(self)       
    
            
class RD(Dioid):
    def __init__(self, val):
        self.val = sympify(val)
        super().__init__()
    
    def zero(self):
        return S(0)
    
    def one(self):
        return S(1)
    
    def s(self):
        return "TODO R^ set "

    def _eval_neg(self):
        """ NOTE: in a dioid, negation is _not_ mandatory. See page 7 of Graphs, Dioids and Semirings book
        """
        return self.__class__(- self.args[0])
        
    def _eval_add(self, d2):
        
        if isinstance(d2,int) or isinstance(d2,float):
            return self.__class__(self.args[0] * d2)
        elif isinstance(d2, RD):
            return self.__class__(self.args[0] + d2.args[0])
        
    def _eval_mul(self, d2):
        if isinstance(d2,int) or isinstance(d2,float):
            return self.__class__(self.args[0] * d2)
        elif isinstance(d2, RD):
            return self.__class__(self.args[0] * d2.args[0])
        elif return NotImplemented
        
    
    #@classmethod
    #def eval(cls, arg):
        # Phi(x) + Phi(-x) == 1
        #if arg.could_extract_minus_sign():
        #    return 1-cls(-arg)
        
class Rel(ImmutableMatrix):
    def __init__(self, par, dom=[], cod=[]):
        super().__init__()
        self.dom=dom
        self.cod=cod
                
    def _eval_matrix_mul(self, other):
        r = super()._eval_matrix_mul(other)
        r.dom = self.dom
        r.cod = other.cod
        return r
    
    def _eval_transpose(self):
        r = super()._eval_transpose()
        r.dom = self.cod
        r.cod = self.dom
        return r
    
    T = property(transpose, None, None, "Matrix transposition.")
```


```python
(Add(RD(3), RD(7))).evalf()
```


```python
simplify(Add(RD(3), RD(7)))
```


```python
RD(5)
```


```python
RD(5) == RD(5)
```




    True




```python
-RD(5)
```


```python
RD(3) + RD(7)
```


```python
w = Rel([RD(3)])
```


```python
sympify(Add(RD(3), RD(7)))
```


```python
Add(RD(3), RD(7)).doit()
```


```python
simplify(Add(RD(3), RD(7)))
```


```python
(Add(Integer(3), Integer(7))).evalf()
```


```python
simplify(Add(Integer(3), Integer(7)))
```


```python
w = Rel([[RD(2),RD(5)]], dom=['a','b'], cod=['x','y','z'])
```


```python
w
```




$$\left[\begin{matrix}RD(2) & RD(5)\end{matrix}\right]$$




```python
x = w*w.T
```


```python
x
```




$$\left[\begin{matrix}RD(4) + RD(25)\end{matrix}\right]$$




```python
simplify(x[0])
```


```python
r = Rel([[2,5]], dom=['a','b'], cod=['x','y','z'])
```


```python
p = r*r.T
```


```python
p
```




$$\left[\begin{matrix}29\end{matrix}\right]$$




```python
type(p)
```




    __main__.Rel




```python
p.dom
```




    ['a', 'b']




```python
p.cod
```




    ['a', 'b']




```python
r
```




$$\left[\begin{matrix}2 & 5\end{matrix}\right]$$




```python
r.dom
```




    ['a', 'b']




```python
Rel([2,5])
```




$$\left[\begin{matrix}2\\5\end{matrix}\right]$$




```python
s = sympify("r * r.T", locals={'r':r}, evaluate=False)
```


```python
s
```




$$\left[\begin{matrix}2\\5\end{matrix}\right] \left[\begin{matrix}2 & 5\end{matrix}\right]$$




```python
s.args[0].dom
```




    ['a', 'b']




```python
s.args[0].cod
```




    ['x', 'y', 'z']




```python
s.simplify
```


```python
m
```




$$\left[\begin{matrix}2\\3\end{matrix}\right]$$




```python
m.prova = ['a','b']
```


```python
m.prova
```




    ['a', 'b']




```python
s = sympify("m * m.T", locals={'m':m}, evaluate=False)
```


```python
s
```




$$\left[\begin{matrix}2\\3\end{matrix}\right] \left[\begin{matrix}2 & 3\end{matrix}\right]$$




```python
s.args[0]
```




$$\left[\begin{matrix}2\\3\end{matrix}\right]$$




```python
s.args[0].prova
```


```python

```

496e4e999b6ef74d9674c15515d1e54aaa24c02a
ipynb
Jupyter Notebook
relsym.ipynb
DavidLeoni/relmath
18e1bcad4e31ce8661e23e64f7fb450b8036bfcf
Apache-2.0
2019-01-04T13:22:00.000Z
2019-01-04T13:22:00.000Z
relsym.ipynb
DavidLeoni/relmath
18e1bcad4e31ce8661e23e64f7fb450b8036bfcf
Apache-2.0
2019-01-02T16:58:41.000Z
2019-01-02T17:03:38.000Z
relsym.ipynb
DavidLeoni/relmath
18e1bcad4e31ce8661e23e64f7fb450b8036bfcf
Apache-2.0
Qwen/Qwen-72B
1. YES
2. YES