同じような行列の最適化

4 views (last 30 days)
qrqr
qrqr on 5 Feb 2019
Commented: satoru on 7 Feb 2019
以下の変数があります。
x=[0:1:10]
a=[0,0,1,2,2,2,3,4,6,6,6]%青
b=[0,1,1,2,2,3,4,4,5,5,6]%赤
c=[0,0,2,2,3,4,4,5,6,6,6]%黄
plot(x,a,x,b,x,c)%xは時間
これらをグラフで表すと以下のようになります。
a,b,cそれぞれが0以上になる瞬間を合わせると
b=[0,0,1,1,2,2,3,4,4,5,5] %0を増やして一番右の6を消す
黄色のグラフを2ずらすと
c=[0,0,0,0,2,2,3,4,4,5,6]
4から7の間は3つのグラフが重なります。
この様にa,b,cのデータが一番重なる時間が長い期間(0~10の間で重なる合計が多ければ0~2と5~9のように間が重なってなくても平気です)をMATLABで計算させることはできますか?
a,b,c共に[0,0,0,0,2,2,3,4,4,5,6]一番左を増やすときは0、一番右を増やすときは6にします。
増やした分反対側の値を消します。
例)[0,0,0,0,2,2,3,4,4,5,6] → [0,0,0,2,2,3,4,4,5,6,6]や[0,0,0,0,0,2,2,3,4,4,5]は可能です。
[0,0,0,2,2,2,3,4,4,5,6]←途中を追加するのはできません。
※aの値は変更できません!!
実際は0~10000まであるので今回のように目で判断して求めることはできません。
宜しくお願いします。
MATLABのバージョンは2013bから最新までどれでもいいです。

Accepted Answer

satoru
satoru on 6 Feb 2019
要素数が10,000程度ということですので、最適化アルゴリズムを使わず、端からデータが一致している数をカウントしてもあまり時間はかからないかと思います。
試してみたサンプルコードは以下です。
x=[0:1:10];
a=[0,0,1,2,2,2,3,4,6,6,6];
b=[0,1,1,2,2,3,4,4,5,5,6];
c=[0,0,2,2,3,4,4,5,6,6,6];
dnb = search_min_delta_n(a, b)
dnc = search_min_delta_n(a, c)
function dn = search_min_delta_n(a, b)
n = size(a, 2) - 1;
b_ex = [zeros(1, n) b ones(1, n)*b(n + 1)];
d = zeros(1, n*2+1);
for ii = 1:n*2+1
b_tmp = b_ex(ii:ii+10);
m = 0;
for jj = 1:11
if a(jj) == b_tmp(jj)
m = m + 1;
end
end
d(ii) = m;
end
dn = (n+1) - find(d == max(d));
end
これにより、
dnb =
1
dnc =
2 1
が得られます。
この結果は、bについては1つずらすと最も重なる合計が多い、cについては1つあるいは2つずらすと最も重なる合計が多い、ということを意味しています。
cの1つずらした場合は意図している結果と異なるかもしれませんが、実際にaとcを1つずらしたものを並べてみると
[0,0,1,2,2,2,3,4,6,6,6] a
[0,0,0,2,2,3,4,4,5,6,6] c1つずらしたもの
であり、7ヶ所で一致し、2つずらしたものと一致している値の数は同じです。
いかがでしょうか。
  6 Comments
satoru
satoru on 7 Feb 2019
b、cの列数がaと異なることは想定していません。
search_min_delta_n.mの一行目で、
n = size(a, 2) - 1;
としてaの列数を取得しています。これが、bも同じであることを仮定しています。提案しているアルゴリズムは、同じ長さのaとbを用意した上で、aに対してbの両端をaの列数-1だけ拡張し、
a | [0,0,1,2,2,2,3,4,6,6,6]→ずらしながら一致数を数える
b_ex | [0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,4,5,5,6,6,6,6,6,6,6,6,6,6,6]←拡張したb
[0,1,1,2,2,3,4,4,5,5,6]←元のb
のようにずらしながら、aとbで一致している数を数え上げています。
これに対し、aとbの列数が異なるのであれば、
na = size(a, 2) - 1;
nb = size(b, 2) - 1;
としてa、b、それぞれの列数を取得した上で、
a | [0,0,1,2,2,2,3,4,6,6,6]→ずらしながら一致数を数える
b_ex | [0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,4,5,5,6,6,7,7,7,7,7,7,7,7,7,7,7]←拡張したb
^^^^^^^^^^^^^^^^^^^^^ <-aの列数分だけ拡張する-> ^^^^^^^^^^^^^^^^^^^^
とするように変更すれば良いと思います。
変更してみたソースコードは以下の通りです。
main2.m:
a=[0,0,1,2,2,2,3,4,6,6,6];
b=[0,1,1,2,2,3,4,4,5,5,6,6,7];
c=[0,0,1,1,2,2,3,4,4,5,6,6,6,7,7,7];
dnb = search_min_delta_n2(a, b)
dnc = search_min_delta_n2(a, c)
search_min_delta_n2.m:
function dn = search_min_delta_n2(a, b)
na = size(a, 2) - 1;
nb = size(b, 2) - 1;
b_ex = [zeros(1, na) b ones(1, na)*b(nb + 1)];
d = zeros(1, na+nb+1);
for ii = 1:na+nb+1
b_tmp = b_ex(ii:ii+na);
m = 0;
for jj = 1:11
if a(jj) == b_tmp(jj)
m = m + 1;
end
end
d(ii) = m;
end
dn = (na+1) - find(d == max(d));
end
とし、コマンドウィンドウにて
main2
で、新しいmain2.mを実行してみて下さい。
これで、aとbの列数が異なる場合でも対応できるかな、と思います。

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!