乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

Python

今回はDuckDBを用いた
簡単SQLデータ分析についてです

解説動画はこちら



DuckDB

データ分析したいけどSQLならわかるんだけど
Python良く分からないなー

そんな時はDuckDB使えばいいじゃない!!

ということで
DuckDBのご紹介です。

Python上でSQLでデータ取得できるライブラリで
DataFrameをそのままSQLテーブルとして扱えます。

pandasの複雑なメソッドを覚えなくても
SQL操作で任意のデータが抽出できるものです。
pandasも加えると更に深掘りも出来てお得です。


早速使い方を見ていきましょう。


インストール

Google Colabでは
インストール済みなので不要です。

ローカルなどでインストールしていない人は
下記コマンドを実行しておいてください。
pip install duckdb


ライブラリの呼び出し

これだけです。
import duckdb


操作の基本
# 実行結果を表示
duckdb.sql("SQL文").show()

# 実行結果を変数に格納
データフレーム変数 = duckdb.sql("SQL文").df()

データフレームを作ってSQL文を投げてみます
import pandas as pd

df = pd.DataFrame({
    "a":[1,2,3],
    "b":[10,20,30]
})

sql = "SELECT * FROM df WHERE a > 1"

result_df = duckdb.sql(sql).df()
result_df

ab
0220
1330

DuckDBではデータフレームや
ファイルに直接SQL文のクエリを実行し
データ抽出が行えます。


SQL分をファイルから読み込みする
sql = open("ファイルパス").read()
df = duckdb.sql(sql).df()


ファイルを直接クエリする

sql = open("ファイルパス").read()
df = duckdb.sql(sql).df()
Google Colabなどでもファイルを置いておけば参照できます。



サンプルデータで簡易分析

sklearnサンプルデータを用いて
DuckDBでSQL分析してみましょう。

今回用いるデータは
「California Housing Dataset」

カリフォルニアの
地域ごとの住宅価格などのデータです。
下記コードで読み込みできます。
import duckdb
import pandas as pd
from sklearn.datasets import fetch_california_housing

# データロード
data = fetch_california_housing(as_frame=True)

df = data.frame

# DuckDBに接続
con = duckdb.connect()

# DataFrameを登録
con.register("housing", df)

データの準備が整ったら
DuckDBでSQLを実行してみましょう。

1.平均住宅価格
sql = """
SELECT
    AVG(MedHouseVal) as avg_price
FROM housing
"""

print(con.sql(sql).df())

2.住宅価格ランキング
sql = """
SELECT
    MedHouseVal
FROM housing
GROUP BY MedHouseVal
ORDER BY MedHouseVal DESC
LIMIT 10
"""

print(con.sql(sql).df())

3.地域ごとの住宅価格
sql = """
SELECT
    ROUND(Latitude,1) as lat,
    ROUND(Longitude,1) as lon,
    AVG(MedHouseVal) as avg_price,
    COUNT(*) as houses
FROM housing
GROUP BY lat, lon
ORDER BY avg_price DESC, houses DESC
LIMIT 15
"""

print(con.sql(sql).df())

4.収入と住宅価格
sql = """
SELECT
    CASE
        WHEN MedInc < 2 THEN 'low'
        WHEN MedInc < 5 THEN 'middle'
        ELSE 'high'
    END as income_level,
    AVG(MedHouseVal) as avg_price,
    COUNT(*) as cnt
FROM housing
GROUP BY income_level
ORDER BY avg_price DESC
"""

print(con.sql(sql).df())

5.家の広さと価格
sql = """
SELECT
    ROUND(AveRooms,0) as rooms,
    AVG(MedHouseVal) as price,
    COUNT(*) as n
FROM housing
GROUP BY rooms
HAVING n > 50
ORDER BY rooms
"""

print(con.sql(sql).df())


応用編

海沿い住宅は高いのかどうか

