code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
  <!--Created by yEd 3.21-->
  <key attr.name="Description" attr.type="string" for="graph" id="d0"/>
  <key for="port" id="d1" yfiles.type="portgraphics"/>
  <key for="port" id="d2" yfiles.type="portgeometry"/>
  <key for="port" id="d3" yfiles.type="portuserdata"/>
  <key attr.name="url" attr.type="string" for="node" id="d4"/>
  <key attr.name="description" attr.type="string" for="node" id="d5"/>
  <key for="node" id="d6" yfiles.type="nodegraphics"/>
  <key for="graphml" id="d7" yfiles.type="resources"/>
  <key attr.name="url" attr.type="string" for="edge" id="d8"/>
  <key attr.name="description" attr.type="string" for="edge" id="d9"/>
  <key for="edge" id="d10" yfiles.type="edgegraphics"/>
  <graph edgedefault="directed" id="G">
    <data key="d0" xml:space="preserve"/>
    <node id="n0">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="503.0" y="298.0"/>
          <y:Fill color="#99CCFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="12.208984375" x="8.8955078125" xml:space="preserve" y="6.015625">A<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n1">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="595.9936" y="298.0"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="12.232421875" x="8.8837890625" xml:space="preserve" y="6.015625">B<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n2">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="688.9872" y="298.0"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="12.37890625" x="8.810546875" xml:space="preserve" y="6.015625">C<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n3">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="781.9808" y="298.0"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="13.240234375" x="8.3798828125" xml:space="preserve" y="6.015625">D<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n4">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="503.0" y="378.296"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="10.90234375" x="9.548828125" xml:space="preserve" y="6.015625">F<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n5">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="595.9936" y="378.296"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="13.298828125" x="8.3505859375" xml:space="preserve" y="6.015625">G<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n6">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="688.9872" y="378.296"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="13.0234375" x="8.48828125" xml:space="preserve" y="6.015625">H<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n7">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="781.9808" y="378.296"/>
          <y:Fill color="#FF6600" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="13.0" y="13.0">
            <y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n8">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="503.0" y="458.592"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.5390625" x="11.23046875" xml:space="preserve" y="6.015625">J<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n9">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="595.9936" y="458.592"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.869140625" x="9.0654296875" xml:space="preserve" y="6.015625">K<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n10">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="688.9872" y="458.592"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="10.685546875" x="9.6572265625" xml:space="preserve" y="6.015625">L<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n11">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="781.9808" y="458.592"/>
          <y:Fill color="#FF6600" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="13.0" y="13.0">
            <y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n12">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="503.0" y="538.8879999999999"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="12.9765625" x="8.51171875" xml:space="preserve" y="6.015625">N<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n13">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="595.9936" y="538.8879999999999"/>
          <y:Fill color="#FF6600" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="13.0" y="13.0">
            <y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n14">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="688.9872" y="538.8879999999999"/>
          <y:Fill color="#FF6600" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="13.0" y="13.0">
            <y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n15">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="781.9808" y="538.8879999999999"/>
          <y:Fill color="#FF6600" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="4.0" x="13.0" y="13.0">
            <y:LabelModel>
              <y:SmartNodeLabelModel distance="4.0"/>
            </y:LabelModel>
            <y:ModelParameter>
              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
            </y:ModelParameter>
          </y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n16">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="874.9744000000001" y="298.0"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.58203125" x="9.208984375" xml:space="preserve" y="6.015625">E<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n17">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="874.9744000000001" y="378.296"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="7.5390625" x="11.23046875" xml:space="preserve" y="6.015625">I<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n18">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="874.9744000000001" y="458.592"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="14.353515625" x="7.8232421875" xml:space="preserve" y="6.015625">M<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n19">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="874.9744000000001" y="538.8879999999999"/>
          <y:Fill color="#CCFFCC" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="13.4453125" x="8.27734375" xml:space="preserve" y="6.015625">O<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n20">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="503.0" y="619.1839999999999"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.236328125" x="9.3818359375" xml:space="preserve" y="6.015625">P<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n21">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="595.9936" y="619.1839999999999"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="13.4453125" x="8.27734375" xml:space="preserve" y="6.015625">Q<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n22">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="688.9872" y="619.1839999999999"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="12.337890625" x="8.8310546875" xml:space="preserve" y="6.015625">R<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n23">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="781.9808" y="619.1839999999999"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.6171875" x="9.19140625" xml:space="preserve" y="6.015625">S<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <node id="n24">
      <data key="d6">
        <y:ShapeNode>
          <y:Geometry height="30.0" width="30.0" x="874.9744000000001" y="619.1839999999999"/>
          <y:Fill color="#FFFFFF" transparent="false"/>
          <y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.330078125" x="9.3349609375" xml:space="preserve" y="6.015625">T<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:Shape type="roundrectangle"/>
        </y:ShapeNode>
      </data>
    </node>
    <edge id="e0" source="n0" target="n1">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649693066406257" xml:space="preserve" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e1" source="n1" target="n2">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649701757812522" xml:space="preserve" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e2" source="n2" target="n3">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649710449218787" xml:space="preserve" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e3" source="n0" target="n4">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.634765625" xml:space="preserve" y="16.147328613281275">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e4" source="n4" target="n8">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.634765625" xml:space="preserve" y="16.147338623046835">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e5" source="n8" target="n12">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.634765625" xml:space="preserve" y="16.147318115234384">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e6" source="n16" target="n17">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.63479189453119" xml:space="preserve" y="16.147328613281275">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e7" source="n17" target="n18">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.63479189453119" xml:space="preserve" y="16.147338623046835">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e8" source="n18" target="n19">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.63479189453119" xml:space="preserve" y="16.147318115234384">4<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e9" source="n3" target="n16">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649719140625052" xml:space="preserve" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e10" source="n2" target="n6">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.63474824218747" xml:space="preserve" y="16.147328613281275">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e11" source="n6" target="n10">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.63474824218747" xml:space="preserve" y="16.147338623046835">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e12" source="n9" target="n10">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649701757812522" xml:space="preserve" y="1.9999895019531095">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e13" source="n5" target="n9">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.634756933593735" xml:space="preserve" y="16.147338623046835">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e14" source="n5" target="n6">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649701757812522" xml:space="preserve" y="2.0000100097656173">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e15" source="n1" target="n5">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.634756933593735" xml:space="preserve" y="16.147328613281275">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e16" source="n4" target="n5">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649693066406257" xml:space="preserve" y="2.0000100097656173">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e17" source="n8" target="n9">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649693066406257" xml:space="preserve" y="1.9999895019531095">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e18" source="n19" target="n24">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.63479189453119" xml:space="preserve" y="16.14732812499983">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e19" source="n23" target="n24">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649719140625052" xml:space="preserve" y="1.9999790039061054">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e20" source="n22" target="n23">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649710449218787" xml:space="preserve" y="1.9999790039061054">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e21" source="n21" target="n22">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649701757812522" xml:space="preserve" y="1.9999790039061054">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e22" source="n20" target="n21">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="25.649693066406257" xml:space="preserve" y="1.9999790039061054">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
    <edge id="e23" source="n12" target="n20">
      <data key="d10">
        <y:PolyLineEdge>
          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
          <y:LineStyle color="#000000" type="line" width="1.0"/>
          <y:Arrows source="none" target="none"/>
          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" horizontalTextPosition="center" iconTextGap="4" modelName="side_slider" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" verticalTextPosition="bottom" visible="true" width="11.634765625" x="-13.634765625" xml:space="preserve" y="16.14732812499983">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/></y:EdgeLabel>
          <y:BendStyle smoothed="false"/>
        </y:PolyLineEdge>
      </data>
    </edge>
  </graph>
  <data key="d7">
    <y:Resources/>
  </data>
