%% Toolbox の依存関係を知るには
% MATLABのToolboxを使うときに前提となるToolboxが必要な場合があります。例えばComputer Vision ToolboxにはMATLABとImage Processing Toolboxが前提になっています。どのToolboxが前提となっているのか知りたい、というときに先日公開されたMATLAB Answersの回答「どのように MathWorks ツールボックス製品の依存関係を確認しますか？」で紹介されている製品要件ページが便利です。
% Toolbox毎に依存関係のあるToolboxが表形式でまとまっています。
%
%
% ただ、MATLAB芸を使って依存関係をもっと見やすく可視化できないか、考えてみました。
%
%% readtableでHTMLからテーブル形式で読み込み
% Webページの情報を読み取るのにwebread関数や使うことが多いですが、今回のような表形式だとreadtableが使えるんです。
% readtableがHTML形式に対応したのがR2021b、そしてR2022aでWebOptionsを入れられるようになり、文字エンコーディングを指定できるようになりました。
% それでは製品要件ページをreadtableで読み込んでみます。

% 製品要件ページのURL
url = "https://www.mathworks.com/support/requirements/product-requirements-platform-availability-list.html";

% HTMLの読み込む形式を指定
opts = detectImportOptions(url);
opts.TableSelector = "//TABLE"; % 最初の<table>タグを読み取り
opts.SelectedVariableNames = ["Product", "Required Products"]; % Detailsカラムは使用しないので読み込まない
tbl = readtable(url, opts);

% 先頭行を確認
head(tbl)

%
%% 読み込んだテーブルの詳細確認
% 製品要件ページの表をうまく読み込めていますが、「Required Products」の列に「↵」のような文字が含まれてしまっています。
% HTMLのリスト形式である<li>タグを分割する際に入ってしまったようですね。
% また、「↵」が4個になっているのと思いきや、SimBiologyがある91行目では、MATLABとStatistics and Machine Learning Toolboxの間に「↵」が1個だけになっています。

disp(tbl(91, :))

% これはHTMLの元ページが
% <li>MATLAB</li><li> Statistics and Machine Learning Toolbox</li>
% ではなく、
% <li>MATLAB<br> Statistics and Machine Learning Toolbox</li>
% と、段落の改行を表すHTMLの<br>タグが使われてしまっているためなんです。
% 読み込んだテーブルの「↵」コードを取り除く必要がありますね。
%
%% テーブルの前処理
% それでは「Required Products」を前処理していきます。
% 「Required Products」カラムは文字列のstring形式になっていますので、split関数で分割していきます。「↵」はnewline関数で抽出できます。

% テーブルの行毎に改行コードで分割し、空白行を削除する
tbl.ReqProd =  table2array(varfun(@(x) arrayfun(@(a) rmmissing(convertStringsToChars(split(a, newline))), x, 'UniformOutput', false), tbl(:, 2)));

% ここでvarfunやarrayfunを組み合わせて使いました。ベクトル演算に慣れないうちはfor文で書いてみるのも良いでしょう。下記のコメントを解除(「%」を削除)して実行してみてください。同じ結果が得られます。

% for n=1:height(tbl)   
%     tempText = split(tbl.("Required Products")(n), newline);
%     idx = tempText ~= "";
%     tbl.ReqProd{n} = convertStringsToChars(tempText(idx));
% end

% ここで「Required Products」カラムではなく「ReqProd」カラムを追加して分割したデータを格納しています。

head(tbl.ReqProd)

% 各行にセル配列として前提製品が格納されていることが分かりますね。
%
%% table.('カラム名')なのかい、table.カラム名なのかい、どっちなんだい！？
% ここで少し脱線します。
% さっきはtbl.("Required Products")でカラムのデータにアクセスしていましたが、今度はtbl.ReqProdでアクセスしています。
% table.('カラム名')なのかtable.カラム名なのか、どっちを使えば良いのか迷いますね。
% 先にReqProductsカラムで実験してみましょう。

head(tbl.('ReqProd')) % table.('カラム名')
head(tbl.("ReqProd")) % table.("カラム名")
head(tbl.ReqProd) % table.カラム名

% 「ReqProd」カラムだとtable.('カラム名')、table.("カラム名")、table.カラム名全てでいけますね。
% 次に「Required Products」カラムの場合を見てみます。

head(tbl.('Required Products')) % table.('カラム名')
head(tbl.("Required Products")) % table.("カラム名")

%

%head(tbl.Required Products) % table.カラム名

