Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for dynamics randomization #61

Closed
ryanjulian opened this issue May 15, 2018 · 5 comments
Closed

Support for dynamics randomization #61

ryanjulian opened this issue May 15, 2018 · 5 comments
Assignees
Labels
big big multi-feature projects feature

Comments

@ryanjulian
Copy link
Owner

https://blog.openai.com/generalizing-from-simulation/

We should probably not attempt this until #4 is done.

For now, only MuJoCo support is necessary. If MuJoCo is too burdensome, we can consider switching engines (e.g. Bullet)

Related issue openai/mujoco-py#148 suggests this may be nontrivial.

@ryanjulian ryanjulian added this to the Week of May 21 milestone May 15, 2018
@ryanjulian ryanjulian self-assigned this May 21, 2018
@ryanjulian ryanjulian added feature big big multi-feature projects labels May 23, 2018
@ryanjulian
Copy link
Owner Author

Here's my proof of concept for a simple XPath-based implementation.

Immediate observations

  • XPath works great. There's no need for anything more clever.
  • There's an apparent 100% overhead to mutating the model in this way if you're only running it for ~1000 steps between mutations (profile to follow). It's not clear what this translates into for a real rllab run, since I'm not sure how much time the sampler actually spends in MuJoCo
  • The dict style of defining the variants get's tiresome and hard to read quickly, we should probably make a fluent interface for specifying them
  • Multi-element attributes (e.g. size) present a challenge
  • We will might want support for different methods of choosing variants (e.g. random multiplier on the default vs absolute) and different distributions (e.g. at least gaussian and uniform)

Benchmark results (MacBook Pro w/ 2 Core i5)

(venv) kolmogorov:mjtest ryan$ time python bench.py

real	0m21.990s
user	0m20.750s
sys	0m0.786s
(venv) kolmogorov:mjtest ryan$ time python no_mutation.py

real	0m11.601s
user	0m11.401s
sys	0m0.154s

Code

XPath Implementation

#!/usr/bin/env python3
"""
Benchmark model mutation for dynamics randomization
"""
import os
import os.path as osp
import xml.etree.ElementTree as ET

import numpy as np
from mujoco_py import load_model_from_xml
from mujoco_py import MjSim
from mujoco_py import MjViewer

MUJOCO_PY_PATH = "/Users/ryan/code/mujoco-py/"
TOSSER_XML = osp.join(MUJOCO_PY_PATH, "xmls/tosser.xml")

# Load original model text into memory
tosser = ET.parse(TOSSER_XML)

variants = {
    "a1": {
        "xpath": ".//motor[@name='a1']",
        "elem": None,
        "attrib": "gear",
        "default": None,
        "method": "coefficient",
        "distribution": "uniform",
        "range": (0.5, 1.5),
    },
    "a2": {
        "xpath": ".//motor[@name='a2']",
        "elem": None,
        "attrib": "gear",
        "default": None,
        "method": "coefficient",
        "distribution": "uniform",
        "range": (0.5, 1.5),
    },
    "wr_js": {
        "xpath": ".//joint[@name='wr_js']",
        "elem": None,
        "attrib": "damping",
        "default": None,
        "method": "absolute",
        "distribution": "uniform",
        "range": (5, 15),
    },
}

# Retrieve defaults and cache etree elems
for k, v in variants.items():
    e = tosser.find(v["xpath"])
    v["elem"] = e
    v["default"] = float(e.attrib[v["attrib"]])

for _ in range(1000):

    # Mutate model randomly
    for k, v in variants.items():
        e = v["elem"]
        
        if v["method"] == "coefficient":
            c = np.random.uniform(low=v["range"][0], high=v["range"][1])
            e.attrib[v["attrib"]] = str(c * v["default"])
        elif v["method"] == "absolute":
            c = np.random.uniform(low=v["range"][0], high=v["range"][1])
            e.attrib[v["attrib"]] = str(c)
        else:
            raise NotImplementedError("Unknown method")

    # Reify model
    model_xml = ET.tostring(tosser.getroot()).decode("ascii")

    # Run model loop
    model = load_model_from_xml(model_xml)
    sim = MjSim(model)
    #viewer = MjViewer(sim)

    #sim_state = sim.get_state()


    #sim.set_state(sim_state)

    for i in range(1000):
        if i < 150:
            sim.data.ctrl[:] = 0.0
        else:
            sim.data.ctrl[:] = -1.0
        sim.step()
        #viewer.render()

