test_tensorflow.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. import random
  2. from sympy.core.function import Derivative
  3. from sympy.core.symbol import symbols
  4. from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayAdd, \
  5. PermuteDims, ArrayDiagonal
  6. from sympy.core.relational import Eq, Ne, Ge, Gt, Le, Lt
  7. from sympy.external import import_module
  8. from sympy.functions import \
  9. Abs, ceiling, exp, floor, sign, sin, asin, sqrt, cos, \
  10. acos, tan, atan, atan2, cosh, acosh, sinh, asinh, tanh, atanh, \
  11. re, im, arg, erf, loggamma, log
  12. from sympy.matrices import Matrix, MatrixBase, eye, randMatrix
  13. from sympy.matrices.expressions import \
  14. Determinant, HadamardProduct, Inverse, MatrixSymbol, Trace
  15. from sympy.printing.tensorflow import tensorflow_code
  16. from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array
  17. from sympy.utilities.lambdify import lambdify
  18. from sympy.testing.pytest import skip
  19. from sympy.testing.pytest import XFAIL
  20. tf = tensorflow = import_module("tensorflow")
  21. if tensorflow:
  22. # Hide Tensorflow warnings
  23. import os
  24. os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
  25. M = MatrixSymbol("M", 3, 3)
  26. N = MatrixSymbol("N", 3, 3)
  27. P = MatrixSymbol("P", 3, 3)
  28. Q = MatrixSymbol("Q", 3, 3)
  29. x, y, z, t = symbols("x y z t")
  30. if tf is not None:
  31. llo = [list(range(i, i+3)) for i in range(0, 9, 3)]
  32. m3x3 = tf.constant(llo)
  33. m3x3sympy = Matrix(llo)
  34. def _compare_tensorflow_matrix(variables, expr, use_float=False):
  35. f = lambdify(variables, expr, 'tensorflow')
  36. if not use_float:
  37. random_matrices = [randMatrix(v.rows, v.cols) for v in variables]
  38. else:
  39. random_matrices = [randMatrix(v.rows, v.cols)/100. for v in variables]
  40. graph = tf.Graph()
  41. r = None
  42. with graph.as_default():
  43. random_variables = [eval(tensorflow_code(i)) for i in random_matrices]
  44. session = tf.compat.v1.Session(graph=graph)
  45. r = session.run(f(*random_variables))
  46. e = expr.subs({k: v for k, v in zip(variables, random_matrices)})
  47. e = e.doit()
  48. if e.is_Matrix:
  49. if not isinstance(e, MatrixBase):
  50. e = e.as_explicit()
  51. e = e.tolist()
  52. if not use_float:
  53. assert (r == e).all()
  54. else:
  55. r = [i for row in r for i in row]
  56. e = [i for row in e for i in row]
  57. assert all(
  58. abs(a-b) < 10**-(4-int(log(abs(a), 10))) for a, b in zip(r, e))
  59. # Creating a custom inverse test.
  60. # See https://github.com/sympy/sympy/issues/18469
  61. def _compare_tensorflow_matrix_inverse(variables, expr, use_float=False):
  62. f = lambdify(variables, expr, 'tensorflow')
  63. if not use_float:
  64. random_matrices = [eye(v.rows, v.cols)*4 for v in variables]
  65. else:
  66. random_matrices = [eye(v.rows, v.cols)*3.14 for v in variables]
  67. graph = tf.Graph()
  68. r = None
  69. with graph.as_default():
  70. random_variables = [eval(tensorflow_code(i)) for i in random_matrices]
  71. session = tf.compat.v1.Session(graph=graph)
  72. r = session.run(f(*random_variables))
  73. e = expr.subs({k: v for k, v in zip(variables, random_matrices)})
  74. e = e.doit()
  75. if e.is_Matrix:
  76. if not isinstance(e, MatrixBase):
  77. e = e.as_explicit()
  78. e = e.tolist()
  79. if not use_float:
  80. assert (r == e).all()
  81. else:
  82. r = [i for row in r for i in row]
  83. e = [i for row in e for i in row]
  84. assert all(
  85. abs(a-b) < 10**-(4-int(log(abs(a), 10))) for a, b in zip(r, e))
  86. def _compare_tensorflow_matrix_scalar(variables, expr):
  87. f = lambdify(variables, expr, 'tensorflow')
  88. random_matrices = [
  89. randMatrix(v.rows, v.cols).evalf() / 100 for v in variables]
  90. graph = tf.Graph()
  91. r = None
  92. with graph.as_default():
  93. random_variables = [eval(tensorflow_code(i)) for i in random_matrices]
  94. session = tf.compat.v1.Session(graph=graph)
  95. r = session.run(f(*random_variables))
  96. e = expr.subs({k: v for k, v in zip(variables, random_matrices)})
  97. e = e.doit()
  98. assert abs(r-e) < 10**-6
  99. def _compare_tensorflow_scalar(
  100. variables, expr, rng=lambda: random.randint(0, 10)):
  101. f = lambdify(variables, expr, 'tensorflow')
  102. rvs = [rng() for v in variables]
  103. graph = tf.Graph()
  104. r = None
  105. with graph.as_default():
  106. tf_rvs = [eval(tensorflow_code(i)) for i in rvs]
  107. session = tf.compat.v1.Session(graph=graph)
  108. r = session.run(f(*tf_rvs))
  109. e = expr.subs({k: v for k, v in zip(variables, rvs)}).evalf().doit()
  110. assert abs(r-e) < 10**-6
  111. def _compare_tensorflow_relational(
  112. variables, expr, rng=lambda: random.randint(0, 10)):
  113. f = lambdify(variables, expr, 'tensorflow')
  114. rvs = [rng() for v in variables]
  115. graph = tf.Graph()
  116. r = None
  117. with graph.as_default():
  118. tf_rvs = [eval(tensorflow_code(i)) for i in rvs]
  119. session = tf.compat.v1.Session(graph=graph)
  120. r = session.run(f(*tf_rvs))
  121. e = expr.subs({k: v for k, v in zip(variables, rvs)}).doit()
  122. assert r == e
  123. def test_tensorflow_printing():
  124. assert tensorflow_code(eye(3)) == \
  125. "tensorflow.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]])"
  126. expr = Matrix([[x, sin(y)], [exp(z), -t]])
  127. assert tensorflow_code(expr) == \
  128. "tensorflow.Variable(" \
  129. "[[x, tensorflow.math.sin(y)]," \
  130. " [tensorflow.math.exp(z), -t]])"
  131. # This (random) test is XFAIL because it fails occasionally
  132. # See https://github.com/sympy/sympy/issues/18469
  133. @XFAIL
  134. def test_tensorflow_math():
  135. if not tf:
  136. skip("TensorFlow not installed")
  137. expr = Abs(x)
  138. assert tensorflow_code(expr) == "tensorflow.math.abs(x)"
  139. _compare_tensorflow_scalar((x,), expr)
  140. expr = sign(x)
  141. assert tensorflow_code(expr) == "tensorflow.math.sign(x)"
  142. _compare_tensorflow_scalar((x,), expr)
  143. expr = ceiling(x)
  144. assert tensorflow_code(expr) == "tensorflow.math.ceil(x)"
  145. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  146. expr = floor(x)
  147. assert tensorflow_code(expr) == "tensorflow.math.floor(x)"
  148. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  149. expr = exp(x)
  150. assert tensorflow_code(expr) == "tensorflow.math.exp(x)"
  151. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  152. expr = sqrt(x)
  153. assert tensorflow_code(expr) == "tensorflow.math.sqrt(x)"
  154. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  155. expr = x ** 4
  156. assert tensorflow_code(expr) == "tensorflow.math.pow(x, 4)"
  157. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  158. expr = cos(x)
  159. assert tensorflow_code(expr) == "tensorflow.math.cos(x)"
  160. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  161. expr = acos(x)
  162. assert tensorflow_code(expr) == "tensorflow.math.acos(x)"
  163. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(0, 0.95))
  164. expr = sin(x)
  165. assert tensorflow_code(expr) == "tensorflow.math.sin(x)"
  166. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  167. expr = asin(x)
  168. assert tensorflow_code(expr) == "tensorflow.math.asin(x)"
  169. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  170. expr = tan(x)
  171. assert tensorflow_code(expr) == "tensorflow.math.tan(x)"
  172. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  173. expr = atan(x)
  174. assert tensorflow_code(expr) == "tensorflow.math.atan(x)"
  175. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  176. expr = atan2(y, x)
  177. assert tensorflow_code(expr) == "tensorflow.math.atan2(y, x)"
  178. _compare_tensorflow_scalar((y, x), expr, rng=lambda: random.random())
  179. expr = cosh(x)
  180. assert tensorflow_code(expr) == "tensorflow.math.cosh(x)"
  181. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random())
  182. expr = acosh(x)
  183. assert tensorflow_code(expr) == "tensorflow.math.acosh(x)"
  184. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2))
  185. expr = sinh(x)
  186. assert tensorflow_code(expr) == "tensorflow.math.sinh(x)"
  187. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2))
  188. expr = asinh(x)
  189. assert tensorflow_code(expr) == "tensorflow.math.asinh(x)"
  190. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2))
  191. expr = tanh(x)
  192. assert tensorflow_code(expr) == "tensorflow.math.tanh(x)"
  193. _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2))
  194. expr = atanh(x)
  195. assert tensorflow_code(expr) == "tensorflow.math.atanh(x)"
  196. _compare_tensorflow_scalar(
  197. (x,), expr, rng=lambda: random.uniform(-.5, .5))
  198. expr = erf(x)
  199. assert tensorflow_code(expr) == "tensorflow.math.erf(x)"
  200. _compare_tensorflow_scalar(
  201. (x,), expr, rng=lambda: random.random())
  202. expr = loggamma(x)
  203. assert tensorflow_code(expr) == "tensorflow.math.lgamma(x)"
  204. _compare_tensorflow_scalar(
  205. (x,), expr, rng=lambda: random.random())
  206. def test_tensorflow_complexes():
  207. assert tensorflow_code(re(x)) == "tensorflow.math.real(x)"
  208. assert tensorflow_code(im(x)) == "tensorflow.math.imag(x)"
  209. assert tensorflow_code(arg(x)) == "tensorflow.math.angle(x)"
  210. def test_tensorflow_relational():
  211. if not tf:
  212. skip("TensorFlow not installed")
  213. expr = Eq(x, y)
  214. assert tensorflow_code(expr) == "tensorflow.math.equal(x, y)"
  215. _compare_tensorflow_relational((x, y), expr)
  216. expr = Ne(x, y)
  217. assert tensorflow_code(expr) == "tensorflow.math.not_equal(x, y)"
  218. _compare_tensorflow_relational((x, y), expr)
  219. expr = Ge(x, y)
  220. assert tensorflow_code(expr) == "tensorflow.math.greater_equal(x, y)"
  221. _compare_tensorflow_relational((x, y), expr)
  222. expr = Gt(x, y)
  223. assert tensorflow_code(expr) == "tensorflow.math.greater(x, y)"
  224. _compare_tensorflow_relational((x, y), expr)
  225. expr = Le(x, y)
  226. assert tensorflow_code(expr) == "tensorflow.math.less_equal(x, y)"
  227. _compare_tensorflow_relational((x, y), expr)
  228. expr = Lt(x, y)
  229. assert tensorflow_code(expr) == "tensorflow.math.less(x, y)"
  230. _compare_tensorflow_relational((x, y), expr)
  231. # This (random) test is XFAIL because it fails occasionally
  232. # See https://github.com/sympy/sympy/issues/18469
  233. @XFAIL
  234. def test_tensorflow_matrices():
  235. if not tf:
  236. skip("TensorFlow not installed")
  237. expr = M
  238. assert tensorflow_code(expr) == "M"
  239. _compare_tensorflow_matrix((M,), expr)
  240. expr = M + N
  241. assert tensorflow_code(expr) == "tensorflow.math.add(M, N)"
  242. _compare_tensorflow_matrix((M, N), expr)
  243. expr = M * N
  244. assert tensorflow_code(expr) == "tensorflow.linalg.matmul(M, N)"
  245. _compare_tensorflow_matrix((M, N), expr)
  246. expr = HadamardProduct(M, N)
  247. assert tensorflow_code(expr) == "tensorflow.math.multiply(M, N)"
  248. _compare_tensorflow_matrix((M, N), expr)
  249. expr = M*N*P*Q
  250. assert tensorflow_code(expr) == \
  251. "tensorflow.linalg.matmul(" \
  252. "tensorflow.linalg.matmul(" \
  253. "tensorflow.linalg.matmul(M, N), P), Q)"
  254. _compare_tensorflow_matrix((M, N, P, Q), expr)
  255. expr = M**3
  256. assert tensorflow_code(expr) == \
  257. "tensorflow.linalg.matmul(tensorflow.linalg.matmul(M, M), M)"
  258. _compare_tensorflow_matrix((M,), expr)
  259. expr = Trace(M)
  260. assert tensorflow_code(expr) == "tensorflow.linalg.trace(M)"
  261. _compare_tensorflow_matrix((M,), expr)
  262. expr = Determinant(M)
  263. assert tensorflow_code(expr) == "tensorflow.linalg.det(M)"
  264. _compare_tensorflow_matrix_scalar((M,), expr)
  265. expr = Inverse(M)
  266. assert tensorflow_code(expr) == "tensorflow.linalg.inv(M)"
  267. _compare_tensorflow_matrix_inverse((M,), expr, use_float=True)
  268. expr = M.T
  269. assert tensorflow_code(expr, tensorflow_version='1.14') == \
  270. "tensorflow.linalg.matrix_transpose(M)"
  271. assert tensorflow_code(expr, tensorflow_version='1.13') == \
  272. "tensorflow.matrix_transpose(M)"
  273. _compare_tensorflow_matrix((M,), expr)
  274. def test_codegen_einsum():
  275. if not tf:
  276. skip("TensorFlow not installed")
  277. graph = tf.Graph()
  278. with graph.as_default():
  279. session = tf.compat.v1.Session(graph=graph)
  280. M = MatrixSymbol("M", 2, 2)
  281. N = MatrixSymbol("N", 2, 2)
  282. cg = convert_matrix_to_array(M * N)
  283. f = lambdify((M, N), cg, 'tensorflow')
  284. ma = tf.constant([[1, 2], [3, 4]])
  285. mb = tf.constant([[1,-2], [-1, 3]])
  286. y = session.run(f(ma, mb))
  287. c = session.run(tf.matmul(ma, mb))
  288. assert (y == c).all()
  289. def test_codegen_extra():
  290. if not tf:
  291. skip("TensorFlow not installed")
  292. graph = tf.Graph()
  293. with graph.as_default():
  294. session = tf.compat.v1.Session()
  295. M = MatrixSymbol("M", 2, 2)
  296. N = MatrixSymbol("N", 2, 2)
  297. P = MatrixSymbol("P", 2, 2)
  298. Q = MatrixSymbol("Q", 2, 2)
  299. ma = tf.constant([[1, 2], [3, 4]])
  300. mb = tf.constant([[1,-2], [-1, 3]])
  301. mc = tf.constant([[2, 0], [1, 2]])
  302. md = tf.constant([[1,-1], [4, 7]])
  303. cg = ArrayTensorProduct(M, N)
  304. assert tensorflow_code(cg) == \
  305. 'tensorflow.linalg.einsum("ab,cd", M, N)'
  306. f = lambdify((M, N), cg, 'tensorflow')
  307. y = session.run(f(ma, mb))
  308. c = session.run(tf.einsum("ij,kl", ma, mb))
  309. assert (y == c).all()
  310. cg = ArrayAdd(M, N)
  311. assert tensorflow_code(cg) == 'tensorflow.math.add(M, N)'
  312. f = lambdify((M, N), cg, 'tensorflow')
  313. y = session.run(f(ma, mb))
  314. c = session.run(ma + mb)
  315. assert (y == c).all()
  316. cg = ArrayAdd(M, N, P)
  317. assert tensorflow_code(cg) == \
  318. 'tensorflow.math.add(tensorflow.math.add(M, N), P)'
  319. f = lambdify((M, N, P), cg, 'tensorflow')
  320. y = session.run(f(ma, mb, mc))
  321. c = session.run(ma + mb + mc)
  322. assert (y == c).all()
  323. cg = ArrayAdd(M, N, P, Q)
  324. assert tensorflow_code(cg) == \
  325. 'tensorflow.math.add(' \
  326. 'tensorflow.math.add(tensorflow.math.add(M, N), P), Q)'
  327. f = lambdify((M, N, P, Q), cg, 'tensorflow')
  328. y = session.run(f(ma, mb, mc, md))
  329. c = session.run(ma + mb + mc + md)
  330. assert (y == c).all()
  331. cg = PermuteDims(M, [1, 0])
  332. assert tensorflow_code(cg) == 'tensorflow.transpose(M, [1, 0])'
  333. f = lambdify((M,), cg, 'tensorflow')
  334. y = session.run(f(ma))
  335. c = session.run(tf.transpose(ma))
  336. assert (y == c).all()
  337. cg = PermuteDims(ArrayTensorProduct(M, N), [1, 2, 3, 0])
  338. assert tensorflow_code(cg) == \
  339. 'tensorflow.transpose(' \
  340. 'tensorflow.linalg.einsum("ab,cd", M, N), [1, 2, 3, 0])'
  341. f = lambdify((M, N), cg, 'tensorflow')
  342. y = session.run(f(ma, mb))
  343. c = session.run(tf.transpose(tf.einsum("ab,cd", ma, mb), [1, 2, 3, 0]))
  344. assert (y == c).all()
  345. cg = ArrayDiagonal(ArrayTensorProduct(M, N), (1, 2))
  346. assert tensorflow_code(cg) == \
  347. 'tensorflow.linalg.einsum("ab,bc->acb", M, N)'
  348. f = lambdify((M, N), cg, 'tensorflow')
  349. y = session.run(f(ma, mb))
  350. c = session.run(tf.einsum("ab,bc->acb", ma, mb))
  351. assert (y == c).all()
  352. def test_MatrixElement_printing():
  353. A = MatrixSymbol("A", 1, 3)
  354. B = MatrixSymbol("B", 1, 3)
  355. C = MatrixSymbol("C", 1, 3)
  356. assert tensorflow_code(A[0, 0]) == "A[0, 0]"
  357. assert tensorflow_code(3 * A[0, 0]) == "3*A[0, 0]"
  358. F = C[0, 0].subs(C, A - B)
  359. assert tensorflow_code(F) == "(tensorflow.math.add((-1)*B, A))[0, 0]"
  360. def test_tensorflow_Derivative():
  361. expr = Derivative(sin(x), x)
  362. assert tensorflow_code(expr) == \
  363. "tensorflow.gradients(tensorflow.math.sin(x), x)[0]"