a = tf.constant(1)
b = a * 2
b

b.op

b.consumers()

a.op

a.consumers()

"""
Explanation: TensorFlow图相关知识简介
参考: https://www.tensorflow.org/programmers_guide/graphs


tf.Graph


op, tensor


variable


name_scope, variable_scop, collection


save and restore



0. tf.Graph
tf.Graph: GraphDef => *.pb文件
+ Graph structure: Operator, Tensor-like object, 连接关系
+ Graph collections: metadata
tf.Session():
+ 本地
+ 分布式：master (worker_0)
python
with tf.Session("grpc://example.org:2222"):
  pass
状态（Variable) => *.ckpt文件
1. 算子与Tensor
End of explanation
"""


b.op.outputs

list(b.op.inputs)

print(b.op.inputs[0])
print(a)

list(a.op.inputs)

"""
Explanation: tensorflow/python/framework/ops.py
+ Tensor:
    - device
    - graph
    - op
    - consumers
    - _override_operator:
      数学算子：math_op.add 重载 __add__
End of explanation
"""


v = tf.Variable([0])
c = b + v
c

list(c.op.inputs)

c.op.inputs[1].op

list(c.op.inputs[1].op.inputs)

v

"""
Explanation: Operator: NodeDef
device
inputs
outputs
graph
node_def
op_def
run
traceback

Operator和Tensor构成无向图
```python
run
sess.run([b])
```
参考:
+ tf.Tensor: https://www.tensorflow.org/versions/master/api_docs/python/tf/Tensor
+ tf.Operator: https://www.tensorflow.org/versions/master/api_docs/python/tf/Operation
2. 变量
End of explanation
"""


graph_a = tf.Graph()
with graph_a.as_default():
    v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
    print(v1)
    inc_v1 = v1.assign(v1+1)
      
    init_op = tf.global_variables_initializer()
    saver = tf.train.Saver()
  
    with tf.Session() as sess:
        sess.run(init_op)
        inc_v1.op.run()
        save_path = saver.save(sess, "./tmp/model.ckpt", write_meta_graph=True)
        print("Model saved in path: %s" % save_path)
        
        pb_path = tf.train.write_graph(graph_a.as_graph_def(), "./tmp/", "graph.pbtxt", as_text=True)
        print("Graph saved in path: %s" % pb_path)

"""
Explanation: 实际上，对变量的读是通过tf.identity算子得到：
python
c = tf.add(b, tf.identity(v))

Variable: act like Tensor
ops
VariableV2
ResourceVariable


_AsTensor -> g.as_graph_element
value: Identity(variable) -> Tensor
assign
init_op: Assign(self, init_value)
to_proto: VariableDef

参考：https://www.tensorflow.org/versions/master/api_docs/python/tf/Variable
3. collections

collections: 按作用分组
Variable: global_varialbe
更多见tf.GraphKeys
name_scope: Operator, Tensor
variable_scope: Variable
伴生name_scope

python
class Layer:
  def build(self):
    pass
  def call(self, inputs):
    pass

参考：https://www.tensorflow.org/programmers_guide/summaries_and_tensorboard
4. 保存与恢复
End of explanation
"""


graph_b = tf.Graph()
with graph_b.as_default():
    with tf.Session() as sess:
        saver = tf.train.import_meta_graph('./tmp/model.ckpt.meta')
        saver.restore(sess, "./tmp/model.ckpt")
        print(graph_b.get_operations())
        
        v1 = graph_b.get_tensor_by_name("v1:0")
        print("------------------")
        print("v1 : %s" % v1.eval(session=sess))

"""
Explanation: graph.pbtxt部份示意：v1 + 1:
bash
node {
  name: "add"
  op: "Add"
  input: "v1/read"
  input: "add/y"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
}
End of explanation
"""


