-
Notifications
You must be signed in to change notification settings - Fork 0
Experiment/optimize zhenxin s f 65nm ptm #6
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: master
Are you sure you want to change the base?
Changes from all commits
9b5bc75
cdd2f9a
1657084
905aec7
d06a33e
69f9400
897319e
902b4b5
528cac4
b58079d
31ecec2
65a1bc4
de9e5cd
4e70a37
b069551
37a346d
fdd48e6
f312107
fbd06b6
abfe4fd
30310b6
cb41fb6
b30cb30
d3e7714
d6e8dec
b4456a4
12ac8cd
c0f0ed0
556ee4d
2973585
7762c2b
8f08909
24e2f1b
a583013
7a7cee5
bc477ae
2baf41d
767009a
cd5ff8b
02d3055
44f09bd
dcdf673
d3baea0
f4fcd47
60a7f5c
37eeddb
6e05981
bd28006
4990aee
bdd4adc
bc96532
bce6b44
e32d329
1be048b
b7a94f5
9a3d967
b1b4134
718eed6
5ed931b
f936a93
9669e54
6f88b91
049da6c
7935a58
9ac3b67
2114647
bc212a7
a08ba2c
b9963d6
5e6fe0a
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 |
|---|---|---|
|
|
@@ -200,4 +200,5 @@ marimo/_lsp/ | |
| __marimo__/ | ||
|
|
||
| # Streamlit | ||
| .streamlit/secrets.toml | ||
| .streamlit/secrets.toml | ||
| *.out | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,365 @@ | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| A new ckt environment based on a new structure of MDP | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| import gym | ||||||||||||||||||||||||||||||
| from gym import spaces | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| import numpy as np | ||||||||||||||||||||||||||||||
| import random | ||||||||||||||||||||||||||||||
| import psutil | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| from multiprocessing.dummy import Pool as ThreadPool | ||||||||||||||||||||||||||||||
| from collections import OrderedDict | ||||||||||||||||||||||||||||||
| import yaml | ||||||||||||||||||||||||||||||
| import yaml.constructor | ||||||||||||||||||||||||||||||
| import statistics | ||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||
| import IPython | ||||||||||||||||||||||||||||||
| import itertools | ||||||||||||||||||||||||||||||
| from eval_engines.util.core import * | ||||||||||||||||||||||||||||||
| import pickle | ||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| from eval_engines.ngspice.TwoStageClass import * | ||||||||||||||||||||||||||||||
| from eval_engines.ngspice.LEDRO_D_FC import * | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| from loguru import logger | ||||||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Custom format string | ||||||||||||||||||||||||||||||
| log_format = ( | ||||||||||||||||||||||||||||||
| "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | " | ||||||||||||||||||||||||||||||
| "<level>{level: <8}</level> | " | ||||||||||||||||||||||||||||||
| "<cyan>{module}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - " | ||||||||||||||||||||||||||||||
| "<level>{message}</level>" | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Clear default logger | ||||||||||||||||||||||||||||||
| logger.remove() | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Log to stdout | ||||||||||||||||||||||||||||||
| logger.add(sys.stdout, format=log_format, level="DEBUG") | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Log to file with rotation and retention | ||||||||||||||||||||||||||||||
| logger.add( | ||||||||||||||||||||||||||||||
| "logs/ngspice_ledro_d_fc45.log", | ||||||||||||||||||||||||||||||
| format=log_format, | ||||||||||||||||||||||||||||||
| level="DEBUG", | ||||||||||||||||||||||||||||||
| rotation="1 day", | ||||||||||||||||||||||||||||||
| retention="7 days", | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # way of ordering the way a yaml file is read | ||||||||||||||||||||||||||||||
| class OrderedDictYAMLLoader(yaml.Loader): | ||||||||||||||||||||||||||||||
|
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. Use SafeLoader for YAML; avoid arbitrary object construction. yaml.load with yaml.Loader is unsafe. Switch to SafeLoader subclass and named Loader kwarg. -class OrderedDictYAMLLoader(yaml.Loader):
+class OrderedDictYAMLLoader(yaml.SafeLoader):
@@
- yaml.Loader.__init__(self, *args, **kwargs)
+ yaml.SafeLoader.__init__(self, *args, **kwargs)
@@
- yaml_data = yaml.load(f, OrderedDictYAMLLoader)
+ yaml_data = yaml.load(f, Loader=OrderedDictYAMLLoader)Also applies to: 62-62, 111-111 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| A YAML loader that loads mappings into ordered dictionaries. | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def __init__(self, *args, **kwargs): | ||||||||||||||||||||||||||||||
| yaml.Loader.__init__(self, *args, **kwargs) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| self.add_constructor("tag:yaml.org,2002:map", type(self).construct_yaml_map) | ||||||||||||||||||||||||||||||
| self.add_constructor("tag:yaml.org,2002:omap", type(self).construct_yaml_map) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def construct_yaml_map(self, node): | ||||||||||||||||||||||||||||||
| data = OrderedDict() | ||||||||||||||||||||||||||||||
| yield data | ||||||||||||||||||||||||||||||
| value = self.construct_mapping(node) | ||||||||||||||||||||||||||||||
| data.update(value) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def construct_mapping(self, node, deep=False): | ||||||||||||||||||||||||||||||
| if isinstance(node, yaml.MappingNode): | ||||||||||||||||||||||||||||||
| self.flatten_mapping(node) | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| raise yaml.constructor.ConstructorError( | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| "expected a mapping node, but found %s" % node.id, | ||||||||||||||||||||||||||||||
| node.start_mark, | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| mapping = OrderedDict() | ||||||||||||||||||||||||||||||
| for key_node, value_node in node.value: | ||||||||||||||||||||||||||||||
| key = self.construct_object(key_node, deep=deep) | ||||||||||||||||||||||||||||||
| value = self.construct_object(value_node, deep=deep) | ||||||||||||||||||||||||||||||
| mapping[key] = value | ||||||||||||||||||||||||||||||
| return mapping | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| class LEDRO_D_FC(gym.Env): | ||||||||||||||||||||||||||||||
| metadata = {"render.modes": ["human"]} | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| PERF_LOW = -1 | ||||||||||||||||||||||||||||||
| PERF_HIGH = 0 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # obtains yaml file | ||||||||||||||||||||||||||||||
| path = os.getcwd() | ||||||||||||||||||||||||||||||
| CIR_YAML = path + "/eval_engines/ngspice/ngspice_inputs/yaml_files/ledro_d_fc.yaml" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
Comment on lines
+98
to
+101
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. 🛠️ Refactor suggestion Make CIR_YAML path robust (don’t rely on CWD). Use path relative to this file to work across runners and notebooks. - path = os.getcwd()
- CIR_YAML = path + "/eval_engines/ngspice/ngspice_inputs/yaml_files/ledro_d_fc.yaml"
+ path = os.path.dirname(os.path.abspath(__file__))
+ CIR_YAML = os.path.abspath(
+ os.path.join(path, "../../eval_engines/ngspice/ngspice_inputs/yaml_files/ledro_d_fc.yaml")
+ )📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| def __init__(self, env_config): | ||||||||||||||||||||||||||||||
| self.multi_goal = env_config.get("multi_goal", False) | ||||||||||||||||||||||||||||||
| self.generalize = env_config.get("generalize", False) | ||||||||||||||||||||||||||||||
| num_valid = env_config.get("num_valid", 50) | ||||||||||||||||||||||||||||||
| self.specs_save = env_config.get("save_specs", False) | ||||||||||||||||||||||||||||||
| self.valid = env_config.get("run_valid", False) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| self.env_steps = 0 | ||||||||||||||||||||||||||||||
| with open(LEDRO_D_FC.CIR_YAML, "r") as f: | ||||||||||||||||||||||||||||||
| yaml_data = yaml.load(f, OrderedDictYAMLLoader) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # design specs | ||||||||||||||||||||||||||||||
| if self.generalize == False: | ||||||||||||||||||||||||||||||
| specs = yaml_data["target_specs"] | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| load_specs_path = ( | ||||||||||||||||||||||||||||||
| LEDRO_D_FC.path + "/autockt/gen_specs/ngspice_specs_gen_ledro_d_fc" | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| with open(load_specs_path, "rb") as f: | ||||||||||||||||||||||||||||||
| specs = pickle.load(f) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
Comment on lines
+117
to
+122
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. Gating and validating pickle load. Untrusted pickle is unsafe (S301) and path may be missing. Gate with an explicit flag and validate existence. - with open(load_specs_path, "rb") as f:
- specs = pickle.load(f)
+ assert env_config.get("trust_pickle", False), \
+ "Refuse to load specs from pickle unless env_config['trust_pickle']=True"
+ if not os.path.isfile(load_specs_path):
+ raise FileNotFoundError(f"Missing specs pickle at {load_specs_path}")
+ with open(load_specs_path, "rb") as f:
+ specs = pickle.load(f)📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.12.2)121-121: (S301) |
||||||||||||||||||||||||||||||
| self.specs = OrderedDict(sorted(specs.items(), key=lambda k: k[0])) | ||||||||||||||||||||||||||||||
| if self.specs_save: | ||||||||||||||||||||||||||||||
| with open( | ||||||||||||||||||||||||||||||
| "specs_" + str(num_valid) + str(random.randint(1, 100000)), "wb" | ||||||||||||||||||||||||||||||
| ) as f: | ||||||||||||||||||||||||||||||
| pickle.dump(self.specs, f) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| self.specs_ideal = [] | ||||||||||||||||||||||||||||||
| self.specs_id = list(self.specs.keys()) | ||||||||||||||||||||||||||||||
| self.fixed_goal_idx = -1 | ||||||||||||||||||||||||||||||
| self.num_os = len(list(self.specs.values())[0]) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # param array | ||||||||||||||||||||||||||||||
| params = yaml_data["params"] | ||||||||||||||||||||||||||||||
| self.params = [] | ||||||||||||||||||||||||||||||
| self.params_id = list(params.keys()) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| for value in params.values(): | ||||||||||||||||||||||||||||||
| param_vec = np.linspace(value[0], value[1], value[2]) | ||||||||||||||||||||||||||||||
| self.params.append(param_vec) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # initialize sim environment | ||||||||||||||||||||||||||||||
| self.sim_env = LEDRO_D_FC_Class( | ||||||||||||||||||||||||||||||
| yaml_path=LEDRO_D_FC.CIR_YAML, num_process=1, path=LEDRO_D_FC.path | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| self.action_meaning = [-1, 0, 2] | ||||||||||||||||||||||||||||||
| self.action_space = spaces.Tuple( | ||||||||||||||||||||||||||||||
| [spaces.Discrete(len(self.action_meaning))] * len(self.params_id) | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| # self.action_space = spaces.Discrete(len(self.action_meaning)**len(self.params_id)) | ||||||||||||||||||||||||||||||
| self.observation_space = spaces.Box( | ||||||||||||||||||||||||||||||
| low=np.array( | ||||||||||||||||||||||||||||||
| [LEDRO_D_FC.PERF_LOW] * 2 * len(self.specs_id) | ||||||||||||||||||||||||||||||
| + len(self.params_id) * [1] | ||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||
| high=np.array( | ||||||||||||||||||||||||||||||
| [LEDRO_D_FC.PERF_HIGH] * 2 * len(self.specs_id) | ||||||||||||||||||||||||||||||
| + len(self.params_id) * [1] | ||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
Comment on lines
+153
to
+162
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. Fix observation_space bounds and normalize parameter indices (current obs violates Box). Spec deltas can be in [-1, 1], but high is set to 0. Param indices are raw (0..N-1) while Box limits them to [0,1]. This will break Gym checks and learning stability. Apply these diffs: @@
- self.observation_space = spaces.Box(
- low=np.array(
- [LEDRO_D_FC.PERF_LOW] * 2 * len(self.specs_id)
- + len(self.params_id) * [1]
- ),
- high=np.array(
- [LEDRO_D_FC.PERF_HIGH] * 2 * len(self.specs_id)
- + len(self.params_id) * [1]
- ),
- )
+ self.observation_space = spaces.Box(
+ low=np.concatenate(
+ [np.full(2 * len(self.specs_id), LEDRO_D_FC.PERF_LOW, dtype=np.float32),
+ np.zeros(len(self.params_id), dtype=np.float32)]
+ ),
+ high=np.concatenate(
+ [np.full(2 * len(self.specs_id), 1.0, dtype=np.float32),
+ np.ones(len(self.params_id), dtype=np.float32)]
+ ),
+ dtype=np.float32,
+ )
@@
- self.ob = np.concatenate(
- [cur_spec_norm, self.specs_ideal_norm, self.cur_params_idx]
- )
+ self.ob = np.concatenate(
+ [cur_spec_norm, self.specs_ideal_norm, self.cur_params_idx / self.param_max_idx]
+ )
@@
- self.ob = np.concatenate(
- [cur_spec_norm, self.specs_ideal_norm, self.cur_params_idx]
- )
+ self.ob = np.concatenate(
+ [cur_spec_norm, self.specs_ideal_norm, self.cur_params_idx / self.param_max_idx]
+ )Add this once after params are built (outside selected range): # after building self.params
self.param_max_idx = np.array([len(p) - 1 for p in self.params], dtype=np.float32)Also applies to: 220-222, 260-262 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # initialize current param/spec observations | ||||||||||||||||||||||||||||||
| self.cur_specs = np.zeros(len(self.specs_id), dtype=np.float32) | ||||||||||||||||||||||||||||||
| self.cur_params_idx = np.zeros(len(self.params_id), dtype=np.int32) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Get the g* (overall design spec) you want to reach | ||||||||||||||||||||||||||||||
| self.global_g = [] | ||||||||||||||||||||||||||||||
| for spec in list(self.specs.values()): | ||||||||||||||||||||||||||||||
| self.global_g.append(float(spec[self.fixed_goal_idx])) | ||||||||||||||||||||||||||||||
| self.g_star = np.array(self.global_g) | ||||||||||||||||||||||||||||||
| self.global_g = np.array(yaml_data["normalize"]) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # objective number (used for validation) | ||||||||||||||||||||||||||||||
| self.obj_idx = 0 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def reset(self): | ||||||||||||||||||||||||||||||
| # if multi-goal is selected, every time reset occurs, it will select a different design spec as objective | ||||||||||||||||||||||||||||||
| if self.generalize == True: | ||||||||||||||||||||||||||||||
| if self.valid == True: | ||||||||||||||||||||||||||||||
| if self.obj_idx > self.num_os - 1: | ||||||||||||||||||||||||||||||
| self.obj_idx = 0 | ||||||||||||||||||||||||||||||
| idx = self.obj_idx | ||||||||||||||||||||||||||||||
| self.obj_idx += 1 | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| idx = random.randint(0, self.num_os - 1) | ||||||||||||||||||||||||||||||
| self.specs_ideal = [] | ||||||||||||||||||||||||||||||
| for spec in list(self.specs.values()): | ||||||||||||||||||||||||||||||
| self.specs_ideal.append(spec[idx]) | ||||||||||||||||||||||||||||||
| self.specs_ideal = np.array(self.specs_ideal) | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| if self.multi_goal == False: | ||||||||||||||||||||||||||||||
| self.specs_ideal = self.g_star | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| idx = random.randint(0, self.num_os - 1) | ||||||||||||||||||||||||||||||
| self.specs_ideal = [] | ||||||||||||||||||||||||||||||
| for spec in list(self.specs.values()): | ||||||||||||||||||||||||||||||
| self.specs_ideal.append(spec[idx]) | ||||||||||||||||||||||||||||||
| self.specs_ideal = np.array(self.specs_ideal) | ||||||||||||||||||||||||||||||
| # print("num total:"+str(self.num_os)) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # applicable only when you have multiple goals, normalizes everything to some global_g | ||||||||||||||||||||||||||||||
| self.specs_ideal_norm = self.lookup(self.specs_ideal, self.global_g) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # initialize current parameters | ||||||||||||||||||||||||||||||
| self.cur_params_idx = np.array([2] * 17) | ||||||||||||||||||||||||||||||
| self.cur_params_idx = np.array( | ||||||||||||||||||||||||||||||
| # [2, 2, 2, 2, 2, 2] + [200, 200, 200, 200, 200, 200] + [10, 10, 10, 10, 10] | ||||||||||||||||||||||||||||||
| [2, 2, 2, 2, 2, 2] | ||||||||||||||||||||||||||||||
| + [200, 200, 200, 200, 200, 200] | ||||||||||||||||||||||||||||||
| + [10, 10, 10, 10, 10] | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
Comment on lines
+207
to
+213
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. Remove hard-coded 17-dim indices. Compute from YAML to avoid shape mismatches. Hard-coding breaks as soon as param counts change. - self.cur_params_idx = np.array([2] * 17)
- self.cur_params_idx = np.array(
- # [2, 2, 2, 2, 2, 2] + [200, 200, 200, 200, 200, 200] + [10, 10, 10, 10, 10]
- [2, 2, 2, 2, 2, 2]
- + [200, 200, 200, 200, 200, 200]
- + [10, 10, 10, 10, 10]
- )
+ # start from midpoints of each discrete grid
+ self.cur_params_idx = np.array([len(p) // 2 for p in self.params], dtype=np.int32)
@@
- env.step([2] * 17)
+ env.step([1] * len(env.params_id))Also applies to: 359-359 🧰 Tools🪛 Ruff (0.12.2)210-212: Consider iterable unpacking instead of concatenation Replace with iterable unpacking (RUF005) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| self.cur_specs = self.update(self.cur_params_idx) | ||||||||||||||||||||||||||||||
| cur_spec_norm = self.lookup(self.cur_specs, self.global_g) | ||||||||||||||||||||||||||||||
| reward = self.reward(self.cur_specs, self.specs_ideal) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # observation is a combination of current specs distance from ideal, ideal spec, and current param vals | ||||||||||||||||||||||||||||||
| self.ob = np.concatenate( | ||||||||||||||||||||||||||||||
| [cur_spec_norm, self.specs_ideal_norm, self.cur_params_idx] | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| return self.ob | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def step(self, action): | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| :param action: is vector with elements between 0 and 1 mapped to the index of the corresponding parameter | ||||||||||||||||||||||||||||||
| :return: | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Take action that RL agent returns to change current params | ||||||||||||||||||||||||||||||
| action = list(np.reshape(np.array(action), (np.array(action).shape[0],))) | ||||||||||||||||||||||||||||||
| self.cur_params_idx = self.cur_params_idx + np.array( | ||||||||||||||||||||||||||||||
| [self.action_meaning[a] for a in action] | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # self.cur_params_idx = self.cur_params_idx + np.array(self.action_arr[int(action)]) | ||||||||||||||||||||||||||||||
| self.cur_params_idx = np.clip( | ||||||||||||||||||||||||||||||
| self.cur_params_idx, | ||||||||||||||||||||||||||||||
| [0] * len(self.params_id), | ||||||||||||||||||||||||||||||
| [(len(param_vec) - 1) for param_vec in self.params], | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Get current specs and normalize | ||||||||||||||||||||||||||||||
| self.cur_specs = self.update(self.cur_params_idx) | ||||||||||||||||||||||||||||||
| cur_spec_norm = self.lookup(self.cur_specs, self.global_g) | ||||||||||||||||||||||||||||||
| reward = self.reward(self.cur_specs, self.specs_ideal) | ||||||||||||||||||||||||||||||
| done = False | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # incentivize reaching goal state | ||||||||||||||||||||||||||||||
| if reward >= 10: | ||||||||||||||||||||||||||||||
| done = True | ||||||||||||||||||||||||||||||
| print("-" * 10) | ||||||||||||||||||||||||||||||
| print("params = ", self.cur_params_idx) | ||||||||||||||||||||||||||||||
| print("specs:", self.cur_specs) | ||||||||||||||||||||||||||||||
| print("ideal specs:", self.specs_ideal) | ||||||||||||||||||||||||||||||
| print("re:", reward) | ||||||||||||||||||||||||||||||
| print("-" * 10) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
Comment on lines
+250
to
+259
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. Episode never terminates with current reward sign. reward() returns a negative penalty, but done triggers on reward >= 10, which is unreachable. - if reward >= 10:
+ # done when total penalty magnitude is within tolerance
+ if -reward <= self.success_tolerance:
done = True
- print("-" * 10)
- print("params = ", self.cur_params_idx)
- print("specs:", self.cur_specs)
- print("ideal specs:", self.specs_ideal)
- print("re:", reward)
- print("-" * 10)
+ logger.info("-" * 10)
+ logger.info(f"params = {self.cur_params_idx}")
+ logger.info(f"specs: {self.cur_specs}")
+ logger.info(f"ideal specs: {self.specs_ideal}")
+ logger.info(f"reward: {reward}")
+ logger.info("-" * 10)Also define a tolerance in init (outside selected range): self.success_tolerance = float(env_config.get("success_tolerance", 0.02))🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| self.ob = np.concatenate( | ||||||||||||||||||||||||||||||
| [cur_spec_norm, self.specs_ideal_norm, self.cur_params_idx] | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| self.env_steps = self.env_steps + 1 | ||||||||||||||||||||||||||||||
| print("***cur params idx:", self.cur_params_idx, "specs: ", self.cur_specs, " reward: ", reward) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # print('cur ob:' + str(self.cur_specs)) | ||||||||||||||||||||||||||||||
| # print('ideal spec:' + str(self.specs_ideal)) | ||||||||||||||||||||||||||||||
| # print(reward) | ||||||||||||||||||||||||||||||
| return self.ob, reward, done, {} | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def lookup(self, spec, goal_spec): | ||||||||||||||||||||||||||||||
| goal_spec = [float(e) for e in goal_spec] | ||||||||||||||||||||||||||||||
| norm_spec = (spec - goal_spec) / (goal_spec + spec) | ||||||||||||||||||||||||||||||
| return norm_spec | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def reward(self, spec, goal_spec): | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| Reward: doesn't penalize for overshooting spec, is negative | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| # rel_specs = self.lookup(spec, goal_spec) | ||||||||||||||||||||||||||||||
| # pos_val = [] | ||||||||||||||||||||||||||||||
| # reward = 0.0 | ||||||||||||||||||||||||||||||
| # for i, rel_spec in enumerate(rel_specs): | ||||||||||||||||||||||||||||||
| # if self.specs_id[i] == "ibias_max": | ||||||||||||||||||||||||||||||
| # rel_spec = rel_spec * -1.0 # /10.0 | ||||||||||||||||||||||||||||||
| # if rel_spec < 0: | ||||||||||||||||||||||||||||||
| # reward += rel_spec | ||||||||||||||||||||||||||||||
| # pos_val.append(0) | ||||||||||||||||||||||||||||||
| # else: | ||||||||||||||||||||||||||||||
| # pos_val.append(1) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # return reward if reward < -0.02 else 10 | ||||||||||||||||||||||||||||||
| norm_specs = self.lookup(spec, goal_spec) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # pay attention to reward calculation, this is not quite the reward function in RL | ||||||||||||||||||||||||||||||
| # but rather a penalty value for the optimization process | ||||||||||||||||||||||||||||||
| reward = 0 | ||||||||||||||||||||||||||||||
| for i, rel_spec in enumerate(norm_specs): | ||||||||||||||||||||||||||||||
| # For power, smaller is better | ||||||||||||||||||||||||||||||
| # For gain, larger (compared to the target/goal) is better | ||||||||||||||||||||||||||||||
| # For other specs (pm, ugbw, etc.), smaller is better | ||||||||||||||||||||||||||||||
| assert self.specs_id[i] in ["ibias_max", "gain_min", "ugbw_min", "phm_min"] | ||||||||||||||||||||||||||||||
| if self.specs_id[i] == "ibias_max" and rel_spec > 0: | ||||||||||||||||||||||||||||||
| reward += np.abs(rel_spec) # /10 | ||||||||||||||||||||||||||||||
| elif self.specs_id[i] == "gain_min" and rel_spec < 0: | ||||||||||||||||||||||||||||||
| reward += 3 * np.abs(rel_spec) # /10 | ||||||||||||||||||||||||||||||
| elif self.specs_id[i] != "ibias_max" and rel_spec < 0: | ||||||||||||||||||||||||||||||
| reward += np.abs(rel_spec) | ||||||||||||||||||||||||||||||
| return -reward | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def update(self, params_idx): | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| :param action: an int between 0 ... n-1 | ||||||||||||||||||||||||||||||
| :return: | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| params = [self.params[i][params_idx[i]] for i in range(len(self.params_id))] | ||||||||||||||||||||||||||||||
| param_val = [OrderedDict(list(zip(self.params_id, params)))] | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # run param vals and simulate | ||||||||||||||||||||||||||||||
| cur_specs = OrderedDict( | ||||||||||||||||||||||||||||||
| sorted( | ||||||||||||||||||||||||||||||
| self.sim_env.create_design_and_simulate(param_val[0])[1].items(), | ||||||||||||||||||||||||||||||
| key=lambda k: k[0], | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||
| cur_specs = np.array(list(cur_specs.values())) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| return cur_specs | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def main(): | ||||||||||||||||||||||||||||||
| env_config = {"generalize": True, "valid": True} | ||||||||||||||||||||||||||||||
| env = LEDRO_D_FC(env_config) | ||||||||||||||||||||||||||||||
| env.reset() | ||||||||||||||||||||||||||||||
| # env.step( | ||||||||||||||||||||||||||||||
| # [ | ||||||||||||||||||||||||||||||
| # 2, | ||||||||||||||||||||||||||||||
| # 2, | ||||||||||||||||||||||||||||||
| # 2, | ||||||||||||||||||||||||||||||
| # 2, | ||||||||||||||||||||||||||||||
| # 2, | ||||||||||||||||||||||||||||||
| # 2, | ||||||||||||||||||||||||||||||
| # 10 - 9, | ||||||||||||||||||||||||||||||
| # 10 - 9, | ||||||||||||||||||||||||||||||
| # 10 - 9, | ||||||||||||||||||||||||||||||
| # 10 - 9, | ||||||||||||||||||||||||||||||
| # 10 - 9, | ||||||||||||||||||||||||||||||
| # 10 - 9, | ||||||||||||||||||||||||||||||
| # 0.2, | ||||||||||||||||||||||||||||||
| # 0.2, | ||||||||||||||||||||||||||||||
| # 0.2, | ||||||||||||||||||||||||||||||
| # 0.2, | ||||||||||||||||||||||||||||||
| # 0.2, | ||||||||||||||||||||||||||||||
| # ] | ||||||||||||||||||||||||||||||
| # ) | ||||||||||||||||||||||||||||||
| env.step([2] * 17) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| IPython.embed() | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if __name__ == "__main__": | ||||||||||||||||||||||||||||||
| main() | ||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove star imports and duplicate import; import only what you use.
Avoid F403/F405 collisions and the class name shadowing with local LEDRO_D_FC.
Also drop the duplicate
import oson Line 22.🧰 Tools
🪛 Ruff (0.12.2)
20-20:
from eval_engines.util.core import *used; unable to detect undefined names(F403)
22-22: Redefinition of unused
osfrom line 17Remove definition:
os(F811)
24-24:
from eval_engines.ngspice.TwoStageClass import *used; unable to detect undefined names(F403)
25-25:
from eval_engines.ngspice.LEDRO_D_FC import *used; unable to detect undefined names(F403)
🤖 Prompt for AI Agents