Implemented crisscross algorithm for solving LP problems.
[sympycore.git] / sympycore / heads / neg.py
blob6f8ddaa954e29728ae1cf86d0a29c537accc3c43
2 __all__ = ['NEG']
4 from .base import heads_precedence, ArithmeticHead
5 from ..core import init_module
7 init_module.import_heads()
8 init_module.import_lowlevel_operations()
9 init_module.import_numbers()
11 class NegHead(ArithmeticHead):
13 """
14 NegHead represents negative unary operation where operand (data)
15 is an expression.
16 """
18 op_mth = '__neg__'
20 def is_data_ok(self, cls, data):
21 if not isinstance(data, cls):
22 return '%s data part must be %s instance but got %s' % (self, cls, type(data))
24 def __repr__(self): return 'NEG'
26 def new(self, cls, expr, evaluate=True):
27 if not evaluate:
28 return cls(self, expr)
29 h, d = expr.pair
30 if h is NUMBER:
31 return cls(NUMBER, -d)
32 if h is TERM_COEFF:
33 t, c = d
34 return TERM_COEFF.new(cls, (t, -c))
35 return cls(NEG, expr)
37 def reevaluate(self, cls, expr):
38 return -expr
40 def data_to_str_and_precedence(self, cls, expr):
41 if cls.algebra_options.get('evaluate_addition'):
42 if expr.head is NEG:
43 expr = expr.data
44 return expr.head.data_to_str_and_precedence(cls, expr.data)
45 s, s_p = expr.head.data_to_str_and_precedence(cls, expr.data)
46 neg_p = heads_precedence.NEG
47 if s_p < neg_p:
48 return '-(' + s + ')', neg_p
49 return '-' + s, neg_p
51 def to_lowlevel(self, cls, data, pair):
52 if isinstance(data, numbertypes):
53 return -data
54 if data.head is NUMBER:
55 return -data.data
56 return cls(TERM_COEFF, (data, -1))
58 def term_coeff(self, cls, expr):
59 e = expr.data
60 t, c = e.head.term_coeff(cls, e)
61 return t, -c
63 def scan(self, proc, cls, expr, target):
64 expr.head.scan(proc, cls, expr.data, target)
65 proc(cls, self, expr, target)
67 def walk(self, func, cls, operand, target):
68 operand1 = operand.head.walk(func, cls, operand.data, operand)
69 if operand1 is operand:
70 return func(cls, self, operand, target)
71 r = self.new(cls, operand1)
72 return func(cls, r.head, r.data, r)
74 def to_TERM_COEFF_DICT(self, Algebra, data, expr):
75 return -data.head.to_TERM_COEFF_DICT(Algebra, data.data, data)
77 def to_ADD(self, Algebra, data, expr):
78 return -data.head.to_ADD(Algebra, data.data, data)
80 def algebra_pos(self, Algebra, expr):
81 return expr
83 def algebra_neg(self, Algebra, expr):
84 if Algebra.algebra_options.get('evaluate_addition'):
85 return expr.data
86 return Algebra(NEG, expr)
88 def algebra_add_number(self, Algebra, lhs, rhs, inplace):
89 return self.algebra_add(Algebra, lhs, Algebra(NUMBER, rhs), inplace)
91 def algebra_add(self, Algebra, lhs, rhs, inplace):
92 rhead, rdata = rhs.pair
93 if rhead is ADD:
94 data = [lhs] + rdata
95 elif rhead is TERM_COEFF_DICT or rhead is EXP_COEFF_DICT:
96 data = [lhs] + rhs.to(ADD).data
97 else:
98 data = [lhs, rhs]
99 if Algebra.algebra_options.get('evaluate_addition'):
100 ADD.combine_add_list(Algebra, data)
101 return add_new(Algebra, data)
103 def algebra_mul_number(self, Algebra, lhs, rhs, inplace):
104 if Algebra.algebra_options.get('is_additive_group_commutative'):
105 term, coeff = lhs.head.term_coeff(Algebra, lhs)
106 return term_coeff_new(Algebra, (term, coeff * rhs))
107 else:
108 if Algebra.algebra_options.get('evaluate_addition'):
109 if rhs == 0:
110 return Algebra(NUMBER, 0)
111 term, coeff = lhs.head.term_coeff(Algebra, lhs)
112 return term_coeff_new(Algebra, (term, coeff * rhs))
113 return mul_new(Algebra, [lhs, Algebra(NUMBER, rhs)])
115 def algebra_mul(self, Algebra, lhs, rhs, inplace):
116 ldata = lhs.data
117 if Algebra.algebra_options.get('is_additive_group_commutative'):
118 return super(type(self), self).algebra_mul(Algebra, lhs, rhs, inplace)
119 else:
120 if Algebra.algebra_options.get('evaluate_addition'):
121 rhead, rdata = rhs.pair
122 if rhead is NUMBER:
123 return ldata.head.algebra_mul_number(Algebra, ldata, -rdata, inplace)
124 return super(type(self), self).algebra_mul(Algebra, lhs, rhs, inplace)
125 return mul_new(Algebra, [lhs, rhs])
127 NEG = NegHead()