カリフォルニアは 西側が海なので
経度(Longitude) で判定


sql = """
SELECT
    CASE
        WHEN Longitude < -121 THEN 'coastal'
        ELSE 'inland'
    END AS location_type,
    AVG(MedHouseVal) AS avg_house_price,
    COUNT(*) AS houses
FROM housing
GROUP BY location_type
"""

result = con.sql(sql).df()

print("海沿い住宅(coastal) vs 内陸住宅(inland)")
print(result)

結果はコードを試すか
動画の方をご覧ください





まとめ


DuckDBを用いるとSQLを使ったデータ分析が
簡単に行えます。

Pythonのコードに慣れていなくても
直接ファイルにSQLを実行して分析結果を得られます。

複雑な集計もSQLを書ければ出来ちゃうので
データアナリストでなくても簡単に分析できちゃいます。

手元にデータが有るけどデータベース作れない
SQLは分かるけどpython分からない人向け
超お手軽ライブラリなので、おすすめです

ぜひ試してみてください
それでは。





 

今回は
FastAPI × htmx で作るプロトタイプを爆速実装する方法
についてです。


解説動画はこちら




 FastAPI × htmx

昨今のPython界隈は streamlit というライブラリのおかげで
フロントエンドもまとめて作ることができる様になりました。

そのおかげで、似たような見た目ばかりになる
streamlit臭のするデザインのモックばかり
という哀しい現象が起きてきています。

なので、こんな状況を打破すべく
 - デザイン部分は自由に作り込める
 - フロントエンド(React/Vue)の学習コストが高すぎて、モック作りが進まない
 - FastAPI(堅牢なバックエンド) + htmx(HTML だけで Ajax)というシンプル構成

という FastAPI + htmx の組み合わせの方法をお伝えします。


FastAPI とは何か

爆速で動く、現代的な『注文受け付け窓口』
Python言語で作られたWEBフレームワークです。

プログラムの実行速度が非常に速く
開発者がコードを書くスピードも速くなるように設計されており

仕様書(APIドキュメント)を自動で作成
型(データ)のチェックなども行ってくれます。


htmx とは何か

HTMLを『魔法の言葉』に変える道具
通常、Webページの一部を書き換えるには
JavaScriptをたくさん書く必要があります。

htmxだと「HTMLを数文字書き足すだけ」で実現でき
JavaScriptの部分をHTMLの属性だけで指示できるます。

学習コストが劇的に低い(HTMLが分かるなら)
ので初学者でも取り組みが楽です。


なので
この組み合わせが事業モックに最適です。

フロントとバックエンド、2つの学習コストが低い
シンプルでサクサク動くし、修正が簡単

モックとして作った後も
そのまま本番サービス転用も可能です。



環境構築と基本設定

Python側のインストール
pip install fastapi uvicorn jinja2 python-multipart


FASTAPIの実行方法
main.py のあるディレクトリで
uvicorn main:app --reload

WEBブラウザー側で http://127.0.0.1:8000/
にアクセスするとFASTAPIの画面が見れます。



デモプロジェクトの概要


デモプロジェクトのディレクトリ構成

├── main.py
└── templates/
    ├── index.html        (ベースレイアウト)
    ├── customer_list.html (顧客一覧)
    ├── customer_detail.html (顧客詳細)
    ├── stock_list.html    (在庫一覧)
    ├── stock_detail.html  (在庫詳細)
    └── chat.html          (AIチャット)


こんな内容のものを作ることができます。
スクリーンショット 2026-02-21 17.28.21
スクリーンショット 2026-02-21 17.28.28
スクリーンショット 2026-02-21 17.28.34




main.py のコード

FAST API のコードはこんな感じになっています。
from fastapi import FastAPI, Request, Form
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from datetime import datetime

app = FastAPI()
templates = Jinja2Templates(directory="templates")

