Код: Выделить всё
from collections import defaultdict
import re
# Parameters
X_percent = 0.93 # Desired coverage percentage (e.g., 93%)
lambda_penalty = 500 # Adjusted penalty
max_attack_time = 3600 # Maximum allowed execution time per attack in seconds
max_total_time = 20 * 3600 # Maximum total execution time in seconds (15 hours)
min_new_plains = 10 # Minimum number of new plains an attack must cover
max_plain_weight = 5 # Maximum weight assigned to any plain
set_a_directory = '/root/setA/' # Directory containing Set A files
file_b_path = '/root/h.txt' # Path to File B
# Step 1: Read File B and assign unique IDs to plains
plain_to_id = {}
id_to_plain = {}
with open(file_b_path, 'r') as f:
for line in f:
plain = line.strip()
if plain not in plain_to_id:
plain_id = len(plain_to_id)
plain_to_id[plain] = plain_id
id_to_plain[plain_id] = plain
total_plains = len(plain_to_id)
print(f"Total number of plains in File B: {total_plains}")
# Step 2: Process Set A files and build data structures
attack_info = []
plain_to_attacks = defaultdict(set) # Maps plain ID to set of attack indices
# Regular expression to extract time from file name
time_pattern = re.compile(r'^(\d+)_')
# Iterate over each file in Set A
for file_name in os.listdir(set_a_directory):
file_path = os.path.join(set_a_directory, file_name)
# Extract execution time from file name
time_match = time_pattern.match(file_name)
if not time_match:
continue # Skip files that don't match the pattern
execution_time = int(time_match.group(1))
if execution_time > max_attack_time:
continue # Exclude attacks over the maximum allowed time
with open(file_path, 'r') as f:
lines = f.readlines()
if not lines:
continue # Skip empty files
attack_command = lines[0].strip()
plains_covered = set()
for line in lines[1:]:
parts = line.strip().split(':')
if not parts:
continue
plain = parts[0].strip()
if plain in plain_to_id:
plain_id = plain_to_id[plain]
plains_covered.add(plain_id)
plain_to_attacks[plain_id].add(len(attack_info)) # Index of this attack
attack_info.append({
'command': attack_command,
'time': execution_time,
'plains': plains_covered,
'index': len(attack_info)
})
num_attacks = len(attack_info)
print(f"Total number of attacks in Set A after filtering: {num_attacks}")
# Step 3: Compute the number of attacks covering each plain (f_p)
plain_cover_count = {}
for plain_id in plain_to_id.values():
cover_count = len(plain_to_attacks[plain_id])
plain_cover_count[plain_id] = cover_count
# Step 4: Assign weights to plains with a maximum weight
plain_weights = {}
for plain_id, f_p in plain_cover_count.items():
if f_p > 0:
plain_weights[plain_id] = min(1.0 / f_p, max_plain_weight)
else:
plain_weights[plain_id] = max_plain_weight
# Step 5: Implement the weighted greedy algorithm with adjusted efficiency
total_plains_needed = int(total_plains * X_percent)
print(f"Number of plains needed for {X_percent*100}% coverage: {total_plains_needed}")
covered_plains = set()
selected_attacks = []
remaining_attacks = set(range(num_attacks))
total_execution_time = 0
while len(covered_plains) < total_plains_needed and remaining_attacks:
best_efficiency = -1
best_attack = None
for i in remaining_attacks:
attack = attack_info[i]
new_plains = attack['plains'] - covered_plains
if len(new_plains) < min_new_plains:
continue # Skip attacks that cover too few new plains
# Calculate W_i (sum of weights of new plains)
W_i = sum(plain_weights[p] for p in new_plains)
# Adjusted Efficiency E_i
efficiency = (W_i * len(new_plains)) / (attack['time'] + lambda_penalty)
if efficiency > best_efficiency:
best_efficiency = efficiency
best_attack = i
if best_attack is None:
print("No further attacks can improve coverage.")
break
# Check if adding this attack exceeds the maximum total execution time
if total_execution_time + attack_info[best_attack]['time'] > max_total_time:
print("Reached maximum total execution time limit.")
break
# Select the attack with the highest adjusted efficiency
selected_attacks.append(best_attack)
covered_plains.update(attack_info[best_attack]['plains'])
remaining_attacks.remove(best_attack)
total_execution_time += attack_info[best_attack]['time']
# Optional: Print progress
coverage_percentage = (len(covered_plains) / total_plains) * 100
print(f"Selected attack {best_attack}: Coverage {coverage_percentage:.2f}%, "
f"Total Time: {total_execution_time / 3600:.2f} hours")
# Step 6: Output the results
print("\nSelected Attacks:")
for idx in selected_attacks:
attack = attack_info[idx]
print(f"Attack Index: {idx}")
print(f"Command: {attack['command']}")
print(f"Time: {attack['time']} seconds")
print(f"Plains Covered: {len(attack['plains'])}")
print("-----------------------------")
final_coverage = (len(covered_plains) / total_plains) * 100
print(f"Final Coverage: {final_coverage:.2f}%")
print(f"Total Execution Time: {total_execution_time / 3600:.2f} hours")
print(f"Total Attacks Selected: {len(selected_attacks)}")
Подробнее здесь: https://stackoverflow.com/questions/791 ... ross-files