こんにちわ世界

これはGorgoniaでとても簡単な計算を行うための段階的なチュートリアルです。

私たちのゴールはGorgoniaのすべての配管を使用して簡単な操作を行うことです:

$ f(x,y) = x + y $

値は x = 2y = 5

どの様に動作するか

x + y = z の評価はグラフで表す事ができます:

graph LR; z[z] --> add(Round edge) add[+] --> x add[+] --> y

結果を計算する為に4つのステップを使います:

  • Gorgonia での様なグラフを作成する
  • nodes xy に幾つかのを設定する
  • gorgonia vm上でグラフを起動する
  • node zからvalueを取り出す *

グラフの作成

以下の方法で空の式グラフを作成します:

g := gorgonia.NewGraph()

ノードの作成

いくつかのノードを作成しそれらを ExprGraph に関連付けます。

var x, y, z *gorgonia.Node

プレースホルダの作成

xyはスカラー変数です。対応するノードは次のように作成できます:

x = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("x"))
y = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("y"))

関数は引数としてexprgraphを取ります; 結果のノードは自動的にグラフに関連付けられます。

次に加算演算子を作成します。この演算子は2つのノードを取り新しいノードzを返します:

if z, err = gorgonia.Add(x, y); err != nil {
        log.Fatal(err)
}

戻り値のノードzgzまたはAdd関数に渡されていない場合でもグラフには追加されます。

値の設定

z = x + y を表す ExprGraph ができました。ではxyにいくつかの値を割り当てます。

関数 Let を使います:

gorgonia.Let(x, 2.0)
gorgonia.Let(y, 2.5)

グラフの実行

グラフを実行して結果を計算するには VM をインスタンス化する必要があります。 TapeMachineを使いましょう:

machine := gorgonia.NewTapeMachine(g)
defer machine.Close()

そしてグラフの実行:

if err = machine.RunAll(); err != nil {
        log.Fatal(err)
}

2回目の実行が必要な場合vmオブジェクトのReset()メソッドを呼び出すことが必須です: machine.Reset()

値の取得

これでノードzが結果を保持します。 Valueを抽出するにはValue()メソッドを呼び出します:

fmt.Printf("%v", z.Value())

この場合float64を保持するinterface{}を返すz.Value().Data()を呼び出して、基になる”Go”値にアクセスすることもできます。

最終結果

package main

import (
        "fmt"
        "log"

        "gorgonia.org/gorgonia"
)

func main() {
        g := gorgonia.NewGraph()

        var x, y, z *gorgonia.Node
        var err error

        // define the expression
        x = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("x"))
        y = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("y"))
        if z, err = gorgonia.Add(x, y); err != nil {
                log.Fatal(err)
        }

        // create a VM to run the program on
        machine := gorgonia.NewTapeMachine(g)
        defer machine.Close()

        // set initial values then run
        gorgonia.Let(x, 2.0)
        gorgonia.Let(y, 2.5)
        if err = machine.RunAll(); err != nil {
                log.Fatal(err)
        }

        fmt.Printf("%v", z.Value())
}
$ go run main.go
4.5