# --- ダミーデータ ---
CUSTOMERS = {
    "C001": {"id": "C001", "name": "山田 太郎", "birth": "1985/05/20", "gender": "男性", "address": "東京都渋谷区...", "rank": "S", "items": [{"name": "ルンバ", "qty": 1, "price": 50000}]},
    "C002": {"id": "C002", "name": "佐藤 花子", "birth": "1992/11/02", "gender": "女性", "address": "大阪府大阪市...", "rank": "A", "items": [{"name": "化粧水", "qty": 2, "price": 4000}]},
    # ...他3件(実装上は同様に定義)
}

STOCKS = {
    "S001": {"id": "S001", "name": "ロキソニンS", "category": "解熱鎮痛剤", "count": 150, "desc": "第1類医薬品。速効性に優れています。"},
    "S002": {"id": "S002", "name": "アレグラFX", "category": "鼻炎薬", "count": 45, "desc": "眠くなりにくいアレルギー専用鼻炎薬。"},
}

def calc_age(birth_str):
    birth_date = datetime.strptime(birth_str, "%Y/%m/%d")
    today = datetime.today()
    return today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))

# --- Routes ---
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

# 1. 顧客管理
@app.get("/customers", response_class=HTMLResponse)
async def list_customers(request: Request):
    data = []
    for c in CUSTOMERS.values():
        data.append({**c, "age": calc_age(c['birth']), "birth_month": c['birth'][:7]})
    return templates.TemplateResponse("customer_list.html", {"request": request, "customers": data})

@app.get("/customers/{cid}", response_class=HTMLResponse)
async def detail_customer(request: Request, cid: str):
    c = CUSTOMERS.get(cid)
    return templates.TemplateResponse("customer_detail.html", {"request": request, "customer": c, "age": calc_age(c['birth'])})

# 2. 在庫チェック
@app.get("/stocks", response_class=HTMLResponse)
async def list_stocks(request: Request):
    return templates.TemplateResponse("stock_list.html", {"request": request, "stocks": STOCKS.values()})

@app.get("/stocks/{sid}", response_class=HTMLResponse)
async def detail_stock(request: Request, sid: str):
    return templates.TemplateResponse("stock_detail.html", {"request": request, "stock": STOCKS.get(sid)})

# 3. AIチャット
@app.get("/chat", response_class=HTMLResponse)
async def chat_page(request: Request):
    return templates.TemplateResponse("chat.html", {"request": request})

@app.post("/chat/send", response_class=HTMLResponse)
async def chat_send(request: Request, message: str = Form(...)):
    # 簡易的なAIレスポンスのシミュレーション
    ai_response = f"「{message}」について承知いたしました。AIとしての回答をここに表示します。"
    return f"""ここは省略しています"""

index.htmlなどは
AIエージェントを使って作ってみてください





まとめ


FAST API + htmx を用いると爆速でモック開発ができる
こちらは必要最低限の知識を学ぶだけで済む
デザイン部分は自由に作り込めるので好きなCSSを勉強しよう

足りない部分はAIエージェント使ってください
こちらは作りたいものを指示するだけ
本番作りもAIエージェントで爆速開発できます

PS
最近はこれでプロトタイプ開発していたりします。
AIエージェントも使いこなせると
爆速で開発できる様にできますよ

それでは。

 

プログラミング未経験の方のための
プログラミング学習講座を作成しました

その名も
「1時間で学べるPythonプログラミング」


講義動画はこちら




この講座は初学者の方が
短時間でPython言語を学ぶことのできる
プログラミング学習用の講座です

プログラミングが分からないない方は
Python言語を通じて
プログラミングの基礎を学習できます

講座は動画に加えてGoogle Colabを用いて
手元でコードを動かすことのできます
コードがどう動くのかを確認をしながら
進めていってください

資料はここ:
Google Colabの資料


