m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

512 lines
16 KiB

7 months ago
  1. import warnings
  2. from sympy.core.add import Add
  3. from sympy.core.function import (Function, diff)
  4. from sympy.core.numbers import (Number, Rational)
  5. from sympy.core.singleton import S
  6. from sympy.core.symbol import (Symbol, symbols)
  7. from sympy.functions.elementary.complexes import Abs
  8. from sympy.functions.elementary.exponential import (exp, log)
  9. from sympy.functions.elementary.miscellaneous import sqrt
  10. from sympy.functions.elementary.trigonometric import sin
  11. from sympy.integrals.integrals import integrate
  12. from sympy.physics.units import (amount_of_substance, convert_to, find_unit,
  13. volume, kilometer, joule)
  14. from sympy.physics.units.definitions import (amu, au, centimeter, coulomb,
  15. day, foot, grams, hour, inch, kg, km, m, meter, millimeter,
  16. minute, quart, s, second, speed_of_light, bit,
  17. byte, kibibyte, mebibyte, gibibyte, tebibyte, pebibyte, exbibyte,
  18. kilogram, gravitational_constant)
  19. from sympy.physics.units.definitions.dimension_definitions import (
  20. Dimension, charge, length, time, temperature, pressure,
  21. energy
  22. )
  23. from sympy.physics.units.prefixes import PREFIXES, kilo
  24. from sympy.physics.units.quantities import Quantity
  25. from sympy.physics.units.systems import SI
  26. from sympy.testing.pytest import XFAIL, raises, warns_deprecated_sympy
  27. k = PREFIXES["k"]
  28. def test_str_repr():
  29. assert str(kg) == "kilogram"
  30. def test_eq():
  31. # simple test
  32. assert 10*m == 10*m
  33. assert 10*m != 10*s
  34. def test_convert_to():
  35. q = Quantity("q1")
  36. q.set_global_relative_scale_factor(S(5000), meter)
  37. assert q.convert_to(m) == 5000*m
  38. assert speed_of_light.convert_to(m / s) == 299792458 * m / s
  39. # TODO: eventually support this kind of conversion:
  40. # assert (2*speed_of_light).convert_to(m / s) == 2 * 299792458 * m / s
  41. assert day.convert_to(s) == 86400*s
  42. # Wrong dimension to convert:
  43. assert q.convert_to(s) == q
  44. assert speed_of_light.convert_to(m) == speed_of_light
  45. expr = joule*second
  46. conv = convert_to(expr, joule)
  47. assert conv == joule*second
  48. def test_Quantity_definition():
  49. q = Quantity("s10", abbrev="sabbr")
  50. q.set_global_relative_scale_factor(10, second)
  51. u = Quantity("u", abbrev="dam")
  52. u.set_global_relative_scale_factor(10, meter)
  53. km = Quantity("km")
  54. km.set_global_relative_scale_factor(kilo, meter)
  55. v = Quantity("u")
  56. v.set_global_relative_scale_factor(5*kilo, meter)
  57. assert q.scale_factor == 10
  58. assert q.dimension == time
  59. assert q.abbrev == Symbol("sabbr")
  60. assert u.dimension == length
  61. assert u.scale_factor == 10
  62. assert u.abbrev == Symbol("dam")
  63. assert km.scale_factor == 1000
  64. assert km.func(*km.args) == km
  65. assert km.func(*km.args).args == km.args
  66. assert v.dimension == length
  67. assert v.scale_factor == 5000
  68. with warns_deprecated_sympy():
  69. Quantity('invalid', 'dimension', 1)
  70. with warns_deprecated_sympy():
  71. Quantity('mismatch', dimension=length, scale_factor=kg)
  72. def test_abbrev():
  73. u = Quantity("u")
  74. u.set_global_relative_scale_factor(S.One, meter)
  75. assert u.name == Symbol("u")
  76. assert u.abbrev == Symbol("u")
  77. u = Quantity("u", abbrev="om")
  78. u.set_global_relative_scale_factor(S(2), meter)
  79. assert u.name == Symbol("u")
  80. assert u.abbrev == Symbol("om")
  81. assert u.scale_factor == 2
  82. assert isinstance(u.scale_factor, Number)
  83. u = Quantity("u", abbrev="ikm")
  84. u.set_global_relative_scale_factor(3*kilo, meter)
  85. assert u.abbrev == Symbol("ikm")
  86. assert u.scale_factor == 3000
  87. def test_print():
  88. u = Quantity("unitname", abbrev="dam")
  89. assert repr(u) == "unitname"
  90. assert str(u) == "unitname"
  91. def test_Quantity_eq():
  92. u = Quantity("u", abbrev="dam")
  93. v = Quantity("v1")
  94. assert u != v
  95. v = Quantity("v2", abbrev="ds")
  96. assert u != v
  97. v = Quantity("v3", abbrev="dm")
  98. assert u != v
  99. def test_add_sub():
  100. u = Quantity("u")
  101. v = Quantity("v")
  102. w = Quantity("w")
  103. u.set_global_relative_scale_factor(S(10), meter)
  104. v.set_global_relative_scale_factor(S(5), meter)
  105. w.set_global_relative_scale_factor(S(2), second)
  106. assert isinstance(u + v, Add)
  107. assert (u + v.convert_to(u)) == (1 + S.Half)*u
  108. # TODO: eventually add this:
  109. # assert (u + v).convert_to(u) == (1 + S.Half)*u
  110. assert isinstance(u - v, Add)
  111. assert (u - v.convert_to(u)) == S.Half*u
  112. # TODO: eventually add this:
  113. # assert (u - v).convert_to(u) == S.Half*u
  114. def test_quantity_abs():
  115. v_w1 = Quantity('v_w1')
  116. v_w2 = Quantity('v_w2')
  117. v_w3 = Quantity('v_w3')
  118. v_w1.set_global_relative_scale_factor(1, meter/second)
  119. v_w2.set_global_relative_scale_factor(1, meter/second)
  120. v_w3.set_global_relative_scale_factor(1, meter/second)
  121. expr = v_w3 - Abs(v_w1 - v_w2)
  122. assert SI.get_dimensional_expr(v_w1) == (length/time).name
  123. Dq = Dimension(SI.get_dimensional_expr(expr))
  124. with warns_deprecated_sympy():
  125. Dq1 = Dimension(Quantity.get_dimensional_expr(expr))
  126. assert Dq == Dq1
  127. assert SI.get_dimension_system().get_dimensional_dependencies(Dq) == {
  128. 'length': 1,
  129. 'time': -1,
  130. }
  131. assert meter == sqrt(meter**2)
  132. def test_check_unit_consistency():
  133. u = Quantity("u")
  134. v = Quantity("v")
  135. w = Quantity("w")
  136. u.set_global_relative_scale_factor(S(10), meter)
  137. v.set_global_relative_scale_factor(S(5), meter)
  138. w.set_global_relative_scale_factor(S(2), second)
  139. def check_unit_consistency(expr):
  140. SI._collect_factor_and_dimension(expr)
  141. raises(ValueError, lambda: check_unit_consistency(u + w))
  142. raises(ValueError, lambda: check_unit_consistency(u - w))
  143. raises(ValueError, lambda: check_unit_consistency(u + 1))
  144. raises(ValueError, lambda: check_unit_consistency(u - 1))
  145. raises(ValueError, lambda: check_unit_consistency(1 - exp(u / w)))
  146. def test_mul_div():
  147. u = Quantity("u")
  148. v = Quantity("v")
  149. t = Quantity("t")
  150. ut = Quantity("ut")
  151. v2 = Quantity("v")
  152. u.set_global_relative_scale_factor(S(10), meter)
  153. v.set_global_relative_scale_factor(S(5), meter)
  154. t.set_global_relative_scale_factor(S(2), second)
  155. ut.set_global_relative_scale_factor(S(20), meter*second)
  156. v2.set_global_relative_scale_factor(S(5), meter/second)
  157. assert 1 / u == u**(-1)
  158. assert u / 1 == u
  159. v1 = u / t
  160. v2 = v
  161. # Pow only supports structural equality:
  162. assert v1 != v2
  163. assert v1 == v2.convert_to(v1)
  164. # TODO: decide whether to allow such expression in the future
  165. # (requires somehow manipulating the core).
  166. # assert u / Quantity('l2', dimension=length, scale_factor=2) == 5
  167. assert u * 1 == u
  168. ut1 = u * t
  169. ut2 = ut
  170. # Mul only supports structural equality:
  171. assert ut1 != ut2
  172. assert ut1 == ut2.convert_to(ut1)
  173. # Mul only supports structural equality:
  174. lp1 = Quantity("lp1")
  175. lp1.set_global_relative_scale_factor(S(2), 1/meter)
  176. assert u * lp1 != 20
  177. assert u**0 == 1
  178. assert u**1 == u
  179. # TODO: Pow only support structural equality:
  180. u2 = Quantity("u2")
  181. u3 = Quantity("u3")
  182. u2.set_global_relative_scale_factor(S(100), meter**2)
  183. u3.set_global_relative_scale_factor(Rational(1, 10), 1/meter)
  184. assert u ** 2 != u2
  185. assert u ** -1 != u3
  186. assert u ** 2 == u2.convert_to(u)
  187. assert u ** -1 == u3.convert_to(u)
  188. def test_units():
  189. assert convert_to((5*m/s * day) / km, 1) == 432
  190. assert convert_to(foot / meter, meter) == Rational(3048, 10000)
  191. # amu is a pure mass so mass/mass gives a number, not an amount (mol)
  192. # TODO: need better simplification routine:
  193. assert str(convert_to(grams/amu, grams).n(2)) == '6.0e+23'
  194. # Light from the sun needs about 8.3 minutes to reach earth
  195. t = (1*au / speed_of_light) / minute
  196. # TODO: need a better way to simplify expressions containing units:
  197. t = convert_to(convert_to(t, meter / minute), meter)
  198. assert t.simplify() == Rational(49865956897, 5995849160)
  199. # TODO: fix this, it should give `m` without `Abs`
  200. assert sqrt(m**2) == m
  201. assert (sqrt(m))**2 == m
  202. t = Symbol('t')
  203. assert integrate(t*m/s, (t, 1*s, 5*s)) == 12*m*s
  204. assert (t * m/s).integrate((t, 1*s, 5*s)) == 12*m*s
  205. def test_issue_quart():
  206. assert convert_to(4 * quart / inch ** 3, meter) == 231
  207. assert convert_to(4 * quart / inch ** 3, millimeter) == 231
  208. def test_issue_5565():
  209. assert (m < s).is_Relational
  210. def test_find_unit():
  211. assert find_unit('coulomb') == ['coulomb', 'coulombs', 'coulomb_constant']
  212. assert find_unit(coulomb) == ['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
  213. assert find_unit(charge) == ['C', 'coulomb', 'coulombs', 'planck_charge', 'elementary_charge']
  214. assert find_unit(inch) == [
  215. 'm', 'au', 'cm', 'dm', 'ft', 'km', 'ly', 'mi', 'mm', 'nm', 'pm', 'um',
  216. 'yd', 'nmi', 'feet', 'foot', 'inch', 'mile', 'yard', 'meter', 'miles',
  217. 'yards', 'inches', 'meters', 'micron', 'microns', 'decimeter',
  218. 'kilometer', 'lightyear', 'nanometer', 'picometer', 'centimeter',
  219. 'decimeters', 'kilometers', 'lightyears', 'micrometer', 'millimeter',
  220. 'nanometers', 'picometers', 'centimeters', 'micrometers',
  221. 'millimeters', 'nautical_mile', 'planck_length', 'nautical_miles', 'astronomical_unit',
  222. 'astronomical_units']
  223. assert find_unit(inch**-1) == ['D', 'dioptre', 'optical_power']
  224. assert find_unit(length**-1) == ['D', 'dioptre', 'optical_power']
  225. assert find_unit(inch ** 3) == [
  226. 'L', 'l', 'cL', 'cl', 'dL', 'dl', 'mL', 'ml', 'liter', 'quart', 'liters', 'quarts',
  227. 'deciliter', 'centiliter', 'deciliters', 'milliliter',
  228. 'centiliters', 'milliliters', 'planck_volume']
  229. assert find_unit('voltage') == ['V', 'v', 'volt', 'volts', 'planck_voltage']
  230. def test_Quantity_derivative():
  231. x = symbols("x")
  232. assert diff(x*meter, x) == meter
  233. assert diff(x**3*meter**2, x) == 3*x**2*meter**2
  234. assert diff(meter, meter) == 1
  235. assert diff(meter**2, meter) == 2*meter
  236. def test_quantity_postprocessing():
  237. q1 = Quantity('q1')
  238. q2 = Quantity('q2')
  239. SI.set_quantity_dimension(q1, length*pressure**2*temperature/time)
  240. SI.set_quantity_dimension(q2, energy*pressure*temperature/(length**2*time))
  241. assert q1 + q2
  242. q = q1 + q2
  243. Dq = Dimension(SI.get_dimensional_expr(q))
  244. assert SI.get_dimension_system().get_dimensional_dependencies(Dq) == {
  245. 'length': -1,
  246. 'mass': 2,
  247. 'temperature': 1,
  248. 'time': -5,
  249. }
  250. def test_factor_and_dimension():
  251. assert (3000, Dimension(1)) == SI._collect_factor_and_dimension(3000)
  252. assert (1001, length) == SI._collect_factor_and_dimension(meter + km)
  253. assert (2, length/time) == SI._collect_factor_and_dimension(
  254. meter/second + 36*km/(10*hour))
  255. x, y = symbols('x y')
  256. assert (x + y/100, length) == SI._collect_factor_and_dimension(
  257. x*m + y*centimeter)
  258. cH = Quantity('cH')
  259. SI.set_quantity_dimension(cH, amount_of_substance/volume)
  260. pH = -log(cH)
  261. assert (1, volume/amount_of_substance) == SI._collect_factor_and_dimension(
  262. exp(pH))
  263. v_w1 = Quantity('v_w1')
  264. v_w2 = Quantity('v_w2')
  265. v_w1.set_global_relative_scale_factor(Rational(3, 2), meter/second)
  266. v_w2.set_global_relative_scale_factor(2, meter/second)
  267. expr = Abs(v_w1/2 - v_w2)
  268. assert (Rational(5, 4), length/time) == \
  269. SI._collect_factor_and_dimension(expr)
  270. expr = Rational(5, 2)*second/meter*v_w1 - 3000
  271. assert (-(2996 + Rational(1, 4)), Dimension(1)) == \
  272. SI._collect_factor_and_dimension(expr)
  273. expr = v_w1**(v_w2/v_w1)
  274. assert ((Rational(3, 2))**Rational(4, 3), (length/time)**Rational(4, 3)) == \
  275. SI._collect_factor_and_dimension(expr)
  276. with warns_deprecated_sympy():
  277. assert (3000, Dimension(1)) == Quantity._collect_factor_and_dimension(3000)
  278. @XFAIL
  279. def test_factor_and_dimension_with_Abs():
  280. with warns_deprecated_sympy():
  281. v_w1 = Quantity('v_w1', length/time, Rational(3, 2)*meter/second)
  282. v_w1.set_global_relative_scale_factor(Rational(3, 2), meter/second)
  283. expr = v_w1 - Abs(v_w1)
  284. with warns_deprecated_sympy():
  285. assert (0, length/time) == Quantity._collect_factor_and_dimension(expr)
  286. def test_dimensional_expr_of_derivative():
  287. l = Quantity('l')
  288. t = Quantity('t')
  289. t1 = Quantity('t1')
  290. l.set_global_relative_scale_factor(36, km)
  291. t.set_global_relative_scale_factor(1, hour)
  292. t1.set_global_relative_scale_factor(1, second)
  293. x = Symbol('x')
  294. y = Symbol('y')
  295. f = Function('f')
  296. dfdx = f(x, y).diff(x, y)
  297. dl_dt = dfdx.subs({f(x, y): l, x: t, y: t1})
  298. assert SI.get_dimensional_expr(dl_dt) ==\
  299. SI.get_dimensional_expr(l / t / t1) ==\
  300. Symbol("length")/Symbol("time")**2
  301. assert SI._collect_factor_and_dimension(dl_dt) ==\
  302. SI._collect_factor_and_dimension(l / t / t1) ==\
  303. (10, length/time**2)
  304. def test_get_dimensional_expr_with_function():
  305. v_w1 = Quantity('v_w1')
  306. v_w2 = Quantity('v_w2')
  307. v_w1.set_global_relative_scale_factor(1, meter/second)
  308. v_w2.set_global_relative_scale_factor(1, meter/second)
  309. assert SI.get_dimensional_expr(sin(v_w1)) == \
  310. sin(SI.get_dimensional_expr(v_w1))
  311. assert SI.get_dimensional_expr(sin(v_w1/v_w2)) == 1
  312. def test_binary_information():
  313. assert convert_to(kibibyte, byte) == 1024*byte
  314. assert convert_to(mebibyte, byte) == 1024**2*byte
  315. assert convert_to(gibibyte, byte) == 1024**3*byte
  316. assert convert_to(tebibyte, byte) == 1024**4*byte
  317. assert convert_to(pebibyte, byte) == 1024**5*byte
  318. assert convert_to(exbibyte, byte) == 1024**6*byte
  319. assert kibibyte.convert_to(bit) == 8*1024*bit
  320. assert byte.convert_to(bit) == 8*bit
  321. a = 10*kibibyte*hour
  322. assert convert_to(a, byte) == 10240*byte*hour
  323. assert convert_to(a, minute) == 600*kibibyte*minute
  324. assert convert_to(a, [byte, minute]) == 614400*byte*minute
  325. def test_conversion_with_2_nonstandard_dimensions():
  326. good_grade = Quantity("good_grade")
  327. kilo_good_grade = Quantity("kilo_good_grade")
  328. centi_good_grade = Quantity("centi_good_grade")
  329. kilo_good_grade.set_global_relative_scale_factor(1000, good_grade)
  330. centi_good_grade.set_global_relative_scale_factor(S.One/10**5, kilo_good_grade)
  331. charity_points = Quantity("charity_points")
  332. milli_charity_points = Quantity("milli_charity_points")
  333. missions = Quantity("missions")
  334. milli_charity_points.set_global_relative_scale_factor(S.One/1000, charity_points)
  335. missions.set_global_relative_scale_factor(251, charity_points)
  336. assert convert_to(
  337. kilo_good_grade*milli_charity_points*millimeter,
  338. [centi_good_grade, missions, centimeter]
  339. ) == S.One * 10**5 / (251*1000) / 10 * centi_good_grade*missions*centimeter
  340. def test_eval_subs():
  341. energy, mass, force = symbols('energy mass force')
  342. expr1 = energy/mass
  343. units = {energy: kilogram*meter**2/second**2, mass: kilogram}
  344. assert expr1.subs(units) == meter**2/second**2
  345. expr2 = force/mass
  346. units = {force:gravitational_constant*kilogram**2/meter**2, mass:kilogram}
  347. assert expr2.subs(units) == gravitational_constant*kilogram/meter**2
  348. def test_issue_14932():
  349. assert (log(inch) - log(2)).simplify() == log(inch/2)
  350. assert (log(inch) - log(foot)).simplify() == -log(12)
  351. p = symbols('p', positive=True)
  352. assert (log(inch) - log(p)).simplify() == log(inch/p)
  353. def test_issue_14547():
  354. # the root issue is that an argument with dimensions should
  355. # not raise an error when the `arg - 1` calculation is
  356. # performed in the assumptions system
  357. from sympy.physics.units import foot, inch
  358. from sympy.core.relational import Eq
  359. assert log(foot).is_zero is None
  360. assert log(foot).is_positive is None
  361. assert log(foot).is_nonnegative is None
  362. assert log(foot).is_negative is None
  363. assert log(foot).is_algebraic is None
  364. assert log(foot).is_rational is None
  365. # doesn't raise error
  366. assert Eq(log(foot), log(inch)) is not None # might be False or unevaluated
  367. x = Symbol('x')
  368. e = foot + x
  369. assert e.is_Add and set(e.args) == {foot, x}
  370. e = foot + 1
  371. assert e.is_Add and set(e.args) == {foot, 1}
  372. def test_deprecated_quantity_methods():
  373. step = Quantity("step")
  374. with warns_deprecated_sympy():
  375. step.set_dimension(length)
  376. step.set_scale_factor(2*meter)
  377. assert convert_to(step, centimeter) == 200*centimeter
  378. assert convert_to(1000*step/second, kilometer/second) == 2*kilometer/second
  379. def test_issue_22164():
  380. warnings.simplefilter("error")
  381. dm = Quantity("dm")
  382. SI.set_quantity_dimension(dm, length)
  383. SI.set_quantity_scale_factor(dm, 1)
  384. bad_exp = Quantity("bad_exp")
  385. SI.set_quantity_dimension(bad_exp, length)
  386. SI.set_quantity_scale_factor(bad_exp, 1)
  387. expr = dm ** bad_exp
  388. # deprecation warning is not expected here
  389. SI._collect_factor_and_dimension(expr)