Skip to content

Commit 5a9d113

Browse files
committed
Update action
1 parent 7a8a0fa commit 5a9d113

2 files changed

Lines changed: 125 additions & 32 deletions

File tree

.github/actions/collect_info/s_getInfo.py

Lines changed: 99 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from concurrent.futures import ThreadPoolExecutor, TimeoutError
44
from multiprocessing import Process, Queue
55
import signal
6+
import shutil
67

78
# Add optiprofiler to the system path
89
import os
@@ -43,6 +44,19 @@
4344
# To store all the 'time out' problems
4445
timeout_problems = []
4546

47+
# Helper function to append to txt files
48+
def append_to_txt(file_path, value):
49+
try:
50+
if os.path.exists(file_path):
51+
with open(file_path, 'r') as f:
52+
existing = [line.strip() for line in f.readlines()]
53+
if value in existing:
54+
return
55+
with open(file_path, 'a') as f:
56+
f.write(value + '\n')
57+
except Exception as e:
58+
print(f"Error appending to {file_path}: {e}")
59+
4660
# Find problems that are parametric
4761
filename = os.path.join(cwd, 'list_of_parametric_problems_with_parameters_python.txt')
4862
# Scan each line, each line only has one problem name, which ends before the first comma
@@ -80,7 +94,7 @@ def flush(self):
8094
self.log.flush()
8195

8296
# Record the log from terminal
83-
log_file = open(os.path.join(saving_path, 'log_python.txt'), 'w')
97+
log_file = open(os.path.join(saving_path, 'log_python_temp.txt'), 'a')
8498
sys.stdout = Logger(log_file)
8599
sys.stderr = Logger(log_file)
86100

@@ -147,6 +161,7 @@ def get_problem_info(problem_name, known_feasibility, problem_argins=None):
147161
except TimeoutError:
148162
print(f"Timeout while loading problem {problem_name}.")
149163
timeout_problems.append(problem_name)
164+
append_to_txt(os.path.join(saving_path, 'timeout_problems_python_temp.txt'), problem_name)
150165
print(f"Skipping problem {problem_name} due to timeout.")
151166
return info_single
152167

@@ -176,6 +191,7 @@ def get_problem_info(problem_name, known_feasibility, problem_argins=None):
176191
elif np.size(f) == 0 or np.isnan(f) or problem_name in known_feasibility:
177192
info_single['isfeasibility'] = 1
178193
feasibility.append(problem_name)
194+
append_to_txt(os.path.join(saving_path, 'feasibility_python_temp.txt'), problem_name)
179195
else:
180196
info_single['isfeasibility'] = 0
181197
if problem_name == 'LIN':
@@ -189,6 +205,7 @@ def get_problem_info(problem_name, known_feasibility, problem_argins=None):
189205
info_single['f0'] = 0
190206
info_single['isfeasibility'] = 1
191207
feasibility.append(problem_name)
208+
append_to_txt(os.path.join(saving_path, 'feasibility_python_temp.txt'), problem_name)
192209

193210
if problem_name in feasibility:
194211
info_single['isgrad'] = 1
@@ -349,6 +366,7 @@ def process_arg(problem_name, arg, fixed_argins):
349366
except TimeoutError:
350367
print(f"Timeout while processing problem {problem_name} with argument {arg}.")
351368
timeout_problems.append(problem_name + f" with arg {arg}")
369+
append_to_txt(os.path.join(saving_path, 'timeout_problems_python_temp.txt'), problem_name + f" with arg {arg}")
352370
continue
353371
except Exception as e:
354372
print(f"Error while processing problem {problem_name} with argument {arg}: {e}")
@@ -379,45 +397,96 @@ def process_arg(problem_name, arg, fixed_argins):
379397
return info_single
380398

