最適化のパラメータ変数範囲の最大値と最小値を探索する。
import designer
import csv
import subprocess
app = designer.GetApplication()
class DialogData:
def __init__(self):
self.num_trials = 20
self.csv_file_name = ""
self.is_open_csv = False
self.is_update_range = False
self.is_add_cases = False
self.is_valid = False
class RangeData:
def __init__(self):
self.name = ""
self.optimization_range= 0
self.param_index = 0
self.init_value = 0
def main():
data = get_data_from_input_dialog()
if data.is_valid == False:
return
if search_size_range_in_optimization_table(data)==False:
return
show_normal_exit_message()
def get_data_from_input_dialog():
dialog = create_input_dialog()
return show_input_dialog(dialog)
def create_input_dialog():
dialog = app.CreateDialogBox()
title_jp = "最適化の寸法範囲の探索"
title_en = "Search Size Range in Optimization Table"
inputlbl_jp = "入力:"
inputlbl_en = "Input:"
outputlbl_jp = "出力:"
outputlbl_en = "Output:"
optionlbl_jp = "オプション:"
optionlbl_en = "Option:"
numtrialslbl_jp = "探索回数:"
numtrialslbl_en = "Number of Search:"
noteslbl_jp = "1寸法あたりの探索回数は上限側/下限側合わせて、探索回数*2になります"
noteslbl_en = "Number of searches per dimension is equal to number of search times * 2 with upper limit side / lower limit side combined"
csvfile_jp = "結果ファイル:"
csvfile_en = "Result File:"
updatevallbl_jp = "最適化ダイアログの寸法値の最大値/最小値を更新する"
updatevallbl_en = "Update Max/Min of The Dimensions in Optimization Dialog"
leavecaseslbl_jp = "探索で形状を生成したケースを追加する"
leavecaseslbl_en = "Add Cases that Generated Shapes in Search"
dialog.SetTranslation(title_en, title_jp)
dialog.SetTranslation(inputlbl_en, inputlbl_jp)
dialog.SetTranslation(outputlbl_en, outputlbl_jp)
dialog.SetTranslation(optionlbl_en, optionlbl_jp)
dialog.SetTranslation(numtrialslbl_en, numtrialslbl_jp)
dialog.SetTranslation(noteslbl_en, noteslbl_jp)
dialog.SetTranslation(csvfile_en, csvfile_jp)
dialog.SetTranslation(updatevallbl_en, updatevallbl_jp)
dialog.SetTranslation(leavecaseslbl_en, leavecaseslbl_jp)
dialog.SetTitle(title_en)
dialog.AddLabel(inputlbl_en)
dialog.AddInteger("num_trials", numtrialslbl_en, 20)
dialog.SetTooltip("num_trials", noteslbl_en)
dialog.AddLine()
dialog.AddLabel(outputlbl_en)
dialog.AddSaveFilename("csv_file_name", csvfile_en, "", "CSV file (*.csv)")
dialog.AddLine()
dialog.AddLabel(optionlbl_en)
dialog.AddCheckBox("is_update_range", updatevallbl_en, False)
dialog.AddCheckBox("is_add_cases", leavecaseslbl_en, False)
return dialog
def show_input_dialog(dialog):
dialog.Show()
if dialog.WasCancelled() == False:
data = get_values_from_input_dialog(dialog)
if data.is_valid == False:
return show_input_dialog(dialog)
return data
return DialogData()
def get_values_from_input_dialog(dialog):
data = DialogData()
if dialog.GetValue("num_trials") <= 0:
message_en = "The number of trials must be greater than 0."
message_jp = "探索回数は0より大きな値を入力してください。"
show_error_exit_message(message_en, message_jp)
return data
if dialog.GetValue("csv_file_name") == "":
message_en = "Please specify result file name."
message_jp = "結果ファイル名を指定してください。"
show_error_exit_message(message_en, message_jp)
return data
data.num_trials = dialog.GetValue("num_trials")
data.is_update_range = dialog.GetValue("is_update_range")
data.is_add_cases = dialog.GetValue("is_add_cases")
data.csv_file_name = dialog.GetValue("csv_file_name")
data.is_valid = True
return data
def search_size_range_in_optimization_table(data):
range_list = []
if check_optimization_range(range_list) == False:
return False
if app.GetCurrentModel().IsCadLinkOpen() == False:
app.GetCurrentModel().RestoreCadLink()
app.GetCurrentStudy().SetCurrentCase(0)
geomApp = app.CreateGeometryEditor()
geomDoc = geomApp.GetDocument()
if geomDoc.NumBuildMessages() > 0:
show_error_exit_message("Initial case has error.", "初期ケースにエラーがあります。")
return False
initialTopologyKey = geomDoc.GetTopologyHashKey()
designTable = app.GetCurrentStudy().GetDesignTable()
num_case = designTable.NumCases()
result_list = []
for range_data in range_list:
optimizationRange = range_data.optimization_range
result = []
result.append(range_data.name)
result.append(search_size_range(range_data, optimizationRange.GetMin(), geomDoc, initialTopologyKey, data.num_trials))
result.append(search_size_range(range_data, optimizationRange.GetMax(), geomDoc, initialTopologyKey, data.num_trials))
result_list.append(result)
if data.is_update_range == True:
set_range_to_optimization_table(optimizationRange, result[1], result[2])
if data.is_add_cases == False:
remove_temp_cases(num_case)
output_csv_file(result_list, data.csv_file_name)
return True
def check_optimization_range(range_list):
designTable = app.GetCurrentStudy().GetDesignTable()
optimizationTable = app.GetCurrentStudy().GetOptimizationTable()
numParam = designTable.NumParameters()
for i in range(numParam):
if is_optimization_item(i) == False:
continue
name = designTable.ParameterName(i)
optimizationRange = optimizationTable.GetParametricItemByParameterName(name)
ini = designTable.GetValue(0, i)
if app.HasError():
app.ClearError()
optimizationTable.AddParametricItem(name)
optimizationRange = optimizationTable.GetParametricItemByParameterName(name)
optimizationRange.SetMin(ini)
optimizationRange.SetMax(ini)
min = optimizationRange.GetMin()
max = optimizationRange.GetMax()
if max < min:
message_en = "Maximum value of {0} in optimization dialog must be greater than or equal to minimum value.".format(name)
message_jp = "最適化ダイアログの {0} の最大値は最小値以上の値を入力してください。".format(name)
show_error_exit_message(message_en, message_jp)
return False
if min > ini:
message_en = "Minimum value of {0} in optimization dialog must be less than or equal to that of initial case.".format(name)
message_jp = "最適化ダイアログの {0} の最小値は初期ケースの値以下の値を入力してください。".format(name)
show_error_exit_message(message_en, message_jp)
return False
if max < ini:
message_en = "Maximum value of {0} in optimization dialog must be greater than or equal to that of initial case.".format(name)
message_jp = "最適化ダイアログの {0} の最大値は初期ケースの値以上の値を入力してください。".format(name)
show_error_exit_message(message_en, message_jp)
return False
data = RangeData()
data.name = name
data.optimization_range = optimizationRange
data.param_index = i
data.init_value = ini
range_list.append(data)
return True
def is_optimization_item(index):
designTable = app.GetCurrentStudy().GetDesignTable()
if designTable.IsCadParameter(index):
if designTable.ParameterTypeName(index) == "Real":
return True
return False
def search_size_range(range_data, limit, geomDoc, initialTopologyKey, num_trials):
designTable = app.GetCurrentStudy().GetDesignTable()
ini = range_data.init_value
paramIndex = range_data.param_index
shift = 0.0
shift = abs(limit - ini) / 2
if shift == 0:
return limit
elif limit > ini:
sign = 1
else:
sign = -1
binary = 0.0
binary = limit
for i in range(num_trials):
designTable.AddCase()
lastIndex = designTable.NumCases() - 1
for j in range(designTable.NumParameters()):
designTable.SetValue(lastIndex, j, designTable.GetValue(0, j))
designTable.SetValue(lastIndex, paramIndex, binary)
app.GetCurrentStudy().SetCurrentCase(lastIndex)
if geomDoc.NumBuildMessages() > 0 or geomDoc.GetTopologyHashKey() != initialTopologyKey:
binary = designTable.GetValue(lastIndex, paramIndex) - sign * shift
else:
if designTable.GetValue(lastIndex, paramIndex) == limit:
return limit
binary = designTable.GetValue(lastIndex, paramIndex) + sign * shift
shift /= 2
return designTable.GetValue(lastIndex, paramIndex)
def set_range_to_optimization_table(optimizationRange, min, max):
if optimizationRange.GetMin() != min:
optimizationRange.SetMin(min)
if optimizationRange.GetMax() != max:
optimizationRange.SetMax(max)
def remove_temp_cases(num_case):
designTable = app.GetCurrentStudy().GetDesignTable()
while num_case < designTable.NumCases():
index = designTable.NumCases() - 1
designTable.RemoveCase(index)
def output_csv_file(range_list, csv_file_name):
f = open(csv_file_name.decode('utf-8'), 'w')
writer = csv.writer(f, lineterminator='\n')
writer.writerow(["ParameterName", "Min", "Max"])
for line in range_list:
writer.writerow(line)
f.close()
def show_normal_exit_message():
title_en = "Search Finished"
title_jp = "探索終了"
message_en = "Search of Dimension Range is Finished."
message_jp = "寸法範囲の探索が終了しました。"
show_message(title_en, title_jp, message_en, message_jp)
def show_error_exit_message(message_en, message_jp):
title_en = "Error"
title_jp = "エラー"
show_message(title_en, title_jp, message_en, message_jp)
def show_message(title_en, title_jp, message_en, message_jp):
msgdlg = app.CreateDialogBox()
msgdlg.SetTranslation(title_en, title_jp)
msgdlg.SetTranslation(message_en, message_jp)
msgdlg.SetCancelButtonVisible(False)
msgdlg.SetTitle(title_en)
msgdlg.AddLabel(message_en)
msgdlg.Show()
main()


