<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki.swarma.org/index.php?action=history&amp;feed=atom&amp;title=%E6%B5%81%E7%BD%91%E7%BB%9C%E6%A0%B9%E6%8D%AE%E6%B5%81%E8%B7%9D%E7%A6%BB%E5%B5%8C%E5%85%A5%E7%A9%BA%E9%97%B4</id>
	<title>流网络根据流距离嵌入空间 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.swarma.org/index.php?action=history&amp;feed=atom&amp;title=%E6%B5%81%E7%BD%91%E7%BB%9C%E6%A0%B9%E6%8D%AE%E6%B5%81%E8%B7%9D%E7%A6%BB%E5%B5%8C%E5%85%A5%E7%A9%BA%E9%97%B4"/>
	<link rel="alternate" type="text/html" href="https://wiki.swarma.org/index.php?title=%E6%B5%81%E7%BD%91%E7%BB%9C%E6%A0%B9%E6%8D%AE%E6%B5%81%E8%B7%9D%E7%A6%BB%E5%B5%8C%E5%85%A5%E7%A9%BA%E9%97%B4&amp;action=history"/>
	<updated>2026-11-02T17:54:17Z</updated>
	<subtitle>本wiki的该页面的版本历史</subtitle>
	<generator>MediaWiki 1.35.0</generator>
	<entry>
		<id>https://wiki.swarma.org/index.php?title=%E6%B5%81%E7%BD%91%E7%BB%9C%E6%A0%B9%E6%8D%AE%E6%B5%81%E8%B7%9D%E7%A6%BB%E5%B5%8C%E5%85%A5%E7%A9%BA%E9%97%B4&amp;diff=34782&amp;oldid=prev</id>
		<title>13944556914：/* 参考文献 */</title>
		<link rel="alternate" type="text/html" href="https://wiki.swarma.org/index.php?title=%E6%B5%81%E7%BD%91%E7%BB%9C%E6%A0%B9%E6%8D%AE%E6%B5%81%E8%B7%9D%E7%A6%BB%E5%B5%8C%E5%85%A5%E7%A9%BA%E9%97%B4&amp;diff=34782&amp;oldid=prev"/>
		<updated>2024-05-21T08:31:55Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;参考文献&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;zh-Hans-CN&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;←上一版本&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;2024年5月21日 (二) 08:31的版本&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l377&quot; &gt;第377行：&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第377行：&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=参考文献=&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=参考文献=&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;references /&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;references /&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;category&lt;/del&gt;:&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;旧词条迁移&lt;/del&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;Category&lt;/ins&gt;:&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;待润色&lt;/ins&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>13944556914</name></author>
	</entry>
	<entry>
		<id>https://wiki.swarma.org/index.php?title=%E6%B5%81%E7%BD%91%E7%BB%9C%E6%A0%B9%E6%8D%AE%E6%B5%81%E8%B7%9D%E7%A6%BB%E5%B5%8C%E5%85%A5%E7%A9%BA%E9%97%B4&amp;diff=15512&amp;oldid=prev</id>
		<title>小趣木木：创建页面，内容为“我们的'''目的是根据流网络的流距离（[http://wiki.swarma.net/index.php/%E5%9F%BA%E4%BA%8E%E9%A9%AC%E5%B0%94%E5%8F%AF%E5%A4%AB%E9%93%BE%E7%9A%84…”</title>
		<link rel="alternate" type="text/html" href="https://wiki.swarma.org/index.php?title=%E6%B5%81%E7%BD%91%E7%BB%9C%E6%A0%B9%E6%8D%AE%E6%B5%81%E8%B7%9D%E7%A6%BB%E5%B5%8C%E5%85%A5%E7%A9%BA%E9%97%B4&amp;diff=15512&amp;oldid=prev"/>
		<updated>2020-10-16T11:43:15Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“我们的&amp;#039;&amp;#039;&amp;#039;目的是根据&lt;a href=&quot;/index.php/%E6%B5%81%E7%BD%91%E7%BB%9C&quot; title=&quot;流网络&quot;&gt;流网络&lt;/a&gt;的&lt;a href=&quot;/index.php/%E6%B5%81%E8%B7%9D%E7%A6%BB&quot; title=&quot;流距离&quot;&gt;流距离&lt;/a&gt;（[http://wiki.swarma.net/index.php/%E5%9F%BA%E4%BA%8E%E9%A9%AC%E5%B0%94%E5%8F%AF%E5%A4%AB%E9%93%BE%E7%9A%84…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;我们的'''目的是根据[[流网络]]的[[流距离]]（[http://wiki.swarma.net/index.php/%E5%9F%BA%E4%BA%8E%E9%A9%AC%E5%B0%94%E5%8F%AF%E5%A4%AB%E9%93%BE%E7%9A%84%E6%B5%81%E7%BD%91%E7%BB%9C%E5%88%86%E6%9E%90 平均首达时间矩阵L]）矩阵，将整个网络嵌入到一个欧氏空间里面去，使得任意两点的欧氏距离尽量靠近他们的流距离.&amp;lt;ref name=&amp;quot;ENA&amp;quot;&amp;gt;{{cite journal | last = Peiteng Shi | first =  Xiaohan Huang | date = 2015 | title = A Geometric Representation of Collective Attention Flows | journal = PLOS ONE}}&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;Big&amp;quot;&amp;gt;{{cite journal | last = Shavitt Y | first =  Tankel T | date = 2004 | title =  Big-bang simulation for embedding network distances in euclidean space | journal =  IEEE/ACM Transactions on Networking (TON)}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
=原理解析=&lt;br /&gt;
给定某流网络，假想网络中各节点两两之间用弹簧相互连接，嵌入要做的即调整弹簧，使其松弛长度等于流距离。初始时各节点在欧式空间的坐标完全随机，以此我们可以计算节点两两之间的欧式距离。如果两节点间的流距离大于相应的欧式距离，表示弹簧被压缩了，那么我们应该拉伸这两节点间的弹簧；反之，我们应该压缩该弹簧。具体拉伸或者压缩多少取决于弹簧系数k及流距离和欧式距离的偏差x，即形变量=k*x。我们用该形变量去更新相应的节点欧式位置。反复这一过程，直至收敛。（注：实际运用之，我们常常不考虑流网络的源和汇节点，即流距离矩阵中不需要含有源和汇的项）&lt;br /&gt;
&lt;br /&gt;
=嵌入程序（Matlab版本）=&lt;br /&gt;
==初始准备==&lt;br /&gt;
此处程序没有考虑流矩阵中无穷大的情况&lt;br /&gt;
===输入变量流距离矩阵-flow_distance,节点编号-nodes_num，嵌入维数dim===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dim=10;&lt;br /&gt;
max_distance=max(max(flow_distance));&lt;br /&gt;
max_x=max_distance;&lt;br /&gt;
max_y=max_x;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===%为每个节点生成随机位置===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
initial_pos=[];&lt;br /&gt;
for i=1:length(nodes_num) &lt;br /&gt;
    tmp=[];&lt;br /&gt;
    for j=1:dim&lt;br /&gt;
    tmp=[tmp max_x-2*max_x*rand(1)];&lt;br /&gt;
    end&lt;br /&gt;
initial_pos=[initial_pos;tmp];&lt;br /&gt;
end   &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==第一步优化，按照欧氏距离和流距离的差别大小受力==&lt;br /&gt;
===开始运动===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
current_pos=initial_pos; &lt;br /&gt;
iterations=1; &lt;br /&gt;
complete_temperature_iterations = 0;&lt;br /&gt;
current_target= compute_distance(initial_pos,flow_distance );&lt;br /&gt;
basic_size=20;&lt;br /&gt;
target=[];&lt;br /&gt;
all_temperature=[];&lt;br /&gt;
probility=[];&lt;br /&gt;
&lt;br /&gt;
while iterations&amp;lt; 200&lt;br /&gt;
    iterations&lt;br /&gt;
    %-------------产生新的坐标-------------%&lt;br /&gt;
    new_pos=[];&lt;br /&gt;
    distance_matrix=compute_distance_matrix(current_pos);&lt;br /&gt;
    k=1.0000e-0;&lt;br /&gt;
    for i=1:size(current_pos,1)&lt;br /&gt;
        %计算每一个节点受到的合力&lt;br /&gt;
        %计算节点到其他节点距离和流距离的差值&lt;br /&gt;
        diff_distance=(distance_matrix(i,:)-flow_distance(i,:))';&lt;br /&gt;
        force_direction=-1*(repmat(current_pos(i,:),size(current_pos,1),1)-current_pos);&lt;br /&gt;
        force_direction=force_direction./repmat(sqrt(sum(force_direction.^2,2)),1,size(current_pos,2)) ;&lt;br /&gt;
        force_direction(isnan(force_direction))=0;&lt;br /&gt;
&lt;br /&gt;
        force_vector=diff_distance;&lt;br /&gt;
        final_force_vector=force_direction.*repmat(force_vector,1,size(current_pos,2));&lt;br /&gt;
        all_force=sum(final_force_vector,1)/length(diff_distance);&lt;br /&gt;
        new_pos=[new_pos;current_pos(i,:)+all_force*k];&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
     %-------------比较新的位置与原来的位置-------------%&lt;br /&gt;
     current_distance=compute_distance(current_pos,flow_distance);&lt;br /&gt;
     new_distance=compute_distance(new_pos,flow_distance);&lt;br /&gt;
     diff = abs(current_distance - new_distance);&lt;br /&gt;
     target=[target;current_distance];&lt;br /&gt;
       &lt;br /&gt;
        if complete_temperature_iterations &amp;gt;= 10&lt;br /&gt;
            temperature = cooling_rate*temperature;&lt;br /&gt;
            complete_temperature_iterations = 0;&lt;br /&gt;
        end&lt;br /&gt;
       iterations = iterations + 1;&lt;br /&gt;
       complete_temperature_iterations = complete_temperature_iterations + 1;&lt;br /&gt;
       current_pos=new_pos;&lt;br /&gt;
        &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===第二步优化，按照每个节点失真程度大小受力===&lt;br /&gt;
===开始运动===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
initial_pos=new_pos; &lt;br /&gt;
&lt;br /&gt;
iterations=1; &lt;br /&gt;
complete_temperature_iterations = 0;&lt;br /&gt;
&lt;br /&gt;
current_target= compute_distance(initial_pos,flow_distance );&lt;br /&gt;
cooling_rate=0.9;&lt;br /&gt;
basic_size=20;&lt;br /&gt;
target=[];&lt;br /&gt;
all_temperature=[];&lt;br /&gt;
probility=[];&lt;br /&gt;
while iterations&amp;lt; 200&lt;br /&gt;
    iterations&lt;br /&gt;
   &lt;br /&gt;
    %-------------产生新的坐标-------------%&lt;br /&gt;
    new_pos=[];&lt;br /&gt;
   &lt;br /&gt;
    distance_matrix=compute_distance_matrix(current_pos);&lt;br /&gt;
    distortion=distance_matrix./flow_distance-1;&lt;br /&gt;
    distortion(isnan(distortion))=0;&lt;br /&gt;
    k=30.0000e-0;&lt;br /&gt;
    for i=1:size(current_pos,1)&lt;br /&gt;
        %计算每一个节点受到的合力&lt;br /&gt;
        %计算节点到其他节点距离和流距离的差值&lt;br /&gt;
        diff_distance=distortion(:,i);&lt;br /&gt;
        force_direction=-1*(repmat(current_pos(i,:),size(current_pos,1),1)-current_pos);&lt;br /&gt;
        force_direction=force_direction./repmat(sqrt(sum(force_direction.^2,2)),1,size(current_pos,2)) ;&lt;br /&gt;
        force_direction(isnan(force_direction))=0;&lt;br /&gt;
        force_vector=diff_distance;&lt;br /&gt;
        final_force_vector=force_direction.*repmat(force_vector,1,size(current_pos,2));&lt;br /&gt;
        all_force=sum(final_force_vector,1)/length(diff_distance);&lt;br /&gt;
        new_pos=[new_pos;current_pos(i,:)+all_force*k];&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
     %-------------比较新的位置与原来的位置-------------%&lt;br /&gt;
     &lt;br /&gt;
     current_distance=compute_distance(current_pos,flow_distance);&lt;br /&gt;
     new_distance=compute_distance(new_pos,flow_distance);&lt;br /&gt;
     diff = abs(current_distance - new_distance);&lt;br /&gt;
     target=[target;current_distance];&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
       &lt;br /&gt;
     iterations = iterations + 1;&lt;br /&gt;
     &lt;br /&gt;
 &lt;br /&gt;
     all_temperature=[all_temperature;temperature];&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==计算拟合效果==&lt;br /&gt;
===横轴是流距离，纵轴是欧式距离===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
figure&lt;br /&gt;
tmp=bone_L;&lt;br /&gt;
tmp(logical(eye(size(bone_L,1))))=1;&lt;br /&gt;
tmp_L=flow_distance(find(tmp&amp;gt;0));&lt;br /&gt;
tmp_dis=distance_matrix(find(tmp&amp;gt;0));&lt;br /&gt;
plot(tmp_L(:),tmp_dis(:),'.')&lt;br /&gt;
hold on&lt;br /&gt;
plot([0; max([max(tmp_dis(:)) max(tmp_dis(:))])],[0;max([max(tmp_dis(:)) max(tmp_dis(:))])],'r-')&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===平均失真程度===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
distortion=tmp_dis./tmp_L;&lt;br /&gt;
distortion(isnan(distortion))=0;&lt;br /&gt;
&lt;br /&gt;
distortion(find(distortion&amp;lt;1&amp;amp;distortion&amp;gt;0))=1./distortion(find(distortion&amp;lt;1&amp;amp;distortion&amp;gt;0));&lt;br /&gt;
average_distortion=sum(sum(distortion))/length(find(distortion&amp;gt;0))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==中间计算距离的函数==&lt;br /&gt;
===现在距离与流距离的总差值===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function [ target_distance ] = compute_distance(new_pos,flow_distance )&lt;br /&gt;
%UNTITLED Summary of this function goes here&lt;br /&gt;
%Detailed explanation goes here&lt;br /&gt;
new_distance_matrix=compute_distance_matrix(new_pos);&lt;br /&gt;
target_distance=sum(sum((new_distance_matrix-flow_distance).^2));&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===根据节点坐标，计算节点之间距离===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function [ distance_matrix] = compute_distance_matrix( nodes )&lt;br /&gt;
%UNTITLED3 Summary of this function goes here&lt;br /&gt;
%   Detailed explanation goes here&lt;br /&gt;
distance_matrix=zeros(size(nodes,1),size(nodes,1));&lt;br /&gt;
for i=1:size(nodes,1)&lt;br /&gt;
    for j=i+1:size(nodes,1)&lt;br /&gt;
    distance_matrix(i,j)=sqrt((nodes(i,1)-nodes(j,1))^2+(nodes(i,2)-nodes(j,2))^2);&lt;br /&gt;
    distance_matrix(j,i)= distance_matrix(i,j);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
flow_distance=distance_matrix;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=嵌入程序（python版本）=&lt;br /&gt;
==输入参数==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
def spring_algorithm(_c, _dim):&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
_c：'''去掉源和汇节点'''的流距离矩阵，且默认已经将流距离无穷大的节点做处理了&lt;br /&gt;
&lt;br /&gt;
_dim：嵌入维数&lt;br /&gt;
==初始化==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# 最大小幅变化次数（可弹性调整）&lt;br /&gt;
max_count = 10&lt;br /&gt;
&lt;br /&gt;
# 弹簧系数（可弹性调整，一般取在(0,1)之间，且k1&amp;gt;k2）&lt;br /&gt;
k1, k2 = [0.8, 0.5]&lt;br /&gt;
    &lt;br /&gt;
# 阈值（可弹性调整， 依据具体问题而定）&lt;br /&gt;
threshold1, threshold2 = [0.05, 0.01]&lt;br /&gt;
    &lt;br /&gt;
# 各节点初始位置（dim维）&lt;br /&gt;
initial_pos = np.random.rand(_c.shape[0], _dim)  # [0, 1)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step1 按照欧氏距离和流距离的差别大小受力（快速调整）==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# step1 按照欧氏距离和流距离的差别大小受力&lt;br /&gt;
total_pos_mat = np.mat(initial_pos)&lt;br /&gt;
&lt;br /&gt;
t1 = 0&lt;br /&gt;
# 连续小幅度变化的次数&lt;br /&gt;
small_count1 = 0&lt;br /&gt;
# 与真实流距离的误差&lt;br /&gt;
error_list = []&lt;br /&gt;
# 上一次迭代的总距离误差&lt;br /&gt;
last_distance_sum_error = float(&amp;quot;inf&amp;quot;)&lt;br /&gt;
while True:&lt;br /&gt;
    print '距离差受力第%d次迭代' % t1&lt;br /&gt;
    for _i in range(_c.shape[0]):&lt;br /&gt;
        node_i_pos_mat = total_pos_mat[_i]&lt;br /&gt;
        repeat_node_i_pos_mat = np.matlib.repmat(node_i_pos_mat, _c.shape[0], 1)  # 重复len(_c)*1次&lt;br /&gt;
&lt;br /&gt;
        ##### 节点至其它节点的欧式距离euclidean_distance #####&lt;br /&gt;
        distance_offset_mat = repeat_node_i_pos_mat - total_pos_mat  # 当前节点i与其它节点实际位置偏移矩阵&lt;br /&gt;
        dis_square = np.multiply(distance_offset_mat, distance_offset_mat)  # 对应元素相乘&lt;br /&gt;
        euclidean_distance = np.mat(np.sqrt(np.sum(dis_square, 1)))  # 列向量：当前节点到其余所有节点（包括自己）的欧式距离&lt;br /&gt;
&lt;br /&gt;
        # 欧式距离和流距离的偏差行向量，即弹簧形变量x&lt;br /&gt;
        diff_distance = np.mat(_c[_i, :] - euclidean_distance.T)&lt;br /&gt;
&lt;br /&gt;
        # 防止除以该向量中的0元素出现Nan&lt;br /&gt;
        modifier_euclidean_distance = np.ones((_c.shape[0], 1)) - np.sign(euclidean_distance) + euclidean_distance&lt;br /&gt;
&lt;br /&gt;
        # 受力方向:单位向量 当前节点距其余节点的距离向量/|当前节点距其余节点的距离向量|&lt;br /&gt;
        direction = distance_offset_mat / modifier_euclidean_distance&lt;br /&gt;
&lt;br /&gt;
        ##### 距离差受力矢量 F = k*x*direction #####&lt;br /&gt;
        force = np.multiply(diff_distance.T, direction) * k1&lt;br /&gt;
&lt;br /&gt;
        ##### 位置调整 #####&lt;br /&gt;
        sum_force = np.sum(force, 0)&lt;br /&gt;
        total_pos_mat[_i] += np.divide(sum_force, _c.shape[0]).astype(np.float64)&lt;br /&gt;
&lt;br /&gt;
        ##### 误差项 #####&lt;br /&gt;
        node_i_error = np.sum(np.multiply(diff_distance, diff_distance))&lt;br /&gt;
        error_list.append(node_i_error)&lt;br /&gt;
&lt;br /&gt;
    sum_distance_error = sum(error_list)&lt;br /&gt;
    print sum_distance_error&lt;br /&gt;
    if abs(last_distance_sum_error - sum_distance_error) &amp;lt;= threshold1:&lt;br /&gt;
            small_count1 += 1&lt;br /&gt;
            if small_count1 &amp;gt;= max_count:&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
    t1 += 1&lt;br /&gt;
    last_distance_sum_error = sum_distance_error&lt;br /&gt;
    error_list = []&lt;br /&gt;
&amp;lt;/syntaxhighlight &amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Step2 按照每个节点失真程度大小受力（微调）==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# step2 按照每个节点失真程度大小受力&lt;br /&gt;
t2 = 0&lt;br /&gt;
# 连续小幅度变化的次数&lt;br /&gt;
small_count2 = 0&lt;br /&gt;
# 失真度误差&lt;br /&gt;
distortion_list = []&lt;br /&gt;
# 上一次迭代的总失真度误差&lt;br /&gt;
last_sum_distortion_error = float(&amp;quot;inf&amp;quot;)&lt;br /&gt;
while True:&lt;br /&gt;
    print '失真度受力第%d次迭代' % t2&lt;br /&gt;
    for _i in range(_c.shape[0]):&lt;br /&gt;
        node_i_pos_mat = total_pos_mat[_i]&lt;br /&gt;
        repeat_node_i_pos_mat = np.matlib.repmat(node_i_pos_mat, _c.shape[0], 1)  # 重复len(_c)*1次&lt;br /&gt;
&lt;br /&gt;
        ##### 节点至其它节点的欧式距离euclidean_distance #####&lt;br /&gt;
        distance_offset_mat = repeat_node_i_pos_mat - total_pos_mat  # 当前节点i与其它节点实际位置差距矩阵&lt;br /&gt;
        dis_square = np.multiply(distance_offset_mat, distance_offset_mat)  # 对应元素相乘&lt;br /&gt;
        euclidean_distance = np.mat(np.sqrt(np.sum(dis_square, 1)))  # 列向量：当前节点到其余所有节点（包括自己）的欧式距离&lt;br /&gt;
&lt;br /&gt;
        # 防止除以该向量中的0元素出现Nan&lt;br /&gt;
        modifier_euclidean_distance = np.ones((_c.shape[0], 1)) - np.sign(euclidean_distance) + euclidean_distance&lt;br /&gt;
&lt;br /&gt;
        # 失真度=max(_c[_i] / modifier_euclidean_distance, modifier_euclidean_distance / _c[_i])&lt;br /&gt;
        # 这里为方便，只采用 失真度=_c[_i] / modifier_euclidean_distance&lt;br /&gt;
        distortion_ratio = _c[_i, :] / modifier_euclidean_distance.T&lt;br /&gt;
        modifier_distortion = np.ones((1, _c.shape[0])) - np.sign(distortion_ratio) + distortion_ratio - 1&lt;br /&gt;
&lt;br /&gt;
        # 受力方向:单位向量 当前节点距其余节点的距离向量/\当前节点距其余节点的距离向量\&lt;br /&gt;
        direction = distance_offset_mat / modifier_euclidean_distance&lt;br /&gt;
&lt;br /&gt;
        ##### 失真度受力矢量 #####&lt;br /&gt;
        force = np.multiply(modifier_distortion.T, direction) * k2&lt;br /&gt;
&lt;br /&gt;
        ##### 位置调整 #####&lt;br /&gt;
        sum_force = np.sum(force, 0)&lt;br /&gt;
        total_pos_mat[_i] += np.divide(sum_force, _c.shape[0]).astype(np.float64)&lt;br /&gt;
&lt;br /&gt;
        ##### 误差项 #####&lt;br /&gt;
        node_i_error = np.sum(np.multiply((distortion_ratio - 1), (distortion_ratio - 1)))&lt;br /&gt;
        distortion_list.append(node_i_error)&lt;br /&gt;
&lt;br /&gt;
    sum_distortion_error = sum(distortion_list)&lt;br /&gt;
    print sum_distortion_error&lt;br /&gt;
&lt;br /&gt;
    if abs(last_sum_distortion_error - sum_distortion_error) &amp;lt;= threshold2:&lt;br /&gt;
            small_count2 += 1&lt;br /&gt;
            if small_count2 &amp;gt;= max_count:&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
    t2 += 1&lt;br /&gt;
    last_sum_distortion_error = sum_distortion_error&lt;br /&gt;
    distortion_list = []&lt;br /&gt;
&lt;br /&gt;
return total_pos_mat&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==测试样例==&lt;br /&gt;
===思路===&lt;br /&gt;
随机生成n个dim维欧式空间中的点，计算各点间的欧式距离得到n*n维欧式距离矩阵，以此当作c矩阵输入到弹簧算法中，得到n个dim维嵌入向量。若dim&amp;gt;2,则降维到2维，可视化前后两种点坐标表示，比较&lt;br /&gt;
===程序===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
n, dim = 10, 2&lt;br /&gt;
# n各点初始位置（2维）&lt;br /&gt;
initial_pos = np.random.rand(n, dim)  # [0, 1)&lt;br /&gt;
plt.subplot(121)&lt;br /&gt;
plt.title('original position')&lt;br /&gt;
plt.plot(initial_pos[:, 0], initial_pos[:, 1], 'ro')&lt;br /&gt;
for i, (_x, _y) in enumerate(zip(initial_pos[:, 0], initial_pos[:, 1])):&lt;br /&gt;
    plt.text(_x, _y, i)&lt;br /&gt;
&lt;br /&gt;
# 各节点间的欧式距离&lt;br /&gt;
edistance_list = []&lt;br /&gt;
for i in range(n):&lt;br /&gt;
    distance_offset_vec = initial_pos[i] - initial_pos  # 当前节点i与所有节点（包括自己）欧式位置差距&lt;br /&gt;
    dis_square = np.multiply(distance_offset_vec, distance_offset_vec)  # 对应元素相乘&lt;br /&gt;
    edistance = np.sqrt(np.sum(dis_square, 1)).T.tolist()  # 行向量&lt;br /&gt;
    edistance_list.append(edistance)&lt;br /&gt;
edistance_matrix = np.mat(edistance_list)&lt;br /&gt;
&lt;br /&gt;
# 嵌入（此处采用迭代500次作为终止条件，也可换成采用阈值，但是需要手动调整大小）&lt;br /&gt;
embed_vec = spring_algorithm(edistance_matrix, 2)&lt;br /&gt;
&lt;br /&gt;
plt.subplot(122)&lt;br /&gt;
plt.title('embedding position')&lt;br /&gt;
plt.plot(embed_vec[:, 0], embed_vec[:, 1], 'bo')&lt;br /&gt;
for i, (_x, _y) in enumerate(zip(embed_vec[:, 0], embed_vec[:, 1])):&lt;br /&gt;
    plt.text(_x, _y, i)&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===结果===&lt;br /&gt;
结果如下：&lt;br /&gt;
&lt;br /&gt;
[[File:figure.png|600px]]&lt;br /&gt;
&lt;br /&gt;
可以看到原始图和嵌入图非常相似，这证明弹簧算法的正确性。&lt;br /&gt;
&lt;br /&gt;
'''注意：'''两幅图之间可能存在平移、旋转、对称线性变换关系，但是这属于正常现象。（要想完全吻合，需要加入摩擦系数）&lt;br /&gt;
&lt;br /&gt;
=补充：[[Deepwalk|Deepwalk方式嵌入]]=&lt;br /&gt;
请参考[[Word2Vec与流网络]]&lt;br /&gt;
&lt;br /&gt;
=参考文献=&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
[[category:旧词条迁移]]&lt;/div&gt;</summary>
		<author><name>小趣木木</name></author>
	</entry>
</feed>