import numpy as np
import matplotlib.pyplot as plt
from SALib.sample import saltelli
from SALib.analyze import sobol
class ProductionNode:
def __init__(self, name, node_type, defect_rate, cost, inspect_cost=None, disassemble_cost=None):
self.name = name
self.type = node_type
self.defect_rate = defect_rate
self.cost = cost
self.inspect_cost = inspect_cost
self.disassemble_cost = disassemble_cost
self.children = []
self.parent = None
def add_child(self, child):
self.children.append(child)
child.parent = self
def build_complex_network():
"""根据表2构建两道工序、8零配件的树形网络"""
parts = [
ProductionNode("Part1", "part", 0.10, 2, 1),
ProductionNode("Part2", "part", 0.10, 8, 1),
ProductionNode("Part3", "part", 0.10, 12, 2),
ProductionNode("Part4", "part", 0.10, 2, 1),
ProductionNode("Part5", "part", 0.10, 8, 1),
ProductionNode("Part6", "part", 0.10, 12, 2),
ProductionNode("Part7", "part", 0.10, 8, 1),
ProductionNode("Part8", "part", 0.10, 12, 2)
]
semi1 = ProductionNode("Semi1", "semi", 0.10, 8, 4, 6)
semi1.add_child(parts[0])
semi1.add_child(parts[1])
semi2 = ProductionNode("Semi2", "semi", 0.10, 8, 4, 6)
semi2.add_child(parts[2])
semi2.add_child(parts[3])
semi3 = ProductionNode("Semi3", "semi", 0.10, 6, 10, 6)
semi3.add_child(parts[4])
semi3.add_child(parts[5])
semi3.add_child(parts[6])
semi3.add_child(parts[7])
final = ProductionNode("Final", "final", 0.0, 0, None, None)
final.add_child(semi1)
final.add_child(semi2)
final.add_child(semi3)
return final
def calculate_residual_value(node, inspect_decisions, disassemble_decisions, depth=0):
"""递归计算节点及其子树的剩余价值(带缩进打印)"""
indent = " " * depth
print(f"{indent}计算节点 [{node.name}] 类型={node.type}")
if node.type == 'part':
if inspect_decisions.get(node.name, False):
residual = (1 - node.defect_rate) * node.cost - node.inspect_cost
print(f"{indent} - 检测后剩余价值: {residual:.2f}")
else:
residual = node.cost
print(f"{indent} - 不检测剩余价值: {residual:.2f}")
return residual
elif node.type == 'semi':
if disassemble_decisions.get(node.name, False):
child_values = [calculate_residual_value(child, inspect_decisions, disassemble_decisions, depth+1)
for child in node.children]
total = sum(child_values) - node.disassemble_cost
print(f"{indent} - 拆解后总价值: {total:.2f}")
return total
else:
print(f"{indent} - 不拆解,剩余价值=0")
return 0
elif node.type == 'final':
return 0
class GeneticOptimizer:
def __init__(self, pop_size=50, elite_size=5, mutation_rate=0.1, generations=100):
self.pop_size = pop_size
self.elite_size = elite_size
self.mutation_rate = mutation_rate
self.generations = generations
def initialize_population(self, decision_length=12):
"""生成随机初始种群(二进制编码)"""
return [np.random.randint(0, 2, decision_length).tolist() for _ in range(self.pop_size)]
def decode_decisions(self, individual):
"""解析基因编码为检测与拆解决策字典"""
inspect_parts = {f"Part{i+1}": bool(individual[i]) for i in range(8)}
inspect_semi = {f"Semi{i+1}": bool(individual[8+i]) for i in range(3)}
disassemble_final = {"Final": bool(individual[11])}
return {**inspect_parts, **inspect_semi, **disassemble_final}
def calculate_total_cost(self, root_node, inspect_decisions):
"""计算总成本(包括检测成本)"""
total_cost = 0
for part in root_node.children[0].children:
if inspect_decisions.get(part.name, False):
total_cost += part.inspect_cost
return total_cost
def monte_carlo_risk(self, root_node, inspect_decisions, n_sim=1000):
"""蒙特卡洛风险模拟"""
profits = []
for _ in range(n_sim):
total_cost = self.calculate_total_cost(root_node, inspect_decisions)
residual_value = calculate_residual_value(root_node, inspect_decisions, {})
profit = (1000 * 200) - total_cost + residual_value
profits.append(profit)
return np.mean(profits), np.std(profits)
def fitness(self, individual, root_node):
"""计算适应度:利润 + 0.3*剩余价值 - 0.2*风险标准差"""
decisions = self.decode_decisions(individual)
inspect_decisions = {k: v for k, v in decisions.items() if k.startswith('Part') or k.startswith('Semi')}
disassemble_decisions = {k: v for k, v in decisions.items() if k == 'Final'}
total_cost = self.calculate_total_cost(root_node, inspect_decisions)
residual_value = calculate_residual_value(root_node, inspect_decisions, disassemble_decisions)
profit = (1000 * 200) - total_cost + residual_value
_, profit_std = self.monte_carlo_risk(root_node, inspect_decisions)
return profit + 0.3 * residual_value - 0.2 * profit_std
def roulette_selection(self, population):
"""轮盘赌选择"""
total_fitness = sum(ind[0] for ind in population)
selection_probs = [ind[0] / total_fitness for ind in population]
return np.random.choice([ind[1] for ind in population], size=self.pop_size - self.elite_size, p=selection_probs)
def crossover(self, parent1, parent2):
"""单点交叉"""
crossover_point = np.random.randint(1, len(parent1))
return parent1[:crossover_point] + parent2[crossover_point:]
def mutate(self, individual):
"""随机位变异"""
for i in range(len(individual