-
Notifications
You must be signed in to change notification settings - Fork 54
feat(core): add ContinuousSpace action-space primitive #927
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
base: main
Are you sure you want to change the base?
Changes from all commits
84742cb
7d68edf
bf2b690
c341433
7ac83fd
7fdae40
f4c93e3
a7c6587
822e8a3
1ecadee
6dbe05e
ee55ba4
d02769e
2437aa7
988bbaf
ec1a67d
b1cf51c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # SPDX-FileCopyrightText: NVIDIA CORPORATION & AFFILIATES | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # you may not use this file except in compliance with the License. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # You may obtain a copy of the License at | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # Unless required by applicable law or agreed to in writing, software | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # See the License for the specific language governing permissions and | ||||||||||||||||||||||||||||||||||||||||||||||||||
| # limitations under the License. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Action-space primitives for CloudAI DSE. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| CloudAI describes a tunable action space as a mapping from parameter name to | ||||||||||||||||||||||||||||||||||||||||||||||||||
| its candidate domain. Discrete parameters use a ``list`` of candidate values; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| continuous parameters use :class:`ContinuousSpace`, a closed real interval. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Agents and adapters (e.g. ``GymnasiumAdapter``) read these to build their own | ||||||||||||||||||||||||||||||||||||||||||||||||||
| action representation and to decode sampled actions back to native values. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Literal | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| from pydantic import BaseModel, ConfigDict, model_validator | ||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing_extensions import Self | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| class ContinuousSpace(BaseModel): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| A continuous (closed-interval) action-space dimension. | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Represents a single tunable parameter drawn from ``[low, high]``. ``dtype`` | ||||||||||||||||||||||||||||||||||||||||||||||||||
| declares whether decoded samples should be quantized to integers | ||||||||||||||||||||||||||||||||||||||||||||||||||
| (``"int"``) or kept as floats (``"float"``); quantization is applied by | ||||||||||||||||||||||||||||||||||||||||||||||||||
| consumers when decoding an action, not stored here. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| model_config = ConfigDict(extra="forbid") | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| low: float | ||||||||||||||||||||||||||||||||||||||||||||||||||
| high: float | ||||||||||||||||||||||||||||||||||||||||||||||||||
| dtype: Literal["int", "float"] = "float" | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| @model_validator(mode="after") | ||||||||||||||||||||||||||||||||||||||||||||||||||
| def _validate_bounds(self) -> Self: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.low >= self.high: | ||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError(f"ContinuousSpace requires low < high; got low={self.low}, high={self.high}") | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if self.dtype == "int" and (not self.low.is_integer() or not self.high.is_integer()): | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+45
to
+55
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor 🧩 Analysis chain🏁 Script executed: #!/bin/bash
python - <<'PY'
from pydantic import BaseModel, ConfigDict
class Model(BaseModel):
model_config = ConfigDict(extra="forbid")
x: float
for value in (float("nan"), float("inf"), float("-inf")):
try:
print("accepted", value, "->", Model(x=value).x)
except Exception as exc:
print("rejected", value, type(exc).__name__)
PYRepository: NVIDIA/cloudai Length of output: 214 🏁 Script executed: # First, locate and examine the ContinuousSpace class
cat -n src/cloudai/_core/action_space.py | head -70Repository: NVIDIA/cloudai Length of output: 2879 🏁 Script executed: # Search for usage of ContinuousSpace in the codebase
rg "ContinuousSpace" --type py -A 2 -B 2Repository: NVIDIA/cloudai Length of output: 152 🏁 Script executed: # Check for any existing finite validation or tests related to bounds
rg "isfinite|NaN|infinity" --type py src/cloudai/Repository: NVIDIA/cloudai Length of output: 396 🏁 Script executed: # Retry searching for ContinuousSpace usage with broader search
rg "ContinuousSpace" --type pyRepository: NVIDIA/cloudai Length of output: 152 🏁 Script executed: # Find test files related to action_space
find . -name "*test*action*" -o -name "*action*test*" | grep -E "\.py$"Repository: NVIDIA/cloudai Length of output: 181 🏁 Script executed: # Search for imports from action_space to find consumers
rg "from.*action_space import|import.*action_space" --type pyRepository: NVIDIA/cloudai Length of output: 152 🏁 Script executed: # Check test file for ContinuousSpace
cat tests/test_action_space.pyRepository: NVIDIA/cloudai Length of output: 2514 🏁 Script executed: # Search broadly for ContinuousSpace in all text files
rg "ContinuousSpace" .Repository: NVIDIA/cloudai Length of output: 1501 🏁 Script executed: # Look for files that use low/high bounds or action space
rg "\.low|\.high" --type py | grep -i "space\|adapter" | head -20Repository: NVIDIA/cloudai Length of output: 152 Reject non-finite bounds explicitly.
Proposed fix+import math
from typing import Literal
@@
`@model_validator`(mode="after")
def _validate_bounds(self) -> Self:
+ if not math.isfinite(self.low) or not math.isfinite(self.high):
+ raise ValueError(f"ContinuousSpace requires finite bounds; got low={self.low}, high={self.high}")
if self.low >= self.high:
raise ValueError(f"ContinuousSpace requires low < high; got low={self.low}, high={self.high}")📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.15.18)[warning] 54-54: Avoid specifying long messages outside the exception class (TRY003) 🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Valid; deferred with the PR. The finite-bound (NaN/inf) guard will land when ContinuousSpace is revived and wired into param_space.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🧠 Learnings used |
||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| f"ContinuousSpace(dtype='int') requires integer bounds; got low={self.low}, high={self.high}" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return self | ||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.