Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • lamp/cs206
  • bwermeil/cs206-2020
  • zabifade/cs206-2020
  • cauderan/cs206-2020
  • malonga/cs206-2020
  • dumoncel/cs206
  • bounekhe/cs206
  • bergerault/cs206
  • flealsan/cs206
  • hsu/cs206
  • mouchel/cs206
  • vebraun/cs206
  • vcanard/cs206
  • ybelghmi/cs206
  • belghmi/cs206
  • bousbina/cs206
  • waked/cs206
  • gtagemou/cs206
  • arahmoun/cs206
  • elhachem/cs206
  • benrahha/cs206
  • benslima/cs206
22 results
Show changes
Showing
with 0 additions and 3624 deletions
labs/lab4-barnes-hut-simulation/force-components.png

9.55 KiB

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="force_components.svg"
inkscape:export-filename="C:\cygwin\home\axel22\workspaces\scala\parprog\statements\barneshut\force-components.png"
inkscape:export-xdpi="43.470001"
inkscape:export-ydpi="43.470001">
<defs
id="defs4">
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7470"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7472" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker6528"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path6530"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker5832"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path5834" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4718"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4720" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker4622"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path4624"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4228"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4231"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="596.83099"
inkscape:cy="659.30507"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1600"
inkscape:window-height="877"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4142"
cx="269.28571"
cy="190.21935"
r="13.141105" />
<circle
r="13.141105"
cy="470.63928"
cx="802.48016"
id="circle4144"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="267.72015"
y="150.9595"
id="text4146"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4148"
x="267.72015"
y="150.9595">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4150">1</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text4152"
y="460.49185"
x="837.86316"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="460.49185"
x="837.86316"
id="tspan4154"
sodipodi:role="line">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4158">2</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text4160"
y="178.65207"
x="113.20886"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="178.65207"
x="113.20886"
id="tspan4162"
sodipodi:role="line">(x<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4180">1</tspan>,y<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4178">1</tspan>)</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="817.0473"
y="529.71088"
id="text4182"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4184"
x="817.0473"
y="529.71088">(x<tspan
id="tspan4186"
style="font-size:64.99999762%;baseline-shift:sub">2</tspan>,y<tspan
id="tspan4188"
style="font-size:64.99999762%;baseline-shift:sub">2</tspan>)</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4622)"
d="m 269.71073,191.71224 0,272.93917"
id="path4190"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.90697932;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart)"
d="m 782.93078,471.122 -512.2099,0"
id="path4192"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="452.44324"
y="517.38312"
id="text4182-2"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4184-5"
x="452.44324"
y="517.38312">x<tspan
id="tspan4186-4"
style="font-size:64.99999762%;baseline-shift:sub">2</tspan>-x<tspan
id="tspan4188-5"
style="font-size:64.99999762%;baseline-shift:sub">1</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text4614"
y="380.34897"
x="152.27205"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="380.34897"
x="152.27205"
id="tspan4616"
sodipodi:role="line">y<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4618">2</tspan>-y<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4620">1</tspan></tspan></text>
<path
inkscape:connector-curvature="0"
id="path4716"
d="M 269.71073,191.71224 791.91605,462.45778"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4718)"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="611.58893"
y="349.7601"
id="text5130"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5132"
x="611.58893"
y="349.7601">distance</tspan></text>
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path5830"
d="m 258.28216,197.42653 0,113.16557"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:9, 3;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker5832)" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:9, 3;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker6528)"
d="m 258.28216,311.71224 228.57143,-2.54872"
id="path6526"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path7468"
d="M 280.42502,182.42653 496.85359,297.02067"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:9, 3;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker7470)" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="400"
y="223.07649"
id="text7888"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7890"
x="400"
y="223.07649">F</tspan></text>
<text
sodipodi:linespacing="125%"
id="text7892"
y="266.64792"
x="202.85715"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="266.64792"
x="202.85715"
id="tspan7894"
sodipodi:role="line">F<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan7896">y</tspan></tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="356.42859"
y="354.50507"
id="text7898"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7900"
x="356.42859"
y="354.50507">F<tspan
id="tspan7902"
style="font-size:64.99999762%;baseline-shift:sub">x</tspan></tspan></text>
</g>
</svg>
labs/lab4-barnes-hut-simulation/net-force.png

7.49 KiB

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="net-force.svg"
inkscape:export-filename="C:\cygwin\home\axel22\workspaces\scala\parprog\statements\barneshut\net-force.png"
inkscape:export-xdpi="44.869999"
inkscape:export-ydpi="44.869999">
<defs
id="defs4">
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4222"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:0.50289019;fill:#000000;fill-opacity:0.50289019"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4224" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4214"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4216" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4208"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4210" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker12608"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path12610"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker11876"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path11878"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker10168"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path10170"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7470"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7472" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker4622"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path4624"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4228"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4231"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="742.82023"
inkscape:cy="615.35072"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1600"
inkscape:window-height="877"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path10486"
d="M 281.85359,190.99796 1066.8536,329.87782"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,24;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4142"
cx="269.28571"
cy="190.21935"
r="13.141105" />
<circle
r="13.141105"
cy="332.01859"
cx="1071.6188"
id="circle4144"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="267.72015"
y="162.38808"
id="text4146"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4148"
x="267.72015"
y="162.38808">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4150">1</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text4152"
y="360.44257"
x="1098.4303"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="360.44257"
x="1098.4303"
id="tspan4154"
sodipodi:role="line">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4158">2</tspan></tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4622)"
d="m 259.71073,187.42653 257.14285,45.7963"
id="path4190"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path5830"
d="M 273.99645,200.28367 659.71073,696.30638"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,24;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="724.85712"
y="443.07648"
id="text7888"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7890"
x="724.85712"
y="443.07648">F<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan10448">net</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text7892"
y="192.36221"
x="402.85715"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="192.36221"
x="402.85715"
id="tspan7894"
sodipodi:role="line">F<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan7896">21</tspan></tspan></text>
<path
sodipodi:nodetypes="cc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:7.83889103, 3.91944551;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker10168)"
d="M 271.13929,191.71224 699.0589,476.74351"
id="path10166"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="678.91986"
y="739.88269"
id="text10476"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan10478"
x="678.91986"
y="739.88269">m<tspan
id="tspan10480"
style="font-size:64.99999762%;baseline-shift:sub">3</tspan></tspan></text>
<circle
r="13.141105"
cy="704.74292"
cx="663.1554"
id="circle10482"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker11876)"
d="M 268.28215,190.28367 449.0589,429.60064"
id="path11874"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text13116"
y="268.07651"
x="245.71429"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="268.07651"
x="245.71429"
id="tspan13118"
sodipodi:role="line">F<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan13120">31</tspan></tspan></text>
</g>
</svg>
labs/lab4-barnes-hut-simulation/observation.png

11.2 KiB

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="observation.svg"
inkscape:export-filename="C:\cygwin\home\axel22\workspaces\scala\parprog\statements\barneshut\observation.png"
inkscape:export-xdpi="44.869999"
inkscape:export-ydpi="44.869999">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker12608"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path12610"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker11876"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path11878"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker10168"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path10170"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7470"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7472" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4718"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4720" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker4622"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path4624"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4228"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4231"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.7"
inkscape:cx="557.69109"
inkscape:cy="615.35072"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1600"
inkscape:window-height="877"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4142"
cx="269.28571"
cy="190.21935"
r="13.141105" />
<circle
r="13.141105"
cy="332.01859"
cx="1071.6188"
id="circle4144"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="267.72015"
y="162.38808"
id="text4146"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4148"
x="267.72015"
y="162.38808">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4150">1</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text4152"
y="360.44257"
x="1098.4303"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="360.44257"
x="1098.4303"
id="tspan4154"
sodipodi:role="line">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4158">2</tspan></tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4622)"
d="m 259.71073,187.42653 152.85714,25.7963"
id="path4190"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
id="path4716"
d="M 262.56786,184.56938 390.48747,293.88635"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker4718)"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path5830"
d="M 273.99645,200.28367 659.71073,696.30638"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,24;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path7468"
d="M 277.56788,196.71225 898.28217,742.73496"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,24;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="677.71429"
y="470.21933"
id="text7888"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7890"
x="677.71429"
y="470.21933">F<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan10448">net</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text7892"
y="192.36221"
x="402.85715"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="192.36221"
x="402.85715"
id="tspan7894"
sodipodi:role="line">F<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan7896">21</tspan></tspan></text>
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle8064"
cx="898.1554"
cy="741.17151"
r="13.141105" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="914.96698"
y="778.88129"
id="text8066"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan8068"
x="914.96698"
y="778.88129">m<tspan
id="tspan8070"
style="font-size:64.99999762%;baseline-shift:sub">3</tspan></tspan></text>
<path
sodipodi:nodetypes="cc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:7.83889103, 3.91944551;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker10168)"
d="M 271.13929,191.71224 661.91604,423.88636"
id="path10166"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="335.71429"
y="329.50507"
id="text10450"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan10452"
x="335.71429"
y="329.50507">F<tspan
id="tspan10454"
style="font-size:64.99999762%;baseline-shift:sub">31</tspan></tspan></text>
<circle
r="13.141105"
cy="497.88727"
cx="1058.5369"
id="circle10468"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text10470"
y="527.02557"
x="1083.2056"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="527.02557"
x="1083.2056"
id="tspan10472"
sodipodi:role="line">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan10474">4</tspan></tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="678.91986"
y="739.88269"
id="text10476"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan10478"
x="678.91986"
y="739.88269">m<tspan
id="tspan10480"
style="font-size:64.99999762%;baseline-shift:sub">5</tspan></tspan></text>
<circle
r="13.141105"
cy="704.74292"
cx="663.1554"
id="circle10482"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,24;stroke-dashoffset:0;stroke-opacity:1"
d="M 281.85359,190.99796 1056.8536,497.02068"
id="path10484"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path10486"
d="M 281.85359,190.99796 1066.8536,329.87782"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3,24;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker11876)"
d="m 268.28215,190.28367 59.34818,80.74554"
id="path11874"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.91944551;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker12608)"
d="M 266.85357,188.85509 493.34462,276.7435"
id="path12606"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="498.57144"
y="269.50507"
id="text13110"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan13112"
x="498.57144"
y="269.50507">F<tspan
id="tspan13114"
style="font-size:64.99999762%;baseline-shift:sub">41</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text13116"
y="268.07651"
x="245.71429"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="268.07651"
x="245.71429"
id="tspan13118"
sodipodi:role="line">F<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan13120">51</tspan></tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="991.77698"
y="642.73987"
id="text13406"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan13408"
x="991.77698"
y="642.73987">M<tspan
id="tspan13410"
style="font-size:64.99999762%;baseline-shift:sub" /></tspan></text>
<circle
r="24.149361"
cy="598.31439"
cx="961.01251"
id="circle13404"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:10, 5;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</svg>
labs/lab4-barnes-hut-simulation/quadtree.png

