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

Add Study.study_name #157

Merged
merged 25 commits into from
Sep 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8c65be2
Add study_name attribute to Study.
toshihikoyanase Aug 13, 2018
cbd26db
Add --name option to create-study subcommand of CLI.
toshihikoyanase Aug 13, 2018
21de4e0
Remove an unused variable.
toshihikoyanase Aug 13, 2018
45aa758
Merge branch 'master' into add-study-name
toshihikoyanase Aug 15, 2018
89030d5
Replace 'None' with a empty string when study_name is None.
toshihikoyanase Aug 15, 2018
dd4951a
Rmove an unused argument. Fix a comment.
toshihikoyanase Aug 15, 2018
b927a20
Add a test case to check default value of study_name.
toshihikoyanase Aug 15, 2018
751fd5b
Fix an assertion of empty string.
toshihikoyanase Aug 15, 2018
f2f8ae7
Update explanation of a CLI argument.
toshihikoyanase Aug 15, 2018
00d679f
Raise ValueError when study_name already exists.
toshihikoyanase Aug 15, 2018
8787c6f
Change type of StudyModel.study_name from Optional[str] to str.
toshihikoyanase Aug 17, 2018
bc2e58a
Add --study_name option to pfnopt minimize command.
toshihikoyanase Aug 17, 2018
b11925f
Add tests of study_name to test_cli.py.
toshihikoyanase Aug 17, 2018
cf1d89d
Remove inappropriate None-check.
toshihikoyanase Aug 22, 2018
55441c4
Replace --study_name with --study-name to keep consistency of options.
toshihikoyanase Aug 22, 2018
2eca0af
Use StorageSupplier to provide storages for unit tests.
toshihikoyanase Aug 22, 2018
5163fc5
Add a TODO comment to improve code quality.
toshihikoyanase Aug 22, 2018
82614b8
Remove redundant none checking.
toshihikoyanase Aug 23, 2018
dab3061
Use StorageSupplier in test_create_new_study_id_with_name.
toshihikoyanase Aug 23, 2018
eb1bd2f
Merge master to add-study-name.
toshihikoyanase Sep 7, 2018
6037645
Fix a comment.
toshihikoyanase Sep 11, 2018
dfb05b3
Merge branch 'master' into add-study-name.
toshihikoyanase Sep 12, 2018
11c8975
fixup! Merge branch 'master' into add-study-name.
toshihikoyanase Sep 12, 2018
728f45d
Remove --study-name argument from 'pfnopt minimize'.
toshihikoyanase Sep 13, 2018
d0202c3
Merge branch 'master' into add-study-name.
toshihikoyanase Sep 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions pfnopt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ def get_parser(self, prog_name):
# type: (str) -> ArgumentParser

parser = super(CreateStudy, self).get_parser(prog_name)
parser.add_argument('--study-name', default=None,
help='A human-readable name of a study to distinguish it from others.')
return parser

def take_action(self, parsed_args):
Expand All @@ -55,7 +57,7 @@ def take_action(self, parsed_args):
config = pfnopt.config.load_pfnopt_config(self.app_args.config)
storage_url = get_storage_url(self.app_args.storage, config)
storage = pfnopt.storages.RDBStorage(storage_url)
study_uuid = pfnopt.create_study(storage).study_uuid
study_uuid = pfnopt.create_study(storage, study_name=parsed_args.study_name).study_uuid
print(study_uuid)


Expand Down Expand Up @@ -84,7 +86,7 @@ def take_action(self, parsed_args):
class Studies(Lister):

_datetime_format = '%Y-%m-%d %H:%M:%S'
_study_list_header = ('UUID', 'TASK', 'N_TRIALS', 'DATETIME_START')
_study_list_header = ('UUID', 'NAME', 'TASK', 'N_TRIALS', 'DATETIME_START')

def get_parser(self, prog_name):
# type: (str) -> ArgumentParser
Expand All @@ -103,7 +105,7 @@ def take_action(self, parsed_args):
for s in summaries:
start = s.datetime_start.strftime(self._datetime_format) \
if s.datetime_start is not None else None
row = (s.study_uuid, s.task.name, s.n_trials, start)
row = (s.study_uuid, s.study_name, s.task.name, s.n_trials, start)
rows.append(row)

return self._study_list_header, tuple(rows)
Expand Down
18 changes: 16 additions & 2 deletions pfnopt/storages/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@
from pfnopt import distributions # NOQA
from pfnopt import structs # NOQA

