import os
import json
import itertools
import shutil
import re
import ast
from collections import defaultdict
# Global variable - path to common parameter file
OTHER_JSON_PATH = "Channel_H_Generator/config_file/simulation_parameter_basic.json"
def clear_config_folder(folder_path):
"""Clear specified folder, create if not exists"""
if os.path.exists(folder_path):
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
print(f'Failed to delete {file_path}. Reason: {e}')
else:
os.makedirs(folder_path, exist_ok=True)
def parse_range_or_list(value_str):
"""解析范围字符串(如10:10:30)或逗号分隔列表,支持嵌套列表"""
# 尝试直接解析整个字符串
try:
parsed = ast.literal_eval(value_str)
if isinstance(parsed, list):
return parsed
except (ValueError, SyntaxError):
pass # 继续后续解析
# 尝试解析范围语法
if ':' in value_str and value_str.count(':') >= 2:
parts = value_str.split(':')
if len(parts) == 3:
try:
start = float(parts[0])
step = float(parts[1])
end = float(parts[2])
values = []
current = start
while current <= end:
# 如果是整数则转为int
if current.is_integer():
values.append(int(current))
else:
values.append(current)
current += step
return values
except ValueError:
pass # 回退到其他处理方式
# 尝试解析嵌套列表(多个方括号结构)
if re.match(r'^(\s*\[[^\]]*\]\s*,)+\s*\[[^\]]*\]\s*$', value_str):
list_items = re.findall(r'\[[^\]]*\]', value_str)
parsed_values = []
for item in list_items:
try:
clean_item = item.strip()[1:-1].strip()
inner_values = []
for v in clean_item.split(','):
inner_v = v.strip()
try:
inner_values.append(ast.literal_eval(inner_v))
except (ValueError, SyntaxError):
inner_values.append(inner_v)
parsed_values.append(inner_values)
except (ValueError, SyntaxError):
parsed_values.append(item)
return parsed_values
# 尝试解析单个列表结构
if re.match(r'^\s*\[.*\]\s*$', value_str):
try:
# 移除可能的空格干扰后解析
cleaned = re.sub(r'\s+', '', value_str)
return ast.literal_eval(cleaned)
except (ValueError, SyntaxError):
pass # 继续后续处理
# 尝试解析逗号分隔值
if ',' in value_str:
# 先尝试整体解析
try:
parsed = ast.literal_eval(value_str)
if isinstance(parsed, (tuple, list)):
return list(parsed)
except (ValueError, SyntaxError):
pass
# 保底的分割逻辑
values = []
for v in value_str.split(','):
v = v.strip()
try:
# 尝试解析每个部分
parsed = ast.literal_eval(v)
values.append(parsed)
except (ValueError, SyntaxError):
values.append(v)
return values
# 单值处理
try:
parsed = ast.literal_eval(value_str)
return [parsed]
except (ValueError, SyntaxError):
return [value_str]
def parse_cell_id_special(value_str):
"""Special parsing for cell_id format like [0;8],[3],[4;5;6]"""
matches = re.findall(r'\[([^\]]*)\]', value_str)
if not matches:
return [value_str] # Return original if no match
cell_id_groups = []
for group in matches:
try:
ids = [int(x.strip()) for x in group.split(';') if x.strip()]
cell_id_groups.append(ids)
except ValueError:
cell_id_groups.append([group])
return cell_id_groups
def parse_cell_based_parameter(value_str):
"""Parse cell-based parameter values using the same logic as cell_id"""
matches = re.findall(r'\[([^\]]*)\]', value_str)
if not matches:
return [[value_str]]
param_groups = []
for group in matches:
try:
parsed = ast.literal_eval(f'[{group}]')
param_groups.append(parsed)
except (ValueError, SyntaxError):
values = [v.strip() for v in group.split(';') if v.strip()]
try:
parsed_values = [ast.literal_eval(v) for v in values]
param_groups.append(parsed_values)
except (ValueError, SyntaxError):
param_groups.append(values)
return param_groups
def parse_parameter_file(file_path):
"""Parse parameter combination file, preserving original value types"""
parameters = {}
combo_parameters = defaultdict(list)
allowed_prefixes = [
"simulation_parameter_case_",
"bs_parameter_case_",
"user_specific_parameter_",
"3gpp_params_",
"3gpp_params_bound_"
]
with open(file_path, 'r') as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
if '=' not in line:
continue
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
key_lower = key.lower()
prefix_found = None
for prefix in allowed_prefixes:
if key_lower.startswith(prefix.lower()):
prefix_found = prefix
break
if key_lower.startswith('combo'):
pure_key = re.sub(r'^combo_?', '', key, flags=re.IGNORECASE).strip()
for prefix in allowed_prefixes:
if pure_key.startswith(prefix.lower()):
prefix_found = prefix
if prefix_found:
param_name = pure_key[len(prefix_found):]
if param_name.lower() in ["cell_id"] or prefix_found in ["bs_parameter_case_"]:
combo_values = parse_cell_based_parameter(value)
else:
combo_values = parse_range_or_list(value)
combo_parameters[f"{prefix_found}{param_name}"] = combo_values
elif pure_key.lower() in ["cell_id"] :
combo_parameters[pure_key] = parse_cell_based_parameter(value)
else:
combo_parameters[pure_key] = parse_range_or_list(value)
else:
for prefix in allowed_prefixes:
if key_lower.startswith(prefix.lower()):
prefix_found = prefix
if prefix_found:
param_name = key_lower[len(prefix_found):]
if param_name.lower() in ["cell_id"]or prefix_found in ["bs_parameter_case_"]:
parsed_values = parse_cell_based_parameter(value)
else:
parsed_values = parse_range_or_list(value)
parameters[f"{prefix_found}{param_name}"] = parsed_values
elif key_lower.lower() in ["cell_id"]:
parameters[key] = parse_cell_based_parameter(value)
else:
parameters[key] = parse_range_or_list(value)
return parameters, combo_parameters
def generate_combinations(normal_params, combo_params):
"""Generate all parameter combinations"""
normal_combinations = []
if normal_params:
keys = list(normal_params.keys())
value_lists = [normal_params[k] for k in keys]
for combo in itertools.product(*value_lists):
normal_combinations.append(dict(zip(keys, combo)))
combo_combinations = []
if combo_params:
num_values = None
for key, values in combo_params.items():
if num_values is None:
num_values = len(values)
elif len(values) != num_values:
raise ValueError(f"Combo parameter {key} has {len(values)} values, inconsistent with others ({num_values})")
if num_values > 0:
for i in range(num_values):
combo_dict = {}
for key, values in combo_params.items():
combo_dict[key] = values[i]
combo_combinations.append(combo_dict)
all_combinations = []
if combo_combinations:
if normal_combinations:
for norm_combo in normal_combinations:
for combo in combo_combinations:
merged = norm_combo.copy()
merged.update(combo)
all_combinations.append(merged)
else:
all_combinations = combo_combinations
else:
all_combinations = normal_combinations
return all_combinations
def find_and_update_parameter(data, path, value):
"""Recursively find and update matching parameters in JSON structure"""
count = 0
if isinstance(data, dict):
for k, v in list(data.items()):
clean_key = k.strip().lower()
clean_target = path[0].strip().lower()
if clean_key == clean_target:
if len(path) == 1:
data[k] = value
count += 1
else:
count += find_and_update_parameter(v, path[1:], value)
else:
if isinstance(v, (dict, list)):
count += find_and_update_parameter(v, path, value)
elif isinstance(data, list):
for item in data:
if isinstance(item, (dict, list)):
count += find_and_update_parameter(item, path, value)
return count
def update_json_with_parameters(json_data, parameters):
"""Update JSON data with all matching parameters"""
updated_params = set()
not_found = set()
for param, value in parameters.items():
path_list = [p.strip() for p in param.split('.')]
update_count = find_and_update_parameter(json_data, path_list, value)
if update_count > 0:
updated_params.add(param)
else:
not_found.add(param)
return json_data, not_found
def create_case_folders(config_dir, case_combinations, template_dir):
"""Create folders and config files for each case"""
os.makedirs(config_dir, exist_ok=True)
try:
with open(OTHER_JSON_PATH, 'r') as f:
other_json_data = json.load(f)
except FileNotFoundError:
other_json_data = {}
print(f"Warning: Common parameter file not found: {OTHER_JSON_PATH}")
case_list_path = os.path.join(config_dir, "case_list.txt")
with open(case_list_path, 'w') as case_file:
for i, combo in enumerate(case_combinations):
case_file.write(f"Case_{i}: {'; '.join(f'{k} = {v}' for k, v in combo.items())}\n")
allowed_prefixes = [
"simulation_parameter_case_",
"bs_parameter_case_",
"user_specific_parameter_",
"3gpp_params_",
"3gpp_params_bound_"
]
DEFAULT_CELL_ID = [[0, 8]]
for i, combo in enumerate(case_combinations):
case_dir = os.path.join(config_dir, str(i))
os.makedirs(case_dir, exist_ok=True)
template_files = [
"simulation_parameter_case.json",
"bs_parameter_case.json",
"user_specific_parameter.json",
"3gpp_params.json",
"3gpp_params_bound.json"
]
for file_name in template_files:
src_path = os.path.join(template_dir, file_name)
dst_path = os.path.join(case_dir, file_name)
if os.path.exists(src_path):
shutil.copy(src_path, dst_path)
no_prefix_combo = {}
if 'cell_id' in combo:
cell_id_value = combo['cell_id']
combo_without_cell_id = {k: v for k, v in combo.items() if k != 'cell_id'}
else:
cell_id_value = None
combo_without_cell_id = combo.copy()
for key, value in combo_without_cell_id.items():
if not any(key.lower().startswith(prefix.lower()) for prefix in allowed_prefixes):
no_prefix_combo[key] = value
sim_data, bs_data, user_data = {}, {}, {}
not_found = set(no_prefix_combo.keys())
file_parameters = {
"simulation_parameter_case": [],
"bs_parameter_case": [],
"user_specific_parameter": []
}
processed_params = set()
for param in combo.keys():
if param.startswith("simulation_parameter_case_"):
pure_param = param.replace("simulation_parameter_case_", "")
file_parameters["simulation_parameter_case"].append((pure_param, combo[param]))
not_found.discard(param)
elif param.startswith("bs_parameter_case_"):
pure_param = param.replace("bs_parameter_case_", "")
file_parameters["bs_parameter_case"].append((pure_param, combo[param]))
not_found.discard(param)
elif param.startswith("user_specific_parameter_"):
pure_param = param.replace("user_specific_parameter_", "")
file_parameters["user_specific_parameter"].append((pure_param, combo[param]))
not_found.discard(param)
bs_object_fields = {"ue_count", "ue_speed", "ue_direction", "ue_positions",
"ue_doppler_sampling_pattern", "ue_freq_sampling_pattern"}
global_bs_params = {k: v for k, v in combo_without_cell_id.items()
if k in bs_object_fields}
# 1. Update simulation_parameter_case.json
sim_path = os.path.join(case_dir, "simulation_parameter_case.json")
if os.path.exists(sim_path):
with open(sim_path, 'r') as f:
sim_data = json.load(f)
for param, value in file_parameters["simulation_parameter_case"]:
updated, missing = update_json_with_parameters(sim_data, {param: value})
if missing:
print(f"Warning: Case_{i} parameter not found: {param} (in simulation_parameter_case.json)")
sim_data, sim_not_found = update_json_with_parameters(sim_data, no_prefix_combo)
not_found = set(not_found) & set(sim_not_found)
with open(sim_path, 'w') as f:
json.dump(sim_data, f, indent=2)
cell_id_value = combo.get('cell_id', [])
if cell_id_value and not isinstance(cell_id_value[0], list):
cell_id_value = [cell_id_value]
# 2. Update bs_parameter_case.json
bs_path = os.path.join(case_dir, "bs_parameter_case.json")
bs_data_templates={}
if os.path.exists(bs_path):
with open(bs_path, 'r') as f:
bs_data = json.load(f)
bs_data_templates = bs_data['bs_parameters'][0]
prefixed_params = {}
regular_params = {}
prefix = "bs_parameter_case_"
for key, value in combo.items():
if key.startswith(prefix):
pure_key = key[len(prefix):]
prefixed_params[pure_key] = value
elif key not in ["cell_id"]: #
#
regular_params[key] = value
#
#
cell_id_value = combo.get('cell_id', DEFAULT_CELL_ID)
if not isinstance(cell_id_value[0], list):
cell_id_value = [cell_id_value]
#
param_groups = {}
for param, value in prefixed_params.items():
#
if not isinstance(value, list) or not value or not isinstance(value[0], list):
if isinstance(value, list):
value = [value] #
else:
value = [[value]] #
param_groups[param] = value
#
bs_data["bs_parameters"] = []
for group_idx, cell_group in enumerate(cell_id_value):
for cell_idx, cell_id in enumerate(cell_group):
bs_data_templates["cell_id"]=cell_id
cell_obj = bs_data_templates.copy()
#
for param, value_groups in param_groups.items():
if group_idx < len(value_groups) and cell_idx < len(value_groups[group_idx]):
cell_obj[param] = value_groups[group_idx][cell_idx]
bs_data["bs_parameters"].append(cell_obj)
#
if regular_params:
bs_data, reg_not_found = update_json_with_parameters(bs_data, regular_params)
not_found = not_found & reg_not_found
with open(bs_path, 'w') as f:
json.dump(bs_data, f, indent=2)
# 3. Update user_specific_parameter.json
user_path = os.path.join(case_dir, "user_specific_parameter.json")
if os.path.exists(user_path):
with open(user_path, 'r') as f:
user_data = json.load(f)
for param, value in file_parameters["user_specific_parameter"]:
updated, missing = update_json_with_parameters(user_data, {param: value})
if missing:
print(f"Warning: Case_{i} parameter not found: {param} (in user_specific_parameter.json)")
user_data, user_not_found = update_json_with_parameters(user_data, no_prefix_combo)
not_found = set(not_found) & set(user_not_found)
with open(user_path, 'w') as f:
json.dump(user_data, f, indent=2)
# 4. Check in common parameters
if not_found:
for param in list(not_found):
path_list = [p.strip() for p in param.split('.')]
if find_and_update_parameter(other_json_data, path_list, no_prefix_combo[param]) > 0:
print(f"Overridden common parameter: {param} = {no_prefix_combo[param]}")
not_found.remove(param)
if not_found:
print(f"Warning: Case_{i} parameters not found: {', '.join(not_found)}")
with open(OTHER_JSON_PATH, 'w') as f:
json.dump(other_json_data, f, indent=2)
print(f"Common parameter file updated: {OTHER_JSON_PATH}")
def main():
param_file = "Configuration parameter combination.txt"
config_dir = "Config"
template_dir = "templates"
print("Initializing Config folder...")
clear_config_folder(config_dir)
print(f"Cleared/created: {config_dir}")
normal_params, combo_params = parse_parameter_file(param_file)
print(f"Parsed normal parameters: {len(normal_params)}, combo parameters: {len(combo_params)}")
case_combinations = generate_combinations(normal_params, combo_params)
print(f"Generated {len(case_combinations)} parameter combinations")
create_case_folders(config_dir, case_combinations, template_dir)
print("All case configurations completed")
print(f"Each case folder contains:")
print("- simulation_parameter_case.json")
print("- bs_parameter_case.json")
print("- user_specific_parameter.json")
print("- 3gpp_params.json")
print("- 3gpp_params_bound.json")
print(f"Common parameter file location: {OTHER_JSON_PATH}")
if __name__ == "__main__":
main()
请在不改变原有功能的基础上,如果我的输入为interference_cell_id_list=[1]或interference_cell_id_list=[1,2,3]则输出一个case interference_cell_id_list=[1]或interference_cell_id_list=[1,2,3](列表格式)
如果interference_cell_id_list=1,2,3则输出三个case 为1 2 3,给出修改部分代码(尽可能小的修改)
最新发布