%
% 「Required Products」カラムの場合、table.カラム名でアクセスするとエラーになってしまいました。
% ドキュメント「table 内のデータへのアクセス」にありますが、R2019b から変数名と行名にスペースや非 ASCII 文字など任意の文字を入れられるようになりました。
% カラム名にスペースや日本語などのマルチバイト文字が入っている場合、table.('カラム名')やtable.("カラム名")を使うことができます。
%
%% digraph で有向グラフで可視化
% さて、それでは製品依存を可視化していきます。
% ここでdigraphを使って有向グラフ(矢印付きのグラフ)で描いていきます。

% グラフ表示用のテーブルを作成
% tbl.ReqProdを各行でセル配列の中身を展開する
edgeTbl = varfun(@(x) vertcat(x{:}), tbl(:, 3));
% カラム名をFun_ReqProdからReqProdにリネーム
edgeTbl = renamevars(edgeTbl, "Fun_ReqProd", "ReqProd");

% Productを各行でReqProdの長さごとに複製
cellT = rowfun(@(x, y) repmat(x, height(y{:}), 1), tbl, InputVariables=["Product", "ReqProd"], OutputFormat="cell");
edgeTbl.Product = vertcat(cellT{:});

% Productカラムを1列目に変更
edgeTbl = movevars(edgeTbl, 'Product', 'Before', 'ReqProd');

% MATLABをProductのカテゴリーに追加
edgeTbl.Product = categorical(edgeTbl.Product);
edgeTbl.Product = addcats(edgeTbl.Product, "MATLAB");
% アルファベット順にカテゴリーを並べ替え
edgeTbl.Product = reordercats(edgeTbl.Product);

% missingの行を削除
edgeTbl = rmmissing(edgeTbl, DataVariables="ReqProd"); 
edgeTbl.ReqProd = categorical(edgeTbl.ReqProd);

% ノードテーブルの作成
nodeTbl = tbl.Product;
nodeTbl(end+1, :) =  "MATLAB";

% 有向グラフの作成
diG = digraph(edgeTbl.Product, edgeTbl.ReqProd, [], nodeTbl);

% 有向グラフの可視化
impDig = centrality(diG, "indegree");
impDig(impDig >= 20) = 20;
impDig(impDig >= 10 &  impDig < 20) = 10;
impDig(impDig >= 5 &  impDig < 10) = 5;
impDig(impDig >= 1 &  impDig < 5) = 1;
diG.Nodes.Rank = impDig;
p = plot(diG,'NodeLabel', diG.Nodes.Name, 'Layout','force', 'ArrowSize', 6, 'NodeCData', diG.Nodes.Rank, 'MarkerSize', diG.Nodes.Rank+1);
ax = gca;
% 黒枠線の削除
ax.Box = 'off';
ax.XColor = 'none';
ax.YColor = 'none';
ax.Position = [0.0258823529411765 0.00122549019607843 0.956470588235294 0.97671568627451];

% どのToolboxがどの製品を前提としているのか、可視化できましたね。
%
%
%
%% どのToolboxがベースを支えている？
% digraphにはさらに便利な機能も。
% ワードクラウドで文字を可視化してみましょう。

wordcloud(edgeTbl.ReqProd)

% MATLABが一番多く、Simulinkが続くのは予想通り。さらにSignal Processing Toolboxがありますね。
%
%% 数値で見てみる
% 内向きの矢印数

indegArr = indegree(diG);

% 外向きの矢印数

outdegArr = outdegree(diG);

% 多い順にソート

[sortedRank, sortIdx] = sortrows(indegArr, 'descend');
table(sortedRank, diG.Nodes.Name(sortIdx))

% MATLAB、Simulinkが1、2位なのは予想通りですが、3位にSignal Processing Toolbox、4位にDSP System Toolboxと信号処理系がランクイン。
%
%% MATLAB以外で見てみる
% MATLAB が前提となったのは分かったので、それ以外を見やすくするように、グラフからMATLAB とSimulinkを除いてみます。
% subgraph関数で、グラフから部分グラフを抽出できます。

idx = nodeTbl ~= "MATLAB" & nodeTbl ~= "Simulink";
subG = subgraph(diG, idx);

% 有向グラフの可視化
plot(subG, 'NodeLabel', subG.Nodes.Name, 'Layout','circle', 'ArrowSize', 6)
ax = gca;
ax.Box = 'off';
ax.XColor = 'none';
ax.YColor = 'none';

% 実行結果の画像。Toolbox同士の依存関係が可視化できました。
%
%
%
%% 留意点
% このデモはR2023a時点のものです。今後システム要件ページが更新されることにより、この実行結果と合わなくなる可能性もあります。また、今回はシステム要件ページの「Details」カラムは考慮していません。実際には例えばDeep Learning Toolboxのモデルの学習(trainNetwork)でGPUを使用する場合はParallel Computing Toolboxが必要になりますので、「Required Products」カラムだけで見た場合と前提製品が変わることもあります。