DEFAULT_STUDY_NAME_PREFIX = 'no-name-'


@six.add_metaclass(abc.ABCMeta)
class BaseStorage(object):

# Basic study manipulation

@abc.abstractmethod
def create_new_study_id(self):
# type: () -> int
def create_new_study_id(self, study_name=None):
# type: (Optional[str]) -> int

raise NotImplementedError

Expand Down Expand Up @@ -55,6 +57,18 @@ def get_study_uuid_from_id(self, study_id):

raise NotImplementedError

@abc.abstractmethod
def get_study_id_from_name(self, study_name):
# type: (str) -> int

raise NotImplementedError

@abc.abstractmethod
def get_study_name_from_id(self, study_id):
# type: (int) -> str

raise NotImplementedError

@ abc.abstractmethod
def get_study_task(self, study_id):
# type: (int) -> structs.StudyTask
Expand Down
24 changes: 22 additions & 2 deletions pfnopt/storages/in_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from pfnopt import distributions # NOQA
from pfnopt.storages import base
from pfnopt.storages.base import DEFAULT_STUDY_NAME_PREFIX
from pfnopt import structs


Expand All @@ -24,6 +25,7 @@ def __init__(self):
self.task = structs.StudyTask.NOT_SET
self.study_user_attrs = {} # type: Dict[str, Any]
self.study_system_attrs = {} # type: Dict[str, Any]
self.study_name = DEFAULT_STUDY_NAME_PREFIX + IN_MEMORY_STORAGE_STUDY_UUID # type: str

self._lock = threading.Lock()

Expand All @@ -38,8 +40,11 @@ def __setstate__(self, state):
self.__dict__.update(state)
self._lock = threading.Lock()

def create_new_study_id(self):
# type: () -> int
def create_new_study_id(self, study_name=None):
# type: (Optional[str]) -> int

if study_name is not None:
self.study_name = study_name

return IN_MEMORY_STORAGE_STUDY_ID # TODO(akiba)

Expand Down Expand Up @@ -76,6 +81,20 @@ def get_study_uuid_from_id(self, study_id):
self._check_study_id(study_id)
return IN_MEMORY_STORAGE_STUDY_UUID

def get_study_id_from_name(self, study_name):
# type: (str) -> int

if study_name != self.study_name:
raise ValueError("No such study {}.".format(study_name))

return IN_MEMORY_STORAGE_STUDY_ID

def get_study_name_from_id(self, study_id):
# type: (int) -> str

self._check_study_id(study_id)
return self.study_name

def get_study_task(self, study_id):
# type: (int) -> structs.StudyTask

