Kivy と buildozer で スマホアプリ作成

Kivy と buildozer で スマホアプリ作成

目次

1 概要

  • Android純正の開発環境重すぎ
  • クロスプラットフォームの開発環境で作りたい(ソースの使い回し)
  • ということで、これができる開発環境の一つである、Kivy + buildozer で Androidアプリを作ってみる
  • 環境は Ubuntu version 20.04ベースで行う(Dockerを利用すれば、Dockerを利用できる他のプラットフォームでも同じ手順で行える)

2 リンク

3 Ubuntuでコンパイル

3.1 以下の操作を行っている動画



3.2 buildozerのUbuntu20.04へのインストール手順

  • 手順の確認はDockerのUbuntu 20.04を利用した
  • 以下の手順で共有ディレクトリを作成し、Dockerは1000のuidのユーザーで行った
sudo mkdir /work/kivy
sudo chown 1000.1000 /work/kivy/
  • 起動は以下のコマンドで行った
docker run -it --rm -v /work/kivy:/home/ ubuntu:20.04 

3.3 手順

3.3.1 必要パッケージのインストール

apt update
apt install sudo python3-kivy python3-pip python3-virtualenv vim default-jdk zlib1g-dev
apt install -y sudo vim git aidl ffmpeg python3 automake autoconf libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev libltdl-dev libssl-dev lld clang lldb zip unar unzip
  • 一般ユーザーで以下を行う場合は 以下のように先頭に sudoをつける
sudo apt update
sudo apt install sudo python3-kivy python3-pip python3-virtualenv vim default-jdk zlib1g-dev
sudo apt install -y sudo vim git aidl ffmpeg python3 automake autoconf libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev libltdl-dev libssl-dev lld clang lldb zip unar unzip

3.3.2 一般ユーザー追加

  • これは通常のUbuntuでは不要、Dockerで行っていて、操作を一般ユーザーで行いたいときに、以下の手順を実行
  • この例ではユーザー名はyoutubeとしている
  • 通常のUbuntu 20.04の場合はこの手順は恐らく不要
adduser youtube
  1. 追加した一般ユーザーがsudo使えるようにする(これは特に必要ない手順)
    • これは通常のUbuntuでは不要、Dockerで行っていて、操作を一般ユーザーで行いたいときに、以下の手順を実行
    • この例ではユーザー名はyoutubeとしている
    adduser youtube sudo
    

3.3.3 virtual環境で実行

  • ここでは kivy_buildozer ディレクトリで行う
virtualenv  --no-packaging  kivy_buildozer
cd kivy_buildozer
source bin/activate

3.3.4 git で管理できるようにしとく

  • ユーザー名と、メールアドレスは、自分にあわせてください。ここでは”Your Name”, “you@example.com”としてます。
git init
git add -A
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
git commit -m "first"

3.3.5 必要なPythonパッケージのインストール

pip3 install Cython
pip3 install buildozer

3.3.6 自分のプロジェクト用のディレクトリ作成

mkdir app
cd app
mkdir test001
cd test001/

3.3.7 サンプル用のHello Worldプログラム作成

  • main.py というファイル名で以下内容のファイル作成
import kivy

from kivy.app import App
from kivy.uix.label import Label

class HelloWorldApp(App):

    def build(self):
        return Label(text='Hello World!')

if __name__ == '__main__':
    HelloWorldApp().run()

3.3.8 Android用のapkファイル作成

  • bin ディレクトリにエラーがなければ、apkファイルが作成されます
buildozer init
buildozer android debug deploy run
  • 実行中にAndroid用のライセンス表示されるので、yを入力しエンターを押す必要があるケースあり

3.4 この章のまとめ

  • Ubuntu 20.04に kivy+buildozerを利用したスマホアプリ開発環境インストールし、Androidアプリを作成
  • Dockerを利用すれば、同じ手順で環境構築と、Androidアプリ作成可能

4 Kivy+buildozer関連リンク

  • 開発ツール関係文書

4.1 以下の説明を行っている動画

4.3 使うかもしれないパッケージ

5 Kivy Launcherの使い方

5.1 以下の説明を行っている動画

5.3 概要

  • Androidにkivy Luncherをインストール
  • adbコマンドで db push kivy/ storage/sdcard0 で kivyディレクトリ以下のプロジェクトファイルをコピー(storage/emulated/0/kivy 以下にプロジェクトディレクトリを準備)
  • プロジェクトはディレクトリにまとめて、android.txtファイルを準備(以下が例)
    • title にアプリの名前
    • author に作者名
    • orientation に画面の方向
title=accelerometer_basic
author=plyer example
orientation=portrait

5.4 実際の手順

  • Android端末(スマホ)に、kivy Launcherをインストール(Google Playストア)
  • Androidの端末でUSBデバッグ可能に設定(ファイル転送にadbコマンドを使う場合 Ubuntuでadbパッケージ)
    • Androidの設定を起動
      • システム→端末情報を開き、一番下の「ビルド番号」を何度もタップ(7から8回)すると、開発者むけオプションが有効になる
      • システムに戻ると、「開発者向けオプション」ができてるので、それをタップ、「USBデバッグ」を有効に変更
  • adbコマンド等で、/storage/emulated/0/kivy/ディレクトリ以下にプロジェクトファイルをコピー

5.4.1 kivyソースに含まれるサンプルをコピー

  • コピーするプロジェクトがはいっているディレクトリを用意
mkdir kivy
  • ソースをゲットするディレクトリを作成し、そのディレクトリに移動(使い慣れたツールでやってもOK)
mkdir github
cd github
  • kivy,plyerのソースをgitコマンドでコピー(ダウンロードして展開してもOK)
git clone https://github.com/kivy/kivy.git
git clone https://github.com/kivy/plyer.git
  • ソースに含まれているAndroid用サンプルを、一つしたのディレクトリのkivyディレクトリにコピー
cp -r kivy/examples/settings/ ../kivy/
cp -r kivy/examples/demo/showcase/ ../kivy/
cp -r kivy/examples/demo/pictures/ ../kivy/
cp -r kivy/examples/demo/touchtracer/ ../kivy/
cp -r kivy/examples/widgets/sequenced_images/ ../kivy/
cp -r kivy/examples/keyboard/ ../kivy/
cp -r kivy/examples/android/takepicture/ ../kivy/
cp -r kivy/examples/android/compass/ ../kivy/
cp -r plyer/examples/accelerometer/basic/ ../kivy/accelerometer_basic/
  • accelerometer_basic用のandroid.txtがないので追加 ( ../kivy/accelerometer_basic/android.txt )
title=accelerometer_basic
author=plyer example
orientation=portrait
  • PCとAndroidをUSBケーブルで接続
  • adbコマンドでAndroidにコピー
adb push ../kivy/ /storage/emulated/0/
  • android側でKivy Launcher起動
  • 動かしたいのを選択して起動

5.5 Kivy Launcherの使い方のまとめ

  • Kivy Launcher でapk作成せずに、手軽に効率良く、android本体で動作テストする手順
  • temuxとか、sl4aとか、QPython等があるが、色々なパッケージとの連携を行いながら、しかもapkパッケージ化が難しく、kivy Launcherが良さげ
  • 次の章で、Google Playストアで配布されているKivy Launcherには含まれていないplyerを含んだ、Kivy Launcherをビルドする

6 plyer入りのKivy Launcherの作成とインストール(好きなパッケージ入りのKivy Launcherの作り方)

6.1 以下の説明を行っている動画



6.2 関連文書

6.3 カスタマイズした、Kivy Launcherの作成手順

6.3.1 ソースゲット

git clone https://github.com/kivy/kivy-launcher.git

6.3.2 buildozer.specの requirements = kivy, androidの後に追加したパッケージを記述

  • plyer, python3, pyjniusを追加
...省略
requirements = kivy, android, plyer, python3, pyjnius
...省略

6.3.3 ビルドインストール

  • Androidを開発モードにして、USBデバッグ可能にしてから、PCとUSB接続
  • 以下のコマンドで、「Ubuntuでコンパイル」の章の https://www.youtube.com/embed/-xUmhSMK4Jk で作成した環境にはいる
source ~/kivy_buildozer/bin/activate
  • それから、以下のコマンドを実行
buildozer android debug deploy

6.4 この章のまとめ

  • Kivy Launcherをカスタマイズして、plyerのパッケージが必要なソースを動くようにしてみた

7 plyer関係の機能の利用方法の調べ方

  • exampleをメインで、関係文書を元に調べると、使い方を効率的に調べれそう

7.1 以下の説明を行っている動画

7.2 関係文書

7.3 手順

  • ソースに含まれるサンプルコードを調べれば使い方だいたいわかる。(あと公式文書、ソースも)
  • plyerのソースをgitコマンドでコピー(ダウンロードして展開してもOK)
git clone https://github.com/kivy/plyer.git
  • plyer/examples/ディレクトリ内に多数サンプルある
  • android用のバーチャル環境にはいり、apk生成出来る環境に
source ~/kivy_buildozer/bin/activate
  • buildozer.specファイルあるものは、そのディレクトリに移動し、以下のコマンドで、コンパイル、転送、実行
buildozer android debug deploy run
  • 一部のサンプルは動かないものもあった(Androidの機種によって、そのセンサーはいってないとか)
  • gpsサンプルは、simがはいっていて、位置情報の詳細がオン設定になっていないと動作しなかった(GPSじゃなくて、ネットで位置を調べているように感じた)

7.4 サンプルディレクトリ

  • accelerometer/basic/ 加速度計 こっちは正常動作
  • accelerometer/using_graph/ 加速度計 こっちは動かなかった
  • audio/ ファイルのパーミッション変更が必要
  • barometer/ 気圧計(F1 Playには気圧計ないみたい、Pixcel3aXLでは正常動作)
  • battery/ バッテリー関係
  • bluetooth/ 未チェック
  • brightness/ 起動できず
  • call/ 未チェック
  • camera/ 動作せず
  • compass/ コンパス(方位磁石) 起動できず
  • email/ eメイル,未チェック
  • filechooser/ ファイル選択
  • flash/ 未チェック
  • gps/ gps関係、gpsの電波がないところでも動作しており、simカードがないとエラーになっていた、基地局利用の位置情報?
  • gravity/ 重力
  • gyroscope/ ジャイロスコープ
  • humidity/ 湿度,未チェックorコンパイル時にエラー
  • light/ 明るさセンサー
  • notification/ 通知
  • orientation/ 向き?
  • proximity/ 近接?,enableでダウン
  • screenshot/ スクショ? buildozer.specがないため未チェック
  • sms/ SMS関係
  • spatialorientation/ 空間定位
  • speech2text/ 動作させたがスタートおしてもすぐに止まる、マイクの権限与えてもダメ
  • storagepath/ ストレージのパス
  • temperature/ 気温?、動作せず
  • text2speech/ 文字を発音、文字化けしてた
  • uniqueid/ ユニークなID取得
  • vibrator/ バイブ
  • wifi/ 未チェック

7.4.1 コンパイルして、次々とインストールする場合

  • Android端末をUSB接続して、plyer/exampleディレクトリにはいって、以下のコマンドを実行
cd accelerometer/basic/  ; buildozer android debug deploy run; cd ../..
cd accelerometer/using_graph/ ; buildozer android debug deploy run; cd ../..
cd audio/ ; buildozer android debug deploy run; cd ..
cd barometer/ ; buildozer android debug deploy run; cd ..
cd battery/ ; buildozer android debug deploy run; cd ..
cd bluetooth/ ; buildozer android debug deploy run; cd ..
cd brightness/ ; buildozer android debug deploy run; cd ..
cd call/ ; buildozer android debug deploy run; cd ..
cd compass/ ; buildozer android debug deploy run; cd ..
cd email/ ; buildozer android debug deploy run; cd ..
cd flash/ ; buildozer android debug deploy run; cd ..
cd gps/ ; buildozer android debug deploy run; cd ..
cd gravity/ ; buildozer android debug deploy run; cd ..
cd gyroscope/ ; buildozer android debug deploy run; cd ..
cd humidity/ ; buildozer android debug deploy run; cd ..
cd light/ ; buildozer android debug deploy run; cd ..
cd notification/ ; buildozer android debug deploy run; cd ..
cd orientation/ ; buildozer android debug deploy run; cd ..
cd proximity/ ; buildozer android debug deploy run; cd ..
cd sms/ ; buildozer android debug deploy run; cd ..
cd spatialorientation/ ; buildozer android debug deploy run; cd ..
cd speech2text/ ; buildozer android debug deploy run; cd ..
cd storagepath/ ; buildozer android debug deploy run; cd ..
cd temperature/ ; buildozer android debug deploy run; cd ..
cd text2speech/ ; buildozer android debug deploy run; cd ..
cd uniqueid/ ; buildozer android debug deploy run; cd ..
cd vibrator/ ; buildozer android debug deploy run; cd ..

7.5 Androidの特殊機能を利用する方法

7.5.1 pyler利用

  • クロスプラットフォームのソースになる
  • しかしiOSでサポートされていない機能多い

7.5.2 Pyjnius等を利用して、PythonからJavaを利用

  • Androidの開発ツールのライブラリを利用できる
  • 情報少ない

7.5.3 import Androidで利用

  • 情報少ない(あまり文書をみつけれてない、みつけたらまたリンクはっときます)

7.6 この章のまとめ

  • スマホ固有の機能の動作させるライブラリplyer関係の使い方の調べ方紹介
  • かたっぱしからコンパイルしてインストールすると相当時間かかるが、ソースみるまえに動作させた方がわかりやすい
  • exampleをメインで、関係文書を元に調べると、使い方を効率的に調べれそう
  • 全部コンパイルすると、30-40Gの容量が必要

8 広告

8.1 以下の説明を行っている動画



8.2 使えそうなパッケージ

8.2.2 手順

  • 以下の手順で(Ubuntuでコンパイルhttps://www.youtube.com/embed/EF0PNSlblYYの手順をDocker内のUbuntuではなく、通常のUbuntuで行って構築した環境)apkを作成できる環境に移行
source ~/kivy_buildozer/bin/activate
  • KivMod Github https://github.com/MichaelStott/KivMobの記述どうりの手順で行う(INTERSTITIALタイプ、全画面タイプで広告表示)
  • package.domain部分がorg.testのままだと、広告が表示されないので、org.kivyなどorg.test以外に変更
  • 以下のコマンドでインストール実行
buildozer android debug deploy run
  • KivMob Tutorial http://kivmob.com/tutorials.htmlにあるBannerタイプとか、Rewarded Videoタイプ(広告のかわりに、なにかユーザーにプレゼントするタイプ)とかもコンパイルして実行する

8.3 この章のまとめ

  • KivModを利用すると、GoogleのAdMobを利用して簡単に色々なタイプの広告を表示可能

9 課金

9.1 以下の説明を行っている動画

10 KivyMD

  • ナイスなルックスで、豊富な部品があるライブラリ
  • Kivy純正の部品よりも、KivyMDの部品で作成した方がルックス良いアプリ作成簡単にできそう

10.1 以下の説明を行っている動画

10.3 install (Ubuntu ユーザースペース)

  • pip install kivymd==0.104.1 をしろとGitHubに書いてあるが、以下でも同じバージョンがはいった(2020/08/21)
pip3 install kivymd
  • その時のアウトプット
Collecting kivymd
  Using cached kivymd-0.104.1-py3-none-any.whl (2.4 MB)
Requirement already satisfied: kivy in /usr/lib/python3/dist-packages (from kivymd) (1.10.1)
Requirement already satisfied: pillow in /usr/lib/python3/dist-packages (from kivymd) (7.0.0)
Requirement already satisfied: requests in /usr/lib/python3/dist-packages (from kivymd) (2.22.0)
Installing collected packages: kivymd
Successfully installed kivymd-0.104.1

10.4 pkg作成時にKivyMDを利用する

  • buildozer.specのrequestsにkivymdを追加

10.5 デモのコンパイルと実行

  • KivyMDのソースゲット
git clone https://github.com/kivymd/KivyMD.git
  • 取ったソースのバックアップ(20200821にゲットしたので、その日付をつけた、KivyMD.20200821.tgz を作成)
tar cvzf KivyMD.20200821.tgz KivyMD/
  • 前作成したapk作成環境に移行(virtualenvで作成した環境にはいる)
source ~/kivy_buildozer/bin/activate
  • AndroidをUSBケーブルでPCと接続
  • デモのあるディレクトリに移動し、コンパイル実行
cd KivyMD/demos/kitchen_sink/
buildozer android debug deploy run

10.6 各部品の使い方の調べ方

  • 上の文書のリンクと、動かしたサンプルソースのソースを調べれば、簡単に使い方を調べることが可能
  • 使う部品は

10.7 この章のまとめ

  • ルックスの良いKivyMDを紹介
  • デフォルトのKivyの部品よりもKivyMDの部品を使うべき
  • 動画では、サンプルの動作の様子も紹介

11 デバッグ手法いくつか紹介

11.1 以下の説明を行っている動画

11.3 手順

  • USBデバッグを可能にしたAndroid実機とPC接続
  • ソースにprint文とかlogging文をいれる
  • 特殊な文字列をいれとくと後で検索しやすくなる
  • 確認したい行の前後にいれるとかも良い
  • そこを通過してるかの確認にも使える
  • 変数の値のチェックにも便利
  • 以下はLoggerを使っているが、print文でもログに出る
from kivy.logger import Logger
... 省略
Logger.info('#####情報#####')
  • テストしたい動作の手前で以下を実行し、ログを適当なファイル名で保存(下の例だとlog001.txt)
adb logcat > log001.txt 2>&1
  • 以下にしとくと画面にも表示しながらファイルに保存
adb logcat 2>&1 | tee log001.txt

11.4 バグの例

  • org.renpy.android.PythonActivity’がみつからない例
08-22 21:10:02.938 30206 30239 I python  :  jnius.jnius.JavaException: Class not found b'org/renpy/android/PythonActivity'
  • 特殊文字をいれてわかりやすくした例
........... 省略
08-23 15:20:12.353 15129 15161 I python  : [INFO   ] #####before vibrate#####
08-23 15:20:12.353 15129 15161 I python  : [INFO   ] [Base        ] Leaving application in progress...
........... 省略
08-23 15:20:12.357 15129 15161 I python  :    File "/storage/emulated/0/kivy/vibrate02/main.py", line 56, in vibrate
08-23 15:20:12.357 15129 15161 I python  :      jvibrator.vibrate(1000)
08-23 15:20:12.358 15129 15161 I python  :    File "jnius/jnius_export_class.pxi", line 745, in jnius.jnius.JavaMethod.__call__
08-23 15:20:12.358 15129 15161 I python  :  jnius.jnius.JavaException: Invalid call, number of argument mismatch, got 1 need 4
08-23 15:20:12.358 15129 15161 I python  : Python for android ended.
........... 省略

11.5 この章について

  • 低次元のデバッグ方法の一種を紹介

12 Kivy Launcherの拡張その2

12.1 以下の説明を行っている動画

12.2 関係動画

12.3 関係ソース

12.4 以下のようにKivy Launcherのbuildozer.specのrequestsを追加

  • opencv関係や、sympy関係もいれたかったが、現状のバージョンだと、エラーになる、配布元でのデバッグ終わったら入れるべき
requirements = kivy, android, plyer, python3, pyjnius, kivmob, kivymd, cymunk, pymunk, pandas, libcurl, Pillow, websocket-client, vispy, regex, numpy, pandas

12.5 KivMobhttps://github.com/MichaelStott/KivMobのサンプル用の修正を行う(buildozer.spec)

12.6 この章のまとめ

  • これによってかなりのものを実際にapkファイルを作成することなく、Kivy Launcherで動作確認可能になる
  • 広告関係のサンプルも、Kivy Launcherでテスト可能に

13 pyjniusを使って、java経由でAndroid特有の機能の利用

13.1 以下の説明を行っている動画

13.3 バイブを行ってみた

13.3.1 まずは、pyjniusをつかわず、plyerを使って、バイブできるのを作った

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from plyer import vibrator
Builder.load_string('''
#:import vibrator plyer.vibrator
<My>:
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'vibrate'
        font_size: 80
        on_release: vibrator.vibrate(5)
''')

class My(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return My()

if __name__ == '__main__':
    HelloWorldApp().run()
  • android.txtが以下(3行にすること)
title=Vibrate 001 android.vibrate
author=NM Max
orientation=portrait

13.3.2 pyjniusを使うバージョン

  • https://kivy.org/doc/stable/guide/android.html の断片ソースを利用してやろうとしたら酷い目にあった
    • バージョンが新しいとこのソース動かない
    • org.renpy.android.PythonActivity は org.kivy.android.PythonActivity になってた
      • 前の前の章のデバッグ手法で気づいた org.renpy.android.PythonActivity でつまづいていることに
    • そこらもプログラムで取得可能なようで、plyerのソースを参考に変更した
    • Androidの開発環境のVibrator関係も変更になっていて、vibrate関数の使用が変更となり、VibrationEffectを利用するようになってた
  • plyerのソースの plyer/platforms/android/__init__.py と、plyer/platforms/android/vibrator.pyを参考に作成
  • そうして改造したのが以下 main.py
from os import environ
from jnius import autoclass, cast

try:
    from android import config
    ns = config.JAVA_NAMESPACE
except (ImportError, AttributeError):
    ns = 'org.renpy.android'
PythonActivity = autoclass(ns + '.PythonActivity')
activity = PythonActivity.mActivity

ANDROID_VERSION = autoclass('android.os.Build$VERSION')
SDK_INT = ANDROID_VERSION.SDK_INT

Context = autoclass("android.content.Context")
vibrator_service = activity.getSystemService(Context.VIBRATOR_SERVICE)
vibrator = cast("android.os.Vibrator", vibrator_service)
if SDK_INT >= 26:
    VibrationEffect = autoclass("android.os.VibrationEffect")

from kivy.logger import Logger
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

Builder.load_string('''
<My>:
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'vibrate'
        font_size: 80
        on_release: root.vibrate(5)
''')

class My(BoxLayout):
    def vibrate(self,x):
        Logger.info('#####before vibrate#####')
        if vibrator:
            if SDK_INT >= 26:
                vibrator.vibrate(VibrationEffect.createOneShot(int(1000 * x), VibrationEffect.DEFAULT_AMPLITUDE))
            else:
                vibrator.vibrate(int(1000 * x))
        Logger.info('#####after vibrate#####')

class HelloWorldApp(App):
    def build(self):
        return My()

if __name__ == '__main__':
    HelloWorldApp().run()
  • android.txtが以下(3行にすること) Kivy Launcher用
title=Vibrate 002 pyjnius.vibrate
author=NM Max
orientation=portrait
  • ( buildozer initしたのち)buildozer.specの変更内容
    • title
      • title = My Application を title = Pyjnius vibrator test に修正
    • requirements
      • requirements = python3,kivy を requirements = python3,kivy,pyjnius,plyer に修正
    • android.permissions = INTERNET, VIBRATE を追加
    • buildozer android debug deploy run すれば、USB接続してあるUSBデバッグオンになっているandroidにインストールされ、実行される(binディレクト以下にapkファイルも生成される)

13.4 この章のまとめ

  • 公式の文書に古い記述があり、新しいバージョンでは動かないものも多い
  • plyerやpython-for-androidのソースを参考にすると効率良く動くものをつくれる
  • Kivy用に用意されていないもので、Android用に用意されているJavaライブラリを、pyjniusを使えるようになることで、利用可能になった

14 Kivy Launcherの拡張その3

14.1 以下の説明を行っている動画

14.2 関係文書

14.3 関係動画

14.4 関係ソース

14.5 Kivy Launcherカスタマイズ3の手順

14.5.1 現状(2020/08/28時点)でbuildozerでKivy Gardenを入れる為の手順の説明ありhttps://stackoverflow.com/questions/62260608/kivy-garden-mapview-deploying-error-with-buildozer

  • ~/kivy_buildozer/にvirturlenvで環境作った場合、~/kivy_buildozer/lib/python3.8/site-packages/buildozer/__init__.pyを修正
    • Kivy Gardenのバージョンを0.1.1から0.1.4に変更
self.cmd('pip install Kivy-Garden==0.1.1', env=self.env_venv)
を
self.cmd('pip install Kivy-Garden==0.1.4', env=self.env_venv)
に修正

14.5.2 Kivy Launcherのbuildozer.specのrequirementsを以下に修正

  • ベースは Kivy Launcherのカスタマイズ手順2 https://www.youtube.com/watch?v=Fd4jX-RJ9es の動画でおこなった修正後のファイルに以下の修正を行う
  • pygame, matplotlib, websocket-client, snappy,requests,certifi,urllib3,chardet,idna を追加している
    • pygame はPython用のゲームエンジンの一つ
    • matplotlib はプロット用
    • websocket-client は多分ウェッブ系の部品だと思われる
    • snappy は Python bindings for the snappy compression library from Google.らしい
    • requests,certifi,urllib3,chardet,idna
      • requestsは adb logcat で確認したら無いってエラーが出てた、それ以外にも必要なパッケージあるかもしれないので、以下を参考にそれ以下も入れた
      • FarmersMarketFinderTutorial動画のソースhttps://github.com/Dirk-Sandberg/FarmersMarketFinderTutorialで入れられていたパッケージ
requirements = kivy, android, plyer, python3, pyjnius, kivmob, kivymd, cymunk, pymunk, pandas, libcurl, Pillow, websocket-client, vispy, regex, numpy, pandas, pygame, matplotlib, websocket-client, snappy,requests,certifi,urllib3,chardet,idna
  • 本当はOpenCV関係や、Sympy関係も入れたいが、まだ入れれてない

14.5.3 Kivy Launcherのbuildozer.specのgarden_requirementsを以下に修正

  • 沢山あるが、とりあえず、2つ入れた、他にも試したいのあれば、入れてOKう
garden_requirements = matplotlib, mapview

14.5.4 Kivy Launcher ビルドインストール

  • Kivy Launcherのカスタマイズ手順 https://www.youtube.com/watch?v=YyYNBL0VtdM の手順のビルドインストールコマンド実行部分と同じ(設定ファイルの変更はこのリンクの動画ではなく、上の修正を行う)
  • Androidを開発モードにして、USBデバッグ可能にしてから、PCとUSB接続
  • 以下のコマンドで、「Ubuntuでコンパイル」の章の https://www.youtube.com/embed/-xUmhSMK4Jk で作成した環境にはいる
source ~/kivy_buildozer/bin/activate
  • それから、以下のコマンドを実行
buildozer android debug deploy

14.5.5 mapviewEx02ディレクトリを作成し、必要なandroid.txtとmain.pyをいれる

./mapviewEx02/
├── android.txt
└── main.py

14.5.6 android.txtの中身

  • Kivy Launcher用のファイル
title=MapViewEx02
author=NM Max
orientation=portrait

14.5.7 Kivy Gardenのmapviewのexampleのmap_browser.pyを改造し、main.pyとして以下のようにmapviewEx02ディレクトリに入れる

  • 修正箇所は、Pythonの検索パスに、gardenのmapviewを入れるように設定(ファイルの前半部分)
  • 東京駅の座標を入れ、東京のボタンも増やした
  • スマホだとちょっと文字が大きすぎて崩れていたが、とりあえず放置
  • mainのファイルの変数を、kv言語側にもっていくには、#:import MapSource main.MapSource こういう感じでやれば良いらしい
    • ネットをうろうろしていた時に見つけたサイトで知ったのだが、URLをメモしておらず、URLわからない、英語のサイトだった
import sys
import os
print("########")
print(sys.path)
print("########")
#sys.path.append(os.path.join(os.path.dirname(__file__), 'libs/garden/garden.mapview'))
sys.path.append('./libs/garden/garden.mapview')
print("########")
print(sys.path)
print("########")
print(os.listdir(path='.'))
print("########")
from kivy.base import runTouchApp
from kivy.lang import Builder
from mapview import MapSource

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

#:import MapSource __main__.MapSource
root = Builder.load_string("""
#:import MapSource mapview.MapSource

<Toolbar@BoxLayout>:
    size_hint_y: None
    height: '48dp'
    padding: '4dp'
    spacing: '4dp'

    canvas:
        Color:
            rgba: .2, .2, .2, .6
        Rectangle:
            pos: self.pos
            size: self.size

<ShadedLabel@Label>:
    size: self.texture_size
    canvas.before:
        Color:
            rgba: .2, .2, .2, .6
        Rectangle:
            pos: self.pos
            size: self.size

RelativeLayout:

    MapView:
        id: mapview
        lat: 50.6394
        lon: 3.057
        zoom: 8
        #size_hint: .5, .5
        #pos_hint: {"x": .25, "y": .25}

        #on_map_relocated: mapview2.sync_to(self)
        #on_map_relocated: mapview3.sync_to(self)

        MapMarker:
            lat: 50.6394
            lon: 3.057

        MapMarker
            lat: -33.867
            lon: 151.206

        MapMarker
            lat: 35.6809591
            lon: 139.7673068

    Toolbar:
        top: root.top
        Button:
            text: "Move to Lille, France"
            on_release: mapview.center_on(50.6394, 3.057)
        Button:
            text: "Move to Sydney, Autralia"
            on_release: mapview.center_on(-33.867, 151.206)
        Button:
            text: "Move to Tokyo, Japan"
            on_release: mapview.center_on(35.6809591, 139.7673068)
        Spinner:
            text: "mapnik"
            values: MapSource.providers.keys()
            on_text: mapview.map_source = self.text

    Toolbar:
        Label:
            text: "Longitude: {}".format(mapview.lon)
        Label:
            text: "Latitude: {}".format(mapview.lat)
    """)

runTouchApp(root)

14.5.8 Kivy Launcher が読み取れるディレクトリに、作ったファイルをコピー(adbコマンドを利用してPCからAndroidにコピー, AndroidとPCはUSB接続し、AndroidはUSBデバッグ可能な設定済み)

  • mapviewEx02/ディレクトリ内にいるなら、以下のコマンドでOK
adb push ../mapviewEx02/ /storage/emulated/0/kivy/
  • 後は起動して、MapViewEx02を選択肢から選択して、起動すればOK

14.6 この章のまとめ

  • Kivy Gardenを使いたくて、非常に苦労して成功した時の手順説明
  • Kivy Garden mapview 素晴らしすぎる
  • 地図を表示するアプリを簡単に作れるようになった
  • Pythonの検索パスの変更方法や、Androidパッケージ内部での検索パスの調べ方を知った
    • Kivy Launcher のビルドディレクトリの .buildozer/android/app/ 内にパッケージ化するファイル群がある
    • 本来検索パスの設定変更無しにいけるはずだが、その方法まだわかっておらず。知ってる方いたら、教えて下さい。

15 WebView(ウェブブラウザの部品への埋め込みandroid)

15.1 以下の説明を行っている動画

15.2 関係文書

from kivy.utils import platform
....省略
 if platform == 'android':
   ...android用の処理...

15.3 WebViewを使ってみる手順

from kivy.app import App
from jnius import autoclass
from kivy.clock import Clock
from android.runnable import run_on_ui_thread
from kivy.uix.widget import Widget

WebView = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
activity = autoclass('org.kivy.android.PythonActivity').mActivity

@run_on_ui_thread
def create_webview(*args):
        webview = WebView(activity)
        webview.getSettings().setJavaScriptEnabled(True)
        wvc = WebViewClient();
        webview.setWebViewClient(wvc);
        activity.setContentView(webview)
        webview.loadUrl('https://blog.123abcsoft.com/2020/07/31/kivy-%E3%81%A8-buildozer-%E3%81%A7-%E3%82%B9%E3%83%9E%E3%83%9B%E3%82%A2%E3%83%97%E3%83%AA%E4%BD%9C%E6%88%90')

class Wv(Widget):
        def __init__(self, **kwargs):
                super().__init__(**kwargs)
                self.__functionstable__ = {}
                Clock.schedule_once(create_webview, 0)


class ServiceApp(App):
        def build(self):
                return Wv()

# https://github.com/kivy/python-for-android/issues/1908

if __name__ == '__main__':                                                                      
    ServiceApp().run()

15.4 この章のまとめ

  • 部品として、WebViewを使う方法を調べて、動作することを確認した
  • リンク先をクリックするとリンク先に飛ぶ
  • 戻るが効かない、戻るで1つ前に戻るには更にプログラムが必要らしい

16 Kivy Launcherの拡張その4

  • Sympyを使ったアプリを作りたかったが、p4aにSympyのインストール手順が用意されているが、古い為か、現状はbuilder.specのrequirementsにsympyを追加しても、途中でエラーになって入れれなかった
  • KivyMDを利用する時に発生することが多い意味不明のエラー回避の為にKivyのバージョンを2.0.0rc3に
  • pyopenssl追加
  • 日本語フォントを追加
  • KivyMD関連画像を追加

16.1 関連動画、関連文書

16.2 以下の説明を行っている動画

16.3 手順

  • Kivy Launcherのソースのbuildozer.specのrequirementsを以下に修正
  • kivyのバージョンを2.0.0rc3指定、pyopenssl追加
requirements = kivy==2.0.0rc3, android, plyer, python3, pyjnius, kivmob, kivymd, cymunk, pymunk, pandas, libcurl, Pillow, websocket-client, vispy, regex, numpy, pandas, pygame, matplotlib, websocket-client, snappy,requests,certifi,urllib3,chardet,idna,pyopenssl
  • buildozer.specのsource.include_exts を以下に変更
source.include_exts = py,png,jpg,kv,atlas,ttf
  • buildozer.specのsource.include_patterns を以下に変更
source.include_patterns = images/*,fonts/*

16.3.1 日本語フォント追加

  • Kivy Launcherのソースディレクトリにfontsディレクトリを作成し、IPAフォントファイルをそのディレクトリ内にコピーした
  • Ubuntuなら以下のコマンドでOK(ipaフォントのパッケージイスんトール後、 fonts-ipaexfont-gothic fonts-ipaexfont-mincho fonts-ipafont-gothic fonts-ipafont-mincho )
sudo apt install fonts-ipaexfont-gothic fonts-ipaexfont-mincho fonts-ipafont-gothic fonts-ipafont-mincho 
mkdir fonts
cp /usr/share/texlive/texmf-dist/fonts/truetype/public/ipaex/* fonts/
  • ファイルは、私の環境では以下になった
fonts
├── ipaexg.ttf
├── ipaexm.ttf
├── ipag.ttf
├── ipagp.ttf
├── ipam.ttf
└── ipamp.ttf

16.3.2 KivyMDのロゴ画像を入れた

  • 必要性は低いけど
  • Kivy Launcherのソースディレクトリにimagesディレクトリを作成し、kivyMDのロゴ画像を入れた。画像はKivyMDのGitHubから得た
  • ファイルは、私の環境では以下になった
images/
└── kivymd.png

16.3.3 Kivy LauncherにSympy追加

  • https://github.com/kivy/python-for-android/issues/2303の情報で、Sympy(数式処理パッケージ、前から入れたかった)を入れる方法2つ紹介されている。そのうちの一つ、Pythonで書かれているので、それらのライブラリを、ディレクトリにコピーする手法を選択した
  1. buildozer用のvirturlenvにはいる
    • 私の場合は ~/kivy_buildozer/ に作成したので、以下のコマンドを実行
    cd ~/kivy_buildozer/
    source bin/activate
    
  2. Sympyをインストール
    pip3 install sympy
    
  3. Kivy Launcher のソースディレクトリに移動
    • その後、取ってきてあるkivy Launcherのソースディレクトリに行き,sympyと、それに必要なmpmathをコピーしてくる
    • ~/kivy_buildozer/ の部分は作成したvirturlenvのディレクトリに依存するので、適時変更してください
    cp -r ~/kivy_buildozer/lib/python3.8/site-packages/mpmath .
    cp -r ~/kivy_buildozer/lib/python3.8/site-packages/sympy .
    
  4. ビルドインストール
    • Android端末をPCに接続して以下のコマンドを実行
    • Android端末側でポップアップがでたら、リモートでバッグ可能なように操作
    buildozer android debug deploy run
    
  5. テスト用のプログラムを作成して動かしてみる
    • SympyTest ディレクトリ内に用意する
    mdkir SympyTest
    cd SympyTest
    
    • android.txtを以下で用意
    title=SympyTest
    author=NM Max
    orientation=portrait
    
    • main.pyを以下で作成
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.label import Label
    import sympy
    
    
    x=sympy.Symbol('x')
    y=sympy.Symbol('y')
    
    
    class MyApp(App):
    
        def build(self):
            box = BoxLayout()
            box.orientation = 'vertical'
            box.add_widget(Label(text=str(sympy.expand((x+y)**3)),font_size="20sp"))
            box.add_widget(Label(text=str(sympy.integrate(1/x**3,x)),font_size="30sp"))
            box.add_widget(Label(text=str(sympy.diff(x**2,x)),font_size="30sp"))
            box.add_widget(Label(text=str(sympy.Or(x,y)),font_size="30sp"))
            return box
    
    MyApp().run()
    
  6. ファイルを転送
    • 以下のコマンドで転送する
    adb push ../SympyTest/ /sdcard/kivy/
    
  7. Android端末で動かしてみる
    • 上手く動作した

16.4 この章のまとめ

  • Sympyを入れたバージョンを作成
  • KivyMDと相性のあんま良くないkKivy1系ではなく、最新のKivy2系を入れた
  • 日本語フォントや、KivyMDのロゴも入れておいた

17 Kivyでmatplotlibでグラフ

  • Kivy + Kivy Garden matplotlib + matplotlibでグラフ描いてみた

17.1 関連動画、関連文書

17.2 以下の説明を行っている動画

17.3 手順

  • virtualenvにはいる(私の場合は ~/kivy_buildozer/bin 以下に構築してある)
source ~/kivy_buildozer/bin/activate
  • ディレクトリ matplotlib01 用意
  • コマンドラインでやるなら以下
mkdir matplotlib01
cd matplotlib01
buildozer init
  • buildozer.specのrequestsと,garden_requirementsの行を以下に修正
requirements = python3, kivy==2.0.0rc3, android, jnius, kivmob, kivymd, pandas, numpy, matplotlib
garden_requirements = mapview, matplotlib
  • 以下の内容でmain.pyを用意
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
import matplotlib.pyplot as plt
import numpy as np
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg

fig, ax = plt.subplots()  
xx=range(5)
ax.plot(xx, list(map(lambda x:x**2,xx)), label='x**2', linestyle='--', marker='o')  
ax.plot(xx, list(map(lambda x:x+3,xx)), label='x+3', linestyle='--', marker='o')  
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("title")
ax.legend()
ax.grid()

class MyApp(App):
    def build(self):
        box = BoxLayout()
        box.orientation = 'vertical'
        box.add_widget(FigureCanvasKivyAgg(fig))
        return box

if __name__ == '__main__':
    MyApp().run()

17.3.1 Ubuntu側でテストするようにvirturlenvにmatplotlibをインストール、2020/10/01で、最新のmatplotlibをUbuntu20.04で動かそうとするとエラーになるため、2.2系をインストール

  • まずバーチャル環境にはいる(私は~/kivy_buildozer/に準備してある)
source ~/kivy_buildozer/bin/activate
  • それから3.2系最新のmatplotlibをインストール
pip3 install matplotlib==3.2.2
  • main.pyを動かしてみる
python3 main.py

17.3.2 Androidで実行

  • AndroidとUSB接続して以下を実行
buildozer android debug deploy run

17.4 この章のまとめ

  • Kivy で matplotlib を利用して、グラフ描画(Kiby Gardenのmatplotlibライブラリも利用)できた
  • Kivy Launcherでも動かそうとしたが、なぜかKivy Gardenのmatplotlibが読み込めなかった、そのため、新規パッケージ方式でやった。今後解決方法みつけたら、また文書と動画にします。

18 Kivy+Buildozerで作成したAndroidアプリをGoogle Play Storeに出品する手順

18.1 関連動画、関連文書

18.2 手順

  1. AdMobへの登録とアップロード
    • 登録料不要だった。
    • アプリ名と、広告タイプを登録し、アプリのkeyと、広告のkeyをゲット
  2. buildoze.specとソース修正
    • AdMobのkeyがテスト用になっていたので、それを修正しこのアプリ用のKeyに置き換えるようにbuildozer.specとソース修正
    • 64bitCPU用にする必要があった(32bit用だと審査さえしてもらえなくなってる2020/10/23時点)) buildozer.specの armeabi-v7a を arm64-v8a に変更
    • 来年くらいに32bit用はGoogle Playストアから駆逐されるらしい。2年前くらい前発売のAndroidはみな64bitになってて、その前数年が32bitCPUと64bitCPUが混在。その前は32bitCPUだったらしい。
    android.arch = arm64-v8a
    
    • Androidのバージョンが29対応じゃないと審査してもらえない(2020/10/23時点)。buildozer.specの 27を29に。将来もっと上のバージョンの必要がでてくることが予想される
    android.api = 29
    

18.2.1 リリースバージョンの作成

  • .buildozer/ 以下を削除してから、以下のコマンドで作成しなおした 
buildozer android release
  • 今回のSympyCalculatorだと sympycalclator-0.0.2-arm64-v8a-release-unsigned.apk が出来た。(アプリ名とバージョン番号はbuildozer.specの設定によってかわる)
  • Google Play Storeに出品する為には署名が必要だった。

18.2.2 サイン

  1. key作成
    • alies を test1 にした
    • 以下のコマンドでkeyを生成
    • 姓名、県、市、等を聞かれるから、ちゃんと回答、組織単位名は何も入力せずエンターした(私の場合、ある場合は入れて下さい)国のコードはJAにした。
    • 10,000日間有効な2,048ビットのRSAの鍵ペアと自己署名型証明書が生成された、これらを利用して署名した
    mkdir ./keystores
    keytool -genkey -v -keystore ./keystores/sympycalculator-release-key.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias test1
    
  2. サイン作業
    • これやると良いらしい
    zipalign -v -p 4 ./bin/sympycalclator-0.0.2-arm64-v8a-release-unsigned.apk ./bin/sympycalclator-0.0.2-arm64-v8a-release-unsigned-aligned.apk
    
    • サインする
    apksigner sign --ks ./keystores/sympycalculator-release-key.keystore --out ./bin/sympycalclator-0.0.2-arm64-v8a-release.apk  ./bin/sympycalclator-0.0.2-arm64-v8a-release-unsigned-aligned.apk
    
    • 以下で確認
    apksigner verify ./bin/sympycalclator-0.0.2-arm64-v8a-release.apk
    
    • これで Google Playに登録可能な sympycalclator-0.0.2-arm64-v8a-release.apk が作成できた
  3. GooglePlayへの登録と、アップロード
    • 登録料で3000円弱払った(為替レートで変化するはず,25ドル)
    • xxxxxxxxxxxxxxxxxxxはGoogle Play Storeのサイトに書いてある方法。色々サインの方法があったけど、この記述があるのを選んだ
    • これでoutput.zipを生成して、Google Play Storeにkeyを登録。その後apkをアップロード出来るようになるので、上の手順でサインしたリリースバージョンのapkをアップロードする。私は最初はオープンテストを選択した。審査に3日ほど必要だった。審査後に公開された。
    • foo.keystore と foo はkey生成時のファイルとワードに変更した
    java -jar pepk.jar --keystore=foo.keystore --alias=foo --output=output.zip --include-cert --encryptionkey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    

18.3 この章のまとめ

  • 64bitCPU用にビルドする必要があった
  • サインするのが結構面倒だった
  • apiを29以上にする必要あった(2020/10/23時点で)今後これはもっと上のバージョンになって行く

19 Googleのツールのbuildozerによる自動ダウンロードが出来なくなっています。(恐らく一時的?次のバージョンアップで解消される? 2021/02/01)

  • いつ出来なくなったのかは、2020/10/25〜2021/2/1のいつか(この間でパッケージビルドしてない為正確な日付不明)

19.1 以下の説明を行っている動画

19.2 手順

  • https://youtu.be/3U5_330aySk のようにして、あらかじめ、コマンドラインにて、必要な開発環境を用意
  • 上の手順でANDROID_SDK_ROOT にセットしたディレクトリ直下に、cmdline-tools/バージョン を tools にシンボリックリンク (最新バージョンインストールしてるなら SDKをいれようとしているディレクトリで、 ln -s cmdline-tools/latest tools)
  • 19cのndkを追加インストール(19cより新しいバージョンいれて、buildozerを動かすと、p4aが推奨してないとエラーが出る。 19bは sdkmanager ではインストール出来ない為, 19bは19cをインストールした時に表示されるURL名のcをbに変更すればダウンロード可能なので、それを ndk/android-ndk-r19b/ に移動)
  • v24のビルドツールを追加インストール(最新バージョンでエラーが出るかも知れないので追加インストールした。最新バージョンでもいけるかも、試してない)
  • buildozer.specのandroid.ndk_path, android.sdk_path, android.ant_pathを設定し

19.3 この章のまとめ

  • 今までの手順でパッケージ作成が出来なくなっているので、可能になる手順の一つを紹介
  • 今後のbuildozerのバージョンアップにて、この問題は恐らく解消?(個人的な予想)

20 opencvのコンパイル方法(邪道2021/02/05)

  • buildozerでopencvをインストールすることが出来なかった
  • buildozerでコンパイルに成功したので、その手順を紹介

20.1 以下の説明を行っている動画

20.2 手順

20.2.1 前準備

  • https://youtu.be/3U5_330aySk のようにして、あらかじめ、コマンドラインにて、必要な開発環境を用意(ndk,sdk,cmake等, Android Studioで用意してもよいかも)
  • 上の手順でANDROID_SDK_ROOT にセットしたディレクトリ直下に、cmdline-tools/バージョン を tools にシンボリックリンク (最新バージョンインストールしてるなら SDKをいれようとしているディレクトリで、 ln -s cmdline-tools/latest tools)
  • 19cのndkを追加インストール(19cより新しいバージョンいれて、buildozerを動かすと、p4aが推奨してないとエラーが出る。 19bは sdkmanager ではインストール出来ない為, 19bは19cをインストールした時に表示されるURL名のcをbに変更すればダウンロード可能なので、それを ndk/android-ndk-r19b/ に移動)
  • v24のビルドツールを追加インストール(最新バージョンでエラーが出るかも知れないので追加インストールした。最新バージョンでもいけるかも、試してない)
sdkmanager --list_installed
  • 上のコマンド実行時の出力が以下
    • cmakeは2種類は不要(試行錯誤したので2種類いれた,新しい方だけでOK)
Path                 | Version      | Description                             | Location             
-------              | -------      | -------                                 | -------              
build-tools;24.0.3   | 24.0.3       | Android SDK Build-Tools 24.0.3          | build-tools/24.0.3/  
build-tools;30.0.3   | 30.0.3       | Android SDK Build-Tools 30.0.3          | build-tools/30.0.3/  
cmake;3.10.2.4988404 | 3.10.2       | CMake 3.10.2.4988404                    | cmake/3.10.2.4988404/
cmake;3.6.4111459    | 3.6.4111459  | CMake 3.6.4111459                       | cmake/3.6.4111459/   
cmdline-tools;latest | 3.0          | Android SDK Command-line Tools (latest) | cmdline-tools/latest/
emulator             | 30.3.5       | Android Emulator                        | emulator/            
ndk-bundle           | 22.0.7026061 | NDK                                     | ndk-bundle/          
ndk;19.2.5345600     | 19.2.5345600 | NDK (Side by side) 19.2.5345600         | ndk/19.2.5345600/    
patcher;v4           | 1            | SDK Patch Applier v4                    | patcher/v4/          
platform-tools       | 30.0.5       | Android SDK Platform-Tools              | platform-tools/      
platforms;android-27 | 3            | Android SDK Platform 27                 | platforms/android-27/
platforms;android-29 | 5            | Android SDK Platform 29                 | platforms/android-29/
platforms;android-30 | 3            | Android SDK Platform 30                 | platforms/android-30/
Path                                     | Version      | Description                             | Location                                 
-------                                  | -------      | -------                                 | -------                                  
build-tools;30.0.3                       | 30.0.3       | Android SDK Build-Tools 30.0.3          | build-tools/30.0.3/                      
cmake;3.18.1                             | 3.18.1       | CMake 3.18.1                            | cmake/3.18.1/                            
cmdline-tools;latest                     | 5.0.0 rc1    | Android SDK Command-line Tools (latest) | cmdline-tools/latest/                    
emulator                                 | 30.4.3       | Android Emulator                        | emulator/                                
ndk;22.0.7026061                         | 22.0.7026061 | NDK (Side by side) 22.0.7026061         | ndk/22.0.7026061/                        
patcher;v4                               | 1            | SDK Patch Applier v4                    | patcher/v4/                              
platform-tools                           | 30.0.5       | Android SDK Platform-Tools              | platform-tools/                          
platforms;android-30                     | 3            | Android SDK Platform 30                 | platforms/android-30/                    
sources;android-30                       | 1            | Sources for Android 30                  | sources/android-30/                      
system-images;android-30;google_apis;x86 | 9            | Google APIs Intel x86 Atom System Image | system-images/android-30/google_apis/x86/

20.2.2 buildozerでパッケージ作成

  • 今までのbuildozerの手順でパッケージ作成
  • 前の章の内容のように、現状Googleの自動ダウンロードできなくなっている(2021/2/5現在、将来のバージョンで解決するとは思います)対応
    • buildozer.specのandroid.ndk_path, android.sdk_path, android.ant_pathを設定(上記用意した、NDKやSDKなどにパスを設定する。ndkは新しすぎるとエラーになるので、19系の最新のもので行った)
  • 必要パッケージにopencv追加
  • 作成しようとするとOpenCVのビルド関係でエラーがでるので以下を行った。(これはAndroidの開発環境をホームディレクトリの/Android/SDK/ (${HOME}/Android/SDK/)に入れた場合、他の場所にAndroid環境を入れた場合は、そのパスに設定)
cp ${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake ./.buildozer/android/platform/build-arm64-v8a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/cmake/android/OpenCVDetectAndroidSDK.cmake
chmod -w ./.buildozer/android/platform/build-arm64-v8a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/cmake/android/OpenCVDetectAndroidSDK.cmake
  • これを行ってから再度ビルドすると成功した
  • OpenCVの一部の機能を利用してAndroid端末で動作確認したところ、その機能は正常に動作していた(imread,cvtColor,flip)

20.3 この章のまとめ

  • opencvをbuildozer.specに設定しただけではインストールできなくなっていた不具合をさけて、ビルドすることに成功したので、その手順を紹介した。
  • 今後のbuildozer あるいは python-for-android のバージョンアップにて、この問題は恐らく解消?(個人的な予想)

21 Dlibのクロスコンパイル方法(邪道2021/02/14)

  • クロスコンパイルは、Ubuntu20.04で行った。
  • python-for-androidにDlib用のレシピがなかった。
  • クロスコンパイルもなかなか成功しなかったが、2021年にはいって、ライブラリのクロスコンパイルに成功、しかし、Python用のモジュールに必要な、動的ライブラリの生成に失敗していた。
  • Python用のAndroid用のモジュール、termux環境でpipコマンドにてインストールに成功した、そのファイルを、buildozerのプロジェクトディレクトリにコピーしたが、必要なライブラリが不足していて、termux環境からもってくる必要がありそうだった。Pythonの細かいコンパイル条件も同じではなさそうだったので、この方法は断念。
  • Python用のモジュールに必要な、動的ライブラリのクロスコンパイル、2021/2/13についに成功
  • 途中でエラーがでたときに、操作したりする邪道な手順となっているけど、コンパイルして、buildozerでAndroidのパッケージ化し、インストール動作させて、顔画像のパーツ認識まで成功している

21.2 以下の説明を行っている動画




21.3 手順

21.3.1 前準備

  • コマンドラインにて、AndroidのSDKやNDKをインストール。 https://youtu.be/3U5_330aySk
    • インストールするパッケージは以下で行った。
    • buildozerの現状のバージョンだと、NDKのバージョンは19c以下しか可能ではないので、19の一番新しいバージョンを入れてある
Path                 | Version      | Description                             | Location             
-------              | -------      | -------                                 | -------              
build-tools;24.0.3   | 24.0.3       | Android SDK Build-Tools 24.0.3          | build-tools/24.0.3/  
build-tools;30.0.3   | 30.0.3       | Android SDK Build-Tools 30.0.3          | build-tools/30.0.3/  
cmake;3.10.2.4988404 | 3.10.2       | CMake 3.10.2.4988404                    | cmake/3.10.2.4988404/
cmake;3.6.4111459    | 3.6.4111459  | CMake 3.6.4111459                       | cmake/3.6.4111459/   
cmdline-tools;latest | 3.0          | Android SDK Command-line Tools (latest) | cmdline-tools/latest/
emulator             | 30.3.5       | Android Emulator                        | emulator/            
ndk-bundle           | 22.0.7026061 | NDK                                     | ndk-bundle/          
ndk;19.2.5345600     | 19.2.5345600 | NDK (Side by side) 19.2.5345600         | ndk/19.2.5345600/    
patcher;v4           | 1            | SDK Patch Applier v4                    | patcher/v4/          
platform-tools       | 30.0.5       | Android SDK Platform-Tools              | platform-tools/      
platforms;android-27 | 3            | Android SDK Platform 27                 | platforms/android-27/
platforms;android-29 | 5            | Android SDK Platform 29                 | platforms/android-29/
platforms;android-30 | 3            | Android SDK Platform 30                 | platforms/android-30/
  • パッケージ環境を、作業ディレクトリを作成し、buildozer initで作成したあと、以下の変更を行う
    • arm64-v8a に buildozer.specのターゲット変更
    • 必要なパッケージをインストールするように修正
      • imutilsがあるとDlibで顔認識するとき便利なので、これも追加しておくことをオススメします。後から追加でも良いけど。
      • DlibのGUIでの表示コマンドはAndroid+Kivy+buildozerでは動作しなかったので、OpenCVあるいは、Pillow も入れておくことをオススメします。後から追加でも良いけど。OpenCVを入れる場合は現状はエラーになるので、https://www.youtube.com/embed/V0Z5cgzEsRg の手順でやれば回避可能(将来のバージョンでは、こんなややこしい手順不要になると思われる)
      • 追加情報
        • OpenCVの場合、画像表示は、Kivyのcanvasに、上下反転、カラーマップを変更して流し込めばいけた。カラーマップはrgbaにしとかないと、エラーになった。バージョンによって挙動ちがうかも。(kivy 2.0.0, Python3.8.5, OpenCV 4.5.1で試した。OpenCVのバージョンを4.5.1にするには、python-for-androidのOpenCV用のレシピを変更する必要あり)
    • android.ndk_path, android.sdk_path, android.ant_path を、この作業ディレクトリからの相対パスにて設定。
      • シンボリックリンクをはって、そこに設定した方が楽かも。私はこれは行ってないけど
    • その他必要な変更を行う
mkdir ${HOME}/mydlib
cd ${HOME}/mydlib
# source ~/kivy_buildozer/bin/activate # buildozer 用のvirturlenvが ~/kivy_buildozer にある場合
buildozer init
touch main.py # からのmain.pyを作成。何か動くものにした方が良いけど、ここでは空ファイル用意します。
# その後buildozer.specをテキストエディタで変更
  • main.pyを用意
    • dlibのバージョンも表示するようにしてあるので、dlibを入れる前だとエラーになる
    • dlibのPythonを上手くインストールできれば、Kivy, Python, Dlib, OpenCV, imutils のバージョンが表示される
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
import kivy
import sys 
import cv2
import dlib
import imutils

class HelloWorldApp(App):
 def build(self):
  b = BoxLayout(orientation="vertical")
  l2 = Label(text="Kivy:"+kivy.__version__,font_size=50)
  b.add_widget(l2)
  l4 = Label(text="Py:"+sys.version,font_size=20)
  b.add_widget(l4)
  l5 = Label(text="dlib:"+dlib.__version__,font_size=20)
  b.add_widget(l5)
  l6 = Label(text="opencv:"+cv2.__version__,font_size=20)
  b.add_widget(l6)
  l11 = Label(text="imutils:"+imutils.__version__,font_size=20)
  b.add_widget(l11)
  return b

if __name__ == '__main__':
 HelloWorldApp().run()
  • buildozer.specの変更箇所例
    • “… 省略” はbuildozer.specにコピペしない。変更しない箇所という意味
    • ndk,sdk,antのパスは実際用意してある、AndroidのNDKやSDKをあらかじめインストールしてあるパスに設定、この例では、ホームディレクトリのAndroid/SDK以下にインストールしている https://youtu.be/3U5_330aySk
    • android.arch は 現状Googleストアでうけつけてくれる64bitCPU用のものに変更(buildozer initした直後は32bit用のarmeabi-v7aになっている)
    • tiltleとパッケージネームは適当に変更してある
... 省略
title = MyDlibTest001
... 省略
package.name = mydlibtest001
... 省略
source.include_exts = py,png,jpg,kv,atlas,so
... 省略
requirements = python3,kivy==2.0.0,imutils,opencv
... 省略
android.ndk_path = ../Android/SDK/ndk/19.2.5345600
... 省略
android.sdk_path = ../Android/SDK
... 省略
android.ant_path = ../Android/SDK/cmdline-tools/latest/proguard/apache-ant-1.9.4/bin/ant
... 省略
android.arch = arm64-v8a
... 省略
  • Dlibの無い状態で、一旦Android用のバイナリを生成。
    • これによって、作業ディレクトリの .buildozer/ ディレクトリに、Dlibのクロスコンパイルに必要なファイルが生成される
    • OpenCVをrequirementsに追加してるなら、エラー発生現状はするので、前の章の手順で回避https://www.youtube.com/embed/V0Z5cgzEsRg。この手順は将来のバージョンでは不要になると思われる
buildozer android debug deploy run
  • 下が実行例 tee コマンド等でログをファイルに出しておくと良い
buildozer android debug deploy run 2>&1 | tee log001.txt

21.3.2 Dlibのソースゲット

  • 上のパッケージ作成とは別作業ディレクトリに移動。(例えば${HOME}/mydlib_dlibとか)
  • 最新安定バージョンは、コンパイル時にワーニング出まくります。なので今回はGithubの最新ソースをコンパイルします。
  • 最新安定バージョンでも同じ手順で多分クロスコンパイル出来るはず
# mkdir ${HOME}/mydlib_dlib  # 作業用のディレクトリ作成
# cd ${HOME}/mydlib_dlib     # 作業用のディレクトリに移動
git clone https://github.com/davisking/dlib

21.3.3 Dlibソースのバックアップ

  • dateコマンドを組み合わせた方だと、実行時の日付や日時入りのファイル名でバックアップ取れます。
  • 1行目のコマンドなら、dlib.org.tgz でバックアップ取れる
tar cvzf dlib.org.tgz dlib
# or
tar cvzf dlib.`date +%Y%m%d_%H%M`.tgz dlib

21.3.4 Dlibライブラリ(Python用は次の手順)のクロスコンパイル

  • Python用のクロスコンパイルするなら、ここの手順は不要
  • 作業用のディレクトリを作成し、そこに移動
    • これはコマンドラインで行わなくてもOK(使い慣れたツールでやってください)
cd dlib
mkdir build
cd build
  • 作業用のディレクトリを作成し、そこに移動し、以下を実行
    • Android用の開発環境はホームディレクトリの、Android/SDK ディレクトリ以下にインストール済み https://youtu.be/3U5_330aySk
    • ndkは19系の作業時点で一番新しいバージョンを利用した。
    • ターゲットは’arm64-v8a’にしている
    • 動的ライブラリを生成しようとしている -DANDROID_STL=c++_shared を無くせば、静的ライブラリを生成
    • ANDROID_PLATFORM=”android-16″の場合、他のバージョンにするなら、そこを変更
${HOME}/Android/SDK/cmake/3.10.2.4988404/bin/cmake -DBUILD_SHARED_LIBS=1 -DANDROID_NDK="${HOME}/Android/SDK/ndk/19.2.5345600" -DCMAKE_TOOLCHAIN_FILE="${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-std=c++11 -frtti -fexceptions" -DCMAKE_C_FLAGS=-O3 -DANDROID_ABI='arm64-v8a' -DANDROID_PLATFORM="android-16" -DANDROID_TOOLCHAIN=clang -DANDROID_STL=c++_shared -DANDROID_CPP_FEATURES=rtti exceptions .. 2>&1 | tee log001.txt

21.3.5 DlibライブラリPython用のクロスコンパイル

  • 作業用のディレクトリを作成し、そこに移動し、以下を実行
cd dlib
mkdir tools/python/build
cd tools/python/build
  • 設定のファイルの位置確認1
    • もし無いなら、find ${HOME}/mydlib/.buildozer/ -iname python -type f で探し、cmakeするときのオプションの該当箇所を変更
ls ${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/hostpython3/desktop/hostpython3/native-build/python
  • 設定のファイルの位置確認2
    • もし無いなら、find ${HOME}/mydlib/.buildozer/ -iname Python.h -type f で探し、そのディレクトリを調べておく、cmakeするときのオプションの該当箇所を変更
ls ${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Include 
  • 設定のファイルの位置確認3
    • もし無いなら、find ${HOME}/mydlib/.buildozer/ -iname libpython3.8.so -type f で探し、そのディレクトリを調べておく、cmakeするときのオプションの該当箇所を変更
ls ${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build/libpython3.8.so 
  • 以下のコマンドを実行,ただし、環境にあわせて、コマンド変更する必要あります。
    • 前準備で用意した、Androidパッケージの開発ディレクトリが、下の例だと ${HOME}/mydlib/ になっています。このディレクトリじゃない場合は、前準備で行ったディレクトリに変更してください。
    • Android用の開発環境はホームディレクトリの、Android/SDK ディレクトリ以下にインストール済み https://youtu.be/3U5_330aySk 。他のバージョンを利用する場合は、そこを変更してください。
  • その他の設定について
    • ndkは19系の作業時点で一番新しいバージョンを利用した。
    • ターゲットは’arm64-v8a’にしている
    • android.ndk_apiが21の場合。21以外なら、以下のコマンドの21をその番号に変更
    • lsコマンドで事前に調べたオプションが環境にあってないなら、該当箇所を変更
    • 2行目のコメントアウトしているコマンドは、2021/2/15現在で、python-for-android develp(githubで最新)を使う時のコマンド、Python関係のファイルの位置がちょっと違う
${HOME}/Android/SDK/cmake/3.10.2.4988404/bin/cmake -DANDROID_NDK="${HOME}/Android/SDK/ndk/19.2.5345600" -DCMAKE_TOOLCHAIN_FILE="${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI='arm64-v8a' -DANDROID_PLATFORM="android-21" -DANDROID_TOOLCHAIN=clang -DANDROID_CPP_FEATURES=rtti exceptions -DPYTHON_EXECUTABLE=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/hostpython3/desktop/hostpython3/native-build/python -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=build/lib.arm64-v8a -DPYTHON_INCLUDE_DIRS=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Include -DPYTHON_LIBRARY=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build/libpython3.8.so .. 2>&1 | tee log001.txt
# ${HOME}/Android/SDK/cmake/3.10.2.4988404/bin/cmake -DANDROID_NDK="${HOME}/Android/SDK/ndk/19.2.5345600" -DCMAKE_TOOLCHAIN_FILE="${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI='arm64-v8a' -DANDROID_PLATFORM="android-21" -DANDROID_TOOLCHAIN=clang -DANDROID_CPP_FEATURES=rtti exceptions -DPYTHON_EXECUTABLE=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/hostpython3/desktop/hostpython3/native-build/python -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=build/lib.arm64-v8a -DPYTHON_INCLUDE_DIRS=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3-libbz2-liblzma/arm64-v8a__ndk_target_21/python3/Include -DPYTHON_LIBRARY=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3-libbz2-liblzma/arm64-v8a__ndk_target_21/python3/android-build/libpython3.8.so .. 2>&1 | tee log001.txt # python-for-android develの場合こっちだった
  • 上のコマンドでエラーがなければ
make 2>&1 | tee log002.txt
  • これを実行すると、コンパイルには成功しますが、リンクの時にエラーが出ます。以下のようなエラーならOK。100%までコンパイルできずにエラーになってたら、上のcmakeのオプションがまずいので、修正
... 省略
[100%] Linking CXX shared module build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so
... 膨大なエラーメッセージ
  • リンクで失敗しているので、そこの命令をマニュアルで実行します。
  • CMakeFiles/_dlib_pybind11.dir/link.txt にリンク時のコマンドが生成されてるので、-L${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build -lpython3.8 を追加します。私は-latomic の前に挿入しました。
  • ユーザー名がyoutubeの時こんな感じ
/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -frtti  -O2 -DNDEBUG  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -shared  -o build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so CMakeFiles/_dlib_pybind11.dir/src/dlib.cpp.o CMakeFiles/_dlib_pybind11.dir/src/matrix.cpp.o CMakeFiles/_dlib_pybind11.dir/src/vector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_c_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_rank_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/decision_functions.cpp.o CMakeFiles/_dlib_pybind11.dir/src/other.cpp.o CMakeFiles/_dlib_pybind11.dir/src/basic.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cca.cpp.o CMakeFiles/_dlib_pybind11.dir/src/sequence_segmenter.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_struct.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image2.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image3.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image4.cpp.o CMakeFiles/_dlib_pybind11.dir/src/rectangles.cpp.o CMakeFiles/_dlib_pybind11.dir/src/object_detection.cpp.o CMakeFiles/_dlib_pybind11.dir/src/shape_predictor.cpp.o CMakeFiles/_dlib_pybind11.dir/src/correlation_tracker.cpp.o CMakeFiles/_dlib_pybind11.dir/src/face_recognition.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cnn_face_detector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/global_optimization.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image_dataset_metadata.cpp.o CMakeFiles/_dlib_pybind11.dir/src/numpy_returns.cpp.o CMakeFiles/_dlib_pybind11.dir/src/line.cpp.o dlib_build/libdlib.a -latomic -lm
  • -L${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build -lpython3.8 を追加例が以下
/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -frtti  -O2 -DNDEBUG  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -shared  -o build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so CMakeFiles/_dlib_pybind11.dir/src/dlib.cpp.o CMakeFiles/_dlib_pybind11.dir/src/matrix.cpp.o CMakeFiles/_dlib_pybind11.dir/src/vector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_c_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_rank_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/decision_functions.cpp.o CMakeFiles/_dlib_pybind11.dir/src/other.cpp.o CMakeFiles/_dlib_pybind11.dir/src/basic.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cca.cpp.o CMakeFiles/_dlib_pybind11.dir/src/sequence_segmenter.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_struct.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image2.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image3.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image4.cpp.o CMakeFiles/_dlib_pybind11.dir/src/rectangles.cpp.o CMakeFiles/_dlib_pybind11.dir/src/object_detection.cpp.o CMakeFiles/_dlib_pybind11.dir/src/shape_predictor.cpp.o CMakeFiles/_dlib_pybind11.dir/src/correlation_tracker.cpp.o CMakeFiles/_dlib_pybind11.dir/src/face_recognition.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cnn_face_detector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/global_optimization.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image_dataset_metadata.cpp.o CMakeFiles/_dlib_pybind11.dir/src/numpy_returns.cpp.o CMakeFiles/_dlib_pybind11.dir/src/line.cpp.o dlib_build/libdlib.a -L${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build -lpython3.8 -latomic -lm
  • このコマンドを実行すると、リンクして build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so が生成されます。ファイル名はlinux用になっていますが、中身は arm64-v8a用(Android64bit用)のバイナリになっています。
  • build/lib.arm64-v8a/以下のファイルが、必要ファイルになります。
  • ファイルサイズが240M程度で大きいので、以下を行うと11M程度までファイルが小さくなります。
${HOME}/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin/strip ./build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so
  • あとは./build/lib.arm64-v8a/dlib/ディレクトリを、Dlibを使いたいbuildozerプロジェクトディレクトリにコピーします。
    • コピー先のディレクトリ名は、各自変更してください。下の例だと ${HOME}/mydlib/ にインストールする場合
cp -r ./build/lib.arm64-v8a/dlib/ ${HOME}/mydlib/
  • 必要な動的ライブラリをコピーします
    • コピーする時にファイル名を変更しました。元のままでも動作するかどうかは未確認。ファイル名をもしかしたら、変更しなくても大丈夫かもしれない
    • コピー先のディレクトリ名は、各自変更してください。下の例だと ${HOME}/mydlib/ にインストールする場合
cp ./build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so ${HOME}/mydlib/_dlib_pybind11.cpython-38.so
  • この例だと ${HOME}/mydlib/ の Dlibを使いたいbuildozerプロジェクトを、再度コンパイルしなおせば、そのパッケージでDlibをPythonから使えます。

21.3.6 DlibライブラリPythonを含めたAndroidパッケージ作成とインストール

  • Android端末にUSB等でPCを接続し、以下のコマンドを実行して、Android端末にインストール、実行する
cd ${HOME}/mydlib/
buildozer android debug deploy run 2>&1 | tee log010.txt

21.4 その他

21.5 この章のまとめ

  • python-for-androidにレシピが用意されていなくて、Androidで使いにくかった、Dlibをbuildozerで利用するのに成功した邪道な作業手順を説明した。
  • もっとスマートな方法もあるとは思う
  • 今後もっと楽になる可能性大(buildozerや、python-for-androidのバージョンあがったら)。Dlibは人気のライブラリだし、レシピ用意されると思う。

22 今後

  • 今後も文書追加していきます。

23 この文書のチェンジログ

  • 2020/07/31 初版
  • 2020/08/13 Kivy+buildozer関連リンク の章追加
  • 2020/08/18 Kivy Launcherの使い方の章追加, plyer入りのKivy Launcherの作成とインストール(好きなパッケージ入りのKivy Launcherの作り方)の章追加
  • 2020/08/19 plyer関係の機能の利用方法の調べ方の章追加、広告の章、 課金の章追加
  • 2020/08/19 sl4a関係はkivyとは別物であったことと、kivy launcherカスタマイズしたが、GooglePlayにあるものと同名のものはソースが異ることを訂正,Kivy Launcherの使い方へのリンク追加
  • 2020/08/20 広告の章にKivModの詳細情報と、実際にサンプルソースを動かす手順を記述, 課金に例のリンクを追加
  • 2020/08/23 デバッグ手法いくつか紹介 の章追加, * pyjniusを使って、java経由でAndroid特有の機能の利用 の章追加, * Kivy Launcherの拡張その2 の章追加, 課金の情報にandroidモジュールの情報,公式Android開発環境の情報も追加
  • 2020/08/29 Kivy Launcherの拡張その3 の章追加
  • 2020/08/31 WebView(ウェブブラウザの部品への埋め込みandroid) の章追加
  • 2020/10/01 Kivy Launcherの拡張その4 の章追加
  • 2020/10/01 Kivyでmatplotlibでグラフ の章追加
  • 2020/10/23 Kivy+Buildozerで作成したAndroidアプリをGoogle Play Storeに出品する手順 の章追加
  • 2021/02/02 Googleのツールのbuildozerによる自動ダウンロードが出来なくなっています の章追加
  • 2021/02/05 opencvのコンパイル方法(邪道2021/02/05) の章追加
  • 2021/02/15 Dlibのクロスコンパイル方法(邪道2021/02/14) の章追加

著者: NM Max

Created: 2021-02-15 月 20:23

Validate

CERN ROOT v6-22-00(2020/07/09 最新リリースバージョン) インストール

CERN ROOT v6-22-00(2020/07/09 最新リリースバージョン) インストール

1 概要

  • 超有名なCERNで利用されている、C++インタプリタ+膨大なライブラリのROOTシステム
  • 昔はCINTという日本人作のC++インタプリタがコアだった、今はCINTからCling(LLVMのもの)におきかえられている

2 リンク

3 Ubuntu(20.04)でコンパイル、インストール

3.1 以下の操作を行っている動画


3.2 CERN ROOT のインストール 手順

3.2.1 依存パッケージのインストール

sudo apt install lsb-core cmake make binutils libx11-dev libxpm-dev libxft-dev libxext-dev
sudo apt install gfortran libssl-dev libpcre2-dev libegl1-mesa-dev libglu1-mesa-dev libglew-dev libftgl-dev libmysqlclient-dev fftw-dev libcfitsio-dev libgraphviz-dev  libavahi-compat-libdnssd-dev libldap2-dev python3-dev libxml2-dev libgsl-dev
sudo apt-get install dpkg-dev cmake g++ gcc binutils libx11-dev libxpm-dev libxft-dev libxext-dev python3
sudo apt-get install gfortran libssl-dev libpcre3-dev xlibmesa-glu-dev libglew1.5-dev libftgl-dev libmysqlclient-dev libfftw3-dev libcfitsio-dev graphviz-dev libavahi-compat-libdnssd-dev libldap2-dev python3-dev libxml2-dev libkrb5-dev libgs-dev qt5-default

3.2.2 ソースゲット

git clone --branch v6-22-00-patches https://github.com/root-project/root.git root_src

3.2.3 ソースバックアップ

tar czf root_src_v6-22-00-patches.tgz root_src/

3.2.4 コンパイル

mkdir v6-22-00-build v6-22-00
cd v6-22-00-build/
cmake -DCMAKE_INSTALL_PREFIX=/opt/root/v6-22-00 /opt/root/root_src 2>&1 | tee ./log001.txt
cmake --build . --target install 2>&1 | tee log002.txt
  • これでコンパイルが実行される、私のマシンで約3.5時間程度必要になった

3.3 バックアップ(インストールしたファイル群と、ビルドしたファイル群)

cd ..
tar cvzf v6-22-00.000.tgz v6-22-00/
tar cvzf v6-22-00-build.000.tgz v6-22-00-build/

3.4 動作確認

source v6-22-00/bin/thisroot.sh 
root
  • 上のコマンドで、環境の設定、ROOTの起動。以下の画面が表示された
   ------------------------------------------------------------------
  | Welcome to ROOT 6.22/01                        https://root.cern |
  | (c) 1995-2020, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Jul 09 2020, 12:45:00                 |
  | From heads/v6-22-00-patches@v6-22-00-41-gc1502e9d23              |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] 
  • テストで以下を入力
cout << 1+2 << endl
  • 以下が表示された
root [0] cout << 1+2 << endl
3
(std::basic_ostream<char, std::char_traits<char> >::__ostream_type &) @0x7f9081c39480
root [1] 
  • .quitと入力しEnterキーで終了
root [1] .quit

3.5 この章のまとめ

  • CERNのROOTをソースをコンパイルしてインストールしてみた

4 今後

  • 今後も文書追加していきます。

5 この文書のチェンジログ

  • 2020/07/09 初版

著者: NM Max

Created: 2020-07-09 木 20:46

Validate

YaneuraOuさんの将棋ソフトのUbuntuへのインストール(2020/7 バージョン)

YaneuraOuさんの将棋ソフトのUbuntuへのインストール(2020/7 バージョン)

目次

1 概要

  • ここ数年YaneuraOuさんの将棋ライブラリを利用した将棋ソフトがコンピューター将棋大会で優勝
  • C++とアセンブラベース
  • Stockfishというチェスソフトをかなり取り込んだ作りになってるらしい
  • GitHubにてソース公開されている
  • バージョンによって使い方が相当変化している
    • 昔のバージョンに戻せば、過去の動画の使い方も出来る(今は同じ方法で同じように使えない)
    • スレッド等他のライブラリとの依存関係があり、使う難易度が高い

2 リンク

3 エンジン部分のインストール

3.1 Ubuntuでコンパイル

3.1.1 以下の操作を行っている動画





3.2 手順

3.2.1 依存パッケージのインストール

  • 色々あると思う、私は色々入れていたので、私の環境の場合以下を入れる必要があった
sudo apt install bash vim clang make lldb gdb git libc6-dev wget unar
sudo apt install libomp-dev libopenblas-dev
sudo apt install uci2wb xboard 

3.2.2 利用PCのCPUチェック

  • avx拡張命令の利用可能チェック
grep -i avx /proc/cpuinfo
  • sse拡張命令の利用可能チェック
grep -i sse /proc/cpuinfo

3.2.3 ソースゲット

git clone https://github.com/yaneurao/YaneuraOu.git

3.2.4 ソースバックアップ

tar cvzf YaneuraOu.org.tgz YaneuraOu

3.2.5 コンパイル(トーナメントタイプの場合)

  • CPUがSSE42タイプの場合(私のマシンのCPUはタイプが古くAVX2タイプをサポートしていないため)
  • AVX2タイプのCPU命令可能な場合はSSE42の部分をAVX2にすればOK
  • SSE42もダメな場合はNO_SSEや、OTHER、ZEN2というCPUタイプも選択可能
  • UbuntuなどLinuxの場合は/proc/cpuinfoで利用可能かどうか確認可能 ( grep -i sse4 /proc/cpuinfo, grep -i avx2 /proc/cpuinfo 等)
cd YaneuraOu/source 
make clean tournament TARGET_CPU=SSE42
  • これでコンパイルが実行され、YaneuraOu-by-gcc っていう実行可能なファイルが生成される(必要なライブラリやツールがインストールされていた場合、不足している場合はエラーメッセージから必要なパッケージをインストールしていく)
  • 取得してソースバックアップし、コンパイル後にコンパイル後のファイルも保存するスクリプトが以下
  • 現状はSSE42用(CPUタイプ)
    • それ以外のCPUタイプ希望の場合は他のものを有効にし(行頭の#をとる)、SSE42のところをコメントに(行頭に#をいれる)
#!/bin/bash
#TARGET_CPU=AVX512
#TARGET_CPU=AVX2
TARGET_CPU=SSE42
#TARGET_CPU=SSE41
#TARGET_CPU=SSE2
#TARGET_CPU=NO_SSE
#TARGET_CPU=OTHER
#TARGET_CPU=ZEN2
D=`date +%Y%m%d`
DT=`date +%Y%m%d_%H%M`
mkdir ${DT}
cd ${DT}
git clone https://github.com/yaneurao/YaneuraOu.git
tar cvzf YaneuraOu_${DT}.tgz YaneuraOu/
(cd YaneuraOu/source && make clean tournament TARGET_CPU=${TARGET_CPU}) 2>&1 | tee ./log001.txt
tar cvzf YaneuraOu_${DT}_build.tgz YaneuraOu/
(
mkdir LEARN
cd LEARN
tar xvzf ../YaneuraOu_${DT}.tgz
(cd YaneuraOu/source && make clean evallearn TARGET_CPU=${TARGET_CPU}) 2>&1 | tee ./log002.txt
)

3.2.6 コンパイル(学習タイプの場合、評価関数ファイルを生成できるタイプ)

  • CPUがSSE42タイプの場合(私のマシンのCPUはタイプが古くAVX2タイプをサポートしていないため)
  • AVX2タイプのCPU命令可能な場合はSSE42の部分をAVX2にすればOK
  • SSE42もダメな場合はNO_SSEや、OTHER、ZEN2というCPUタイプも選択可能
  • UbuntuなどLinuxの場合は/proc/cpuinfoで利用可能かどうか確認可能 ( grep -i sse4 /proc/cpuinfo, grep -i avx2 /proc/cpuinfo 等)
make clean evallearn TARGET_CPU=SSE42
  • 同じく YaneuraOu-by-gcc というファイルが生成される
  • コンパイルする前にLEARNディレクトリにソースを解凍してそこで行った
mkdir LEARN
cd LEARN
tar xvzf ../YaneuraOu.org.tgz
cd YaneuraOu/source 

3.3 ゼロの評価関数ファイルの生成

  • 学習タイプの YaneuraOu-by-gcc の起動
./YaneuraOu-by-gcc
  • YaneuraOu/docs/解説.txt にある文書の手順で行う
EvalDir xyz              // 存在しないフォルダを評価関数の読み込みフォルダに指定する
SkipLoadingEval true     // こうしておけば評価関数ファイルの読み込みに失敗してもエラーにならない
isready                  // このタイミングで評価関数が読み込まれるが存在しないフォルダから読み込むのでゼロクリアされた評価関数を読み込んだことになる。
EvalSaveDir eval_zero    // 保存フォルダ名を"eval_zero"に設定(何でも良い)
test evalsave            // メモリ上の評価関数を保存するコマンド
  • 停止
quit                     // 停止
  • これにより eval_zero/nn.bin に評価関数ファイル nn.binが生成される
  • nn.binを競技用YaneuraOu-by-gccのあるディレクトリのevalの中に入れる
cp -i eval_zero/nn.bin ../../../YaneuraOu/source/eval/

3.4 動作確認

  • 以下のコマンドで起動
./YaneuraOu-by-gcc
  • usiコマンドをいれて動作確認(usi,d等)
usi
isready
d
  • quitで停止
quit

3.5 評価関数の準備

  • いくつか有力なものある
  • どれかを選択し、解凍したnn.binを eval ディレクトリにいれる

3.6 KristallweizenさんのKristallweizen_kaiV0.4.zipの場合

wget https://github.com/Tama4649/Kristallweizen/raw/master/Kristallweizen_kaiV0.4.zip
unar Kristallweizen_kaiV0.4.zip

3.7 評価関数 orqha レーティング約4330の評価関数

wget https://www.qhapaq.org/static/media/bin/orqha.7z
unar orqha.7z

3.8 Elmo wcsc29バージョン

unar elmo_wcsc29_eval.zip

3.9 定跡の準備

3.10 YaneuraOuさんの定跡

wget https://github.com/yaneurao/YaneuraOu/releases/download/BOOK-700T-Shock/700T-shock-book.zip https://github.com/yaneurao/YaneuraOu/releases/download/v4.73_book/standard_book.zip https://github.com/yaneurao/YaneuraOu/releases/download/v4.73_book/yaneura_book1_V101.zip https://github.com/yaneurao/YaneuraOu/releases/download/v4.73_book/yaneura_book3.zip 
unar 700T-shock-book.zip 
unar standard_book.zip 
unar yaneura_book1_V101.zip 
unar yaneura_book3.zip 

3.11 解凍したものを book というディレクトリを作成していれる

3.12 起動用のスクリプトファイルを用意

3.13 YaneuraOu-by-gccの起動用スクリプトファイル作成

#!/bin/sh
cd `dirname $0`
./YaneuraOu-by-gcc

3.14 実行権限を与える

chmod +x 作成したスクリプトファイル名
  • 例 startYaneuraOu.shなら
chmod +x startYaneuraOu.sh

3.15 ファイルの再配置

  • YaneuraOu-by-gcc はトーナメント用の実行ファイルを利用
.
├── FEN
├── YaneuraOu-by-gcc
├── book
│   ├── standard_book.db
│   ├── yaneura_book1.db
│   └── yaneura_book3.db
├── eval
│   └── nn.bin
└── startYaneuraOu.sh

3.16 エンジンの動作確認

  • startYaneuraOu.shを起動した後に以下を入れる
  • isready に対して readyok が返ってきたらOK (評価関数や、定跡ファイルとしてどれが利用されているか確認すること)
usi
isready
quit

4 GUIの準備

5 xboardの場合

  • インストールが一番簡単
  • 見た目がイマイチ
xboard -fcp "uci2wb debug -s /opt/shogi/20200707/startYaneuraOu.sh" -scp "uci2wb debug -s  /opt/shogi/20200707/startYaneuraOu.sh" -variant shogi  -coords  -pid /usr/share/games/xboard/themes/shogi/ -highlightSquareColor  "#00FFFF" -clockMode true -tc 5 -mps 30 -showMoveTime true -positionDir /opt/shogi/20200707/FEN -useBoardTexture true -liteBackTextureFile /usr/share/games/xboard/themes/textures/wood_d.png -darkBackTextureFile /usr/share/games/xboard/themes/textures/wood_d.png

6 Android用のYaneuraOuをビルド

  • Android用のバイナリを作るためのファイルも配布物に同梱されているらしいことに気づいたので、コンパイルしてみました。
  • 前準備として、Andrido NDKをインストールする必要があります。https://youtu.be/3U5_330aySk

6.1 以下の操作を行っている動画


6.2 Android用のYaneuraOuをビルド する手順

6.2.1 最新バージョンをコンパイル(2021/01/19時点)

  • 頻繁に更新されるため、これ以下の方法では、今後のバージョンコンパイルできない可能性あり
  • gitのタグだと 9bbd0f38498b22e9f3e6cf9493a7f8849c02e496 のものは以下でコンパイル出来ている(通常モードは作成可だった。能詰将棋エンジンはコンパイル中にエラーになる)
  1. YaneuraOuのソースゲット
    git clone https://github.com/yaneurao/YaneuraOu.git
    
  2. ソースのバックアップ
    • 最初の命令はdateコマンドで日付と時間をバックアップファイル名にする方法
    • 後の方はYaneuraOu_000.tgz というファイル名でバックアップ。別の名前でバックアップとっておいてもよい
    • 別のツールでバックアップもOK
    • バックアップ取らない選択もあり
    tar cvzf YaneuraOu_`date +%Y%m%d_%H%M`.tgz YaneuraOu/
    とか
    tar cvzf YaneuraOu_000.tgz YaneuraOu/
    
  3. コンパイル
    • コンパイルできるディレクトリに移動YaneuraOu/jni/
    cd YaneuraOu/jni/
    
    • 以下は64bit用の設定。
    • TARGET_ARCH_ABI=armeabi-v7a とすれば32bit用を作成可能
    • 他のCPUのタイプも含めて全部コンパイルするには TARGET_ARCH_ABI=なんちゃら を省略すればOK
    ndk-build TARGET_ARCH_ABI=arm64-v8a
    
    • 詰将棋エンジンをコンパイルするには以下(ただし、このバージョンではエラー発生してビルド失敗する)
      • ENGINE_NAME=YaneuraOu_MATE_arm64-v8a をいれてないとコンパイルエラーになる
    ndk-build YANEURAOU_EDITION=MATE_ENGINE TARGET_ARCH_ABI=arm64-v8a ENGINE_NAME=YaneuraOu_MATE_arm64-v8a
    

6.2.2 リリースバージョンをコンパイル(version4.88)

  1. YaneuraOuのソースゲット
    • https://github.com/ai5/YaneuraOuの右のReleasehttps://github.com/ai5/YaneuraOu/releasesに「Android版 やねうら王」となってる最新のところからダウンロード。2019/1/19時点で最新はv4.88https://github.com/ai5/YaneuraOu/releases/tag/android_488。zip版でもtar.gz版でもOK。私はtar.gzバージョンをダウンロードした。
    • もっと新しいバージョンでてるなら、そちらを選択してください。2021/1/19時点では4.88が最新
    • こちらは詰将棋エンジンバージョンもコンパイルは成功する。ただし、詰将棋をAndroidでとかせようとすると、セグメーテーションエラー発生。通常バージョンは正常動作していた。
  2. Android版 やねうら王v4.88のソース解凍
    tar xvzf YaneuraOu-android_488.tar.gz
    
  3. Android版 やねうら王v4.88のコンパイル
    • arm64-v8a (64bitCPU用)の詰将棋エンジンを作成します。
    cd YaneuraOu-android_488/jni/
    ndk-build ENGINE_TARGET=MATE_ENGINE TARGET_ARCH_ABI=arm64-v8a
    
    • ../libs/arm64-v8a/YaneuraOu-mate-arm64-v8a が作成されます。
      • ただ私がUmidigi F1Playで動作確認したところ、go mate infiniteするとセグメンテーションエラーで落ちてしまい、詰将棋とけませんでした。
      • エンジンオプションでなんとかならないか色々試しました(Hash減らすとか)が上手く動作せず
      • デバッガーオプションつけて、デバッガーでそのうち確認してみようと思ってますが。まだやってません。
    • arm64-v8a (64bitCPU用)の通常バージョンを作成します。
    ndk-build TARGET_ARCH_ABI=arm64-v8a
    
    • ../libs/arm64-v8a/YaneuraOu-nnue-halfkp256-arm64-v8aが作成されます。
      • こちらは上手く動作しました。Umidigi F1Playで。評価関数と、定跡ファイルをいれれば

6.3 この章のまとめ

  • Android用のバイナリをクロスコンパイルしてみた。
  • 通常の将棋エンジンは、上手くコンパイル実行できていました。また動作確認結果も良好。
  • 詰将棋エンジンは、最新のソースでは上手くコンパイルできず、リリースバージョンでも、コンパイルは出来るものの、詰将棋をとかせる命令(go mate infinite等))を入れるとセグメンテーションエラーが発生

7 Android用のYaneuraOuをビルド2(2021/05/17)

  • 前からノーマル将棋エンジンはクロスコンパイルに成功していた
  • 詰将棋エンジンはv4.88はコンパイルには成功するものの、動かすとセグメンテーションエラーで動かなかった
  • 詰将棋エンジンは最新バージョンでコンパイルに成功しなかった。(色々エラー出て)
  • 久しぶりにGitHubから最新ソースをゲットして、クロスコンパイルを環境変数の設定色々変更してやってみたら、上手くいった

7.1 以下の操作を行っている動画


7.2 Android用のYaneuraOuをビルド2(2021/05/17)を行う手順

  • 前準備として、Andrido NDKをインストールする必要があります。https://youtu.be/3U5_330aySk
  • sdkmanager –list_installed で確認したインストール済みのAndroid SDK NDK関係は以下の通り
    • コンパイルに利用したndkはndk-bundleを利用した
Installed packages:=====================] 100% Fetch remote repository...       
  Path                   | Version      | Description                             | Location               
  -------                | -------      | -------                                 | -------                
  build-tools;24.0.3     | 24.0.3       | Android SDK Build-Tools 24.0.3          | build-tools/24.0.3/    
  build-tools;29.0.2     | 29.0.2       | Android SDK Build-Tools 29.0.2          | build-tools/29.0.2/    
  build-tools;30.0.2     | 30.0.2       | Android SDK Build-Tools 30.0.2          | build-tools/30.0.2/    
  build-tools;30.0.3     | 30.0.3       | Android SDK Build-Tools 30.0.3          | build-tools/30.0.3/    
  build-tools;31.0.0-rc2 | 31.0.0 rc2   | Android SDK Build-Tools 31-rc2          | build-tools/31.0.0-rc2/
  cmake;3.10.2.4988404   | 3.10.2       | CMake 3.10.2.4988404                    | cmake/3.10.2.4988404/  
  cmake;3.6.4111459      | 3.6.4111459  | CMake 3.6.4111459                       | cmake/3.6.4111459/     
  cmdline-tools;latest   | 4.0          | Android SDK Command-line Tools (latest) | cmdline-tools/latest/  
  emulator               | 30.6.5       | Android Emulator                        | emulator/              
  ndk-bundle             | 22.1.7171670 | NDK                                     | ndk-bundle/            
  ndk;19.2.5345600       | 19.2.5345600 | NDK (Side by side) 19.2.5345600         | ndk/19.2.5345600/      
  patcher;v4             | 1            | SDK Patch Applier v4                    | patcher/v4/            
  platform-tools         | 31.0.2       | Android SDK Platform-Tools              | platform-tools/        
  platforms;android-27   | 3            | Android SDK Platform 27                 | platforms/android-27/  
  platforms;android-29   | 5            | Android SDK Platform 29                 | platforms/android-29/  
  platforms;android-30   | 3            | Android SDK Platform 30                 | platforms/android-30/  
  • 頻繁に更新されるため、これ以下の方法では、今後のバージョンコンパイルできない可能性あり
  • gitのタグだと a866bafb71aae5833be3d34c1227564c6ccb323b のものは以下でコンパイル出来ている。
    • YaneuraOuさんのソースの更新頻度高く、新しいバージョンで同じ手順で成功しなくなるかも。その時は上の git の id に git checkout a866bafb71aae5833be3d34c1227564c6ccb323b で戻して、そこで同じ手順でやれば上手くいくはず
  • 動画では、Docker Image( https://youtu.be/473GGAkxqy8に作成方法ある)を使ってコンパイルしています。
  1. YaneuraOuのソースゲット
    git clone https://github.com/yaneurao/YaneuraOu.git
    
  2. ソースのバックアップ
    • 最初の命令はdateコマンドで日付と時間をバックアップファイル名にする方法
    • 後の方はYaneuraOu_000.tgz というファイル名でバックアップ。別の名前でバックアップとっておいてもよい
    • 別のツールでバックアップもOK
    • バックアップ取らない選択もあり
    tar cvzf YaneuraOu_`date +%Y%m%d_%H%M`.tgz YaneuraOu/
    とか
    tar cvzf YaneuraOu_000.tgz YaneuraOu/
    
  3. コンパイル
    • コンパイルできるディレクトリに移動YaneuraOu/jni/
      • 備考 YaneuraOu/jni/ でなく YaneuraOu/ ディレクトリでもコンパイルできた 
    cd YaneuraOu/jni/
    
    • 以下は64bit用の設定。
      • TARGET_ARCH_ABI=armeabi-v7a とすれば32bit用を作成可能
      • 他のCPUのタイプも含めて全部コンパイルするには TARGET_ARCH_ABI=なんちゃら を省略すればOK
      • 実行ファイルのバックアップと、転送の手順は省略している
      • この実行ファイルの動作確認には、評価関数ファイルが必要
      • 定跡ファイルもあった方が良い
    ndk-build TARGET_ARCH_ABI=arm64-v8a clean #掃除
    ndk-build TARGET_ARCH_ABI=arm64-v8a
    mkdir -p arm64-v8a/ #バックアップ用のディレクトリ作成
    mv ../libs/arm64-v8a/YaneuraOu_NNUE_arm64-v8a arm64-v8a/ # 消さないようにビルドしたバイナリを移動
    
  4. tanuki詰将棋エンジンコンパイル
    • 詰将棋エンジンをコンパイルするには以下
      • ENGINE_NAME に設定必要
      • YANEURAOU_EDITION は MATE_ENGINE だとリンク時にエラー発生
      • YANEURAOU_EDITION は TANUKI_MATE_ENGINE か YANEURAOU_ENGINE_MATERIAL なら ビルド可能
    • YANEURAOU_EDITION=TANUKI_MATE_ENGINE と設定するとtanuki詰将棋エンジンビルド
    ndk-build YANEURAOU_EDITION=TANUKI_MATE_ENGINE TARGET_ARCH_ABI=arm64-v8a ENGINE_NAME=Tanuki_MATE_arm64-v8a  clean # 最初にファイルクリア
    ndk-build YANEURAOU_EDITION=TANUKI_MATE_ENGINE TARGET_ARCH_ABI=arm64-v8a ENGINE_NAME=Tanuki_MATE_arm64-v8a  2>&1 | tee log_tanukimate001.txt # ビルド
    mkdir -p arm64-v8a/
    mv ../libs/arm64-v8a/Tanuki_MATE_arm64-v8a_arm64-v8a arm64-v8a/  # 消さないようにビルドしたバイナリを移動
    
  5. YaneuraOu詰将棋エンジンコンパイル
    • YANEURAOU_EDITION=YANEURAOU_ENGINE_MATERIALと設定するとYaneuraOu詰将棋エンジンビルド
    ndk-build YANEURAOU_EDITION=YANEURAOU_ENGINE_MATERIAL TARGET_ARCH_ABI=arm64-v8a ENGINE_NAME=YaneuraOu_MATE_arm64-v8a clean #  最初にファイルクリア
    ndk-build YANEURAOU_EDITION=YANEURAOU_ENGINE_MATERIAL TARGET_ARCH_ABI=arm64-v8a ENGINE_NAME=YaneuraOu_MATE_arm64-v8a 2>&1 | tee log_yanemate001.txt # ビルド
    mkdir -p arm64-v8a/
    mv ../libs/arm64-v8a/YaneuraOu_MATE_arm64-v8a_arm64-v8a  arm64-v8a/ # 消さないようにビルドしたバイナリを移動
    

7.3 動作確認

7.3.1 ビルドしたファイル転送

  • 動作確認するAndroid端末とUSB接続してから以下を実行
adb push arm64-v8a/* /data/local/tmp
# or
# adb push ./arm64-v8a/YaneuraOu_NNUE_arm64-v8a ./arm64-v8a/Tanuki_MATE_arm64-v8a_arm64-v8a ./arm64-v8a/YaneuraOu_MATE_arm64-v8a_arm64-v8a /data/local/tmp

7.3.2 実行

  1. tanuki詰将棋エンジンの実行
    adb shell /data/local/tmp/Tanuki_MATE_arm64-v8a_arm64-v8a 
    
  2. YaneuraOu詰将棋エンジンの実行
    adb shell /data/local/tmp/YaneuraOu_MATE_arm64-v8a_arm64-v8a 
    
  3. USIコマンド
    • 最初はこれをいれて、エンター
    usi
    
    • 次にこれをいれて、エンター
    isready
    
    • テスト用の盤面設定
    position lnsgkgsnl/1r5b1/ppp1+Ppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b N 1
    
    • 盤面確認(YaneuraOuさんソフト用のUSI拡張コマンド)
    d
    
    • 詰将棋解く (制限時間60秒 秒はmsec単位で与える。無制限の場合は infinite)
    go mate 60000
    
    • 終了
    quit
    

7.4 この章のまとめ

  • Android用のバイナリをクロスコンパイルしてみた。
  • 昔ダメだった、詰将棋エンジンのコンパイルと動作に成功した。(ダメだったのは、コンパイルオプションがまずかったのか、他の原因なのか調べてない)
    • コンパイル時の環境変数の設定を変更したら、最新版のソースで上手くいった
    • リリースバージョンのv4.88では詰将棋エンジン関係は未確認

8 今後

  • 今後も文書追加していきます。

9 この文書のチェンジログ

  • 2020/07/07 初版
  • 2021/01/19 Android用のYaneuraOuをビルド の章追加
  • 2021/05/17 Android用のYaneuraOuをビルド2 の章追加(最新バージョンのソースで、詰将棋エンジンのコンパイルと動作に成功)

著者: NM Max

Created: 2021-05-19 水 06:52

Validate

YaneuraOuさんの将棋ライブラリで楽しむ(2020バージョン)

YaneuraOuさんの将棋ライブラリで楽しむ(2020/7バージョン)

目次

1 概要

  • ここ数年YaneuraOuさんの将棋ライブラリを利用した将棋ソフトがコンピューター将棋大会で優勝
  • C++とアセンブラベース
  • Stockfishというチェスソフトをかなり取り込んだ作りになってるらしい
  • GitHubにてソース公開されている
  • バージョンによって使い方が相当変化している
    • 昔のバージョンに戻せば、過去の動画の使い方も出来る(今は同じ方法で同じように使えない)
    • スレッド等他のライブラリとの依存関係があり、使う難易度が高い
  • YaneuraOuさんの将棋ソフトのUbuntuへのインストール(2020/7 バージョン) という別文書とリンク部分とインストール部分はほぼ同じ

2 リンク

3 Ubuntuでコンパイル

3.1 以下の操作を行っている動画





3.2 easyAIのインストール 手順

3.3 手順

3.3.1 依存パッケージのインストール

  • 色々あると思う、私は色々入れていたので、私の環境の場合以下を入れる必要があった
sudo apt install libomp-dev libopenblas-dev

3.3.2 ソースゲット

git clone https://github.com/yaneurao/YaneuraOu.git

3.3.3 ソースバックアップ

tar cvzf YaneuraOu.org.tgz YaneuraOu

3.3.4 コンパイル(トーナメントタイプの場合)

  • CPUがSSE42タイプの場合(私のマシンのCPUはタイプが古くAVX2タイプをサポートしていないため)
  • AVX2タイプのCPU命令可能な場合はSSE42の部分をAVX2にすればOK
  • SSE42もダメな場合はNO_SSEや、OTHER、ZEN2というCPUタイプも選択可能
  • UbuntuなどLinuxの場合は/proc/cpuinfoで利用可能かどうか確認可能 ( grep -i sse4 /proc/cpuinfo, grep -i avx2 /proc/cpuinfo 等)
cd YaneuraOu/source 
make clean tournament TARGET_CPU=SSE42
  • これでコンパイルが実行され、YaneuraOu-by-gcc っていう実行可能なファイルが生成される(必要なライブラリやツールがインストールされていた場合、不足している場合はエラーメッセージから必要なパッケージをインストールしていく)
  • 取得してソースバックアップし、コンパイル後にコンパイル後のファイルも保存するスクリプトが以下
#!/bin/bash
#TARGET_CPU=AVX512
#TARGET_CPU=AVX2
TARGET_CPU=SSE42
#TARGET_CPU=SSE41
#TARGET_CPU=SSE2
#TARGET_CPU=NO_SSE
#TARGET_CPU=OTHER
#TARGET_CPU=ZEN2
D=`date +%Y%m%d`
DT=`date +%Y%m%d_%H%M`
mkdir ${DT}
cd ${DT}
git clone https://github.com/yaneurao/YaneuraOu.git
tar cvzf YaneuraOu_${DT}.tgz YaneuraOu/
(cd YaneuraOu/source && make clean tournament TARGET_CPU=${TARGET_CPU}) 2>&1 | tee ./log001.txt
tar cvzf YaneuraOu_${DT}_build.tgz YaneuraOu/
(
mkdir LEARN
cd LEARN
tar xvzf ../YaneuraOu_${DT}.tgz
(cd YaneuraOu/source && make clean evallearn TARGET_CPU=${TARGET_CPU}) 2>&1 | tee ./log002.txt
)

3.3.5 コンパイル(学習タイプの場合、評価関数ファイルを生成できるタイプ)

  • CPUがSSE42タイプの場合(私のマシンのCPUはタイプが古くAVX2タイプをサポートしていないため)
  • AVX2タイプのCPU命令可能な場合はSSE42の部分をAVX2にすればOK
  • SSE42もダメな場合はNO_SSEや、OTHER、ZEN2というCPUタイプも選択可能
  • UbuntuなどLinuxの場合は/proc/cpuinfoで利用可能かどうか確認可能 ( grep -i sse4 /proc/cpuinfo, grep -i avx2 /proc/cpuinfo 等)
make clean evallearn TARGET_CPU=SSE42
  • 同じく YaneuraOu-by-gcc というファイルが生成される
  • コンパイルする前にLEARNディレクトリにソースを解凍してそこで行った
mkdir LEARN
cd LEARN
tar xvzf ../YaneuraOu.org.tgz
cd YaneuraOu/source 

3.4 ゼロの評価関数ファイルの生成

3.4.1 以下の操作を行っている動画


3.4.2 手順

  • 学習タイプの YaneuraOu-by-gcc の起動
./YaneuraOu-by-gcc
  • YaneuraOu/docs/解説.txt にある文書の手順で行う
EvalDir xyz              // 存在しないフォルダを評価関数の読み込みフォルダに指定する
SkipLoadingEval true     // こうしておけば評価関数ファイルの読み込みに失敗してもエラーにならない
isready                  // このタイミングで評価関数が読み込まれるが存在しないフォルダから読み込むのでゼロクリアされた評価関数を読み込んだことになる。
EvalSaveDir eval_zero    // 保存フォルダ名を"eval_zero"に設定(何でも良い)
test evalsave            // メモリ上の評価関数を保存するコマンド
  • これにより eval_zero/nn.bin に評価関数ファイル nn.binが生成される
  • nn.binを競技用YaneuraOu-by-gccのあるディレクトリのevalの中に入れる
cp -i eval_zero/nn.bin ../../../YaneuraOu/source/eval/

3.5 動作確認

  • 以下のコマンドで起動
./YaneuraOu-by-gcc
  • usiコマンドをいれて動作確認(usi,d等)
usi
isready
d
  • quitで停止
quit

4 下準備

4.1 以下の操作を行っている動画


4.2 Makefileの修正

  • YaneuraOu/sourceディレクトリで以下の作業を行う

4.2.1 Makefile の バックアップ

cp Makefile Makefile.org

4.2.2 myMain.cpp の 作成

cp main.cpp myMain.cpp

4.3 Makefileの修正

4.3.1 Makefile 修正内容

  • CPUタイプの修正、(各自該当のCPUに変更、私のPCのCPUはSSE42タイプ)
  • デバッグ機能をオン, デバッグ情報追加
  • libYaneuraOu-by-gcc.so という動的ライブラリファイル作成、動的ライブラリにするため、コンパイル時に -fPICオプション追加
  • 独自のmain関数用のmyMain.cppを追加し、これをメイン関数とした myMainを作成、myMainを更新成功したら、myMainを実行

4.3.2 Makefileを修正し、以下のコマンドで、patchファイルを作成した

diff -c Makefile.org Makefile > Makefile.diff
  • CPU SSE42タイプの場合のMakefileが以下
# ビルドターゲット
# normal     : 通常使用用
# evallearn  : 教師局面からの学習用
# tournament : 大会で使う用
# gensfen    : 教師生成用(現状、非公開)


# やねうら王の使いたいエディションを指定する
# YANEURAOU_ENGINE_NNUE       : NNUE型評価関数(halfKP256),標準NNUE型
# YANEURAOU_ENGINE_NNUE_KP256 : NNUE型評価関数(KP256)
# YANEURAOU_ENGINE_KPPT       : KPPT型評価関数
# YANEURAOU_ENGINE_KPP_KKPT   : KPP_KKPT型評価関数
# YANEURAOU_ENGINE_MATERIAL   : 駒得のみの評価関数
# MATE_ENGINE                 : tanuki- 詰将棋エンジン
# USER_ENGINE                 : USER定義エンジン

YANEURAOU_EDITION = YANEURAOU_ENGINE_NNUE
#YANEURAOU_EDITION = YANEURAOU_ENGINE_NNUE_KP256
#YANEURAOU_EDITION = YANEURAOU_ENGINE_KPPT
#YANEURAOU_EDITION = YANEURAOU_ENGINE_KPP_KKPT
#YANEURAOU_EDITION = YANEURAOU_ENGINE_MATERIAL
#YANEURAOU_EDITION = MATE_ENGINE
#YANEURAOU_EDITION = USER_ENGINE


# ターゲットCPU
# 利用できるCPU拡張命令を指定する。
# ARM系ならOTHERを指定する。
# 32bit環境用はNO_SSE
# AMDのZen2はZEN2を選択すると良いかも?(clang9以降で対応)

#TARGET_CPU = AVX512
#TARGET_CPU = AVX2
TARGET_CPU = SSE42
#TARGET_CPU = SSE41
#TARGET_CPU = SSE2
#TARGET_CPU = NO_SSE
#TARGET_CPU = OTHER
#TARGET_CPU = ZEN2


# デバッガーを使用するか
#DEBUG = OFF
DEBUG = ON


# clangでコンパイルしたほうがgccより数%速いっぽい。
#COMPILER = g++
COMPILER = clang++


# 標準的なコンパイルオプション
CFLAGS   = -std=c++17 -fno-exceptions -fno-rtti -Wextra -Ofast -MMD -MP -fpermissive
WCFLAGS  =
LDFLAGS  =
LIBS     =
INCLUDE  = # -I../include

# デバッガーを使わないなら、NDEBUGをdefineする。
ifeq ($(DEBUG),OFF)
        CFLAGS += -DNDEBUG
endif

# clang用にCFLAGSなどを変更
ifeq ($(findstring clang++,$(COMPILER)),clang++)
        # stdlib
        CFLAGS += -stdlib=libstdc++

        # C++17のfilesystem
        # LDFLAGS += -lstdc++fs

        # 関数の引数が関数本体で使われていないときに警告出るのうざすぎるので抑制。
        CFLAGS += -Wno-unused-parameter

        # static リンクを行う際に __cxa_guard_acquire __cxa_guard_release の生成を抑止
        #   undefined reference to `__imp___cxa_guard_acquire'
        #   undefined reference to `__imp___cxa_guard_release'
        # static 変数を初期化したかを pthread_mutex_t でロックを取って確認し、
        # 最初の実行なら初期化するスレッドセーフなコードを生成するためのもの。
        # → 本当に消してしまっても大丈夫か?
        WCFLAGS += -fno-threadsafe-statics

else
        ifeq ($(findstring g++,$(COMPILER)),g++)
                # mingw g++ で AVX512 向けビルドを行おうとするとエラーになる問題の回避
                # https://stackoverflow.com/questions/43152633/invalid-register-for-seh-savexmm-in-cygwin
                # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65782
                WCFLAGS += -fno-asynchronous-unwind-tables

                # C++17のfilesystem
                # LDFLAGS += -lstdc++fs

        endif
endif

ifeq ($(OS),Windows_NT)
        CFLAGS += $(WCFLAGS)
        LDFLAGS += -static -Wl,--stack,25000000
        TARGET = YaneuraOu-by-gcc.exe
else
        CFLAGS += -D_LINUX
        TARGET = YaneuraOu-by-gcc
endif

# リンク時最適化。
# CFLAGSとLDFLAGSの両方で-fltoを指定する必要がある。
# cf. https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Optimize-Options.html#Optimize-Options
LTOFLAGS = -flto

# wstringを使うためにこのシンボル定義が必要。
CFLAGS  += -DUNICODE

# stripの指示。(実行ファイルのサイズを小さく)
LDFLAGS += -Wl,-s

# mingw64では-D_WIN64,-D_WIN32は環境に応じて自動で設定されるので指定すべきではない。
# CFLAGS += -D_WIN64

# これを指定していると、各CPU向けの実行ファイルが生成されないので指定すべきではない。
# CFLAGS   += -march=native

# デバッグ情報を付加
CFLAGS  += -g3 -ggdb
CFLAGS  += -fPIC

# OpenMPを使うときにCFLAGSとして指定するオプション
# ※ 学習部ではOpenMpを用いるので、学習用のビルドではこのオプションを指定する。
# clangでOPENMPを有効にしてビルドする方法については、解説.txtを参照のこと。

# エンジンの表示名("usi"コマンドに対して出力される)
#ENGINE_NAME =

# 開発中のbranchならdevと指定する
#ENGINE_BRANCH = dev

ifeq ($(findstring g++,$(COMPILER)),g++)
        OPENMP   = -fopenmp
        OPENMP_LDFLAGS =
endif
ifeq ($(findstring clang++,$(COMPILER)),clang++)
        ifeq ($(MSYSTEM),MINGW64)
                # MSYS2 MINGW64 env
                # libgompを指定した場合、ビルドは通るがOpenMPは無効化される?
                OPENMP = -fopenmp=libgomp
                OPENMP_LDFLAGS =
        else
                ifeq ($(findstring w64-mingw32,$(COMPILER)),w64-mingw32)
                        # Ubuntu mingw-w64 clang++ env (experimental)
                        OPENMP = -fopenmp=libgomp
                        OPENMP_LDFLAGS =
                else
                        # Other (normal clang++/libomp env)
                        OPENMP = -fopenmp
                        OPENMP_LDFLAGS = -lomp
                endif
        endif
endif

# NNUE評価関数 学習バイナリ用 OpenBLAS
ifeq ($(findstring YANEURAOU_ENGINE_NNUE,$(YANEURAOU_EDITION)),YANEURAOU_ENGINE_NNUE)
        BLAS = -DUSE_BLAS
        BLAS_LDFLAGS = -lopenblas
        ifeq ($(MSYSTEM),MINGW64)
                BLAS += -I$(shell cygpath -aw /mingw64/include/OpenBLAS)
        endif
endif

CFLAGS += -DNO_EXCEPTIONS
LDFLAGS += -lpthread
LDFLAGS += -v

OBJDIR   = ../obj
ifeq "$(strip $(OBJDIR))" ""
        OBJDIR = ..
endif

#SOURCES  = $(wildcard *.cpp)
SOURCES  = \
        main.cpp                                                                   \
        types.cpp                                                                  \
        bitboard.cpp                                                               \
        misc.cpp                                                                   \
        movegen.cpp                                                                \
        position.cpp                                                               \
        usi.cpp                                                                    \
        usi_option.cpp                                                             \
        thread.cpp                                                                 \
        tt.cpp                                                                     \
        movepick.cpp                                                               \
        timeman.cpp                                                                \
        benchmark.cpp                                                              \
        extra/book/apery_book.cpp                                                  \
        extra/book/book.cpp                                                        \
        extra/book/makebook2019.cpp                                                \
        extra/bitop.cpp                                                            \
        extra/long_effect.cpp                                                      \
        extra/mate/mate1ply_with_effect.cpp                                        \
        extra/mate/mate1ply_without_effect.cpp                                     \
        extra/mate/mate_n_ply.cpp                                                  \
        extra/test_cmd.cpp                                                         \
        extra/sfen_packer.cpp                                                      \
        extra/kif_converter/kif_convert_tools.cpp                                  \
        eval/evaluate_bona_piece.cpp                                               \
        eval/evaluate.cpp                                                          \
        eval/evaluate_io.cpp                                                       \
        eval/evaluate_mir_inv_tools.cpp                                            \
        learn/learner.cpp                                                          \
        learn/learning_tools.cpp                                                   \
        learn/multi_think.cpp

ifeq ($(YANEURAOU_EDITION),YANEURAOU_ENGINE_KPPT)
        SOURCES += \
                eval/kppt/evaluate_kppt.cpp                                            \
                eval/kppt/evaluate_kppt_learner.cpp                                    \
                engine/yaneuraou-engine/yaneuraou-search.cpp
endif

ifeq ($(YANEURAOU_EDITION),YANEURAOU_ENGINE_KPP_KKPT)
        SOURCES += \
                eval/kppt/evaluate_kppt.cpp                                            \
                eval/kpp_kkpt/evaluate_kpp_kkpt.cpp                                    \
                eval/kpp_kkpt/evaluate_kpp_kkpt_learner.cpp                            \
                engine/yaneuraou-engine/yaneuraou-search.cpp
endif

ifeq ($(YANEURAOU_EDITION),YANEURAOU_ENGINE_MATERIAL)
        SOURCES += \
                engine/yaneuraou-engine/yaneuraou-search.cpp
endif

ifeq ($(findstring YANEURAOU_ENGINE_NNUE,$(YANEURAOU_EDITION)),YANEURAOU_ENGINE_NNUE)
        ifeq ($(YANEURAOU_EDITION),YANEURAOU_ENGINE_NNUE)
        else
                CFLAGS += -DYANEURAOU_ENGINE_NNUE
        endif
        ifeq ($(YANEURAOU_EDITION),YANEURAOU_ENGINE_NNUE_KP256)
                CFLAGS += -DEVAL_NNUE_KP256
        else
                ifeq ($(NNUE_EVAL_ARCH),KP256)
                        CFLAGS += -DEVAL_NNUE_KP256
                endif
        endif
        SOURCES += \
                eval/nnue/evaluate_nnue.cpp                                            \
                eval/nnue/evaluate_nnue_learner.cpp                                    \
                eval/nnue/nnue_test_command.cpp                                        \
                eval/nnue/features/k.cpp                                               \
                eval/nnue/features/p.cpp                                               \
                eval/nnue/features/half_kp.cpp                                         \
                eval/nnue/features/half_relative_kp.cpp                                \
                engine/yaneuraou-engine/yaneuraou-search.cpp
endif

ifeq ($(YANEURAOU_EDITION),MATE_ENGINE)
        SOURCES += engine/mate-engine/mate-search.cpp
endif

ifeq ($(YANEURAOU_EDITION),USER_ENGINE)
        SOURCES += engine/user-engine/user-search.cpp
endif

ifneq ($(ENGINE_NAME),)
        CFLAGS += -DENGINE_NAME_FROM_MAKEFILE=$(ENGINE_NAME)
endif

# 開発用branch
ifeq ($(findstring dev,$(ENGINE_BRANCH)),dev)
        # SuperSort使ってみよう。
        SOURCES += extra/super_sort.cpp
endif


# CPU判別

# AMDなど特定のCPU
ifeq ($(TARGET_CPU),ZEN2)
        CFLAGS += -DUSE_AVX2 -mbmi -mbmi2 -mavx2 -march=znver2

# それ以外は、AVX512,AVX2,SSE4.2,SSE4.1,SSE2のように利用できるCPU拡張命令で振り分ける。
else ifeq ($(TARGET_CPU),AVX512)
        # skylake     : -DUSE_AVX512 -DUSE_AVX512VLBWDQ -march=skylake-avx512
        # cascadelake : -DUSE_AVX512 -DUSE_AVX512VLBWDQ -DUSE_AVX512VNNI -march=cascadelake
        # icelake     : -DUSE_AVX512 -DUSE_AVX512VLBWDQ -DUSE_AVX512VNNI -DUSE_AVX512VBMI -DUSE_AVX512IFMA -USE_GFNI -march=icelake-client
        CFLAGS += -DUSE_AVX512 -DUSE_AVX512VLBWDQ -march=skylake-avx512

else ifeq ($(TARGET_CPU),AVX2)
        CFLAGS += -DUSE_AVX2 -mbmi -mbmi2 -mavx2 -march=corei7-avx

else ifeq ($(TARGET_CPU),SSE42)
        CFLAGS += -DUSE_SSE42 -msse4.2 -march=corei7

else ifeq ($(TARGET_CPU),SSE41)
        CFLAGS += -DUSE_SSE41 -msse4.1 -march=core2

else ifeq ($(TARGET_CPU),SSE2)
        CFLAGS += -DUSE_SSE2 -msse2 -march=core2

else ifeq ($(TARGET_CPU),NO_SSE)
        # 32bit用。-m32は、MSYS2 MinGW-64だと無視されるので、
        # MinGW-64の32bit環境用でコンパイルする必要がある。
        CFLAGS += -DNO_SSE -m32 -march=pentium3

else ifeq ($(TARGET_CPU),OTHER)
        CFLAGS += -DNO_SSE

endif


CFLAGS += -DUSE_MAKEFILE -D$(YANEURAOU_EDITION)

OBJECTS  = $(addprefix $(OBJDIR)/, $(SOURCES:.cpp=.o))
DEPENDS  = $(OBJECTS:.o=.d)

$(TARGET): $(OBJECTS) $(LIBS)
        $(COMPILER) -o $@ $^ $(LDFLAGS) $(CFLAGS)

myMain.o : myMain.cpp
        $(COMPILER) $(CFLAGS) $(INCLUDE) -o $@ -c $<

myMain : myMain.o $(OBJECTS) $(LIBS) lib$(TARGET).so
        $(COMPILER) -o $@ myMain.o lib$(TARGET).so $(LDFLAGS) $(CFLAGS) && LD_LIBRARY_PATH=. ./$@

lib$(TARGET).so: $(OBJECTS) $(LIBS)
        $(COMPILER) -shared -o $@ $^ $(LDFLAGS) $(CFLAGS)

$(OBJDIR)/%.o: %.cpp
        @[ -d $(dir $@) ] || mkdir -p $(dir $@)
        $(COMPILER) $(CFLAGS) $(INCLUDE) -o $@ -c $<

all: clean $(TARGET)

# https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html


# ビルドターゲット

# 通常使用。
normal:
        $(MAKE) CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LTOFLAGS)' $(TARGET)

# 学習用。openmp , openblasなどを有効にする。
evallearn:
        $(MAKE) CFLAGS='$(CFLAGS) $(OPENMP) $(BLAS)' LDFLAGS='$(LDFLAGS) $(OPENMP_LDFLAGS) $(BLAS_LDFLAGS) $(LTOFLAGS)' $(TARGET)

# トーナメント用
tournament:
        $(MAKE) CFLAGS='$(CFLAGS) -DFOR_TOURNAMENT' LDFLAGS='$(LDFLAGS) $(LTOFLAGS)' $(TARGET)

# トーナメント用lib
tournamentlib:
        $(MAKE) CFLAGS='$(CFLAGS) -DFOR_TOURNAMENT' LDFLAGS='$(LDFLAGS) $(LTOFLAGS)' lib$(TARGET).so

# 教師棋譜生成用
gensfen:
        $(MAKE) CFLAGS='$(CFLAGS) $(OPENMP) $(BLAS) -DGENSFEN2019' LDFLAGS='$(LDFLAGS) $(OPENMP_LDFLAGS) $(BLAS_LDFLAGS) $(LTOFLAGS)' $(TARGET)


# とりあえずPGOはAVX2とSSE4.2専用
prof:
        $(MAKE) CFLAGS='$(CFLAGS) -pg' tournament

profgen:
        $(MAKE) CFLAGS='$(CFLAGS) -fprofile-generate -lgcov' LDFLAGS='$(LDFLAGS) -fprofile-generate -lgcov'

profuse:
        $(MAKE) CFLAGS='$(CFLAGS) -fprofile-use -lgcov' LDFLAGS='$(LDFLAGS) -fprofile-use -lgcov $(LTOFLAGS)'

pgo:
        $(MAKE) profgen
        @./$(TARGET) EvalDir ../build/eval , bench , quit
        @touch $(SOURCES)
        $(MAKE) profuse

clean:
        rm -f $(OBJECTS) $(DEPENDS) $(TARGET) ${OBJECTS:.o=.gcda}

-include $(DEPENDS)

4.4 libYaneuraOu-by-gcc.soの作成

  • -fPIC オプションをつけてコンパイルしなおさないといけないから、以下で一旦コンパイルしたものを消して再度コンパイルしなおす
make clean tournamentlib
  • ソースを消してやるのが上のコマンドだけど、変更してないのをコンパイルしなおさないのは以下
make tournamentlib

4.5 myMain を作成(myMain.cppをmain関数とした実行ファイルの作成)

  • myMainのコンパイルに成功したら、実行される
make myMain
  • 単体で実行するには以下(libYaneuraOu-by-gcc.soをカレントディレクトリに探しにいくように、LD_LIBRARY_PATHの設定が必要になる)
LD_LIBRARY_PATH=. ./myMain

4.6 この章のまとめ

  • 動的ライブラリの作成
  • 昔の動画では、コンパイルコマンドを自作してたけど、今回はMakefileの改造で対応

5 下準備2

5.1 以下の操作を行っている動画


5.2 myMain.cpp の修正

  • USIのループに行かないようにする
  • 評価関数の読み込み処理部分をusi.cppからもってくる(これを行わないと、セグメンテーションエラーになるようになったようだ、数年前はこれなしでいけてた)
//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み


        // 生成して、待機させていたスレッドの停止

        Threads.set(0);

        return 0;
}

5.3 コンパイル実行

make myMain

5.4 この章のまとめ

  • 数年前にアップしてた動画の方法で、現在はダメ
  • 最新のソースで上手く行く方法の一つを紹介

6 Positionクラス(盤面クラス)の初期化と表示

6.1 以下の操作を行っている動画


6.2 myMain.cpp の修正

  • Posionオブジェクトと、必要なオブジェクト生成
  • 平手の盤面設定コード追加
    • 以下の2つの方法ある。どちらでもOK(posはPosionクラスのオブジェクトがはいっている変数)
pos.set_hirate(&states->back(),Threads.main());
pos.set(SFEN_HIRATE,&states->back(),Threads.main());
  • 平手にしたPosionオブジェクトの表示
//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

#include "types.h"
#include "usi.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"

#include <sstream>
#include <queue>

using namespace std;

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み

  Position pos;
  StateListPtr states = StateListPtr(new StateList(1));
  // pos.set_hirate(&states->back(),Threads.main());
  pos.set(SFEN_HIRATE,&states->back(),Threads.main());

  cout << pos << endl;

        // 生成して、待機させていたスレッドの停止

        Threads.set(0);

        return 0;
}

6.3 コンパイル実行

make myMain

6.4 この章のまとめ

  • Postionオブジェクトの生成、盤面設定、表示
  • 評価関数を読み込んでからじゃないと、セグメンテーションエラーとなる

7 ある盤面で可能な手をすべて表示

7.1 以下の操作を行っている動画


7.2 myMain.cpp の修正

//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

#include "types.h"
#include "usi.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"

#include <sstream>
#include <queue>

using namespace std;

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み

  Position pos;
  StateListPtr states = StateListPtr(new StateList(1));
  // pos.set_hirate(&states->back(),Threads.main());
  pos.set(SFEN_HIRATE,&states->back(),Threads.main());

  cout << pos << endl;

  //可能な手を全て表示 
  MoveList< LEGAL_ALL > ml(pos);
  cout << "ml.size()=" << ml.size() << endl;
  for(auto m : ml) {
    //cout << m.move << endl;
    cout << m << endl;
  }

        // 生成して、待機させていたスレッドの停止
        Threads.set(0);

        return 0;
}

7.3 コンパイル実行

make myMain

7.4 この章のまとめ

  • ある盤面で可能な手をすべて表示

8 現状の盤面の評価値表示

8.1 以下の操作を行っている動画


8.2 myMain.cpp の修正

//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

#include "types.h"
#include "usi.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"

#include <sstream>
#include <queue>

using namespace std;

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み

  Position pos;
  StateListPtr states = StateListPtr(new StateList(1));
  // pos.set_hirate(&states->back(),Threads.main());
  pos.set(SFEN_HIRATE,&states->back(),Threads.main());

  cout << pos << endl;

  //可能な手を全て表示 
  MoveList< LEGAL_ALL > ml(pos);
  cout << "ml.size()=" << ml.size() << endl;
  for(auto m : ml) {
    //cout << m.move << endl;
    cout << m << endl;
  }

  //現状の盤面の評価値を表示
  cout << "eval=" <<  Eval::compute_eval(pos) << endl;
  Eval::print_eval_stat(pos);

        // 生成して、待機させていたスレッドの停止
        Threads.set(0);

        return 0;
}

8.3 コンパイル実行

make myMain

8.4 この章のまとめ

  • 現状の盤面の評価値表示

9 高速1手詰め探索ルーチン利用

9.1 以下の操作を行っている動画


9.2 myMain.cpp の修正

//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

#include "types.h"
#include "usi.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"

#include <sstream>
#include <queue>

using namespace std;

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み

  Position pos;
  StateListPtr states = StateListPtr(new StateList(1));
  // pos.set_hirate(&states->back(),Threads.main());
  pos.set(SFEN_HIRATE,&states->back(),Threads.main());

  cout << pos << endl;
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;

  //可能な手を全て表示 
  MoveList< LEGAL_ALL > ml(pos);
  cout << "ml.size()=" << ml.size() << endl;
  for(auto m : ml) {
    //cout << m.move << endl;
    cout << m << endl;
  }

  //現状の盤面の評価値を表示
  cout << "eval=" <<  Eval::compute_eval(pos) << endl;
  Eval::print_eval_stat(pos);

  //世界一早い1手づめチェックルーチン
  // lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L[N] w 0 1
  pos.set("lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L b N 1",&states->back(),Threads.main());

  cout << pos << endl;
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;

        // 生成して、待機させていたスレッドの停止
        Threads.set(0);

        return 0;
}

9.3 コンパイル実行

make myMain

9.4 この章のまとめ

  • 高速1手詰め探索ルーチン利用

10 詰みチェック

10.1 以下の操作を行っている動画


10.2 myMain.cpp の修正

  • Positionオブジェクトのis_mated() メソッドで行える
//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

#include "types.h"
#include "usi.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"

#include <sstream>
#include <queue>

using namespace std;

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み

  Position pos;
  StateListPtr states = StateListPtr(new StateList(1));
  // pos.set_hirate(&states->back(),Threads.main());
  pos.set(SFEN_HIRATE,&states->back(),Threads.main());

  cout << pos << endl;
  // 高速一手詰みチェックルーチン
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;
  // 詰みか表示
  cout << "pos.is_mated()=" << pos.is_mated() << endl;

  //可能な手を全て表示 
  MoveList< LEGAL_ALL > ml(pos);
  cout << "ml.size()=" << ml.size() << endl;
  for(auto m : ml) {
    //cout << m.move << endl;
    cout << m << endl;
  }

  //現状の盤面の評価値を表示
  cout << "eval=" <<  Eval::compute_eval(pos) << endl;
  Eval::print_eval_stat(pos);

  //世界一早い1手づめチェックルーチン
  // lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L[N] w 0 1
  pos.set("lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L b N 1",&states->back(),Threads.main());

  cout << pos << endl;
  // 高速一手詰みチェックルーチン
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;
  // 詰みか表示
  cout << "pos.is_mated()=" << pos.is_mated() << endl;

        // 生成して、待機させていたスレッドの停止
        Threads.set(0);

        return 0;
}

10.3 コンパイル実行

make myMain

10.4 この章のまとめ

  • 詰みチェック

11 指定の一手を行う

11.1 以下の操作を行っている動画


11.2 myMain.cpp の修正

  • Positionオブジェクトのdo_move() メソッドで行える
//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

#include "types.h"
#include "usi.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"

#include <sstream>
#include <queue>

using namespace std;

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み

  Position pos;
  StateListPtr states = StateListPtr(new StateList(1));
  // pos.set_hirate(&states->back(),Threads.main());
  pos.set(SFEN_HIRATE,&states->back(),Threads.main());

  cout << pos << endl;
  // 高速一手詰みチェックルーチン
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;
  // 詰みか表示
  cout << "pos.is_mated()=" << pos.is_mated() << endl;

  //可能な手を全て表示 
  MoveList< LEGAL_ALL > ml(pos);
  cout << "ml.size()=" << ml.size() << endl;
  for(auto m : ml) {
    //cout << m.move << endl;
    cout << m << endl;
  }

  //現状の盤面の評価値を表示
  cout << "eval=" <<  Eval::compute_eval(pos) << endl;
  Eval::print_eval_stat(pos);

  //世界一早い1手づめチェックルーチン
  // lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L[N] w 0 1
  pos.set("lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L b N 1",&states->back(),Threads.main());

  cout << pos << endl;
  //可能な手を全て表示 (LEGAL_ALL ではなく、 LEGALタイプ)
  MoveList< LEGAL > ml2(pos);
  cout << "ml.size()=" << ml2.size() << endl;
  for(auto m : ml2) {
    //cout << m.move << endl;
    cout << m << endl;
  }
  // 高速一手詰みチェックルーチン
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;
  // 詰みか表示
  cout << "pos.is_mated()=" << pos.is_mated() << endl;
  Move m=pos.mate1ply();
  // 上位bitに駒種を入れておかないとpseudo_legal()で引っかかる。
  //これやっとなかないと、MoveList<LEGAL>(pos).contains(m) で正しいのがかえってこない
  m = pos.move16_to_move(m); 

  cout << "m=" << m << endl;
  cout << "MoveList<LEGAL>(pos).contains(m)=" << MoveList<LEGAL>(pos).contains(m) << endl;
  if (MoveList<LEGAL>(pos).contains(m)) {
    // 1手進めるごとにStateInfoが積まれていく。これは千日手の検出のために必要。
    states->emplace_back();
    if (m == MOVE_NULL) // do_move に MOVE_NULL を与えると死ぬので
    {
      cout << "MOVE_NULL " << m << endl;
      pos.do_null_move(states->back());
    }
    else
    {
      cout << "not MOVE_NULL " << m << endl;
      pos.do_move(m, states->back());
    }
    cout << pos << endl;
    cout << "pos.is_mated()=" << pos.is_mated() << endl;
  }

  Move mymove = USI::to_move("7f7g");

  cout << mymove << endl;

        // 生成して、待機させていたスレッドの停止
        Threads.set(0);

        return 0;
}

/*
  // 指し手のリストをパースする(あるなら)
  while (is >> token && (m = USI::to_move(pos, token)) != MOVE_NONE)
  {
    // 1手進めるごとにStateInfoが積まれていく。これは千日手の検出のために必要。
    states->emplace_back();
    if (m == MOVE_NULL) // do_move に MOVE_NULL を与えると死ぬので
      pos.do_null_move(states->back());
    else
      pos.do_move(m, states->back());
  }

Move USI::to_move(const Position& pos, const std::string& str)
{
  // 全合法手のなかからusi文字列に変換したときにstrと一致する指し手を探してそれを返す
  //for (const ExtMove& ms : MoveList<LEGAL_ALL>(pos))
  //  if (str == move_to_usi(ms.move))
  //    return ms.move;

  // ↑のコードは大変美しいコードではあるが、棋譜を大量に読み込むときに時間がかかるうるのでもっと高速な実装をする。

  if (str == "resign")
    return MOVE_RESIGN;

  if (str == "win")
    return MOVE_WIN;

  // パス(null move)入力への対応 {UCI: "0000", GPSfish: "pass"}
  if (str == "0000" || str == "null" || str == "pass")
    return MOVE_NULL;

  // usi文字列を高速にmoveに変換するやつがいるがな..
  Move move = USI::to_move(str);

  // 上位bitに駒種を入れておかないとpseudo_legal()で引っかかる。
  move = pos.move16_to_move(move);

#if defined(MUST_CAPTURE_SHOGI_ENGINE)
  // 取る一手将棋は合法手かどうかをGUI側でチェックしてくれないから、
  // 合法手かどうかのチェックを入れる。
  if (!MoveList<LEGAL>(pos).contains(move))
    sync_cout << "info string Error!! Illegal Move = " << move << sync_endl;
#endif

  if (pos.pseudo_legal(move) && pos.legal(move))
    return move;

  // いかなる状況であろうとこのような指し手はエラー表示をして弾いていいと思うが…。
  // cout << "\nIlligal Move : " << str << "\n";

  return MOVE_NONE;
}



*/

11.3 コンパイル実行

make myMain

11.4 この章のまとめ

  • 指定の一手を行う

12 指定の一手を行った後、その手の取り消し

12.1 以下の操作を行っている動画


12.2 myMain.cpp の修正

  • Positionオブジェクトのundo_move() メソッドで行える
//#include <iostream>
//#include "bitboard.h"
//#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"
#include "usi.h"
#include "misc.h"

#include "types.h"
#include "usi.h"
#include "position.h"
#include "search.h"
#include "thread.h"
#include "tt.h"

#include <sstream>
#include <queue>

using namespace std;

// ----------------------------------------
//  main()
// ----------------------------------------

int main(int argc, char* argv[])
{
        // --- 全体的な初期化

        Misc::init(argv);
        USI::init(Options);
        Bitboards::init();
        Position::init();
        Search::init();
        Threads.set(Options["Threads"]);
        //Search::clear();
        Eval::init();

        // USIコマンドの応答部

        //USI::loop(argc, argv);


  // ************* 評価関数の読み込み
  Eval::load_eval();

  // チェックサムの計算と保存(その後のメモリ破損のチェックのため)
  u64 eval_sum;
  eval_sum = Eval::calc_check_sum();

  // ソフト名の表示
  Eval::print_softname(eval_sum);

  USI::load_eval_finished = true;
  // ************* 評価関数の読み込み

  Position pos;
  StateListPtr states = StateListPtr(new StateList(1));
  // pos.set_hirate(&states->back(),Threads.main());
  pos.set(SFEN_HIRATE,&states->back(),Threads.main());

  cout << pos << endl;
  // 高速一手詰みチェックルーチン
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;
  // 詰みか表示
  cout << "pos.is_mated()=" << pos.is_mated() << endl;

  //可能な手を全て表示 
  MoveList< LEGAL_ALL > ml(pos);
  cout << "ml.size()=" << ml.size() << endl;
  for(auto m : ml) {
    //cout << m.move << endl;
    cout << m << endl;
  }

  //現状の盤面の評価値を表示
  cout << "eval=" <<  Eval::compute_eval(pos) << endl;
  Eval::print_eval_stat(pos);

  //世界一早い1手づめチェックルーチン
  // lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L[N] w 0 1
  pos.set("lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L b N 1",&states->back(),Threads.main());

  cout << pos << endl;
  //可能な手を全て表示 (LEGAL_ALL ではなく、 LEGALタイプ)
  MoveList< LEGAL > ml2(pos);
  cout << "ml.size()=" << ml2.size() << endl;
  for(auto m : ml2) {
    //cout << m.move << endl;
    cout << m << endl;
  }
  // 高速一手詰みチェックルーチン
  cout << "pos.mate1ply()=" << pos.mate1ply() << endl;
  // 詰みか表示
  cout << "pos.is_mated()=" << pos.is_mated() << endl;
  Move m=pos.mate1ply();
  // 上位bitに駒種を入れておかないとpseudo_legal()で引っかかる。
  //これやっとなかないと、MoveList<LEGAL>(pos).contains(m) で正しいのがかえってこない
  m = pos.move16_to_move(m); 

  cout << "m=" << m << endl;
  cout << "MoveList<LEGAL>(pos).contains(m)=" << MoveList<LEGAL>(pos).contains(m) << endl;
  if (MoveList<LEGAL>(pos).contains(m)) {
    // 1手進めるごとにStateInfoが積まれていく。これは千日手の検出のために必要。
    states->emplace_back();
    if (m == MOVE_NULL) // do_move に MOVE_NULL を与えると死ぬので
    {
      cout << "MOVE_NULL " << m << endl;
      pos.do_null_move(states->back());
    }
    else
    {
      cout << "not MOVE_NULL " << m << endl;
      pos.do_move(m, states->back());
    }
    cout << pos << endl;
    cout << "pos.is_mated()=" << pos.is_mated() << endl;
    // cout << "pos.lastMove=" << pos.lastMove  << endl; // ERROR

    // undo_move してみる
    pos.undo_move(m);
    cout << pos << endl;
    cout << "pos.is_mated()=" << pos.is_mated() << endl;
  }

  Move mymove = USI::to_move("7f7g");

  cout << mymove << endl;

        // 生成して、待機させていたスレッドの停止
        Threads.set(0);

        return 0;
}

/*
  // 指し手のリストをパースする(あるなら)
  while (is >> token && (m = USI::to_move(pos, token)) != MOVE_NONE)
  {
    // 1手進めるごとにStateInfoが積まれていく。これは千日手の検出のために必要。
    states->emplace_back();
    if (m == MOVE_NULL) // do_move に MOVE_NULL を与えると死ぬので
      pos.do_null_move(states->back());
    else
      pos.do_move(m, states->back());
  }

Move USI::to_move(const Position& pos, const std::string& str)
{
  // 全合法手のなかからusi文字列に変換したときにstrと一致する指し手を探してそれを返す
  //for (const ExtMove& ms : MoveList<LEGAL_ALL>(pos))
  //  if (str == move_to_usi(ms.move))
  //    return ms.move;

  // ↑のコードは大変美しいコードではあるが、棋譜を大量に読み込むときに時間がかかるうるのでもっと高速な実装をする。

  if (str == "resign")
    return MOVE_RESIGN;

  if (str == "win")
    return MOVE_WIN;

  // パス(null move)入力への対応 {UCI: "0000", GPSfish: "pass"}
  if (str == "0000" || str == "null" || str == "pass")
    return MOVE_NULL;

  // usi文字列を高速にmoveに変換するやつがいるがな..
  Move move = USI::to_move(str);

  // 上位bitに駒種を入れておかないとpseudo_legal()で引っかかる。
  move = pos.move16_to_move(move);

#if defined(MUST_CAPTURE_SHOGI_ENGINE)
  // 取る一手将棋は合法手かどうかをGUI側でチェックしてくれないから、
  // 合法手かどうかのチェックを入れる。
  if (!MoveList<LEGAL>(pos).contains(move))
    sync_cout << "info string Error!! Illegal Move = " << move << sync_endl;
#endif

  if (pos.pseudo_legal(move) && pos.legal(move))
    return move;

  // いかなる状況であろうとこのような指し手はエラー表示をして弾いていいと思うが…。
  // cout << "\nIlligal Move : " << str << "\n";

  return MOVE_NONE;
}



*/

12.3 コンパイル実行

make myMain

12.4 この章のまとめ

  • 指定の一手を行った後、その手の取り消し

13 Python+cppyyを利用して、PythonからYaneuraouのライブラリの直接利用

  • CERNのROOTをいれて数ヶ月前にトライしたが、ヘッダーファイルにC++の新しい規格が使われていて、ROOTでサポートされておらずエラー多発。ソース変更が面倒なので放置
  • PythonにcppyyというCERNのROOTの技術を利用したC++やCの外部ライブラリを利用できるパッケージがあることを知り、試してみたら上手くいった。
    • CERNのROOTで何故上手くいかず、こちらで上手くいったのか、原因は調べてない。(よくわかんない)
  • 関連動画

13.1 以下の操作を行っている動画


13.2 実際の手順

  • 以下のソースを実行すると、盤面を平手に設定して、盤面が表示される
  • 平手の設定をPython側から行おうとしたが、書き方がわからず、cppyy.cppdefを利用して実現した(書き方わかる方はコメント欄で教えてください)
    • 失敗した命令はコメントアウトして残してあります。
import cppyy                                                                                                                                  
from array import array

cppyy.include("search.h")                                                                                                                     
cppyy.include("thread.h")                                                                                                                     
cppyy.include("tt.h")                                                                                                                         
cppyy.include("usi.h")                                                                                                                        
cppyy.include("misc.h")                                                                                                                       
cppyy.include("iostream")                                                                                                                       

cppyy.load_library("./libYaneuraOu-by-gcc.so")      

cppyy.cppdef('char* argv[]={{}};')
cppyy.cppdef('unsigned long tmp01=Options["Threads"];')

cppyy.gbl.Misc.init(cppyy.gbl.argv)
cppyy.gbl.USI.init(cppyy.gbl.Options)
cppyy.gbl.Bitboards.init()
cppyy.gbl.Position.init()
cppyy.gbl.Search.init();
cppyy.gbl.Threads.set(4)
cppyy.gbl.Eval.init()
cppyy.gbl.Eval.load_eval();

cppyy.cppdef('StateListPtr create_states() { return StateListPtr(new StateList(1));};')
cppyy.cppdef('void setMyPosition(Position& pos, std::string sfen, StateListPtr states) { pos.set(sfen,&states->back(),Threads.main()); }; ')
cppyy.cppdef('void myPrintPosition(Position& pos) { std::cout << pos << std::endl; };')

pos=cppyy.gbl.Position()
states=cppyy.gbl.create_states()
print("cppyy.gbl.Threads.size()")
print(cppyy.gbl.Threads.size())
print(pos.sfen())
cppyy.gbl.setMyPosition(pos,cppyy.gbl.SFEN_HIRATE,states)
#pos.set(cppyy.gbl.SFEN_HIRATE,cppyy.addressof(states.back()),cppyy.gbl.Threads.main()) #ERR
#pos.set(cppyy.gbl.SFEN_HIRATE,states.back(),cppyy.gbl.Threads.main()) #Error
cppyy.gbl.myPrintPosition(pos)

13.3 この章のまとめ

  • Python+cppyyを利用することで、インタプリタ環境から、Yaneuraouさんの将棋ライブラリを利用することが可能になった
    • 何故かCERNのROOTでも数ヶ月前に試したがダメだった
      • ヘッダーの読み込みで新しいC++の規格が利用できないというエラーが発生
      • 修正が面倒で放置
    • 何の修正もなく利用可能に
      • 試行錯誤が非常にやりやすくなった
      • 一部cppyyで書き方がわからないものは、cppyy.cppdefで定義した関数を利用して、動作できるものを作成した
      • cppyy.cppdefを利用せずとも、平手に設定出来る方法わかるかたはコメントして教えて下さい

14 最新ソースをダウンロード(2020/11/19)して、トーナメント用、詰将棋用のエンジンコンパイル、それらのライブラリコンパイル用のスクリプトについて の章を作成

  • 2020/07頃の動画や、文書(上の方の章)での手順では、現在(2020/11/19)では上手くいかなくなっていた(ライブラリのコンパイル)
  • 関連動画

14.2 以下の操作を行っている動画


14.3 2020/11/19で、最新のYaneuraOuさんの将棋エンジン、詰将棋エンジン、tanukiさんの詰将棋エンジン、それらのライブラリ作成するスクリプトについて

14.3.1 ソースダウンロードして、コンパイルするスクリプトファイルの作成

  • get というファイルを以下の内容で作成
  • CPUがSSSE42以外を希望する場合は、以下のどれか希望の物にSSR42という文字列を全部置き換える(文字列置換を一括で行えるエディタを利用すると便利)
    • AVX512VNNI
    • AVX512
    • AVX2
    • SSE42
    • SSE41
    • SSSE3
    • SSE2
    • NO_SSE
    • OTHER
    • ZEN1
    • ZEN2
  • 使えるCPUの確認は、 cat /proc/cpuinfo | grep -i sse や cat /proc/cpuinfo | grep -i avx 等で確認可能(Ubuntu等、Linuxマシンの場合)
  • 使えるCPUの種類の確認方法の解説動画は[[]]等があります(Ubuntuで行った動画,他のLinuxでも同じ手順で多分いける)
#!/bin/bash
D=`date +%Y%m%d`
DT=`date +%Y%m%d_%H%M`
mkdir ${DT}
cd ${DT}
git clone https://github.com/yaneurao/YaneuraOu.git
#tar cvzf YaneuraOu_${DT}_000.tgz YaneuraOu/
#(cd YaneuraOu/ ;git checkout 9bbd0f38498b22e9f3e6cf9493a7f8849c02e496)
tar cvzf YaneuraOu_${DT}.tgz YaneuraOu/
git clone https://github.com/nodchip/tanuki-.git
#tar cvzf tanuki-_${DT}_000.tgz tanuki-
#(cd tanuki-/ ;git checkout 258d55331385a9e594ed8e624409ea3bfdd53602)
tar cvzf tanuki-_${DT}.tgz tanuki-
(cd YaneuraOu/source && make clean tournament TARGET_CPU=SSE42) 2>&1 | tee ./log001.txt
tar cvzf YaneuraOu_${DT}_build.tgz YaneuraOu/
(
mkdir MATE2LIB
cd MATE2LIB
tar xvzf ../tanuki-_${DT}.tgz 
(cd tanuki-/source && patch -p2 < ../../../../06makefile_DEBUG_lib_tanuki.patch && make clean tournamentlib TARGET_CPU=SSE42 YANEURAOU_EDITION=MATE_ENGINE ) 2>&1 | tee ./log010.txt
)
(
mkdir MATELIB
cd MATELIB
tar xvzf ../YaneuraOu_${DT}.tgz
(cd YaneuraOu/source && patch -p2 < ../../../../06makefile_DEBUG_lib.patch && make clean tournamentlib TARGET_CPU=SSE42 YANEURAOU_EDITION=MATE_ENGINE ) 2>&1 | tee ./log010.txt
)
# cp main.cpp myMain.cpp
# make myMain TARGET_CPU=SSE42 YANEURAOU_EDITION=MATE_ENGINE
# LD_LIBRARY_PATH=. ./myMain 
(
mkdir MATE2
cd MATE2
tar xvzf ../tanuki-_${DT}.tgz 
(cd tanuki-/source/ && make clean tournament TARGET_CPU=SSE42 YANEURAOU_EDITION=MATE_ENGINE ) 2>&1 | tee ./log004.txt
)
(
mkdir LEARN
cd LEARN
tar xvzf ../YaneuraOu_${DT}.tgz
(cd YaneuraOu/source && make clean evallearn TARGET_CPU=SSE42) 2>&1 | tee ./log002.txt
)
(
mkdir MATE
cd MATE
tar xvzf ../YaneuraOu_${DT}.tgz
(cd YaneuraOu/source && make clean tournament TARGET_CPU=SSE42 YANEURAOU_EDITION=MATE_ENGINE ) 2>&1 | tee ./log003.txt
)
(
mkdir TOURNAMENTLIB
cd TOURNAMENTLIB
tar xvzf ../YaneuraOu_${DT}.tgz
(cd YaneuraOu/source && patch -p2 < ../../../../06makefile_DEBUG_lib.patch && make clean tournamentlib TARGET_CPU=SSE42 ) 2>&1 | tee ./log011.txt
)
# cp main.cpp myMain.cpp
# make myMain TARGET_CPU=SSE42 
# LD_LIBRARY_PATH=. ./myMain 

14.3.2 作ったスクリプトに実行権限を与える

chmod +x get

14.3.3 上のスクリプトで利用するバッチファイルの生成

  1. 06makefile_DEBUG_lib.patch
    • 以下のテキストはbase64でエンコードしてあるので、デコードして 06makefile_DEBUG_lib.patch というファイル名で保存
    LS0tIFlhbmV1cmFPdS5vcmcvc291cmNlL01ha2VmaWxlCTIwMjAtMTEtMTkgMDg6MzY6MzUuMDAw
    MDAwMDAwICswOTAwCisrKyBZYW5ldXJhT3Uvc291cmNlL01ha2VmaWxlCTIwMjAtMTEtMTkgMDg6
    NDc6NDcuMzkyOTU1OTMyICswOTAwCkBAIC01Niw4ICs1Niw4IEBAIFRBUkdFVF9DUFUgPSBBVlgy
    CiAKIAogIyDjg4fjg5Djg4Pjgqzjg7zjgpLkvb/nlKjjgZnjgovjgYsgKGRlYnVnZ2VyKQotREVC
    VUcgPSBPRkYKLSNERUJVRyA9IE9OCisjIERFQlVHID0gT0ZGCitERUJVRyA9IE9OCiAKIAogIyDk
    vb/nlKjjgZnjgovjgrPjg7Pjg5HjgqTjg6kgKGNvbXBpbGVyKQpAQCAtMTUzLDcgKzE1Myw4IEBA
    IExERkxBR1MgKz0gLVdsLC1zCiAjIENQUEZMQUdTICAgKz0gLW1hcmNoPW5hdGl2ZQogCiAjIOOD
    h+ODkOODg+OCsOaDheWgseOCkuS7mOWKoAotIyBDUFBGTEFHUyAgKz0gLWczIC1nZ2RiCitDUFBG
    TEFHUyAgKz0gLWczIC1nZ2RiCitDUFBGTEFHUyAgKz0gLWZQSUMKIAogIyBPcGVuTVDjgpLkvb/j
    gYbjgajjgY3jgatDUFBGTEFHU+OBqOOBl+OBpuaMh+WumuOBmeOCi+OCquODl+OCt+ODp+ODswog
    IyDigLsg5a2m57+S6YOo44Gn44GvT3Blbk1w44KS55So44GE44KL44Gu44Gn44CB5a2m57+S55So
    44Gu44OT44Or44OJ44Gn44Gv44GT44Gu44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44CC
    CkBAIC0yMDIsOCArMjAzLDkgQEAgaWZlcSAiJChzdHJpcCAkKE9CSkRJUikpIiAiIgogZW5kaWYK
    IAogI1NPVVJDRVMgID0gJCh3aWxkY2FyZCAqLmNwcCkKKyMJbWFpbi5jcHAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAor
    IwogU09VUkNFUyAgPSBcCi0JbWFpbi5jcHAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogCXR5cGVzLmNwcCAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    IFwKIAliaXRib2FyZC5jcHAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICBcCiAJbWlzYy5jcHAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXApAQCAtMzg4LDYg
    KzM5MCwxNSBAQCBhbGw6IGNsZWFuICQoVEFSR0VUKQogJChUQVJHRVQpOiAkKE9CSkVDVFMpICQo
    TElCUykKIAkkKENPTVBJTEVSKSAtbyAkQCAkXiAkKExERkxBR1MpICQoQ1BQRkxBR1MpCiAKK215
    TWFpbi5vIDogbXlNYWluLmNwcAorCSQoQ09NUElMRVIpICQoQ1BQRkxBR1MpICQoSU5DTFVERSkg
    LW8gJEAgLWMgJDwKKworbXlNYWluIDogbXlNYWluLm8gJChMSUJTKSBsaWIkKFRBUkdFVCkuc28K
    KwkkKENPTVBJTEVSKSAtbyAkQCBteU1haW4ubyBsaWIkKFRBUkdFVCkuc28gJChMREZMQUdTKSAk
    KENQUEZMQUdTKQorCitsaWIkKFRBUkdFVCkuc286ICQoT0JKRUNUUykgJChMSUJTKQorCSQoQ09N
    UElMRVIpIC1zaGFyZWQgLW8gJEAgJF4gJChMREZMQUdTKSAkKENQUEZMQUdTKQorCiAkKE9CSkRJ
    UikvJS5vOiAlLmNwcAogCUBbIC1kICQoZGlyICRAKSBdIHx8IG1rZGlyIC1wICQoZGlyICRAKQog
    CSQoQ09NUElMRVIpICQoQ1BQRkxBR1MpICQoSU5DTFVERSkgLW8gJEAgLWMgJDwKQEAgLTQwOSw2
    ICs0MjAsMTAgQEAgZXZhbGxlYXJuOgogdG91cm5hbWVudDoKIAkkKE1BS0UpIENQUEZMQUdTPSck
    KENQUEZMQUdTKSAtREZPUl9UT1VSTkFNRU5UJyBMREZMQUdTPSckKExERkxBR1MpICQoTFRPRkxB
    R1MpJyAkKFRBUkdFVCkKIAorIyDjg4jjg7zjg4rjg6Hjg7Pjg4jnlKhsaWIKK3RvdXJuYW1lbnRs
    aWI6CisJJChNQUtFKSBDUFBGTEFHUz0nJChDUFBGTEFHUykgLURGT1JfVE9VUk5BTUVOVCcgTERG
    TEFHUz0nJChMREZMQUdTKSAkKExUT0ZMQUdTKScgbGliJChUQVJHRVQpLnNvCisKICMg5pWZ5bir
    5qOL6K2c55Sf5oiQ55SoKOmWi+eZuueUqOOBquOBruOBp+mdnuWFrOmWiykgLy8gY3VycmVudGx5
    IHByaXZhdGUKIGdlbnNmZW46CiAJJChNQUtFKSBDUFBGTEFHUz0nJChDUFBGTEFHUykgJChPUEVO
    TVApICQoQkxBUykgLURFVkFMX0xFQVJOIC1ER0VOU0ZFTjIwMTknIExERkxBR1M9JyQoTERGTEFH
    UykgJChPUEVOTVBfTERGTEFHUykgJChCTEFTX0xERkxBR1MpICQoTFRPRkxBR1MpJyAkKFRBUkdF
    VCkK
    
    • 上の内容を 06makefile_DEBUG_lib.patch.base64というファイルに保存して、それをデコードする場合は以下のコマンドでデコード可能
    cat 06makefile_DEBUG_lib.patch.base64 | base64 -d > 06makefile_DEBUG_lib.patch
    
  2. 06makefile_DEBUG_lib_tanuki.patch
    • 以下のテキストはbase64でエンコードしてあるので、デコードして 06makefile_DEBUG_lib_tanuki.patch というファイル名で保存
    • tanukiのMakefileが現在のYanauraOuさんの最新のMakefileと異る為、別ファイルを作成する必要がありました。tanukiのMakefileがYaneuraOuさんの最新Makefileに追いついたら、 06makefile_DEBUG_lib_tanuki.patchは前の 06makefile_DEBUG_lib.patch と同じ内容でいけるはず
    LS0tIHRhbnVraS0ub3JnL3NvdXJjZS9NYWtlZmlsZQkyMDIwLTExLTE5IDA5OjQwOjQxLjU5NzM5
    Njg0OSArMDkwMAorKysgdGFudWtpLS9zb3VyY2UvTWFrZWZpbGUJMjAyMC0xMS0xOSAwOTo0Njow
    Ny4yNTE4OTU5NzcgKzA5MDAKQEAgLTQxLDggKzQxLDggQEAgVEFSR0VUX0NQVSA9IEFWWDIKIAog
    CiAjIOODh+ODkOODg+OCrOODvOOCkuS9v+eUqOOBmeOCi+OBiwotREVCVUcgPSBPRkYKLSNERUJV
    RyA9IE9OCisjREVCVUcgPSBPRkYKK0RFQlVHID0gT04KIAogCiAjIGNsYW5n44Gn44Kz44Oz44OR
    44Kk44Or44GX44Gf44G744GG44GMZ2Nj44KI44KK5pWwJemAn+OBhOOBo+OBveOBhOOAggpAQCAt
    MTIyLDYgKzEyMiw5IEBAIExERkxBR1MgKz0gLVdsLC1zCiAKICMg44OH44OQ44OD44Kw5oOF5aCx
    44KS5LuY5YqgCiAjIENGTEFHUyAgKz0gLWczIC1nZ2RiCitDRkxBR1MgICs9IC1nMyAtZ2dkYgor
    Q0ZMQUdTICArPSAtZlBJQworCiAKICMgT3Blbk1Q44KS5L2/44GG44Go44GN44GrQ0ZMQUdT44Go
    44GX44Gm5oyH5a6a44GZ44KL44Kq44OX44K344On44OzCiAjIOKAuyDlrabnv5Lpg6jjgafjga9P
    cGVuTXDjgpLnlKjjgYTjgovjga7jgafjgIHlrabnv5LnlKjjga7jg5Pjg6vjg4njgafjga/jgZPj
    ga7jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgIIKQEAgLTE3NSw4ICsxNzgsOSBAQCBp
    ZmVxICIkKHN0cmlwICQoT0JKRElSKSkiICIiCiBlbmRpZgogCiAjU09VUkNFUyAgPSAkKHdpbGRj
    YXJkICouY3BwKQorIwltYWluLmNwcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCisjCiBTT1VSQ0VTICA9IFwKLQltYWlu
    LmNwcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICBcCiAJdHlwZXMuY3BwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogCWJpdGJvYXJkLmNwcCAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    IFwKIAltaXNjLmNwcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgICAgICAgICAgICAgICAgICAgICBcCkBAIC0zMTYsNiArMzIwLDE4IEBAIERFUEVORFMgID0g
    JChPQkpFQ1RTOi5vPS5kKQogJChUQVJHRVQpOiAkKE9CSkVDVFMpICQoTElCUykKIAkkKENPTVBJ
    TEVSKSAtbyAkQCAkXiAkKExERkxBR1MpICQoQ0ZMQUdTKQogCitsaWIkKFRBUkdFVCkuc286ICQo
    T0JKRUNUUykgJChMSUJTKQorCSQoQ09NUElMRVIpIC1zaGFyZWQgLW8gJEAgJF4gJChMREZMQUdT
    KSAkKENGTEFHUykKKworbXlNYWluLm8gOiBteU1haW4uY3BwCisJJChDT01QSUxFUikgJChDRkxB
    R1MpICQoSU5DTFVERSkgLW8gJEAgLWMgJDwKKworbXlNYWluIDogbXlNYWluLm8gJChMSUJTKSBs
    aWIkKFRBUkdFVCkuc28KKwkkKENPTVBJTEVSKSAtbyAkQCBteU1haW4ubyBsaWIkKFRBUkdFVCku
    c28gJChMREZMQUdTKSAkKENGTEFHUykKKworbGliJChUQVJHRVQpLnNvOiAkKE9CSkVDVFMpICQo
    TElCUykKKwkkKENPTVBJTEVSKSAtc2hhcmVkIC1vICRAICReICQoTERGTEFHUykgJChDRkxBR1Mp
    CisKICQoT0JKRElSKS8lLm86ICUuY3BwCiAJQFsgLWQgJChkaXIgJEApIF0gfHwgbWtkaXIgLXAg
    JChkaXIgJEApCiAJJChDT01QSUxFUikgJChDRkxBR1MpICQoSU5DTFVERSkgLW8gJEAgLWMgJDwK
    QEAgLTMzOSw2ICszNTUsMTAgQEAgZXZhbGxlYXJuOgogdG91cm5hbWVudDoKIAkkKE1BS0UpIENG
    TEFHUz0nJChDRkxBR1MpIC1ERk9SX1RPVVJOQU1FTlQnIExERkxBR1M9JyQoTERGTEFHUykgJChM
    VE9GTEFHUyknICQoVEFSR0VUKQogCisjIOODiOODvOODiuODoeODs+ODiOeUqGxpYgordG91cm5h
    bWVudGxpYjoKKwkkKE1BS0UpIENGTEFHUz0nJChDRkxBR1MpIC1ERk9SX1RPVVJOQU1FTlQnIExE
    RkxBR1M9JyQoTERGTEFHUykgJChMVE9GTEFHUyknIGxpYiQoVEFSR0VUKS5zbworCiAjIOaVmeW4
    q+aji+itnOeUn+aIkOeUqAogZ2Vuc2ZlbjoKIAkkKE1BS0UpIENGTEFHUz0nJChDRkxBR1MpICQo
    T1BFTk1QKSAkKEJMQVMpIC1ER0VOU0ZFTjIwMTknIExERkxBR1M9JyQoTERGTEFHUykgJChPUEVO
    TVBfTERGTEFHUykgJChCTEFTX0xERkxBR1MpICQoTFRPRkxBR1MpJyAkKFRBUkdFVCkK
    
    • 上の内容を 06makefile_DEBUG_lib_tanuki.patch.base64というファイルに保存して、それをデコードする場合は以下のコマンドでデコード可能
    cat 06makefile_DEBUG_lib_tanuki.patch.base64 | base64 -d > 06makefile_DEBUG_lib_tanuki.patch
    

14.3.4 作ったスクリプトを実行

  • 以下のコマンドでソースゲット、色々コンパイルしてくれる
  • 変化が激しい為、今後修正しないと動かなくなる可能性あり
    • 動作確認した時のgitのバージョンは YaneuraOuが 9bbd0f38498b22e9f3e6cf9493a7f8849c02e496
      • Mon Nov 16 03:16:47 2020 +0900
    • 動作確認した時のgitのバージョンは tanuki が 258d55331385a9e594ed8e624409ea3bfdd53602
      • Tue May 5 00:32:13 2020 +0900
  • コンパイル出来ない時は、git checkout xxxx (xxxはバージョン)として、過去のソースにすることで、コンパイル可能に
    • get の以下の行のコメントを外すと(先頭の#をはずず)、指定のバージョンのソースでコンパイル
      • #tar cvzf YaneuraOu_${DT}_000.tgz YaneuraOu/
      • #(cd YaneuraOu/ ;git checkout 9bbd0f38498b22e9f3e6cf9493a7f8849c02e496)
      • #tar cvzf tanuki-_${DT}_000.tgz tanuki-
      • #(cd tanuki-/ ;git checkout 258d55331385a9e594ed8e624409ea3bfdd53602)
./get
  • 20201119_2000 のような、年月日、時間、分の名前のディレクトリが作成され、その中に、githubからソースをダウンロードしてコンパイルが実行される
    • YaneuraOu/source に通常のものがコンパイルされる YaneuraOu-by-gcc
    • TOURNAMENTLIB/YaneuraOu/source に上のライブラリバージョンが作成される libYaneuraOu-by-gcc.so
      • main.cppをmyMain.cppとコピーして、これをベースに改造したメイン関数を作成
      • make myMain TARGET_CPU=SSE42 でmyMainをコンパイル
        • SSE42は利用しているCPUに
      • LD_LIBRARY_PATH=. ./myMain で実行
    • MATE/YaneuraOu/source に詰将棋エンジンが作成される YaneuraOu-by-gcc
    • MATELIB/YaneuraOu/source 上のライブラリ libYaneuraOu-by-gcc.so
      • main.cppをmyMain.cppとコピーして、これをベースに改造したメイン関数を作成
      • make myMain TARGET_CPU=SSE42 YANEURAOU_EDITION=MATE_ENGINE でmyMainをコンパイル
        • SSE42は利用しているCPUに
      • LD_LIBRARY_PATH=. ./myMain で実行
    • MATE2/tanuki-/source にtanukiさんのgithubのソースから作成した詰将棋エンジンが作成される YaneuraOu-by-gcc
    • MATE2LIB/tanuki-/source にtanukiさんのgithubのソースから作成した詰将棋エンジンが作成される libYaneuraOu-by-gcc.so
      • main.cppをmyMain.cppとコピーして、これをベースに改造したメイン関数を作成
      • make myMain TARGET_CPU=SSE42 YANEURAOU_EDITION=MATE_ENGINE でmyMainをコンパイル
        • SSE42は利用しているCPUに
      • LD_LIBRARY_PATH=. ./myMain で実行

14.4 この章のまとめ

  • 最新ソースでは以前の修正内容では対応出来なくなっていたのを修正
  • パッチファイルとスクリプトファイルを用意して、楽に最新ソースをコンパイル可能にしてみた

15 Ayaneの利用(PythonからYaneuraOuを利用する別の方法)

15.1 関係リンク

15.2 以下の操作を行っている動画


15.3 この章での手順

15.3.1 バーチャル環境作成

cd
virtualenv yaneuraou01

15.3.2 バーチャル環境に入る

cd yaneuraou01/
source bin/activate

15.3.3 python-shogiインストール

pip3 install python-shogi

15.3.4 Ayaneゲットとバックアップ

git clone https://github.com/yaneurao/Ayane.git
tar cvzf Ayane.`date +%Y%m%d`.tgz Ayane/

15.3.5 Ayaneインストール

  • カレントディレクトリで動くように
ln -s Ayane/source/shogi .

15.3.6 前の章で作成したエンジンの実行ファイルのパス確認

  • 実行ファイルが必要です。詰将棋エンジンは評価関数等が不要で楽
  • 通常の将棋エンジンを利用する場合は、評価関数や、定跡ファイルを用意

15.3.7 動作確認

  • 配布サイトの文書のコマンドを試してみる

15.4 この章について

  • Yaneura王さんが作成した、Python用のインターフェイスライブラリを試してみた
  • エンジンを実行ファイルとして、利用するのに便利

16 Ayaneの利用2(PythonからYaneuraOuを利用する別の方法)

  • 前の章の手順だと、Ayaneとpython-shogiの同時利用が不可能であったので、インストール方法を変更することで、同時利用可能に

16.1 関係リンク

16.2 以下の操作を行っている動画


16.2.1 Ayaneインストール

  • カレントディレクトリで動くように以下を行ったが、これ(shogiディレクトリへのリンク)を消して、直接python-shogiのインストール先のディレクトリにAyane.pyをコピーする
  • インストール先のディレクトリ名は、Pythonのバージョンで異るので、異るバージョンの場合は、それにあわせる
cd ~/yaneuraou01/
rm shogi
cp Ayane/source/shogi/Ayane.py lib/python3.8/site-packages/shogi/

16.2.2 Ayaneとpython-shogiを同時に動かせる確認

  • 以下でバーチャル環境に入る
source bin/activate
  • ipythonを起動した後以下を行って、エラーが発生しなければOK
import shogi
import shogi.KIF
import shogi.Ayane as ayane

16.3 この章について

  • 前の章の手順だと、Ayaneとpython-shogiの同時利用が不可能であったので、インストール方法を変更することで、同時利用可能に

17 python-shogiの基本的な使い方

17.1 関係リンク

17.2 以下の操作を行っている動画


17.3 試した手順

  • バーチャル環境のディレクトリに入る
cd ~/yaneuraou01/
  • 以下でバーチャル環境に入る
source bin/activate
  • 必要なものをインポート
import shogi
import shogi.KIF
import shogi.Ayane as ayane
  • kifuファイルの読み込み
  • kifデータを読み込む時、xxxx.kifu の感じで .kifu で終わるファイル名なら utf-8 仮定で読み込まれるようだ(utf-8の場合こういうファイル名に変更)
kif=shogi.KIF.Parser.parse_file("kifu/20201117-02.kif.kifu")[0]
  • 読み込んだ全ての手を表示
for i in kif['moves']:
  print(i)
  • ボード作成
board = shogi.Board()
  • ボード表示
print(board.kif_str())
  • ボードのsfen表示
print(board.sfen())
  • 一手目の内容を表示後、一手目を動かして、盤面とsfen文字を表示
print(kif['moves'][0])
board.push_usi(kif['moves'][0])
print(board.kif_str())
print(board.sfen())

17.4 この章について

  • python-shogiの基本的な使い方を確認した

18 USIを直接使って、内容を確認してみよう1(詰将棋エンジンで、指定の盤面を解いてみる)

18.1 関係リンク

18.2 以下の操作を行っている動画


18.3 試した手順

18.3.1 詰将棋エンジンを起動

  • 詰将棋エンジンを起動する(最近紹介した、githubからダウンロードして、コンパイルするスクリプトを改造し、tournament モードじゃなく normalモードで今日コンパイルしたもの。前の動画のコンパイルの仕方をしたものでも同じ手順で可能)
  • 例えば./20201125_2103/MATE/YaneuraOu/source/ に実行ファイルが有る場合は以下
./20201125_2103/MATE/YaneuraOu/source/YaneuraOu-by-gcc 
  • 将棋エンジンの実行ファイルが入っているディレクトリ名は修正してください。今回はカレントディレクトリに入っているものとします
./YaneuraOu-by-gcc 

18.3.2 USIコマンドを入れていく

  1. 最初はusi
    • 以下を入れてEnterキーを押す
    usi
    
    • 私の環境だと以下がかえってきた
    id name YaneuraOu mate solver Material 5.32 64SSE42
    id author by yaneurao
    option name Threads type spin default 4 min 1 max 512
    option name USI_Hash type spin default 4096 min 1 max 33554432
    option name WriteDebugLog type check default false
    option name NetworkDelay type spin default 120 min 0 max 10000
    option name NetworkDelay2 type spin default 1120 min 0 max 10000
    option name MinimumThinkingTime type spin default 2000 min 1000 max 100000
    option name SlowMover type spin default 100 min 1 max 1000
    option name MaxMovesToDraw type spin default 0 min 0 max 100000
    option name DepthLimit type spin default 0 min 0 max 2147483647
    option name NodesLimit type spin default 0 min 0 max 9223372036854775807
    option name Contempt type spin default 2 min -30000 max 30000
    option name ContemptFromBlack type check default false
    option name EvalDir type string default eval
    option name MorePreciseMatePv type check default true
    usiok
    
  2. 次はisreadyを入れる
    • 以下を入れてEnterキーを押す
    isready
    
    • 私の環境だと以下がかえってきた
    readyok
    
  3. 盤面を設定する
    • 以下を入れてEnterキーを押す
    • positionはsfenでもYaneuraOuさんの詰将棋エンジンは大丈夫なようです
    position lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L b Np 0
    
    • 何もかえってきません。
    • デバッグ用に用意されている d コマンドで現状の盤面を確認。(これは他の詰将棋エンジンでは実装されてないかも)
    • 以下を入れてEnter
    d
    
    • 私の環境だと以下がかえってきた
    • 桂馬をと金の横にうてば、詰む状態を作ってある。
    ^香^桂^銀^金^玉^金^銀^桂^香
     口^飛 口 口 口 口 口^角 口
    ^歩^歩^歩^歩 と 口^歩^歩^歩
     口 口 口 口 口 口 口 口 口
     口 口 口 口 口 口 口 口 口
     口 口 口 口 口 口 口 口 口
     歩 歩 歩 歩 歩 歩 歩 歩 歩
     口 角 口 口 口 口 口 飛 口
     香 桂 銀 金 玉 金 銀 口 香
    先手 手駒 :  桂 , 後手 手駒 :  歩
    手番 = 先手
    sfen lnsgkgsnl/1r5b1/pppp+P1ppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGS1L b Np 0
    
  4. 詰将棋を探索させる
    go mate infinite
    
    • 私の環境だと以下がかえってきた
    info string pn 0 dn 100000000 nodes_searched 0
    info  time 1 nodes 0 nps 0 hashfull 0
    checkmate N*4c
    
  5. 平手で探索させて、詰まないことを確認
    • 平手に盤面を設定して、盤面表示
    sfen startpos
    d
    
    • 私の環境だと以下がかえってきた
    ^香^桂^銀^金^玉^金^銀^桂^香
     口^飛 口 口 口 口 口^角 口
    ^歩^歩^歩^歩^歩^歩^歩^歩^歩
     口 口 口 口 口 口 口 口 口
     口 口 口 口 口 口 口 口 口
     口 口 口 口 口 口 口 口 口
     歩 歩 歩 歩 歩 歩 歩 歩 歩
     口 角 口 口 口 口 口 飛 口
     香 桂 銀 金 玉 金 銀 桂 香
    先手 手駒 :  , 後手 手駒 : 
    手番 = 先手
    sfen lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL b - 1
    
    • 探索させる
    go mate infinite
    
    • 私の環境だと以下がかえってきた
    info string pn 100000000 dn 0 nodes_searched 0
    checkmate nomate
    

18.4 この章のまとめ

  • USIを取り扱えるGUIを利用せずに直接詰将棋エンジンを操作して、詰将棋を解かせてみた

19 USIを直接使って対戦(GUIを使わず直接エンジンと対話)

19.1 関連リンク

19.2 以下の操作を行っている動画


19.3 試した手順

19.3.1 事前準備

  • YaneuraOuをあからじめコンパイル
  • 評価関数、定跡ファイルを準備
  • ファイル構成は以下で動画で行っている
.
├── YaneuraOu-by-gcc
├── book/
├──── standard_book.db
├──── yaneura_book1.db
├──── yaneura_book3.db
├── eval/
└──── nn.bin

19.3.2 詰将棋エンジンを起動

  • 以下はUbuntu等のLinuxマシンの場合、Windowsなら、将棋エンジンのexeファイルを起動
./YaneuraOu-by-gcc

19.3.3 USIでの操作

  1. 事前準備
    • usiにたいしてはusiokがかえってくればOK
    usi
    
    • isreadyにたいしてはreadyokがかえってくればOK
    • 評価関数ファイル nn.binが必要(デフォルトでは実行ディレクトリにあるevalディレクトリ無いに必要。option等で設定すれば他の場所でもいけるかも)
    • 定跡ファイルも必要かも
    • エラーがでて、readyokが帰ってこなければ、評価関数ファイルと、定跡ファイルを用意しましよう
    isready
    
  2. ゲーム開始
    usinewgame
    
  3. 盤面確認(YaneuraOuの将棋エンジン特有のUSI拡張命令 d を利用
    d
    
  4. 駒の移動1
    • 以下は飛車先の歩をすすめる
    position startpos moves 2g2f
    
  5. 将棋エンジンに手を考えさせる1
    • 動画では以下のgoコマンドで、bestmove 5a4b ponder 2f2eがかえってきてた
    • この時5a4bがベストと将棋エンジンが思考した手で、ponderの後の2f2eが相手の手の予想になります
    go
    
  6. 将棋エンジンに手を考えさせる2(先読みさせる)
    • 思考させた手と予想手を追加したposition命令を入れる
    position startpos moves 2g2f 5a4b 2f2e
    
    • dコマンドで盤面確認するとわかりやすくなる(他の将棋エンジンでは、このUSIコマンドは装備されてないかも)
    d
    
    1. 将棋エンジンの予想手が当たってたとき
      ponderhit
      
    2. 将棋エンジンの予想手が外れてた時
      • stopコマンドで思考を止めて
      stop
      
      • 実際に相手が行った手を入れる(ここでは6i7hとすると)
      position startpos moves 2g2f 5a4b 6i7h
      
      • その後に思考させる(思考させるまえにdコマンドで盤面確認した方がわかりやすい
      go
      
  7. 終了
    • 上の繰り返しを行って最後終わる時は
    quit
    

19.4 この章のまとめ

  • GUIを利用せずに、直接将棋エンジンとUSIプロトコルで対話して、対戦してみた
  • USIの理解をするのに、これをやってみるのは良い感じ

20 検討の時にどのようなUSIコマンドを使うべきか、将棋エンジンの設定について調べてみた

20.2 以下の操作を行っている動画


20.3 説明

20.4 実際にやってみる

  • 最初の定形
usi
setoption name Threads value 2
setoption name ConsiderationMode value true
isready
usinewgame
  • 適当な盤面(最近の私の対戦の1つの局面)
position 4B2Sl/l4g1k1/5pnpp/p2pp1p2/1p7/P2+s2P2/1P3PN1P/3+n2S2/+r1+rPGK2L b Lb2gsn4p 101
go depth 20
  • その時の出力。私のPCでだいたい30秒くらい思考
info depth 1 seldepth 1 score cp -2391 nodes 271 nps 135500 time 2 pv 5a4b+ 6h5i 4i3i
info depth 2 seldepth 3 score cp -2391 nodes 483 nps 241500 time 2 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b
info depth 3 seldepth 4 score cp -513 nodes 676 nps 338000 time 2 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b
info depth 4 seldepth 6 score cp -513 nodes 864 nps 288000 time 3 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b
info depth 5 seldepth 7 score cp -2310 nodes 1554 nps 518000 time 3 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b 3b3c
info depth 6 seldepth 8 score cp -513 nodes 1912 nps 637333 time 3 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b 3b3c 7i6i
info depth 7 seldepth 10 score cp -1207 nodes 3768 nps 753600 time 5 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b 4b3c 5i4i 3i2i
info depth 8 seldepth 9 score cp -1207 nodes 4249 nps 849800 time 5 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b 4b3c 5i4i 3i2i
info depth 9 seldepth 13 score cp -913 nodes 6952 nps 993142 time 7 pv 5a4b+ 6h5i 4i3i 2b2a G*3b 2a1b 4b3c 5i4i 3i2i
info depth 10 seldepth 12 score cp -2164 nodes 13621 nps 1047769 time 13 pv 5a4b+ 6h5i 4i3i G*4h 3i2h 4h3h 2h2g S*1h 1i1h 3h3g 2g3g N*4e 3g2f
info depth 11 seldepth 17 score cp -5278 nodes 65211 nps 869480 time 75 pv 4i3i 4b4a L*4f S*5b 5i6h 4a5a N*2e B*5i 2e3c+ 2b3c N*2e 3c4b 3i2h 5i6h+ 6i6h 7i1i 2h2g
info depth 12 seldepth 19 score cp -5045 nodes 87268 nps 831123 time 105 pv 4i3i 4b4a 5a8d+ 6f5f 5i6h 7i6h N*2e 3c2e 3g2e 9i6i 3i2h
info depth 13 seldepth 16 score cp -4986 nodes 104602 nps 823637 time 127 pv 4i3i 4b4a 5a8d+ 6f5f 8d8e S*5b 5i6h 7i6h 3i2h 2b2a 6i6h
info depth 14 seldepth 15 score cp -4741 nodes 118104 nps 814510 time 145 pv 4i3i 4b4a 5a8d+ 6f5f 8d8e S*5b 5i6h 7i6h 8e5b
info depth 15 seldepth 23 score cp -5741 nodes 1532976 nps 876487 hashfull 592 time 1749 pv 4i3i 4b5b 5i6h 5b5a L*5c 5a4b N*4f 2b2a 4f3d 4b5c 3g2e 3c2e 3h4i 2a3b P*2b G*4a 2b2a+
info depth 16 seldepth 26 score cp -5807 upperbound nodes 2639289 nps 851108 hashfull 820 time 3101 pv 4i3i 4b5b 5i6h 5b5a L*5c 5a4b N*4f 2b2a 4f3d 4b5c 3g2e 3c2e 3h4i 2a3b P*2b G*4a 2b2a+ 3b2a
info depth 16 seldepth 26 score cp -5848 upperbound nodes 3112688 nps 845609 hashfull 890 time 3681 pv 4i3i 4b5b 5i6h 5b5a L*5c 5a4b N*4f 2b2a 4f3d 4b5c 3g2e 3c2e 3h4i 2a3b P*2b G*4a 2b2a+ 3b2a
info depth 16 seldepth 26 score cp -5905 upperbound nodes 3977493 nps 819257 hashfull 951 time 4855 pv 4i3i 4b5b 5i6h
info depth 16 seldepth 26 score cp -5981 upperbound nodes 4851367 nps 828726 hashfull 983 time 5854 pv 4i3i 4b5b 3i2h 6h5i L*1b 1a1b 2a1b+ 2b3b 5a8d+ B*5g 1g1f
info depth 16 seldepth 26 score cp -5920 lowerbound nodes 5580566 nps 835039 hashfull 994 time 6683 pv 4i3i B*5g 3i2i 4b5b L*5c S*3i 2a3b+ 2b3b 5a3c+ 3b3c N*2e 3c4b
info depth 16 seldepth 26 score cp -5927 nodes 5701475 nps 836606 hashfull 996 time 6815 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h N*5f 5h6f 5f6h+ 6i6h 2d6h 3i2i 4d5e
info depth 17 seldepth 24 score cp -5946 upperbound nodes 5867366 nps 838914 hashfull 996 time 6994 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h N*5f 5h6f 5f6h+ 6i6h 2d6h 3i2i 4d5e
info depth 17 seldepth 24 score cp -5965 upperbound nodes 5962177 nps 839979 hashfull 996 time 7098 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h N*5f 5h6f 5f6h+ 6i6h 2d6h 3i2i 4d5e
info depth 17 seldepth 24 score cp -5994 upperbound nodes 6148436 nps 842713 hashfull 997 time 7296 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h N*5f 5h6f 5f6h+ 6i6h 2d6h 3i2i 4d5e
info depth 17 seldepth 24 score cp -6035 upperbound nodes 6667511 nps 846990 hashfull 998 time 7872 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h
info depth 17 seldepth 24 score cp -6092 upperbound nodes 7174905 nps 851317 hashfull 998 time 8428 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h
info depth 17 seldepth 24 score cp -6167 upperbound nodes 8101274 nps 855467 hashfull 1000 time 9470 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h
info depth 17 seldepth 24 score cp -6177 nodes 8583451 nps 858430 hashfull 1000 time 9999 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h 6f6e 3i2h G*2b 4i5g 2b2a 5g6e
info depth 18 seldepth 29 score cp -6196 upperbound nodes 9405168 nps 860569 hashfull 1000 time 10929 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d N*5h
info depth 18 seldepth 29 score cp -6215 upperbound nodes 10363702 nps 862061 hashfull 1000 time 12022 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h N*5f N*1f 2d1d 3g4e 3c4d 2a3b 4d5e 3b4a 5b6b
info depth 18 seldepth 29 score cp -6244 upperbound nodes 11624861 nps 865782 hashfull 1000 time 13427 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h N*5f N*1f
info depth 18 seldepth 29 score cp -6285 upperbound nodes 13213656 nps 870120 hashfull 1000 time 15186 pv 4i3i B*5g L*4h
info depth 18 seldepth 29 score cp -6252 lowerbound nodes 13296528 nps 869850 hashfull 1000 time 15286 pv 4i3i B*5g L*4h
info depth 18 seldepth 29 score cp -6180 nodes 13306369 nps 869867 hashfull 1000 time 15297 pv 4i3i B*5g L*4h 4b5b 5a8d+ 2b2a 8d8e 5b4b 8e4i 6h6i 5i6i 7i6i N*4e 2a2b 3i2h 3c4e 3g4e S*3i 4i3i 6i3i 2h2g
info depth 19 seldepth 25 score cp -6198 upperbound nodes 13474472 nps 870106 hashfull 1000 time 15486 pv 4i3i B*5g L*4h 4b5b 5a8d+ 2b2a 8d8e 5b4b 8e4i 6h6i 5i6i 7i6i N*4e 2a2b 3i2h G*3b
info depth 19 seldepth 25 score cp -6217 upperbound nodes 13947562 nps 870688 hashfull 1000 time 16019 pv 4i3i B*5g L*4h
info depth 19 seldepth 25 score cp -6246 upperbound nodes 14057638 nps 870927 hashfull 1000 time 16141 pv 4i3i B*5g L*4h 4b5b 5a8d+ 2b2a 8d8e 5b4b 8e4i 6h6i 5i6i 7i6i N*4e
info depth 19 seldepth 25 score cp -6222 lowerbound nodes 14619891 nps 871632 hashfull 1000 time 16773 pv 4i3i B*5g L*4h
info depth 19 seldepth 27 score cp -6287 upperbound nodes 15112718 nps 872709 hashfull 1000 time 17317 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h N*5f 3g4e 3c4d 2a3b 4d5e 6h5g
info depth 19 seldepth 29 score cp -6226 lowerbound nodes 17538540 nps 872911 hashfull 1000 time 20092 pv 4i3i B*5g 3i2i 4b5b 3g2e
info depth 19 seldepth 29 score cp -6363 upperbound nodes 18354145 nps 874548 hashfull 1000 time 20987 pv 4i3i B*5g 3i2i 4b5b 3g2e
info depth 19 seldepth 29 score cp -6244 lowerbound nodes 23156655 nps 875322 hashfull 1000 time 26455 pv 4i3i B*5g L*4h
info depth 19 seldepth 29 score cp -6317 nodes 23173727 nps 875272 hashfull 1000 time 26476 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d 2a3b N*5f 3g4e 4d5e N*5h 5f6h+ 5h6f 5e6f 6i6h
info depth 20 seldepth 23 score cp -6336 upperbound nodes 24103006 nps 875199 hashfull 1000 time 27540 pv 4i3i B*5g L*4h
info depth 20 seldepth 23 score cp -6317 lowerbound nodes 24117267 nps 875114 hashfull 1000 time 27559 pv 4i3i B*5g L*4h
info depth 20 seldepth 23 score cp -6288 lowerbound nodes 24122255 nps 875104 hashfull 1000 time 27565 pv 4i3i B*5g L*4h
info depth 20 seldepth 27 score cp -6355 upperbound nodes 24338011 nps 875027 hashfull 1000 time 27814 pv 4i3i B*5g L*4h
info depth 20 seldepth 27 score cp -6301 lowerbound nodes 24353457 nps 874984 hashfull 1000 time 27833 pv 4i3i B*5g L*4h
info depth 20 seldepth 27 score cp -6293 nodes 24694818 nps 875237 hashfull 1000 time 28215 pv 4i3i B*5g L*4h 4b5b 5a3c+ 2b3c N*4i 5g2d+ 5i6h 3c4d 2a3b N*5f 3g4e 4d5e N*5h 5f6h+ 6i6h 2d6h 3i2h S*5i 3b4c 5b4c
bestmove 4i3i ponder B*5g
  • 将棋エンジン停止
quit
  • 次に詰みがある盤面をやってみた。
usi
setoption name Threads value 2
setoption name ConsiderationMode value true
isready
usinewgame
position lnsg3nl/4k1G2/p1pp1pp1p/4p4/7r1/P1P1P1R+B1/1PSPbPP1P/2G6/LN2KGSNL b SP2p 1
go depth 20
  • 一瞬でおわった
  • 詰みがあると 「mate 詰みまでの手数」がエンジンからinfoで送られてくる
info depth 1 seldepth 2 score mate 3 nodes 206 nps 206000 time 1 pv S*5c 5b5a 3b4b
info depth 2 seldepth 4 score mate 3 nodes 479 nps 479000 time 1 pv S*5c 5b5a 3b4b
info depth 3 seldepth 4 score mate 3 nodes 698 nps 349000 time 2 pv S*5c 5b5a 3b4b
info depth 4 seldepth 4 score mate 3 nodes 911 nps 455500 time 2 pv S*5c 5b5a 3b4b
info depth 5 seldepth 4 score mate 3 nodes 1122 nps 561000 time 2 pv S*5c 5b5a 3b4b
info depth 6 seldepth 4 score mate 3 nodes 1345 nps 672500 time 2 pv S*5c 5b5a 3b4b
info depth 7 seldepth 4 score mate 3 nodes 1562 nps 781000 time 2 pv S*5c 5b5a 3b4b

20.5 この章のまとめ

  • 検討したいときに、USIコマンドでどのようなコマンドをYaneuraOuエンジンに送れば良いのかをネット検索した
    • 他の将棋エンジンも、このUSIコマンドをサポートしているか不明。方言あるため
  • 実際に直接USIコマンドで、どの程度時間かかるのかと、どのような情報が将棋エンジンから送られるのかを確認した。
  • ネット対局の棋譜の解析を今は手動で行っているが、今回の調査を元に、自動化したいと考えてます。

21 今後

  • 今後も文書追加していきます。

22 この文書のチェンジログ

  • 2020/07/06 初版
  • 2020/07/08 一括でソースゲットしてコンパイルするプログラム修正、情報URLの修正
  • 2020/07/09 下準備の章追加
  • 2020/07/09 下準備2の章,Positionクラス(盤面クラス)の初期化と表示の章 追加
  • 2020/07/10 詰みチェック,指定の一手を行う,指定の一手を行った後、その手の取り消しの章追加
  • 2020/09/02 Python+cppyyを利用して、PythonからYaneuraouのライブラリの直接利用 の章追加
  • 2020/11/19 最新ソースをダウンロード(2020/11/19)して、トーナメント用、詰将棋用のエンジンコンパイル、それらのライブラリコンパイル用のスクリプトについて の章を作成
  • 2020/11/19 Ayaneの利用(PythonからYaneuraOuを利用する別の方法) の章追加
  • 2020/11/20 Ayaneの利用2(PythonからYaneuraOuを利用する別の方法) の章追加
  • 2020/11/20 python-shogiの基本的な使い方 の章追加
  • 2020/11/25 USIを直接使って、内容を確認してみよう1(詰将棋エンジンで、指定の盤面を解いてみる) の章追加
  • 2020/12/09 USIを直接使って対戦(GUIを使わず直接エンジンと対話) の章追加
  • 2021/01/19 検討の時にどのようなUSIコマンドを使うべきか、将棋エンジンの設定について調べてみた の章追加

著者: NM Max

Created: 2021-01-21 木 06:12

Validate