Baseline without mutation

#!/usr/bin/env python3
"""
Benchmark model mutation for dynamics randomization

No mutation baseline.
"""
import os.path as osp

from mujoco_py import load_model_from_path
from mujoco_py import MjSim
from mujoco_py import MjViewer

MUJOCO_PY_PATH = "/Users/ryan/code/mujoco-py/"
TOSSER_XML = osp.join(MUJOCO_PY_PATH, "xmls/tosser.xml")

# Load model
model = load_model_from_path(TOSSER_XML)
sim = MjSim(model)
#viewer = MjViewer(sim)

sim_state = sim.get_state()

# Model loop
for _ in range(1000):
    
    sim.set_state(sim_state)

    for i in range(1000):
        if i < 150:
            sim.data.ctrl[:] = 0.0
        else:
            sim.data.ctrl[:] = -1.0
        sim.step()
        #viewer.render()

@ryanjulian
Copy link
Owner Author

Profiler Results

The overhead is spread out between elements:

  • 5s of MuJoCo loading the new model (this could get worse with larger models)
  • 2.8s in NumPy (surprising!)
  • 3.5s modifying/writing XML, mostly in serializing the XML to text

I speculate the that NumPy portions can probably be optimized to be negligible or removed entirely. Python's XML implementation is known to be non-optimal, and people looking for performance usually use lxml.

The MuJoCo portions are a black box and probably not directly optimizable. For this I have 3 ideas:

  1. ignore it
  2. pipeline the mutation and loading of new mujoco sims into different threads
  3. use MjSimPool and gradually change the population of the pool over time. This only works if the overhead of changing the MjSimPool is negligible (also OpenAI just removed MjSimPool).

with mutation

(venv) kolmogorov:mjtest ryan$ python -m cProfile -s cumulative bench.py | head -40
         5534300 function calls (5476484 primitive calls) in 22.939 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    317/1    0.010    0.000   22.940   22.940 {built-in method builtins.exec}
        1    0.001    0.001   22.940   22.940 bench.py:4(<module>)
        1    3.297    3.297   22.403   22.403 bench.py:46(main)
  1000000   11.910    0.000   11.910    0.000 {method 'step' of 'mujoco_py.cymj.MjSim' objects}
     1000    4.195    0.004    5.034    0.005 {mujoco_py.cymj.load_model_from_xml}
   837000    0.173    0.000    1.507    0.000 numeric.py:424(asarray)
   837076    1.251    0.000    1.335    0.000 {built-in method numpy.core.multiarray.array}
     1000    0.010    0.000    1.006    0.001 ElementTree.py:1119(tostring)
     1000    0.010    0.000    0.994    0.001 ElementTree.py:720(write)
       17    0.000    0.000    0.862    0.051 __init__.py:1(<module>)
51000/1000    0.321    0.000    0.690    0.001 ElementTree.py:898(_serialize_xml)
    357/4    0.002    0.000    0.536    0.134 <frozen importlib._bootstrap>:966(_find_and_load)
    357/4    0.001    0.000    0.536    0.134 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
    335/6    0.001    0.000    0.535    0.089 <frozen importlib._bootstrap>:651(_load_unlocked)
    286/6    0.001    0.000    0.535    0.089 <frozen importlib._bootstrap_external>:672(exec_module)
    470/5    0.000    0.000    0.535    0.107 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
   400/44    0.000    0.000    0.348    0.008 {built-in method builtins.__import__}
     1000    0.007    0.000    0.243    0.000 tempfile.py:522(NamedTemporaryFile)
        1    0.000    0.000    0.240    0.240 builder.py:1(<module>)
     1000    0.114    0.000    0.216    0.000 ElementTree.py:837(_namespaces)
     1000    0.009    0.000    0.201    0.000 tempfile.py:249(_mkstemp_inner)
   359000    0.161    0.000    0.189    0.000 {method 'write' of '_io.TextIOWrapper' objects}
 1301/350    0.001    0.000    0.170    0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
     1000    0.003    0.000    0.140    0.000 tempfile.py:500(__exit__)
        4    0.000    0.000    0.138    0.034 __init__.py:15(<module>)
     1001    0.135    0.000    0.135    0.000 {built-in method posix.open}
  326/299    0.001    0.000    0.134    0.000 <frozen importlib._bootstrap>:564(module_from_spec)
     1000    0.133    0.000    0.133    0.000 {method '__exit__' of '_io._IOBase' objects}
