スクリーンショット_2019-12-28_22

Jupyter+Dashで配送計画

以前紹介したJupyterlab+DashはWndowsに対応していなかったようだが,JupyterならWindowsでも動くようだ.

とりあえず配送計画のGUIを作ってみた.

使うのはJupyterlabの方だ.CSSを使うと簡単に綺麗になる.

# Build AppViewer
# external CSS stylesheets
external_stylesheets = [
   'https://codepen.io/chriddyp/pen/bWLwgP.css'
]
app = dash.Dash(__name__,
               external_stylesheets=external_stylesheets)
# Build AppViewer 
from jupyterlab_dash import AppViewer
viewer = AppViewer()

レイアウトはこんな感じで,テーブルなどの中身は長くなるので他で定義しておく.よってこのままでは動かないので注意.

app.layout = html.Div(children=[ 
   html.H3('Vehicle Routing Solver Dashboard'),
   header_div,
   dcc.Tabs([
       dcc.Tab(label="Customer Data", children=[
           customer_table_div
       ]),
       dcc.Tab(label="Vehicle Data", children=[
           vehicle_table_div
       ]),
       dcc.Tab(label='Gannt Chart', children=[
           gannt_div
       ]),
       dcc.Tab(label='Result', children=[
           html.Div(className="row", 
              children=[
                html.Div(className="six columns", 
                  children=[map_div]),
                html.Div(className="six columns", 
                  children=[map_div2]),
              ]
           ),
           route_div
       ]) 
   ])  # end of Tabs    
])

CSSでsix columns表示のスタイルなどが定義されているので,半分の領域にdivを表示してくれる.全部では12 columnsだ.デザインとしてはDashのタブを利用して,種々の表示をタブで切り替えるようにした.Dashは複数ページにすると色々面倒なことが起こるので,できるだけ1ページにおさめるためだ.

#最適化のボタンを押すと,地図とガントチャートを表示
@app.callback([Output('output-state2', 'children'),Output("map","figure"),Output("gannt","figure") ],
             [Input('solve-button','n_clicks')],
             [State('input-box', 'value'),State("input-box-tw","value")])
def update_output2(n_clicks, input1, input2):
   if n_clicks>=1:
       if int(input2)==10000:
           obj, model = solve(int(input1))
       else:
           obj, model = solve(int(input1),int(input2))
       fig = make_fig(model)
       gannt_fig = gannt(model)
       
       save_route(model)
       
       return f"Obj.={obj}", fig, gannt_fig
   else:
       pass
# ルートを選択すると、選んだトラックを表示
@app.callback(
   Output('dd-output-container', 'children'),
   [Input('vehicle-dropdown', 'value')])
def update_output(value):
   return 'You have selected  vehicle {}'.format(value)
# ルートを選択すると、表を表示(同時に地図のルートを表示)
@app.callback(
   [Output('table-route','data'),Output("map2","figure")],
   [Input('vehicle-dropdown', 'value')])
def update_output(value):
   #route_df = make_route_df(int(value))
   route_df = pd.read_csv(f"route{value}.csv")
   #route_df = make_route_df(value,model)
   fig = make_fig_route(route_df) 
   return route_df.to_dict('records'), fig

viewer.show(app)

あとは,callback関数に入力,出力,状態のデコレータを付与して,最適化とかルート選択時の表示切り替えを定義するだけだ.もちろん,呼び出す関数の中では色々面倒なことを書いているが,配送最適化ソルバーMETROを使えば簡単に作ることができる.

冒頭の画面は地図とルート選択のdrop downの部分だ.Webアプリの開発は苦行だったが,昔のように楽しく作れるようになると良い.ただし,デバッグ環境が最悪なので,まだまだだ.よっぽど用心深いプログラマでないと,こう短時間には開発できないだろう.





この記事が気に入ったらサポートをしてみませんか?