Macキーボード不調 (シフトロック) 対応記録

論文執筆中にPCが壊れるというのはよくある話で、特に学位審査前はバックアップをこまめにとりましょうね、ということは暗黙知としてよく知られるところである。

現在、ジャーナル投稿論文と学位論文の両方を抱えている私にとって、そうした危険性はダブルで高まっていると考えて差し支えなく、実際にキーボードの調子が悪くなって二日ほど執筆が遅れたという週末を過ごした。

具体的な症状は

  • Mac ( MacBookAir2015early, macOS Sierra - 10.12.6 )のキーボード不調
  • シフトロックがかかったままになる(一瞬外れてもまたロックされる)
  • 修飾キーを押すとfnキーが同時に押されたままになる

であり、文字入力がままならないという最悪の事態だった。

対処法をググってたどりついた読者向けに、まずは結論から述べる。

キーボード不調時の対処法

1. SMCクリアして直るかどうか

SMCクリアとはどういうものか、公式の説明はこちら。

Mac の SMC (システム管理コントローラ) をリセットする - Apple サポート

要は、システム系の再起動って感じですね。これを実行してもデータが初期化されたりはしないので大丈夫です。 実行方法は簡単で、

  1. (起動している場合は)電源を落とす
  2. [shift]+[control]+[option]ボタンを押しながら[電源ボタン]を10秒くらい押す
  3. 手を離しても起動しないことを確認
  4. [電源ボタン]を押して通常通り起動させる

ちなみに、これを実行しても私の場合は直りませんでした。 (むしろ、シフトロックされたままだったのでパスワードが正しく入力されず、ログインできなくなってしまうという一層ひどい状況に……)

2. PRAM(NVRAM)クリアして直るかどうか

まず、公式の説明ページはこちらです。

Mac の NVRAM をリセットする方法 - Apple サポート

こちらは、キーボードやスピーカーなどのハードに関するトラブルを解消するための再起動メニューのようです。

  1. (起動している場合は)電源を落とす
  2. [電源ボタン]を押す (素早く次の動作を行う)(起動音「ジャーン」という音が1回鳴る)
  3. (2の直後に素早く) [option]+[command]+[R]+[P]ボタンを押し続ける。
  4. もう一度、起動音「ジャーン」という音が1回鳴ったら手を離す

私の場合はこれで解決!元通りになりました。

その他

3. 新規ユーザーを作って別アカウントで直るかどうか

キーボードの不調は、ユーザーアカウント毎に発生することもあるようです(Apple公式サポートのオペレーターから聞いた話)。新たにユーザーアカウントをつくると、そちらでは問題が起きないというケースもあるようなので、SMCクリア・PRAMクリアを数回試しても解決しないようであれば、こちらもトライしてみてください。 詳しくはこちらをどうぞ。

Mac で別のユーザアカウントを使って問題を検証する方法 - Apple サポート

4. リカバリー起動モード(最終手段)

セーブブートとは異なる、リカバリー起動モードです。

macOS 復元について - Apple サポート

起動時に読み込むシステムファイルが制限されたところでも、同じ問題が起きるかどうかで原因を調べることができます。ただし、起動後のユーティリティー画面で「TimeMachineバックアップから復元」や「macOSを再インストール」を押してしまうと、直近のデータが失われたりデータが全消失することになりますので、慎重に。「ディスクユーティリティー」を選んで、修復を試みるようにしましょう。

というか、たぶん(あまりパソコン関係に詳しくない人が)このリカバリーモードを試さなければならない場合は、公式サポートのオペレーターの指示で行った方がいいと思います。というわけで、次の最後の最終手段……

5. 公式のサポートを受ける

システム上の(ソフトウェア的な)不具合ではなく、ハードウェアの物理的損傷によって問題が起きている場合は、上記のプロセスを経ても直りません。OSの再インストールをしてデータを全消去する前に、AppleStoreに持ち込んだり、電話でのサポートを受ける方が良いでしょう。

予約ページはこちらです。

www.apple.com

個人的には、AppleStoreが近くにあり、かつ時間に余裕があるなら店舗に行って見てもらうことをおススメします。対面応対はやはり安心感が違います。予約しておいたほうが無難ですが、予約なしでも営業時間内なら受け付けてくれることも多いです(待たされますが…)。

遠隔の場合は電話応対ですね。時間を指定して予約し、サポートセンターから電話をかけてもらうのが良いでしょう。予約の際に、何の製品のトラブルなのかを申請しますが、自分のappleIDに製品を登録しておくとシリアルナンバーの確認の手間など省略できるので楽です。

ともあれ、何が起こっても大丈夫なように、論文のデータはクラウドに置いておきましょう、そしてこまめにローカルのHDDにもバックアップしておきましょう、ってことだね。 ではでは、よいMacライフを。

行列力学用・Python3でのややマニアックな行列演算まとめ

量子力学の計算(行列力学)をするとき、これまではMATLABを使っていたんだけど、何かとPythonのほうが応用がききそうなので乗り換えつつある。(あと何と言ってもMATLABは高い。。。)

MATLABに実装されているたいていの処理はPythonでも実行可能なのだが、やはり少し勝手が違う。他の技術ブログとかではまとまってなかったところに限って、(半分自分のために)まとめておこうと思う。

【随時更新予定】

行列の積

Pythonでは、+, -, *, /の四則演算子(記号で演算が済むもの)は、対応する要素同士の演算である。つまり、MATLABにおけるA.*BPythonでのA*Bが対応している。

ゆえに、内積numpy.dot(A, B)で、外積numpy.cross(A, B)で計算する。

ハミルトニアンの次元を拡張するとき等に使う「クロネッカー積」は、MATLABではkron(A, B)で、Pythonではnumpy.kron(A, B)である。

行列の複素共役転置

MATLABでは、行列Aに対してA'とすれば転置行列を返してくれる。さらに、行列要素に複素数が入っている場合は暗黙のうちに複素共役をとってくれる。

一方Pythonは、転置行列を返すメソッド(hoge.T)と、複素共役をとってくれる関数(numpy.conjugate(hoge))が別々に定義されている。したがって、

# MATLABでは
A'
# Pythonでは
numpy.conjugate(A.T)

が等価。

行列の指数

[tex:{ \displaystyle

e^{-iHt} }]

のように、ハミルトニアンHで時間発展する波動関数(行列)への作用(演算子)を計算したいときがあって、 こういうときには、『行列の指数』を計算しないといけない。

MATLABではexpm(H)という関数で済むのだけど、Pythonの場合はScipyで定義されているexpmを使わないといけないので、次のようにする。

import scipy.expm
# あるいは、
# from scipy import expm

scipy.expm(A)

「行列の指数」で探すと、他にもNumpyの中のexpm1()とかmatrix_power()とか 似たようなものがいっぱいあるが、ちゃんとMATLABexpmと同じ結果を返す関数はコレだった。 探し出すのにそこそこ苦労したので他の人の参考になれば嬉しい。

ちなみに、MATLABでは「3i」のようにすると暗黙のうちにi虚数単位として複素数のデータ型で計算してくれるが、Pythonではiではなくjを使う(特に宣言せずとも虚数単位と解釈してくれるのは同じ)ので少し注意が必要。

その他

MATLABPythonで置換しようという動きはおそらく数値計算をしている人にとっては当然の発想であるので、 必然的に両者を比較したサイトは多い。

中でも使えそうなサイトを列挙しておくので、参考にしてほしい。

MATLABユーザー向け

Pythonにおける行列操作・演算の基本について

書ければいい人のためのPython3超入門(他言語既習者向け)

知り合いのJavaぷよぐやまーが「Pythonさわってみたい!」と言ってくれたので、布教を兼ねて基礎的なことをまとめてみた。

これくらい知ってればそこそこ書けるんじゃね?っていう程度のもの。 綺麗には書けないかもしれないけど、ゴリ押しはできるはず←

ただし、何かしらの言語をさわったことがある人向け。「関数…?(´・ω・`)」みたいな読者は想定していません。

※この記事はタイトルにある通り、Python3用です!!

データ型について

Pythonは関数型っぽくも使えるし、オブジェクト指向も使える。ここでは、どんなモノ(データ型)が扱えるのか、サクッと概観してみよう。

  • 数値型:intとかfloatとかおなじみのやつら
  • 真偽値:ブール値。TrueとFalseね
  • 関数・オブジェクト:読んで字のごとく
  • 要素が並んだもの
    • 文字列:文字が並んだもの
    • リスト:いわゆる配列。データが並んだもの
    • タプル:要素が変更できないリスト
    • セット:要素の重複を許さないリスト
    • 辞書:いわゆるハッシュ。キーと値をセットにして格納する

では、それぞれの使い方を簡単にみていく。

リスト(配列)

角括弧でくくる → list = [ hoge, hoge, ... ]

配列の添え字(インデックス)は0から始まります。

# 定義の例
s = [ hoge0, hoge1, hoge2 ]
# 要素の取り出し
s[0] #=> 先頭の要素hoge0を指定
s[0:2] #=> 0番目から2番目の「手前」までの要素を指定
s[-1] #=> 負の添え字も使える。先頭ゼロから末尾に-1、さらに逆順に-2, -3…

range関数

よく使うのでここで紹介しておく。range関数は正確にはリストそのものを返すわけではなく、リストのように振る舞うオブジェクトを返しているだけなのだが、整数列を効率良く生成してくれたりするので重宝する。特にfor文のループ回数指定で頻出。

range(n) #=> [0, 1, 2, ..., n-1]という整数列をつくる
range(m, n) #=> [m, m+1, ..., n-1]という整数列をつくる
range(m, n, k) #=> mからn-1まで、kずつ飛ばした整数列をつくる

タプル

丸括弧でくくる → tuple = ( hoge, hoge, ... )

要素の変更はできないが、タプルを連結・切り出し・繰り返しなどで新しいタプルをつくることは可能

セット

丸括弧と角括弧でくくる → set = ([ hoge, hoge, ... ])

set同士はand, or, xorなどの集合演算ができる。

使う場面は限られそうだけど、おもしろい。

辞書

波括弧を使いキーと値のペアを記述 → dict = {key1:val1 , key2:val2, ...}

要素のアクセスにはkeyを使って、dict[key1]のように指定すればval1が得られる。

代表的なメソッドをリストアップしておく。

  • dict.items():要素をキーと値をペアで全て返す
  • dict.keys():全てのキーを返す
  • dict.values():全ての値を返す

演算子

次に演算子について見てみよう。

  • 四則演算子(加減乗除の順に):+, -, *, /
  • 少数点以下を切り捨てて整数の商を返す除算://
  • 剰余:%
  • べき乗:**

Pythonでは除算に2種類ある。たとえば、「3÷2」を3/2と実行すると1.5が得られるが、 3//2と実行すると小数点以下切り捨てとなって1が返ってくる。

文字列の扱い

  • シングルクォーテーションで囲っても、ダブルクォーテーションで囲っても構わない。
  • もし、複数行を「改行を含めて、入力したまま」表示したい場合は、ダブルクォーテーション3つで囲う。
  • シングルクォーテーション3つで囲った場合は「複数行コメントアウト」になるので注意。
  • 1行コメントアウト#を行頭につける。

キャスト(型変換)

データ型を変換する場合は、関数を使う。

  • 文字列から整数:int( 'hoge' )
  • 文字列から浮動小数点:float( 'hoge' )
  • 整数or浮動小数点から文字列:str( hoge )
  • リストからタプル:tuple( hoge )
  • タプルからリスト:list( hoge )

まぁ、データ型を表しそうな単語が関数になっているよね。

制御構文

Pythonは、処理が同じブロックに属しているかをインデント(行頭の位置)がそろっているかどうかで判断する。これを「見やすい」と取るか「気持ち悪い」と取るかは人によって差が出そう。

ブロック1:
    処理1
    処理2
    処理3

ブロック2:
    処理4
    処理5

処理6
処理7

たとえば上のようなコードの場合、処理1〜3はブロック1の中処理で、処理4と5はブロック2の処理になる。そして処理6と7は、ブロック1とブロック2と同じレベルにある処理ということ。したがって、この場合プログラムは大きく「ブロック1→ブロック2→処理6→処理7」という順番で命令を実行していく。

では、基本的な構文についてみていこう。

条件分岐if

構文は次の通り。

# 基本式
if [条件式1] :
    hoge1
    hoge2
elif [条件式2] :
    hoge3
else :
    hoge4

# elifがない場合は1行でも書ける
hoge1 if [条件式1] else hoge2
  • 比較演算子
    • <, >
    • <=, >=
    • ==:イコール
    • !=:ノットイコール
  • 論理演算子
    • and, or, not

論理演算子に、ありがちな&&とか||ではなく文字のandとかを用いるのが独特かな?

ループ処理

while文

# 基本式
while [条件式1] :
    hoge1
    hoge2
else :
    hoge4

else節はなくてもよい。ある場合は、条件式を満たさなくなった(ループを抜けた)後に、else節を実行するようになる。

for文

# 基本式
for [var] in [expr]:
    hoge1
    hoge2
else:
    hoge3

else節はなくてもよい。

単純にn回繰り返したいときは、[expr]range(n)を使い、[var]にfor文内で使う変数(iとか)を書いておく。

Pythonのfor文はC言語などと違って、ループが終わるたびに条件判定をしてループするかしないかを決めるわけではない。 ループするたび、[expr]に格納された要素を順番に[var]に代入していって、代入するものがなくなったら終わり、という方式なのである。 したがって、[expr]にはリストやタプルの各要素や辞書のkeyや文字列なんかを指定することができる。

for name in ['mac', 'win10', 'linux']
    print('I like ' + name + '.')

# => 標準出力には次のように表示される。
# => I like mac.
# => I like win10.
# => I like linux.

リスト内包表記

# 基本構文
sampleList = [ 処理1 for 変数 in シーケンス ]

簡潔なコードを書くとき、Pythonでよく利用されるのがこのリスト内包表記である。 上の基本構文の例の挙動を解釈すると、シーケンスに格納された要素を順番に変数に代入していき、処理1を行った結果を要素にもつ新しいリストをつくって、それをsampleListと名付けた、という感じだろうか。

使う場面としては、

  • あるシーケンス(たとえばリスト)や、イテラブル(繰り返し可能なオブジェクト)の各要素に対して、
    • ある操作を行った結果を要素にもつ新しいリストをつくりたい
    • ある条件を満たす要素だけからなる部分集合的なシーケンスをつくりたい

みたいなときに大活躍する。

最後に例として、n=1〜5までの平方数(2乗した数)のリストをつくるコードを挙げておく。

# for文を使う
sq = []
for x in range(5):
   sq.append( (x+1)**2 )
   # appendはリスト末尾に要素を追加するメソッド
   # range(5)は0〜4までの要素をもつリストなので、
   # (x+1)としている。

# 内包表記を使う
sq = [ (x+1)**2 for x in range(5) ]
   # 3行かかったfor文が1行で済む!しゅごい!!

# ラムダ式を使う
sq = list( map( lambda x: (x+1)**2, range(5) ) )
   # 載せただけ。解説はしない。

for文よりも内包表記の方がいいのは、簡潔に書けるということだけではない。 for文だとxという変数がfor文終了後も残るのだが、内包表記(とラムダ式)の場合はxは実行後には残らない。 つまり、変数を書き換えちゃった、みたいな思わぬミスが起きにくいと言える。 まぁ、1行で書けるっていうのが書いてる側からしたら大きいけどね。

プログラムを実行するにあたって

関数の定義

# 基本構文
def 関数名(引数1, 引数2, ...):
    hoge1
    hoge2
    ...
    return 変数1, 変数2, ...

defによる宣言を使う。一つの関数内で行う処理は、インデックスをそろえないといけない(入れ子の場合はさらに下げるけど)。返り値はreturnで指定すればよい。

標準入出力

標準出力

print()関数で標準出力へ文字列を表示することができる。さらに、.format()メソッドを使うと、{数字}で記述した部分に変数の値を代入して表示することができる。

a = 1
b = 2
print( 'a = {0}, b = {1}'.format(a, b) )
# => 出力には、 "a = 1, b = 2"  と表示される。

標準入力

input()関数を使うと、標準入力からの入力結果を受け取ることができる。input()の中では、こちらから文字列を表示することもできる。

ただし、必ずString型で受け取ってしまうので、数値を受け取る場合はnum = int( input() )のようにキャストしないといけない。

もし、記号などで区切られた二つの数値を受け取りたいような場合は、.split('hoge')メソッドを使う。※hogeには、空白スペースとかカンマ・ピリオドなどの区切り記号を入れて使う。

number = int( input() )
num1 = int( input('Please type your number: ') )
a, b = input().split(',')

Pythonコード末尾の謎のif節

エラい人が書いたPythonのコードを見ていると、

hoge1
hoge2
hoge3
...

if __name__ == '__main__':
    hoge4
    hoge5
    hoge6
    ...

という、奇妙なif文に遭遇する。最初は相当面食らう(はず)だろう。 これについて、辞書的な(正確な)説明は他のサイトを見てもらうとして、「使えりゃいい」派の人向けの説明を試みる。

まず、Pythonのコードはhoge.pyという拡張子で保存される。そうすると、このファイル自体はもう「モジュール」みたいなもんになる。だからたとえば、別のコードhogehoge.pyを書いているときに、hoge.pyの中でつくった関数(ここではfunc1としよう)を流用したいと思った時は、hogehoge.pyの文頭あたりでimport hogeと記述しておけば、そこではhoge.func1という名前でその関数を再利用できるようになる。

いちいちhoge.という「どのモジュールに属しているfunc1か」を明記しないといけない(回避する方法もあるが非推奨)のが少し面倒だが、逆にメンテナンス性があがるということで良しとしよう。

さて、ただのスクリプトがモジュール(プラグインツールボックスと言った方が分かりやすい人もいるかな?)としても使えるということになると、同じスクリプトファイルに対して、処理として実行したい時モジュールを読み込む時の2種類のアクションがあることがわかる。

たとえば「円周率を計算するスクリプト」を作り、そのなかで「円周の長さを計算する関数」を定義してあったとする。で、今まったく別のスクリプトを書いているのだが、どうしてもその時の「円周の長さを計算する関数」を再利用したいとする。このとき、先ほど説明した通りimportというコマンドを使えば良いのだが、単純にimportしてしまうとモジュールを読み込んだときに、今行っている処理とはまったく無関係に「円周率を計算してしまう」というような副作用が起きるかもしれないわけだ。

それを阻止するために、モジュールとしてではなく、実行するスクリプトとしてPythonに呼び出されたときに以下の処理を行いなさいというのがif __name__ == '__main__:'のブロックに書いてある処理なのである。

すなわち、先ほどの例でhoge1〜3が関数の定義とかが書かれている部分とすると、importしたときに読み込まれるのがそのhoge1〜3のブロックで、hoge4〜6はそのスクリプト自身が実行されたときに実際に行う処理、ということになる。

例を示そう。 次のコードは、a, bの二つの引数を持ちcを返す関数func1と、dという引数を持ちeを返す関数func2を定義している。そして、func1にa=1, b=2を与えた時の返り値output1をfunc2の引数として与えて、最終的に計算される値output2を出力するというもの。

def func1(a, b):
    hoge0
    hoge1
    ...
    return c

def func2(d):
    hoge_10
    hoge_11
    ...
    return e

if __name__ == '__main__':
    output1 = func1(1, 2)
    output2 = func2(output1)
    print('Final output is {0}'.format(output2) )

こうしておけば、モジュールとして読み込んだ時に、a=1, b=1の算出結果が標準出力に吐き出される心配なく、func1func2を再利用することができる。 イメージはつかめただろうか??

さいごに

これだけの知識があれば、とりあえず簡単なコードは書けそう…だろうか? あと必要なメソッドや関数は、公式のリファレンスを読もう。あとはネットで調べると沢山説明が出てくるはずだ。 「Pythonらしい簡潔なコード」を書くには修行が必要だと思うけど、原理的には「条件分岐とループ処理が出来ればどんなアルゴリズムも実装可能」なはずなので、「動けばいいんだ、動けば」というタイプの人間はここらへんまでの知識があればとりあえず何か書いて動かせるようにはなると思う。

Python上達の近道は、サンプルコードを読みまくることらしい。公開されているモジュールの中身のスクリプトを読むとか、公式チュートリアルのサンプルコードを読むとか、そこらへんが勉強になる(と、どこかに書いてあった)。

個人的には、「Doing Math with Python」という本(の日本語訳版:Pythonからはじめる数学入門)がオススメ。長々とメソッドの説明されるよりも、具体的に「こうしたいときはこう」みたいなレクチャーの方が僕は好きなので。

Pythonからはじめる数学入門

Pythonからはじめる数学入門

僕はアフェリエイトしてないので、Amazonのリンク踏んでも大丈夫です(←なにがだw)

心機一転

明けましておめでとうございます。

 

今年の目標は「健康的に研究に没頭する」です。

 

ええ。

 

健全な研究は健全な精神と健全な肉体に宿るのです。

 

たぶん。

 

そして、ブログを刷新しました。

ツイッターアカウントのIDも変えました。

ちょっと思うところあって。

 

今年はもうちょっといっぱい技術ネタを書きたいですね。