Expand Down Expand Up @@ -112,6 +131,7 @@ def get_all_study_summaries(self):
return [structs.StudySummary(
study_id=IN_MEMORY_STORAGE_STUDY_ID,
study_uuid=IN_MEMORY_STORAGE_STUDY_UUID,
study_name=self.study_name,
task=self.task,
best_trial=best_trial,
user_attrs=copy.deepcopy(self.study_user_attrs),
Expand Down
21 changes: 20 additions & 1 deletion pfnopt/storages/rdb/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from pfnopt.structs import StudyTask
from pfnopt.structs import TrialState

SCHEMA_VERSION = 7
SCHEMA_VERSION = 8
MAX_ATTR_LENGTH = 2048
NOT_FOUND_MSG = 'Record does not exist.'

Expand All @@ -29,6 +29,7 @@ class StudyModel(BaseModel):
__tablename__ = 'studies'
study_id = Column(Integer, primary_key=True)
study_uuid = Column(String(255), unique=True)
study_name = Column(String(255), unique=True, nullable=False)
task = Column(Enum(StudyTask), nullable=False)

@classmethod
Expand Down Expand Up @@ -67,6 +68,24 @@ def find_or_raise_by_uuid(cls, study_uuid, session):

return study

@classmethod
def find_by_name(cls, study_name, session):
# type: (str, orm.Session) -> Optional[StudyModel]

study = session.query(cls).filter(cls.study_name == study_name).one_or_none()

return study

@classmethod
def find_or_raise_by_name(cls, study_name, session):
# type: (str, orm.Session) -> StudyModel

study = cls.find_by_name(study_name, session)
if study is None:
raise ValueError(NOT_FOUND_MSG)

return study

@classmethod
def all(cls, session):
# type: (orm.Session) -> List[StudyModel]
Expand Down
34 changes: 30 additions & 4 deletions pfnopt/storages/rdb/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from pfnopt import distributions
from pfnopt import logging
from pfnopt.storages.base import BaseStorage
from pfnopt.storages.base import DEFAULT_STUDY_NAME_PREFIX
from pfnopt.storages.rdb import models
from pfnopt import structs
from pfnopt import version
Expand All @@ -42,8 +43,8 @@ def __init__(self, url, connect_args=None):
self._check_table_schema_compatibility()
self.logger = logging.get_logger(__name__)

def create_new_study_id(self):
# type: () -> int
def create_new_study_id(self, study_name=None):
# type: (Optional[str]) -> int

session = self.scoped_session()

Expand All @@ -53,9 +54,15 @@ def create_new_study_id(self):
if study is None:
break

study = models.StudyModel(study_uuid=study_uuid, task=structs.StudyTask.NOT_SET)
if study_name is None:
study_name = DEFAULT_STUDY_NAME_PREFIX + study_uuid

study = models.StudyModel(study_uuid=study_uuid, study_name=study_name,
task=structs.StudyTask.NOT_SET)
session.add(study)
self._commit(session)
if not self._commit_with_integrity_check(session):
raise ValueError(
"study_name {} already exists. Please use a different name.".format(study_name))

self.logger.info('A new study created with UUID: {}'.format(study.study_uuid))

Expand Down Expand Up @@ -127,6 +134,24 @@ def get_study_uuid_from_id(self, study_id):

return study.study_uuid

def get_study_id_from_name(self, study_name):
# type: (str) -> int

session = self.scoped_session()

study = models.StudyModel.find_or_raise_by_name(study_name, session)

return study.study_id

def get_study_name_from_id(self, study_id):
# type: (int) -> str

session = self.scoped_session()

study = models.StudyModel.find_or_raise_by_id(study_id, session)

return study.study_name

def get_study_task(self, study_id):
# type: (int) -> structs.StudyTask

Expand Down Expand Up @@ -211,6 +236,7 @@ def get_all_study_summaries(self):
study_sumarries.append(structs.StudySummary(
study_id=study_model.study_id,
study_uuid=study_model.study_uuid,
study_name=study_model.study_name,
task=self.get_study_task(study_model.study_id),
best_trial=best_trial,
user_attrs=self.get_study_user_attrs(study_model.study_id),
Expand Down
1 change: 1 addition & 0 deletions pfnopt/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class FrozenTrial(
'StudySummary',
[('study_id', int),
('study_uuid', str),
('study_name', str),
('task', StudyTask),
('best_trial', Optional[FrozenTrial]),
('user_attrs', Dict[str, Any]),
Expand Down
5 changes: 4 additions & 1 deletion pfnopt/study.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ def create_study(
storage=None, # type: Union[None, str, storages.BaseStorage]
sampler=None, # type: samplers.BaseSampler
pruner=None, # type: pruners.BasePruner
study_name=None, # type: Optional[str]
):
# type: (...) -> Study

Expand All @@ -317,14 +318,16 @@ def create_study(
Sampler object that implements background algorithm for value suggestion.
pruner:
Pruner object that decides early stopping of unpromising trials.
study_name:
A human-readable name of a study.

Returns:
A study object.

"""

storage = storages.get_storage(storage)
study_uuid = storage.get_study_uuid_from_id(storage.create_new_study_id())
study_uuid = storage.get_study_uuid_from_id(storage.create_new_study_id(study_name))
return Study(study_uuid=study_uuid, storage=storage, sampler=sampler, pruner=pruner)


Expand Down
26 changes: 13 additions & 13 deletions tests/storages_tests/rdb_tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class TestStudySystemAttributeModel(object):

@staticmethod
def test_find_by_study_and_key(session):
study = StudyModel(study_id=1)
study = StudyModel(study_id=1, study_name='test-study')
session.add(StudySystemAttributeModel(study_id=study.study_id, key='sample-key',
value_json='1'))
session.commit()
Expand All @@ -40,8 +40,8 @@ def test_find_by_study_and_key(session):

@staticmethod
def test_where_study_id(session):
sample_study = StudyModel(study_id=1)
empty_study = StudyModel(study_id=2)
sample_study = StudyModel(study_id=1, study_name='test-study')
empty_study = StudyModel(study_id=2, study_name='test-study')

session.add(StudySystemAttributeModel(study_id=sample_study.study_id, key='sample-key',
value_json='1'))
Expand Down Expand Up @@ -73,8 +73,8 @@ def test_default_datetime(session):
def test_count(session):
# type: (Session) -> None

study_1 = StudyModel(study_id=1)
study_2 = StudyModel(study_id=2)
study_1 = StudyModel(study_id=1, study_name='test-study-1')
study_2 = StudyModel(study_id=2, study_name='test-study-2')

session.add(TrialModel(study_id=study_1.study_id, state=TrialState.COMPLETE))
session.add(TrialModel(study_id=study_1.study_id, state=TrialState.RUNNING))
Expand All @@ -92,7 +92,7 @@ class TestTrialUserAttributeModel(object):
def test_find_by_trial_and_key(session):
# type: (Session) -> None

study = StudyModel(study_id=1)
study = StudyModel(study_id=1, study_name='test-study')
trial = TrialModel(study_id=study.study_id)

session.add(TrialUserAttributeModel(trial_id=trial.trial_id, key='sample-key',
Expand All @@ -108,7 +108,7 @@ def test_find_by_trial_and_key(session):
def test_where_study(session):
# type: (Session) -> None

study = StudyModel(study_id=1, task=StudyTask.MINIMIZE)
study = StudyModel(study_id=1, study_name='test-study', task=StudyTask.MINIMIZE)
trial = TrialModel(trial_id=1, study_id=study.study_id, state=TrialState.COMPLETE)

session.add(study)
Expand All @@ -126,7 +126,7 @@ def test_where_study(session):
def test_where_trial(session):
# type: (Session) -> None

study = StudyModel(study_id=1, task=StudyTask.MINIMIZE)
study = StudyModel(study_id=1, study_name='test-study', task=StudyTask.MINIMIZE)
trial = TrialModel(trial_id=1, study_id=study.study_id, state=TrialState.COMPLETE)

session.add(TrialUserAttributeModel(trial_id=trial.trial_id, key='sample-key',
Expand All @@ -142,7 +142,7 @@ def test_where_trial(session):
def test_all(session):
# type: (Session) -> None

study = StudyModel(study_id=1, task=StudyTask.MINIMIZE)
study = StudyModel(study_id=1, study_name='test-study', task=StudyTask.MINIMIZE)
trial = TrialModel(trial_id=1, study_id=study.study_id, state=TrialState.COMPLETE)

session.add(TrialUserAttributeModel(trial_id=trial.trial_id, key='sample-key',
Expand All @@ -161,7 +161,7 @@ class TestTrialSystemAttributeModel(object):
def test_find_by_trial_and_key(session):
# type: (Session) -> None

study = StudyModel(study_id=1)
study = StudyModel(study_id=1, study_name='test-study')
trial = TrialModel(study_id=study.study_id)

session.add(TrialSystemAttributeModel(trial_id=trial.trial_id, key='sample-key',
Expand All @@ -177,7 +177,7 @@ def test_find_by_trial_and_key(session):
def test_where_study(session):
# type: (Session) -> None

study = StudyModel(study_id=1, task=StudyTask.MINIMIZE)
study = StudyModel(study_id=1, study_name='test-study', task=StudyTask.MINIMIZE)
trial = TrialModel(trial_id=1, study_id=study.study_id, state=TrialState.COMPLETE)

session.add(study)
Expand All @@ -195,7 +195,7 @@ def test_where_study(session):
def test_where_trial(session):
# type: (Session) -> None

study = StudyModel(study_id=1, task=StudyTask.MINIMIZE)
study = StudyModel(study_id=1, study_name='test-study', task=StudyTask.MINIMIZE)
trial = TrialModel(trial_id=1, study_id=study.study_id, state=TrialState.COMPLETE)

session.add(TrialSystemAttributeModel(trial_id=trial.trial_id, key='sample-key',
Expand All @@ -211,7 +211,7 @@ def test_where_trial(session):
def test_all(session):
# type: (Session) -> None

study = StudyModel(study_id=1, task=StudyTask.MINIMIZE)
study = StudyModel(study_id=1, study_name='test-study', task=StudyTask.MINIMIZE)
trial = TrialModel(trial_id=1, study_id=study.study_id, state=TrialState.COMPLETE)

session.add(TrialSystemAttributeModel(trial_id=trial.trial_id, key='sample-key',
Expand Down
Loading