連立代数方程式の求解
このトピックでは、Symbolic Math Toolbox™ を使用して連立方程式をシンボリックに求解する方法を説明します。このツールボックスでは数値とシンボリックの両方の方程式ソルバーが提供されています。数値ソルバーとシンボリック ソルバーの比較については、数値ソルバーまたはシンボリック ソルバーの選択を参照してください。
solve の出力の処理
次の連立方程式があり
これを と について解くことを考えます。はじめに、必要なシンボリック オブジェクトを作成します。
syms x y a
いくつかの方法で、solve の出力先を指定できます。1 つの方法は、2 つの出力を使って呼び出すことです。この呼び出しは次を返します。
[solx,soly] = solve(x^2*y^2 == 0, x-y/2 == a)
solx =
soly =
最初の方程式を に変更します。新しい連立方程式には、より多くの解があります。4 つの異なる解が生成されました。
[solx,soly] = solve(x^2*y^2 == 1, x-y/2 == a)
solx =
soly =
従属変数を指定していないので、solve は symvar を使って変数を特定します。
solve からの出力を代入するこの方法は、"小さな" 連立方程式に対しては、かなり有効です。たとえば、10 元 10 次の連立方程式がある場合、次のように入力するのは面倒で時間が掛かります。
[x1,x2,x3,x4,x5,x6,x7,x8,x9,x10] = solve(...)
この問題を解決するために、solve は、そのフィールドがそれぞれの解である構造体を出力できます。たとえば、連立方程式 u^2 - v^2 = a^2、u + v = 1、a^2 - 2*a = 3 を解きます。ソルバーは、その結果を構造体に格納して返します。
syms u v a S = solve(u^2 - v^2 == a^2, u + v == 1, a^2 - 2*a == 3)
S = struct with fields:
a: [2×1 sym]
u: [2×1 sym]
v: [2×1 sym]
a の解は、S の "a フィールド" に帰属します。
S.a
ans =
u と v の解も同様に解釈されます。これで、このフィールドとインデックスによる構造体 S の操作が可能になり、特定範囲の解にアクセスできます。たとえば、2 番目の解を調べるためには、次のステートメントを使用して、各フィールドの 2 番目の成分を取り出します。
s2 = [S.a(2),S.u(2),S.v(2)]
s2 =
次のステートメントは、各行が個々の方程式の解である、解の行列 M を作成します。
M = [S.a,S.u,S.v]
M =
solx と solyを消去して後で使えるようにします。
clear solx soly
連立線形方程式の求解
連立線形方程式は、行列の除算を使用して解くこともできます。たとえば、次の連立方程式を解きます。
clear u v x y syms u v x y eqns = [x + 2*y == u, 4*x + 5*y == v]; S = solve(eqns); sol = [S.x;S.y]
sol =
[A,b] = equationsToMatrix(eqns,x,y); z = A\b
z =
このように、sol と z は、結果が異なる変数に代入されていますが、同じ解です。
連立方程式の完全解を返す
solve は自動的には方程式のすべての解を返しません。すべての解を解のパラメーターおよび条件と共に返すには、オプション ReturnConditions を true に設定します。
次の連立方程式を考えます。
fimplicit を使用して連立方程式を可視化します。x 軸と y 軸の値を pi に換算して指定するため、a の axes を使用して axes ハンドルを取得します。-2*pi から 2*pi までの値のシンボリック配列 S を pi/2 の間隔で作成します。目盛りを S に設定するため、a のプロパティ XTick と YTick を使用します。x 軸と y 軸のラベルを設定するため、S を文字ベクトルに変換します。arrayfun を使用して S のすべての要素に char を適用し、T を返します。a のプロパティ XTickLabel と YTickLabel を T に設定します。
syms x y eqn1 = sin(x)+cos(y) == 4/5; eqn2 = sin(x)*cos(y) == 1/10; a = axes; fimplicit(eqn1,[-2*pi 2*pi],"b"); hold on grid on fimplicit(eqn2,[-2*pi 2*pi],"m"); L = sym(-2*pi:pi/2:2*pi); a.XTick = double(L); a.YTick = double(L); M = arrayfun(@char, L, UniformOutput=false); a.XTickLabel = M; a.YTickLabel = M; title("Plot of System of Equations") legend("sin(x)+cos(y) == 4/5","sin(x)*cos(y) == 1/10",... Location="best",AutoUpdate="off")