00:00 1.はじめに
02:13 2.導入方法
02:55 3.GoogleColaboratoryの操作方法
06:19 4.Pythonの計算の基礎
27:27 5.Pythonの制御文
42:14 6.Pythonのクラス
49:11 7.Pythonのその他構文
64:30 8.まとめ

なおPythonチートシートを作成しています。

コーディングに迷った際に役に立ち

WEB検索する時間を無くして

作業時間を効率化できます。

note
Pythonチートシート


 

今回は最近公開された
Xのフィードアルゴリズムについてです

解説動画はこちら





Xのフィード・アルゴリズムの仕組みについて

Xのアルゴリズムコードはこちらになります。

xai



システムの4つの主要コンポーネント



Xのフィードアルゴリズムは
大きく4つのコンポーネントで構成されています。

4components



1. Home Mixer:
全体の司令塔(オーケストレーション層)です。

候補の抽出からランク付け、フィルタリングまでの全工程を管理します。
パイプラインは以下のステージで構成されています:

    1.Query Hydration - ユーザーのエンゲージメント履歴とメタデータを取得
    2.Candidate Sources - ThunderとPhoenixから候補を取得
    3.Hydration - 候補に追加データを付与
    4.Pre-Scoring Filters - 不適格な投稿を除外
    重複、古い投稿、自分の投稿、ブロック/ミュートしたアカウント、ミュートキーワードなど
    5.Scoring - 複数のスコアラーを順次適用
      Phoenix Scorer (ML予測)
      Weighted Scorer (予測の重み付け結合)
      Author Diversity Scorer (多様性のための減衰)
      OON Scorer (Out-of-Network調整)
    6.Selection - スコアでソートし、上位K件を選択
    7.Post-Selection Filters - 最終検証 (削除済み/スパム/暴力的コンテンツなど)
    8.Side Effects - キャッシュとログ記録


2. Thunder:
フォロー中ユーザーの投稿をリアルタイムで追跡するメモリ内ストアです。

ミリ秒単位の高速な読み込みを可能にします。

主要機能:
    1.Kafkaからのリアルタイム取り込み - 投稿の作成/削除イベントを消費
    2.ユーザー別ストア管理 - オリジナル投稿、リプライ/リツイート、動画投稿を分類
    3.サブミリ秒ルックアップ - 外部データベースにアクセスせずに高速検索
    4.自動トリミング - 保持期間を超えた古い投稿を自動削除

パフォーマンス最適化:
    1.タイムアウト機能 (デフォルト設定可能)
    2.ユーザーあたりの投稿数制限
    3.メモリ効率化のための自動容量調整


3. Phoenix:
機械学習(ML)を担当する心臓部です。

検索: フォロー外から好みに合う投稿を見つけ出します。
ランキング: ユーザーがその投稿に反応(いいねやリプライなど)する確率を予測します。

・アルゴリズムの詳細

2つのステップ

1. Retrieval(Retrieval段階):
数億のツイートから、2タワーモデル(Two-Tower Model)を用いて
「関連がありそうな数千件」をミリ秒単位で抽出します。

2. Ranking(ランキング段階):
抽出された数千件に対し、トランスフォーマーモデルを用いて
いいねやリポストなどの「具体的なエンゲージメント確率」を
詳細に予測・採点します。


Retrieval: Two-Tower Model (2タワーモデル)
   1. User Tower(ユーザー側): 
   ユーザーの属性(User Hashes)と、過去のエンゲージメント履歴(History)を
   トランスフォーマーで処理し、ユーザーの「現在の興味」を
   1つの数値ベクトル(User Representation)に凝縮します。

   2. Candidate Tower(ツイート側): 
   ツイート内容や投稿者情報を同様にベクトル化(Candidate Representation)します。

近さの計算(ドット積)
   「近さ」の採点は、ユーザーベクトルと
   ツイートベクトルの**ドット積(内積)**で行われます。

   ベクトル同士の向きが近い(興味が一致する)ほどスコアが高くなります。
   全てのツイートが事前にベクトル化されているため
   数億件の中から瞬時に上位K件を取得可能です。


