Code Monkey home page Code Monkey logo

Comments (5)

merrymercy avatar merrymercy commented on June 10, 2024

Proposed new design by @rbavishi

@generator
def func(...):
	...

### Iterator Style
  for _ in func.env(strategy: Strategy = None,
                    model: GeneratorModel = None,
                    tracing: bool=False,
                    replay: Union[Dict, GeneratorTrace] = None,
                    hooks: List[Hook] = None).generate():
	... 

### Call Style
func.env(strategy: Strategy = None,
         model: GeneratorModel = None,
         tracing: bool=False,
         replay: Union[Dict, GeneratorTrace] = None,
         hooks: List[Hook] = None).call()

### Common Use-Cases

# Partial Replay
for i in func.env(replay={'op1': [1]}).generate(args):
    print("Replayed Result: ", i)
	
# Replay Single Value
result = func.env(replay={'op1': [1]}).call(args)

# Partial Replay with Tracing
for i, trace in func.env(replay={'op1': [1]}, tracing=True).generate(args):
    print("Replayed Result: ", i)
    print("Trace: ", trace)
	
# Replay with Trace - Single Value
result, trace = func.env(replay={'op1': [1]}, tracing=True).call(args)

# Temporary Strategy (other than the default strategy)
for i in func.env(strategy=MyOwnStrategy()).generate(args):
    print("Result: ", i)
	
# Temporary Model (other than the default model)
for i in func.env(model=MyOwnModel()).generate(args):
    print("Result: ", i)

Comments by @merrymercy

  1. Make the call to env implicit if all settings are default values
for i in func.generate(args): # implicitly build an env with default settings
    print("Result: ", i)

func.call(args)  # implicitly build an env with default settings
func(args)       # The same as the above one
  1. Some alternatives to eliminate the .env(...)
    A natural understanding is that args are arguments of func, and strategy, model, hooks are arguments of generate. So we can do

ALT1

for i in func.generate(strategy=.., model=..)(args):
    print("Results: ", i)

func.call(strategy=.., model=..)(args):
func(args)  # The same as the above one

or

ALT2

for i in func.generate(args=.., kwargs=.., strategy=.., model=..):
    print("Results: ", i)

func.call(args=.., kwargs=.., strategy=.., model=..)
func(args)  # The same as the above one
  1. I think it is okay to leave tracing, replay in top-level, but I am not sure about model.

from atlas.

merrymercy avatar merrymercy commented on June 10, 2024

cc @carolemieux @royf

from atlas.

rbavishi avatar rbavishi commented on June 10, 2024

Thanks for the post and the comments Lianmin!

(a) Regarding your first comment, yeah I forgot to clarify this, I indeed intend to have .env as implicit when keyword args are defaults.

(b) Regarding the second, I'm not sure if we are gaining anything here - the separation of function arguments and generator arguments is being lost without much improvement in clarity or verbosity.

(c) I fully agree with having the two modes of iterator-based and single-return-value-based being made explicitly clear. The use of .generate and .call is a step towards that.

(d) A hook is certainly a primitive, but one that I would really not want people to use apart from some special debugging/logging use-cases (most should be doable by subclassing existing strategies and overriding generic_call). Hence, I strongly believe exposing it in order to eliminate the convenience functions of trace and replay is not the way to go. Moreover, the number of imports and classes exposed within the code is something I think should be avoided lest we start looking like Tensorflow's early days where writing anything simple felt like writing Java in the nano editor -

from atlas.tracing import DefaultTracer

@generator
def func(...):
       ....

tracer = DefaultTracer()
for res in func.env(hooks=[tracer]).generate():
       # Some computation with res...
       trace = tracer.get_last_trace()
       # Some computation with trace

as compared to

@generator
def func(...):
       ....

for res, trace in func.env(tracing=True).generate():
      # Some computation with res ...
      # Some computation with trace...

Given that tracing and replaying are going to used widely in our generators for synthesis (maybe even testing) it makes sense to have wrappers for them.

(e) Regarding models, you are right that they are indeed an argument to strategies. My concern is that not having a single interface (through the Generator object) would force users to explicitly create the DfsStrategy object or the RandStrategy object and then set the model which I believe is error-prone and verbose. Primarily because the assignment and/or error-checking can happen under the hood. As an example, consider the two snippets for running the generator in two different modes -

@generator
def func():
       ....

for res in func.env(model=SomeFancyModel()).generate():
       print(res)

for res in func.env(model=SomeOtherBaselineModel()).generate():
       print(res)
from atlas.strategies import DfsStrategy

@generator
def func():
      ...

s = DfsStrategy()
func.set_default_strategy(s)

s.set_model(SomeFancyModel())

for res in func.generate():
      print(res)

s.set_model(SomeOtherBaselineModel())
for res in func.generate():
     print(res)

Another point to consider as we move forward is that we may have a lot more "in-built" strategies that we can offer via use of simple strings (as is the case for "dfs" and "randomized" currently as follows -

@generator(strategy='randomized')
def func(...):
      ....

in which case, exposing another interface via the Strategy class seems a bit unusual to me. In any case, I may be inaccurate in my line of thought here and I'd really appreciate more feedback on this.

from atlas.

merrymercy avatar merrymercy commented on June 10, 2024
(b) Regarding the second, I'm not sure if we are gaining anything here - the separation of function arguments and generator arguments is being lost without much improvement in clarity or verbosity.

Actually ALT2 is my favorite. We do gain clairty by removing the concept of env and simplicity by only doing one function call. If env is not global and only affects its next 'generate' or 'call', we can hide it. In addition, this api form is common in other python libraries (thread, multiprocessing).


(e) Regarding models, you are right that they are indeed an argument to strategies. My concern is ... 

For your example, I will do

from atlas import generator, DfsStrategy

@generator
def func():
      ...

for res in func.env(strategy=DfdStrategy(SomeFancyModel())).generate():
       print(res)

for res in func.env(strategy=DFSStrategy(SomeOtherBaselineModel())).generate():
       print(res)

The same number of lines, but more clear hierarchy.

from atlas.

rbavishi avatar rbavishi commented on June 10, 2024

(a) I didn't see that you were passing args and not *args. You are right that this approach is prevalent in libraries like multiprocessing. I have a few concerns though -

  1. This strongly reinforces the concept of this being a wrapper of sorts around the original concept which I personally would like to stay away from.

  2. This is not language cross-compatible.

  3. It loses the 'natural' calling convention of func.generate(a, b=c, d=e) as opposed to func.generate(args=(a), kwargs={'b': c, 'd': e}).

(b) Fair point. Let me think it through.

from atlas.

Related Issues (1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.