947606/947605    0.126    0.000    0.132    0.000 {built-in method builtins.isinstance}
        1    0.000    0.000    0.127    0.127 mjviewer.py:1(<module>)
    36/30    0.000    0.000    0.127    0.004 <frozen importlib._bootstrap_external>:919(create_module)
    36/30    0.056    0.002    0.127    0.004 {built-in method _imp.create_dynamic}
        1    0.000    0.000    0.116    0.116 __init__.py:106(<module>)
        1    0.000    0.000    0.113    0.113 Distutils.py:1(<module>)
        1    0.000    0.000    0.113    0.113 build_ext.py:1(<module>)

no mutation

(venv) kolmogorov:mjtest ryan$ python -m cProfile -s cumulative no_mutation.py | head -40
         1510688 function calls (1502989 primitive calls) in 11.571 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    313/1    0.010    0.000   11.572   11.572 {built-in method builtins.exec}
        1    0.001    0.001   11.572   11.572 no_mutation.py:6(<module>)
        1    0.959    0.959   11.016   11.016 no_mutation.py:17(main)
  1000000   10.025    0.000   10.025    0.000 {method 'step' of 'mujoco_py.cymj.MjSim' objects}
       16    0.001    0.000    0.983    0.061 __init__.py:1(<module>)
    352/1    0.002    0.000    0.555    0.555 <frozen importlib._bootstrap>:966(_find_and_load)
    352/1    0.001    0.000    0.555    0.555 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
    330/1    0.001    0.000    0.554    0.554 <frozen importlib._bootstrap>:651(_load_unlocked)
    282/1    0.001    0.000    0.554    0.554 <frozen importlib._bootstrap_external>:672(exec_module)
    462/1    0.000    0.000    0.554    0.554 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
        1    0.000    0.000    0.378    0.378 builder.py:1(<module>)
   397/42    0.000    0.000    0.339    0.008 {built-in method builtins.__import__}
 1298/382    0.001    0.000    0.163    0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
  321/294    0.001    0.000    0.140    0.000 <frozen importlib._bootstrap>:564(module_from_spec)
        4    0.000    0.000    0.139    0.035 __init__.py:15(<module>)
    35/30    0.000    0.000    0.132    0.004 <frozen importlib._bootstrap_external>:919(create_module)
    35/30    0.061    0.002    0.132    0.004 {built-in method _imp.create_dynamic}
        1    0.000    0.000    0.128    0.128 mjviewer.py:1(<module>)
        1    0.000    0.000    0.110    0.110 Distutils.py:1(<module>)
        1    0.000    0.000    0.110    0.110 __init__.py:6(<module>)
        1    0.000    0.000    0.110    0.110 build_ext.py:1(<module>)
        1    0.000    0.000    0.108    0.108 util.py:6(<module>)
        1    0.000    0.000    0.107    0.107 __init__.py:16(<module>)
        1    0.000    0.000    0.106    0.106 old_build_ext.py:7(<module>)
        1    0.000    0.000    0.106    0.106 __init__.py:106(<module>)
        3    0.000    0.000    0.100    0.033 old_build_ext.py:28(_check_stack)
        3    0.000    0.000    0.100    0.033 inspect.py:1464(getouterframes)
      162    0.000    0.000    0.100    0.001 inspect.py:1425(getframeinfo)
  441/162    0.001    0.000    0.098    0.001 inspect.py:680(getsourcefile)
      114    0.019    0.000    0.095    0.001 inspect.py:714(getmodule)
        1    0.000    0.000    0.084    0.084 add_newdocs.py:10(<module>)
  284/272    0.000    0.000    0.070    0.000 <frozen importlib._bootstrap_external>:393(_check_name_wrapper)
        2    0.000    0.000    0.070    0.035 <frozen importlib._bootstrap>:674(_load)
        1    0.000    0.000    0.070    0.070 builder.py:43(load_cython_ext)
        1    0.000    0.000    0.070    0.070 builder.py:103(load_dynamic_ext)