</graphml>


code:
(list (channel
        (name 'guix)
        (url "https://git.savannah.gnu.org/git/guix.git")
        (branch "master")
        (commit
          "c50cd1bbece27097456242f246f89c053e7cc1a2")
        (introduction
          (make-channel-introduction
            "9edb3f66fd807b096b48283debdcddccfea34bad"
            (openpgp-fingerprint
              "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))

repo_name: ZelphirKaltstahl/guile

license: mit


code:
#!/usr/bin/env bash

set -Eeuxo pipefail

DIR=$(dirname "$(readlink -f "${0}")")

guix time-machine \
     --channels="${DIR}/channels.scm" -- \
     shell \
     --manifest="${DIR}/manifest.scm" \
     --development \
     --check \
     --cores=8


code:
(specifications->manifest
 '("guile"
   "guile-pfds"))


code:
(library (a-star)
  (export A*)
  (import (except (rnrs base)
                  let-values
                  map)
          (only (guile)
                lambda* λ
                when
                unless
                simple-format
                string<?
                call-with-output-string)
          (ice-9 pretty-print)
          (srfi srfi-1)  ; lists
          (srfi srfi-69)  ; hash tables
          (srfi srfi-11)  ; let-values
          ;; Functional Sets
          (pfds sets)
          ;; Priority Search Queues
          (pfds psqs)
          (priority-search-queues)
          ;; Bounded Balance Trees
          (pfds bbtrees)
          (graph-model))

  (define A*
    (lambda* (start
              target
              node-names
              nodes-table
              get-neighbor-distance
              cost-heuristic
              distance<)
      (let ([fringe (psq-set (make-psq string<? <)
                             ;; Initially put the start node in the open-set,
                             ;; since we need at least some node to go on from.
                             (node-name start)
                             ;; The start node has priority 0, which is the
                             ;; highest priority. It does not really matter,
                             ;; since there is only one element in the open-set.
                             0)]
            ;; routes stores the node preceding any target node on the cheapest
            ;; path to that target node. Initially only the preceding node for
            ;; the start node is set. The start node itself.
            [routes (alist->hash-table (list (cons (node-name start)
                                                   (node-name start)))
                                       string=?)]
            ;; score stores the cost of the cheapest path from the start node to
            ;; other nodes as currently known. Initially it is only set for the
            ;; start node, as one does not know other costs yet.
            [cheapest-path-costs
             (alist->hash-table `((,(node-name start) . 0)) string=?)]
            ;; Also keep track of a best estimate (calculated using the
            ;; heuristic) of the cost from the start node to the target node via
            ;; a node. Initially we have not explored any other nodes than the
            ;; start node, so the cost for any path via them to the target node
            ;; is pessimistically estimated to be infinite. Update formula:
            ;; via-node-cost-estimate(node) := current-best-score(node) + heuristic(node).
            [via-node-cost-estimate (make-hash-table string=?)])

        ;; Set cost estimate for start node.
        (for-each (λ (name)
                    (hash-table-set! via-node-cost-estimate
                                     name
                                     +inf.0))
                  node-names)

        (for-each (λ (name)
                    (unless (string=? name (node-name start))
                      (hash-table-set! cheapest-path-costs
                                       name
                                       +inf.0)))
                  node-names)

        (hash-table-set! via-node-cost-estimate
                         (node-name start)
                         (cost-heuristic start target))

        (simple-format #t "search begins\n")

        (let iter
            (;; The current-node-name° is the one, that is estimated
             ;; to have the lowest cost, when a path to the target
             ;; contains it. Initially this should be the start node,
             ;; because there is only one node in the fringe.
             [current-node-name° (psq-min fringe)]
             [fringe° fringe]
             [visited° (set-insert (make-set string<?) (node-name start))])

          (simple-format #t "fringe: ~a\n" (psq->list fringe°))
          (simple-format #t "current node: ~a\n" current-node-name°)

          (cond
           ;; If the current node is the target node, return the routes.
           [(string=? current-node-name° (node-name target))
            (simple-format
             #t "reached the target, returning routes:\n~a\n"
             (call-with-output-string
               (λ (port)
                 (pretty-print (hash-table->alist routes) port))))
            routes]
           [else
            (let ([neighbor-names
                   (node-neighbors (hash-table-ref nodes-table current-node-name°))])

              ;; Per neighbor node update the following: routes, cheapest path
              ;; cost, via node path cost estimate
              (for-each (λ (neighbor-name)
                          ;; (cond
                          ;;  ;; [(set-member? visited° neighbor-name)
                          ;;  ;;  (simple-format
                          ;;  ;;   #t "node ~a is already visited ignoring it as a neighbor\n"
                          ;;  ;;   neighbor-name)
                          ;;  ;;  (let-values ([(_node-name-of-min fringe-without-current) (psq-pop fringe°)])
                          ;;  ;;    (iter fringe-without-current visited°))]
                          ;;  [else ...])
                          (let* ([distance
                                  (get-neighbor-distance current-node-name° neighbor-name)]
                                 ;; At first the tentative score is the distance
                                 ;; from the start to the neighbor going via the
                                 ;; current node.
                                 [tentative-score
                                  (+ (hash-table-ref cheapest-path-costs
                                                     current-node-name°)
                                     distance)])

                            ;; If we have found a cheaper path to the neighbor
                            ;; ...
                            (when (< tentative-score
                                     (hash-table-ref cheapest-path-costs
                                                     neighbor-name))

                              ;; ... update the preceding node on the path to
                              ;; the neighbor in the routes map ...
                              (hash-table-set! routes
                                               neighbor-name
                                               current-node-name°)
                              ;; ... and update the cheapest path costs for the
                              ;; neighbor ...
                              (hash-table-set! cheapest-path-costs
                                               neighbor-name
                                               tentative-score)
                              ;; ... and update the estimates of the cost of a
                              ;; path from the start node through the neighbor
                              ;; to the target node.
                              (hash-table-set! via-node-cost-estimate
                                               neighbor-name
                                               (+ tentative-score
                                                  (cost-heuristic
                                                   (hash-table-ref nodes-table current-node-name°)
                                                   (hash-table-ref nodes-table neighbor-name)))))))
                        neighbor-names)
              (let ([updated-fringe
                     (fold (λ (node-name fringe-acc)
                             ;; Avoid adding visited nodes back to the
                             ;; fringe, to avoid going in circles.
                             (if (set-member? visited° node-name)
                                 fringe-acc
                                 (psq-set fringe-acc
                                          node-name
                                          (hash-table-ref cheapest-path-costs
                                                          node-name))))
                           ;; Remove the current node from the fringe.
                           ;; -- It is now visited and should not be
                           ;; visited again.
                           (psq-delete fringe° current-node-name°)
                           ;; For all neighbors update the
                           ;; fringe. The fringe is a priority search
                           ;; queue, which will have the minimum item
                           ;; readily available at the beginning of
                           ;; the next iteration.
                           neighbor-names)])
                (cond
                 [(psq-empty? updated-fringe)
                  ;; TODO: add proper exception type
                  (error 'A*
                         (call-with-output-string
                           (λ (port)
                             (simple-format port "no path found from start node to target node")))
                         (node-name start)
                         (node-name target))]
                 [else
                  (iter (psq-min updated-fringe)
                        updated-fringe
                        (set-insert visited° current-node-name°))])))]))))))


code:
(library (dijkstra)
  (export dijkstra-shortest-path)
  (import (except (rnrs base)
                  let-values
                  map)
          (only (guile)
                lambda* λ
                when
                simple-format)
          (ice-9 pretty-print)
          (srfi srfi-1)  ; lists
          (srfi srfi-69)  ; hash tables
          ;; Functional Sets
          (pfds sets)
          ;; Priority Search Queues
          (pfds psqs)
          ;; Bounded Balance Trees
          (pfds bbtrees))

  (define make-empty-set
    (λ (less?)
      (make-set less?)))

  (define set-insert-multiple
    (λ (myset items)
      (cond
       [(null? items) myset]
       [else
        (set-insert-multiple (set-insert myset (car items))
                             (cdr items))])))

  (define set-empty?
    (λ (set)
      (= (set-size set) 0)))

  (define dijkstra-shortest-path
    (lambda* (start-node
              nodes
              get-neighbors
              get-neighbor-distance
              node<
              #:key
              (distance< <))
      "Find the shortest paths between the START-NODE and all other NODES,
given:

GET-NEIGHBORS: A function, that maps from an actual node struct to a list
of node structures.

GET-NEIGHBOR-DISTANCE: A function that returns the distance from one
node to another.

NODE<: A less function, that introduces an order to nodes. This is
important for the underlying functional set implementation.

DISTANCE<: A less function for comparing distances. This is useful for
comparing distances, that are not mere numbers, but might consist of
several attributes. For example how many times a person needs to
change means of transportation to arrive at a destination."
      (define init-unvisited-nodes (set-insert-multiple (make-empty-set node<) nodes))
      (define init-visited-nodes (make-empty-set node<))
      (define init-distances
        (alist->hash-table
         (map (λ (node)
                (if (equal? node start-node)
                    (cons node 0)
                    (cons node +inf.0)))
              nodes)))
      ;; Set distance from start node to itself to 0.
      (define init-routes-table
        (alist->hash-table (list (cons start-node start-node))
                           eq?))

      ;; (hash-table-set! init-distances start-node 0)
      ;; (hash-table-set! init-routes-table start-node start-node)
      ;; Visit an unvisited node with shortest known distance from start
      ;; node. Initially the start node, since all other nodes still have infinite
      ;; distance.
      (let iter ([current-node start-node]
                 [distances° init-distances]
                 [unvisited° init-unvisited-nodes]
                 [visited° init-visited-nodes]
                 [routes° init-routes-table])
        (cond
         ;; Stop, if there are no more unvisited nodes.
         [(set-empty? unvisited°)
          (values distances° routes°)]
         [else
          ;; Calculate distance to every unvisited neighbor from the start
          ;; node. The distance is the distance to current node plus distance to
          ;; the unvisted neighbor).
          (let* ([neighbors (get-neighbors current-node)]
                 ;; Only look at unvisited neighbors.
                 [unvisited-neighbors
                  (filter (λ (neighbor) (set-member? unvisited° neighbor))
                          neighbors)])
            (cond
             ;; If this particular node does not have any unvisited neighbors, go
             ;; back to visiting the next node.
             [(null? unvisited-neighbors)
              ;; Repeat until all nodes visited.
              (iter (set-fold (λ (node acc)
                                (cond [(null? acc) node]
                                      [(distance< (hash-table-ref distances° node)
                                                  (hash-table-ref distances° acc))
                                       node]
                                      [else acc]))
                              '()
                              unvisited°)
                    distances°
                    ;; Mark current node as visited.
                    (set-remove unvisited° current-node)
                    (set-insert visited° current-node)
                    routes°)]
             [else
              ;; Look at the distances to all neighbors and update distances and
              ;; routes accordingly.
              (for-each (λ (neighbor)
                          (let ([start-to-neighbor-distance
                                 (+ (hash-table-ref distances° current-node)
                                    (get-neighbor-distance current-node neighbor))])
                            ;; If distance from the start node to a neighbor node
                            ;; is less than previously known distance for that
                            ;; node, update that distance in the distances
                            ;; table. If a distance is updated, also update what
                            ;; that node's previous node on the path to the node
                            ;; is (the current node).
                            (when (distance< start-to-neighbor-distance
                                             (hash-table-ref distances° neighbor))
                              ;; WARNING: Mutation here! Need
                              ;; something like a functional hash
                              ;; table here ...
                              (hash-table-set! distances°
                                               neighbor start-to-neighbor-distance)
                              (hash-table-set! routes°
                                               neighbor current-node))))
                        unvisited-neighbors)
              ;; Continue with unvisted nodes.
              (iter (set-fold (λ (node acc)
                                (cond [(null? acc) node]
                                      [(distance< (hash-table-ref distances° node)
                                                  (hash-table-ref distances° acc))
                                       node]
                                      [else acc]))
                              '()
                              unvisited°)
                    distances°
                    ;; Mark current node as visited.
                    (set-remove unvisited° current-node)
                    (set-insert visited° current-node)
                    routes°)]))])))))


code:
(library (debug)
  (export debug-peek
          pretty-peek)

  (import
   (except (rnrs base)
           let-values
           map
           error
           vector-map)
   (only (guile)
         lambda* λ
         simple-format
         current-output-port
         call-with-output-string)
   (ice-9 pretty-print))

  (define debug-peek
    (lambda* (sth #:optional (message ""))
      (let ([as-string
             (call-with-output-string
               (λ (port)
                 (simple-format port "~a" sth)))])
        (simple-format (current-output-port)
                       "~a~a\n"
                       message
                       as-string)
        sth)))

  (define pretty-peek
    (lambda* (thing
              #:optional (port (current-output-port))
              #:key
              (width 80)
              (max-expr-width 80)
              (display? #t)
              (per-line-prefix "")
              (select (λ (thing) thing)))
      (pretty-print (select thing)
                    #:port port
                    #:width width
                    #:max-expr-width max-expr-width
                    #:display? display?
                    #:per-line-prefix per-line-prefix)
      thing)))


code:
(library (distances)
  (export manhattan)
  (import
   (except (rnrs base) let-values map error)
   (only (guile)
         lambda* λ))

  (define manhattan
    (λ (y1 y2 x1 x2)
      (+ (abs (- y1 y2))
         (abs (- x1 x2))))))


code:
(library (fileio)
  (export get-string-from-file
          get-lines-from-file
          get-lines-from-port
          get-lines-from-file-using-splitting
          put-lines-to-file
          put-string-to-file)
  (import
   (except (rnrs base)
           let-values
           map)
   (only (guile)
         lambda* λ
         ;; ports and files
         call-with-input-file
         call-with-output-file
         set-port-encoding!
         eof-object?
         ;; string
         string-split
         string-join)
   (ice-9 textual-ports)  ; for textual reading and writing procedures
   (ice-9 binary-ports)  ; not sure if needed
   (ice-9 rdelim)  ; for `eof-object?`
   (ice-9 optargs)  ; for keyword arguments
   ;; not sure if needed
   (srfi srfi-1))

  (define get-string-from-file
    (lambda* (file-path
              #:key
              (encoding "UTF-8"))
      (call-with-input-file file-path
        (λ (port)
          (set-port-encoding! port encoding)
          (get-string-all port)))))

  (define get-lines-from-file
    (lambda* (file-path
              #:key
              (encoding "UTF-8"))
      ;; another common encoding is: "ISO-8859-1"
      ;; see http://www.iana.org/assignments/character-sets for more
      (define (get-lines-from-port port)
        (let ([line (get-line port)])
          (cond [(eof-object? line) '()]
                [else
                 (cons line
                       (get-lines-from-port port))])))
      (call-with-input-file file-path
        (λ (port)
          (set-port-encoding! port encoding)
          (get-lines-from-port port)))))

  (define get-lines-from-file-using-splitting
    (lambda* (file-path
              #:key
              (encoding "UTF-8"))
      (string-split (get-string-from-file file-path #:encoding encoding)
                    ;; You could use simple character here, but I am using
                    ;; lambda to show that it can be used as well.
                    (λ (char) (char=? char #\newline)))))

  (define put-lines-to-file
    (lambda* (file-path
              lines
              #:key
              (encoding "UTF-8")
              (mode 'replace))
      (call-with-output-file file-path
        (λ (port)
          (set-port-encoding! port encoding)
          (put-string port
                      (cond
                       [(eq? mode 'append)
                        (string-append (get-string-from-file
                                        file-path
                                        #:encoding encoding)
                                       "\n"
                                       (string-join lines "\n"))]
                       [(equal? mode 'replace) (string-join lines "\n")]
                       [else (string-join lines "\n")]))))))

  (define put-string-to-file
    (lambda* (file-path
              string
              #:key
              (encoding "UTF-8")
              (mode 'replace))
      (call-with-output-file file-path
        (λ (port)
          (set-port-encoding! port encoding)
          (put-string port
                      (cond
                       [(eq? mode 'append)
                        (string-append (get-string-from-file
                                        file-path
                                        #:encoding encoding)
                                       "\n"
                                       string)]
                       [(equal? mode 'replace) string]
                       [else string])))))))


code:
(library (grammar-basics)
  (export NUMBER
          SPACE
          COMMA
          ARROW
          ANYTHING-EXCEPT-SPACE)
  (import (except (rnrs base)
                  let-values
                  map
                  error
                  vector-map)
          (only (guile)
                lambda* λ)
          ;; standard library
          (ice-9 peg))

  (define-peg-pattern NUMBER body (and (? (or "-" "+")) (+ (range #\0 #\9))))
  (define-peg-pattern SPACE none " ")
  (define-peg-pattern COMMA none ",")
  (define-peg-pattern ARROW none "->")
  (define-peg-pattern ANYTHING-EXCEPT-SPACE body
    (* (and (not-followed-by SPACE) peg-any))))


code:
(library (graph-grammar)
  (export Y
          X
          COORDS
          NODE-NAME
          NODE
          ASSOC-NODE-NAME
          SOURCE-NODE-NAME
          TARGET-NODE-NAME
          WEIGHT
          ASSOCIATION)
  (import (except (rnrs base)
                  let-values
                  map
                  error
                  vector-map)
          (only (guile)
                lambda* λ)

   ;; standard library
   (ice-9 peg)
   (grammar-basics))

  (define-peg-pattern Y all NUMBER)
  (define-peg-pattern X all NUMBER)
  (define-peg-pattern COORDS all (and Y COMMA X))
  (define-peg-pattern NODE-NAME all (+ ANYTHING-EXCEPT-SPACE))
  (define-peg-pattern NODE all (and NODE-NAME SPACE COORDS))

  (define-peg-pattern ASSOC-NODE-NAME body (+ ANYTHING-EXCEPT-SPACE))
  (define-peg-pattern SOURCE-NODE-NAME all ASSOC-NODE-NAME)
  (define-peg-pattern TARGET-NODE-NAME all ASSOC-NODE-NAME)
  (define-peg-pattern WEIGHT all NUMBER)

  (define-peg-pattern ASSOCIATION all
    (and SOURCE-NODE-NAME SPACE
         ARROW SPACE
         TARGET-NODE-NAME SPACE
         WEIGHT)))


code:
(library (graph-model)
  (export <node>
          node?
          construct-node
          node-name
          set-node-name
          node-y
          set-node-y
          node-x
          set-node-x
          node-neighbors
          set-node-neighbors
          make-node
          node<)
  (import (except (rnrs base)
                  let-values
                  map
                  error
                  vector-map)
          (only (guile)
                lambda* λ)
          ;; functional records
          (srfi srfi-9 gnu))

  (define-immutable-record-type <node>
    (construct-node name y x neighbors)
    node?
    (name node-name set-node-name)
    (y node-y set-node-y)
    (x node-x set-node-x)
    (neighbors node-neighbors set-node-neighbors))

  (define make-node
    (lambda* (name y x #:key (neighbors '()))
      (construct-node name y x neighbors)))

  (define node<
    (λ (n1 n2)
      (or (< (node-y n1) (< node-y n2))
          (and (= (node-y n1) (< node-y n2))
               (< (node-x n1) (< node-x n2)))))))


code:
(library (graph-reader)
  (export read-graph)
  (import (except (rnrs base)
                  let-values
                  map
                  error
                  vector-map)
          (only (guile)
                lambda* λ
                ;; strings
                string-null?
                ;; lists
                map
                ;; output
                simple-format
                current-output-port)

          ;; standard library
          (ice-9 pretty-print)
          (ice-9 peg)
          (ice-9 match)
          ;; (ice-9 format)

          ;; custom modules
          (fileio)
          (pipeline)
          (debug)
          (list-helpers)

          ;; parsing
          (prefix (peg-tree-utils) peg-tree:)

          ;; lists
          (except (srfi srfi-1) split-at map)
          ;; receive
          (srfi srfi-8)
          ;; functional records
          (srfi srfi-9 gnu)
          ;; hash tables
          (srfi srfi-69)
          ;; let-values
          (srfi srfi-11)

          (graph-grammar)
          (graph-model))

  (define parse-nodes
    (λ (line)
      (peg:tree
       (match-pattern NODE line))))

  (define node-parse-tree->node
    (λ (tree)
      (make-node (car (peg-tree:tree-refs tree '(NODE NODE-NAME)))
                 (string->number (car (peg-tree:tree-refs tree '(NODE COORDS Y))))
                 (string->number (car (peg-tree:tree-refs tree '(NODE COORDS X)))))))

  (define parse-associations
    (λ (line)
      (-> line
          (match-pattern ASSOCIATION)
          peg:tree)))

  (define assoc-parse-trees->neighbor-assocs
    (λ (assocs-parse-trees)
      (let iter
          ([trees° assocs-parse-trees]
           [previous-node-name°
            (car (peg-tree:tree-refs (first assocs-parse-trees)
                                     '(SOURCE-NODE-NAME)))]
           [neighbors° '()]
           [nodes-to-neighbors° '()])
        (cond
         [(null? trees°)
          (alist->hash-table
           (cons (cons previous-node-name° neighbors°)
                 nodes-to-neighbors°))]
         [else
          (let* ([tree (first trees°)]
                 [source-node-name
                  (car (peg-tree:tree-refs tree '(SOURCE-NODE-NAME)))]
                 [neighbor-name
                  (car (peg-tree:tree-refs tree '(TARGET-NODE-NAME)))])
            (cond
             [(string=? source-node-name previous-node-name°)
              (iter (drop trees° 1)
                    previous-node-name°
                    (cons neighbor-name neighbors°)
                    nodes-to-neighbors°)]
             [else
              (iter (drop trees° 1)
                    source-node-name
                    (list neighbor-name)
                    (cons (cons previous-node-name° neighbors°)
                          nodes-to-neighbors°))]))]))))

  (define assoc-parse-trees->distances
    (λ (assoc-parse-trees nodes-table)
      "Take a list of parse trees and return a map from 2 nodes
which have a neighbor relationship to the distance between
them."
      (let iter
          ([trees° assoc-parse-trees]
           [nodes-to-neighbors° '()])
        (cond
         [(null? trees°)
          (alist->hash-table nodes-to-neighbors°)]
         [else
          (let* ([tree (first trees°)]
                 [node-name (car (peg-tree:tree-refs tree '(SOURCE-NODE-NAME)))]
                 [neighbor-name (car (peg-tree:tree-refs tree '(TARGET-NODE-NAME)))]
                 [weight (string->number (car (peg-tree:tree-refs tree '(WEIGHT))))])
            (iter (drop trees° 1)
                  (cons (cons (cons node-name neighbor-name) weight)
                        nodes-to-neighbors°)))]))))

  (define read-graph
    (λ (input-filename)
      "Takes an input filename, parses the nodes of a graph from
that file and returns 3 values: (1) the nodes, (2) a hash
table of distances between nodes, (3) a hash table of node
names to nodes."
      (let ([lines (get-lines-from-file input-filename)])

        (let-values ([(node-lines association-lines)
                      (split-at lines (λ (line index) (string-null? line)))])

          (let ([assoc-parse-trees (map parse-associations association-lines)]
                [nodes-parse-trees (map parse-nodes node-lines)])

            (let* (;; To fill in the neighbors, we need to parse the associations.
                   [nodes-no-neighbors (map node-parse-tree->node nodes-parse-trees)]
                   [associations (assoc-parse-trees->neighbor-assocs assoc-parse-trees)]
                   [nodes
                    (map (λ (node)
                           (set-node-neighbors
                            node
                            (hash-table-ref associations (node-name node))))
                         nodes-no-neighbors)]
                   [nodes-table (alist->hash-table
                                 (map (λ (node) (cons (node-name node) node))
                                      nodes))]
                   [distances-table (assoc-parse-trees->distances assoc-parse-trees
                                                                  nodes-table)])

              (simple-format #t "nodes no neighbors:\n")
              (pretty-print nodes-no-neighbors
                            #:width 80
                            #:max-expr-width 80)

              (simple-format #t "associations:\n")
              (pretty-print (hash-table->alist associations))

              (simple-format #t "nodes:\n")
              (pretty-print nodes
                            #:width 80
                            #:max-expr-width 80)

              (simple-format #t "distances-table:\n")
              (pretty-print (hash-table->alist distances-table)
                            #:width 80
                            #:max-expr-width 80)

              (simple-format #t "nodes-table:\n")
              (pretty-print (hash-table->alist nodes-table)
                            #:width 80
                            #:max-expr-width 80)

              (values nodes
                      distances-table
                      nodes-table))))))))


code:
(library (graph-utils)
  (export routes->path)
  (import (except (rnrs base)
                  let-values
                  map)
          (only (guile)
                lambda* λ)
          ;; SRFIs
          ;; hash tables
          (srfi srfi-69))

  (define routes->path
    (lambda* (routes target #:key (equal-test eq?))
      "Constructs the shortest path from the start node to the
target node using a routes table. A routes table is assumed
to be a hash table, which stores the preceding node on a
path to any node."
      (let iter ([current-node° target] [path° (list target)])
        (let ([prior-node (hash-table-ref routes current-node°)])
          (cond
           [(equal-test current-node° prior-node) path°]
           [else
            (iter prior-node (cons prior-node path°))]))))))


code:
(library (list-helpers)
  (export flatten
          make-list
          split-off-n
          split-into-n-sized-segments
          split-at
          split-into-segments
          split-into-n-segments)
  (import
   (except (rnrs base) let-values map error)
   (only (guile)
         lambda* λ
         remainder
         round
         simple-format)
   ;; receive form
   (srfi srfi-8))

  (define flatten
    (λ (lst)
      (cond [(null? lst) '()]
            [(pair? lst)
             (append (flatten (car lst))
                     (flatten (cdr lst)))]
            [else
             (list lst)])))

  (define make-list
    (λ (val count)
      (cond
       [(> count 0)
        (cons val (make-list val (- count 1)))]
       [else '()])))

  (define split-off-n
    (λ (lst n)
      "Take a list LST and split off the first N elements. Return
2 values: The split off part and the remaining part of the
list LST."
      (let iter ([lst° lst]
                 [counter 0]
                 [cont
                  (λ (acc-split-off rem-lst)
                    (values acc-split-off rem-lst))])
        (cond
         [(null? lst°)
          (cont '() lst°)]
         [(= counter n)
          (cont '() lst°)]
         [else
          (iter (cdr lst°)
                (+ counter 1)
                (λ (new-tail rem-lst)
                  (cont (cons (car lst°) new-tail)
                        rem-lst)))]))))

  (define split-into-n-sized-segments
    (λ (lst n)
      (cond
       [(null? lst) '()]
       [else
        (receive (split-off-part remaining-list)
            (split-off-n lst n)
          (cons split-off-part
                (split-into-n-sized-segments remaining-list n)))])))

  (define split-at
    (λ (lst pred)
      "Each element of LST is checked using the predicate. If the
predicate is satisfied for an element, then that element
will be seen as the separator. Return 2 values: The split
off part and the remaining part of the list LST."
      (let iter ([lst° lst]
                 [index° 0]
                 [cont
                  (λ (acc-split-off rem-lst)
                    (values acc-split-off rem-lst))])
        (cond
         [(null? lst°)
          (cont '() lst°)]
         [(pred (car lst°) index°)
          (cont '() (cdr lst°))]
         [else
          (iter (cdr lst°)
                (+ index° 1)
                (λ (new-tail rem-lst)
                  (cont (cons (car lst°) new-tail)
                        rem-lst)))]))))

  (define split-into-segments
    (λ (lst pred)
      "Split the list LST into segments based on a predicate for
an element being a separator or not. Each element is checked
using the predicate. If the predicate is satisfied for an
element, then that element will be seen as a separator and
will not be part of the resulting segments."
      (cond
       [(null? lst) '()]
       [else
        (receive (split-off-part remaining-list) (split-at lst pred)
          (cons split-off-part
                (split-into-segments remaining-list pred)))])))

  (define split-into-n-segments
    (λ (lst n)
      "Try to split list LST into N segments. The function tries
to make the segments as evenly sized as possible."
      (let ([chunk-size (round (/ (length lst) n))])
        (let iter ([lst° lst] [counter 0])
          (cond
           [(= counter (- n 1)) (list lst°)]
           [(and (< counter n) (null? lst°))
            (cons '() (iter lst° (+ counter 1)))]
           [(null? lst°) '()]
           [else
            (receive (split-off-part remaining-list) (split-off-n lst° chunk-size)
              (cons split-off-part
                    (iter remaining-list (+ counter 1))))]))))))


code:
(library (parallelism)
  (export run-in-parallel
          map-indexed
          parallel-map)
  (import
   (except (rnrs base) let-values map)
   (only (guile)
         lambda* λ)
   (ice-9 futures)
   (srfi srfi-1))

  (define map-indexed
    (λ (proc lst)
      "Map PROC to all elements of LST, but also give the index of
each element to the mapped PROC as an argument. PROC is
called (proc elem index)."
      (let iter ([ind 0] [lst° lst])
        (cond
         [(null? lst°) '()]
         [else
          (cons (proc (car lst°) ind)
                (iter (+ ind 1) (cdr lst°)))]))))

  (define run-in-parallel
    (λ (segments map-indexed-proc reduce-proc reduce-init)
      "Use futures to run a procedure in parallel, if
multiple cores are available. Take a list of SEGMENTS as
input, which are ranges of values to work on. MAP-PROC is
applied to the SEGMENTS using map. When the MAP-PROC calls
for all segments finished and returned values, the
REDUCE-PROC is applied to the map result using reduce and
the REDUCE-INIT argument."
      (let ([futures
             (map-indexed
              (λ (seg ind)
                (make-future
                 ;; Need to wrap in a thunk, to not
                 ;; immediately start evaluating.
                 (λ () (map-indexed-proc seg ind))))
              segments)])
        (let ([segment-results (map touch futures)])
          (reduce reduce-proc
                  reduce-init
                  segment-results)))))

  (define parallel-map
    (λ (map-indexed-proc lst)
      "Parallelized version of map, if multiple cores are
available."
      (let ([futures
             (map-indexed (λ (elem ind)
                            (make-future (λ () (map-indexed-proc elem ind))))
                          lst)])
        (let ([results (map touch futures)])
          results)))))


code:
(library (peg-tree-utils)
  (export find-in-tree
          find-in-tree*
          tree-refs)
  (import
   (except (rnrs base) let-values)
   (only (guile) lambda* λ
         current-output-port
         simple-format)
   (srfi srfi-1))

  (define find-in-tree
    (λ (peg-tree label equal-test)
      (define traverse
        (λ (peg-tree label)
          (cond
           [(null? peg-tree) #f]
           [(pair? (car peg-tree))
            (or (traverse (first peg-tree) label)
                (traverse (cdr peg-tree) label))]
           [(symbol? (car peg-tree))
            (cond
             [(equal-test (car peg-tree) label)
              (car (cdr peg-tree))]
             [else
              (traverse (cdr peg-tree) label)])]
           [else
            (traverse (cdr peg-tree) label)])))
      (traverse peg-tree label)))

  (define tree-refs
    (lambda* (peg-tree refs #:key (equal-test eq?))
      (let traverse ([tree° peg-tree]
                     [refs° refs])
        (cond
         [(null? refs°) tree°]
         [(null? tree°) #f]
         [(pair? (car tree°))
          (or (traverse (car tree°) refs°)
              (traverse (cdr tree°) refs°))]
         [(symbol? (car tree°))
          (cond
           ;; success case
           [(equal-test (car tree°) (car refs°))
            (traverse (cdr tree°) (cdr refs°))]
           [else
            (traverse (cdr tree°) refs°)])]
         [else
          (traverse (cdr tree°) refs°)]))))

  (define find-in-tree*
    (λ (peg-tree filter-proc)

      (define traverse
        (λ (subtree cont)
          ;; (simple-format (current-output-port)
          ;;                "working with subtree ~a\n"
          ;;                subtree)
          (cond
           [(null? subtree) (cont)]
           [(pair? (first subtree))
            (traverse (first subtree)
                      (λ () (traverse (cdr subtree) cont)))]
           [(filter-proc (first subtree))
            (cons subtree (cont))]
           [else
            (traverse (cdr subtree) cont)])))

      (traverse peg-tree (λ () '())))))


code:
(library (priority-search-queues)
  (export psq->list)
  (import
   (except (rnrs base)
           let-values
           map
           error
           vector-map)
   (only (guile)
         lambda* λ)
   ;; let-values
   (srfi srfi-11)
   ;; functional priority search queues
   (pfds psqs))

  (define psq->list
    (λ (queue)
      (cond
       [(psq-empty? queue) '()]
       [else
        (let-values ([(min-key popped-queue) (psq-pop queue)])
          (cons min-key
                (psq->list popped-queue)))]))))


code:
(library (sets)
  (export make-empty-set
          set-insert-multiple
          set-empty?)
  (import
   (except (rnrs base)
           let-values
           map
           error
           vector-map)
   (only (guile)
         lambda* λ)
   (pfds sets))

  (define make-empty-set
    (λ (less?)
      (make-set less?)))

  (define set-insert-multiple
    (λ (myset items)
      (cond
       [(null? items) myset]
       [else
        (set-insert-multiple (set-insert myset (car items))
                             (cdr items))])))

  (define set-empty?
    (λ (set)
      (= (set-size set) 0))))


code:
(library (pipeline)
  (export ->)

  (import
   (except (rnrs base)
           let-values
           map
           error
           vector-map)
   (only (guile)
         lambda* λ))

  (define-syntax ->
    (syntax-rules ()
      ;; first expression is left unchanged
      [(-> expr) expr]
      ;; take from the back, wrap other calls
      [(-> expr* ... (op args* ...))
       (op args* ... (-> expr* ...))]
      ;; make parens unnecessary in trivial case of no further arguments
      [(-> expr* ... op)
       (op (-> expr* ...))])))


code:
(library (segment)
  (export make-segment
          segment-start
          segment-end
          segment-map
          segment)

  (import (except (rnrs base)
                  let-values
                  map)
          (only (guile)
                lambda* λ))

  (define make-segment
    (λ (start end)
      (cons start end)))

  (define segment-start
    (λ (seg)
      (car seg)))

  (define segment-end
    (λ (seg)
      (cdr seg)))

  (define segment-map
    (lambda* (proc seg #:key (next (λ (num) (+ num 1))))
      (let ([min-val (segment-start seg)]
            [max-val (segment-end seg)])
        (let iter ([current-val° min-val])
          (cond
           [(<= current-val° max-val)
            (cons (proc current-val°)
                  (iter (next current-val°)))]
           [else '()])))))

  (define segment
    (lambda* (start end segment-count #:key (next (λ (num) (+ num 1))))
      "Make segments of mostly equal length/size. A
segment's starting point is based on the previous segment's
ending point. Segments do not necessarily connect with no
gap in between. The NEXT argument is a function, which is
used to calculate the start of the starting point of the
following segment from the ending point of the previous
segment."
      (let ([segment-size
             (ceiling
              (/ (- end start)
                 segment-count))])
        (let loop ([pos start])
          (cond
           [(>= (+ pos segment-size) end)
            (list (make-segment pos end))]
           [else
            (cons (make-segment pos (+ pos segment-size))
                  (loop (next (+ pos segment-size))))]))))))


code:
(import
 (except (rnrs base)
         let-values
         map
         error
         vector-map)
 (only (guile)
       lambda* λ
       simple-format
       current-output-port)

 ;; standard library
 (ice-9 pretty-print)

 ;; custom modules
 (fileio)
 (pipeline)
 (debug)
 (list-helpers)

 ;; hash tables
 (srfi srfi-69)
 ;; let-values
 (srfi srfi-11)

 ;; graph algos
 (a-star)
 (dijkstra)

 ;; distances
 (prefix (distances) distance:)

 (graph-model)
 (graph-reader)
 (graph-utils)
 )

;; (define input-filename "example-graphs/graph-01.txt")
(define input-filename "example-graphs/graph-01.txt")

(define-values (nodes distances-table nodes-table)
  (read-graph input-filename))

(simple-format #t "node names: ~s\n" (hash-table-keys nodes-table))

(define manhattan-node-distance
  (λ (source-node target-node)
    (distance:manhattan (node-y source-node)
                        (node-y target-node)
                        (node-x source-node)
                        (node-x target-node))))

(define get-node-distance
  (λ (source-node-name target-node-name)
    (hash-table-ref distances-table
                    (cons source-node-name
                          target-node-name))))

(let ([start-node (hash-table-ref nodes-table "A")]
      [target-node (hash-table-ref nodes-table "O")])
  (pretty-print
   (routes->path (A* start-node
                     target-node
                     (hash-table-keys nodes-table)
                     nodes-table
                     get-node-distance
                     manhattan-node-distance
                     <)
                 (node-name target-node)
                 #:equal-test string=?)))


code:
(import
 (except (rnrs base)
         let-values
         map
         error
         vector-map)
 (only (guile)
       lambda* λ
       simple-format)

 ;; standard library
 (ice-9 pretty-print)

 ;; custom modules
 (fileio)
 (pipeline)
 (debug)
 (list-helpers)

  ;; let-values
 (srfi srfi-11)
 ;; hash tables
 (srfi srfi-69)

 ;; graph algos
 (dijkstra)

 (graph-model)
 (graph-reader)
 (graph-utils)
 )

(define input-filename "example-graphs/graph-02.txt")

(define-values (nodes distances-table nodes-table)
  (read-graph input-filename))

(define get-neighbors
  (λ (node)
    "A function, that maps from an actual node struct to a
list of node structures."
    (map (λ (node-name)
           (hash-table-ref nodes-table node-name))
         (node-neighbors node))))

(define get-neighbor-distance
  (λ (node1 node2)
    "A function that returns the distance from NODE1 to NODE2."
    (let ([key (cons (node-name node1) (node-name node2))])
      (hash-table-ref distances-table key))))

(define node<
  (λ (node1 node2)
    "A function introduction an order to nodes. Important for
functional sets implementation backed by a tree
implementation."
    (or (< (node-y node1)
           (node-y node2))
        (and (= (node-y node1)
                (node-y node2))
             (< (node-x node1)
                (node-x node2))))))

(let ([start-node (hash-table-ref nodes-table "A")])
  (let-values ([(distances° routes°)
                (dijkstra-shortest-path start-node
                                        nodes
                                        get-neighbors
                                        get-neighbor-distance
                                        node<
                                        #:distance< <)])
    (simple-format #t "shortest distances from A to other nodes:\n")
    (pretty-print (hash-table->alist distances°))
    (simple-format #t "shortest path from A to T:\n")
    (pretty-print (routes->path routes° (hash-table-ref nodes-table "T")))))


code:
- [guile-algorithms](#guile-algorithms)
- [NOTICE](#notice)

# guile-algorithms

This repository contains a collection of algorithms written in GNU Guile.

# NOTICE

This repository is moved to <https://codeberg.org/ZelphirKaltstahl/guile-algorithms>.