解は 2 つのプロットの交点にあります。これは、この方程式には反復する周期解があることを示しています。この連立方程式を解いてすべての解を求めるには、solve を使用し、ReturnConditions オプションを true に設定します。
S = solve(eqn1,eqn2,ReturnConditions=true)
S = struct with fields:
x: [2×1 sym]
y: [2×1 sym]
parameters: [z z1]
conditions: [2×1 sym]
solve は、x に対する解をもつ S.x、y に対する解をもつ S.y、解のパラメーターをもつ S.parameters、解の条件をもつ S.conditions の各フィールドから成る構造体 S を返します。1 つの解は S.x、S.y および S.conditions の同じインデックス番号をもつ要素により構成されます。したがって、S.x(1)、S.y(1) および S.conditions(1) により連立方程式の解の 1 つが構成されます。S.parameters のパラメーターはすべての解に表れる場合があります。
S にインデックス付けして、解、パラメーターおよび条件を返します。
S.x
ans =
S.y
ans =
S.parameters
ans =
S.conditions
ans =
条件下における連立方程式の求解
条件下で連立方程式を求解するには、solve への入力に条件を指定します。
前述の連立方程式において -2*pi から 2*pi の区間で x および y を求めます。scatter を使用して解をプロットに重ね合わせます。
Srange = solve(eqn1, eqn2, -2*pi < x, x < 2*pi, -2*pi < y, y < 2*pi, ReturnConditions=true);
scatter(Srange.x,Srange.y,"k")
solve によって返される解、パラメーター、条件の操作
solve によって返される解、パラメーター、条件を使用して、ある区間内またはその他の条件下における解を求めることができます。この節の目標は前節同様、検索範囲内で連立方程式を解くことですが、アプローチが異なります。ここでは条件を直接指定する代わりに、solve によって返されるパラメーターと条件を使用する方法を説明します。
連立方程式の完全解 S を求めるには、区間 -2*pi から 2*pi における x と y の値を求めます。そのためには、パラメーター S.parameters に対する解 S.x と S.y を、その区間内および条件 S.conditions 下において求めます。
区間内の x および y について求解する前に、assume を使用して S.conditions の条件を仮定し、返される解が条件を満たすようにします。1 番目の解に対する条件を仮定します。
assume(S.conditions(1))
S.x と S.y のパラメーターを求めます。
paramx = intersect(symvar(S.x),S.parameters)
paramx =
paramy = intersect(symvar(S.y),S.parameters)
paramy =
パラメーター paramx に対する x の 1 番目の解を求めます。
solparamx(1,:) = solve(S.x(1) > -2*pi, S.x(1) < 2*pi, paramx)
solparamx =
同様に、paramy に対する y の 1 番目の解を求めます。
solparamy(1,:) = solve(S.y(1) > -2*pi, S.y(1) < 2*pi, paramy)
solparamy =
assume を使用して S.conditions(1) によって設定された仮定を消去します。asumptions を呼び出して仮定が消去されていることを確認します。
assume(S.parameters,"clear")
assumptionsans = Empty sym: 1-by-0
2 番目の解に対する条件を仮定します。
assume(S.conditions(2))
パラメーター paramx および paramy に対する x と y の 2 番目の解を求めます。
solparamx(2,:) = solve(S.x(2) > -2*pi, S.x(2) < 2*pi, paramx)
solparamx =
solparamy(2,:) = solve(S.y(2) > -2*pi, S.y(2) < 2*pi, paramy)
solparamy =
paramx と paramy の 1 番目の行が連立方程式の 1 番目の解を構成し、2 番目の行が 2 番目の解を構成します。
paramx および paramy のこれらの値に対する x と y の値を求めるため、subs を使用して S.x および S.y の paramx と paramy に代入します。
solx(1,:) = subs(S.x(1), paramx, solparamx(1,:)); solx(2,:) = subs(S.x(2), paramx, solparamx(2,:))
solx =
soly(1,:) = subs(S.y(1), paramy, solparamy(1,:)); soly(2,:) = subs(S.y(2), paramy, solparamy(2,:))
soly =
solx および soly が x および y に対する 2 組の解である点に注目してください。連立方程式のすべての解は、solx と soly において可能な値すべての組み合わせからなる、2 組の点集合です。
scatter を使用してこれら 2 組の点集合をプロットします。方程式のプロットの上に重ね合わせます。予想どおり、解は 2 つの方程式のプロットの交点に表れます。
for i = 1:length(solx(1,:)) for j = 1:length(soly(1,:)) scatter(solx(1,i), soly(1,j), "k") scatter(solx(2,i), soly(2,j), "k") end end

シンボリックな結果の数値への変換
シンボリック計算は厳密な解を出しますが、数値計算は近似値を出します。この精度低下にもかかわらず、数値計算で使用するためにシンボリックな解を近似する数値に変換しなければならない場合があります。高精度な変換を行うには、関数vpaで提供される可変精度演算を使用します。標準的な精度でパフォーマンスを向上させるには、doubleを使用して倍精度値に変換します。
vpa を使用してシンボリック解 solx および soly を数値形に変換します。
solxvpa = vpa(solx)
solxvpa =
solyvpa = vpa(soly)
solyvpa =
複雑な結果の単純化によるパフォーマンスの改善
結果が複雑で solve が止まった場合、またはパフォーマンスを改善したい場合は、関数 solve で求めた方程式の解のトラブルシューティングを参照してください。