@ryanjulian
Copy link
Owner Author

Updated profiler results

I increased the runtime by 5x to chase out fixed overhead like imports. I was using my machine for other stuff while running these, which explains the variance in results.

Conclusions:

  • lxml is definitely faster than Python's xml implementation and it's basically free to use, so we might as well.
  • Increasing the runtime makes it abundantly clear that loading the model into MuJoCo is the major bottleneck
  • What I thought was numpy overhead was actually mujoco-py creating a numpy interface for the model, so I've merged that into the tally for the MuJoCo loading step

I would be curious to see how a multithreaded implementation shakes out, since I'm not sure what synchronization is inside MuJoCo. If there is no locking overhead, in principle you could create an n-length queue with a mutator module as the source and the environment as the sink. Then the implementations would be like.

Mutator:

q = collections.dequeue(10)
while select(not q.is_full()):
    q.push(make_new_mutation())

Dynamics Randomization Environment:

class MuJoCoDynamicsRandomizationEnv:
    
    def reset():
        self._sim.close()
        self._sim = q.pop()
        self._sim.reset()

Profiler results

replace xml with lxml

  • 62s MuJoCo steps
  • 38s MuJoCo loading
  • 4.3s XML
(venv) kolmogorov:mjtest ryan$ python -m cProfile -s cumulative bench_lxml_nonumpy.py | head -40
         14762814 function calls (14754802 primitive calls) in 111.095 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    314/1    0.010    0.000  111.095  111.095 {built-in method builtins.exec}
        1    0.001    0.001  111.095  111.095 bench_lxml_nonumpy.py:4(<module>)
        1   18.594   18.594  110.554  110.554 bench_lxml_nonumpy.py:47(main)
  5000000   61.572    0.000   61.572    0.000 {method 'step' of 'mujoco_py.cymj.MjSim' objects}
     5000   20.672    0.004   24.982    0.005 {mujoco_py.cymj.load_model_from_xml}
  4185000    0.950    0.000    7.177    0.000 numeric.py:424(asarray)
  4185076    5.785    0.000    6.227    0.000 {built-in method numpy.core.multiarray.array}
     5000    0.038    0.000    1.440    0.000 tempfile.py:522(NamedTemporaryFile)
     5000    0.052    0.000    1.213    0.000 tempfile.py:249(_mkstemp_inner)
     5001    0.833    0.000    0.833    0.000 {built-in method posix.open}
       16    0.000    0.000    0.826    0.052 __init__.py:1(<module>)
     5000    0.013    0.000    0.565    0.000 tempfile.py:500(__exit__)
    359/4    0.002    0.000    0.541    0.135 <frozen importlib._bootstrap>:966(_find_and_load)
    359/4    0.001    0.000    0.541    0.135 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
    333/4    0.001    0.000    0.540    0.135 <frozen importlib._bootstrap>:651(_load_unlocked)
    469/4    0.000    0.000    0.540    0.135 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
     5000    0.533    0.000    0.533    0.000 {method '__exit__' of '_io._IOBase' objects}
    283/5    0.001    0.000    0.527    0.105 <frozen importlib._bootstrap_external>:672(exec_module)
     5000    0.027    0.000    0.442    0.000 _internal.py:447(_dtype_from_pep3118)
   399/43    0.000    0.000    0.357    0.008 {built-in method builtins.__import__}
    10000    0.005    0.000    0.244    0.000 tempfile.py:481(func_wrapper)