33.4 KiB

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="quadtree.svg"
inkscape:export-filename="C:\cygwin\home\axel22\workspaces\scala\parprog\statements\barneshut\quadtree.png"
inkscape:export-xdpi="32.65155"
inkscape:export-ydpi="32.65155">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker15906"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path15908"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker15660"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path15662" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker15306"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path15308" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker15086"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path15088"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="marker15028"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path15030"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker12608"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path12610"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker11876"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path11878"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker10168"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path10170"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker7470"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path7472" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4228"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4231"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.175"
inkscape:cx="1095.4717"
inkscape:cy="135.41975"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1600"
inkscape:window-height="877"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:window-maximized="1"
inkscape:snap-text-baseline="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4142"
cx="83.397331"
cy="151.83354"
r="13.141105" />
<circle
r="13.141105"
cy="721.93744"
cx="1136.2686"
id="circle4144"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-17.160173"
y="189.79347"
id="text4146"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4148"
x="-17.160173"
y="189.79347">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4150">A</tspan></tspan></text>
<text
sodipodi:linespacing="125%"
id="text4152"
y="748.34113"
x="1165.1003"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="748.34113"
x="1165.1003"
id="tspan4154"
sodipodi:role="line">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan4158">E</tspan></tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="1152.1206"
y="688.21014"
id="text7888"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7890"
x="1152.1206"
y="688.21014">(x<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan14976">E</tspan>,y<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan14974">E</tspan>)</tspan></text>
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle8064"
cx="1028.7399"
cy="1033.1528"
r="13.141105" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="1045.5515"
y="1070.8625"
id="text8066"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan8068"
x="1045.5515"
y="1070.8625">m<tspan
id="tspan8070"
style="font-size:64.99999762%;baseline-shift:sub">C</tspan></tspan></text>
<circle
r="13.141105"
cy="653.45074"
cx="741.34894"
id="circle10468"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text10470"
y="682.58905"
x="766.01764"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="682.58905"
x="766.01764"
id="tspan10472"
sodipodi:role="line">m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan10474">D</tspan></tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="743.56964"
y="1123.7406"
id="text10476"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan10478"
x="743.56964"
y="1123.7406">m<tspan
id="tspan10480"
style="font-size:64.99999762%;baseline-shift:sub">B</tspan></tspan></text>
<circle
r="13.141105"
cy="1088.6008"
cx="727.80518"
id="circle10482"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="966.52319"
y="915.48102"
id="text13406"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan13408"
x="966.52319"
y="915.48102">mass</tspan></text>
<circle
r="24.149361"
cy="902.3703"
cx="916.56573"
id="circle13404"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:10, 5;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.00350261;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle14942"
cx="1019.0909"
cy="35.033726"
r="13.141105" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="1029.74"
y="8.9094801"
id="text14944"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan14946"
x="1029.74"
y="8.9094801">m<tspan
id="tspan14948"
style="font-size:64.99999762%;baseline-shift:sub">F</tspan></tspan></text>
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect14952"
width="1052.579"
height="1052.579"
x="82.832512"
y="36.148746" />
<rect
y="558.17084"
x="604.85461"
height="531.79376"
width="531.79376"
id="rect14954"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect14956"
width="521.14429"
height="521.14429"
x="84.185783"
y="37.502014" />
<rect
y="-822.98016"
x="-869.66394"
height="264.46457"
width="264.46457"
id="rect14958"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
transform="scale(-1,-1)" />
<rect
transform="scale(-1,-1)"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect14960"
width="265.25757"
height="265.25757"
x="-1134.2817"
y="-1087.5979" />
<text
sodipodi:linespacing="125%"
id="text14978"
y="619.51978"
x="717.755"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="619.51978"
x="717.755"
id="tspan14980"
sodipodi:role="line">(x<tspan
id="tspan14982"
style="font-size:64.99999762%;baseline-shift:sub">D</tspan>,y<tspan
id="tspan14984"
style="font-size:64.99999762%;baseline-shift:sub">D</tspan>)</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="704.62305"
y="1058.9362"
id="text14986"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan14988"
x="704.62305"
y="1058.9362">(x<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan14990">B</tspan>,y<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan14992">B</tspan>)</tspan></text>
<text
sodipodi:linespacing="125%"
id="text14994"
y="1004.3879"
x="991.50635"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1004.3879"
x="991.50635"
id="tspan14996"
sodipodi:role="line">(x<tspan
id="tspan14998"
style="font-size:64.99999762%;baseline-shift:sub">C</tspan>,y<tspan
id="tspan15000"
style="font-size:64.99999762%;baseline-shift:sub">C</tspan>)</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:100%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="888.2475"
y="861.99701"
id="text15002"
sodipodi:linespacing="100%"
inkscape:export-xdpi="34.630001"
inkscape:export-ydpi="34.630001"><tspan
sodipodi:role="line"
id="tspan15004"
x="888.2475"
y="861.99701"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:30px;line-height:100%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;writing-mode:lr-tb;text-anchor:start">(mass<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan15020">X</tspan>,mass<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan15016">Y</tspan>)</tspan></text>
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path15022"
cx="-218.31874"
cy="1531.9603"
r="74.751289" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.89491892;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker15028);marker-end:url(#marker15086)"
d="m 611.75315,1157.4181 516.98645,0"
id="path15026"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="825.29462"
y="1220.0476"
id="text15252"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan15254"
x="825.29462"
y="1220.0476">size<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan15256">SE</tspan></tspan></text>
<circle
r="74.751289"
cy="1300.5319"
cx="301.68127"
id="circle15266"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
r="74.751289"
cy="1531.9603"
cx="130.25279"
id="circle15268"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
r="74.751289"
cy="1531.9603"
cx="495.96689"
id="circle15270"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle15272"
cx="861.68121"
cy="1531.9603"
r="74.751289" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="253.18787"
y="1313.6995"
id="text15274"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan15276"
x="253.18787"
y="1313.6995">Fork</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker12608)"
d="m 229.18777,1310.8423 -392.8572,165.7143"
id="path15278"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
id="path15304"
d="m 256.33057,1357.9852 -85.7143,108.5714"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker15306)"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path15658"
d="m 350.61637,1359.4137 104.2857,108.5715"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker15660)" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker15906)"
d="m 376.33067,1312.2709 425.7143,164.2857"
id="path15904"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="20.037586"
y="1358.3875"
id="text16312"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16314"
x="20.037586"
y="1358.3875">nw</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="143.27599"
y="1409.9053"
id="text16316"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16318"
x="143.27599"
y="1409.9053">ne</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="412.98669"
y="1405.8646"
id="text16320"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16322"
x="412.98669"
y="1405.8646">sw</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="537.23566"
y="1364.4484"
id="text16324"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16326"
x="537.23566"
y="1364.4484">se</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16328"
y="1544.2709"
x="430.90222"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1544.2709"
x="430.90222"
id="tspan16330"
sodipodi:role="line">Empty</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:111.40943146px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="97.928688"
y="1576.5566"
id="text16332"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16334"
x="97.928688"
y="1576.5566">F</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16342"
y="1574.5566"
x="-253.49989"
style="font-style:normal;font-weight:normal;font-size:111.40943146px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1574.5566"
x="-253.49989"
id="tspan16344"
sodipodi:role="line">A</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16916"
y="1542.2709"
x="813.18781"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1542.2709"
x="813.18781"
id="tspan16918"
sodipodi:role="line">Fork</tspan></text>
<circle
r="74.751289"
cy="1766.2461"
cx="338.8241"
id="circle16920"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle16922"
cx="687.39557"
cy="1766.2461"
r="74.751289" />
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle16924"
cx="1053.1097"
cy="1766.2461"
r="74.751289" />
<circle
r="74.751289"
cy="1766.2461"
cx="1418.8241"
id="circle16926"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path16928"
d="m 786.33067,1545.128 -392.8572,165.7143"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker12608)" />
<path
sodipodi:nodetypes="cc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker15306)"
d="m 813.47347,1592.2709 -85.7143,108.5714"
id="path16930"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker15660)"
d="m 907.75927,1593.6994 104.28563,108.5715"
id="path16932"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path16934"
d="m 933.47357,1546.5566 425.71423,164.2857"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker15906)" />
<text
sodipodi:linespacing="125%"
id="text16936"
y="1584.1017"
x="605.75201"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1584.1017"
x="605.75201"
id="tspan16938"
sodipodi:role="line">nw</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16940"
y="1644.1909"
x="700.41876"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1644.1909"
x="700.41876"
id="tspan16942"
sodipodi:role="line">ne</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16944"
y="1640.1503"
x="970.12946"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1640.1503"
x="970.12946"
id="tspan16946"
sodipodi:role="line">sw</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16948"
y="1598.7341"
x="1094.3785"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1598.7341"
x="1094.3785"
id="tspan16950"
sodipodi:role="line">se</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16956"
y="1810.8424"
x="655.07159"
style="font-style:normal;font-weight:normal;font-size:111.40943146px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1810.8424"
x="655.07159"
id="tspan16958"
sodipodi:role="line">E</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:111.40943146px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="303.64294"
y="1808.8424"
id="text16960"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16962"
x="303.64294"
y="1808.8424">D</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:111.40943146px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="1383.6429"
y="1807.9852"
id="text16968"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16970"
x="1383.6429"
y="1807.9852">C</tspan></text>
<text
sodipodi:linespacing="125%"
id="text16972"
y="1808.8424"
x="1017.9285"
style="font-style:normal;font-weight:normal;font-size:111.40943146px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="1808.8424"
x="1017.9285"
id="tspan16974"
sodipodi:role="line">B</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="918.23126"
y="1466.4738"
id="text16976"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan16978"
x="918.23126"
y="1466.4738">mass = m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan16980">D</tspan> + m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan16982">E</tspan> + m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan16984">B</tspan> + m<tspan
style="font-size:64.99999762%;baseline-shift:sub"
id="tspan16986">C</tspan></tspan></text>
</g>
</svg>
labs/lab4-barnes-hut-simulation/sectormatrix.png

