exp 中的Direct=y 问题

讨论了含有LOB对象的表在使用Direct模式导出时的情况,实际操作表明即使设置Direct=y,含有LOB字段的表仍然可以被成功导出并导入到另一个数据库。
参看exp 中的Direct=y   说含有LOB对象的表不支持直接导出模式。

但是我Direct=y导出的一个表中有lob字段,导出后再导入到另一库中,可以看到在导入的库中,这个表还是有lob的字段的!?请问是不是我理解错误啊?

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8497396/viewspace-748635/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/8497396/viewspace-748635/

--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[15], line 727 724 logger.info("结果已保存到 '灌溉系统优化结果.csv'") 726 if __name__ == "__main__": --> 727 main() Cell In[15], line 653 650 logger.info(f"直接连接喷头比例: {np.sum(direct_pipe_mask)/len(sprinkler_df)*100:.1f}%") 652 # 8. 可视化 --> 653 visualize_system(sprinkler_df, tank_positions, assignments, direct_pipe_mask, vor) 654 plot_cost_breakdown(tank_cost, pipe_cost) 656 # 9. 储水罐容量分析 Cell In[15], line 556 554 mid_y = (RIVER_POINT[1] + tank[1]) / 2 555 length = np.sqrt((RIVER_POINT[0]-tank[0])**2 + (RIVER_POINT[1]-tank[1])**2) --> 556 ax.text(mid_x, mid_y, f'{length:.1f}m\n{Q_opt[j]:.0f}L/d', fontsize=8, 557 bbox=dict(boxstyle="round,pad=0.3", facecolor="white", alpha=0.7)) 559 ax.set_xlabel('X坐标 (m)') 560 ax.set_ylabel('Y坐标 (m)') NameError: name 'Q_opt' is not definedimport numpy as np import pandas as pd from scipy.optimize import minimize, Bounds from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score import matplotlib.pyplot as plt from scipy.spatial import Voronoi, voronoi_plot_2d, ConvexHull import warnings import logging from matplotlib.patches import Polygon import matplotlib.cm as cm from sklearn.preprocessing import StandardScaler # 设置日志记录 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # 忽略特定警告 warnings.filterwarnings("ignore", category=UserWarning, module="sklearn") warnings.filterwarnings("ignore", category=RuntimeWarning) # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体 plt.rcParams['axes.unicode_minus'] = False # 正常显示负号 # ==================== 常量定义 ==================== DEPTH = 0.05 # 5 cm DRY_DENS = 1500 # kg/m³ dry_mass_per_m2 = DRY_DENS * DEPTH # 75 kg/m² MIN_SOIL_MOISTURE = 0.22 # 最低土壤湿度 # 农场尺寸 (1公顷正方形) FARM_SIZE = 100 # 米 FARM_SIZE_X, FARM_SIZE_Y = FARM_SIZE, FARM_SIZE logger.info(f"农场尺寸: {FARM_SIZE_X}m × {FARM_SIZE_Y}m") # 作物信息 CROPS = { 'sorghum': { 'area': 0.5 * 10000, # 公顷转换为平方米 'sowing_water': 5, # 播种期需水量 (L/m²) 'flowering_water': 10, # 开花期需水量 (L/m²) 'mature_water': 8, # 成熟期需水量 (L/m²) 'sowing_days': 20, # 播种期天数 'flowering_days': 50 # 开花期天数 }, 'corn': { 'area': 0.3 * 10000, 'sowing_water': 6, 'flowering_water': 12, 'mature_water': 10, 'sowing_days': 32, 'flowering_days': 50 }, 'soybean': { 'area': 0.2 * 10000, 'sowing_water': 4, 'flowering_water': 8, 'mature_water': 6, 'sowing_days': 40, 'flowering_days': 40 } } # 作物分布(假设按区域分布) CROP_REGIONS = { 'sorghum': {'x_min': 0, 'x_max': FARM_SIZE_X, 'y_min': 0, 'y_max': FARM_SIZE_Y/2}, 'corn': {'x_min': 0, 'x_max': FARM_SIZE_X/2, 'y_min': FARM_SIZE_Y/2, 'y_max': FARM_SIZE_Y}, 'soybean': {'x_min': FARM_SIZE_X/2, 'x_max': FARM_SIZE_X, 'y_min': FARM_SIZE_Y/2, 'y_max': FARM_SIZE_Y} } SPRINKLER_RADIUS = 15 # 喷头半径 RIVER_POSITION = 'south' # 河流取水点 (假设河流在南边中间) RIVER_POINT = (FARM_SIZE_X / 2, FARM_SIZE_Y) # 调整成本公式参数 PIPE_LENGTH_COEFF = 50 # 管道长度系数 PIPE_FLOW_COEFF = 0.1 # 管道流量系数 PIPE_LENGTH_EXP = 1.1 # 管道长度指数 (降低) PIPE_FLOW_EXP = 1.3 # 管道流量指数 (降低) TANK_COST_PER_LITER = 5 # 储水罐单位容积成本 # ==================== 数据加载与处理 ==================== def load_soil_moisture_data(): """ 加载土壤湿度数据 """ try: # 尝试加载数据 data = pd.read_excel('附件/该地土壤湿度数据.xlsx', sheet_name='JingYueTan') logger.info(f"土壤湿度数据结构: {data.info()}") # 转换日期格式 data['DATE'] = pd.to_datetime(data['DATE']) # 提取7月数据 july_data = data[(data['DATE'] >= '2021-07-01') & (data['DATE'] <= '2021-07-31')] # 按日期分组并计算平均土壤湿度 daily_avg_moisture = july_data.groupby('DATE')['5cm_SM'].mean() # 绘制土壤湿度变化图 plt.figure(figsize=(12, 6)) plt.plot(daily_avg_moisture.index, daily_avg_moisture.values, 'b-', linewidth=2) plt.axhline(y=MIN_SOIL_MOISTURE, color='r', linestyle='--', label='最低土壤湿度阈值') plt.title('2021年7月土壤湿度变化') plt.xlabel('日期') plt.ylabel('土壤湿度 (5cm_SM)') plt.legend() plt.grid(True) plt.xticks(rotation=45) plt.tight_layout() plt.savefig('土壤湿度变化图.png', dpi=300) plt.show() return daily_avg_moisture, july_data except Exception as e: logger.error(f"加载土壤湿度数据时出错: {e}") # 创建模拟数据 dates = pd.date_range('2021-07-01', periods=31) default_moisture = pd.Series([0.15 + 0.1 * np.sin(i/10) for i in range(31)], index=dates) # 绘制模拟土壤湿度变化图 plt.figure(figsize=(12, 6)) plt.plot(dates, default_moisture.values, 'b-', linewidth=2) plt.axhline(y=MIN_SOIL_MOISTURE, color='r', linestyle='--', label='最低土壤湿度阈值') plt.title('2021年7月土壤湿度变化 (模拟数据)') plt.xlabel('日期') plt.ylabel('土壤湿度 (5cm_SM)') plt.legend() plt.grid(True) plt.xticks(rotation=45) plt.tight_layout() plt.savefig('土壤湿度变化图.png', dpi=300) plt.show() return default_moisture, pd.DataFrame({'DATE': dates, '5cm_SM': default_moisture}) def calculate_daily_irrigation_demand(daily_moisture, crop_type=None): """ 计算每日每平方米灌溉需求,考虑作物类型 """ base_demand = max(0.0, (MIN_SOIL_MOISTURE - daily_moisture) * dry_mass_per_m2) # 根据作物类型调整需求 if crop_type and crop_type in CROPS: # 7月假设为开花期 crop_factor = CROPS[crop_type]['flowering_water'] / 10 # 以高粱的开花需水量10为基准 base_demand *= crop_factor return base_demand def calculate_irrigation_demand(daily_avg_moisture, sprinkler_df): """ 计算每日灌溉需求,考虑作物类型 """ irrigation_demand = {} for crop in CROPS.keys(): crop_demand = [] for moisture in daily_avg_moisture: demand_per_m2 = calculate_daily_irrigation_demand(moisture, crop) crop_demand.append(demand_per_m2) irrigation_demand[crop] = crop_demand # 计算每个喷头的需求 sprinkler_demands = [] for _, sprinkler in sprinkler_df.iterrows(): crop = sprinkler['crop_type'] crop_idx = list(CROPS.keys()).index(crop) max_demand = max(irrigation_demand[crop]) sprinkler_demands.append(sprinkler['area'] * max_demand) sprinkler_df['max_demand'] = sprinkler_demands # 绘制灌溉需求变化图 plt.figure(figsize=(12, 6)) for crop, demand in irrigation_demand.items(): plt.plot(daily_avg_moisture.index, demand, label=f'{crop}需求') plt.title('2021年7月不同作物每日灌溉需求') plt.xlabel('日期') plt.ylabel('灌溉需求 (L/m²)') plt.legend() plt.grid(True) plt.xticks(rotation=45) plt.tight_layout() plt.savefig('作物灌溉需求变化图.png', dpi=300) plt.show() return irrigation_demand, sprinkler_df # ==================== 喷头布局生成 ==================== def generate_sprinkler_layout(farm_size_x=FARM_SIZE_X, farm_size_y=FARM_SIZE_Y, radius=SPRINKLER_RADIUS): """ 根据农场实际形状生成六角形喷头布局 """ spacing = radius * 1.5 # 喷头间距 sprinklers = [] # 六角形网格生成 rows = int(farm_size_y / (spacing * np.sqrt(3)/2)) + 2 cols = int(farm_size_x / spacing) + 2 for i in range(rows): for j in range(cols): x = j * spacing y = i * spacing * np.sqrt(3)/2 # 奇数行偏移 if i % 2 == 1: x += spacing / 2 # 确保喷头在农场范围内 if 0 <= x <= farm_size_x and 0 <= y <= farm_size_y: # 确定喷头所在的作物区域 crop_type = None for crop, region in CROP_REGIONS.items(): if region['x_min'] <= x <= region['x_max'] and region['y_min'] <= y <= region['y_max']: crop_type = crop break sprinklers.append({ 'id': len(sprinklers), 'x': x, 'y': y, 'radius': radius, 'crop_type': crop_type }) return pd.DataFrame(sprinklers) def calculate_sprinkler_coverage(sprinkler_df, farm_size_x=FARM_SIZE_X, farm_size_y=FARM_SIZE_Y): """ 计算每个喷头的覆盖面积(使用Voronoi图划分) """ points = sprinkler_df[['x', 'y']].values # 创建Voronoi图 vor = Voronoi(points) # 计算每个Voronoi单元的面积 areas = [] for region in vor.regions: if not -1 in region and len(region) > 0: polygon = vor.vertices[region] try: hull = ConvexHull(polygon) area = hull.volume # 对于2D,volume是面积 areas.append(area) except: # 对于无效区域使用默认面积 areas.append((farm_size_x * farm_size_y) / len(sprinkler_df)) else: areas.append((farm_size_x * farm_size_y) / len(sprinkler_df)) # 确保面积不为负且不超过农场总面积 areas = np.clip(areas, 0, farm_size_x * farm_size_y) sprinkler_df['area'] = areas[:len(sprinkler_df)] return sprinkler_df, vor # ==================== 多储水罐优化 ==================== def determine_optimal_clusters(sprinkler_df, max_clusters=10): """ 使用肘部法和轮廓系数确定最佳聚类数量,考虑作物类型 """ # 创建特征矩阵:位置 + 作物类型(one-hot编码) coordinates = sprinkler_df[['x', 'y']].values crop_types = pd.get_dummies(sprinkler_df['crop_type']).values # 标准化特征 features = np.hstack([coordinates, crop_types]) scaler = StandardScaler() scaled_features = scaler.fit_transform(features) # 计算不同聚类数量的SSE和轮廓系数 sse = [] silhouette_scores = [] k_range = range(2, max_clusters + 1) for k in k_range: kmeans = KMeans(n_clusters=k, random_state=42, n_init=10) kmeans.fit(scaled_features) sse.append(kmeans.inertia_) if k > 1: # 轮廓系数需要至少2个聚类 silhouette_scores.append(silhouette_score(scaled_features, kmeans.labels_)) else: silhouette_scores.append(0) # 绘制肘部法曲线 plt.figure(figsize=(12, 5)) plt.subplot(1, 2, 1) plt.plot(k_range, sse, 'bo-') plt.xlabel('聚类数量') plt.ylabel('SSE') plt.title('肘部法') plt.grid(True) plt.subplot(1, 2, 2) plt.plot(k_range[1:], silhouette_scores[1:], 'ro-') plt.xlabel('聚类数量') plt.ylabel('轮廓系数') plt.title('轮廓系数法') plt.grid(True) plt.tight_layout() plt.savefig('聚类数量选择.png', dpi=300) plt.show() # 选择最佳聚类数量 (肘部法 + 轮廓系数) # 计算SSE的下降率 sse_diff = np.diff(sse) sse_ratio = sse_diff[:-1] / sse_diff[1:] # 找到肘点 (SSE下降率最大的点) elbow_point = np.argmax(sse_ratio) + 2 # 从k=2开始 # 找到轮廓系数最大的点 best_silhouette = np.argmax(silhouette_scores[1:]) + 2 # 综合选择最佳聚类数量 optimal_clusters = min(max(3, elbow_point), max(3, best_silhouette)) # 至少3个储水罐 logger.info(f"肘部法建议聚类数量: {elbow_point}") logger.info(f"轮廓系数法建议聚类数量: {best_silhouette}") logger.info(f"最终选择聚类数量: {optimal_clusters}") return optimal_clusters def generate_candidate_tanks(sprinkler_df, num_tanks): """ 生成候选储水罐位置,考虑作物类型 """ # 创建特征矩阵:位置 + 作物类型(one-hot编码) coordinates = sprinkler_df[['x', 'y']].values crop_types = pd.get_dummies(sprinkler_df['crop_type']).values # 标准化特征 features = np.hstack([coordinates, crop_types]) scaler = StandardScaler() scaled_features = scaler.fit_transform(features) kmeans = KMeans(n_clusters=num_tanks, random_state=42, n_init=10) kmeans.fit(scaled_features) # 获取聚类中心的位置部分(忽略作物类型部分) cluster_centers = kmeans.cluster_centers_[:, :2] # 反标准化位置 cluster_centers = scaler.inverse_transform( np.hstack([cluster_centers, np.zeros((num_tanks, crop_types.shape[1]))]) )[:, :2] return cluster_centers, kmeans.labels_ def calculate_distance_matrix(sprinkler_df, tank_positions): """ 计算喷头到储水罐的距离矩阵 """ num_sprinklers = len(sprinkler_df) num_tanks = len(tank_positions) distances = np.zeros((num_sprinklers, num_tanks)) for i, sprinkler in sprinkler_df.iterrows(): for j, tank in enumerate(tank_positions): dist = np.sqrt((sprinkler['x'] - tank[0])**2 + (sprinkler['y'] - tank[1])**2) distances[i, j] = dist return distances def two_stage_optimization(sprinkler_df, irrigation_demand, tank_positions): """ 两阶段优化:先分配喷头,再优化容量和管道 """ # 阶段1: 喷头分配到储水罐或管道 distances = calculate_distance_matrix(sprinkler_df, tank_positions) num_sprinklers = len(sprinkler_df) num_tanks = len(tank_positions) # 计算每个喷头的最大日需求 sprinkler_max_demands = sprinkler_df['max_demand'].values # 分配喷头到最近的储水罐(如果在15m内),否则标记为直接连接管道 assignments = np.argmin(distances, axis=1) direct_pipe_mask = np.min(distances, axis=1) > SPRINKLER_RADIUS # 限制直接连接管道的比例不超过10% direct_ratio = np.sum(direct_pipe_mask) / num_sprinklers if direct_ratio > 0.1: # 如果直接连接比例超过10%,重新分配最远的喷头 sorted_indices = np.argsort(np.min(distances, axis=1))[::-1] # 从最远到最近 for i in sorted_indices: if direct_pipe_mask[i] and direct_ratio > 0.1: direct_pipe_mask[i] = False direct_ratio = np.sum(direct_pipe_mask) / num_sprinklers if direct_ratio <= 0.1: break # 阶段2: 优化储水罐容量和管道流量 def objective(vars): V = vars[:num_tanks] # 储水罐容量 Q = vars[num_tanks:num_tanks+num_tanks] # 到每个储水罐的管道流量 # 储水罐成本 tank_cost = TANK_COST_PER_LITER * np.sum(V) # 管道成本 pipe_cost = 0 for j in range(num_tanks): L = np.sqrt((RIVER_POINT[0] - tank_positions[j][0])**2 + (RIVER_POINT[1] - tank_positions[j][1])**2) pipe_cost += PIPE_LENGTH_COEFF * (L ** PIPE_LENGTH_EXP) + PIPE_FLOW_COEFF * (Q[j] ** PIPE_FLOW_EXP) # 惩罚项:储水罐容量不足 penalty = 0 for j in range(num_tanks): # 计算该储水罐覆盖喷头的总最大需求 tank_demand = np.sum(sprinkler_max_demands[(assignments == j) & ~direct_pipe_mask]) if V[j] < tank_demand: penalty += 1000 * (tank_demand - V[j]) # 惩罚项:直接连接管道过多 direct_penalty = 10000 * max(0, np.sum(direct_pipe_mask) / num_sprinklers - 0.1) return tank_cost + pipe_cost + penalty + direct_penalty # 约束条件 constraints = [] # 流量约束:管道流量应大于等于储水罐需求 for j in range(num_tanks): tank_demand = np.sum(sprinkler_max_demands[(assignments == j) & ~direct_pipe_mask]) constraints.append({'type': 'ineq', 'fun': lambda x, j=j, td=tank_demand: x[num_tanks+j] - td}) # 容量约束 for j in range(num_tanks): constraints.append({'type': 'ineq', 'fun': lambda x, j=j: x[j]}) # V[j] ≥ 0 # 初始值 initial_V = [np.sum(sprinkler_max_demands[(assignments == j) & ~direct_pipe_mask]) for j in range(num_tanks)] initial_Q = [1.2 * v for v in initial_V] # 流量比容量多20%以提供缓冲 x0 = initial_V + initial_Q # 边界 bounds = Bounds([0] * (2 * num_tanks), [np.inf] * (2 * num_tanks)) # 使用SLSQP进行优化 logger.info("开始优化...") result = minimize( objective, x0, bounds=bounds, constraints=constraints, method='SLSQP', options={'disp': True, 'ftol': 1e-6, 'maxiter': 100} ) return result, assignments, direct_pipe_mask # ==================== 成本计算与可视化 ==================== def calculate_total_cost(result, sprinkler_df, tank_positions, assignments, direct_pipe_mask): """ 计算总成本 """ num_tanks = len(tank_positions) V_opt = result.x[:num_tanks] Q_opt = result.x[num_tanks:2*num_tanks] # 储水罐成本 tank_cost = TANK_COST_PER_LITER * np.sum(V_opt) # 管道成本 pipe_cost = 0 for j in range(num_tanks): L = np.sqrt((RIVER_POINT[0] - tank_positions[j][0])**2 + (RIVER_POINT[1] - tank_positions[j][1])**2) pipe_cost += PIPE_LENGTH_COEFF * (L ** PIPE_LENGTH_EXP) + PIPE_FLOW_COEFF * (Q_opt[j] ** PIPE_FLOW_EXP) # 直接连接管道的喷头成本 direct_sprinklers = sprinkler_df[direct_pipe_mask] if len(direct_sprinklers) > 0: # 计算主管道长度(到直接连接喷头的中心) center_x = np.mean(direct_sprinklers['x']) center_y = np.mean(direct_sprinklers['y']) L_direct = np.sqrt((RIVER_POINT[0] - center_x)**2 + (RIVER_POINT[1] - center_y)**2) Q_direct = np.sum(sprinkler_df[direct_pipe_mask]['max_demand']) pipe_cost += PIPE_LENGTH_COEFF * (L_direct ** PIPE_LENGTH_EXP) + PIPE_FLOW_COEFF * (Q_direct ** PIPE_FLOW_EXP) total_cost = tank_cost + pipe_cost return total_cost, tank_cost, pipe_cost def visualize_system(sprinkler_df, tank_positions, assignments, direct_pipe_mask, vor): """ 可视化灌溉系统 """ fig, ax = plt.subplots(figsize=(14, 12)) # 绘制农场边界 ax.plot([0, FARM_SIZE_X, FARM_SIZE_X, 0, 0], [0, 0, FARM_SIZE_Y, FARM_SIZE_Y, 0], 'k-', linewidth=2) # 绘制河流 if RIVER_POSITION == 'south': ax.plot([0, FARM_SIZE_X], [FARM_SIZE_Y, FARM_SIZE_Y], 'b-', linewidth=4, label='河流') # 绘制作物区域 colors = {'sorghum': 'lightgreen', 'corn': 'lightyellow', 'soybean': 'lightblue'} for crop, region in CROP_REGIONS.items(): rect = plt.Rectangle((region['x_min'], region['y_min']), region['x_max'] - region['x_min'], region['y_max'] - region['y_min'], alpha=0.3, color=colors[crop], label=crop) ax.add_patch(rect) # 绘制Voronoi图 voronoi_plot_2d(vor, ax=ax, show_points=False, show_vertices=False, line_colors='gray', line_width=0.5, alpha=0.5) # 绘制喷头 tank_colors = cm.rainbow(np.linspace(0, 1, len(tank_positions))) for i, sprinkler in sprinkler_df.iterrows(): if direct_pipe_mask[i]: # 直接连接管道的喷头 ax.plot(sprinkler['x'], sprinkler['y'], 'ko', markersize=4) ax.add_patch(plt.Circle((sprinkler['x'], sprinkler['y']), SPRINKLER_RADIUS, color='gray', alpha=0.1)) else: # 由储水罐覆盖的喷头 tank_id = assignments[i] color = tank_colors[tank_id] ax.plot(sprinkler['x'], sprinkler['y'], 'o', color=color, markersize=4) ax.add_patch(plt.Circle((sprinkler['x'], sprinkler['y']), SPRINKLER_RADIUS, color=color, alpha=0.1)) # 绘制储水罐 for j, tank in enumerate(tank_positions): color = tank_colors[j] ax.plot(tank[0], tank[1], 's', color=color, markersize=10, markeredgecolor='black', markeredgewidth=2) ax.add_patch(plt.Circle((tank[0], tank[1]), SPRINKLER_RADIUS*2, color=color, alpha=0.2)) ax.text(tank[0], tank[1], f'T{j+1}', fontsize=12, ha='center', va='center', fontweight='bold') # 绘制管道 for j, tank in enumerate(tank_positions): ax.plot([RIVER_POINT[0], tank[0]], [RIVER_POINT[1], tank[1]], 'r-', linewidth=2, label='管道' if j == 0 else "") # 标注管道长度和流量 mid_x = (RIVER_POINT[0] + tank[0]) / 2 mid_y = (RIVER_POINT[1] + tank[1]) / 2 length = np.sqrt((RIVER_POINT[0]-tank[0])**2 + (RIVER_POINT[1]-tank[1])**2) ax.text(mid_x, mid_y, f'{length:.1f}m\n{Q_opt[j]:.0f}L/d', fontsize=8, bbox=dict(boxstyle="round,pad=0.3", facecolor="white", alpha=0.7)) ax.set_xlabel('X坐标 (m)') ax.set_ylabel('Y坐标 (m)') ax.set_title('农业灌溉系统布局优化') ax.legend() ax.grid(True) plt.savefig('灌溉系统布局图.png', dpi=300) plt.show() def plot_cost_breakdown(tank_cost, pipe_cost): """ 绘制成本分解图 """ labels = ['储水罐成本', '管道成本'] sizes = [tank_cost, pipe_cost] colors = ['lightblue', 'lightcoral'] plt.figure(figsize=(8, 8)) plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90) plt.axis('equal') plt.title('成本分解') plt.savefig('成本分解图.png', dpi=300) plt.show() def plot_tank_capacity_analysis(V_opt, tank_demands): """ 绘制储水罐容量分析图 """ num_tanks = len(V_opt) x = np.arange(num_tanks) width = 0.35 fig, ax = plt.subplots(figsize=(10, 6)) rects1 = ax.bar(x - width/2, V_opt, width, label='设计容量') rects2 = ax.bar(x + width/2, tank_demands, width, label='需求容量') ax.set_xlabel('储水罐编号') ax.set_ylabel('容量 (L)') ax.set_title('储水罐容量与需求对比') ax.set_xticks(x) ax.set_xticklabels([f'T{i+1}' for i in range(num_tanks)]) ax.legend() # 添加数值标签 for i, v in enumerate(V_opt): ax.text(i - width/2, v + max(V_opt)*0.01, f'{v:.0f}', ha='center') for i, v in enumerate(tank_demands): ax.text(i + width/2, v + max(V_opt)*0.01, f'{v:.0f}', ha='center') plt.tight_layout() plt.savefig('储水罐容量分析.png', dpi=300) plt.show() # ==================== 主函数 ==================== def main(): """ 主优化流程 """ logger.info("开始农业灌溉系统优化...") # 1. 加载和处理数据 daily_avg_moisture, july_data = load_soil_moisture_data() # 2. 生成喷头布局 sprinkler_df = generate_sprinkler_layout() sprinkler_df, vor = calculate_sprinkler_coverage(sprinkler_df) logger.info(f"生成喷头数量: {len(sprinkler_df)}") # 3. 计算灌溉需求 irrigation_demand, sprinkler_df = calculate_irrigation_demand(daily_avg_moisture, sprinkler_df) logger.info(f"最大日灌溉需求: {sprinkler_df['max_demand'].sum()/sprinkler_df['area'].sum():.2f} L/m²") # 4. 确定最佳聚类数量 optimal_clusters = determine_optimal_clusters(sprinkler_df, max_clusters=8) # 5. 生成候选储水罐位置 tank_positions, cluster_labels = generate_candidate_tanks(sprinkler_df, optimal_clusters) logger.info(f"候选储水罐位置: {tank_positions}") # 6. 两阶段优化 result, assignments, direct_pipe_mask = two_stage_optimization( sprinkler_df, irrigation_demand, tank_positions) if result.success: logger.info("优化成功!") # 7. 计算成本 total_cost, tank_cost, pipe_cost = calculate_total_cost( result, sprinkler_df, tank_positions, assignments, direct_pipe_mask) logger.info(f"总成本: {total_cost:.2f} 元") logger.info(f"储水罐成本: {tank_cost:.2f} 元 ({tank_cost/total_cost*100:.1f}%)") logger.info(f"管道成本: {pipe_cost:.2f} 元 ({pipe_cost/total_cost*100:.1f}%)") logger.info(f"直接连接喷头比例: {np.sum(direct_pipe_mask)/len(sprinkler_df)*100:.1f}%") # 8. 可视化 visualize_system(sprinkler_df, tank_positions, assignments, direct_pipe_mask, vor) plot_cost_breakdown(tank_cost, pipe_cost) # 9. 储水罐容量分析 num_tanks = len(tank_positions) V_opt = result.x[:num_tanks] tank_demands = [] for j in range(num_tanks): tank_demand = np.sum(sprinkler_df['max_demand'][(assignments == j) & ~direct_pipe_mask]) tank_demands.append(tank_demand) plot_tank_capacity_analysis(V_opt, tank_demands) # 10. 输出结果表格 output_results(sprinkler_df, tank_positions, result, assignments, direct_pipe_mask) else: logger.error("优化失败:", result.message) def output_results(sprinkler_df, tank_positions, result, assignments, direct_pipe_mask): """ 输出优化结果表格 """ num_tanks = len(tank_positions) V_opt = result.x[:num_tanks] Q_opt = result.x[num_tanks:2*num_tanks] # 计算每个储水罐的需求 tank_demands = [] for j in range(num_tanks): tank_demand = np.sum(sprinkler_df['max_demand'][(assignments == j) & ~direct_pipe_mask]) tank_demands.append(tank_demand) # 创建结果DataFrame results_df = pd.DataFrame({ '储水罐编号': range(1, num_tanks+1), 'X坐标': [f"{tank[0]:.1f}" for tank in tank_positions], 'Y坐标': [f"{tank[1]:.1f}" for tank in tank_positions], '容量(L)': [f"{v:.0f}" for v in V_opt], '需求容量(L)': [f"{d:.0f}" for d in tank_demands], '安全余量(%)': [f"{(v-d)/d*100:.1f}" if d > 0 else "N/A" for v, d in zip(V_opt, tank_demands)], '管道流量(L/天)': [f"{q:.0f}" for q in Q_opt], '管道长度(m)': [f"{np.sqrt((RIVER_POINT[0]-tank[0])**2 + (RIVER_POINT[1]-tank[1])**2):.1f}" for tank in tank_positions] }) # 计算覆盖统计 coverage_stats = [] for j in range(num_tanks): covered = np.sum((assignments == j) & ~direct_pipe_mask) coverage_stats.append(covered) results_df['覆盖喷头数'] = coverage_stats results_df['直接连接喷头数'] = np.sum(direct_pipe_mask) # 添加直接连接喷头信息 direct_sprinklers = sprinkler_df[direct_pipe_mask] if len(direct_sprinklers) > 0: center_x = np.mean(direct_sprinklers['x']) center_y = np.mean(direct_sprinklers['y']) L_direct = np.sqrt((RIVER_POINT[0] - center_x)**2 + (RIVER_POINT[1] - center_y)**2) Q_direct = np.sum(sprinkler_df[direct_pipe_mask]['max_demand']) results_df['直接连接中心X'] = f"{center_x:.1f}" results_df['直接连接中心Y'] = f"{center_y:.1f}" results_df['直接连接管道长度'] = f"{L_direct:.1f}" results_df['直接连接流量'] = f"{Q_direct:.0f}" logger.info("\n优化结果详情:") print(results_df.to_string(index=False)) # 保存结果 results_df.to_csv('灌溉系统优化结果.csv', index=False, encoding='utf-8-sig') logger.info("结果已保存到 '灌溉系统优化结果.csv'") if __name__ == "__main__": main()修改返回完整代码
最新发布
08-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值