6126/6067    0.176    0.000    0.240    0.000 {built-in method builtins.__build_class__}
        1    0.000    0.000    0.232    0.232 builder.py:1(<module>)
     5000    0.137    0.000    0.231    0.000 _internal.py:490(__dtype_from_pep3118)
     5000    0.230    0.000    0.230    0.000 {method 'flush' of '_io.BufferedRandom' objects}
    10000    0.051    0.000    0.190    0.000 tempfile.py:473(__getattr__)
 1308/316    0.001    0.000    0.187    0.001 <frozen importlib._bootstrap>:997(_handle_fromlist)
     5001    0.012    0.000    0.182    0.000 {built-in method builtins.next}
     5001    0.026    0.000    0.170    0.000 tempfile.py:157(__next__)
  324/284    0.001    0.000    0.157    0.001 <frozen importlib._bootstrap>:564(module_from_spec)
    37/29    0.000    0.000    0.151    0.005 <frozen importlib._bootstrap_external>:919(create_module)
    37/29    0.061    0.002    0.150    0.005 {built-in method _imp.create_dynamic}
        4    0.000    0.000    0.135    0.034 __init__.py:15(<module>)
     5006    0.127    0.000    0.127    0.000 {built-in method io.open}
        1    0.000    0.000    0.125    0.125 mjviewer.py:1(<module>)

naive implementation

  • 60s MuJoCo steps
  • 40s MuJoCo loading
  • 20s XML
(venv) kolmogorov:mjtest ryan$ python -m cProfile -s cumulative bench.py | head -40
         25666109 function calls (25408293 primitive calls) in 115.223 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    317/1    0.010    0.000  115.224  115.224 {built-in method builtins.exec}
        1    0.001    0.001  115.224  115.224 bench.py:4(<module>)
        1   17.506   17.506  114.674  114.674 bench.py:46(main)
  5000000   60.450    0.000   60.450    0.000 {method 'step' of 'mujoco_py.cymj.MjSim' objects}
     5000   21.251    0.004   25.600    0.005 {mujoco_py.cymj.load_model_from_xml}
  4185000    0.879    0.000    7.764    0.000 numeric.py:424(asarray)
  4185076    6.462    0.000    6.885    0.000 {built-in method numpy.core.multiarray.array}
     5000    0.050    0.000    5.139    0.001 ElementTree.py:1119(tostring)
     5000    0.049    0.000    5.079    0.001 ElementTree.py:720(write)
255000/5000    1.648    0.000    3.542    0.001 ElementTree.py:898(_serialize_xml)
     5000    0.033    0.000    1.451    0.000 tempfile.py:522(NamedTemporaryFile)
     5000    0.047    0.000    1.256    0.000 tempfile.py:249(_mkstemp_inner)
     5000    0.580    0.000    1.097    0.000 ElementTree.py:837(_namespaces)
  1795000    0.827    0.000    0.973    0.000 {method 'write' of '_io.TextIOWrapper' objects}
     5001    0.911    0.000    0.911    0.000 {built-in method posix.open}
       17    0.000    0.000    0.866    0.051 __init__.py:1(<module>)
4483642/4483641    0.600    0.000    0.628    0.000 {built-in method builtins.isinstance}
     5000    0.013    0.000    0.582    0.000 tempfile.py:500(__exit__)
    357/4    0.002    0.000    0.552    0.138 <frozen importlib._bootstrap>:966(_find_and_load)
    357/4    0.001    0.000    0.552    0.138 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
     5000    0.551    0.000    0.551    0.000 {method '__exit__' of '_io._IOBase' objects}
    335/6    0.001    0.000    0.550    0.092 <frozen importlib._bootstrap>:651(_load_unlocked)
    286/6    0.001    0.000    0.550    0.092 <frozen importlib._bootstrap_external>:672(exec_module)
    470/5    0.000    0.000    0.547    0.109 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
    15004    0.023    0.000    0.488    0.000 {built-in method builtins.next}
     5000    0.028    0.000    0.424    0.000 _internal.py:447(_dtype_from_pep3118)
   400/44    0.000    0.000    0.354    0.008 {built-in method builtins.__import__}
   905000    0.340    0.000    0.340    0.000 ElementTree.py:1076(_escape_attrib)
    10000    0.113    0.000    0.315    0.000 ElementTree.py:785(_get_writer)
6141/6082    0.190    0.000    0.255    0.000 {built-in method builtins.__build_class__}
    10000    0.005    0.000    0.248    0.000 tempfile.py:481(func_wrapper)
        1    0.000    0.000    0.242    0.242 builder.py:1(<module>)
     5000    0.236    0.000    0.236    0.000 {method 'flush' of '_io.BufferedRandom' objects}
     5000    0.006    0.000    0.218    0.000 contextlib.py:79(__enter__)
     5000    0.117    0.000    0.197    0.000 _internal.py:490(__dtype_from_pep3118)