12.3 KiB

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="sectormatrix.svg"
inkscape:export-filename="C:\cygwin\home\axel22\workspaces\scala\parprog\statements\barneshut\sectormatrix.png"
inkscape:export-xdpi="32.6516"
inkscape:export-ydpi="32.6516">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="marker4830"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4832"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker4542"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mstart"
inkscape:collect="always">
<path
transform="scale(0.4) translate(10,0)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4544" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path4196"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Sstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4202"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
transform="scale(0.2) translate(6,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="692.30131"
inkscape:cy="448.67197"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1600"
inkscape:window-height="877"
inkscape:window-x="-4"
inkscape:window-y="-4"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4138"
width="157.25688"
height="157.25688"
x="160.41716"
y="293.24829" />
<rect
y="293.24829"
x="317.80426"
height="157.25688"
width="157.25688"
id="rect4140"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="293.24829"
x="474.40179"
height="157.25688"
width="157.25688"
id="rect4142"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4144"
width="157.25688"
height="157.25688"
x="631.78894"
y="293.24829" />
<rect
y="450.89859"
x="160.41716"
height="157.25688"
width="157.25688"
id="rect4146"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4148"
width="157.25688"
height="157.25688"
x="317.80426"
y="450.89859" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4150"
width="157.25688"
height="157.25688"
x="474.40179"
y="450.89859" />
<rect
y="450.89859"
x="631.78894"
height="157.25688"
width="157.25688"
id="rect4152"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="608.02252"
x="160.41716"
height="157.25688"
width="157.25688"
id="rect4154"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4156"
width="157.25688"
height="157.25688"
x="317.80426"
y="608.02252" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4158"
width="157.25688"
height="157.25688"
x="474.40179"
y="608.02252" />
<rect
y="608.02252"
x="631.78894"
height="157.25688"
width="157.25688"
id="rect4160"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4162"
width="157.25688"
height="157.25688"
x="160.41716"
y="765.67279" />
<rect
y="765.67279"
x="317.80426"
height="157.25688"
width="157.25688"
id="rect4164"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
y="765.67279"
x="474.40179"
height="157.25688"
width="157.25688"
id="rect4166"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.60580969;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4168"
width="157.25688"
height="157.25688"
x="631.78894"
y="765.67279" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path4170"
cx="435"
cy="491.64792"
r="13.571428" />
<circle
r="13.571428"
cy="854.50507"
cx="699.28577"
id="circle4172"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4174"
cx="769.28577"
cy="824.50507"
r="13.571428" />
<circle
r="13.571428"
cy="894.50507"
cx="790.71436"
id="circle4176"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4178"
cx="726.42865"
cy="295.93362"
r="13.571428" />
<circle
r="13.571428"
cy="805.93365"
cx="267.85727"
id="circle4180"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<circle
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4182"
cx="555.20319"
cy="717.37964"
r="13.571428" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:15, 5;stroke-dashoffset:0;marker-start:url(#Arrow1Mstart)"
d="m 721.42857,569.50506 c 250,-70 350.00003,-5.71428 350.00003,-5.71428"
id="path4184"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="1090"
y="582.36218"
id="text4530"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4532"
x="1090"
y="582.36218"
style="-inkscape-font-specification:'Andale Mono';font-family:'Andale Mono';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">ConcBuffer[Body]</tspan></text>
<path
inkscape:connector-curvature="0"
id="path4540"
d="m 738.57143,392.3622 c 250,-70 395.71437,142.85715 395.71437,142.85715"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:15, 5;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4542)"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:15, 5;stroke-dashoffset:0;stroke-opacity:1;marker-start:url(#marker4830)"
d="m 725.71429,699.50506 c 280.00001,38.57143 402.85731,-92.85714 402.85731,-92.85714"
id="path4828"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="171.72594"
y="345.25543"
id="text5218"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5220"
x="171.72594"
y="345.25543">0,0</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5222"
y="345.25543"
x="341.43158"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="345.25543"
x="341.43158"
id="tspan5224"
sodipodi:role="line">1,0</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="494.97476"
y="345.25543"
id="text5226"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5228"
x="494.97476"
y="345.25543">2,0</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5230"
y="345.25543"
x="650.53827"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="345.25543"
x="650.53827"
id="tspan5232"
sodipodi:role="line">3,0</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5234"
y="504.85953"
x="171.72594"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="504.85953"
x="171.72594"
id="tspan5236"
sodipodi:role="line">0,1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="341.43158"
y="504.85953"
id="text5238"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5240"
x="341.43158"
y="504.85953">1,1</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5242"
y="504.85953"
x="494.97476"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="504.85953"
x="494.97476"
id="tspan5244"
sodipodi:role="line">2,1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="650.53827"
y="504.85953"
id="text5246"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5248"
x="650.53827"
y="504.85953">3,1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="171.72594"
y="656.38239"
id="text5250"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5252"
x="171.72594"
y="656.38239">0,2</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5254"
y="656.38239"
x="341.43158"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="656.38239"
x="341.43158"
id="tspan5256"
sodipodi:role="line">1,2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="494.97476"
y="656.38239"
id="text5258"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5260"
x="494.97476"
y="656.38239">2,2</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5262"
y="656.38239"
x="650.53827"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="656.38239"
x="650.53827"
id="tspan5264"
sodipodi:role="line">3,2</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5266"
y="813.96619"
x="171.72594"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="813.96619"
x="171.72594"
id="tspan5268"
sodipodi:role="line">0,3</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="341.43158"
y="813.96619"
id="text5270"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5272"
x="341.43158"
y="813.96619">1,3</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5274"
y="813.96619"
x="494.97476"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="813.96619"
x="494.97476"
id="tspan5276"
sodipodi:role="line">2,3</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="650.53827"
y="813.96619"
id="text5278"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5280"
x="650.53827"
y="813.96619">3,3</tspan></text>
</g>
</svg>
# Concurrent Bounded Buffer
Use the following commands to make a fresh clone of your repository:
```
git clone -b pubsub git@gitlab.epfl.ch:lamp/student-repositories-s21/cs206-GASPAR.git cs206-pubsub
```
## Useful links
* [The API documentation of the Scala standard library](https://www.scala-lang.org/files/archive/api/2.13.4)
* [The API documentation of the Java standard library](https://docs.oracle.com/en/java/javase/15/docs/api/index.html)
**If you have issues with the IDE, try [reimporting the
build](https://gitlab.epfl.ch/lamp/cs206/-/blob/master/labs/example-lab.md#ide-features-like-type-on-hover-or-go-to-definition-do-not-work),
if you still have problems, use `compile` in sbt instead.**
## Introduction
The goal of this assignment is to implement a fixed size buffer that can be accessed concurrently by multiple threads running in parallel.
This is a simple yet important data structure that is widely used in concurrent applications.
In particular, we provide you an implementation of a Publish/Subscribe (PubSub) application that uses the bounded buffer you would be developing.
We will provide a brief overview of the Publish/Subscribe application, and instructions on how to run it towards the end of this assignment.
However, the only data structure that you should implement for this assignment is the bounded buffer, which is explained below:
## Bounded Buffer - Definition and Operations
A concurrent bounded buffer is a data structure that supports the following two operations:
- a method `put(e)` that puts a value `e` in the buffer,
- a method `take` that takes a value from the buffer, and removes it.
Importantly, the `put` and `take` methods should follow the FIFO (First-In, First-Out) semantics.
Intuitively, this means that `take` should return the _oldest_ element that was `put` into the buffer.
<!-- [comment]: # (A pointer to linearizability ?) -->
The buffer is *bounded*, which means that it can only store a finite number of elements.
The maximum number of elements the buffer can hold is passed as an argument to the constructor of `BoundedBuffer`.
The following is the definition of the data structure, which can be found in the file:
`src/main/scala/pubsub/collection/BoundedBuffer`
```scala
class BoundedBuffer[T](size: Int) extends AbstractBoundedBuffer[T](size) {
override def put(e: T): Unit = ???
override def take(): T = ???
}
```
A `put` operation invoked on a buffer that is full will *wait* (or block) until an element is taken from
the buffer. Dually, a `take` operation invoked on an empty buffer will *wait* until an element is put
into the buffer.
Note that multiple `put` and `take` operations can be initiated concurrently from different threads. Hence,
care must be taken to ensure that the `buffer` is not accessed or left in an inconsistent state by the `put` or `take`
methods. To understand the challenges better let us start by considering a sequential setting.
## A Sequential Bounded Buffer
Let us try to implement the `BoundedBuffer` class without worrying at all about concurrency.
That is, imagine that there is only one thread that performs a sequence of `put` and `take` operations on an object of type `BoundedBuffer`.
Can you implement the `put` and `take` methods in this setting?
Note that your implementation should run in constant time in the worst-case.
(A remark: the data structure you implement in this case is also called a _circular queue_.)
To write your solution, use the `pubsub.collection.BoundedBuffer` class skeleton that is given to you in the handout.
You are given two _variables_: `count` and `head`, and an internal buffer that exposes a minimal array-like API.
It is important that you use the variables given to you, and the internal buffer API.
*You are strongly advised not to create any other fields or classes or objects*. Otherwise,
you may fail the testcases.
The following is an illustration of the input/output behavior of the buffer in the sequential case.
In the comments, we show the contents of the array used internally by the `BoundedBuffer` class, and the
return values (if any) of the operations.
```scala
def example1() = { // Internal Buffer:
val buf = new BoundedBuffer(2) // | | |
buf.put(1) // | 1 | |
buf.put(2) // | 1 | 2 |
val x = buf.take() // | | 2 | and x is 1
buf.put(3) // | 3 | 2 |
val y = buf.take() // | 3 | | and y is 2
}
```
Now, think about what should happen if we try to `put` an element into a buffer that is full?
Obviously, the element cannot be stored in the buffer. Furthermore, there is no use of waiting for
some space to be created in the buffer because no element in the buffer could be read simultaneously.
(Recall that there is only one thread accessing the buffer in the sequential setting).
Hence, you may throw an exception in this case. Similarly, handle the dual case of invoking a
`take` on an empty buffer.
Think about what happens when your sequential buffer is used in a concurrent system. What can happen?
Try running the test suite that was given to you with the handout. What can you see?
As you may have seen, the test suite was able to find many problematic schedules for the non-concurrent buffer. This is to be expected!
Now, using your sequential implementation as a stepping stone, let us develop a concurrent bounded buffer, which is your real goal.
## Concurrent Bounded Buffer
Now, let us imagine that there are two threads currently performing operations on a shared buffer of
max size 2 as shown below:
```scala
val buf = new BoundedBuffer(2)
Thread 1 Thread 2
buf.put(1) y = buf.take()
```
The first change you need to make to your sequential implementation is that `buf.take()` invoked
by `Thread 2` should *wait* until an element is put into the buffer by `Thread 1`.
Similarly, a `put` method should *wait* until an element is taken from the buffer.
Throwing an exception in these cases as in the sequential case is not acceptable
here because operations can be happening simultaneously. In other words, a `put` that cannot
succeed now can succeed in the future, because of a concurrently executing `take`.
For this purpose, you may use a `wait` method of the Java standard library.
You can find a brief description of the semantics of the method, and references for further reading in the section *Synchronization Primitives* below. An alternative is to loop continuously until the buffer has an element. This is called as *busy waiting*. But as you can imagine this wastes precious processor cycles, and hence is not preferred. (See the section on busy waiting as well for some examples.)
With this waiting strategy, in the above example, `Thread 2` will enter into *wait* state if it executes before `Thread 1`,
and `Thread 1` will proceed to execute. However, after completing the execution `Thead 1` should *wake up*
`Thread 2` (and also every other thread that would be waiting on the buffer to become non-empty).
For this purpose, you have to use the `notify()`, and/or `notifyAll()` primitives (see section *Synchronization Primitives*).
Note that there are subtle differences between `notify()` and `notifyAll()` which is also briefly explained below.
*Important Hint: You should invoke the synchronization primitives like `wait`, `notify`, `synchronized` etc. only
on the `this` reference when implementing the methods of the `BoundedBuffer` class. Otherwise, your
implementation may get stuck (and run into deadlocks) while testing*
Also remember that `notify` and `wait` should be invoked only inside a `synchronized` block.
Now that we know how to implement the waiting strategy to alleviate the above problem of `Thread 2`
running before `Thread 1`, let us look at other issues that may arise when `put` and `take` methods run concurrently.
In particular, say `Thread 1` starts before `Thread 2`.
Let us study how the operations they perform can interleave, assuming that you implemented
them using `count` and `head`.
Consider the following interleaving of operations of `put` and `get`
```scala
val buf = new BoundedBuffer(2)
Thread 1 Thread 2
//start buf.put(1)
//start buf.take
//reads count -> 0
//...
//updates count -> 1
//reads count -> 1
//read internal buffer(0) (crash !!)
//internal buffer(0) <- 1
```
Clearly, if your code permits the above interleaving then it would crash. Now, your goal is to come up
with adequate synchronization so that no interleaving of operations of `put` and `take` performed
by any number of threads result either in a crash or in an incorrect buffer state.
You may use all the synchronization primitives described below.
The test suite provided along with the project may help you find problematic schedules.
A schedule is a sequence of operations carried out by the different threads such as the one
shown above.
The test suite runs your code on several thousand schedules. You may use that to check whether your bounded
buffer reaches a consistent state on some schedule.
An incorrect run on a schedule could either be that:
- An operation returns an incorrect value.
- An operation throws an exception when it should not.
Remember that some operations, even though they look *atomic*, are decomposed into multiple smaller operations.
For instance, consider `buffer(head) = ...`. Is this atomic ?
In the remaining sections, we talk about the synchronization primitives and some of the commons cases of errors.
## Synchronization Primitives
- `synchronized[T](body: => T)`, which executes `body` in a critical section. This ensures that only a single thread at a time can execute the instructions passed as argument.
- [`wait()`][1], which stops the execution of the thread until it is notified. `wait()` can only be called within a `synchronized` block.
- [`notify()`][2], which unblocks one of the waiting thread. Note that it's not possible to specify which thread is unblocked.
- [`notifyAll()`][3], which unblocks all of the waiting threads.
## Using the Pub/Sub Server
The following section describes how you can run and use the Pub/Sub server implemented for you,
This small server allows any amount of people to connect and chat together around topics of their choice. Playing with it may help you discover errors in your ConcurrentBoundedBuffer.
### Running the server
You can start the Pub/Sub Server as any normal SBT project, simply type `sbt run` while in the root folder of the project. No additional setup is required.
### Connecting to the server
You can connect to the server via command-line interface and the [`telnet`][4] protocole.
When the server is started it will display a line such as:
Connect to <server_ip> (or `localhost`), port 7676 with `telnet` to join this server
Which gives you the IP address of the running server.
In your command-line you must do the following telnet command: `telnet <server_ip> 7676`
You should then be greeted by the server with a `connection_ack`.
*telnet is not enabled by default on Windows 8 and 10; [here are fast and simple instructions to enable telnet on recent Windows][5]*
*There are also issues with telnet connecting to the server when using Windows 10 due to firewall issues. However on Linux telnet works flawlessy [sorry for any inconvenience]*
### Commands available
Now that the server is running and you have a connected client, here is the comprehensive list of the commands any client can use on the server:
- `rename <nickname>`: change your display name to `<nickname>`. Your new name cannot contain any space or single quote.
- `subscribe <topic>`: add yourself to the `<topic>` subscriber list. You will receive all messages sent to that topic.
- `unsubscribe <topic>`: remove yourself from the `<topic>` subscriber list. You will no longer receive messages sent to that topic.
- `publish <topic> '<message>'`: publish the `<message>` of your choice to the `<topic>` of your choice. Your `<message>` can span on multiple lines but has to be enclosed with single-quote `'` to be deemed valid.
- `leave`: end the connection with the server in a polite manner
## Common Pitfalls
### Busy Waiting
Consider the following code snippet that uses a while loop (with an empty body) to guard the execution of the `put` and `take` operations.
```scala
class BoundedBuffer[T](size: Int) extends AbstractBoundedBuffer[T](size) {
override def put(e: T): Unit = {
while (isFull) {}
// Rest of your code
???
}
override def take(): T = {
while (isEmpty) {}
// Rest of your code
???
}
}
```
What is the problem with this way of waiting? Apart from those potential problems,
is this code behaving correctly in a concurrent setting i.e, is there a schedule that would
result in an incorrect behavior on the above code.
_Hint: what happens when one `put` and two `take` are running in parallel ?_
### `notify()` vs `notifyAll()`
As per the documentation [documentation][2]:_ of `notify()`, invoking the `notify` method on an object `o` wakes up a _single_ thread that is waiting on the object `o`'s monitor. If there are multiple threads waiting on `o`, one of them is chosen **arbitrarily** at the discretion of the implementation. Note that a thread waits on an object's monitor by calling one of the wait methods.
Using the `notify` method often leads to tricky problems which can sometimes result in deadlocks. This can lead to bugs that can be hard to see and reproduce. For this reason, it is often strongly advised to use `notifyAll` instead.
Can you figure out why this is the case?
_Hint: Could it ever happen that the thread unblocked by notify somehow cannot execute even though there are other threads that could execute if they were unblocked instead ?_
### Waiting using `if` vs `while`
Due to the semantics of `notify` and `notifyAll`, there are no guarantees that the condition on which a thread is waiting will be fulfilled when the thread is unblocked. Therefore, the following code is problematic:
```scala
synchronized {
if (!condition) {
wait()
}
// We have no garantees that the condition holds here.
}
```
Instead, the waiting thread should always recheck the condition when it is unblocked. This can easily be done using a `while` instead of `if`.
Can you come up with a schedule in which using a simple `if` would be problematic?
_Hint: Try using a system with 3 threads, two of which try to execute `take` and one of which executes `put` in an initially empty buffer?_
_Hint: Note that, as specified in the [documentation of `notify`][2]:_
> The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, **the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object**.
[1]: https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/Object.html#wait()
[2]: https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/Object.html#notify()
[3]: https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/Object.html#notifyAll()
[4]: https://en.wikipedia.org/wiki/Telnet
[5]: http://www.sysprobs.com/install-and-enable-telnet-in-windows-8-use-as-telnet-client
# Lock-free Sorted List
Use the following commands to make a fresh clone of your repository:
```
git clone -b lockfree git@gitlab.epfl.ch:lamp/student-repositories-s21/cs206-GASPAR.git cs206-lockfree
```
## Useful links
* [The API documentation of the Scala standard library](https://www.scala-lang.org/files/archive/api/2.13.4)
* [The API documentation of the Java standard library](https://docs.oracle.com/en/java/javase/15/docs/api/index.html)
**If you have issues with the IDE, try [reimporting the
build](https://gitlab.epfl.ch/lamp/cs206/-/blob/master/labs/example-lab.md#ide-features-like-type-on-hover-or-go-to-definition-do-not-work),
if you still have problems, use `compile` in sbt instead.**
## Introduction
The goal of this assignment is to implement a concurrent list that stores values of type `Int` in ascending order.
Last week, we have seen how to use a monitor to make data structures operations behave correctly in a concurrent setting.
This week, the data structure we will implement will not use a monitor or a lock of any kind.
Instead, we will use an atomic operation, called `compareAndSet`, in your implementation of the data structure operations.
The goal will still be to have a data structure that can safely be used in a concurrent setting.
In addition, the sorted list operations you will implement will be *lock-free*.
In a system where all concurrent operations have this property, the progress of at least one thread is ***guaranteed***.
There can not be a global deadlock in which none of the thread can make progress!
Note that this does *not* guarantee that all threads can make progress.
Operation with this property is said to be *wait-free*.
## Atomic Variables
The list methods you will implement will make use of atomic variables. An atomic variable is an object which holds a value of a given type `T`. The object offers two methods to manipulate this value:
- `get`, which returns the current value held in the variable,
- `compareAndSet`, which modifies the content of the variable provided that the previous value is given. This method returns `true` if it was successful, `false` otherwise.
The operation `compareAndSet` applies the following logic ***atomically***, which means there cannot be any context switches between the instructions of the operation:
```scala
def compareAndSet(expected: T, value: T) {
if (current == expected) {
current = value
true
}
else {
false
}
}
```
The `AtomicVariable` class is given to you. You do not have to worry about implementing it!
Note that a similar class exists in the Java standard library, called [`AtomicReference`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html).
The main difference between `AtomicReference` and the `AtomicVariable` class we defined for this exercise is that `AtomicReference` uses referential equality to check whether `expected` and `current` are the same, while `AtomicVariable` uses the `==` method.
## The Sorted List Data Structure
The data structure you will implement is a mutable linked list of integers, sorted in ascending order. Each integer is stored in a `Node`. In addition to the integer value, each node contains a mutable reference to the next node in the list. This mutable reference is held in an `AtomicVariable`.
```scala
abstract class Node(val value: Int, initTail: Option[Node]) {
type State = Option[Node]
def initialState: State = initTail
val atomicState: AbstractAtomicVariable[State] = new AtomicVariable[State](initialState)
def next: Option[Node] = atomicState.get
// ...
}
```
Then, `SortedList` is simply a class that holds a reference to the first node of the list. This class is defined in `SortedList.scala`.
```scala
class SortedList extends AbstractSortedList {
// The sentinel node at the head.
private val _head = createNode(0, None, isHead=true)
// The first logical node is referenced by the head.
def firstNode: Option[Node] = _head.next
def findNodeWithPrev(pred: Int => Boolean): (Node, Option[Node]) = ???
def insert(e: Int): Unit = ???
def contains(e: Int): Boolean = ???
def delete(e: Int): Boolean = ???
}
```
The value `_head` of the list is called a [*sentinel* node](https://en.wikipedia.org/wiki/Sentinel_node). This value is simply `Node` that will serve only as a reference to the first actual node of the list. The value (viz. zero) held by this special node should be completely ignored. This technique is useful because it limits the duplication of code. An alternative is to have a reference to the first node using an `AtomicVariable`. But this would force us to handle the first node differently from the rest. So will use a sentinel node for this assignment.
### `findNodeWithPrev`
The first method you will implement is an internal helper method which will be used all other methods.
This method should do a traversal of the list to find the first node whose value satisfies the parameter predicate.
The method should return the following two values as a pair:
- the predecessor of the node,
- the node.
If `node` is the first node whose value satisfies the predicate and `predecessor` its predecessor, then the method should return `(predecessor, Some(node))`. Due to the use of the sentinel node at the head of the list, the method is bound to find a predecessor, even for the first logical node.
When the predicate doesn't hold on any of the values, then the function should return `(last, None)`, where
`last` is the last node of the list.
### `insert`
Your first goal will be to code the insert method of the lock-free list. The idea is very simple:
1. Locate the position you need to insert by using the `findNodeWithPrev` method you have just implemented.
2. Create a new node that holds the value and points to the correct next node. For this, you should use `createNode(value, nextNode)`.
3. Use the `compareAndSet` operation to make the previous node point to your newly created node.
4. If the operation failed, retry from the start! Otherwise, the operation is done!
### `contains`
Next, you should implement the `contains` method, which checks if the list contains a given element. You may of course use the `findNodeWithPrev` method you have implemented.
### `delete`
With the addition of `delete`, things get rapidly trickier. The intuitive solution would be to:
1. Find the node to delete and its predecessor using `findNodeWithPrev`.
2. Use an atomic `compareAndSet` operation to make the predecessor node point to the successor.
Unfortunately, this solution is not entirely satisfactory!
Indeed, there exist schedules in which some successful operations are lost. Can you think of any?
As an example, assume that the list currently contains the values `10` and `30`.
![Step 0](step0.png "Initial configuration")
- Imagine one thread starts executing the insertion of `20` in the list and correctly locates where to insert the new node (between `10` and `30`). The thread then creates a node with value `20` and makes it point to the node with value `30`. ![Step 1](step1.png "Right in the middle of inserting 20")
- Now, some other thread is scheduled and starts executing the deletion of the node with value `10`. The thread finds the two nodes that surround it, that is the sentinel node at the head of the list and the node with value `30` (note that the insertion of `20` by the other thread isn't visible yet!). The thread, using compare and set, changes the next pointer of the sentinel node to the node with value `30`. The `delete` operation then terminates successfully. ![Step 2](step2.png "After the deletion of 10")
- Now, the first thread resumes its execution. Its next instruction is to use compare and set to change the next pointer of the node with value `10`, which it can do without any problem! Indeed, this atomic variable wasn't touched by the delete operation. The `insert` operation looks successful, even though the node that was inserted is not reachable from the head of the list! The operation was lost... ![Step 3](step3.png "Final configuration")
One solution to this problem, as proposed by Timothy L. Harris in his paper [A Pragmatic Implementation of Non-Blocking Linked Lists](https://www.cl.cam.ac.uk/research/srg/netos/papers/2001-caslists.pdf), is to somehow record in the node that it was deleted.
We will proceed similarly in this assignment.
#### Marking Nodes
The first step is to modify the mutable state held by nodes. Open the `Node.scala` file. Until now the state was just `Option[Node]`, which is an optional reference to the next node.
You will need to add, in addition to this information, a boolean flag that indicates whether the node was deleted or not.
```scala
abstract class Node(val value: Int, initTail: Option[Node]) {
type State = ???
def initialState: State = ???
val atomicState: AbstractAtomicVariable[State] = new AtomicVariable[State](initialState)
def next: Option[Node] = ???
def deleted: Boolean = ???
def mark: Boolean = ???
}
```
Begin by modifying the `State` type to any type that you deem appropriate. Remember that the value of this type should contain an `Option[Node]` (the next node) and a flag (whether the node has been marked).
Complete the other functions, described below, as well:
- `initialState` should return the state of the node when it is first created. Note that the node should not be marked and the optional reference to the next node should be set to `initTail`.
- `next` should return the optional reference to the next node held currently in the state.
- `deleted` should return `true` if the node was marked, `false` otherwise.
- `mark` should mark the node as `deleted`. The method should return `true` only if it is the first time this node is marked. If the node was previously marked, this method should return `false`. (Think carefully about this!)
#### Implementing `delete` of `SortedList`
Now, we can implement a version of delete that is not vulnerable to the problem exposed earlier. The idea is to:
1. Find the node to delete and its predecessor using `findNodeWithPrev`.
2. Mark the node as `deleted` using its `mark` method. If it returns false, retry from the start!
Once this is done, we still have to modify the other list methods to handle the fact that nodes can be marked.
Marked nodes will be deleted within the `findNodeWithPrev` method.
#### Adapting `findNodeWithPrev` to handle marked nodes
The first method you need to adapt is `findNodeWithPrev`. The method should do exactly as before except when it encounters a marked node during its traversal. When it does so, the method should use compare and set to modify the next node pointed by the predecessor node. Regardless of the outcome of the compare and set operation, the `findNodeWithPrev` should then restart from scratch.
#### Adapting `insert` to handle marked nodes
The last method you need to change is `insert`. The logic remains exactly the same, except that when you perform the `compareAndSet` operation, you should make sure that the parameters are of type `State` and are not flagged as deleted.
You are now done with this assignment. Congratulations!
labs/lab6-lock-free-sorted-list/step0.png

1.99 KiB

labs/lab6-lock-free-sorted-list/step1.png

4.18 KiB

labs/lab6-lock-free-sorted-list/step2.png

6.33 KiB

labs/lab6-lock-free-sorted-list/step3.png

6.95 KiB

## Binary Trees
Use the following commands to make a fresh clone of your repository:
```
git clone -b actorbintree git@gitlab.epfl.ch:lamp/student-repositories-s21/cs206-GASPAR.git cs206-actorbintree
```
## Useful links
* [The API documentation of Akka](https://doc.akka.io/api/akka/current/akka/index.html)
* [The API documentation of the Scala standard library](https://www.scala-lang.org/files/archive/api/2.13.4)
* [The API documentation of the Java standard library](https://docs.oracle.com/en/java/javase/15/docs/api/index.html)
**If you have issues with the IDE, try [reimporting the
build](https://gitlab.epfl.ch/lamp/cs206/-/blob/master/labs/example-lab.md#ide-features-like-type-on-hover-or-go-to-definition-do-not-work),
if you still have problems, use `compile` in sbt instead.**
## Introduction
Binary trees are tree based data structures where every node has at most two children (left and right).
In this exercise, every node stores an integer element.
From this we can build a binary search tree by requiring for every node that
* values of elements in the left subtree are strictly smaller than the node's element
* values of elements in the right subtree are strictly bigger than the node's element
In addition, there should be no duplicates, hence we obtain a binary tree set.
Your task in this assignment is to implement an actor-based binary tree set where each node is
represented by one actor. The advantage of such an actor-based solution is that it can execute
fully asynchronously and in parallel.
#### The API
You can find the message-based API for the actor-based binary tree to be implemented in the supplied `BinaryTreeSet` object
in the file `BinaryTreeSet.scala`.
The operations, represented by actor messages, that the implementation should support are the following:
* `Insert`
* `Remove`
* `Contains`
All three of the operations expect an `ActorRef` representing the requester of the operation, a numerical identifier of
the operation and the element itself. `Insert` and `Remove` operations should result in an `OperationFinished` message sent
to the provided requester `ActorRef` reference including the id of the operation. `Insert` and `Remove` should return an
`OperationFinished` message even if the element was already present in the tree or was not found, respectively.
`Contains` should result in a `ContainsResult` message containing the result of the lookup (a Boolean which is
true if and only if the element is in the tree when the query arrives) and the identifier of the `Contains` query.
#### Handling of Removal
You should observe that both the `Insert` and `Contains` operations share an important property, namely, they only
traverse a linear path from the root of the tree to the appropriate inner node or leaf. Since the tree nodes are actors
which process messages one-by-one, no additional synchronization is needed between these operations. Removal in a
binary tree unfortunately results in tree restructuring, which means that nodes would need to communicate and coordinate
between each other (while additional operations arrive from the external world!).
Therefore, instead of implementing the usual binary tree removal, in your solution you should use a flag that is stored
in every tree node (`removed`) indicating whether the element in the node has been removed or not. This will result in a very
simple implementation that is concurrent and correct with minimal effort. Unfortunately this decision results in the
side effect that the tree set accumulates "garbage" (elements that have been removed) over time.
#### Garbage Collection
As we have seen, removal of entries can be implemented simply by using a removal flag with the
added cost of growing garbage over time. To overcome this limitation you will need to implement a "garbage collection"
feature. Whenever your binary tree set receives a `GC` message, it should clean up all the removed elements, while
additional operations might arrive from the external world.
The garbage collection task can be implemented in two steps. The first subtask is to implement an internal
`CopyTo` operation on the binary tree that copies all its non-removed contents from the binary tree to a provided new one. This
implementation can assume that no operations arrive while the copying happens (i.e. the tree is protected from modifications
while copying takes places).
The second part of the implementation is to implement garbage collection in the manager (`BinaryTreeSet`) by using the copy operation.
The newly constructed tree should replace the old one and all actors from the old one should be stopped.
Since copying assumes no other concurrent operations, the manager should handle the case when operations arrive while still
performing the copy in the background. It is your responsibility to implement the manager in such a way that the fact
that garbage collection happens is invisible from the outside (of course additional delay is allowed).
For the sake of simplicity, your implementation should ignore GC requests that arrive while garbage collection is taking place.
#### Ordering Guarantees
Replies to operations may be sent in any order but the contents of `ContainsResult` replies must obey the order of the
operations. To illustrate what this means observe the following example:
Client sends:
Insert(testActor, id=100, elem=1)
Contains(testActor, id=50, elem=2)
Remove(testActor, id=10, elem=1)
Insert(testActor, id=20, elem=2)
Contains(testActor, id=80, elem=1)
Contains(testActor, id=70, elem=2)
Client receives:
ContainsResult(id=70, true)
OperationFinished(id=20)
OperationFinished(id=100)
ContainsResult(id=80, false)
OperationFinished(id=10)
ContainsResult(id=50, false)
While the results seem "garbled", they actually strictly correspond to the order of the original operations. On
closer examination you can observe that the order of original operations was [100, 50, 10, 20, 80, 70]. Now if you
order the responses according to this sequence the result would be:
Insert(testActor, id=100, elem=1) -> OperationFinished(id=100)
Contains(testActor, id=50, elem=2) -> ContainsResult(id=50, false)
Remove(testActor, id=10, elem=1) -> OperationFinished(id=10)
Insert(testActor, id=20, elem=2) -> OperationFinished(id=20)
Contains(testActor, id=80, elem=1) -> ContainsResult(id=80, false)
Contains(testActor, id=70, elem=2) -> ContainsResult(id=70, true)
As you can see, the responses the client received are the same, hence they must have been executed sequentially,
and only the responses have arrived out of order. Thus, the responses obey the semantics of sequential operations
-- it is simply their arrival order is not
defined. You might find it easier for testing to use sequential identifiers for the operations, since that makes it
easier to follow the sequence of responses.
You might also note that out-of-order responses can only happen if the client does not wait for each individual answer
before continuing with sending operations.
While this loose ordering guarantee on responses might look strange at first, it will significantly simplify the
implementation of the binary tree and you are encouraged to make full use of it.
#### Your task
You can find code stubs in the file `BinaryTreeSet.scala` which provides you with the API as described above,
the `BinaryTreeSet` and `BinaryTreeNode` classes. The `BinaryTreeSet` represents the whole binary tree.
This is also the only actor that is explicitly created by the user and the only actor the user sends messages to.
You can implement as many or as few message handlers as you like and you can add additional variables or helper
functions. We provide suggestions in your code stub, marked with the comment `optional`, but you are free to use
it fully or partially; the optional elements are not part of the tested API.
To see a binary tree in operation check our provided tests in `BinaryTreeSuite.scala`. Note in particular
that it is the user who triggers garbage collection by sending a `GC` message (for the sake of simplicity of this exercise).
Don't forget to make sure that no `Operation` messages interfere during garbage collection and that the user does
not receive any messages that may result from the copying process. To achieve this, put any incoming operation message
into a queue during the garbage collection process. When the copying process is finished, re-send the queued messages
to the tree root and clear the queue.
The following may be useful for your implementation:
* Another way to stop an actor, besides the `stop` method you have seen, is to send it a `PoisonPill` message.
* `context.parent` returns the ActorRef of the actor which created the current actor (i.e. its parent).
* If you see a log message like the following
[INFO] [11/21/2013 14:04:13.237] [PostponeSpec-akka.actor.default-dispatcher-2] [akka://PostponeSpec/deadLetters] Message [actorbintree.BinaryTreeSet$OperationFinished] from Actor[akka://PostponeSpec/user/$e/my-actor#-1012560631] to Actor[akka://PostponeSpec/deadLetters] was not delivered. [1] dead letters encountered.
it means that one of your messages (here the OperationFinished) message was not delivered from actor `my-actor` to actor `deadLetters`—the latter is where actors forward their messages after they terminate.
You should check that you do not stop actors prematurely.
*A word on Actor counts:*
* The grader verifies that enough Actors are created when inserting elements.
* The grader also verifies that enough Actors are stopped in response to a `GC` command (i.e. for those elements that were previously marked removed from the set).
# Wikipedia
Use the following commands to make a fresh clone of your repository:
```
git clone -b wikipedia git@gitlab.epfl.ch:lamp/student-repositories-s21/cs206-GASPAR.git cs206-wikipedia
```
## Useful links
* [The API documentation of Spark](http://spark.apache.org/docs/latest/api/scala/org/apache/spark/index.html)
* [The API documentation of the Scala standard library](https://www.scala-lang.org/files/archive/api/2.13.4)
* [The API documentation of the Java standard library](https://docs.oracle.com/en/java/javase/15/docs/api/index.html)
**If you have issues with the IDE, try [reimporting the
build](https://gitlab.epfl.ch/lamp/cs206/-/blob/master/labs/example-lab.md#ide-features-like-type-on-hover-or-go-to-definition-do-not-work),
if you still have problems, use `compile` in sbt instead.**
## Introduction
For this assignment, you will need to download the wikipedia dataset (68 MB):
[http://alaska.epfl.ch/~dockermoocs/bigdata/wikipedia-grading.dat](http://alaska.epfl.ch/~dockermoocs/bigdata/wikipedia-grading.dat)
and place it in the folder: `src/main/resources/wikipedia` in your
project directory.
In this assignment, you will get to know Spark by exploring full-text Wikipedia
articles.
Gauging how popular a programming language is important for companies judging
whether or not they should adopt an emerging programming language. For that reason,
industry analyst firm RedMonk has bi-annually computed a ranking of programming
language popularity using a variety of data sources, typically from websites like
GitHub and StackOverflow. See their
[top-20 ranking for June 2016](http://redmonk.com/sogrady/2016/07/20/language-rankings-6-16/)
as an example.
In this assignment, we'll use our full-text data from Wikipedia to produce a
rudimentary metric of how popular a programming language is, in an effort to see
if our Wikipedia-based rankings bear any relation to the popular Red Monk rankings.
You'll complete this exercise on just one node (your laptop).
## Set up Spark
For the sake of simplified logistics, we'll be running Spark in "local" mode. This
means that your full Spark application will be run on one node, locally, on your
laptop.
To start, we need a `SparkContext`. A `SparkContext` is the
"handle" to your cluster. Once you have a `SparkContext`, you can use it
to create and populate RDDs with data.
To create a `SparkContext`, you need to first create a
`SparkConf` instance. A `SparkConf` represents the
configuration of your Spark application. It's here that you must specify that you
intend to run your application in "local" mode. You must also name your Spark
application at this point. For help, see the
[Spark API documentation](http://spark.apache.org/docs/latest/api/scala/org/apache/spark/index.html).
Configure your cluster to run in local mode by implementing `val conf`
and `val sc`.
## Read-in Wikipedia Data
There are several ways to read data into Spark. The simplest way to read in data
is to convert an existing collection in memory to an RDD using the
`parallelize` method of the Spark context.
We have already implemented a method `parse` in the object
`WikipediaData` object that parses a line of the dataset and turns it into a `WikipediaArticle`.
Create an `RDD` (by implementing `val wikiRdd`) which contains
the `WikipediaArticle` objects of `articles`.
## Compute a ranking of programming languages
We will use a simple metric for determining the popularity of a programming
language: the number of Wikipedia articles that mention the language at least once.
### Rank languages attempt #1: rankLangs
**Computing** `occurrencesOfLang`
Start by implementing a helper method `occurrencesOfLang` which computes
the number of articles in an `RDD` of type `RDD[WikipediaArticles]`
that mention the given language at least once. For the sake of simplicity we check
that it least one word (delimited by spaces) of the article text is equal to the given
language.
**Computing the ranking,** `rankLangs`
Using `occurrencesOfLang`, implement a method `rankLangs` which
computes a list of pairs where the second component of the pair is the number of
articles that mention the language (the first component of the pair is the name of
the language).
An example of what `rankLangs` might return might look like this, for
example:
```scala
List(("Scala", 999999), ("JavaScript", 1278), ("LOLCODE", 982), ("Java", 42))
```
The list should be sorted in descending order. That is, according to this ranking,
the pair with the highest second component (the count) should be the first element
of the list.
Pay attention to roughly how long it takes to run this part! (It should take
tens of seconds.)
### Rank languages attempt #2: rankLangsUsingIndex
**Compute an inverted index**
An inverted index is an index data structure storing a mapping from content,
such as words or numbers, to a set of documents. In particular, the purpose of
an inverted index is to allow fast full text searches. In our use-case, an
inverted index would be useful for mapping from the names of programming
languages to the collection of Wikipedia articles that mention the name at
least once.
To make working with the dataset more efficient and more convenient, implement
a method that computes an "inverted index" which maps programming language names
to the Wikipedia articles on which they occur at least once.
Implement method `makeIndex` which returns an RDD of the following type:
`RDD[(String, Iterable[WikipediaArticle])]`. This RDD contains pairs,
such that for each language in the given `langs` list there is at most
one pair. Furthermore, the second component of each pair (the `Iterable`)
contains the `WikipediaArticles` that mention the language at least once.
_Hint: You might want to use methods **`flatMap`** and
**`groupByKey`** on **`RDD`** for this part._
**Computing the ranking, `rankLangsUsingIndex`**
Use the `makeIndex` method implemented in the previous part to
implement a faster method for computing the language ranking.
Like in part 1, `rankLangsUsingIndex` should compute a list of pairs
where the second component of the pair is the number of articles that mention
the language (the first component of the pair is the name of the language).
Again, the list should be sorted in descending order. That is, according to
this ranking, the pair with the highest second component (the count) should
be the first element of the list.
_Hint: method **`mapValues`** on **`PairRDD`** could be useful
for this part._
_Can you notice a performance improvement over attempt #1? Why?_
### Rank languages attempt #3: rankLangsReduceByKey
In the case where the inverted index from above is _only_ used for computing
the ranking and for no other task (full-text search, say), it is more efficient
to use the `reduceByKey` method to compute the ranking directly,
without first computing an inverted index. Note that the `reduceByKey`
method is only defined for RDDs containing pairs (each pair is interpreted as
a key-value pair).
Implement the `rankLangsReduceByKey` method, this time computing the
ranking without the inverted index, using `reduceByKey`.
Like in part 1 and 2, `rankLangsReduceByKey` should compute a list
of pairs where the second component of the pair is the number of articles that
mention the language (the first component of the pair is the name of the language).
Again, the list should be sorted in descending order. That is, according to
this ranking, the pair with the highest second component (the count) should
be the first element of the list.
_Can you notice an improvement in performance compared to measuring both the
computation of the index and the computation of the ranking as we did in
attempt #2? If so, can you think of a reason?_
# StackOverflow
Use the following commands to make a fresh clone of your repository:
```
git clone -b stackoverflow git@gitlab.epfl.ch:lamp/student-repositories-s21/cs206-GASPAR.git cs206-stackoverflow
```
## Useful links
* [The API documentation of Spark](http://spark.apache.org/docs/latest/api/scala/org/apache/spark/index.html)
* [The API documentation of the Scala standard library](https://www.scala-lang.org/files/archive/api/2.13.4)
* [The API documentation of the Java standard library](https://docs.oracle.com/en/java/javase/15/docs/api/index.html)
**If you have issues with the IDE, try [reimporting the
build](https://gitlab.epfl.ch/lamp/cs206/-/blob/master/labs/example-lab.md#ide-features-like-type-on-hover-or-go-to-definition-do-not-work),
if you still have problems, use `compile` in sbt instead.**
## Introduction
For this assignment, you will need to download the stackoverflow dataset (84 MB):
[http://alaska.epfl.ch/~dockermoocs/bigdata/stackoverflow-grading.csv](http://alaska.epfl.ch/~dockermoocs/bigdata/stackoverflow-grading.csv)
and place it in the folder: `src/main/resources/stackoverflow` in your
project directory.
The overall goal of this assignment is to implement a distributed k-means algorithm
which clusters posts on the popular question-answer platform StackOverflow
according to their score. Moreover, this clustering should be executed in parallel
for different programming languages, and the results should be compared.
The motivation is as follows: StackOverflow is an important source of documentation.
However, different user-provided answers may have very different ratings (based on
user votes) based on their perceived value. Therefore, we would like to look at the
distribution of questions and their answers. For example, how many highly-rated
answers do StackOverflow users post, and how high are their scores? Are there big
differences between higher-rated answers and lower-rated ones?
Finally, we are interested in comparing these distributions for different
programming language communities. Differences in distributions could reflect
differences in the availability of documentation. For example, StackOverflow could
have better documentation for a certain library than that library's API
documentation. However, to avoid invalid conclusions we will focus on the
well-defined problem of clustering answers according to their scores.
## The Data
You are given a CSV (comma-separated values) file with information about
StackOverflow posts. Each line in the provided text file has the following format:
```scala
<postTypeId>,<id>,[<acceptedAnswer>],[<parentId>],<score>,[<tag>]
```
A short explanation of the comma-separated fields follows.
```scala
<postTypeId>: Type of the post. Type 1 = question,
type 2 = answer.
<id>: Unique id of the post (regardless of type).
<acceptedAnswer>: Id of the accepted answer post. This
information is optional, so maybe be missing
indicated by an empty string.
<parentId>: For an answer: id of the corresponding
question. For a question:missing, indicated
by an empty string.
<score>: The StackOverflow score (based on user
votes).
<tag>: The tag indicates the programming language
that the post is about, in case it's a
question, or missing in case it's an answer.
```
You will see the following code in the main class:
```scala
val lines = sc.textFile("src/main/resources/stackoverflow/stackoverflow-grading.csv")
val raw = rawPostings(lines)
val grouped = groupedPostings(raw)
val scored = scoredPostings(grouped)
val vectors = vectorPostings(scored)
```
It corresponds to the following steps:
1. `lines`: the lines from the csv file as strings
2. `raw`: the raw Posting entries for each line
3. `grouped`: questions and answers grouped together
4. `scored`: questions and scores
5. `vectors`: pairs of (language, score) for each question
The first two methods are given to you. You will have to implement the rest.
## Data processing
We will now look at how you process the data before applying the kmeans algorithm.
### Grouping questions and answers
The first method you will have to implement is `groupedPostings`:
```scala
val grouped = groupedPostings(raw)
```
In the `raw` variable we have simple postings, either questions or
answers, but in order to use the data we need to assemble them together. Questions
are identified using a `postTypeId == 1`. Answers to a question with
`id == QID` have (a) `postTypeId == 2` and (b) `parentId == QID`.
Ideally, we want to obtain an RDD with the pairs of `(Question, Iterable[Answer])`.
However, grouping on the question directly is expensive (can you imagine why?),
so a better alternative is to match on the QID, thus producing an
`RDD[(QID, Iterable[(Question, Answer))]`.
To obtain this, in the `groupedPostings` method, first filter the
questions and answers separately and then prepare them for a `join` operation by
extracting the QID value in the first element of a tuple. Then, use one of the
`join` operations (which one?) to obtain an `RDD[(QID, (Question, Answer))]`.
Then, the last step is to obtain an `RDD[(QID, Iterable[(Question, Answer)])]`.
How can you do that, what method do you use to group by the key of a pair RDD?
Finally, in the description we used QID, Question and Answer types, which we've
defined as type aliases for `Posting`s and `Int`s. The full list of type aliases is
available in `StackOverflow.scala`:
```scala
type Question = Posting
type Answer = Posting
type QID = Int
type HighScore = Int
type LangIndex = Int
```
The above information should allow you to implement the `groupedPostings`
method. Its signature is:
```scala
def groupedPostings(postings: RDD[Posting]):
RDD[(QID, Iterable[(Question, Answer)])]
```
### Computing Scores
Second, implement the `scoredPostings` method, which should return an
RDD containing pairs of (a) questions and (b) the score of the answer with the
highest score (note: this does **_not_** have to be the answer marked as
`acceptedAnswer`!). The type of this scored RDD is:
```scala
val scored: RDD[(Question, HighScore)] = ???
```
For example, the `scored` RDD should contain the following tuples:
```scala
((1, 6, None, None, 140, Some(CSS)), 67)
((1, 42, None, None, 155, Some(PHP)), 89)
((1, 72, None, None, 16, Some(Ruby)), 3)
((1, 126, None, None, 33, Some(Java)), 30)
((1, 174, None, None, 38, Some(C#)), 20)
```
_Hint: use the provided **`answerHighScore`** given in **`scoredPostings`**._
### Creating vectors for clustering
Next, we prepare the input for the clustering algorithm. For this, we transform
the `scored` RDD into a `vectors` RDD containing the vectors
to be clustered. In our case, the vectors should be pairs with two components
(in the listed order!):
- Index of the language (in the `langs` list) multiplied by the
`langSpread` factor.
- The highest answer score (computed above).
The `langSpread` factor is provided (set to 50000). Basically, it makes
sure posts about different programming languages have at least distance 50000
using the distance measure provided by the `euclideanDist` function.
You will learn later what this distance means and why it is set to this value.
The type of the `vectors` RDD is as follows:
```scala
val vectors: RDD[(LangIndex, HighScore)] = ???
```
For example, the `vectors` RDD should contain the following tuples:
```scala
(350000, 67)
(100000, 89)
(300000, 3)
(50000, 30)
(200000, 20)
```
Implement this functionality in method `vectorPostings` and by using
the given `firstLangInTag` helper method.
_(Idea for test: **`scored`** RDD should have 1042132 entries)_
## Kmeans Clustering
```scala
val means = kmeans(sampleVectors(vectors), vectors)
```
Based on these initial means, and the provided variables `converged`
method, implement the K-means algorithm by iteratively:
- pairing each vector with the index of the closest mean (its cluster);
- computing the new means by averaging the values of each cluster.
To implement these iterative steps, use the provided functions
`findClosest`, `averageVectors`, and `euclideanDistance`.
**Note 1:**
In our tests, convergence is reached after 44 iterations (for `langSpread = 50000`)
and in 104 iterations (for `langSpread = 1`), and for the first iterations the
distance kept growing. Although it may look like something is wrong, this is the
expected behavior. Having many remote points forces the kernels to shift quite a
bit and with each shift the effects ripple to other kernels, which also move around,
and so on. Be patient, in 44 iterations the distance will drop from over 100000 to
13, satisfying the convergence condition.
If you want to get the results faster, feel free to downsample the data (each
iteration is faster, but it still takes around 40 steps to converge):
```scala
val scored = scoredPostings(grouped).sample(true, 0.1, 0)
```
However, keep in mind that we will test your assignment on the full data set. So
that means you can downsample for experimentation, but make sure your algorithm
works on the full data set when you submit for grading.
**Note 2:**
The variable `langSpread` corresponds to how far away are languages from
the clustering algorithm's point of view. For a value of 50000, the languages are
too far away to be clustered together at all, resulting in a clustering that only
takes scores into account for each language (similarly to partitioning the data
across languages and then clustering based on the score). A more interesting (but
less scientific) clustering occurs when `langSpread` is set to 1 (we can't
set it to 0, as it loses language information completely), where we cluster according
to the score. See which language dominates the top questions now?
## Computing Cluster Details
After the call to kmeans, we have the following code in method `main`:
```scala
val results = clusterResults(means, vectors)
printResults(results)
```
Implement the `clusterResults` method, which, for each cluster, computes:
- (a) the dominant programming language in the cluster;
- (b) the percent of answers that belong to the dominant language;
- (c) the size of the cluster (the number of questions it contains);
- (d) the median of the highest answer scores.
Once this value is returned, it is printed on the screen by the `printResults`
method.
## Questions
- Do you think that partitioning your data would help?
- Have you thought about persisting some of your data? Can you think of why persisting your data in memory may be helpful for this algorithm?
- Of the non-empty clusters, how many clusters have "Java" as their label (based on the majority of questions, see above)? Why?
- Only considering the "Java clusters", which clusters stand out and why?
- How are the "C# clusters" different compared to the "Java clusters"?
**Hint:** if you break the grader's time or memory constraints, think of how partitioning or persisting could, if at all, help you gain some performance. Please note that our grader only runs unit tests against your methods. It won't run the **main** method, so make sure to place any caching or partitioning code outside the **main**.
# Tools Setup
## Note
We recommend using Linux or macOS for this course, we also support Windows but
typically people have more trouble getting everything working correctly on
Windows and it's harder for us to help them since we don't use Windows
ourselves.
**On Windows, if your username has spaces or special characters in it, the IDE might not
work properly. Please create a new user with a username containing only letters.**
# Step 1: Create an account on gitlab.epfl.ch
If you haven't already [log into gitlab](https://gitlab.epfl.ch/users/sign_in)
and fill in [this table](https://docs.google.com/spreadsheets/d/1rcq_UMgR6bAH-iK1L2I6WoClZtCqUoIOLqQO3NJKdgg) with your GASPAR and SCIPER number to initialize your GitLab repository for the course. Do this as soon as possible because it will take some time between the account creation and the lab submission system working for your account.
## Step 2: Installing the Java Development Kit (JDK) and sbt via coursier
We will use coursier to install the correct version of
Java as well as the sbt build tool:
### On Linux
```shell
curl -fLo cs https://git.io/coursier-cli-linux
```
```shell
chmod +x cs
```
```shell
./cs setup -y --jvm 8 --apps cs,sbt
```
Please reboot after this point.
### On macOS
First, install the Homebrew package manager:
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
Use Homebrew to install coursier:
```scala
brew install coursier/formulas/coursier
```
```shell
[ -f ~/.bash_profile ] && sudo chmod 0666 ~/.bash_profile
```
```shell
cs setup -y --jvm 8 --apps sbt
```
Please close this terminal and open a new one after this point.
### On Windows
Download and install the [Visual C++ 2010 SP1 Redistributable Package](https://www.microsoft.com/en-us/download/details.aspx?id=13523).
Open `cmd.exe` (and not powershell)
First, make sure that you are not in the `System32` directory, instead you
should be in `C:\Users\yourusername`. If you are in `System32` you will need to
change directory to your user directory every time you start a terminal by
running:
```shell
cd %USERPROFILE%
```
Now assuming that you're in the correct directory you can run:
```shell
bitsadmin /transfer cs-cli https://git.io/coursier-cli-windows-exe "%cd%\cs.exe"
```
```shell
.\cs setup -y --jvm 8 --apps cs,sbt
```
(This command might cause your anti-virus to misidentify cs.exe as a virus,
please override that, that might require temporarily turning off your anti-virus
during this setup).
If this command fails with `Error running powershell script`, use the following
alternative instructions (if the command didn't fail, continue to the next
step):
1. Run `.\cs setup --jvm 8 --apps cs,sbt`, at every question answer "n" and
press Enter.
2. The last question should look like "Should we add `C:\...\bin` to your PATH?",
please copy the `C:\...\bin` part here.
3. Edit the Path environment variable and paste the path you just copied to it, see
https://www.architectryan.com/2018/08/31/how-to-change-environment-variables-on-windows-10/
and make sure the path you're adding is the first entry in the Path environment
variable.
4. Start a **new** cmd.exe and continue with the rest of the instructions
**In case of errors please ask on Discord or Gitlab issues for help, but don't
try to run commands as Administrator as this will likely cause further issues!**
Please close this terminal and open a new one after this point.
## Step 5: Installing git
git is a version control system.
### On Ubuntu and Debian
```shell
sudo apt update && sudo apt install git
```
### On macOS
```shell
brew install git
```
### On Windows
Download and install git from [https://git-scm.com/downloads](https://git-scm.com/downloads).
Once git is installed, open a **new** terminal and run:
```shell
git config --global core.autocrlf false
```
If this command worked it will not print anything.
## Step 6: Installing Code
Visual Studio Code is the IDE we strongly recommend using for this class (you are free to use any editor you want, but we won't don't have the resources to help you configure it for Scala).
### On Linux
See [https://code.visualstudio.com/docs/setup/linux](https://code.visualstudio.com/docs/setup/linux)
### On macOS
```shell
brew install --cask visual-studio-code
```
### On Windows
See [https://code.visualstudio.com/docs/setup/windows](https://code.visualstudio.com/docs/setup/windows).
Make sure that the checkbox "Add to PATH (available after restart)" in the
installer is checked.
## Step 7: Installing the Scala support for Code
Open a **new** terminal and run:
```scala
code --install-extension lampepfl.dotty-syntax
```
If you're on Windows and the command is not found, try closing and restarting
the terminal, if that doesn't work
## Step 8: Generate a public/private SSH key pair
To submit labs, you will need an SSH key. If you don't already have one, here's how to generate it:
### Step 8.1: Installing OpenSSH
#### On Ubuntu and Debian
```shell
sudo apt update && sudo apt install openssh-client
```
#### On macOS
Nothing to do, OpenSSH is pre-installed
#### On Windows
Follow the instructions under "Enable OpenSSH Client in Windows 10" on
[https://winaero.com/blog/enable-openssh-client-windows-10/](https://winaero.com/blog/enable-openssh-client-windows-10/)
### Step 8.2: Generating the key pair
Open a **new** terminal and run:
```shell
ssh-keygen -t rsa -b 4096 -C "youremail@example.com"
```
The command will then ask for a location, which you can leave as the default. It will then also ask for a passphrase to encrypt your private key, which you may leave empty. If you don't, make sure to remember your passphrase!
### Adding your public key on Gitlab
To be able to push your code, you'll need to add the public part of your key on Gitlab:
- Go to [gitlab.epfl.ch](https://gitlab.epfl.ch), log in with your EPFL account
- Go to [gitlab.epfl.ch/profile/keys](https://gitlab.epfl.ch/profile/keys) and copy-paste the content of the `id_rsa.pub` file created by the `ssh-keygen` command you just ran (when the command was ran it printed the location where this file was saved).
- Press `Add key`
## Step 9: Follow the example lab
Time to do the [example lab](example-lab.md)!