Multi-Action Prediction (複数アクション予測)
   P(favorite)      - いいね
   P(reply)         - リプライ
   P(repost)        - リツイート
   P(quote)         - 引用ツイート
   P(click)         - クリック
   P(profile_click) - プロフィールクリック
   P(video_view)    - 動画視聴
   P(share)         - シェア
   P(dwell)         - 滞在時間
   P(follow_author) - フォロー
   P(not_interested) - 興味なし (負の重み)
   P(block_author)  - ブロック (負の重み)
   P(mute_author)   - ミュート (負の重み)
   P(report)        - 報告 (負の重み)


最終スコア計算:

   Final Score = Σ (weight_i × P(action_i))

ポジティブなアクションは正の重み、ネガティブなアクションは負の重みを持ちます。


4.Candidate Pipeline:
推薦システムを構築するための再利用可能なフレームワークです。
   Source データソースから候補を取得
   Hydrator 候補に追加特徴を付与
   Filter 表示すべきでない候補を除外
   Scorer ランキング用のスコアを計算
   Selector 上位候補をソート・選択
   SideEffect 非同期サイドエフェクト実行 (キャッシュ、ログ)
   QueryHydrator クエリコンテキストを準備




おすすめが表示されるまでの流れ


フィードが生成されるまでには、以下のステップを踏みます。
flow


1. データの準備 (Hydration): ユーザーの過去のエンゲージメント履歴や
フォローリストを読み込みます。

2. 候補の抽出: 「Thunder(フォロー内)」と「Phoenix(フォロー外)」の
両方から候補となる投稿を集めます。
   
3. フィルタリング(前処理): 重複した投稿、古すぎる投稿
自分がブロックしている相手の投稿、既に見た投稿などを除外します。

4. スコアリング(ランク付け):
 Grokベースのモデルが「いいね」「リプライ」「リポスト」
 「クリック」などの発生確率を個別に予測します。
 それらを重み付けして最終スコアを算出します。
 特定の著者ばかりに偏らないよう「著者多様性スコア」で調整をかけます。

5. 最終選定: スコアの高い順に並べ替え、最終的な表示候補を選び出します。

6. フィルタリング(後処理): 削除済み、スパム、暴力的なコンテンツなどが
混じっていないか最終チェックを行います。


おすすめに表示されやすくなるポイント

ポジティブエンゲージメント
以下のアクションが予測されるとスコアが上昇:

いいね、リツイート、リプライ
動画視聴 (一定時間以上の動画)
フォロー
クリック、シェア、滞在時間

In-Network(フォロー中)
フォローしているアカウントの投稿は優遇されます。

新鮮な投稿 古すぎない
タイムリーな投稿が優先されます。

動画コンテンツ 一定時間以上の動画は
特別な重み付けを受けます。



おすすめに除外されやすくなるポイント

ネガティブシグナル 以下が予測されると
スコアが低下:

興味なし、ブロック、ミュート、報告

ブロック・ミュートしたアカウント
完全に除外されます。

ミュートキーワード
設定したキーワードを含む投稿は除外。

自分自身の投稿
自分の投稿は「For You」から除外。

既に見た投稿
過去に表示された投稿は除外(Bloom Filter使用)。

古すぎる投稿
一定期間以上経過した投稿は除外。

削除済み・スパム・暴力的コンテンツ
最終段階で除外されます。



スコアリングの仕組み

最終スコア = Σ (重み × 各アクションの予測確率)

= P(いいね) × いいね重み
+ P(リツイート) × リツイート重み
+ P(リプライ) × リプライ重み
+ ...
+ P(ブロック) × ブロック重み (負の値)
+ P(ミュート) × ミュート重み (負の値)
処理順序:

1. Phoenix Transformer → ML予測
2. Weighted Scorer → 重み付け結合
3. Author Diversity Scorer → 多様性調整
4. OON Scorer → In/Out-of-Network調整
5. Selection → 上位K件選択



ポジティブシグナルの重み

以下のアクションが予測されると、投稿のスコアが上昇します:

アクション 説明 重要度
いいね (Favorite) ユーザーがいいねする確率 ⭐⭐⭐
リツイート (Retweet) リツイートする確率 ⭐⭐⭐
リプライ (Reply) リプライする確率 ⭐⭐⭐
引用ツイート (Quote) 引用ツイートする確率 ⭐⭐
クリック (Click) 投稿をクリックする確率 ⭐⭐
プロフィールクリック 投稿者のプロフィールをクリック ⭐⭐
動画視聴 (Video View) 動画を視聴する確率 ⭐⭐⭐
画像展開 (Photo Expand) 画像を展開する確率 ⭐⭐
シェア (Share) 外部にシェアする確率 ⭐⭐
滞在時間 (Dwell) 投稿に滞在する時間 ⭐⭐
フォロー (Follow Author) 投稿者をフォローする確率 ⭐⭐⭐


実践的アドバイス

表示されやすくするには:
✅ エンゲージメントを促す投稿(いいね、RT、リプライされやすい)
✅ 動画・画像付きコンテンツ
✅ タイムリーな情報
✅ フォロワーとの関係構築

除外されないために:
❌ スパム的な投稿を避ける
❌ 暴力的・不適切なコンテンツを避ける
❌ ミュートキーワードに引っかからない
❌ 重複投稿を避ける



まとめ

今回のXのアルゴリズム更新のポイントは
「人間による調整を徹底的に排除し
AI(Grokベースのモデル)に判断を委ねたこと」にあります。

システムは「フォロー内」と「フォロー外」の投稿を統合し
膨大なユーザー履歴から
「あなたが次にどのボタン(いいね、リプライ等)を押すか」
を精密に予測して並べ替えます。

また、多様性を確保しつつ、不適切なコンテンツや重複を
二段階のフィルタリングで排除する
非常に高度かつクリーンな構成になっています。


アルゴリズムの詳細コードを見たい方は
ぜひgithubの方を見てみてください

それでは。

今回は最適化問題を解くことが出来る
OR-Toolsについてです。

解説動画はこちら




OR-Toolsとは


Googleが開発している、組合せ最適化のためのライブラリ

様々な最適化問題を解くためのソルバーが充実していて
C++実装だが、Pythonなどいろいろな言語で使えます。


解ける最適化問題

次のような最適化問題を解くことができます。


1.配送ルート最適化
巡回セールスマン問題 : 1台の車両で最短経路を回る
配送計画問題 : 複数台の車両で分担して配送する

2.スケジューリングと制約プログラミング
決められた制約を全て満たしつつ、最適なスケジュールを組む
従業員のシフト作成
工場のライン計画

3.線形計画・整数計画(LP, MIP)
目的関数を最大化、または最小化する問題を数式で解く手法
生産計画 : 在庫と予算の範囲内で利益の最大化
リソース配分 : 予算内での広告効果最大化の割り当て

4.詰込み・割当問題
ナップサック問題 : 容量制限のあるバッグに価値が最大になるよう詰める
ビンピッキング問題 : サイズの異なる荷物を出来るだけ少ないトラックに詰める

5.ネットワークフロー
最大流問題 : パイプラインで一度に流せる最大量を求める
最小費用問題 : 指定量の輸送で、コストが最も安くなるルートと量の特定


インストール

Google Colab でも無いみたいなので、入れる必要あります。
pip install ortools


OR-Toolsの基本的な使い方

1.ライブラリの読み込み

解く問題に応じて、対応するライブラリを読み込みします
# CP-SATソルバー(制約プログラミング/MIP)
from ortools.sat.python import cp_model

# 線形計画法ソルバー(LP)
from ortools.linear_solver import pywraplp

