Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"The shared non-mathematical backbone of all Nomials" 

2from .data import NomialData 

3from ..small_classes import Numbers, FixedScalar 

4from ..repr_conventions import MUL, UNICODE_EXPONENTS 

5 

6 

7def nomial_latex_helper(c, pos_vars, neg_vars): 

8 """Combines (varlatex, exponent) tuples, 

9 separated by positive vs negative exponent, into a single latex string.""" 

10 pvarstrs = ['%s^{%.2g}' % (varl, x) if "%.2g" % x != "1" else varl 

11 for (varl, x) in pos_vars] 

12 nvarstrs = ['%s^{%.2g}' % (varl, -x) if "%.2g" % -x != "1" else varl 

13 for (varl, x) in neg_vars] 

14 pvarstr = " ".join(sorted(pvarstrs)) 

15 nvarstr = " ".join(sorted(nvarstrs)) 

16 cstr = "%.2g" % c 

17 if pos_vars and cstr in ["1", "-1"]: 

18 cstr = cstr[:-1] 

19 else: 

20 cstr = "%.4g" % c 

21 if "e" in cstr: # use exponential notation 

22 idx = cstr.index("e") 

23 cstr = "%s \\times 10^{%i}" % (cstr[:idx], int(cstr[idx+1:])) 

24 

25 if pos_vars and neg_vars: 

26 return "%s\\frac{%s}{%s}" % (cstr, pvarstr, nvarstr) 

27 if neg_vars and not pos_vars: 

28 return "\\frac{%s}{%s}" % (cstr, nvarstr) 

29 if pos_vars: 

30 return "%s%s" % (cstr, pvarstr) 

31 return "%s" % cstr 

32 

33 

34class Nomial(NomialData): 

35 "Shared non-mathematical properties of all nomials" 

36 sub = None 

37 

38 def str_without(self, excluded=()): 

39 "String representation, excluding fields ('units', varkey attributes)" 

40 units = "" if "units" in excluded else self.unitstr(" [%s]") 

41 if hasattr(self, "key"): 

42 return self.key.str_without(excluded) + units # pylint: disable=no-member 

43 if self.ast: 

44 return self.parse_ast(excluded) + units 

45 mstrs = [] 

46 for exp, c in self.hmap.items(): 

47 varstrs = [] 

48 for (var, x) in exp.items(): 

49 if not x: 

50 continue 

51 varstr = var.str_without(excluded) 

52 if UNICODE_EXPONENTS and int(x) == x and 2 <= x <= 9: 

53 x = int(x) 

54 if x in (2, 3): 

55 varstr += chr(176+x) 

56 elif x in (4, 5, 6, 7, 8, 9): 

57 varstr += chr(8304+x) 

58 elif x != 1: 

59 varstr += "^%.2g" % x 

60 varstrs.append(varstr) 

61 varstrs.sort() 

62 cstr = "%.3g" % c 

63 if cstr == "-1" and varstrs: 

64 mstrs.append("-" + "·".join(varstrs)) 

65 else: 

66 cstr = [cstr] if (cstr != "1" or not varstrs) else [] 

67 mstrs.append(MUL.join(cstr + varstrs)) 

68 return " + ".join(sorted(mstrs)) + units 

69 

70 def latex(self, excluded=()): # TODO: add ast parsing here 

71 "Latex representation, parsing `excluded` just as .str_without does" 

72 mstrs = [] 

73 for exp, c in self.hmap.items(): 

74 pos_vars, neg_vars = [], [] 

75 for var, x in exp.items(): 

76 if x > 0: 

77 pos_vars.append((var.latex(excluded), x)) 

78 elif x < 0: 

79 neg_vars.append((var.latex(excluded), x)) 

80 mstrs.append(nomial_latex_helper(c, pos_vars, neg_vars)) 

81 

82 if "units" in excluded: 

83 return " + ".join(sorted(mstrs)) 

84 units = self.unitstr(r"\mathrm{~\left[ %s \right]}", ":L~") 

85 units_tf = units.replace("frac", "tfrac").replace(r"\cdot", r"\cdot ") 

86 return " + ".join(sorted(mstrs)) + units_tf 

87 

88 @property 

89 def value(self): 

90 """Self, with values substituted for variables that have values 

91 

92 Returns 

93 ------- 

94 float, if no symbolic variables remain after substitution 

95 (Monomial, Posynomial, or Nomial), otherwise. 

96 """ 

97 if isinstance(self, FixedScalar): 

98 return self.cs[0] 

99 p = self.sub({k: k.value for k in self.vks if "value" in k.descr}) # pylint: disable=not-callable 

100 return p.cs[0] if isinstance(p, FixedScalar) else p 

101 

102 def __eq__(self, other): 

103 "True if self and other are algebraically identical." 

104 if isinstance(other, Numbers): 

105 return isinstance(self, FixedScalar) and self.value == other 

106 return super().__eq__(other) 

107 

108 __hash__ = NomialData.__hash__ 

109 # pylint: disable=multiple-statements 

110 def __ne__(self, other): return not Nomial.__eq__(self, other) 

111 def __radd__(self, other): return self.__add__(other, rev=True) # pylint: disable=no-member 

112 def __rmul__(self, other): return self.__mul__(other, rev=True) # pylint: disable=no-member 

113 

114 def prod(self): 

115 "Return self for compatibility with NomialArray" 

116 return self 

117 

118 sum = prod