WEB-DB PRESS122号の数理最適化スケジュールアプリを改修してデプロイしてみた

3 min read読了の目安(約3200字

WEB+DB PRESS 122号 P128- に掲載の看護師のスケジュールを数理最適化で解くアプリを実際に Streamlit.share でデプロイしてみました。

https://share.streamlit.io/kjman678/schedule/main/sched.py

詳細はWEB+DB PRESS 122号をご確認ください。

streamlit.share 上でのデプロイについては過去記事を参照ください。

https://zenn.dev/megane_otoko/articles/017_deploy_streamlit

なお、streamlit.share 上には mip、more_itertools ライブラリがないので、requirements.txt の設定が必要です。

本ブログでは改修点について記載します。

サンプルcsvデータのダウンロード機能の実装

markdownとして記載する必要があるようです。

また、Base64によるバイナリデータの文字列化が必要となるようなので、base64 ライブラリをインポートします。

import base64

download=st.sidebar.button('サンプルCSVをダウンロード') # ボタン上に表示されるテキスト
if download:
  'サンプルCSV内訳' # ボタンを押すと表示されるテキスト
  df_download= pd.DataFrame( # ダウンロードするcsvの中身
    [
     ["佐藤", "休", "", "", "", "", "", "", ""],
     ["田中", "", "休", "", "", "", "", "", ""],
     ["鈴木", "", "", "休", "", "", "", "", ""],
     ["高橋", "", "", "", "", "", "", "", "休"],
    ]
)
  df_download.columns=["Name", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8"]
  df_download
  
  csv = df_download.to_csv(index=False) # ダウンロードするcsvデータの作成

  b64 = base64.b64encode(csv.encode()).decode()  # some strings
  
  linko= f'<a href="data:file/csv;base64,{b64}" download="sample.csv">クリックしてcsvをダウンロード</a>' # ダウンロード用リンクのテキスト
  
  st.markdown(linko, unsafe_allow_html=True) # markdownとして表示

これでサイドバーにあるダウンロードボタンを押すと、サンプルcsvの中身が表示され、ダウンロード用のリンクが表示されます。

https://discuss.streamlit.io/t/how-to-add-a-download-excel-csv-function-to-a-button/4474

https://www.python.ambitious-engineer.com/archives/2066

表のサイズの指定

ブラウザに表示される名前の部分が見切れていたので、表のサイズを指定してちゃんと表示されるようにしました。

streamlit.datafreame()の引数に、width、height を設定してやります。

st.dataframe(res.style.applymap(f), width=500, height=300)

ステータスの日本語化

数理最適化の処理結果がそのまま表示されていたので日本語に修正しました。

status = ""
if m.status == OptimizationStatus.OPTIMAL:
  status = "最適解が算定されました"
elif m.status == OptimizationStatus.INFEASIBLE:
  status = "実行不可能でした"
elif m.status == OptimizationStatus.UNBOUNDED:
  status = "解が無限に存在します"
elif m.status == OptimizationStatus.FEASIBLE:
  status = "整数の実行可能解が見つかりましたが、これが最適解であるかどうかを判断する前に検索が中断されました。"
elif m.status == OptimizationStatus.INT_INFEASIBLE:
  status = "整数問題は実行不可能でした"
elif m.status == OptimizationStatus.NO_SOLUTION_FOUND:
  status = "整数の実行可能解が見つかりませんでした"
elif m.status == OptimizationStatus.LOADED:
  status = "問題はロードされましたが、最適解は実行されませんでした"
elif m.status == OptimizationStatus.CUTOFF:
  status = "現在のカットオフに対して実行可能な解決策はありません"
elif m.status == OptimizationStatus.ERROR:
  status = "エラーが発生しました"

https://python-mip.readthedocs.io/en/latest/classes.html

以上になります、最後までお読みいただきありがとうございました。