baseline

  • 52s MuJoCo steps
(venv) kolmogorov:mjtest ryan$ python -m cProfile -s cumulative no_mutation.py | head -40
         5571226 function calls (5563527 primitive calls) in 57.744 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    313/1    0.010    0.000   57.745   57.745 {built-in method builtins.exec}
        1    0.001    0.001   57.745   57.745 no_mutation.py:6(<module>)
        1    4.951    4.951   57.212   57.212 no_mutation.py:17(main)
  5000000   52.094    0.000   52.094    0.000 {method 'step' of 'mujoco_py.cymj.MjSim' objects}
       16    0.000    0.000    0.943    0.059 __init__.py:1(<module>)
    352/1    0.002    0.000    0.533    0.533 <frozen importlib._bootstrap>:966(_find_and_load)
    352/1    0.001    0.000    0.533    0.533 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
    330/1    0.001    0.000    0.532    0.532 <frozen importlib._bootstrap>:651(_load_unlocked)
    282/1    0.001    0.000    0.532    0.532 <frozen importlib._bootstrap_external>:672(exec_module)
    462/1    0.000    0.000    0.532    0.532 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
        1    0.000    0.000    0.355    0.355 builder.py:1(<module>)
   397/42    0.000    0.000    0.330    0.008 {built-in method builtins.__import__}
     5000    0.054    0.000    0.158    0.000 {method 'set_state' of 'mujoco_py.cymj.MjSim' objects}
 1298/382    0.001    0.000    0.153    0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
        4    0.000    0.000    0.140    0.035 __init__.py:15(<module>)
  321/294    0.001    0.000    0.132    0.000 <frozen importlib._bootstrap>:564(module_from_spec)
        1    0.000    0.000    0.129    0.129 mjviewer.py:1(<module>)
    35/30    0.000    0.000    0.125    0.004 <frozen importlib._bootstrap_external>:919(create_module)
    35/30    0.056    0.002    0.125    0.004 {built-in method _imp.create_dynamic}
        1    0.000    0.000    0.111    0.111 __init__.py:6(<module>)
        1    0.000    0.000    0.111    0.111 Distutils.py:1(<module>)
        1    0.000    0.000    0.110    0.110 build_ext.py:1(<module>)
        1    0.000    0.000    0.109    0.109 util.py:6(<module>)
        1    0.000    0.000    0.108    0.108 __init__.py:16(<module>)
        1    0.000    0.000    0.107    0.107 old_build_ext.py:7(<module>)
        3    0.000    0.000    0.101    0.034 old_build_ext.py:28(_check_stack)
        3    0.000    0.000    0.101    0.034 inspect.py:1464(getouterframes)
      162    0.000    0.000    0.100    0.001 inspect.py:1425(getframeinfo)
  441/162    0.001    0.000    0.099    0.001 inspect.py:680(getsourcefile)
        1    0.000    0.000    0.098    0.098 __init__.py:106(<module>)
      114    0.019    0.000    0.096    0.001 inspect.py:714(getmodule)
        1    0.000    0.000    0.077    0.077 add_newdocs.py:10(<module>)
  284/272    0.000    0.000    0.072    0.000 <frozen importlib._bootstrap_external>:393(_check_name_wrapper)
        1    0.000    0.000    0.071    0.071 builder.py:43(load_cython_ext)
        2    0.000    0.000    0.071    0.036 <frozen importlib._bootstrap>:674(_load)

@ryanjulian ryanjulian assigned CatherineSue and ghost and unassigned ryanjulian May 29, 2018
@CatherineSue
Copy link
Collaborator

Me and Angel discussed about the interface. There is one question we want to confirm:

How should we deal with the size value user set when it is incompatible with its shape?
For example, in tosser, .//geom[@name='obj'] has a size='.05 .075'. If a user calls VariationList().add_variation(range=(0.5, 1.5)), there are three ways to react:

  1. raise an error
  2. randomize a value according to the range, distribution and method, then apply each element of size with the same value
  3. randomize two values and apply each value to size.

Which way is better?

@ryanjulian
Copy link
Owner Author

See rlworkgroup/garage#14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
big big multi-feature projects feature
Projects
None yet
Development

No branches or pull requests

2 participants