"""
Jonathan Zacsh's solution to homework #3, Nov 14., Part I
"""
# Per homework instructions, following lead from matlab example by professor:
#   http://comet.lehman.cuny.edu/schneider/Fall17/CMP464/Maple/PartialDerivatives1.pdf
import sys
import tensorflow as tf
import tempfile
import os
import numpy as np

os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
# not really doing intersting things in this lab, so just ignore optimization

class Differentiable:
    """ encapsulation of a function and its derivative """
    def __init__(self, label, f, d):
        self.func = f
        self.deriv = d
        self.func.name = label
        self.deriv.name = "%sDeriv" % label

# g(x) = x^4+2x-7 ; per matlab example
# g'(x) = 4x^3+2
fExFourth = Differentiable("fExFourth",
        lambda x: tf.add_n([tf.pow(x, 4), tf.multiply(2, x), -7]),
        lambda x: tf.add_n([tf.multiply(4, tf.pow(x, 3)), 2]))

tFofTwo = fExFourth.func(2)
tFofDerivTwo = fExFourth.deriv(2)

log_dir = tempfile.mkdtemp(prefix="hw3-nov14-parti")
print(log_dir)
with tf.Session() as sess:
    writer = tf.summary.FileWriter(log_dir, sess.graph)

    fOfTwo, fDerivOfTwo = results = sess.run([tFofTwo, tFofDerivTwo])
    sys.stderr.write("results:\n\tf(2)=%s\n\tf'(2)=%s\n" % (fOfTwo, fDerivOfTwo))

    # note: only needed when doing a *loop* of sess.run() calls, and want to see
    # intermediary results per-loop.
    #writer.add_summary(results)

    writer.flush()
    writer.close()

[((32, 10, 32, 52), 'tempfile.mkdtemp', 'tempfile.mkdtemp', (), '', False, 'import tempfile\n'), ((34, 5, 34, 17), 'tensorflow.Session', 'tf.Session', ({}, {}), '()', True, 'import tensorflow as tf\n'), ((35, 13, 35, 55), 'tensorflow.summary.FileWriter', 'tf.summary.FileWriter', ({(35, 35, 35, 42): 'log_dir', (35, 44, 35, 54): 'sess.graph'}, {}), '(log_dir, sess.graph)', True, 'import tensorflow as tf\n'), ((38, 4, 38, 81), 'sys.stderr.write', 'sys.stderr.write', ({(38, 21, 38, 80): '("""results:\n\tf(2)=%s\n\tf\'(2)=%s\n""" % (fOfTwo, fDerivOfTwo))'}, {}), '("""results:\n\tf(2)=%s\n\tf\'(2)=%s\n""" % (fOfTwo, fDerivOfTwo))', False, 'import sys\n'), ((26, 28, 26, 40), 'tensorflow.pow', 'tf.pow', ({(26, 35, 26, 36): 'x', (26, 38, 26, 39): '4'}, {}), '(x, 4)', True, 'import tensorflow as tf\n'), ((26, 42, 26, 59), 'tensorflow.multiply', 'tf.multiply', ({(26, 54, 26, 55): '2', (26, 57, 26, 58): 'x'}, {}), '(2, x)', True, 'import tensorflow as tf\n'), ((27, 43, 27, 55), 'tensorflow.pow', 'tf.pow', ({(27, 50, 27, 51): 'x', (27, 53, 27, 54): '3'}, {}), '(x, 3)', True, 'import tensorflow as tf\n')]