Coverage for nodimo / relation.py: 100%

52 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-02-26 03:10 +0000

1# ┓• Licensed under the MIT License 

2# ┏┓┏┓┏┫┓┏┳┓┏┓ Copyright (c) 2024 Rodrigo Castro 

3# ┛┗┗┛┗┻┗┛┗┗┗┛ https://nodimo.readthedocs.io 

4 

5""" 

6Relation 

7======== 

8 

9This module contains the class to create a relation between quantities. 

10 

11Classes 

12------- 

13Relation 

14 Creates a relation between quantities. 

15""" 

16 

17from sympy import Symbol, Equality, Function 1abcdef

18from sympy.printing.pretty.stringpict import prettyForm 1abcdef

19 

20from nodimo.quantity import Quantity, Constant 1abcdef

21from nodimo.groups import HomogeneousGroup, IndependentGroup 1abcdef

22from nodimo._internal import _prettify_name 1abcdef

23 

24 

25class Relation(HomogeneousGroup, IndependentGroup): 1abcdef

26 """Creates a relation between quantities. 

27 

28 Parameters 

29 ---------- 

30 *quantities : Quantity 

31 Quantities that constitute the relation. 

32 

33 Attributes 

34 ---------- 

35 quantities : list[Quantity] 

36 Quantities that constitute the relation. 

37 

38 Raises 

39 ------ 

40 ValueError 

41 If there is more than one dependent quantity. 

42 

43 Examples 

44 -------- 

45 

46 >>> from nodimo import Quantity, Relation 

47 >>> F = Quantity('F', M=1, L=1, T=-2, dependent=True) 

48 >>> m = Quantity('m', M=1) 

49 >>> a = Quantity('a', L=1, T=-2) 

50 >>> rel = Relation(F, m, a) 

51 """ 

52 

53 def __init__(self, *quantities: Quantity, name: str = 'f'): 1abcdef

54 super(Relation, self).__init__(*quantities) 1abcdef

55 super(HomogeneousGroup, self).__init__(*self._quantities) 1abcdef

56 self._name: str = name 1abcdef

57 self._set_relation() 1abcdef

58 

59 def _set_relation(self): 1abcdef

60 self._set_dependent_quantities() 1abcdef

61 self._validate_relation() 1abcdef

62 self._set_symbolic_relation() 1abcdef

63 

64 def _validate_relation(self): 1abcdef

65 if len(self._dependent_quantities) > 1: 1abcdef

66 raise ValueError("A relation cannot have more than one dependent quantity") 1abcdef

67 elif len(self._dependent_quantities) == 0: 1abcdef

68 self._dependent_quantities = (Constant('const'),) 1abcdef

69 

70 def _set_symbolic_relation(self): 1abcdef

71 dep_qty = self._dependent_quantities[0] 1abcdef

72 indep_qts_func = Function(self._name)(*self._independent_quantities) 1abcdef

73 self._symbolic = Equality(dep_qty, indep_qts_func, evaluate=False) 1abcdef

74 

75 def _key(self) -> tuple: 1abcdef

76 return ( 1abcdef

77 tuple(self._dependent_quantities), 

78 frozenset(self._independent_quantities), 

79 ) 

80 

81 def _sympy_(self): 1abcdef

82 return self._symbolic 1abcdef

83 

84 def _sympyrepr(self, printer) -> str: 1abcdef

85 class_name = type(self).__name__ 1abcdef

86 quantities = ', '.join( 1abcdef

87 printer._print(qty._unreduced) for qty in self._quantities 

88 ) 

89 name = f", name='{self._name}'" if self._name != 'f' else '' 1abcdef

90 

91 return f'{class_name}({quantities}{name})' 1abcdef

92 

93 def _sympystr(self, printer) -> str: 1abcdef

94 name = self._name 1abcdef

95 dep_qty = printer._print(self._dependent_quantities[0]._unreduced) 1abcdef

96 indep_qts = ', '.join( 1abcdef

97 printer._print(qty._unreduced) for qty in self._independent_quantities 

98 ) 

99 

100 return f'{dep_qty} = {name}({indep_qts})' 1abcdef

101 

102 def _latex(self, printer) -> str: 1abcdef

103 name = printer._print(Symbol(self._name)) 1abcdef

104 dep_qty = printer._print(self._dependent_quantities[0]._unreduced) 1abcdef

105 indep_qts = R',\ '.join( 1abcdef

106 printer._print(qty._unreduced) for qty in self._independent_quantities 

107 ) 

108 

109 return f'{dep_qty} = {name}\\left({indep_qts}\\right)' 1abcdef

110 

111 def _pretty(self, printer) -> prettyForm: 1abcdef

112 name = _prettify_name(self._name) 1abcdef

113 dep_qty = printer._print(self._dependent_quantities[0]._unreduced) 1abcdef

114 indep_qts = prettyForm('') 1abcdef

115 for i, qty in enumerate(self._independent_quantities): 1abcdef

116 sep = ', ' if i > 0 else '' 1abcdef

117 indep_qts = prettyForm( 1abcdef

118 *indep_qts.right(sep, printer._print(qty._unreduced)) 

119 ) 

120 indep_qts = prettyForm(*indep_qts.parens()) 1abcdef

121 

122 return prettyForm(*dep_qty.right(' = ', name, indep_qts)) 1abcdef