added test file

上级 b8839686
import gof import gof
from gof import current_mode, set_mode, build_mode, eval_mode, pop_mode, UNCOMPUTED, UNDEFINED, PythonR
import numpy import numpy
from copy import copy as pycopy from copy import copy as pycopy
...@@ -7,31 +9,6 @@ from copy import copy as pycopy ...@@ -7,31 +9,6 @@ from copy import copy as pycopy
# __all__ = ['set_mode', 'get_mode', 'NumpyR', 'NumpyOp'] # __all__ = ['set_mode', 'get_mode', 'NumpyR', 'NumpyOp']
_mode = ['eval']
# def set_mode(mode):
# _mode.append(mode)
# def current_mode():
# return _mode[-1]
# def build_mode():
# set_mode('build')
# def eval_mode():
# set_mode('eval')
# def pop_mode():
# if len(_mode) == 1:
# raise Exception("There's only one mode left on the stack.")
# else:
# _mode.pop()
# def end_eval():
# set_mode('eval')
current_mode, set_mode, build_mode, eval_mode, pop_mode = gof.current_mode, gof.set_mode, gof.build_mode, gof.eval_mode, gof.pop_mode
def build(f, *args, **kwargs): def build(f, *args, **kwargs):
build_mode() build_mode()
r = f(*args, **kwargs) r = f(*args, **kwargs)
...@@ -39,29 +16,6 @@ def build(f, *args, **kwargs): ...@@ -39,29 +16,6 @@ def build(f, *args, **kwargs):
return r return r
# class Keyword:
# def __init__(self, name, nonzero=True):
# self.name = name
# self.nonzero = nonzero
# def __nonzero__(self):
# return self.nonzero
# def __str__(self):
# return "<%s>" % self.name
# def __repr__(self):
# return str(self)
UNCOMPUTED = gof.UNCOMPUTED
UNDEFINED = gof.UNDEFINED
# UNCOMPUTED = Keyword("UNCOMPUTED", False)
# UNDEFINED = Keyword("UNDEFINED", False)
class Proxy(object): class Proxy(object):
__slots__ = ['_obj'] __slots__ = ['_obj']
...@@ -85,144 +39,22 @@ class Proxy(object): ...@@ -85,144 +39,22 @@ class Proxy(object):
delattr(self._obj, attr) delattr(self._obj, attr)
# class IViewer(gof.ext.Viewer): def as_string(*rs):
# _v_map = {} s = gof.graph.as_string(gof.graph.inputs(rs), rs)
if len(rs) == 1:
# def view_map(self): return s[1:-1]
# rval = {} else:
# for output, inputs in self._v_map.items(): return s
# if isinstance(inputs, (list, tuple)): # return str(gof.Env(gof.graph.inputs([r]), [r]))[1:-1]
# rval[self.outputs[output]] = [self.inputs[i] for i in inputs]
# else:
# rval[self.outputs[output]] = self.inputs[inputs]
# return rval
# class IDestroyer(gof.ext.Destroyer):
# _d_map = {}
# def destroy_map(self):
# rval = {}
# for output, inputs in self._d_map.items():
# if isinstance(inputs, (list, tuple)):
# rval[self.outputs[output]] = [self.inputs[i] for i in inputs]
# else:
# rval[self.outputs[output]] = self.inputs[inputs]
# return rval
# class PythonR(gof.HolderResult):
# def __init__(self, a = None):
# if a is None:
# self.storage = UNCOMPUTED
# else:
# self.storage = a
# def set_value(self, value):
# self.storage = value
# def __str__(self):
# return str(self.storage)
# def __repr__(self):
# return repr(self.storage)
# gof.PythonR = PythonR
class NumpyR(gof.PythonR):
# def __init__(self, a = None):
# self.set_value(a)
def set_value(self, value):
if value is None or value is UNCOMPUTED:
self.data = UNCOMPUTED
elif isinstance(value, numpy.ndarray):
self.data = value
else:
self.data = numpy.array(value)
def __add__(self, y):
return add(self, y)
def __radd__(self, x):
return add(x, self)
def __iadd__(self, y):
return iadd(self, y)
def __sub__(self, y):
return sub(self, y)
def __rsub__(self, x):
return sub(x, self)
def __isub__(self, y):
return isub(self, y)
def __mul__(self, y):
return dot(self, y)
def __rmul__(self, x):
return dot(x, self)
def __imul__(self, y):
return imul(self, y)
def __div__(self, y):
return div(self, y)
def __rdiv__(self, x):
return div(x, self)
def __idiv__(self, y):
return idiv(self, y)
def __mod__(self, y):
return mod(self, y)
def __rmod__(self, x):
return mod(x, self)
def __pow__(self, y):
return pow(self, y)
def __rpow__(self, x):
return pow(x, self)
def __ipow__(self, y):
return ipow(self, y)
def __neg__(self):
return neg(self)
T = property(lambda self: transpose(self))
Tc = property(lambda self: transpose_copy(self))
def __copy__(self):
return array_copy(self)
#[iadd(iadd(iadd(iadd(<UNCOMPUTED>, itwice(<UNCOMPUTED>)), <UNCOMPUTED>), 1.0), dot(<UNCOMPUTED>, <UNCOMPUTED>))] def print_graph(*rs):
#[iadd(iadd(iadd(iadd(<UNCOMPUTED>, itwice(<UNCOMPUTED>)), <UNCOMPUTED>), 1.0), dot(<UNCOMPUTED>, <UNCOMPUTED>))] print as_string(*rs)
def wrap(x): def wrap(x):
# try:
# return to_numpyr(x)
# except TypeError:
# if isinstance(x, PythonR):
# return x
# else:
# return PythonR(x)
# def to_numpyr(x):
if isinstance(x, NumpyR): if isinstance(x, NumpyR):
return x return x
elif isinstance(x, gof.PythonR): elif isinstance(x, PythonR):
return x return x
elif isinstance(x, omega_op): elif isinstance(x, omega_op):
return x.out return x.out
...@@ -230,106 +62,17 @@ def wrap(x): ...@@ -230,106 +62,17 @@ def wrap(x):
return wrap(x._obj) return wrap(x._obj)
elif isinstance(x, numpy.ndarray): elif isinstance(x, numpy.ndarray):
return NumpyR(x) return NumpyR(x)
elif isinstance(x, (int, float)):
return NumpyR(numpy.array(x))
else: else:
return gof.PythonR(x) return PythonR(x)
# else:
# raise TypeError("%s cannot be converted to or encapsulated in a NumpyR instance." % x)
# class NumpyOp(gof.Op, gof.ext.BuildableFromInputs):
# nout = 1
# def __init__(self, *args):
# inputs = [wrap(arg) for arg in args]
# outputs = [NumpyR() for i in xrange(self.nout)]
# gof.Op.__init__(self, inputs, outputs)
# @classmethod
# def from_inputs(cls, *inputs):
# return cls(*inputs)
# def gen_outputs(self):
# return [NumpyR() for i in xrange(self.nout)]
# class wrapper:
# __slots__ = ['f', 'opclass']
# def __init__(self, name, f, grad, vmap = None, dmap = None, optype = NumpyOp):
# self.f = f
# if not callable(f):
# raise TypeError("Can only wrap a callable.")
# bases = [optype]
# if vmap: bases.append(IViewer)
# if dmap: bases.append(IDestroyer)
# Wrapper = type(name, tuple(bases), {})
# if vmap: Wrapper._v_map = vmap
# if dmap: Wrapper._d_map = dmap
# def thunk(self):
# def ret():
# self.outputs[0].set_value(f(*[input.storage for input in self.inputs]))
# return ret
# Wrapper.thunk = thunk
# if grad is UNDEFINED:
# grad = lambda *_: UNDEFINED
# Wrapper.grad = staticmethod(grad)
# self.opclass = Wrapper
# def __call__(self, *args):
# op = self.opclass(*args)
# if current_mode() == 'eval':
# op.thunk()()
# outputs = pycopy(op.outputs)
# # outputs = [Proxy(output) for output in op.outputs]
# if op.nout == 1:
# return outputs[0]
# else:
# return outputs
# def wrap_producer(f):
# def ret(*args, **kwargs):
# result = f(*args, **kwargs)
# if not isinstance(result, numpy.ndarray):
# result = numpy.array(result)
# return NumpyR(result)
# return ret
inplace = gof.Destroyer
view = gof.Viewer
# def wrap_producer(f):
# wrapped_f = wrapper(f.__name__, f, UNDEFINED)
# def ret(dim, dtype = 'float', order = 'C'):
# return wrapped_f(dim, dtype, order)
# return ret
class omega_op(gof.PythonOp):
inplace = gof.ext.Destroyer
view = gof.ext.Viewer
class omega_op_metaclass(type):
def __init__(cls, name, bases, dct):
type.__init__(cls, name, bases, dct)
cls.__clsinit__(name, bases, dct)
class omega_op(gof.PythonOp): #(gof.Op, gof.ext.BuildableFromInputs):
## __metaclass__ = omega_op_metaclass
## nout = 1
@staticmethod @staticmethod
def __clsinit__(cls, name, bases, dct): def __clsinit__(cls, name, bases, dct):
...@@ -345,40 +88,9 @@ class omega_op(gof.PythonOp): #(gof.Op, gof.ext.BuildableFromInputs): ...@@ -345,40 +88,9 @@ class omega_op(gof.PythonOp): #(gof.Op, gof.ext.BuildableFromInputs):
def __new__(cls, *inputs): def __new__(cls, *inputs):
inputs = [wrap(input) for input in inputs] inputs = [wrap(input) for input in inputs]
return gof.PythonOp.__new__(cls, *inputs) return gof.PythonOp.__new__(cls, *inputs)
# op = gof.Op.__new__(cls)
# op.__init__(*[wrap(input) for input in inputs])
# if cls.current_mode() == 'eval':
# op.thunk()()
# if op.nout == 1:
# return op.out
# else:
# return op.outputs
# def __init__(self, *inputs):
# for input in inputs:
# assert isinstance(input, gof.HolderResult)
# gof.Op.__init__(self, inputs, self.gen_outputs())
# @classmethod
# def from_inputs(cls, *inputs):
# build_mode()
# r = cls(*inputs)
# pop_mode()
# return r.owner
def gen_outputs(self): def gen_outputs(self):
return [NumpyR() for i in xrange(self.nout)] return [NumpyR() for i in xrange(self.nout)]
# def thunk(self):
# def ret():
# results = self.impl(*[input.storage for input in self.inputs])
# if self.nout == 1:
# self.out.set_value(results)
# else:
# assert self.nout == len(results)
# for result, output in zip(results, self.outputs):
# output.set_value(result)
# return ret
def update_gradient(self, grad_d): def update_gradient(self, grad_d):
inputgs = self.grad(*(self.inputs + [grad_d[output] for output in self.outputs])) inputgs = self.grad(*(self.inputs + [grad_d[output] for output in self.outputs]))
...@@ -390,8 +102,47 @@ class omega_op(gof.PythonOp): #(gof.Op, gof.ext.BuildableFromInputs): ...@@ -390,8 +102,47 @@ class omega_op(gof.PythonOp): #(gof.Op, gof.ext.BuildableFromInputs):
def grad(*args): def grad(*args):
return UNDEFINED return UNDEFINED
# def impl(*args):
# raise NotImplementedError("This op has no implementation.") class NumpyR(gof.PythonR):
def set_value(self, value):
if value is None or value is UNCOMPUTED:
self.data = UNCOMPUTED
elif isinstance(value, numpy.ndarray):
self.data = value
else:
self.data = numpy.array(value)
def __add__(self, y): return add(self, y)
def __radd__(self, x): return add(x, self)
def __iadd__(self, y): return iadd(self, y)
def __sub__(self, y): return sub(self, y)
def __rsub__(self, x): return sub(x, self)
def __isub__(self, y): return isub(self, y)
def __mul__(self, y): return mul(self, y)
def __rmul__(self, x): return mul(x, self)
def __imul__(self, y): return imul(self, y)
def __div__(self, y): return div(self, y)
def __rdiv__(self, x): return div(x, self)
def __idiv__(self, y): return idiv(self, y)
def __mod__(self, y): return mod(self, y)
def __rmod__(self, x): return mod(x, self)
def __imod__(self, y): return imod(self, y)
def __pow__(self, y): return pow(self, y)
def __rpow__(self, x): return pow(x, self)
def __ipow__(self, y): return ipow(self, y)
def __neg__(self): return neg(self)
T = property(lambda self: transpose(self))
Tc = property(lambda self: transpose_copy(self))
def __copy__(self): return array_copy(self)
def wrap_producer(f): def wrap_producer(f):
...@@ -407,7 +158,6 @@ array = wrap_producer(numpy.array) ...@@ -407,7 +158,6 @@ array = wrap_producer(numpy.array)
zeros = wrap_producer(numpy.zeros) zeros = wrap_producer(numpy.zeros)
ones = wrap_producer(numpy.ones) ones = wrap_producer(numpy.ones)
## Addition ## ## Addition ##
...@@ -428,7 +178,6 @@ class proto_twice(omega_op): ...@@ -428,7 +178,6 @@ class proto_twice(omega_op):
class twice(proto_twice): class twice(proto_twice):
def impl(x): def impl(x):
# print x
return x + x return x + x
class itwice(proto_twice, inplace): class itwice(proto_twice, inplace):
...@@ -450,7 +199,6 @@ class isub(proto_sub, inplace): ...@@ -450,7 +199,6 @@ class isub(proto_sub, inplace):
impl = numpy.ndarray.__isub__ impl = numpy.ndarray.__isub__
## Element-wise multiplication ## ## Element-wise multiplication ##
class proto_mul(omega_op): class proto_mul(omega_op):
...@@ -492,51 +240,49 @@ class exp(omega_op): ...@@ -492,51 +240,49 @@ class exp(omega_op):
impl = numpy.exp impl = numpy.exp
# ## Element-wise division ## ## Element-wise division ##
# def div_grad(x, y, gz): class proto_div(omega_op):
# return div(gz, y), -div(mul(x, gz), sqr(y)) def grad(x, y, gz):
return div(gz, y), -div(mul(x, gz), sqr(y))
# div = wrapper("div", class div(proto_div):
# numpy.ndarray.__div__, impl = numpy.ndarray.__div__
# div_grad)
# idiv = wrapper("idiv", class idiv(proto_div, inplace):
# numpy.ndarray.__idiv__, impl = numpy.ndarray.__idiv__
# div_grad,
# dmap = {0: 0})
# ## Scaling ## ## Scaling ##
# def scal_grad(x, a, gz): class proto_scal(omega_op):
# return scal(a, gz), sum(mul(x, gz)) def grad(x, a, gz):
return scal(a, gz), sum(mul(x, gz))
# scal = wrapper("scal", class scal(omega_op):
# numpy.ndarray.__mul__, impl = numpy.ndarray.__mul__
# scal_grad)
# iscal = wrapper("iscal", class iscal(omega_op, inplace):
# numpy.ndarray.__imul__, impl = numpy.ndarray.__imul__
# scal_grad,
# dmap = {0: 0})
# neg = wrapper("neg",
# numpy.ndarray.__neg__, class proto_neg(omega_op):
# lambda x, gz: -gz) def grad(x, gz):
return -gz
# ineg = wrapper("ineg", class neg(omega_op):
# lambda x: x.__imul__(-1), impl = numpy.ndarray.__neg__
# lambda x, gz: -gz,
# dmap = {0: 0})
class ineg(omega_op, inplace):
impl = lambda x: x.__imul__(-1)
# ## Dot product ##
# dot = wrapper("dot", ## Dot product ##
# numpy.dot,
# lambda x, y, gz: (dot(gz, transpose(y)), class dot(omega_op):
# dot(transpose(x), gz))) impl = numpy.dot
def grad(x, y, gz):
return dot(gz, transpose(y)), dot(transpose(x), gz)
## Transposition ## ## Transposition ##
...@@ -546,11 +292,6 @@ class transpose(omega_op, view): ...@@ -546,11 +292,6 @@ class transpose(omega_op, view):
def grad(x, gz): def grad(x, gz):
return transpose_copy(gz) return transpose_copy(gz)
# transpose = wrapper("transpose",
# numpy.transpose,
# lambda x, z, gz: transpose_copy(gz),
# vmap = {0: 0})
def transpose_copy(x): def transpose_copy(x):
return array_copy(transpose(x)) return array_copy(transpose(x))
......
...@@ -23,24 +23,16 @@ import gof ...@@ -23,24 +23,16 @@ import gof
# return gof.opt.OpSubOptimizer(op1, op2) # return gof.opt.OpSubOptimizer(op1, op2)
pattern_opt = gof.opt.PatternOptimizer pattern_opt = gof.PatternOptimizer
op_sub = gof.opt.OpSubOptimizer op_sub = gof.OpSubOptimizer
#def make_patterns(patterns):
# return [name, pattern_opt(inp, outp) for name, inp, outp in patterns]
def export_opts(opts): def export_opts(opts):
for name, opt in opts: for name, opt in opts:
if name: if name:
globals()[name] = opt globals()[name] = opt
# double_transpose_eliminator = pattern_opt((transpose, (transpose, 'x')), 'x')
# patterns = make_patterns(patterns)
# export_patterns(patterns)
# List of optimizations to perform. They are listed in the order they are applied. # List of optimizations to perform. They are listed in the order they are applied.
opts = [ opts = [
...@@ -62,24 +54,14 @@ opts = [ ...@@ -62,24 +54,14 @@ opts = [
['add_to_iadd_reverse', pattern_opt((add, 'x', 'y'), ['add_to_iadd_reverse', pattern_opt((add, 'x', 'y'),
(iadd, 'y', 'x'))], (iadd, 'y', 'x'))],
['remove_copies', gof.opt.OpRemover(array_copy)], ['remove_copies', gof.OpRemover(array_copy)],
[None, gof.lib.DummyRemover] # has to be at the end [None, gof.DummyRemover] # has to be at the end
] ]
export_opts(opts) # publish the optimizations performed under individual names
# class AAA(gof.opt.Optimizer):
# def __init__(self, opt): export_opts(opts) # publish the optimizations performed under individual names
# self.opt = opt
# def optimize(self, env):
# build_mode()
# self.opt.optimize(env)
# pop_mode()
optimizer = gof.lib.PythonOpt(gof.opt.MergeOptMerge(gof.opt.SeqOptimizer([opt for name, opt in opts]))) optimizer = gof.PythonOpt(gof.MergeOptMerge(gof.SeqOptimizer([opt for name, opt in opts])))
# import gof
# gof.stealth.method_wrap(int, '__add__', [2, 1], )
# x = gof.stealth.wrap(3)
# y = gof.stealth.wrap(4)
# print x + y
import gof
import core
import numpy
import compile
import grad
# a = core.NumpyR(numpy.ones((3, 3)))
# b = core.NumpyR(numpy.ones((3, 3)))
# w = core.dot #core.wrapper(numpy.dot)
# core.start_build()
# r = a * (b * b)
# core.end_build()
# #r = w(a, w(b, b))
# print r
# print r.owner
# env = gof.Env([a, b], [r._obj])
# print env
# print r
# gof.ThunkLinker()(env)()
# print r
# core.start_build()
# a += b + c
# a = a + b
# a += a + core.transpose(b)
# core.end_build()
# # env = gof.Env(gof.graph.inputs([a]), [a])
# # print env
# # gof.ThunkLinker()(env)()
# # print a
# print gof.Env(gof.graph.inputs([a]), [a])
# prog = compile.single(a)
# print prog.env
# prog()
# print a
############################
# core.build_mode()
# dim = core.wrap(())
# dim2 = core.wrap((2, 2))
# a = core.zeros(dim, dtype='int32') #(core.NumpyR(numpy.ones((3, 3))))
# b = core.ones(dim2, 'int32') #(core.NumpyR(numpy.ones((3, 3))))
# c = core.zeros(dim, dtype='int32')
# d = a + (b + b) + c + numpy.ones(())
# e = d + (b * c)
# core.pop_mode()
# #print e
# #print gof.graph.ops([dim], [e])
# #1/0
# #print gof.Env([dim], [e])
# #f = compile.to_func([dim], [e])
# f = compile.to_func([a, b, c], [e])
# print f(1, 2, 3)
# #print f((2,2))
############################
# a = core.ones((2, 2))
# b = core.ones((2, 2))
# def f():
# return (a + b) + (a + b)
# r = core.build(f)
# env = gof.Env([a, b], [r])
# print env
# gof.opt.MergeOptimizer().optimize(env)
# print env
# print compile.to_func([a, b], [r])(1, 2)
############################
a = core.ones((2, 2))
b = core.ones((2, 2))
def f():
return (a + b) + (a + b)
r = core.build(f)
g = grad.grad(r, a)
core.print_graph(g)
core.print_graph(r)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论