Expressions

概要

数式を記述するための機能を提供する。

  • ヘッダ
#include <tlnc/expressions.hpp>

関数一覧

いずれもtlnc名前空間に属する。 詳しい使い方は使い方を参照。

特に説明のない関数は、 引数としてdouble型やkv::interval<double>等の通常の値型を渡すと Genericの関数と同様の動作をする。 いずれの関数も引数として式を渡すと数式となる。

cos(Expr&&)
sin(Expr&&)
tan(Expr&&)
log(Expr&&)
pow(Base&&, Exponent&&)
prod(Expr1&&, Expr2&&)

Boost.uBLASのprodと同様な動作をする。 ベクトルや行列の積を計算する。

element_prod(Expr1&&, Expr2&&)

Boost.uBLASのelement_prodと同様な動作をする。 同じ大きさのベクトルや行列を渡すと要素ごとの積を計算する。

at<Is...>(Expr&&)

ベクトルや行列を返す式を受け取り、 式の評価結果からIs...要素を取り出す式を返す。 Is...が1個の時はベクトルを返す式を、 Is...が2個の時は行列を返す式を渡さなければならない。

c<T>(T&&)

定数関数を返す。 Tは何らかの値を表す型で、T::valueで保持している値を取得できるものとする。

変数一覧

いずれもtlnc名前空間に属する。 詳しい使い方は使い方を参照。

unspecified x<Is...>

std::size_t型の非型テンプレートパラメータIs...を受け取る変数テンプレート。 Is...が空の時は引数そのものを表し、 Is...が1個の時は引数として渡されるベクトルのある要素を表し、 Is...が2個の時は引数として渡される行列のある要素を指す。 Is...が3個以上の時はコンパイルエラーとなる。

unspecified _1

プレースホルダーを表す。同様の変数が_10まで定義されている。 使い方はプレースホルダーを参照。

unspecified holder<I>

プレースホルダーが10個で足りないときに使う。

使い方

呼び出し方についてはCallを、 微分についてはDerivativeを参照。

定数関数

\(2x\)の係数\(2\)のようなものも含めて、式内の全ての定数は定数関数とみなす。 つまり\(f(x) = 2x\)という関数は、

\[\begin{split}&f_1(x) = 2\\ &f_2(x) = x\\ &f(x) = f_1(x) \cdot f_2(x)\end{split}\]

のような関数の積だと考える。

定数関数はマクロかユーザー定義リテラルと関数の組み合わせによって記述する。 double型の定数かdouble型を要素とする区間を記述することができる。

マクロ

#include <tlnc/constant.hpp>

auto f = TLNC_C(1.0);
auto g = TLNC_I(1.0);
auto h = TLNC_I(1.0, 2.0);

fdouble型の定数1.0を返す関数、 gkv::interval<double>型の点区間\([1.0, 1.0]\)を返す関数、 hkv::interval<double>型の区間\([1.0, 2.0]\)を返す関数を表す。 TLNC_Cマクロに対してC_TLNC_Iマクロに対してI_という別名も定義される。

ユーザー定義リテラルと関数

ユーザー定義リテラルを用いると、(定数関数ではなく)定数を表す特殊なオブジェクトを作ることができる。 そのオブジェクトをtlnc::c関数に渡すと定数関数を生成することができるが、 実際には純粋な定数関数を生成する場合以外はtlnc::cを使わなくても期待した動作をする。

#include <bcl/literals.hpp>  // double型の定数を生成する
#include <cti/literals.hpp>  // double型の点区間を生成する
#include <cti/operators.hpp> // double型の区間を生成する

using bcl::literals;  // _dcリテラルを使えるようにする
using cti::literals;  // _diリテラルを使えるようにする
using cti::operators; // _dcリテラルに対するoperator,を使えるようにする

{
    // (定数関数ではない)定数
    auto f = 1.0_dc;           // 定数1.0
    auto g = 1.0_di;           // 点区間[1.0, 1.0]
    auto h = (1.0_dc, 2.0_dc); // 区間[1.0, 2.0]
}

{
    // 定数関数
    auto f = tlnc::c(1.0_dc);
    auto g = tlnc::c(1.0_di);
    auto h = tlnc::c((1.0_dc, 2.0_dc));
}

{
    // 関数
    using tlnc::x;

    auto f = 1.0_dc * x<>;
    auto g = tlnc::c(1.0_dc) * x<>;
}

関数を含む式

多項式\(f(x) = x^2 + 2x + 1\)は、関数powを用いて以下のように書ける。

using tlnc::x;
using tlnc::pow;

auto f = pow(x<>, 2_dc) + 2_dc * x<> + 1_dc;

\(g(x) = \cos(\sin(x))\)のように入れ子にすることもできる。

using tlnc::x;
using tlnc::cos;
using tlnc::sin;

auto g = cos(sin(x<>));

多変数関数

多変数関数は、ベクトルを受け取る関数として定義する。 例えば、\(f(x_0, x_1) = x_0 x_1 + \cos(\sin(x_0))\)は次のように定義する。

using tlnc::x;
using tlnc::cos;
using tlnc::sin;

auto f = x<0> * x<1> + cos(sin(x<0>));

x<0>は「引数として渡されたベクトルの0番目の要素を取り出す」という意味である。 element_prod()のようなベクトルを受け取る関数に引数を渡す時は、 element_prod(x<>, x<>)のようにx<>を使えばよい。 x<0, 0>のように書けば行列を受け取る関数も記述できる。

行列やベクトルはBoost uBLASのものを使うことを前提としている。

ベクトルや行列を返す関数

関数を,でつなぐとベクトルを返す関数を記述でき、 ベクトルを返す関数を,でつなぐと行列を返す関数を記述できる。

using bcl::literals;
using tlnc::x;

auto f = (x<>, 2.0_dc * x<>);
auto g = (f, (3.0_dc * x<>, 4.0_dc * x<>));

fgはそれぞれ

\[\begin{split}\begin{align} f(x)&=[x\;\;2x]^T\\ g(x)&= \left[ \begin{matrix} x & 2x\\ 3x & 4x \end{matrix} \right] \end{align}\end{split}\]

という関数を表す。 行列やベクトルはBoost uBLASのものを利用する。

プレースホルダー

プレースホルダーを使うと式の一部に仮の値のようなものを置いておき、 評価時に具体的な値に置き換えるということができる。 プレースホルダーはあらかじめtlnc::_1からtlnc::_10までが用意されていて、 それ以上必要な場合はtlnc::holder<I>を使うことができる。

#include <tlnc/call.hpp>
#include <bcl/tuple.hpp>

using tlnc::_1;
using tlnc::x;

auto f = _1 * x<>;

auto v = tlnc::call(f, bcl::make_tuple(1.0, 2.0));

関数fの定義の中にある_1がプレースホルダーである。 上のように呼び出すと評価時に_12.0に置き換えられる。 呼び出しの詳細についてはCallを参照。