made a neat modal system in gof

上级 bc3756f5
import unittest
import constructor_fodder as cf
class Allocator:
def __init__(self, cls, ctor):
self.cls = cls
......
import op, ext, lib, link, result, env, prog, features, opt, graph
import op, result, ext, link, env, features, toolbox, graph
from op import *
from result import *
from ext import *
from lib import *
from link import *
from result import *
from env import *
from prog import *
from features import *
from opt import *
import graph
from toolbox import *
# import op, ext, lib, link, result, env, prog, features, opt, graph
# from op import *
# from ext import *
# from lib import *
# from link import *
# from result import *
# from env import *
# from prog import *
# from features import *
# from opt import *
# import graph
......@@ -62,29 +62,44 @@ t2s = OpSubOptimizer(TransposeView, Sigmoid)
s2t = OpSubOptimizer(Sigmoid, TransposeView)
from constructor import Constructor
from allocators import BuildAllocator
c = Constructor(BuildAllocator)
c.update(globals())
globals().update(c)
# from constructor import Constructor
# from allocators import BuildAllocator
# c = Constructor(BuildAllocator)
# c.update(globals())
# globals().update(c)
# def inputs():
# x = (MyResult('x'))
# y = (MyResult('y'))
# z = (MyResult('z'))
# return x, y, z
class _test_all(unittest.TestCase):
# def env(inputs, outputs, validate = True):
# return Env(inputs, outputs, features = [EquivTool], consistency_check = validate)
import modes
modes.make_constructors(globals(), name_filter = lambda x:x)
def inputs(self):
x = MyResult('x')
y = MyResult('y')
z = MyResult('z')
def inputs():
x = modes.BuildMode(MyResult('x'))
y = modes.BuildMode(MyResult('y'))
z = modes.BuildMode(MyResult('z'))
return x, y, z
def env(self, inputs, outputs, validate = True):
def env(inputs, outputs, validate = True):
inputs = [input.r for input in inputs]
outputs = [output.r for output in outputs]
return Env(inputs, outputs, features = [EquivTool], consistency_check = validate)
class _test_all(unittest.TestCase):
def test_0(self):
x, y, z = self.inputs()
x, y, z = inputs()
e = Add(AddInPlace(x, y), AddInPlace(x, y))
try:
g = self.env([x,y,z], [e])
g = env([x,y,z], [e])
except InconsistencyError, e:
pass
else:
......@@ -94,68 +109,68 @@ class _test_all(unittest.TestCase):
# the loop is needed because a2i will optimize in a random order and sometimes
# only one of them fails
for i in xrange(100):
x, y, z = self.inputs()
x, y, z = inputs()
e = Add(Add(x, y), Add(y, x))
g = self.env([x,y,z], [e])
g = env([x,y,z], [e])
assert g.consistent()
a2i.optimize(g)
assert g.consistent()
assert str(g) != "[AddInPlace(AddInPlace(x, y), AddInPlace(y, x))]"
def test_2(self):
x, y, z = self.inputs()
g = self.env([x,y,z], [Dot(AddInPlace(x, z), x)], False)
x, y, z = inputs()
g = env([x,y,z], [Dot(AddInPlace(x, z), x)], False)
assert not g.consistent()
i2a.optimize(g)
assert g.consistent()
def test_3(self):
for i in xrange(100):
x, y, z = self.inputs()
x, y, z = inputs()
e = Dot(Add(TransposeView(z), y), Add(z, x))
g = self.env([x,y,z], [e])
g = env([x,y,z], [e])
assert g.consistent()
a2i.optimize(g)
assert g.consistent()
assert str(g) != "[Dot(AddInPlace(TransposeView(z), y), AddInPlace(z, x))]"
def test_4(self):
x, y, z = self.inputs()
x, y, z = inputs()
e = Dot(AddInPlace(x,y), TransposeView(x))
g = self.env([x,y,z], [e], False)
g = env([x,y,z], [e], False)
assert not g.consistent()
g.replace(e.owner.inputs[1], Add(x,z))
g.replace(e.r.owner.inputs[1], Add(x,z).r)
assert g.consistent()
def test_5(self):
x, y, z = self.inputs()
x, y, z = inputs()
e = Dot(AddInPlace(x,y), TransposeView(TransposeView(TransposeView(TransposeView(Sigmoid(x))))))
g = self.env([x,y,z], [e])
g = env([x,y,z], [e])
assert g.consistent()
g.replace(e.owner.inputs[1].owner.inputs[0], x, False)
g.replace(e.r.owner.inputs[1].owner.inputs[0], x.r, False)
assert not g.consistent()
def test_6(self):
for i in xrange(100):
x, y, z = self.inputs()
x, y, z = inputs()
e = Dot(AddInPlace(x,Sigmoid(y)), Sigmoid(Sigmoid(Sigmoid(Sigmoid(Sigmoid(x))))))
g = self.env([x,y,z], [e])
g = env([x,y,z], [e])
assert g.consistent()
s2t.optimize(g)
assert g.consistent()
assert str(g) != "[Dot(AddInPlace(x,TransposeView(y)), TransposeView(TransposeView(TransposeView(TransposeView(TransposeView(x))))))]"
def test_7(self):
x, y, z = self.inputs()
x, y, z = inputs()
e = TransposeView(TransposeView(TransposeView(TransposeView(x))))
g = self.env([x,y,z], [e])
g = env([x,y,z], [e])
assert g.consistent()
chk = g.checkpoint()
dtv_elim.optimize(g)
assert str(g) == "[x]"
g.replace(g.equiv(e), Add(x,y))
g.replace(g.equiv(e.r), Add(x,y).r)
assert str(g) == "[Add(x, y)]"
g.replace(g.equiv(e), Dot(AddInPlace(x,y), TransposeView(x)), False)
g.replace(g.equiv(e.r), Dot(AddInPlace(x,y), TransposeView(x)).r, False)
assert str(g) == "[Dot(AddInPlace(x, y), TransposeView(x))]"
assert not g.consistent()
g.revert(chk)
......@@ -163,31 +178,31 @@ class _test_all(unittest.TestCase):
assert str(g) == "[TransposeView(TransposeView(TransposeView(TransposeView(x))))]"
def test_8(self):
x, y, z = self.inputs()
x, y, z = inputs()
e = Dot(Dot(AddInPlace(x,y), AddInPlace(y,z)), Add(z,x))
g = self.env([x,y,z], [e])
g = env([x,y,z], [e])
assert g.consistent()
a2i.optimize(g)
assert g.consistent()
assert str(g) != "[Dot(Dot(AddInPlace(x, y), AddInPlace(y, z)), AddInPlace(z, x))]" # we don't want to see that!
def test_9(self):
x, y, z = self.inputs()
x.indestructible = True
x, y, z = inputs()
x.r.indestructible = True
e = AddInPlace(x, y)
g = self.env([x,y,z], [e], False)
g = env([x,y,z], [e], False)
assert not g.consistent()
g.replace(e, Add(x, y))
g.replace(e.r, Add(x, y).r)
assert g.consistent()
def test_10(self):
x, y, z = self.inputs()
x.indestructible = True
x, y, z = inputs()
x.r.indestructible = True
tv = TransposeView(x)
e = AddInPlace(tv, y)
g = self.env([x,y,z], [e], False)
g = env([x,y,z], [e], False)
assert not g.consistent()
g.replace(tv, Sigmoid(x))
g.replace(tv.r, Sigmoid(x).r)
assert g.consistent()
......
import unittest
from result import ResultBase
from op import Op
from env import Env
from link import *
class Double(ResultBase):
def __init__(self, data, name = "oignon"):
assert isinstance(data, float)
ResultBase.__init__(self, role = None, data = data, name = name)
def __str__(self):
return self.name
def __repr__(self):
return self.name
class MyOp(Op):
nin = -1
def __init__(self, *inputs):
assert len(inputs) == self.nin
for input in inputs:
if not isinstance(input, Double):
raise Exception("Error 1")
self.inputs = inputs
self.outputs = [Double(0.0, self.__class__.__name__ + "_R")]
def perform(self):
self.outputs[0].data = self.impl(*[input.data for input in self.inputs])
class Unary(MyOp):
nin = 1
class Binary(MyOp):
nin = 2
class Add(Binary):
def impl(self, x, y):
return x + y
class Sub(Binary):
def impl(self, x, y):
return x - y
class Mul(Binary):
def impl(self, x, y):
return x * y
class Div(Binary):
def impl(self, x, y):
return x / y
import modes
modes.make_constructors(globals())
def inputs():
x = modes.BuildMode(Double(1.0, 'x'))
y = modes.BuildMode(Double(2.0, 'y'))
z = modes.BuildMode(Double(3.0, 'z'))
return x, y, z
def env(inputs, outputs, validate = True, features = []):
inputs = [input.r for input in inputs]
outputs = [output.r for output in outputs]
return Env(inputs, outputs, features = features, consistency_check = validate)
def perform_linker(env):
lnk = PerformLinker(env)
lnk.compile()
return lnk
class _test_PerformLinker(unittest.TestCase):
def test_0(self):
x, y, z = inputs()
e = mul(add(x, y), div(x, y))
perform_linker(env([x, y, z], [e])).run()
assert e.r.data == 1.5
if __name__ == '__main__':
unittest.main()
import unittest
from modes import *
from result import ResultBase
from op import Op
from env import Env
class Double(ResultBase):
def __init__(self, data, name = "oignon"):
assert isinstance(data, float)
ResultBase.__init__(self, role = None, data = data, name = name)
def __str__(self):
return self.name
def __repr__(self):
return self.name
def __add__(self, other):
return Add(self, other)
def convert(x):
if isinstance(x, float):
return Double(x)
elif isinstance(x, Double):
return x
raise Exception("Error 1")
class MyOp(Op):
nin = -1
def __init__(self, *inputs):
assert len(inputs) == self.nin
inputs = [convert(input) for input in inputs]
self.inputs = inputs
self.outputs = [Double(0.0, self.__class__.__name__ + "_R")]
def perform(self):
self.outputs[0].data = self.impl(*[input.data for input in self.inputs])
class Unary(MyOp):
nin = 1
class Binary(MyOp):
nin = 2
class Add(Binary):
def impl(self, x, y):
return x + y
class Sub(Binary):
def impl(self, x, y):
return x - y
class Mul(Binary):
def impl(self, x, y):
return x * y
class Div(Binary):
def impl(self, x, y):
return x / y
make_constructors(globals())
def inputs(mode):
x = mode(Double(1.0, 'x'))
y = mode(Double(2.0, 'y'))
z = mode(Double(3.0, 'z'))
return x, y, z
def env(inputs, outputs, validate = True):
inputs = [input.r for input in inputs]
outputs = [output.r for output in outputs]
return Env(inputs, outputs, features = [], consistency_check = validate)
class _test_Modes(unittest.TestCase):
def test_0(self):
x, y, z = inputs(BuildMode)
e = add(add(x, y), z)
g = env([x, y, z], [e])
assert str(g) == "[Add(Add(x, y), z)]"
assert e.r.data == 0.0
def test_1(self):
x, y, z = inputs(BuildEvalMode)
e = add(add(x, y), z)
g = env([x, y, z], [e])
assert str(g) == "[Add(Add(x, y), z)]"
assert e.r.data == 6.0
def test_2(self):
x, y, z = inputs(EvalMode)
e = add(add(x, y), z)
g = env([x, y, z], [e])
assert str(g) == "[Add_R]"
assert e.r.data == 6.0
def test_3(self):
x, y, z = inputs(BuildMode)
e = x + y + z
g = env([x, y, z], [e])
assert str(g) == "[Add(Add(x, y), z)]"
assert e.r.data == 0.0
def test_4(self):
x, y, z = inputs(BuildEvalMode)
e = x + 34.0
g = env([x, y, z], [e])
assert str(g) == "[Add(x, oignon)]"
assert e.r.data == 35.0
def test_5(self):
xb, yb, zb = inputs(BuildMode)
xe, ye, ze = inputs(EvalMode)
try:
e = xb + ye
except TypeError:
# Trying to add inputs from different modes is forbidden
pass
else:
raise Exception("Expected an error.")
if __name__ == '__main__':
unittest.main()
......@@ -44,21 +44,19 @@ class Op4(MyOp):
pass
from constructor import Constructor
from allocators import BuildAllocator
c = Constructor(BuildAllocator)
c.update(globals())
for k, v in c.items():
globals()[k.lower()] = v
import modes
modes.make_constructors(globals())
def inputs():
x = MyResult('x')
y = MyResult('y')
z = MyResult('z')
x = modes.BuildMode(MyResult('x'))
y = modes.BuildMode(MyResult('y'))
z = modes.BuildMode(MyResult('z'))
return x, y, z
def env(inputs, outputs, validate = True):
inputs = [input.r for input in inputs]
outputs = [output.r for output in outputs]
return Env(inputs, outputs, features = [EquivTool], consistency_check = validate)
......
......@@ -42,30 +42,33 @@ class Add(MyOp):
class Dot(MyOp):
nin = 2
from constructor import Constructor
from allocators import BuildAllocator
c = Constructor(BuildAllocator)
c.update(globals())
globals().update(c)
import modes
modes.make_constructors(globals())
def inputs():
x = MyResult('x')
y = MyResult('y')
z = MyResult('z')
x = modes.BuildMode(MyResult('x'))
y = modes.BuildMode(MyResult('y'))
z = modes.BuildMode(MyResult('z'))
return x, y, z
def env(inputs, outputs, validate = True, features = []):
inputs = [input.r for input in inputs]
outputs = [output.r for output in outputs]
return Env(inputs, outputs, features = features, consistency_check = validate)
class _test_EquivTool(unittest.TestCase):
def test_0(self):
x, y, z = inputs()
sx = Sigmoid(x)
e = Add(sx, Sigmoid(y))
g = Env([x, y, z], [e], features = [EquivTool])
assert g.equiv(sx) is sx
g.replace(sx, Dot(x, z))
assert g.equiv(sx) is not sx
assert isinstance(g.equiv(sx).owner, Dot.opclass)
sx = sigmoid(x)
e = add(sx, sigmoid(y))
g = env([x, y, z], [e], features = [EquivTool])
assert g.equiv(sx.r) is sx.r
g.replace(sx.r, dot(x, z).r)
assert g.equiv(sx.r) is not sx.r
assert isinstance(g.equiv(sx.r).owner, Dot)
......
......@@ -3,6 +3,40 @@
from utils import AbstractFunctionError
class Dispatcher(list):
all_dispatchers = {}
def __init__(self, name, description):
self.name = name
self.description = description
self.all_dispatchers[name] = self
def __call__(self, *inputs, **opts):
for candidate in self:
try:
return candidate(*inputs, **opts)
except TypeError:
continue
if opts:
s = " with options %s" % opts
else:
s = ""
raise OmegaTypeError("No candidate found for %s(%s) %s" \
% (self.name,
", ".join([input.__class__.__name__ for input in inputs]),
s))
def add_handler(self, x):
self.insert(0, x)
def fallback_handler(self, x):
self.append(x)
class Allocator:
def __init__(self, fn):
......@@ -56,50 +90,3 @@ class Constructor(dict):
# class Constructor:
# def __init__(self):
# pass
# def add_module(self, module, module_name, accept=lambda x:issubclass(x, cf.base)):
# dct = {}
# for symbol in dir(module):
# if symbol[:2] == '__': continue
# obj = getattr(module, symbol)
# if accept(obj): dct[symbol] = Allocator(obj)
# class Dummy:pass
# self.__dict__[module_name] = Dummy()
# self.__dict__[module_name].__dict__.update(dct)
# def add_from_module(self, module, accept=lambda x:issubclass(x, cf.base)):
# for symbol in dir(module):
# if symbol[:2] == '__': continue
# obj = getattr(module, symbol)
# #print 'considering', symbol, obj
# if accept(obj): self.__dict__[symbol] = Allocator(obj)
# def add_globals_from_module(self, module, accept=lambda x:issubclass(x, cf.base)):
# for symbol in dir(module):
# if symbol[:2] == '__': continue
# obj = getattr(module, symbol)
# #print 'considering', symbol, obj
# if accept(obj):
# if hasattr(globals(), symbol):
# print 'Warning, overwriting global variable: %s' % symbol
# globals()[symbol] = Allocator(obj)
# if __name__=='__main__':
# c = Constructor()
# c.add_module(cf,'cf')
# aa,bb = c.cf.A(), c.cf.B()
# print aa,bb
# c.add_from_module(cf)
# a,b = c.A(), c.B()
# print a,b
# c.add_globals_from_module(cf)
# d,e = A(), B()
# print d,e
......@@ -91,6 +91,7 @@ def ops(i, o):
results, orphans = results_and_orphans(i, o)
for r in results:
if r not in i and r not in orphans:
if r.owner is not None:
ops.add(r.owner)
return ops
......
import utils
from op import Op
__all__ = ['ModalConstructor',
'add_modal_members',
'ModalWrapper',
'BuildMode',
'EvalMode',
'BuildEvalMode',
'make_constructors',
]
class ModalConstructor:
def __init__(self, fn):
self.fn = fn
def __call__(self, *args):
modal_wrapper = None
fn_args = []
for arg in args:
if isinstance(arg, ModalWrapper):
if modal_wrapper is None:
modal_wrapper = arg.__class__
else:
if not isinstance(arg, modal_wrapper):
raise TypeError("Inconsistent modes.")
fn_args.append(arg.r)
else:
fn_args.append(arg)
op = self.fn(*fn_args)
if modal_wrapper:
modal_wrapper.filter(op)
if len(op.outputs) == 1:
return modal_wrapper(op.outputs[0])
else:
return [modal_wrapper(output) for output in op.outputs]
def add_modal_members(cls, *members):
def fn(member):
def ret(self, *args):
constructor = ModalConstructor(getattr(self.r.__class__, member))
return constructor(self, *args)
return ret
for member in members:
setattr(cls, member, fn(member))
class ModalWrapper:
def __init__(self, r):
self.r = r
@classmethod
def filter(cls, op):
raise AbstractFunctionError()
members1 = 'add sub mul div pow floordiv mod pow lshift rshift and or xor'.split(' ')
members = []
members += ["__%s__" % x for x in members1 + 'neg invert'.split(' ')]
members += ["__r%s__" % x for x in members1]
add_modal_members(ModalWrapper, *members)
class BuildMode(ModalWrapper):
@classmethod
def filter(cls, op):
pass
class EvalMode(ModalWrapper):
@classmethod
def filter(cls, op):
op.perform()
for output in op.outputs:
output._role = None
class BuildEvalMode(ModalWrapper):
@classmethod
def filter(cls, op):
op.perform()
def _is_op(x):
try: return issubclass(x, Op)
except: return False
def make_constructors(source,
dest = None,
name_filter = utils.camelcase_to_separated,
candidate_filter = _is_op):
if dest is None:
dest = source
for symbol, value in source.items():
if candidate_filter(value):
dest[name_filter(symbol)] = ModalConstructor(value)
return dest
......@@ -2,6 +2,8 @@
# import op
# import result
import re
class OmegaError(Exception): pass
......@@ -42,8 +44,21 @@ def all_bases_collect(cls, raw_name):
return rval
def camelcase_to_separated(string, sep = "_"):
return re.sub('(.)([A-Z])', '\\1%s\\2' % sep, string).lower()
def to_return_values(values):
if len(values) == 1:
return values[0]
else:
return values
def from_return_values(values):
if isinstance(values, (list, tuple)):
return values
else:
return [values]
def partial(func, *args, **keywords):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论