Repository: optuna/optuna

Issue:
Stabilize `study.py`
## Motivation

In this issue, we consider to release a stable version of methods in `study.py`: `enqueue_trial`, `add_trial`, `add_trials`, and `copy_study`. For `enqueue_trial` and `copy_study`, we know we need to discuss/fix:

### Needs discussion

- [x] For `enqueue_trial`, we have to decide whether it allows to specify attributes other than `params` (e.g. `user_attrs`).
  - [updated:2021/11/28] we decide to add `user_attrs` parameter to `enqueue_trial` https://github.com/optuna/optuna/pull/3185
- [x] For `copy_study`, we need to clarify the specification when `copy_study` is invoked for a running study.
  - [updated:2021/11/28] we decide to document that `copy_study` copies a study regardless of its state (if study is in the optimization, it at the time of the call will be copied as is) #3295

### Needs fixing

- [x] An enqueued param is ignored when it is out of range of a parameter distribution #3298
  - We plan to change the behavior so that it prioritizes a enqueued param
    - current: show warning message and ignore enqueued parameter
    - desired: show warning message and use enqueued parameter
 - [x] When `enqueue_trial` and `GridSampler` are used simultaneously, parameters on a grid are overwritten by `enqueue_trial` (https://github.com/optuna/optuna/pull/2946)
   - We will change the behavior so that all parameters on a grid are used


## Description

- [x] Reach agreements about matters in `needs discussion`
- [x] Determine approaches how to fix problems in `needs fixing`
- [x] Merge PRs to reflect modifications for them
- [x] Decide if we release a stable version of each method
- [x] Stabilize methods we decide to release



Discussion:

Resolving patch:
diff --git a/optuna/study/study.py b/optuna/study/study.py
--- a/optuna/study/study.py
+++ b/optuna/study/study.py
@@ -21,7 +21,6 @@
 from optuna import trial as trial_module
 from optuna._convert_positional_args import convert_positional_args
 from optuna._deprecated import deprecated
-from optuna._experimental import experimental
 from optuna._imports import _LazyImport
 from optuna.distributions import BaseDistribution
 from optuna.study._multi_objective import _get_pareto_front_trials
@@ -831,7 +830,6 @@ def objective(trial):
 
         self._stop_flag = True
 
-    @experimental("1.2.0")
     def enqueue_trial(
         self, params: Dict[str, Any], user_attrs: Optional[Dict[str, Any]] = None
     ) -> None:
@@ -880,7 +878,6 @@ def objective(trial):
             )
         )
 
-    @experimental("2.0.0")
     def add_trial(self, trial: FrozenTrial) -> None:
         """Add trial to study.
 
@@ -946,7 +943,6 @@ def objective(trial):
 
         self._storage.create_new_trial(self._study_id, template_trial=trial)
 
-    @experimental("2.5.0")
     def add_trials(self, trials: Iterable[FrozenTrial]) -> None:
         """Add trials to study.
 
@@ -1343,7 +1339,6 @@ def objective(trial):
     storage.delete_study(study_id)
 
 
-@experimental("2.8.0")
 @convert_positional_args(
     previous_positional_arg_names=[
         "from_study_name",


Test patch:
diff --git a/tests/study_tests/test_study.py b/tests/study_tests/test_study.py
--- a/tests/study_tests/test_study.py
+++ b/tests/study_tests/test_study.py
@@ -1095,11 +1095,11 @@ def test_ask() -> None:
 def test_ask_enqueue_trial() -> None:
     study = create_study()
 
-    study.enqueue_trial({"x": 0.5}, user_attrs={"memo", "this is memo"})
+    study.enqueue_trial({"x": 0.5}, user_attrs={"memo": "this is memo"})
 
     trial = study.ask()
     assert trial.suggest_float("x", 0, 1) == 0.5
-    assert trial.user_attrs == {"memo", "this is memo"}
+    assert trial.user_attrs == {"memo": "this is memo"}
 
 
 def test_ask_fixed_search_space() -> None: