「ベクトルのリスト」から行列を返すオリジナルツール
課題
ベクトルのリストvectorList の各要素を列ベクトルと考えて、行列を得たい。たとえば、ベクトル
u = (1,2)
v = (3,4)
に対して、
vectorList = {u, v}
を作成したとする。vectorListを引数として、行列
を得られるような、オリジナルツールを作成する方法を考える。
なお、以下の説明は、GeoGebra バージョン6.0.536.0-wを前提としている。
比較的単純な方法(うまくいかない)
①ベクトルの各成分を並べて行列を作成(matrix1)
matrix1 = Transpose[Zip[{x(α), y(α), z(α)}, Vector[α], vectorList]]
②matrix1の3行目(z座標を集めたもの)が全て0、すなわち2次元ベクトルであれば1、そうでなければ(3次元ベクトルならば)0を返す数値を取得(dimensionChecker)。
dimensionChecker = Product[Zip[α ≟ 0, α, Element[matrix1, 3]]]
③2次元ベクトルの場合には3行目をカットする(output)
output = If[dimensionChecker ≟ 1, Take[matrix1, 1, 2], matrix1]
④outputを、vectorListのみで表したもの
If[Product[Zip[α ≟ 0, α, Element[Transpose[Zip[{x(β), y(β), z(β)}, Vector[β],vectorList]], 3]]] ≟ 1, Take[Transpose[Zip[{x(γ), y(γ), z(γ)}, Vector[γ],vectorList]], 1, 2], Transpose[Zip[{x(δ), y(δ), z(δ)}, Vector[δ],vectorList]]]
うまくいかない原因
④の数式は、GeoGebra(バージョン6.0.536.0-w現在)の仕様上、うまくオリジナルツール化できない(オリジナルツールにした途端に、戻り値が正しくなくなる)。その理由は、概略以下のとおりである。
vectorListを唯一の引数としてオリジナルツールを作成する場合、vectorListは自由オブジェクトである必要がある(そうしなければ、ツール作成時にエラーが生じてしまう)。そのため、vectorListを、
{u, v}
のように、他のオブジェクトに依存する形で定義するのではなく、たとえば
{ (1,2), (3,4) }
のように、座標を用いた形で定義する必要がある。
ところが、どうやら、GeoGebra(バージョン6.0.536.0-w現在)の仕様上、
{ (1,2), (3,4) }
が「点のリスト」なのか、「ベクトルのリスト」なのか、ハッキリしないという点に起因して、Zipコマンド使用時に想定外の処理が行われているようだ。
そこで、まずは、vectorListをZipコマンドにかける前に、vectorListの要素が点なのかベクトルなのかを、こちら側でハッキリさせる必要がある。
ベクトルと点の区別
GeoGebraでは、ある座標を定義にもつオブジェクトが、ベクトルなのか点なのかを判定して、結果に応じて異なる値(true / falseなり、1 / 0なり)を返すことは、きわめて難しい。さしあたり、以下の裏技的手法が有効である*1。すなわち、ある座標で定義されたオブジェクトは、
<オブジェクト> ≟ Translate[ <オブジェクト>, (0, 1) ]
がtrueならばベクトルであり、falseならば点である。
以下では、これを利用して、オリジナルツール作成を目指す。
ベクトルと点を区別して作成する方法(うまくいった)
①vectorListの各要素に対して、ベクトルであれば1、点であれば0として判定し、結果をリストとして取得する(isVector)。
isVector = ¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], (0, 1)], α, 1, Length[vectorList]])
②vectorListの各要素に対して、点であれば1、ベクトルであれば0として判定し、結果をリストとして取得する(isPoint)。感覚的には、isVectorの裏返しである。
isPoint = ¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], (0, 1)], β, 1, Length[vectorList]]
③pointListの要素のうち、ベクトルであるものについては、そのベクトルの成分を用いた点を返す。pointListの要素のうち、点であるものについては、点(0,0)を返す(pointList1)。
pointList1 = vectorList * isVector
④pointListの要素のうち、点であるものについては、そのベクトルの成分を用いた点を返す。pointListの要素のうち、ベクトルであるものについては、点(0,0)を返す(pointList2)。
pointList2 = vectorList * isPoint
⑤pointList1とpointList2を足し算すると、vectorListの全要素を、すべて点オブジェクトに変換したものを得ることができる(pointListAll)
pointListAll = pointList1 + pointList2
⑥pointListAllを、いったん3次元にする(pointListAll3D)。
pointListAll3D = pointListAll + (0, 0, 0)
⑦各座標を並べて行列を作成する(matrix1)。
matrix1 = Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, pointListAll3D]]
⑧2次元ベクトルの場合には3行目をカットする(output)。
output = If[Product[Zip[δ ≟ 0, δ, Element[matrix1, 3]]] ≟ 0, matrix1, Take[matrix1, 1, 2]]
⑨outputを、vectorListのみで表したもの
If[Product[Zip[δ ≟ 0, δ, Element[Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, vectorList (¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], Vector[(0, 1)]], α, 1, Length[vectorList]])) + vectorList (¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], Vector[(0, 1)]], β, 1, Length[vectorList]]) + (0, 0, 0)]], 3]]] ≟ 0, Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, vectorList (¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], Vector[(0, 1)]], α, 1, Length[vectorList]])) + vectorList (¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], Vector[(0, 1)]], β, 1, Length[vectorList]]) + (0, 0, 0)]], Take[Transpose[Zip[{x(γ), y(γ), z(γ)}, γ, vectorList (¬(¬Sequence[Element[vectorList, α] ≟ Translate[Element[vectorList, α], Vector[(0, 1)]], α, 1, Length[vectorList]])) + vectorList (¬Sequence[Element[vectorList, β] ≟ Translate[Element[vectorList, β], Vector[(0, 1)]], β, 1, Length[vectorList]]) + (0, 0, 0)]], 1, 2]]
この方法なら、正しくオリジナルツールを作成することができた。以下では、ツールについて紹介する。
オリジナルツール「VtoM」
構文は、
VtoM[ <ベクトルのリスト> ]
である。
(追記)より簡便な方法
より簡便な方法を思いついたので、紹介する。
①ベクトルのリストに (0,0,0) を加えると、3次元の点のリストを得られる(pointList3D)。これだけで、点のリストであることを明確にできる。
pointList3D = vectorList + (0, 0, 0)
②各座標を並べて行列を作成する(matrix1)。
matrix1 = Transpose[Zip[{x(α), y(α), z(α)}, α, pointList3D]]
③2次元ベクトルの場合には3行目をカットする(output)。
output = If[Product[Zip[β ≟ 0, β, Element[matrix1, 3]]] ≟ 0, matrix1, Take[matrix1, 1, 2]]
④outputを、vectorListのみで表したもの
If[Product[Zip[β ≟ 0, β, Element[Transpose[Zip[{x(α), y(α), z(α)}, α, vectorList + (0, 0, 0)]], 3]]] ≟ 0, Transpose[Zip[{x(α), y(α), z(α)}, α, vectorList + (0, 0, 0)]], Take[Transpose[Zip[{x(α), y(α), z(α)}, α, vectorList + (0, 0, 0)]], 1, 2]]
この方法を用いたオリジナルツール「VtoM」
*1:他にも、ベクトルオブジェクトに{true}を掛けると、点オブジェクトのリストが返されることを利用して、
<オブジェクト> ≟ Element[ <オブジェクト> * {true}, 1 ]
とする方法もある。こちらは、オブジェクトが点ならばtrue、falseならばベクトルである。