381399
if __name__ == "__main__":
382-
# Save problem information into a csv file
383-
results = []
400+
csv_file = os.path.join(saving_path, 'probinfo_python.csv')
401+
csv_file_temp = os.path.join(saving_path, 'probinfo_python_temp.csv')
402+
current_prob_file = os.path.join(saving_path, 'current_problem.txt')
403+
exclude_file = os.path.join(saving_path, 'exclude_python.txt')
404+
405+
# 1. Crash Detection: If current_problem.txt exists, the previous run crashed on that problem.
406+
if os.path.exists(current_prob_file):
407+
with open(current_prob_file, 'r') as f:
408+
crashed_prob = f.read().strip()
409+
if crashed_prob:
410+
print(f"Detected crash during previous run on problem: {crashed_prob}. Adding to exclude list.")
411+
with open(exclude_file, 'a') as f:
412+
f.write(crashed_prob + '\n')
413+
try:
414+
os.remove(current_prob_file)
415+
except:
416+
pass
417+
418+
# 2. Load existing exclusions
419+
if os.path.exists(exclude_file):
420+
with open(exclude_file, 'r') as f:
421+
for line in f:
422+
ex = line.strip()
423+
if ex and ex not in problem_exclude:
424+
problem_exclude.append(ex)
425+
426+
# Update problem_names by removing excluded ones
427+
problem_names = [name for name in problem_names if name not in problem_exclude]
428+
429+
# 3. Resume: Find which problems are already completed
430+
completed_problems = set()
431+
if os.path.exists(csv_file_temp):
432+
try:
433+
existing_df = pd.read_csv(csv_file_temp, usecols=['problem_name'])
434+
completed_problems = set(existing_df['problem_name'].tolist())
435+
print(f"Found {len(completed_problems)} already completed problems in temp file. Resuming...")
436+
except Exception as e:
437+
print(f"Could not read existing temp CSV for resumption: {e}")
438+
439+
# 4. Processing loop
384440
for name in problem_names:
441+
if name in completed_problems:
442+
continue
443+
385444
if name in para_problem_names:
386445
index = para_problem_names.index(name)
387446
args = problem_argins[index] if index < len(problem_argins) else []
388447
else:
389448
args = None
449+
450+
# Write current problem name before processing it to detect crashes
451+
with open(current_prob_file, 'w') as f:
452+
f.write(name)
453+
390454
info = get_problem_info(name, known_feasibility, args)
391-
results.append(info)
455+
456+
# Original logic to filter out 'unknown' values
457+
def has_unknown_values(info_dict):
458+
for value in info_dict.values():
459+
if str(value).strip().lower() == 'unknown':
460+
return True
461+
return False
462+
463+
if not has_unknown_values(info):
464+
df_single = pd.DataFrame([info])
465+
if not os.path.exists(csv_file_temp):
466+
df_single.to_csv(csv_file_temp, index=False, na_rep='nan')
467+
else:
468+
df_single.to_csv(csv_file_temp, mode='a', header=False, index=False, na_rep='nan')
469+
else:
470+
print(f"Filtered out problem {name} due to 'unknown' values.")
471+
472+
# Clear crash detection file after successful processing
473+
if os.path.exists(current_prob_file):
474+
os.remove(current_prob_file)
475+
392476
sys.stdout.flush()
393477
sys.stderr.flush()
394478

395-
df = pd.DataFrame(results)
396-
397-
def has_unknown_values(row):
398-
for value in row:
399-
if str(value).strip().lower() == 'unknown':
400-
return True
401-
return False
402-
unknown_mask = df.apply(has_unknown_values, axis=1)
403-
if unknown_mask.any():
404-
filtered_problems = df.loc[unknown_mask, 'problem_name'].tolist()
405-
print(f"Filtered out {len(filtered_problems)} problems with 'unknown' values:")
406-
for problem in filtered_problems:
407-
print(f" - {problem}")
408-
df_clean = df[~unknown_mask]
409-
410-
df_clean.to_csv(os.path.join(saving_path, 'probinfo_python.csv'), index=False, na_rep='nan')
411-
412-
# Save 'feasibility' to txt file in the one line format with space separated values
413-
feasibility_file = os.path.join(saving_path, 'feasibility_python.txt')
414-
with open(feasibility_file, 'w') as f:
415-
f.write(' '.join(feasibility))
416-
417-
# Save 'timeout_problems' to txt file in the one line format with space separated values
418-
timeout_file = os.path.join(saving_path, 'timeout_problems_python.txt')
419-
with open(timeout_file, 'w') as f:
420-
f.write(' '.join(timeout_problems))
479+
# 5. Finalize: If we reached here, all problems are processed successfully.
480+
print("All problems processed. Finalizing output files...")
481+
if os.path.exists(csv_file_temp):
482+
shutil.move(csv_file_temp, csv_file)
483+
484+
# Handle txt files renaming
485+
for base_name in ['feasibility_python', 'timeout_problems_python', 'log_python']:
486+
temp_path = os.path.join(saving_path, base_name + '_temp.txt')
487+
final_path = os.path.join(saving_path, base_name + '.txt')
488+
if os.path.exists(temp_path):
489+
shutil.move(temp_path, final_path)
421490

422491
print("Script completed successfully.")
423492

.github/workflows/collect_info.yml

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,42 @@ jobs:
9292
- name: Run Python script
9393
if: matrix.language == 'python'
9494
run: |
95-
python3 s_getInfo.py
95+
MAX_RETRIES=50
96+
COUNT=0
97+
while [ $COUNT -lt $MAX_RETRIES ]; do
98+
python3 s_getInfo.py
99+
EXIT_CODE=$?
100+
if [ $EXIT_CODE -eq 0 ]; then
101+
echo "Script completed successfully."
102+
break
103+
fi
104+
echo "Script crashed with exit code $EXIT_CODE. Restarting ($((COUNT+1))/$MAX_RETRIES)..."
105+
COUNT=$((COUNT+1))
106+
# Small sleep to avoid rapid fire restarts
107+
sleep 2
108+
done
109+
if [ $COUNT -eq $MAX_RETRIES ]; then
110+
echo "Reached maximum retry limit."
111+
exit 1
112+
fi
96113
97114
- name: Upload Python artifacts
98-
if: matrix.language == 'python'
115+
if: always() && matrix.language == 'python'
99116
uses: actions/upload-artifact@v4
100117
with:
101118
name: probinfo-files-python
119+
if-no-files-found: ignore
102120
path: |
103121
probinfo_python.csv
122+
probinfo_python_temp.csv
104123
feasibility_python.txt
124+
feasibility_python_temp.txt
105125
timeout_problems_python.txt
126+
timeout_problems_python_temp.txt
106127
log_python.txt
128+
log_python_temp.txt
129+
exclude_python.txt
130+
current_problem.txt
107131
108132
- name: Upload MATLAB artifacts
109133
if: matrix.language == 'matlab'

0 commit comments

Comments
 (0)