我玩 CodeWorld 并使用“入口點”activityOf() 來模擬由坦克組成的物理系統。這里我們有一個水箱,其出口流量 qout(h) 取決于容積水平的高度。當然,對于嚴肅的模擬作業,應該使用其他軟體,但在這里做仍然很有趣!
program = activityOf(initial, change, tank_water)
composedOf = pictures
-- Initial value and parameter
initial(rs) = 5
g = 9.81
area = 0.015
-- Inlet flow
qin = 0.0
-- Dynamics using Euler approximation
qout(h) = area*sqrt(2*g*max(h,0))
change(h, TimePassing(dt)) = max(h,0) - qout(h)*dt qin*dt
change(h, other) = h
-- Animation of system
tank_water(h) = composedOf [tank, water(h), graph, coordinatePlane]
tank = translated(thickRectangle(width,height,0.2),position,4)
width = 3
height = 8
position = -5
water(h) = translated(colored(solidPolygon [(-width/2, 0), (-width/2, h), (width/2, h), (width/2,0)],
light(blue)),position,0)
-- Graph of evolution of h(t) - here used monitored values and about 5 seconds between each data point
graph = polyline [(0,5), (1,3.7), (2,2.3), (3,1.3), (4,0.7), (5,0.2), (6, 0)]
出于教育目的,我認為最好將影片與圖表中的圖表結合起來,以顯示高度隨時間的變化情況。在這里我在代碼中輸入了一個“假”圖,因為它很容易測量(我也可以輸入決議解來使圖適應引數)。
我想知道如何包含一個子系統,該子系統從影片中收集資料并在模擬進行時將其呈現在圖表中。有任何想法嗎?
我想到的一個繁瑣的想法是擴展模型狀態,包括在模擬程序中要收集的測量點。我們可以事先說我們收集了 10 個 h 和 t 的樣本,時間距離為 5 秒,并在資料進入時擴展圖表。
另一個想法是以某種方式“添加”一些通用資料記錄器到 activityOf() 程式,該程式將資料存盤在一個檔案中,之后您可以使用任何軟體進行研究。也許這樣的記錄器已經在 Haskell 環境中可用了?
但我非常不確定如何做到這一點,這里也許有一些更好、更通用的方法來做到這一點?
uj5u.com熱心網友回復:
我將使用“常規”Haskell 環境https://code.world/haskell 的語法和型別進行回應。
a 的型別activityOf是:
activityOf ::
world ->
(Event -> world -> world) ->
(world -> Picture) ->
IO ()
正如您所觀察到的,沒有內置的方法來記錄值??并繪制它們。添加它activityOf似乎是錯誤的(我們可能想要添加很多東西)。
但是對于這樣的函式,您想要什么型別的呢?也許如下:
activityWithGraphOf ::
world ->
(Event -> world -> world) ->
(world -> Picture) ->
(world -> Double) ->
IO ()
考慮到這個抽象,我會去實作那個功能
- 它本身
activityOf當然會使用 - 它會跟蹤
world狀態 - 它會記錄時間
- 它會跟蹤最近的圖表值
TimePassing如果需要,它可能會將傳入的資料分成兩部分,以在正確的時間間隔對圖形進行采樣。- 它會將
Picture包裝的活動提供的與圖形組合在一起
聽起來像一個有趣的練習。現在我有了一個通用函式,可以用于許多圖形繪制模擬。
uj5u.com熱心網友回復:
我提出了一個“繁瑣”的解決方案。希望我能從我得到的輸入中更好地構建它。感謝改進建議,以便代碼可以更短。我覺得元組處理很笨拙。進一步創建表格和稍后的圖表可以與罐程序更加分離。這將有助于重用 CodeWorld 中的其他模擬任務。歡迎改進!
program = activityOf(initial, change, tank_water)
composedOf = pictures
-- Initial values of the total state, i.e. state_and_table
initial(rs) = state_and_table
state_and_table = (time_0, h_0, table_1_0, table_2_0, table_3_0, table_4_0, table_5_0)
time_0 = 0
h_0 = 7
table_1_0 = 0
table_2_0 = 0
table_3_0 = 0
table_4_0 = 0
table_5_0 = 0
-- Functions to read elements of state_and_table and from a tuple
time_of(time_value,_,_,_,_,_,_) = time_value
h_of(_,h_value,_,_,_,_,_) = h_value
table_1_of(_,_,table_value,_,_,_,_) = table_value
table_2_of(_,_,_,table_value,_,_,_) = table_value
table_3_of(_,_,_,_,table_value,_,_) = table_value
table_4_of(_,_,_,_,_,table_value,_) = table_value
table_5_of(_,_,_,_,_,_,table_value) = table_value
second_of(_,x_value) = x_value
-- Parameters related to the water flow
g = 9.81
area = 0.02
-- Parameters of the tank
width = 3
height = 8
position = -5
-- Inlet and outlet flow
qin = 0.0
qout(h) = area*sqrt(2*g*max(h,0))
-- Change of state_and_table
change(state_and_table, TimePassing(dt)) =
-- Update time
(time_of(state_and_table) dt,
-- Physical state equation using Euler approximation
max(h_of(state_and_table),0) - qout(h_of(state_and_table))*dt qin*dt,
-- Event of recording state to table at predfined times
table_1_update(state_and_table),
table_2_update(state_and_table),
table_3_update(state_and_table),
table_4_update(state_and_table),
table_5_update(state_and_table))
-- Default equation
change(state_and_table, other) = state_and_table
-- Events of recording state to table at given times
table_1_update(state_and_table)
| time_of(state_and_table) > 0 && table_1_of(state_and_table)==0 = h_of(state_and_table)
| otherwise = table_1_of(state_and_table)
table_2_update(state_and_table)
| time_of(state_and_table) > 15 && table_2_of(state_and_table)==0 = h_of(state_and_table)
| otherwise = table_2_of(state_and_table)
table_3_update(state_and_table)
| time_of(state_and_table) > 30 && table_3_of(state_and_table)==0 = h_of(state_and_table)
| otherwise = table_3_of(state_and_table)
table_4_update(state_and_table)
| time_of(state_and_table) > 45 && table_4_of(state_and_table)==0 = h_of(state_and_table)
| otherwise = table_4_of(state_and_table)
table_5_update(state_and_table)
| time_of(state_and_table) > 60 && table_5_of(state_and_table)==0 = h_of(state_and_table)
| otherwise = table_5_of(state_and_table)
-- Animation of system
tank_water(state_and_table) = composedOf [tank, water(h_of(state_and_table)),
graph(state_and_table), coordinatePlane]
tank = translated(thickRectangle(width,height,0.2),position,4)
water(h) = translated(colored(solidPolygon [(-width/2, 0), (-width/2, h), (width/2, h), (width/2,0)],
light(blue)),position,0)
-- Graph of evolution of h(t) - note time scale is 1 = 15s etc
graph(state_and_table) = polyline [ p | p <-
[(0, table_1_of(state_and_table)),
(5/2, table_2_of(state_and_table)),
(10/2, table_3_of(state_and_table)),
(15/2, table_4_of(state_and_table)),
(20/2, table_5_of(state_and_table))],
second_of(p) /=0]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/331234.html
