Implemented crisscross algorithm for solving LP problems.
[sympycore.git] / sympycore / ring / algebra.py
blob287dac80a3854ed01568f97f4dd51d43360402e1
2 __all__ = ['Ring', 'CommutativeRing']
4 from ..basealgebra import Algebra
5 from .interface import RingInterface
7 from ..core import init_module, classes
8 init_module.import_heads()
9 init_module.import_numbers()
11 @init_module
12 def _init(m):
13 from ..arithmetic import mpq
14 Ring.coefftypes = (int, long, mpq)
16 class Ring(Algebra, RingInterface):
17 """
18 Ring represents algebraic ring (R, +, *) where (R, +) is abelian
19 group, (R,*) is monoid, with distributivity.
20 """
22 @classmethod
23 def get_function_algebra(cls):
24 return classes.FunctionRing
26 def __str__(self):
27 h, d = self.pair
28 return h.data_to_str_and_precedence(type(self), d)[0]
30 def __pos__(self):
31 return self
33 def __neg__(self):
34 return self.head.neg(type(self), self)
36 def __add__(self, other):
37 cls = type(self)
38 tother = type(other)
39 if tother is not cls:
40 if tother in numbertypes_set:
41 return self.head.add_number(cls, self, other)
42 other = cls.convert(other, typeerror=False)
43 if other is NotImplemented: return NotImplemented
44 return self.head.add(cls, self, other)
46 __radd__ = __add__
48 def __iadd__(self, other):
49 cls = type(self)
50 if type(other) is not cls:
51 other = cls.convert(other, typeerror=False)
52 if other is NotImplemented: return NotImplemented
53 return self.head.inplace_add(cls, self, other)
55 def __sub__(self, other):
56 cls = type(self)
57 tother = type(other)
58 if tother is not cls:
59 if tother in numbertypes_set:
60 return self.head.sub_number(cls, self, other)
61 other = cls.convert(other, typeerror=False)
62 if other is NotImplemented: return NotImplemented
63 return self.head.sub(cls, self, other)
65 def __rsub__(self, other):
66 return other + (-self)
68 def __isub__(self, other):
69 cls = type(self)
70 if type(other) is not cls:
71 other = cls.convert(other, typeerror=False)
72 if other is NotImplemented: return NotImplemented
73 return self.head.inplace_add(cls, self, -other)
75 def __mul__(self, other):
76 cls = type(self)
77 tother = type(other)
78 if cls is not tother:
79 if tother in numbertypes_set:
80 return self.head.non_commutative_mul_number(cls, self, other)
81 other = cls.convert(other, typeerror=False)
82 if other is NotImplemented: return NotImplemented
83 return self.head.non_commutative_mul(cls, self, other)
85 def __rmul__(self, other):
86 cls = type(self)
87 tother = type(other)
88 if cls is not tother:
89 if tother in numbertypes_set:
90 return self.head.non_commutative_rmul_number(cls, self, other)
91 other = cls.convert(other, typeerror=False)
92 if other is NotImplemented: return NotImplemented
93 return other.head.non_commutative_mul(cls, other, self)
95 def __pow__(self, other):
96 cls = type(self)
97 tother = type(other)
98 if tother is not cls:
99 if tother in numbertypes_set:
100 return self.head.pow_number(cls, self, other)
101 other = cls.convert(other, typeerror=False)
102 if other is NotImplemented: return NotImplemented
103 return self.head.pow(cls, self, other)
105 def __rpow__(self, other):
106 cls = type(self)
107 tother = type(other)
108 if cls is not tother:
109 other = cls.convert(other, typeerror=False)
110 if other is NotImplemented: return NotImplemented
111 return other.head.pow(cls, other, self)
113 def __div__(self, other):
114 cls = type(self)
115 tother = type(other)
116 if tother is not cls:
117 if tother in numbertypes_set:
118 return self.head.non_commutative_div_number(cls, self, other)
119 other = cls.convert(other, typeerror=False)
120 if other is NotImplemented: return NotImplemented
121 return self * other**-1
123 def __rdiv__(self, other):
124 cls = type(self)
125 tother = type(other)
126 if cls is not tother:
127 other = cls.convert(other, typeerror=False)
128 if other is NotImplemented: return NotImplemented
129 return other * self**-1
131 __truediv__ = __div__
133 def expand(self):
134 return self.head.expand(type(self), self)
136 def evalf(self, n=None):
137 return self.head.evalf(type(self), self, n)
139 class CommutativeRing(Ring):
141 def __mul__(self, other):
142 cls = type(self)
143 tother = type(other)
144 if tother is not cls:
145 if tother in numbertypes_set:
146 return self.head.commutative_mul_number(cls, self, other)
147 other = cls.convert(other, typeerror=False)
148 if other is NotImplemented:
149 return NotImplemented
150 return self.head.commutative_mul(cls, self, other)
152 __rmul__ = __mul__
154 def __imul__(self, other):
155 cls = type(self)
156 if type(other) is not cls:
157 other = cls.convert(other, typeerror=False)
158 if other is NotImplemented:
159 return NotImplemented
160 return self.head.inplace_commutative_mul(cls, self, other)
162 def __div__(self, other):
163 cls = type(self)
164 tother = type(other)
165 if tother is not cls:
166 if tother in numbertypes_set:
167 return self.head.commutative_div_number(cls, self, other)
168 other = cls.convert(other, typeerror=False)
169 if other is NotImplemented:
170 return NotImplemented
171 return self.head.commutative_div(cls, self, other)
173 def __rdiv__(self, other):
174 cls = type(self)
175 tother = type(other)
176 if tother is not cls:
177 if tother in numbertypes_set:
178 return self.head.commutative_rdiv_number(cls, self, other)
179 other = cls.convert(other, typeerror=False)
180 if other is NotImplemented:
181 return NotImplemented
182 return other * self**-1
184 def to(self, target, *args):
185 """ Convert expression to target representation.
187 The following targets are recognized:
189 EXP_COEFF_DICT - convert expression to exponents-coefficient
190 representation, additional arguments are variables. When
191 no arguments are specified, variables will be all symbols
192 and non-power expressions used in the expression.
194 TERM_COEFF_DICT - convert expression to term-coefficient
195 representation. Note that the returned result may have
196 actual head NUMBER, SYMBOL, TERM_COEFF, POW, or
197 BASE_EXP_DICT instead of TERM_COEFF_DICT.
199 head, data = self.pair
200 if target is head:
201 return self
202 if target is EXP_COEFF_DICT:
203 return head.to_EXP_COEFF_DICT(type(self), data, self, args or None)
204 if target is TERM_COEFF_DICT:
205 return head.to_TERM_COEFF_DICT(type(self), data, self)
206 raise NotImplementedError('%s.to(target=%r)' % (type(self), target))
208 def diff(self, symbol, order=1):
209 if order==0:
210 return self
211 cls = type(self)
212 if type(symbol) is cls:
213 assert symbol.head is SYMBOL,`symbol.pair`
214 symbol = symbol.data
215 elif isinstance(symbol, str):
216 pass
217 else:
218 raise TypeError('diff(symbol, order) first argument must be str or %s instance but got %s instance' % (cls.__name__, type(symbol).__name__))
219 try:
220 cache = {}
221 result = self.head.diff(cls, self.data, self, symbol, order, cache=cache)
222 finally:
223 cache.clear()
224 return result
226 def integrate(self, x):
227 cls = type(self)
229 t = type(x)
230 if t is tuple:
231 x, a, b = x
232 t = type(x)
233 else:
234 a, b = None, None
236 if t is cls:
237 assert x.head is SYMBOL,`x.pair`
238 x = x.data
239 elif t is str:
240 pass
241 else:
242 raise TypeError('integrate(x,..), x must be str or %s instance but got %s instance' % (cls.__name__, type(symbol).__name__))
244 if a is None:
245 return self.head.integrate_indefinite(cls, self.data, self, x)
246 if type(a) is not cls:
247 a = cls(a)
248 if type(b) is not cls:
249 b = cls(b)
250 return self.head.integrate_definite(cls, self.data, self, x, a, b)
252 classes.Ring = Ring
253 classes.CommutativeRing = CommutativeRing