前言:歡迎各位光臨本博客,這里小編帶你直接手撕**,文章并不復雜,愿諸君耐其心性,忘卻雜塵,道有所長!!!!
**🔥個人主頁:IF’Maxue-CSDN博客
🎬作者簡介:C++研發方向學習者
📖**個人專欄:
《C語言》
《C++深度學習》
《Linux》
《數據結構》
《數學建模》**??人生格言:生活是默默的堅持,毅力是永久的享受。不破不立,遠方請直行!
文章目錄
- 一、先搞懂:我們要解決啥問題?
- 二、核心計算:代碼怎么判斷“煙幕有沒有用”?
- 1. 先算單個煙幕的“有效時間段”
- 2. 合并重疊的時間段(避免重復計算)
- 3. 只算“導彈到達前”的有效時間
- 三、代碼優化:加了2個實用功能,結果直接看
- 1. 跑完直接顯示“最優遮蔽時長”
- 2. 參數自動存到Excel,不用手動記
- 四、怎么跑代碼?看2個關鍵步驟
- 1. 先補全“遺傳優化”的核心邏輯
- 2. 調參數平衡“速度”和“精度”
- 五、避坑提醒
- 最后:跑出來的結果長這樣
平時看軍事片里的煙幕遮蔽,其實背后藏著不少參數講究——比如無人機往哪個方向飛、飛多快、啥時候投煙幕、煙幕啥時候爆,這些都會影響“能擋住導彈多久”。我寫了一段代碼專門解決這個問題,能自動算出最優參數,還能直接看結果,今天就用大白話跟大家拆解清楚。
一、先搞懂:我們要解決啥問題?
簡單說,我們的目標是:讓3架無人機投的煙幕,在導彈飛到假目標前,“有效遮蔽時間”最長。
先明確幾個關鍵角色的初始設定(代碼里main
函數能直接改):
- 導彈起點:
[20000, 0, 2000]
(可以理解為x/y/z坐標,單位米) - 真目標位置:
[0, 200, 0]
(我們要保護的目標) - 3架無人機起點:比如“FY1”從
[17800, 0, 1800]
出發,每架位置都能調
代碼里用SmokeObscurationModel
這個“模型類”,把這些初始信息裝進去,后續所有計算都基于這個基礎。
二、核心計算:代碼怎么判斷“煙幕有沒有用”?
煙幕不是投了就有用,得算準“啥時候生效、生效多久、能不能覆蓋導彈飛來的關鍵期”。代碼里最核心的是calculate_effective_time
方法,我拆成3步說:
1. 先算單個煙幕的“有效時間段”
每架無人機投煙幕,都要算2個時間點:
- 煙幕生效時間:無人機飛了
drop_time
秒后投煙,煙幕再等blast_delay
秒爆炸,所以生效時間=drop_time + blast_delay
- 煙幕失效時間:煙幕爆炸后,有效時長是
effective_duration
(代碼里設的20秒),所以失效時間= 生效時間 + 20秒
比如代碼里這段,就是算單架無人機的煙幕時間段:
smoke_blast_time = drop_time + blast_delay # 生效時間
smoke_end_time = smoke_blast_time + self.effective_duration # 失效時間
intervals.append( (smoke_blast_time, smoke_end_time) ) # 存成“(生效,失效)”的格式
2. 合并重疊的時間段(避免重復計算)
3架無人機的煙幕可能會“疊buff”——比如A煙幕10-15秒生效,B煙幕12-18秒生效,重疊的2秒不能算2次。
代碼會把所有時間段排序,然后合并重疊部分:
intervals.sort() # 先按生效時間排序
merged = [intervals[0]] # 先拿第一個時間段當基礎
for current in intervals[1:]:last = merged[-1]if current[0] <= last[1]: # 如果當前時間段和上一個重疊merged[-1] = (last[0], max(last[1], current[1])) # 合并成一個長時間段else:merged.append(current) # 不重疊就直接加進去
3. 只算“導彈到達前”的有效時間
煙幕再久,導彈都已經炸了也沒用。所以要先算導彈飛到假目標的時間(missile_arrival_time
方法):
“導彈飛的距離 ÷ 導彈速度(代碼里設300m/s)”,比如從20000米外飛過來,大概要60多秒。
然后只算“煙幕時間段”和“導彈到達前”的交集:
total = 0
for interval in merged:start = max(0, interval[0]) # 煙幕生效時間不能早于0end = min(missile_arrival, interval[1]) # 煙幕失效時間不能晚于導彈到達if start < end: # 只要有重疊,就加這段時間total += end - start
return total # 這就是最終的“有效遮蔽時間”
三、代碼優化:加了2個實用功能,結果直接看
原來的代碼跑起來看不到關鍵結果,我改了兩處,用起來更方便:
1. 跑完直接顯示“最優遮蔽時長”
代碼里的GeneticOptimizer
(遺傳優化器),會像“試錯進化”一樣,不斷調整無人機參數(方向、速度、投放時間、起爆延遲),找到最優解。
現在跑完會直接打印結果,比如:
# 優化器返回最優參數和對應時間
best_individual, best_time = optimizer.optimize()
print(f"最優遮蔽時長:{best_time:.2f}秒") # 直接顯示,比如“18.72秒”
2. 參數自動存到Excel,不用手動記
3架無人機的最優參數(比如FY1要朝30度飛、速度120m/s),會自動存到result2.xlsx
里,打開就能看:
df = pd.DataFrame({'無人機ID': ['FY1', 'FY2', 'FY3'],'方向角度(度)': best_individual[0::4], # 每4個參數對應1架無人機'飛行速度(m/s)': best_individual[1::4],'投放時間(s)': best_individual[2::4],'起爆延遲(s)': best_individual[3::4]
})
df.to_excel('result2.xlsx', index=False) # 保存到Excel
四、怎么跑代碼?看2個關鍵步驟
1. 先補全“遺傳優化”的核心邏輯
代碼里optimize
方法有個小缺口——“選擇、交叉、變異”這三步沒寫全(這是遺傳算法的核心,用來“篩選好參數、生成新參數”)。補全示例可以參考:
# 補全選擇:選效果好的參數留下
fitnesses = [self.evaluate(ind) for ind in population]
# 按適應度(有效時間)排序,選前50%
sorted_pop = sorted(zip(population, fitnesses), key=lambda x: x[1], reverse=True)
selected = [ind for ind, _ in sorted_pop[:self.pop_size//2]]# 補全交叉:兩個好參數“混合”出新品
offspring = []
for i in range(0, len(selected), 2):parent1 = selected[i]parent2 = selected[i+1] if i+1 < len(selected) else parent1# 隨機選個位置交叉參數cross_pos = random.randint(1, len(parent1)-1)child = parent1[:cross_pos] + parent2[cross_pos:]offspring.append(child)# 補全變異:偶爾改個參數,避免“鉆牛角尖”
for ind in offspring:if random.random() < 0.1: # 10%的變異概率param_idx = random.randint(0, len(ind)-1)low, high = self.param_ranges[param_idx]ind[param_idx] = random.uniform(low, high)# 新種群 = 選出來的好參數 + 新生成的參數
population = selected + offspring
2. 調參數平衡“速度”和“精度”
第一次跑可以先設小一點規模,避免等太久:
pop_size=50
(每次試50組參數,默認150)generations=50
(試50輪,默認80)
比如改優化器初始化:
optimizer = GeneticOptimizer(model, pop_size=50, generations=50)
五、避坑提醒
- 方向角度要轉弧度:代碼里已經用
np.radians(i_param)
把“度”轉成“弧度”(數學計算需要),不用自己再改; - 運行時間可能長:如果參數設得大(比如150種群、80世代),建議用多進程加速(可以搜“Python多進程計算”);
- 先小規模測試:第一次跑先試
pop_size=30
、generations=30
,確認代碼能跑通,再調大參數追求精度。
最后:跑出來的結果長這樣
最優遮蔽時長:18.72秒
參數已保存到result2.xlsx
打開Excel就能看到每架無人機的具體參數——比如FY1要朝45度飛,速度130m/s,10秒后投煙幕,5秒后起爆,這樣3架配合起來,能擋導彈近19秒。
如果想調整場景(比如導彈速度變了、無人機起點改了),直接改main
函數里的初始參數就行,代碼會自動重新算最優解~