# 配送計画(Routing)
from ortools.constraint_solver import pywrapcp, routing_enums_pb2

2. 最適化モデル構築

次に最適化モデルを作ります。
基本の「4ステップ」があります。

STEP 1: モデルのインスタンス作成
まず、問題を定義するための「箱」を作ります。

from ortools.sat.python import cp_model

model = cp_model.CpModel()


STEP 2: 変数の作成
「何を求めたいか」を変数として定義します。

整数変数: model.NewIntVar(下限, 上限, '変数名')
ブール変数: model.NewBoolVar('変数名')


STEP 3: 制約条件の追加
model.Add(...) を使って、守らなければならないルールを記述します。

等式・不等式: model.Add(x + y <= 10)
論理制約: 「Aの時だけBを適用する」といった
条件付き制約(OnlyEnforceIf)も可能


STEP 4: 目的関数の設定と実行
「何を最大化(または最小化)したいか」を決め
ソルバーを起動します。

# 最小化の場合
model.Minimize(目的の式)

# ソルバーの起動
solver = cp_model.CpSolver()
result = solver.Solve(model)

ここまでのコードを作れば
最適化問題が解ける様になっていると思います。


問題を解いてみる

簡単なつるかめ算をやって
あっているかを確認してみましょう。


問題1:
「つる」と「かめ」が合計で10匹、足の合計は28本です
それぞれ何匹ずついるでしょうか?

コードはこんな感じになります。
from ortools.sat.python import cp_model

def solve_tsurukame():
    # モデルの作成
    model = cp_model.CpModel()

    # 変数の定義 (0匹以上10匹以下)
    tsuru = model.NewIntVar(0, 10, 'tsuru')
    kame = model.NewIntVar(0, 10, 'kame')

    # 制約1: 合計が10匹
    model.Add(tsuru + kame == 10)

    # 制約2: 足の合計が28本
    model.Add(2 * tsuru + 4 * kame == 28)

    # ソルバーの準備と実行
    solver = cp_model.CpSolver()
    result = solver.Solve(model)

    if result == cp_model.OPTIMAL:
        print(f'つる: {solver.Value(tsuru)} 羽')
        print(f'かめ: {solver.Value(kame)} 匹')

solve_tsurukame()
つる: 6 羽
かめ: 4 匹


問題2:
50円切手と80円切手が計20枚、合計で1240円になるとき
それぞれ何枚ずつあるでしょうか?

from ortools.sat.python import cp_model

def solve_stamps():
    model = cp_model.CpModel()

    # 変数の定義 (0枚以上20枚以下)
    s50 = model.NewIntVar(0, 20, '50yen')
    s80 = model.NewIntVar(0, 20, '80yen')

    # 制約1: 合計20枚
    model.Add(s50 + s80 == 20)

    # 制約2: 合計金額が1240円
    model.Add(50 * s50 + 80 * s80 == 1240)

    solver = cp_model.CpSolver()
    result = solver.Solve(model)

    if result == cp_model.OPTIMAL:
        print(f'50円切手: {solver.Value(s50)} 枚')
        print(f'80円切手: {solver.Value(s80)} 枚')

solve_stamps()
50円切手: 12 枚
80円切手: 8 枚



問題3:

動画内ではすこし難しめの
入試問題なんかもやっています。

是非みてみてください。



まとめ


OR-Toolsは最適化問題を解くのに、かなり有効なライブラリです。

実社会の巨大な課題にも応用可能で
「Amazonのような配送ルート作成」や
「学校の複雑な時間割作成」など
他にもいろいろな最適化に応用できるものがあります。

だだし、使いこなすにはちょっとした
数学の知識が必要かもしれません。

使いこなせるとかなり問題を解ける幅が広がるので
実社会の問題解決にかなり有利かもしれません。

是非使ってみてください
それでは。



 

このページのトップヘ