<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel rdf:about="https://community.wolfram.com">
    <title>Community RSS Feed</title>
    <link>https://community.wolfram.com</link>
    <description>RSS Feed for Wolfram Community showing any discussions tagged with Graphs and Networks with no replies sorted by most viewed.</description>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/497445" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1136952" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/921122" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1135996" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/2144114" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1382823" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1732378" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1120587" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1383122" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1379016" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1384972" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1732283" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1137401" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1383617" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1728662" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1382967" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1728556" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1733095" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/2964488" />
        <rdf:li rdf:resource="https://community.wolfram.com/groups/-/m/t/1382524" />
      </rdf:Seq>
    </items>
  </channel>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/497445">
    <title>Flags of all countries grouped by similarity</title>
    <link>https://community.wolfram.com/groups/-/m/t/497445</link>
    <description>Today I watched this TED talk &amp;#034;[Why city flags may be the worst-designed thing you&amp;#039;ve never noticed][1]&amp;#034; and it made me really curious about how the five basic principles of flag design apply to countries. Certainly, most country flags are so simple that a child can draw them from memory. But this principle increases the odds of having flag duplicates, and to show this I&amp;#039;ve written the following WL code:&#xD;
&#xD;
    countries = CountryData[&amp;#034;Countries&amp;#034;, &amp;#034;Name&amp;#034;];&#xD;
    flags = Rasterize /@ CountryData[&amp;#034;Countries&amp;#034;, &amp;#034;Flag&amp;#034;];&#xD;
    similarities = # -&amp;gt; First[Nearest[DeleteCases[flags, #], #]] &amp;amp; /@ flags;&#xD;
    g = Graph[Labeled[#[[2]],Placed[Tooltip[#[[2]],#[[1]]],{.7,.6}]]&amp;amp;/@Transpose[{countries,flags}],similarities,ImageSize-&amp;gt;3500]&#xD;
&#xD;
![Flags of all countries group by similarity][2]&#xD;
&#xD;
    ImageCollage[Length[#] -&amp;gt; ImageCollage[#] &amp;amp; /@ WeaklyConnectedComponents[g]]&#xD;
&#xD;
![Flags Collage by Similarity][3]&#xD;
&#xD;
    GraphicsGrid[Partition[Flatten[WeaklyConnectedComponents[g]], 6], Background -&amp;gt; Gray]&#xD;
&#xD;
![List of similar flags][4]&#xD;
&#xD;
Feel free to explore the similarity graph of flags in the CDF attached below.&#xD;
&#xD;
![Flag Similarity Graph][6]&#xD;
&#xD;
Are these similarities mere accidents or deliberate flag copies? &#xD;
Mapping the countries with similar flags might answer this question. To get started, here is how to [Map the Countries of Africa with Their Flags][5].&#xD;
&#xD;
&#xD;
  [1]: https://www.ted.com/talks/roman_mars_why_city_flags_may_be_the_worst_designed_thing_you_ve_never_noticed&#xD;
  [2]: /c/portal/getImageAttachment?filename=SimilarityCountryFlagsGraph.png&amp;amp;userId=56204&#xD;
  [3]: /c/portal/getImageAttachment?filename=SimilarityCountryFlagsCollage.png&amp;amp;userId=56204&#xD;
  [4]: /c/portal/getImageAttachment?filename=SimilarityFlagsGrid.png&amp;amp;userId=56204&#xD;
  [5]: http://www.wolfram.com/mathematica/new-in-10/entity-based-geocomputation/map-the-countries-of-africa-with-their-flags.html&#xD;
  [6]: /c/portal/getImageAttachment?filename=FlagGraph.gif&amp;amp;userId=56204</description>
    <dc:creator>Bernat Espigulé</dc:creator>
    <dc:date>2015-05-15T20:25:24Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1136952">
    <title>[WSS17] Growth and spreading of topics on inSpireHEP/arXiv.org</title>
    <link>https://community.wolfram.com/groups/-/m/t/1136952</link>
    <description># **Growth and spreading of topics on inSpireHEP**#&#xD;
Brief and tentative description of the project carried out at the 2017 Wolfram Summer School.&#xD;
&#xD;
The Mathematica notebook can be found [here][1].&#xD;
&#xD;
## Goal of the project ##&#xD;
The project has a twofold goal. Given a keyword representing a scientific topic (e.g., entanglement, gravitational waves, etc...), we compute the number of occurrences of the keyword that appears in the abstracts of papers in a given time interval and we study how papers about a specific topic are related to each other by analyzing the corresponding citations. In particular, we construct the citation graph associated to the topic and we display its time evolution. &#xD;
&#xD;
## Summary of the work##&#xD;
As a preliminary step, we download an updated snapshot of record metadata in JSON format containing information about one million of papers posted on inSpireHEP. After adjusting the database to our purposes, we collect the abstracts year by year. The first goal is reached by using the built-in function StringCount, which counts how many times the keyword appears in the abstracts within a given time interval. Then we chart the occurrences by using DateListPlot and few examples of keyword search are shown. The second goal is achieved by selecting those papers concerning the chosen topic and by associating each of these papers to their list of citations. We construct the corresponding citation graph and highlight the communities by centrality-based clustering criterion. We emphasize those papers whose position is relevant for the topology of the graph. Finally, we introduce a further time selection of papers (in addition to the topic selection) in order to display the time evolution of the graph.&#xD;
&#xD;
##**Code explanation**##&#xD;
First of all, we download the JSON file containing the record metadata (ID, title, abstract, authors, citations, references, publication date, etc...) from [inSpireHEP website][2] and save it as inSpire.json.&#xD;
&#xD;
Then we import the file using the following line:&#xD;
&#xD;
    data = Part[&#xD;
       Reap[&#xD;
        Module[ {line, file = FileNameJoin[{NotebookDirectory[], &amp;#034;inSpire.json&amp;#034;}]}, &#xD;
         Quiet@Close[file];&#xD;
         OpenRead[file];&#xD;
         While[line =!= EndOfFile, line = ReadString[file, &amp;#034;\n&amp;#034;];&#xD;
          Replace[line, _String :&amp;gt; Sow@Developer`ReadRawJSONString[line]]];&#xD;
         ]&#xD;
        ],&#xD;
       2, 1&#xD;
       ];&#xD;
&#xD;
and save it &#xD;
&#xD;
    DumpSave[&amp;#034;inSpire.mx&amp;#034;, data]&#xD;
&#xD;
The next step is to import the data&#xD;
&#xD;
    &amp;lt;&amp;lt; inSpire.mx&#xD;
&#xD;
and clean it for our objectives.&#xD;
We will call the clean data `pubdata`.&#xD;
&#xD;
For future convenience, we collect the abstracts year by year.&#xD;
We create an association between the creation date and the abstract of the paper and we organizeit in chronological order:&#xD;
&#xD;
     abstractsWithDates =&#xD;
      KeySort[#CreationDate -&amp;gt; #abstract &amp;amp; /@ Normal@pubdata // &#xD;
        Association] ;&#xD;
&#xD;
We define a function to compare the year of two papers&#xD;
    &#xD;
    equalDates[date2_][date1_] := &#xD;
     MatchQ[DateObject[DateValue[date1, &amp;#034;Year&amp;#034;]], &#xD;
      DateObject[DateValue[date2, &amp;#034;Year&amp;#034;]]]&#xD;
  &#xD;
and we select all those papers published in that given year:&#xD;
  &#xD;
    abstractsAtYear[date_] := &#xD;
     KeySelect[abstractsWithDates, equalDates[date]]&#xD;
    &#xD;
    abstractYearData[date_] := Values@abstractsAtYear[date] // StringRiffle&#xD;
    &#xD;
and finally we collect all the abstracts year by year from 1930 to 2017:    &#xD;
&#xD;
    abstractText = &#xD;
      AssociationMap[abstractYearData, &#xD;
       DateRange[DateObject[{1930}], DateObject[{2017}], &#xD;
        Quantity[1, &amp;#034;Years&amp;#034;]]];&#xD;
    &#xD;
 To avoid this evaluation every time, we save the abstracts collection in abstractText:&#xD;
    &#xD;
    DumpSave[FileNameJoin@{NotebookDirectory[], &#xD;
       &amp;#034;abstractText.mx&amp;#034;}, abstractText]&#xD;
&#xD;
&#xD;
----------&#xD;
##Occurrences of keywords in abstract in a given time interval##&#xD;
We are in a position to build a easy search engine for keywords in the abstracts.&#xD;
The user has two degrees of freedom in his search: the keyword and the time interval. The research engine is a useful analytical tool to show the trend of a topic in the time range. In the following, we present some representative examples.&#xD;
&#xD;
We import all the abstracts&#xD;
&#xD;
    &amp;lt;&amp;lt; abstractText.mx&#xD;
&#xD;
and define a function that counts how many times a given keyword appears in abstracts published in that year:&#xD;
&#xD;
    stringCountsAt[date_, words_] := StringCount[abstractText[date], words];&#xD;
    stringCountsAt[words_][date_] := stringCountsAt[date, words]&#xD;
    &#xD;
how many times a given keyword is counted up to that year:&#xD;
    &#xD;
    stringCountUpTo[year_, words_, start_: Automatic] :=&#xD;
     Map[&#xD;
      stringCountsAt[words],&#xD;
      Range[Replace[start, Automatic :&amp;gt; Min@Keys[abstractText]], &#xD;
       Replace[year, _Integer :&amp;gt; DateObject[{year}]], Quantity[1, &amp;#034;Years&amp;#034;]]&#xD;
      ]&#xD;
    &#xD;
and how many occurrences in a time interval:&#xD;
    &#xD;
    occurrences[word_String, dateStart_, &#xD;
      dateEnd_] := {#, stringCountUpTo[#, word] // Total} &amp;amp; /@ &#xD;
       Range[Replace[dateStart, _Integer :&amp;gt; DateObject[{dateStart}]], &#xD;
        Replace[dateEnd, _Integer :&amp;gt; DateObject[{dateEnd}]], &#xD;
        Quantity[1, &amp;#034;Years&amp;#034;]] // TimeSeries&#xD;
&#xD;
We plot the occurrences of the keyword &amp;#034;Higgs&amp;#034; between 1985 and 2015&#xD;
&#xD;
     DateListPlot[&#xD;
     {occurrences[&amp;#034;Higgs&amp;#034;, 1985, 2015]}, &#xD;
     Joined -&amp;gt; True,&#xD;
     PlotLegends -&amp;gt; Placed[{&amp;#034;Higgs&amp;#034;}, {0.2, 0.8}], &#xD;
     PlotTheme -&amp;gt; &amp;#034;Detailed&amp;#034;,&#xD;
     PlotRange -&amp;gt; Full&#xD;
     ] &#xD;
![Occurrences of the keyword &amp;#034;Higgs&amp;#034; from 1985 to 2015][3]&#xD;
&#xD;
&#xD;
##Citations graph and its time evolution##&#xD;
In this section, we explain how to construct the citations graph for a given topic.&#xD;
The citations graph is an useful tool to visualize the relations between papers concerning the same topic and to highlight hidden properties among them. To meet this aim, we construct the citations graph of those papers about the &amp;#034;BMS group&amp;#034;&#xD;
&#xD;
We select the papers with more than 20 citations:&#xD;
    &#xD;
    citationsData = Select[&#xD;
       pubdata,&#xD;
       Length[#[&amp;#034;citations&amp;#034;]] &amp;gt;= 20 &amp;amp;&#xD;
       ];&#xD;
    &#xD;
and we define an association between ID and citations list, authors, abstracts and titles:&#xD;
    &#xD;
    idWithCitations =&#xD;
      #recid -&amp;gt; #citations &amp;amp; /@ Normal@citationsData // Association ;&#xD;
    idAuthor = #recid -&amp;gt; #authors &amp;amp; /@ Normal@citationsData // Association ;&#xD;
    idAbstract = #recid -&amp;gt; #abstract &amp;amp; /@ Normal@citationsData // Association ;&#xD;
    idTitle = #recid -&amp;gt; #title &amp;amp; /@ Normal@citationsData // Association ;&#xD;
    idCreationDate = #recid -&amp;gt; #CreationDate &amp;amp; /@ Normal@citationsData // &#xD;
       Association ;&#xD;
&#xD;
We need to define other functions to compare dates and years:&#xD;
     &#xD;
    compareDates[date1_, date2_] := &#xD;
      If[DateOverlapsQ[date1, date2], DateObject[{DateValue[date1, &amp;#034;Year&amp;#034;]}], &#xD;
       date1 &amp;lt; date2];&#xD;
    compareDates[date1_][date2_] := compareDates[date2, date1];&#xD;
    compareYears[date1_, date2_] := date1 &amp;lt;= date2;&#xD;
    compareYears[date1_Integer][date2_] := compareYears[date2, date1];&#xD;
    compareYears[date1_DateObject] := compareYears[DateValue[date1, &amp;#034;Year&amp;#034;]];&#xD;
    &#xD;
We select those papers containing the keyword in the abstract and define the association between the ID  and the citations list:&#xD;
    &#xD;
    idAbstractswithWord[words_String] := &#xD;
     Keys@Select[idAbstract, StringContainsQ[words]] &#xD;
    idWithCitationsandTopic[words_String] := &#xD;
     Thread[# -&amp;gt; Lookup[idWithCitations, #]] &amp;amp;@idAbstractswithWord[words]&#xD;
    &#xD;
and plot the graph associated to that keyword (representing a concept/topic)&#xD;
    &#xD;
    graphTopic = Graph[&#xD;
       Thread /@ idWithCitationsandTopic[&amp;#034;BMS group&amp;#034;] // Flatten,&#xD;
       DirectedEdges -&amp;gt; False, &#xD;
       VertexStyle -&amp;gt; Red,&#xD;
       VertexSize -&amp;gt; Automatic,&#xD;
       ImageSize -&amp;gt; Automatic&#xD;
       ];&#xD;
&#xD;
We define the highly central vertices: &#xD;
&#xD;
    highlyCentral[graph_] := Pick[&#xD;
      VertexList@graph,&#xD;
      GreaterThan[10] /@ DegreeCentrality@graph&#xD;
      ]&#xD;
&#xD;
and display all the graph communities:&#xD;
&#xD;
    HighlightGraph[&#xD;
     HighlightGraph[&#xD;
      graphTopic,&#xD;
      Map[Subgraph[graphTopic, #] &amp;amp;, &#xD;
       FindGraphCommunities[graphTopic, Method -&amp;gt; &amp;#034;Centrality&amp;#034;]]],&#xD;
     Style[highlyCentral[graphTopic], Black], &#xD;
     ImageSize -&amp;gt; Large&#xD;
     ]&#xD;
&#xD;
![Citation graph for the keyword/topic &amp;#034;BMS group&amp;#034;][4]&#xD;
&#xD;
Within the whole set of papers about the &amp;#034;BMS group&amp;#034;, we might select the most cited papers. The number of citations is usually a reliable bibliometric quantity to evaluate the scientific quality of a paper. In the graph above, we highlighted the graph communities in different colors and the papers with the highest degree of centrality in black. The latter set of papers is a subset of the most cited papers and they play an important role in the topological structure of the graph. In other words, among the most cited papers, we introduce the centrality-based clustering criterion to select the most &amp;#034;important&amp;#034; papers. As an example, the black vertex inside the yellow community is the so-called vertex cut. A vertex cut is that vertex whose removal renders the graph disconnected. In this respect, that paper connects different communities (i.e., different sub-topics) and it represents a seminal paper in the field because it has a non trivial topological position in the graph. In the case at hand, it is the paper by Ashtekar entitled &amp;#034;A unified treatment of null and spatial infinity in general relativity. I - Universal structure, asymptotic symmetries, and conserved quantities at spatial infinity&amp;#034;.&#xD;
&#xD;
It is also interesting to visualize the time evolution of the graph during a given time interval. To achieve this result, we need snapshots of the citations graphs year by year. In other words, we need to further select papers by date, in addition to the first selection by topic, and construct the corresponding graph. &#xD;
&#xD;
We therefore select those papers about a given topic published up to a given date:&#xD;
&#xD;
    idCreationYear = DateValue[#, &amp;#034;Year&amp;#034;] &amp;amp; /@ idCreationDate;&#xD;
&#xD;
    idAbstractswithDateTopic[date_, words_String] := &#xD;
     Intersection[Keys@Select[idCreationYear, compareYears[date]], &#xD;
      Keys@Select[idAbstract, StringContainsQ[words]]]&#xD;
    idCitations[date_, words_String] := &#xD;
     Thread[# -&amp;gt; Lookup[idWithCitations, #]] &amp;amp;@&#xD;
      idAbstractswithDateTopic[date, words]&#xD;
&#xD;
and compute the time evolution from 1978 to 2008&#xD;
&#xD;
    timeEvo = &#xD;
      idCitations[#, &amp;#034;BMS group&amp;#034;] &amp;amp; /@ &#xD;
       DateRange[DateObject[{1978}], DateObject[{2008}], &#xD;
        Quantity[1, &amp;#034;Years&amp;#034;]];&#xD;
    &#xD;
    timeEvoPruned =&#xD;
      With[{edges = Flatten[Thread /@ #]},&#xD;
         Select[edges, Not@*MemberQ[Alternatives @@ #]] &amp;amp;@&#xD;
          Pick[VertexList@edges, LessThan[0] /@ VertexDegree[edges]]&#xD;
         ] &amp;amp; /@ timeEvo;&#xD;
&#xD;
    g = Table[&#xD;
      Graph[timeEvoPruned[[i]], DirectedEdges -&amp;gt; False, &#xD;
       VertexStyle -&amp;gt; Red, VertexSize -&amp;gt; Small, &#xD;
       ImageSize -&amp;gt; Automatic], {i, 1, Length[timeEvoPruned]}];&#xD;
&#xD;
    CommunityConnectedGraph = Table[&#xD;
       HighlightGraph[g[[i]], &#xD;
        Map[Subgraph[g[[i]], #] &amp;amp;, &#xD;
         FindGraphCommunities[g[[i]], Method -&amp;gt; &amp;#034;Centrality&amp;#034;]]], {i, 1, &#xD;
        Length[g]}];&#xD;
&#xD;
    ListAnimate[CommunityConnectedGraph]&#xD;
&#xD;
For the &amp;#034;BMS group&amp;#034; the citations graph has the following growth:&#xD;
&#xD;
![enter image description here][5]&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
##**Conclusion and future work**##&#xD;
In this project, we defined a search engine that charts occurrences of any keyword in the abstracts of papers posted on inSpireHEP/arXiv.org and constructed the corresponding citation graph and highlighted the communities by centrality-based clustering criterion. We emphasized those papers about one specific chosen topic that play an important role in the structure of the citations graph, because of their high degree of centrality and not only because they are the most cited papers in the field. Finally, we displayed the time evolution of the graph. &#xD;
&#xD;
Future directions of investigation require more complete database and a detailed analysis of the topological properties of the graph.&#xD;
&#xD;
&#xD;
  [1]: https://github.com/ROliveri89/WSS17_material&#xD;
  [2]: https://inspirehep.net/info/hep/api&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Higgs.jpg&amp;amp;userId=1081377&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=graph1.jpg&amp;amp;userId=1081377&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=evo1.jpg&amp;amp;userId=1081377&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=evo2.jpg&amp;amp;userId=1081377&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=evo3.jpg&amp;amp;userId=1081377&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=evo4.jpg&amp;amp;userId=1081377&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=evo5.jpg&amp;amp;userId=1081377</description>
    <dc:creator>Roberto Oliveri</dc:creator>
    <dc:date>2017-07-05T21:17:01Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/921122">
    <title>Perfect Coverings</title>
    <link>https://community.wolfram.com/groups/-/m/t/921122</link>
    <description>The [La Jolla Covering Repository](https://www.ccrwest.org/cover/low_tab.html) has a collection of *covers*.  For example, my post [Smallest Project Space](http://community.wolfram.com/groups/-/m/t/816281) has the C(15,3,2) cover.  From numbers to 15, lines of 3 cover all possible subsets of 2, in 35 lines. No subset is reused anywhere within the lines, so this is called a perfect covering.  Another well known example is the [Golay code](http://demonstrations.wolfram.com/GolayCode/) [C(24,8,5)](https://www.ccrwest.org/cover/t_pages/t5/k8/C_24_8_5.html). From numbers to 24, lines of 8 cover all possible subsets of 5, in 759 lines.&#xD;
&#xD;
![smallest projective][1]&#xD;
&#xD;
I wondered what the status was for perfect coverings, so I took a look.  &#xD;
&#xD;
[C(7,3,2)](https://www.ccrwest.org/cover/t_pages/t2/k3/C_7_3_2.html) (Fano plane), [C(9,3,2)](https://www.ccrwest.org/cover/t_pages/t2/k3/C_9_3_2.html), [C(13,3,2)](https://www.ccrwest.org/cover/t_pages/t2/k3/C_13_3_2.html), [C(15,3,2)](https://www.ccrwest.org/cover/t_pages/t2/k3/C_15_3_2.html) (smallest projective space), [C(19,3,2)](https://www.ccrwest.org/cover/t_pages/t2/k3/C_19_3_2.html), [C(21,3,2)](https://www.ccrwest.org/cover/t_pages/t2/k3/C_21_3_2.html), [C(25,3,2)](https://www.ccrwest.org/cover/t_pages/t2/k3/C_25_3_2.html), and more with mod-6 equal to 1 or 3: 27, 31, 33, 37, 39, 43, 45, 49, 51, 55, 57.    &#xD;
 &#xD;
[C(13,4,2)](https://www.ccrwest.org/cover/t_pages/t2/k4/C_13_4_2.html), [C(16,4,2)](https://www.ccrwest.org/cover/t_pages/t2/k4/C_16_4_2.html), [C(25,4,2)](https://www.ccrwest.org/cover/t_pages/t2/k4/C_25_4_2.html), [C(28,4,2)](https://www.ccrwest.org/cover/t_pages/t2/k4/C_28_4_2.html), [C(37,4,2)](https://www.ccrwest.org/cover/t_pages/t2/k4/C_37_4_2.html), [C(40,4,2)](https://www.ccrwest.org/cover/t_pages/t2/k4/C_40_4_2.html), and more with mod 12 equal to 1 or 4: 49, 52, 61, 64, 73, 76, 85, 88, 97, 100.  &#xD;
&#xD;
[C(21,5,2)](https://www.ccrwest.org/cover/t_pages/t2/k5/C_21_5_2.html), [C(25,5,2)](https://www.ccrwest.org/cover/t_pages/t2/k5/C_25_5_2.html), &#xD;
[C(41,5,2)](https://www.ccrwest.org/cover/t_pages/t2/k5/C_41_5_2.html), [C(45,5,2)](https://www.ccrwest.org/cover/t_pages/t2/k5/C_45_5_2.html), and more with mod 20 equal to 1 or 5: 61, 65, 81, 85.  &#xD;
&#xD;
Then things start getting interesting.  [C(31,6,2)](https://www.ccrwest.org/cover/t_pages/t2/k6/C_31_6_2.html), [C(66,6,2)](https://www.ccrwest.org/cover/t_pages/t2/k6/C_66_6_2.html), [C(76,6,2)](https://www.ccrwest.org/cover/t_pages/t2/k6/C_76_6_2.html), [C(91,6,2)](https://www.ccrwest.org/cover/t_pages/t2/k6/C_91_6_2.html), [C(96,6,2)](https://www.ccrwest.org/cover/t_pages/t2/k6/C_96_6_2.html) are all solved.  C(36,6,2), C(46,6,2), C(51,6,2), C(61,6,2), C(81,6,2) are all unsolved. A solution may exist when mod 15 equals 1 or 6.&#xD;
&#xD;
[C(49,7,2)](https://www.ccrwest.org/cover/t_pages/t2/k7/C_49_7_2.html) is solved, the rows, columns, and toroidal diagonals of both squares below give the 56 lines needed. [C(91,7,2)](https://www.ccrwest.org/cover/t_pages/t2/k7/C_91_7_2.html) is also solved. C(43,7,2) and C(85,7,2) are unsolved.&#xD;
![order 7 projective plane][2] &#xD;
&#xD;
[C(57,8,2)](https://www.ccrwest.org/cover/t_pages/t2/k8/C_57_8_2.html) and [C(64,8,2)](https://www.ccrwest.org/cover/t_pages/t2/k8/C_64_8_2.html) are solved. [C(73,9,2)](https://www.ccrwest.org/cover/t_pages/t2/k9/C_73_9_2.html) and [C(81,9,2)](https://www.ccrwest.org/cover/t_pages/t2/k9/C_81_9_2.html) are solved.&#xD;
&#xD;
[C(8,4,3)](https://www.ccrwest.org/cover/t_pages/t3/k4/C_8_4_3.html), [C(10,4,3)](https://www.ccrwest.org/cover/t_pages/t3/k4/C_10_4_3.html), [C(14,4,3)](https://www.ccrwest.org/cover/t_pages/t3/k4/C_14_4_3.html), [C(16,4,3)](https://www.ccrwest.org/cover/t_pages/t3/k4/C_16_4_3.html), [C(20,4,3)](https://www.ccrwest.org/cover/t_pages/t3/k4/C_20_4_3.html) are solved, and more where mod 6 equals 1 or 5: 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58. &#xD;
&#xD;
[C(17,5,3)](https://www.ccrwest.org/cover/t_pages/t3/k5/C_17_5_3.html) and [C(26,5,3)](https://www.ccrwest.org/cover/t_pages/t3/k5/C_26_5_3.html) are solved. [C(22,6,3)](https://www.ccrwest.org/cover/t_pages/t3/k6/C_22_6_3.html) is solved, this is known as the [M22 graph](http://mathworld.wolfram.com/M22Graph.html). [C(26,6,3)](https://www.ccrwest.org/cover/t_pages/t3/k6/C_26_6_3.html) is solved. C(37,7,3) is unsolved. &#xD;
&#xD;
[C(11,5,4)](https://www.ccrwest.org/cover/t_pages/t4/k5/C_11_5_4.html), [C(23,5,4)](https://www.ccrwest.org/cover/t_pages/t4/k5/C_23_5_4.html), and [C(35,5,4)](https://www.ccrwest.org/cover/t_pages/t4/k5/C_35_5_4.html) are solved. [C(27,6,4)](https://www.ccrwest.org/cover/t_pages/t4/k6/C_27_6_4.html) is solved, C(42,6,4) is unsolved. [C(23,7,4)](https://www.ccrwest.org/cover/t_pages/t4/k7/C_23_7_4.html) is solved, the ternary Golay code.&#xD;
&#xD;
For small coverings, that&amp;#039;s pretty much all that&amp;#039;s known.  I was surprised at how many cases were unsolved.  Also, many of the solutions don&amp;#039;t yet have good pictures.&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=smallproj.gif&amp;amp;userId=21530&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Rx7uc.gif&amp;amp;userId=21530</description>
    <dc:creator>Ed Pegg</dc:creator>
    <dc:date>2016-09-08T15:01:11Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1135996">
    <title>[WSS17]  Identification &amp;amp; Graph Structure of Rivers</title>
    <link>https://community.wolfram.com/groups/-/m/t/1135996</link>
    <description>A Road Map for Rivers&#xD;
=================&#xD;
&#xD;
The goal of this project was to identify rivers on maps and satellite images, and to calculate each river&amp;#039;s graph structure.&#xD;
&#xD;
We produced two functions: one will return a highlighting of all the water in a satellite image given a location entity, and the other will return  the graph structure of the water in the related street map image of a given location entity. Both functions start by taking the related street map of a location entity and stripping the image of every color other than one light shade of blue. Let&amp;#039;s use Seoul, South Korea as an example:&#xD;
&#xD;
![enter image description here][1]&#xD;
![enter image description here][2]&#xD;
&#xD;
    waterhighlight[entity_] := &#xD;
      Module[{streetmap, color, r, bluemap, mask, satmap},&#xD;
       streetmap = &#xD;
        RemoveAlphaChannel@&#xD;
         FirstCase[&#xD;
          GeoGraphics[entity, &#xD;
           GeoBackground -&amp;gt; &amp;#034;StreetMap&amp;#034;], _Image, $Failed, Infinity];&#xD;
       satmap = &#xD;
        ImageResize[&#xD;
         RemoveAlphaChannel@&#xD;
          FirstCase[&#xD;
           GeoGraphics[entity, &#xD;
            GeoBackground -&amp;gt; &amp;#034;Satellite&amp;#034;], _Image, $Failed, Infinity], &#xD;
         ImageDimensions[streetmap]];&#xD;
       color = &#xD;
        Apply[List, &#xD;
         ColorConvert[Interpreter[&amp;#034;Color&amp;#034;][&amp;#034;RGB 158 197 226&amp;#034;], &amp;#034;RGB&amp;#034;]];&#xD;
       r = If[ImageColorSpace[streetmap] != &amp;#034;RGB&amp;#034;,&#xD;
         ColorConvert[streetmap, &amp;#034;RGB&amp;#034;], streetmap];&#xD;
       bluemap = &#xD;
        SetAlphaChannel[r, Binarize[r, (Norm[# - color] &amp;lt; .15) &amp;amp;]];&#xD;
       mask = Closing[#, 7] &amp;amp;@FillingTransform@Binarize@bluemap;&#xD;
       HighlightImage[&#xD;
        satmap, {EdgeForm[{Red, AbsoluteThickness[1.5]}], &#xD;
         FaceForm[{Red, Opacity[.2]}], mask}]&#xD;
       ];&#xD;
&#xD;
The first function takes the blue image and uses it as a mask to highlight the related satellite image.&#xD;
&#xD;
![enter image description here][3]&#xD;
![enter image description here][4]&#xD;
&#xD;
    watergraph[entity_] := Module[{streetmap, color, r, bluemap, mask},&#xD;
       streetmap = &#xD;
        RemoveAlphaChannel@&#xD;
         FirstCase[&#xD;
          GeoGraphics[entity, &#xD;
           GeoBackground -&amp;gt; &amp;#034;StreetMap&amp;#034;], _Image, $Failed, Infinity];&#xD;
       color = &#xD;
        Apply[List, &#xD;
         ColorConvert[Interpreter[&amp;#034;Color&amp;#034;][&amp;#034;RGB 158 197 226&amp;#034;], &amp;#034;RGB&amp;#034;]];&#xD;
       r = If[ImageColorSpace[streetmap] != &amp;#034;RGB&amp;#034;,&#xD;
         ColorConvert[streetmap, &amp;#034;RGB&amp;#034;], streetmap];&#xD;
       bluemap = &#xD;
        SetAlphaChannel[r, Binarize[r, (Norm[# - color] &amp;lt; .15) &amp;amp;]];&#xD;
       mask = Closing[#, 7] &amp;amp;@FillingTransform@Binarize@bluemap;&#xD;
       MorphologicalGraph@SkeletonTransform[mask]&#xD;
       ];&#xD;
&#xD;
The second function smooths out the blue image, takes it&amp;#039;s skeleton, and uses that to calculate the graph structure. The end product really is a graph object, so one could play with it using Wolfram&amp;#039;s graph functionality to get some interesting results.&#xD;
&#xD;
![enter image description here][5]&#xD;
![enter image description here][6]&#xD;
&#xD;
&#xD;
Since one of the original goals of the project was to identify whether or not an image contained a river, we did make an attempt. We tried to first cut up the satellite images, binarize them, and then sort the tiny images based on the percentage of black and white pixels. We did this because in a large number of the initial images we saw, the water was usually much darker than the surrounding area. However as we looked at more test cases, this method of classifying images became useless. Many pictures require different binarize thresholds, some rivers are actually lighter than their surroundings, they may even be indistinguishable from the background, cloud coverage either blocks the water or can even create dark spots on its own via shadows, rivers may appear too thin to be recognized as such, and so on. As the list of issues grew, we decided to use the street maps due to their reliability. The street maps may have gaps in the water due to bridges, but this can be largely solved with basic image processing.&#xD;
&#xD;
In the future, we would like to implement a random river generation function and find a way to accurately automate the classification of satellite images as: &amp;#034;river&amp;#034; or &amp;#034;not river&amp;#034; to make a training set. From there, you could probably train a neural network to identify rivers from satellite images. &#xD;
&#xD;
[Github][7]&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=10658streetmap.png&amp;amp;userId=1081910&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=bluemap.png&amp;amp;userId=1081910&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=satellite.png&amp;amp;userId=1081910&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Highlighted.png&amp;amp;userId=1081910&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Skeleton.png&amp;amp;userId=1081910&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=9925Graphstructure.png&amp;amp;userId=1081910&#xD;
  [7]: https://github.com/Mathfig</description>
    <dc:creator>Z D</dc:creator>
    <dc:date>2017-07-05T19:22:36Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/2144114">
    <title>[WELP20] Using Hexagonal Cellular Automata to Model Flooding</title>
    <link>https://community.wolfram.com/groups/-/m/t/2144114</link>
    <description>&amp;amp;[Wolfram Notebook][1]&#xD;
&#xD;
&#xD;
  [1]: https://www.wolframcloud.com/obj/386c7594-731f-4d37-9c3a-5b06d7d7036f</description>
    <dc:creator>Wolfram Education Programs</dc:creator>
    <dc:date>2020-12-21T16:30:04Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1382823">
    <title>[WSC18] Using Multilevel NAND trees to Create XOR Expressions</title>
    <link>https://community.wolfram.com/groups/-/m/t/1382823</link>
    <description>The goal of this project has been to explore NAND expressions and look for expressions equivalent to XOR. The Wolfram Language can already simplify XOR expressions with NANDs by using the following function but it only simplifies to a two level tree. By using more than two levels there is a possibility of finding a simpler version of three or four input XOR expressions. The reason that I chose to use NAND gates is that they are universal gates (any expression can be represented with a combination of NAND gates). Other universal gates like NOR would work but it seemed simplest to just stick with NAND to keep things consistent.&#xD;
&#xD;
    `BooleanMinimize[Xor[a, b, c], &amp;#034;NAND&amp;#034;] // TreeForm`&#xD;
![NAND simplification for XOR[a,b,c] in Tree Form][1]&#xD;
&#xD;
## Two Input Trees ##&#xD;
The first thing I implemented was a recursive function that creates all of the different NAND trees possible with a given amount of NAND gates. It works by assuming that each NAND gate only has two inputs. From this it runs through the possibilities for the NAND gate configurations on each input.&#xD;
&#xD;
![Nand Tree Logic][2]&#xD;
&#xD;
The code starts by defining the first case of the recursive function and then on the next gates it runs through the different combinations with tuples to generate all of the outcomes. It also creates NAND trees with half of the amount of NAND implemented and it doesn&amp;#039;t know what to do with an odd amount of gates so &amp;#034;nandTreeCreate&amp;#034; was implemented to fix that by multiplying the input by two. Additionally it uses a new NAND function that get&amp;#039;s rid of trivial cases that aren&amp;#039;t worth computing (Ex. Xor[a, !a]).&#xD;
&#xD;
    nand[a_, a_] := Null;&#xD;
    nand[a_, ! a_] := Null;&#xD;
    nand[! a_, a_] := Null;&#xD;
    nand[a_, b_] /; OrderedQ[{a, b}] := Sow@Nand[a, b];&#xD;
    nand[a_, b_] := Null;&#xD;
&#xD;
    nandTreeGenerate[0] := {a, b, c, ! a, ! b, ! c}&#xD;
        &#xD;
    nandTuples[list1_, list2_] := &#xD;
     Replace[Reap[&#xD;
       Do[nand[a, b], {a, list1}, {b, list2}]], {{_, {x_}} :&amp;gt; x, _ :&amp;gt; {}}]&#xD;
    &#xD;
    nandTreeGenerate[&#xD;
       0] := {a,b,c,!a,!b,!c};&#xD;
    &#xD;
    nandTreeGenerate[nGates_] := &#xD;
     nandTreeGenerate[nGates] = &#xD;
      Module[{subtrees = nandTreeGenerate /@ Range[0, nGates - 1]},&#xD;
       Join @@ &#xD;
        Table[nandTuples[subtrees[[i]], subtrees[[nGates - i]]], {i, 1, &#xD;
          nGates - 1}]&#xD;
       ]&#xD;
    &#xD;
    nandTreeCreate[nGates_] := nandTreeGenerate[nGates*2]&#xD;
&#xD;
This turned out to be an effective set of functions but it wasn&amp;#039;t very useful since it only generates two input NAND trees and no simpler forms of XOR were found by running tests with this function. The following function was used to compare it to XOR.&#xD;
&#xD;
    Select[nandTreeCreate[5], &#xD;
     TautologyQ[Equivalent[Xor[a, b, c], #]] &amp;amp;]&#xD;
&#xD;
##Multi-Input Tree Generation ##&#xD;
By inputting the amount of leaves into the recursive function, I was able to expand it in order to account for more than two input NAND gates. This uses the same general structure as the two input NAND generate function except it is based on integer partitions to find all of the different combinations.&#xD;
&#xD;
    nand[arg_] := Nand[arg];&#xD;
    nand[args___] /; Equivalent[args] := Null;&#xD;
    nand[args___] /; OrderedQ[{args}] := Nand[args];&#xD;
    nand[args___] := Null;&#xD;
    &#xD;
    nandTuples[l_] := (nand @@ #) &amp;amp; /@ Tuples[l]&#xD;
    &#xD;
    nandTreeGenerate[1] := {a,b,c]};&#xD;
    &#xD;
    nandTreeGenerate[nLeaves_] := nandTreeGenerate[nLeaves]&#xD;
        DeleteCases[Module[{subtrees =  nandTreeGenerate /@ Range[1, nLeaves - 1]},&#xD;
             Join @@ ((nandTuples[subtrees[[#]] &amp;amp; /@ #] &amp;amp; /@ (IntegerPartitions[nLeaves - 1]))&#xD;
        ], Null]&#xD;
This works super well but it&amp;#039;s still computationally intensive and I figured out later that some of the logic must be wrong since it misses a couple of cases every once and awhile. It&amp;#039;s still good for getting a basic idea of the different cases that come from different leaf counts though.&#xD;
## Random Generation ##&#xD;
It seems that the best way to generate expressions computationally comes from random generation. This is because it can be stopped and started within a time limit even though it doesn&amp;#039;t get every possible expression. In order to implement this I used a function that inserts either a NAND gate or a variable at a random spot within the expression.&#xD;
&#xD;
    varlist = {\[FormalA], \[FormalB], \[FormalC]};&#xD;
    &#xD;
    addSomething[ex_] := Module[{positions},&#xD;
      positions = Position[ex, _myNand, {0, Infinity}];&#xD;
      Insert[ex, &#xD;
       RandomChoice[{.2, .7, .7, .7} -&amp;gt; Join[{myNand[]}, varlist]], &#xD;
       Append[RandomChoice[positions], 1]]&#xD;
      ]&#xD;
    &#xD;
    makeTree[nLeaves_] := (&#xD;
       (Last@NestList[addSomething, myNand[], nLeaves - 1]) /. &#xD;
        myNand[] :&amp;gt; RandomChoice[varlist]) /. myNand -&amp;gt; Nor&#xD;
    &#xD;
    randTreeGenerate[nLeaves_, nTimes_] := &#xD;
     makeTree /@ Table[nLeaves, nTimes]&#xD;
&#xD;
Although this is good for generating most functions, some cases become increasingly unlikely as it adds more terms. This makes it necessary to adjust the weights for NANDs and variables so that all of the cases have an equal chance of occurring. I didn&amp;#039;t have enough time to find the right values so eventually I setup the weights as random integers so that it would have a good distribution for each of the different weight combinations.&#xD;
##Visualizing the Data##&#xD;
At the end I made a couple of functions that could generate expressions for awhile and then put it in a form that&amp;#039;s easy to analyze. There are two equivalents of the functions depending on if you want to input the iterations or the duration that it should run for. It also has the option to input what percentage of those expressions should use NOR gates if any variation is needed.&#xD;
&#xD;
    Clear[&amp;#034;Global`*&amp;#034;]&#xD;
    &#xD;
    counts = Table[0, {i, 0, 255}];&#xD;
    &#xD;
    varlist = {a, b, c};&#xD;
    &#xD;
    addSomething[ex_, nand_: 1, var_: 1] := Module[{positions},&#xD;
      positions = Position[ex, _myNand, {0, Infinity}];&#xD;
      Insert[ex, &#xD;
       RandomChoice[{nand, var/3, var/3, var/3} -&amp;gt; &#xD;
         Join[{myNand[]}, varlist]], Append[RandomChoice[positions], 1]]&#xD;
      ]&#xD;
    &#xD;
    makeTreeNand[nLeaves_] := (&#xD;
       (Last@NestList[&#xD;
           addSomething[#, RandomInteger[{1, 20}], &#xD;
             RandomInteger[{1, 20}]] &amp;amp;, myNand[], nLeaves - 1]) /. &#xD;
        myNand[] :&amp;gt; RandomChoice[varlist]) /. myNand -&amp;gt; Nand&#xD;
    &#xD;
    makeTreeNor[nLeaves_] := (&#xD;
       (Last@NestList[&#xD;
           addSomething[#, RandomInteger[{1, 20}], &#xD;
             RandomInteger[{1, 20}]] &amp;amp;, myNand[], nLeaves - 1]) /. &#xD;
        myNand[] :&amp;gt; RandomChoice[varlist]) /. myNand -&amp;gt; Nor&#xD;
    &#xD;
    visualizeCount[leaves_, iterations_, Nand_] := &#xD;
     Module[{tree, counts = Table[0, {i, 0, 255}], c},&#xD;
      Monitor[Do[&#xD;
        c = 100*N@i/iterations;&#xD;
        tree = makeTreeNand[RandomInteger[{1, leaves}]];&#xD;
        counts[[FromDigits[Boole[BooleanTable[tree]], 2]]]++;&#xD;
        , {i, 1, iterations * (Nand/100)}&#xD;
        ], c];&#xD;
      Monitor[Do[&#xD;
        c = 100*N@i/iterations;&#xD;
        tree = makeTreeNor[RandomInteger[{1, leaves}]];&#xD;
        counts[[FromDigits[Boole[BooleanTable[tree]], 2]]]++;&#xD;
        , {i, 1, iterations * (1 - (Nand/100))}&#xD;
        ], c];&#xD;
      Print[ListLogPlot[Sort[counts[[#]] &amp;amp; /@ Range[0, 254]] + 1]];&#xD;
      Print[ArrayPlot[&#xD;
        IntegerDigits[#, 2, 8] &amp;amp; /@ &#xD;
         Flatten[Position[counts[[#]] &amp;amp; /@ Range[0, 254], 0] - 1], &#xD;
        Mesh -&amp;gt; True, ColorRules -&amp;gt; {0 -&amp;gt; Red, 1 -&amp;gt; Darker@Green}]];&#xD;
      Print[Column[&#xD;
        FullForm /@ (FullSimplify[BooleanFunction[#, varlist]] &amp;amp; /@ &#xD;
           Flatten[Position[counts[[#]] &amp;amp; /@ Range[0, 254], 0] - 1])]];&#xD;
      Print[BarChart[counts[[#]] &amp;amp; /@ Range[0, 254]]]&#xD;
      ]&#xD;
    &#xD;
    visualizeWhile[leaves_, time_, Nand_: 100] := &#xD;
     Module[{tree, c, start = UnixTime[]},&#xD;
      Monitor[&#xD;
       While[UnixTime[] &amp;lt; (start + (time*(Nand/100))),&#xD;
        c = UnixTime[] - start;&#xD;
        Do[tree = makeTreeNand[RandomInteger[{1, leaves}]];&#xD;
         len += 1;&#xD;
         counts[[FromDigits[Boole[BooleanTable[tree]], 2]]]++;, {100}]&#xD;
        ], c];&#xD;
      start = UnixTime[];&#xD;
      Monitor[&#xD;
       While[UnixTime[] &amp;lt; (start + (time*(1 - (Nand/100)))),&#xD;
        c = UnixTime[] - start;&#xD;
        Do[tree = makeTreeNand[RandomInteger[{1, leaves}]];&#xD;
         counts[[FromDigits[Boole[BooleanTable[tree]], 2]]]++;, {100}]&#xD;
        ], c];&#xD;
      Print[ListLogPlot[Sort[counts[[#]] &amp;amp; /@ Range[0, 254]] + 1]];&#xD;
      Print[ArrayPlot[&#xD;
        IntegerDigits[#, 2, 8] &amp;amp; /@ &#xD;
         Flatten[Position[counts[[#]] &amp;amp; /@ Range[0, 254], 0] - 1], &#xD;
        Mesh -&amp;gt; True, MeshStyle -&amp;gt; {Black, Thick}, Background -&amp;gt; Black, &#xD;
        ColorRules -&amp;gt; {0 -&amp;gt; Red, 1 -&amp;gt; Darker@Green}]];&#xD;
      Print[Column[&#xD;
        FullForm /@ (FullSimplify[BooleanFunction[#, varlist]] &amp;amp; /@ &#xD;
           Flatten[Position[counts[[#]] &amp;amp; /@ Range[0, 254], 0] - 1])]];&#xD;
      Print[BarChart[counts[[#]] &amp;amp; /@ Range[0, 254]]]&#xD;
      ]&#xD;
&#xD;
Because there are only three variables being used, the amount of possible truth tables is 256. The function uses a list to keep track of the amount of times each of those truth tables occurred and at the end it creates a logarithmic line plot and a histogram. This particular test ran for 12 hours or so. The logarithmic plot is shifted up one to make it easier to analyze the data.&#xD;
&#xD;
![Random Expression Logarithmic Plot][3]&#xD;
&#xD;
![Random Expression Histogram][4]&#xD;
&#xD;
It also formats the truth tables that weren&amp;#039;t generated into an array plot and lists the equivalent expressions for each of those truth tables.&#xD;
&#xD;
![Expressions not generated][5]&#xD;
&#xD;
    Xor[a,b,c,And[a,b,c]]&#xD;
    Not[Xor[a,b,c,And[a,b],And[a,b,c]]]&#xD;
    Not[Xor[a,b,c,And[a,c],And[a,b,c]]]&#xD;
    Not[Xor[a,b,c,And[b,c],And[a,b,c]]]&#xD;
    Not[Xor[a,b,c]]&#xD;
    Not[Xor[a,b,And[a,c],And[b,c],And[a,b,c]]]&#xD;
    Not[Xor[b,c,And[a,b],And[a,c],And[a,b,c]]]&#xD;
    Xor[a,c,And[a,b],And[b,c],And[a,b,c]]&#xD;
    Xor[a,b,c]&#xD;
    Xor[a,b,c,And[b,c],And[a,b,c]]&#xD;
    Xor[a,b,c,And[a,c],And[a,b,c]]&#xD;
    Not[Xor[a,b,c,And[a,b,c]]]&#xD;
&#xD;
##Conclusion##&#xD;
From random generation I was able to deduce to a reasonable degree of certainty that it is impossible to generate an equivalent NAND expression that&amp;#039;s simpler than the one the Wolfram Language generates for three input XOR gates. There are most likely equivalent expressions out there for four or more input XOR expressions but that proves to be very computationally intensive and time consuming. It is pretty interesting how some expressions require significantly more NAND gates to be expressed because of their structure and the nature of NAND gates. It would be interesting to look into making expressions with NOR and XOR gates in the future and maybe putting more time into generating random expressions.&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Capture2.PNG&amp;amp;userId=1371737&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Tree.png&amp;amp;userId=1371737&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Capture1.PNG&amp;amp;userId=1371737&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Capture3.PNG&amp;amp;userId=1371737&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Capture.PNG&amp;amp;userId=1371737</description>
    <dc:creator>Ben Huenemann</dc:creator>
    <dc:date>2018-07-13T17:54:42Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1732378">
    <title>[WSC19] Phylogenetic Graphs of Programming Languages using Machine Learning</title>
    <link>https://community.wolfram.com/groups/-/m/t/1732378</link>
    <description>![enter image description here][1]&#xD;
(more graphs in sample graphs section)&#xD;
&#xD;
## Introduction ##&#xD;
Phylogenetic trees are meant to show evolutionary relationships between species, and versions exist that show historical developments of programming languages. However, these relationships are limited in terms of showing how similar syntaxes are of different languages. This project&amp;#039;s goal was to develop graphs that show relationships between computer languages, that are based off of syntactical factors instead of historical factors. Such graphs would be valuable because in addition to showing similarities between languages, they could provide insight on the order that would be easiest for learning new languages. It also would give more insight into the potential of machine learning to determine such relationships.&#xD;
&#xD;
##Collecting and Saving the Data##&#xD;
Rosetta Code is a website with a list of coding tasks and their implementations in different languages. The advantage in the website is that languages can be directly compared for the same programs. It is the only data source for this project, and for programs that have more than one solution for the same language, the first language is used.&#xD;
&#xD;
The following functions are defined that will be able to scrape the programs off of the Rosetta Code website.&#xD;
&#xD;
To save time by not having to import anything more than once, the importOneTime function is defined so that values can be saved.&#xD;
&#xD;
    importOneTime[args___] := &#xD;
      importOneTime[args] = Import[args];&#xD;
&#xD;
First, a list of all languages is obtained by parsing the html on the Rosetta Code languages page.&#xD;
&#xD;
    allLanguages = &#xD;
      Sort@&#xD;
        Select[&#xD;
         importOneTime[&#xD;
          &amp;#034;http://rosettacode.org/wiki/Category:Programming_Languages&amp;#034;, &#xD;
          &amp;#034;Hyperlinks&amp;#034;],&#xD;
         StringMatchQ[#, &#xD;
            &amp;#034;http://rosettacode.org/wiki/Category:*&amp;#034;] &amp;amp;&amp;amp;&#xD;
           ! &#xD;
            StringMatchQ[#, &amp;#034;*Programming*&amp;#034; | &amp;#034;*Languages*&amp;#034; |&#xD;
              &amp;#034;Encyclopedia*&amp;#034; | &amp;#034;*Cach*&amp;#034;] &amp;amp;] /.       &#xD;
       x_String :&amp;gt; StringReplace[x,&#xD;
         &amp;#034;http://rosettacode.org/wiki/Category:&amp;#034; -&amp;gt; &amp;#034;&amp;#034;];&#xD;
&#xD;
The Rosetta Code website has each language spelled in a specific way, but there are some exceptions, so the following additions are made to help when extracting code in case the user mistypes the language name. Specific user inputs are now treated as the correct spelling.&#xD;
&#xD;
    languageTag[lang_String] :=&#xD;
      ToLowerCase[StringReplace[StringReplace[lang, &amp;#034;_&amp;#034; -&amp;gt; &amp;#034; &amp;#034;],&#xD;
        {&amp;#034;c++&amp;#034; | &amp;#034;C++&amp;#034; -&amp;gt; &amp;#034;cpp&amp;#034;, &amp;#034;#&amp;#034; -&amp;gt; &amp;#034;sharp&amp;#034;, &amp;#034;Common Lisp&amp;#034; -&amp;gt; &amp;#034;Lisp&amp;#034;,&#xD;
         &amp;#034;Liberty Basic&amp;#034; -&amp;gt; &amp;#034;lb&amp;#034;, &amp;#034;Objective C&amp;#034; -&amp;gt; &amp;#034;objc&amp;#034;,&#xD;
         &amp;#034;BASIC&amp;#034; -&amp;gt; &amp;#034;qbasic&amp;#034;, &amp;#034;UNIX Shell&amp;#034; -&amp;gt; &amp;#034;bash&amp;#034;,&#xD;
         &amp;#034;Visual Basic&amp;#034; -&amp;gt; &amp;#034;vb&amp;#034;, &amp;#034; &amp;#034; -&amp;gt; &amp;#034;&amp;#034;, &amp;#034;/&amp;#034; -&amp;gt; &amp;#034;&amp;#034;, &amp;#034;-&amp;#034; -&amp;gt; &amp;#034;&amp;#034;}]];&#xD;
&#xD;
Extracting code will require comparing positions of values in a tree, where positions are described by lists. The following function is defined to compare tree-traversal lists, element-by-element, and to stop as soon as it finds a difference, picking the higher one.&#xD;
&#xD;
    posGreater[a_List, b_List] :=&#xD;
     Module[{i},&#xD;
      i = 1;&#xD;
      While[a[[i]] === b[[i]] &amp;amp;&amp;amp; i &amp;lt; Min[Length[a], Length[b]],&#xD;
       i = i + 1];&#xD;
      Return [a[[i]] &amp;gt; b[[i]]]]&#xD;
&#xD;
The extractCode function is now defined, and it works by parsing the html on a given Rosetta Code problem page to get the program for a given language. Not every language has the same html surrounding its program, so the function checks for multiple cases.&#xD;
&#xD;
    extractCode[path_, language_] :=     &#xD;
     StringTrim[Block[{langPos, langhead, allheads, nexthead, codeText,&#xD;
        codeXML, pageXML},&#xD;
       &#xD;
       (*Retrieves the XML*)       &#xD;
       Echo[pageXML = &#xD;
         importOneTime[path, &amp;#034;XMLObject&amp;#034;] /.          &#xD;
          XMLElement[tag_, b___] :&amp;gt; XMLElement[ToLowerCase[tag], b], &#xD;
        &amp;#034;xml&amp;#034;];&#xD;
       langPos = Position[pageXML,&#xD;
         &amp;#034;class&amp;#034; -&amp;gt; languageTag[language] &amp;lt;&amp;gt; &amp;#034; highlighted_source&amp;#034;];&#xD;
       &#xD;
       If[Length[langPos] &amp;gt;= 1,&#xD;
        (*Code was correctly tagged, can be extracted*)        &#xD;
        codeXML = Extract[pageXML, #[[;; -3]]][[3]] &amp;amp; /@ langPos,        &#xD;
        (*Code was incorrectly tagged, requires further searching*)        &#xD;
        langhead = Position[pageXML,&#xD;
          XMLElement[&amp;#034;h2&amp;#034;, _, cts_] /; &#xD;
           MemberQ[cts, language, \[Infinity]]];&#xD;
        (*Look for a section heading containing the language&amp;#039;s name*)        &#xD;
        If[Length[langhead] == 1, &#xD;
         langhead = First[langhead];&#xD;
         (*Search for all section headings*)         &#xD;
         allheads = Sort[Position[pageXML, XMLElement[&amp;#034;h2&amp;#034;, _, _]]];&#xD;
         nexthead = allheads /. {{a___, langhead} -&amp;gt; \[Infinity],&#xD;
            {a___, langhead, n_, b___} -&amp;gt; n};&#xD;
         (*Extract all XML tagged with generic source code tag&#xD;
         between the two section heads*)&#xD;
         codeXML = Extract[pageXML,&#xD;
           Select[Position[pageXML,&#xD;
             XMLElement[&amp;#034;pre&amp;#034;, {&amp;#034;class&amp;#034; -&amp;gt; &amp;#034;text highlighted_source&amp;#034;},&#xD;
              source_]],&#xD;
            posGreater[#, langhead] &amp;amp;&amp;amp; posGreater[nexthead, #] &amp;amp;]&#xD;
           ];&#xD;
         , codeXML = &amp;#034;&amp;#034;;&#xD;
         ]];&#xD;
       (*Convert the extracted XML to text*)       &#xD;
       Apply[StringJoin, codeXML //. {&#xD;
          XMLElement[&amp;#034;pre&amp;#034;, {&amp;#034;class&amp;#034; -&amp;gt; &amp;#034;text highlighted_source&amp;#034;},&#xD;
            source_] -&amp;gt; source,&#xD;
          XMLElement[&amp;#034;br&amp;#034;, _, _] -&amp;gt; &amp;#034;\n&amp;#034;,&#xD;
          XMLElement[_, _, {text___}] -&amp;gt; text}&#xD;
        ]]]&#xD;
Sometimes a task is listed for a given language on the Rosetta Code page but it ends up being empty. For this reason, a simple function is created to count the characters of a program, and it will be used to filter out any empty programs.&#xD;
&#xD;
    characterCount[str_] :=      &#xD;
      StringLength[&#xD;
       StringReplace[str, {&amp;#034;\n&amp;#034; -&amp;gt; &amp;#034;&amp;#034;, &amp;#034; &amp;#034; -&amp;gt; &amp;#034;&amp;#034;, &amp;#034;\t&amp;#034; -&amp;gt; &amp;#034;&amp;#034;}]];&#xD;
&#xD;
Now, parsing the html for a given programming language allows for the generation of a list of all tasks on Rosetta Code which have a solution written in that language. The function gets a list of every task for a language, using the characterCount function to filter out any empty programs.&#xD;
&#xD;
    getCompletePageList[language_String] := &#xD;
      Module[{links},&#xD;
      links = &#xD;
       Cases[&#xD;
        DeleteCases[&#xD;
         importOneTime[&#xD;
          &amp;#034;http://rosettacode.org/wiki/Category:&amp;#034; &amp;lt;&amp;gt;           &#xD;
           StringReplace[language, &amp;#034; &amp;#034; -&amp;gt; &amp;#034;_&amp;#034;], &amp;#034;Hyperlinks&amp;#034;],&#xD;
         x_String /;&#xD;
          (StringMatchQ[x, StringExpression[&#xD;
             &amp;#034;*Category*&amp;#034; | &amp;#034;*Reports:*&amp;#034; | &amp;#034;*Rosetta_Code*&amp;#034; |&#xD;
              &amp;#034;*Language_Comparison_Table*&amp;#034; | &amp;#034;*Help:*&amp;#034; | &amp;#034;*User:*&amp;#034; |&#xD;
              &amp;#034;*Special:*&amp;#034; |&#xD;
              (&amp;#034;*&amp;#034; &amp;lt;&amp;gt; StringReplace[language, &amp;#034; &amp;#034; -&amp;gt; &amp;#034;_&amp;#034;])]])],&#xD;
        x_String /; StringMatchQ[x, &amp;#034;http://rosettacode.org/wiki/*&amp;#034;]];&#xD;
      Select[links, characterCount[extractCode[#, language]] &amp;gt;= 1 &amp;amp;]]&#xD;
&#xD;
Generating any graph will require the code for each language to be used as data, so this is imported once and saved.&#xD;
&#xD;
This list of lists is defined by iterating through every language and calling getCompletedPageList to find all links that have nonempty programs for the language on them. This contains all links that need to be used. Running this takes a long time, so the progress is monitored. Once finished, the data is saved.&#xD;
&#xD;
    tasksForLang = &#xD;
      Map[Monitor[getCompletePageList[#], #] &amp;amp;, allLanguages];&#xD;
&#xD;
Future graphs will often be generated by using the top n most common languages on Rosetta Code, so now that the amount of programs per language is known, the following list can be ordered to rank all languages by how much data they have on Rosetta Code. As a list of tuples, it also contains the information of how many nonempty programs each language has.&#xD;
&#xD;
    popularOrder = &#xD;
      Reverse@SortBy[&#xD;
        Partition[Riffle[allLanguages, Map[Length[#] &amp;amp;, tasksForLang]], &#xD;
         2], #[[2]] &amp;amp;];&#xD;
&#xD;
Now that all links are listed, a one-time extraction can be done from every single link to get the program. Since this takes a while, it is also monitored. The resulting programs are saved in a list of lists which has the same dimensions as taskForLang.&#xD;
&#xD;
    codeForLang = Module[&#xD;
       {copyOfTasksForLang = tasksForLang},&#xD;
       Monitor[For[i = 1, i &amp;lt;= Length[tasksForLang], i++,&#xD;
         For[j = 1, j &amp;lt;= Length[tasksForLang[[i]]], j++,&#xD;
          copyOfTasksForLang[[i]][[j]] =&#xD;
           extractCode[tasksForLang[[i]][[j]], allLanguages[[i]]]&#xD;
          ]&#xD;
         ], allLanguages[[i]]];&#xD;
       Return[copyOfTasksForLang]&#xD;
       ];&#xD;
&#xD;
Now the results are saved for future reference:&#xD;
&#xD;
    DumpSave[&amp;#034;RosettaCodeData.mx&amp;#034;, {allLanguages, tasksForLang, &#xD;
       codeForLang}];&#xD;
&#xD;
##Importing Saved Data##&#xD;
The saved data can be imported as generating it can take upwards of an hour. This file can be found in my GitHub repository [PhylogeneticGraphs][2] (https://github.com/mshundi/PhylogeneticGraphs).&#xD;
&#xD;
    Clear[allLanguages, tasksForLang, codeForLang]&#xD;
    Import[&amp;#034;RosettaCodeData.mx&amp;#034;]&#xD;
&#xD;
##Creating Functions that will be Used to Generate Graphs##&#xD;
The function that generates graphs will accept either an integer specifying the top n languages, a string of language names separated by spaces, or a list of languages. Three versions of the same function are written -- one for each type of input -- and in case the input is first validated. If the input is invalid, default values are used instead.&#xD;
&#xD;
This pair of functions calculates the top n programs based on amount of data, and rounds up if there are any ties.&#xD;
&#xD;
    hasAtLeastNPrograms[n_] :=      &#xD;
      Length[Select[popularOrder, #[[2]] &amp;gt;= n &amp;amp;]];&#xD;
&#xD;
    thresholdForTopNPrograms[n_] :=&#xD;
      Module[{m = 0},&#xD;
       While[hasAtLeastNPrograms[m] &amp;gt; n, m++]; Return[m]];&#xD;
&#xD;
These functions calculate what languages will be used based on the input of the user. Each has the same name but a different input type so it can easily be called.&#xD;
&#xD;
    languageGenerator[n_Integer] :=&#xD;
      Module[{m},&#xD;
       If[n &amp;lt; 2, m = 2, m = n];&#xD;
       machineLearningLanguages = &#xD;
        programlistofpopularityn[thresholdForTopNPrograms[m]]];&#xD;
&#xD;
    languageGenerator[n_String] :=      &#xD;
      machineLearningLanguages = StringSplit[n];&#xD;
&#xD;
    languageGenerator[n_List] :=&#xD;
      machineLearningLanguages = n;&#xD;
&#xD;
This function is made to get the first n programs for a language and it will be used when selecting programs to add to the dataset.&#xD;
&#xD;
    firstNForLang[n_Integer, lang_String] :=&#xD;
         Take[codeForLang[[&#xD;
            Position[allLanguages, lang][[1]][[1]]&#xD;
            ]], n]&#xD;
&#xD;
When a matrix is generated of all languages that get confused for one another, this function will return a list of edges represented as ordered triples, with the third element representing the weight of the edge. It then returns all edges whose weights are at least at a specified threshold, while not exceeding the upper limit for the threshold. &#xD;
&#xD;
    weightedEdges[n_, langs_, matrix_] :=     &#xD;
     Module[{list = {}, sorted = Sort[langs], returnedList},&#xD;
      For[i = 1, i &amp;lt;= Length[langs], i++,&#xD;
       For[j = i + 1, j &amp;lt;= Length[langs], j++,&#xD;
        AppendTo[list, {sorted[[i]], sorted[[j]], matrix[[j]][[i]]}];&#xD;
        AppendTo[list, {sorted[[j]], sorted[[i]], matrix[[i]][[j]]}]&#xD;
        ]];&#xD;
      (*Edges are reverse sorted by weight in case weak ones need to be&#xD;
    trimmed off*)      &#xD;
      returnedList = &#xD;
       Select[ReverseSortBy[list, #[[3]] &amp;amp;], #[[3]] &amp;gt;= n &amp;amp;];&#xD;
      (*Errors occur when passing this limit, so the excess, &#xD;
      weak edges are trimmed*)&#xD;
      If[Length[returnedList] &amp;gt;= 896,&#xD;
       returnedList = returnedList[[;; 896]],&#xD;
       returnedList = returnedList&#xD;
       ];&#xD;
      Return[returnedList]&#xD;
      ]&#xD;
&#xD;
Now the function that will ultimately make a graph when given the necessary input is created. This takes in a threshold, a graph layout, a list of all languages that will be included on the graph, and the confusion matrix from the machine learning testing. It calls weightedEdges to get a list of edges to use. The results are used to create a graph where the thickness of an edge linearly corresponds to its weight. These weights are just how often two languages get confused for each other. An arrow on the graph going from A to B means that B gets mistaken as A, meaning that B is similar and would be easier to learn if one already knows A.&#xD;
&#xD;
    graphAnEdgeList[n_, layout_: Automatic, langs_, matrix_] :=      &#xD;
      Module[{weights = {}, edge = {}, &#xD;
        edges = weightedEdges[n, langs, matrix]},&#xD;
       Map[AppendTo[weights, #[[3]]/5000.0] &amp;amp;, edges];&#xD;
       Map[AppendTo[edge, #[[2]] -&amp;gt; #[[1]]] &amp;amp;, edges];&#xD;
       Graph[langs, edge, &#xD;
        EdgeStyle -&amp;gt; Thread[edge -&amp;gt; (Thickness[#] &amp;amp; /@ weights)], &#xD;
        VertexLabels -&amp;gt; &amp;#034;Name&amp;#034;, GraphLayout -&amp;gt; layout]&#xD;
       ];&#xD;
&#xD;
##Making the Graphing Functions##&#xD;
&#xD;
Two functions are made, one which outputs a manipulable graph and one which outputs a static graph.&#xD;
&#xD;
For the manipulable graph, the input will be one parameter: either an integer denoting the top n languages, a string of space-separated languages, or a list of languages. The output will be a manipulable graph where the user will be able to change the threshold for edges that are included and change the graph layout.&#xD;
&#xD;
The following well-documented function is used to create the manipulable graph.&#xD;
&#xD;
    phylogeneticGraph[languagestoinclude_] :=&#xD;
     &#xD;
     Module[{machineLearningLanguages = {}, programsToUsePerLanguage, &#xD;
       datasetPrograms, dataset, matrixValues, minThresh, dataTraining, &#xD;
       dataTesting, dataClassifier, dataClassifierTesting},&#xD;
      &#xD;
      (*Generates the list of languages to use based on user input*)&#xD;
      &#xD;
      machineLearningLanguages = languageGenerator[languagestoinclude];&#xD;
      &#xD;
      (*Display errors sometimes occur at high numbers and low thresholds,&#xD;
      so the minimum threshold is adjusted based on how many languages \&#xD;
    are being used*)&#xD;
      &#xD;
      If[Length[machineLearningLanguages] &amp;gt; 50, minThresh = 3, &#xD;
       minThresh = 1];&#xD;
      &#xD;
      (*Finds the minimum amount of data that any of the programs being \&#xD;
    used has, &#xD;
      and uses that number as the amount of tasks to use for each \&#xD;
    language when making the dataset.*)&#xD;
      programsToUsePerLanguage =&#xD;
       Min[Map[&#xD;
         Length[tasksForLang[[Position[allLanguages, #][[1]][[1]]]]] &amp;amp;,&#xD;
         machineLearningLanguages]];&#xD;
      &#xD;
      (*Makes a list of lists of all programs to use for the dataset by \&#xD;
    picking the same amount from each, &#xD;
      which was calculated in programsToUsePerLanguage*)&#xD;
      &#xD;
      datasetPrograms = &#xD;
       Map[firstNForLang[programsToUsePerLanguage, #] &amp;amp;, &#xD;
        machineLearningLanguages];&#xD;
      &#xD;
      (*Creates a 2-column dataset of language and program. &#xD;
      These are taken directly off of datasetPrograms*)&#xD;
      &#xD;
      dataset = &#xD;
       Association @@@ Flatten[Map[Table[{&amp;#034;code&amp;#034; -&amp;gt; datasetPrograms[[&#xD;
                  Position[machineLearningLanguages, lan][[1]][[1]]]][[#]],&#xD;
              &amp;#034;language&amp;#034; -&amp;gt; lan}, {lan, machineLearningLanguages}] &amp;amp;,&#xD;
           Range[programsToUsePerLanguage]], 1] // Dataset;&#xD;
      &#xD;
      (*Splits the dataset into training data and testing data in a ratio \&#xD;
    of 1 to 2*)&#xD;
      {dataTraining, dataTesting} = &#xD;
       TakeDrop[dataset, Round[Length[dataset]/3]];&#xD;
      &#xD;
      (*Creates a classifier based on predicting the language given the \&#xD;
    code, training it and testing it on the designated parts of the data \&#xD;
    set*)&#xD;
      dataClassifier = &#xD;
       Classify[dataTraining -&amp;gt; &amp;#034;language&amp;#034;, PerformanceGoal -&amp;gt; &amp;#034;Speed&amp;#034;];&#xD;
      dataClassifierTesting = &#xD;
       ClassifierMeasurements[dataClassifier, dataTesting -&amp;gt; &amp;#034;language&amp;#034;];&#xD;
      &#xD;
      (*Gets a confusion matrix based on wrong classifications made by \&#xD;
    the classifier. It will be used as the basis of generating the graph*)&#xD;
    &#xD;
        matrixValues = &#xD;
       dataClassifierTesting[{&amp;#034;Precision&amp;#034;, &amp;#034;ConfusionMatrix&amp;#034;}][[2]];&#xD;
      Length[weightedEdges[1, machineLearningLanguages, matrixValues]];&#xD;
      &#xD;
      (*Makes a Manipulable graph where the user can change the layout \&#xD;
    and threshold. &#xD;
      The minimum threshold is determined based on the amount of \&#xD;
    languages and the maximum threshold is determined based on the \&#xD;
    strength of the strongest edge*)&#xD;
      &#xD;
      Manipulate[&#xD;
       graphAnEdgeList[threshold, layout, machineLearningLanguages, &#xD;
        matrixValues], {threshold, minThresh, &#xD;
        weightedEdges[1, machineLearningLanguages, matrixValues][[1]][[3]],&#xD;
        1}, {layout, {Automatic, &amp;#034;BipartiteEmbedding&amp;#034;, &#xD;
         &amp;#034;CircularEmbedding&amp;#034;, &amp;#034;CircularMultipartiteEmbedding&amp;#034;, &#xD;
         &amp;#034;DiscreteSpiralEmbedding&amp;#034;, &amp;#034;GridEmbedding&amp;#034;, &amp;#034;LinearEmbedding&amp;#034;, &#xD;
         &amp;#034;MultipartiteEmbedding&amp;#034;, &amp;#034;SpiralEmbedding&amp;#034;, &amp;#034;StarEmbedding&amp;#034;}}]]&#xD;
&#xD;
For example, using the function to give a manipulable graph for the top 25 languages gives:&#xD;
&#xD;
    phylogeneticGraph[25]&#xD;
![enter image description here][3]&#xD;
&#xD;
To make a static graph, this function essentially does the same thing as the previous function, but instead of outputting a manipulable graph, it only gives one static graph. Because it doesn&amp;#039;t allow the user to change parameters once the graph is generated, it takes in the arguments for threshold and layout as inputs.&#xD;
&#xD;
    staticPhylogeneticGraph[languagestoinclude_, threshold_Integer, &#xD;
      layout_String] :=&#xD;
     Module[&#xD;
      {machineLearningLanguages = {}, programsToUsePerLanguage, &#xD;
       datasetPrograms, dataset, matrixValues, minThresh, dataTraining, &#xD;
       dataTesting, dataClassifier, dataClassifierTesting},&#xD;
      &#xD;
      (*Generates list of languages to use based on user input*)&#xD;
      &#xD;
      machineLearningLanguages = languageGenerator[languagestoinclude];&#xD;
      &#xD;
      (*Display errors sometimes occur at high numbers and low thresholds,&#xD;
      due to having too many branches,&#xD;
      so the minimum threshold is adjusted based on how many languages \&#xD;
    are being used.*)&#xD;
      &#xD;
      If[Length[machineLearningLanguages] &amp;gt; 50, minThresh = 3, &#xD;
       minThresh = 1];&#xD;
      &#xD;
      (*Finds the minimum amount of data that any of the programs being \&#xD;
    used has, &#xD;
      and uses that number as the amount of tasks to use for each \&#xD;
    language when making the dataset.*)&#xD;
      programsToUsePerLanguage =&#xD;
       Min[Map[&#xD;
         Length[tasksForLang[[Position[allLanguages, #][[1]][[1]]]]] &amp;amp;, &#xD;
         machineLearningLanguages]];&#xD;
      &#xD;
      (*Makes a list of lists of all programs to use for the dataset by \&#xD;
    picking the same amount from each, &#xD;
      which was calculated in programsToUsePerLanguage*)&#xD;
      &#xD;
      datasetPrograms = &#xD;
       Map[firstNForLang[programsToUsePerLanguage, #] &amp;amp;, &#xD;
        machineLearningLanguages];&#xD;
      &#xD;
      (*Creates a 2-&#xD;
      column dataset of language and program in cycling order of form. &#xD;
      These are taken directly off of datasetPrograms*)&#xD;
      &#xD;
      dataset = &#xD;
       Association @@@ Flatten[Map[Table[{&amp;#034;code&amp;#034; -&amp;gt; datasetPrograms[[&#xD;
                  Position[machineLearningLanguages, lan][[1]][[1]]]][[#]],&#xD;
              &amp;#034;language&amp;#034; -&amp;gt; lan}, {lan, machineLearningLanguages}] &amp;amp;,&#xD;
           Range[programsToUsePerLanguage]], 1] // Dataset;&#xD;
      &#xD;
      (*Splits the dataset into training data and testing data in a ratio \&#xD;
    of 1 to 2*)&#xD;
      {dataTraining, dataTesting} = &#xD;
       TakeDrop[dataset, Round[Length[dataset]/3]];&#xD;
      &#xD;
      (*Creates a classifier based on predicting the language given the \&#xD;
    code, training it and testing it on the designated parts of the data \&#xD;
    set*)&#xD;
      dataClassifier = &#xD;
       Classify[dataTraining -&amp;gt; &amp;#034;language&amp;#034;, PerformanceGoal -&amp;gt; &amp;#034;Speed&amp;#034;];&#xD;
      dataClassifierTesting = &#xD;
       ClassifierMeasurements[dataClassifier, dataTesting -&amp;gt; &amp;#034;language&amp;#034;];&#xD;
      &#xD;
      (*Gets a confusion matrix based on wrong classifications made by \&#xD;
    the classifier. It will be used as the basis of generating the graph*)&#xD;
    &#xD;
        matrixValues = &#xD;
       dataClassifierTesting[{&amp;#034;Precision&amp;#034;, &amp;#034;ConfusionMatrix&amp;#034;}][[2]];&#xD;
      Length[weightedEdges[1, machineLearningLanguages, matrixValues]];&#xD;
      &#xD;
      (*Generates the static graph by calling graphAnEdgeList*)&#xD;
      &#xD;
      graphAnEdgeList[minThresh + Abs[threshold], layout, &#xD;
       machineLearningLanguages, matrixValues]]&#xD;
&#xD;
To see a low-threshold graph for top 15 languages in a circular display:&#xD;
&#xD;
    staticPhylogeneticGraph[15, 1, &amp;#034;CircularEmbedding&amp;#034;]&#xD;
![enter image description here][4]&#xD;
&#xD;
##Summary of Results##&#xD;
The final product is functions that generate graphs for a list of languages, showing all connections having strength above a specified threshold, and having the thickness of edges correspond to their strengths. Relationships between programming languages were determined by how often a machine learning classifier would confuse languages for each other. On the graph, an arrow from A to B means that B gets confused for A, and someone who knows language A would therefore find it easier to learn language B. Few pairs of languages exist that have strong connections going both ways.&#xD;
&#xD;
All data used came from Rosetta Code, which provides tasks written in different program languages. Individual programs were scraped off of the website by using Mathematica to parse the HTML. This data was saved once extracted, as there were close to 1,000 languages and almost 1,000 unique programming tasks. A data set would be made with programs of all languages that were going to be in the graph. The benefit of using Rosetta Code was that most of the data was of programs doing the same task but coded in different languages. A machine learning classifier would train and test on parts of the data, and confusion between languages would indicate a relationship, with higher amounts of confusion corresponding to a stronger relationship.&#xD;
&#xD;
The are two main functions: one that creates a manipulable graph and one which creates a static graph. Both take in either an integer representing the top n languages or a string of space-separated languages. This determines what languages to include in the graph. The manipulable graph allows the user to change the threshold of the edge strength and the graph layout, while the static graph requires that these two are passed as parameters beforehand.&#xD;
&#xD;
The results do have some limitations. While the overall data size was relatively large, it still represents a tiny subset of all available programs. Additionally, only Rosetta Code was used as a data source, and its programs are relatively short in length. While the code itself does work, it can also likely be cleaned up, and its performance can probably be improved. &#xD;
&#xD;
In terms of using charts for deciding what languages to learn, the arrows might not tell the full story. A strong arrow from A to B might indicate that knowledge of A benefits one most in learning B, but it doesn&amp;#039;t necessarily mean that B is the easiest to learn. It&amp;#039;s still possible that there are languages completely unrelated to A which are still easier to learn than B. While the graphs should be considered, they don&amp;#039;t provide information on the general complexity of a language or how easy or difficult it is to migrate to that language.&#xD;
&#xD;
##Sample Graphs##&#xD;
The following sample graphs are shown for the top n programs and for each n, multiple graphs are given with varying thresholds for minimum edge strength. Arrows from A to B indicate that B gets confused for A and that knowing A would make it easier to learn B.&#xD;
&#xD;
Top 5 Languages: High Threshold&#xD;
![enter image description here][5]&#xD;
Top 5 Languages: Low Threshold&#xD;
![enter image description here][6]&#xD;
Top 10 Languages: High Threshold&#xD;
![enter image description here][7]&#xD;
Top 10 Languages: Low Threshold&#xD;
![enter image description here][8]&#xD;
Top 15 Languages: High Threshold&#xD;
![enter image description here][9]&#xD;
Top 15 Languages: Medium Threshold&#xD;
![enter image description here][10]&#xD;
Top 15 Languages: Low Threshold&#xD;
![enter image description here][11]&#xD;
Top 20 Languages: High Threshold&#xD;
![enter image description here][12]&#xD;
Top 20 Languages: Medium Threshold&#xD;
![enter image description here][13]&#xD;
Top 20 Languages: Low Threshold&#xD;
![enter image description here][14]&#xD;
Top 30 Languages: High Threshold&#xD;
![enter image description here][15]&#xD;
Top 30 Languages: Low Threshold&#xD;
![enter image description here][16]&#xD;
Top 50 Languages: High Threshold&#xD;
![enter image description here][17]&#xD;
Top 50 Languages: Low Threshold&#xD;
![enter image description here][18]&#xD;
Top 100 Languages: High Threshold&#xD;
![enter image description here][19]&#xD;
Top 100 Languages: Low Threshold&#xD;
![enter image description here][20]&#xD;
&#xD;
##Future Explorations##&#xD;
The results from the generated graphs were reasonable and promising, suggesting that similar methods could be used for larger datasets and fields. While the historical influences of programming languages on each other are relatively well known, this could potentially help in finding relationships in writing, music, and even art, both in the past and in the present. Machine learning is capable of handling larger amounts of data than what is available with computer languages, and it would likely scale well for these broader fields.&#xD;
&#xD;
##Links to Data##&#xD;
The full notebook and extracted code can be found in my GitHub repository [PhylogeneticGraphs][21].&#xD;
All data can be found at [Rosetta Code][22].&#xD;
&#xD;
##Acknowledgements##&#xD;
Thank you to my mentor, Nikki Sigurdson, and to everyone -- including Mads Bahrami, Philip Maymin, Christian Pasquel, and more -- at the 2019 Wolfram Summer Camp who helped teach me the Mathematica language and worked with me on coding and debugging. Also a big thank you to Stephen Wolfram and all of the organizers for organizing the camp and providing me with this opportunity.&#xD;
&#xD;
Thank you to Jon McLoone for showing how to extract code from the Rosetta Code website in his blog on comparing code lengths [Code Length Measured in 14 Languages][23], and thank you to  [Rosetta Code][24] and its contributors for providing all of the data.&#xD;
&#xD;
&#xD;
  [1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=WolframFinalPresentation.png&amp;amp;userId=1724884&#xD;
  [2]: https://github.com/mshundi/PhylogeneticGraphs&#xD;
  [3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.29.13PM.png&amp;amp;userId=1724884&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.26.49PM.png&amp;amp;userId=1724884&#xD;
  [5]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.45.37PM.png&amp;amp;userId=1724884&#xD;
  [6]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.45.46PM.png&amp;amp;userId=1724884&#xD;
  [7]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.46.43PM.png&amp;amp;userId=1724884&#xD;
  [8]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.46.49PM.png&amp;amp;userId=1724884&#xD;
  [9]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.47.35PM.png&amp;amp;userId=1724884&#xD;
  [10]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.48.14PM.png&amp;amp;userId=1724884&#xD;
  [11]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.48.25PM.png&amp;amp;userId=1724884&#xD;
  [12]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.49.52PM.png&amp;amp;userId=1724884&#xD;
  [13]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.50.07PM.png&amp;amp;userId=1724884&#xD;
  [14]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.50.18PM.png&amp;amp;userId=1724884&#xD;
  [15]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.53.16PM.png&amp;amp;userId=1724884&#xD;
  [16]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.52.43PM.png&amp;amp;userId=1724884&#xD;
  [17]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.52.26PM.png&amp;amp;userId=1724884&#xD;
  [18]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.52.08PM.png&amp;amp;userId=1724884&#xD;
  [19]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.51.41PM.png&amp;amp;userId=1724884&#xD;
  [20]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2019-07-11at8.51.31PM.png&amp;amp;userId=1724884&#xD;
  [21]: https://github.com/mshundi/PhylogeneticGraphs&#xD;
  [22]: http://rosettacode.org/wiki/Rosetta_Code&#xD;
  [23]: https://blog.wolfram.com/2012/11/14/code-length-measured-in-14-languages&#xD;
  [24]: http://rosettacode.org/wiki/Rosetta_Code</description>
    <dc:creator>Matias Shundi</dc:creator>
    <dc:date>2019-07-12T01:15:23Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1120587">
    <title>Find the longest word path in dictionary?</title>
    <link>https://community.wolfram.com/groups/-/m/t/1120587</link>
    <description>#Cross post [here](https://mathematica.stackexchange.com/questions/144550/how-to-find-a-longest-word-path-in-dictionary)&#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
A word path means the last character of the last word is same to the first character of the next word.If I have $55$ words,I can find it with this method.&#xD;
###Build a graph&#xD;
&#xD;
    SeedRandom[2]&#xD;
    string = Select[ToLowerCase[RandomSample[DictionaryLookup[]]], &#xD;
       3 &amp;lt; StringLength[#] &amp;lt; 5 &amp;amp;];&#xD;
    g = RelationGraph[StringTake[#, -1] == StringTake[#2, 1] &amp;amp;, &#xD;
      string[[;; 55]], VertexLabels -&amp;gt; &amp;#034;Name&amp;#034;]&#xD;
![Mathematica graphics](http://i.stack.imgur.com/FdJXm.png)&#xD;
&#xD;
###Find a longest word path by [Jason](https://mathematica.stackexchange.com/users/9490/jason-b)&amp;#039;s answer [here](https://mathematica.stackexchange.com/a/136278/21532)&#xD;
&#xD;
    allPaths = &#xD;
      FindPath[g, #2, #1, Infinity, All] &amp;amp; @@@ &#xD;
        Subsets[VertexList[g], {2}] // Apply[Join];&#xD;
    First[TakeLargestBy[allPaths, Length@Union@# &amp;amp;, 1]]&#xD;
&amp;gt;`{calm,muir,reef,fray,yaws,seed,deaf,fnma,axis,stow,waft,tint,trig,good,duns,sill,loge,etch,hill,lath,howl}`&#xD;
&#xD;
Well I have to say this is a very very slow solution.I even cannot find more than $60$ words.Actually I want to find `Length[DictionaryLookup[]]=92518` words. It seem I still have a long way to go.Do any suggestion can give?</description>
    <dc:creator>Yode Japhe</dc:creator>
    <dc:date>2017-06-15T01:31:44Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1383122">
    <title>[WSC18] Visualizing Fractional Colorings for Random Graphs</title>
    <link>https://community.wolfram.com/groups/-/m/t/1383122</link>
    <description>![enter image description here][1]&#xD;
#Project Description&#xD;
Graph coloring is an NP-complete problem that asks for the minimum number of colors required to color a graph such that no two adjacent vertices can have the same color. Because this is such a well-known topic, a lot of research has been done on it. However, not much study has been done on fractional colorings, which is simply a generalized graph coloring. What makes the fractional coloring problem complicated is that in addition to the problem constraint, each vertex is assigned a list of colors. So, the problem statement is as follows: &amp;#034;What is the minimum number of colors such that no two adjacent vertices have any colors in common?&amp;#034; Because each vertex can have varying number of colors, the infamous problem of fractional graph coloring is NP-complete. However, it can be reasonably approached through linear programming. In fact, the minimum real number to color a fractional graph while still satisfying the problem&amp;#039;s constraints can be obtained as a solution to a linear program. In this project, I will be comparing two versions of the graph coloring problem: integral and fractional. &#xD;
&#xD;
##Definitions&#xD;
$\textbf{Chromatic Number}$ [$\chi(G)$ , $\chi^F(G)$]: Minimum number of colors required to color a graph while satisfying the coloring problem&amp;#039;s constraints.   &#xD;
$\textbf{Chromatic Polynomial}$ [$P(G, z), P(G^F, z)$]: Polynomial of order $n$ that counts the number of colorings as a function of the number of colors. Therefore, the minimum value that makes the function positive is the chromatic number.    &#xD;
$\textbf{a:b-coloring}$: Coloring that uses $a$ available colors to color a graph with $b$ vertices.  &#xD;
$\textbf{Graph Homomorphism}$: Mapping between two graphs that respects their structure.  &#xD;
$\textbf{Vertex-transitive graph}$: Graph such that every pair of vertices is equivalent under some element of its automorphism group.&#xD;
&#xD;
##Basic Methods&#xD;
Below are the elementary methods purely pertaining to graph colorings:&#xD;
&#xD;
    ValidColoring[g_, c_] := &#xD;
      AllTrue[Table[&#xD;
        Intersection[{c[[i]]}, c[[AdjacencyList[g, i]]]] == {}, {i, 1, &#xD;
         VertexCount[g]}], TrueQ];&#xD;
&#xD;
    ChromaticNumber[g_] := &#xD;
      MinValue[{z, z &amp;gt; 0 &amp;amp;&amp;amp; ChromaticPolynomial[g, z] &amp;gt; 0}, z, Integers];&#xD;
The $\textit{ValidColoring}$ method ensures that the current list of colors satisfies the problem&amp;#039;s constraint that no two adjacent vertices can have the same colors. It does so by checking that there are no intersections between each pair of adjacent vertices. The $\textit{ChromaticNumber}$ method goes through all integer values that make the chromatic polynomial of a graph positive and takes the minimum out of those values.&#xD;
&#xD;
##Fractional Colorings in Terms of Independent Sets&#xD;
$I(G)$: set of all independent sets of vertices in $\textit{V(G)}$  &#xD;
$\textit{I(G,u)}$: set of all independent sets of vertices containing the vertex $u$&#xD;
&#xD;
In this context, a fractional coloring is a mapping $f$: $I(G) \rightarrow$ [0, 1] with the property that, for every vertex $u$, $\sum_{J \in I(G,u)} f(J) \ge 1$. Then, the sum of the function values over all independent sets is called the weight of the fractional coloring. Therefore, the fractional chromatic number is the infimum of all the sums of the fractional coloring weights. To see the connection between fractional colorings and independent sets, one must note that each color class is an independent set belonging to $I(G)$. Then, define $f$: $I(G) \rightarrow$ [0, 1], mapping each color class to 1 and every other independent sets to 0. Next, suppose that a graph $G$ has a proper a:b-coloring. In this case, if one defines a function that sends each color class to $\frac{1}{b}$ and every other independent set to 0, it is true that $\sum_{J \in I(G,u)} f(J) = 1$ for every vertex $u$, which then leads to a fractional coloring with weight $\frac{a}{b}$.&#xD;
&#xD;
##Linear Programming Formulation&#xD;
Below are the methods used to compute the fractional chromatic number:&#xD;
&#xD;
    independentSets[G_] := FindIndependentVertexSet[G, Infinity, All]&#xD;
    A[is_, G_] := &#xD;
     Table[If[MemberQ[is[[i]], j], 1, 0], {i, Length[is]}, {j, &#xD;
       VertexCount[G]}] &#xD;
    OneVector[N_Integer] := Table[1, N]&#xD;
    y[one_, A_, R_] := LinearProgramming[one, Transpose[A], R]&#xD;
From the relationship between chromatic numbers and independent sets, one can formulate a matrix $A(G)$ such that its columns are indexed by $V(G)$ and that its rows are indexed by $I(G)$. When formulating this matrix, entries are 1 if they are in the independent set represented by the column and 0 if they are not. Doing so essentially gives a characteristic function of the vertices&amp;#039; corresponding independent sets. Next, make a variable vector $y(G)$ that is indexed by $I(G)$. Then, the task reduces to minimizing the sum of the variables in the vector $y(G)$ (weighted coloring of graphs), subject to the set of constraints that each entry in $y(G)^T A(G) \ge 1$ and that all elements in $y(G)$ fall in the interval [0, 1].&#xD;
&#xD;
##Coloring the Graph&#xD;
###Idea&#xD;
The $k$-fold chromatic number is given by $\chi(G) = \frac{1}{k}\chi(G&amp;#039;)$, where $G&amp;#039;$ has each vertex in $G$ replaced with $k$ copies, and each edge $(u&amp;#039;,v&amp;#039;)$ in $G&amp;#039;$ is formed if the original vertices of both $u&amp;#039;$ and $v&amp;#039;$ in $G$ are the same or incident. This transformation is called **strong graph product**, which &amp;#039;decomposes&amp;#039; each vertex into a complete graph $K_{k}$,while maintaining the overall structure of $G$. After coloring $G&amp;#039;$, group back all vertices that belong to the same &amp;#039;super-vertex&amp;#039;, which will lead $G$ to have multiple colors contributed by the sub-vertices in $G&amp;#039;$.&#xD;
&#xD;
###Methods&#xD;
&#xD;
    explodeGraph[g_, 1] := g&#xD;
    explodeGraph[g_, k_] := &#xD;
     	Graph[Union @@ newEdges[k] @@@ EdgeList[g]]&#xD;
    newEdges[k_][v1_, v2_] := &#xD;
     	With[{nv1 = Thread[{v1, Range[k]}], nv2 = Thread[{v2, Range[k]}]},&#xD;
      		UndirectedEdge @@@ Join[&#xD;
        			Tuples[{nv1, nv2}],&#xD;
        			Subsets[nv1, {2}],&#xD;
        			Subsets[nv2, {2}]&#xD;
        		]&#xD;
      	]&#xD;
   &#xD;
&#xD;
    mapping[n_, g_, vstyle_, newmapping_] := &#xD;
         Sort[Table[{newmapping[vstyle[[i]][[1]]], vstyle[[i]][[2]]}, {i, &#xD;
            Length[vstyle]}]]&#xD;
    &#xD;
    FractionalColoring[n_Integer, m_Integer, cmaplist_] := &#xD;
     Table[Graphics[{EdgeForm[Black], &#xD;
        Table[{cmaplist[[z]][[k]], &#xD;
          Disk[{0, 0}, &#xD;
           1, {-\[Pi]/2 + 2 \[Pi]*(k - 1)/m, -\[Pi]/2  + &#xD;
             2 \[Pi]*k/m}]},  {k, 1, m , 1}]}], {z, 1, n, 1}]&#xD;
&#xD;
Example with a cycle graph of 5 vertices ($C_{5}$):&#xD;
![Strong graph product example][2]  &#xD;
&#xD;
##Special Graphs&#xD;
###Cycle Graph&#xD;
Denoted by $C_{n}$, a cycle graph is a graph on $n$ nodes containing a single cycle through all nodes.&#xD;
Below is a cycle graph with 8 vertices. &#xD;
![enter image description here][3]&#xD;
&#xD;
In a cycle graph, it is quite obvious that $i)$ if there are even number of vertices, then the chromatic number is 2, and $ii)$ if there are odd number of vertices, then the chromatic number is 3. &#xD;
&#xD;
However, fractional graph coloring is slightly different. Although $\chi(G) = \chi^F(G)$ for even cases, that is not true for odd cases. In fact, $\chi^F (C_{2n + 1}) = 2 + \frac{1}{n}$. The fractional chromatic number in a cycle graph must be greater than 2 because four &amp;#034;one-half&amp;#034; colors must be used in any vertex triplets. Below is an example of 5:2-coloring of a cycle graph. ![enter image description here][4]&#xD;
&#xD;
###Kneser Graph&#xD;
In a Kneser graph $K_{a:b}$, the vertices are $b$-element subsets of a fixed set $\{1, 2, ...., a\}$ and the edges exist between the vertices if and only if the subsets represented by them are disjoint. Therefore, by definition, if $b$ = 1, the graph becomes $K_{a}$, which is a complete graph with a vertices. The connection between graph coloring and graph homomorphism is that a graph is a:b-colorable if and only if there is a homomorphism $\phi : G \rightarrow K_{a:b}$.&#xD;
&#xD;
**Erdos-Ko-Rado Theorem** states that: if $a$ and $b$ are positive integers with $a \ge 2b$, then independence number $\alpha(K_{a:b}) = {a-1\choose b-1}$. It is true that for any graphs, $\chi^F(K_{a:b}) \ge \frac{|V(K_{a:b})|}{\alpha(K_{a:b})}$. In the special case where the graph is vertex-transitive, $\chi^F(K_{a:b}) = \frac{|V(K_{a:b})|}{\alpha(K_{a:b})}$. Since there are ${a\choose b}$ vertices in a Kneser graph, $\chi^F(K_{a:b}) = \frac{{a\choose b}}{{a-1\choose b-1}} = \frac{a}{b}$. &#xD;
&#xD;
##Demonstration&#xD;
Below is the code for the Manipulate function that compares integral and fractional graph colorings:&#xD;
&#xD;
    Manipulate[&#xD;
     Module[{graph, graph2, chrom, colorings, sol, palette, cg, vL, &#xD;
       fracColoring, is, matrix, yV, fracChrom, fracG, vlist, map, fracC, &#xD;
       vstyle, newvl, newmapping, cmap, cmaplist},&#xD;
      SeedRandom[s];&#xD;
      graph = RandomGraph[{n, m}, VertexSize -&amp;gt; Medium]; &#xD;
      graph2 = graph;&#xD;
      &#xD;
      (* Integral Coloring *)&#xD;
      vL = VertexList[graph];&#xD;
      chrom = ChromaticNumber[graph];&#xD;
      colorings = Tuples[Table[i, {i, 1, chrom}], VertexCount[graph]];&#xD;
      sol = SelectFirst[colorings, ValidColoring[graph, #] &amp;amp;];&#xD;
      palette = discreteColors[chrom];&#xD;
      Do[PropertyValue[{graph, v[[1]]}, VertexStyle] = v[[2]], {v, &#xD;
        Table[{i, palette[[sol[[i]]]]}, {i, 1, VertexCount[graph]}]}];&#xD;
      &#xD;
      (*Fractional Coloring *)&#xD;
      fracG = explodeGraph[graph2, 2];&#xD;
      vlist = VertexList[fracG];&#xD;
      newmapping = &#xD;
       Association[&#xD;
        Table[2*(vlist[[i]][[1]] - 1) + vlist[[i]][[2]] -&amp;gt; &#xD;
          vlist[[i]][[1]], {i, Length[vlist]}]];&#xD;
      newvl = &#xD;
       Table[2*(vlist[[i]][[1]] - 1) + vlist[[i]][[2]], {i, &#xD;
         Length[vlist]}];&#xD;
      fracG = &#xD;
       Graph @@ ({vlist, EdgeList[fracG]} /. Thread[vlist -&amp;gt; newvl]);&#xD;
      &#xD;
      fracC = brelaz[fracG];&#xD;
      vstyle = MapIndexed[First[#2] -&amp;gt; ColorData[61, #1] &amp;amp;, fracC];&#xD;
      map = mapping[2, fracG, vstyle, newmapping];&#xD;
      cmap = Table[map[[i]][[2]], {i, Length[map]}];&#xD;
      cmaplist = &#xD;
       Table[cmap[[2*(i - 1) + j]], {i, 1, VertexCount[fracG]/2}, {j, 1, &#xD;
         2}];&#xD;
      fracColoring = &#xD;
       FractionalColoring[VertexCount[graph2], 2, cmaplist];&#xD;
      &#xD;
      is = independentSets[graph];&#xD;
      matrix = A[is, graph];&#xD;
      yV = y[OneVector[Length[is]], matrix, OneVector[VertexCount[graph]]];&#xD;
      fracChrom = Total[yV];&#xD;
      Row[&#xD;
       {Column[{&#xD;
          Row[{Style[&amp;#034;Integral Graph&amp;#034;, Bold, RGBColor[0., 0.79, 0.76], &#xD;
             40, FontFamily -&amp;gt; &amp;#034;Baskerville&amp;#034;]}],&#xD;
          Row[{Style[&amp;#034;Integral Chromatic Number: &amp;#034;, 15], Style[chrom, 20] }],&#xD;
          Graph3D[graph, ImageSize -&amp;gt; {400, 400}, &#xD;
           EdgeStyle -&amp;gt; RGBColor[0.8, 0.8, 0.8]]&#xD;
          }, Center, 5], &#xD;
        Column[Table[&amp;#034;|&amp;#034;, {t, 1, 35}]],&#xD;
        Column[{&#xD;
          Row[{Style[&amp;#034;Fractional Graph&amp;#034;, Bold, RGBColor[0., 0.94, 0.33], &#xD;
             40, FontFamily -&amp;gt; &amp;#034;Baskerville&amp;#034;]}],&#xD;
          Row[{Style[&amp;#034;Fractional Chromatic Number: &amp;#034;, 15], If[fracChrom &amp;lt; chrom, Style[fracChrom, 20, Bold, Pink], &#xD;
             Style[fracChrom, 20]]}],&#xD;
          Graph[graph2, ImageSize -&amp;gt; {400, 400}, &#xD;
           VertexShape -&amp;gt; Thread[VertexList[graph2] -&amp;gt; fracColoring], &#xD;
           EdgeStyle -&amp;gt; RGBColor[0.8, 0.8, 0.8]]&#xD;
          }, &#xD;
         Center, 5]},&#xD;
       &amp;#034;          &amp;#034;&#xD;
       ]&#xD;
      ],&#xD;
     {{n, 3, &#xD;
       &amp;#034;Number of Vertices&amp;#034;}, 3, 7, 1, Appearance -&amp;gt; &amp;#034;Labeled&amp;#034;},&#xD;
     {{m, 3, &amp;#034;Number of Edges&amp;#034;}, 3, n*(n - 1)/2, 1, &#xD;
      Appearance -&amp;gt; &amp;#034;Labeled&amp;#034; },&#xD;
     {{s, 1, &amp;#034;Random Seeding&amp;#034;}, 1, 10000, 1, Appearance -&amp;gt; &amp;#034;Labeled&amp;#034;}, &#xD;
     SaveDefinitions -&amp;gt; True&#xD;
     ]&#xD;
![enter image description here][5]&#xD;
&#xD;
##Future Work&#xD;
First of all, the coloring process needs to be drastically optimized. Because the current algorithm is extremely slow, it cannot color a graph with more than 7 vertices. Initially, I hoped that I would be able to handle at least 100 vertices, but I realized that coloring a graph is not easy as it seems like. With further optimization, I hope to improve this project so that it can efficiently compute both integral and fractional chromatic number and optimally color both integral and fractional graphs almost instantly. Second of all, I wanted to explain the relationships between different topics of graph theory and graph colorings, but I was not able to do so because I spent too much time trying to figure out how to color a fractional graph. For instance, one of the most surprising characteristic of fractional chromatic number is that it is equal to the fractional clique number. Rigorously proving the previous statement requires deep insight into properties and characteristics of both fractional clique number and chromatic number, so doing so would make me digress and talk about tangential topics. Lastly, I want to handle more complicated fractional graphs, such as the ones that have more than just 2 colors assigned to them. In this project, each vertex is assigned 2 colors each. However, I want to expand on this project by having varying number of colors in each vertex. Moreover, the algorithm is not exact because I used the Brelaz heuristic, which is just an approximation of the coloring.&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-13at3.45.36PM.png&amp;amp;userId=1372296&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-13at2.31.56PM.png&amp;amp;userId=1372296&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=4931ScreenShot2018-07-06at6.52.43PMSMALLER.png&amp;amp;userId=1372296&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-06at6.52.43PMSMALLER.png&amp;amp;userId=1372296&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=7158ScreenShot2018-07-06at6.52.43PMSMALLER.png&amp;amp;userId=1372296</description>
    <dc:creator>Jongwan Kim</dc:creator>
    <dc:date>2018-07-13T19:24:33Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1379016">
    <title>[WSS18] Import/Export System for Twine Stories</title>
    <link>https://community.wolfram.com/groups/-/m/t/1379016</link>
    <description>![Twine Button Graph][1]&#xD;
&#xD;
# Wolfram-Twine Bridge&#xD;
&#xD;
The goal of the project was to build an Import/Export system between Twine Projects and the Wolfram Language.&#xD;
[Twine](http://twinery.org) is browser-based software used to make interactive stories and text-based games. One can think of a Twine story as a website, where each webpage is analogous to a passage in the story. Connections between passages can be as sparse or dense as you like. Essentially one has a network of passages.  A nice way to represent a network is with a graph, this is one of the forms I use to represent a Twine Story in Mathematica. (There is a link to my code at the end of this post)&#xD;
&#xD;
## Twine Structure&#xD;
&#xD;
The workspace for Twine projects is the Twine Editor, available [online](http://twinery.org/2/#!/welcome) and desktop. A published Twine file is in html format. This is the file we want to parse for import.&#xD;
&#xD;
Sample Twine file:&#xD;
&#xD;
![Twine HTML Structure][2]&#xD;
&#xD;
&#xD;
&#xD;
The HTML structure is simple:&#xD;
&#xD;
```html&#xD;
&amp;lt;tw-storydata&amp;gt;&#xD;
 &amp;lt;tw-passagedata&amp;gt;&#xD;
   &amp;#034;PASSAGE CONTENT ...&amp;#034;&#xD;
   &amp;lt;/tw-passagedata&amp;gt;&#xD;
 &amp;lt;tw-passagedata&amp;gt;&#xD;
  &amp;#034;PASSAGE CONTENT ...&amp;#034;&#xD;
    &amp;lt;/tw-passagedata&amp;gt;&#xD;
  ...&#xD;
&amp;lt;/tw-storydata&amp;gt;&#xD;
```&#xD;
&#xD;
Some published Twine Projects have other HTML information, though this is not necessary for Import or Export. All we need is whatever is within the `&amp;lt;tw-storydata&amp;gt;` tags.&#xD;
&#xD;
&#xD;
## Import Procedure&#xD;
&#xD;
Initially, there were issues with importing the Twine files I had on hand. I presume it&amp;#039;s because these files were not valid HTML (no doctype). The `XML` import did not work either, presumably for the same reason. Importing as `XMLObject` generated something that looked reasonable, but introduced an extraneous body tag in the middle of the structure. Riccardo Di Virgilio, an instructor at the summer school wrote a parser that takes in a string version of the file and outputs a properly nested XML structure.&#xD;
&#xD;
With the story data in XML form, I could start generating the Graph and Association representation. The first thing I did was look for the particular `Cases` of `XMLElement` patterns to extract the story title and passages. From there I used that data to construct a graph. Harlowe uses a pair of Double Square brackets to denote a link. To create the edges I defined two functions, ` generateEdges`, and `extractLinks`. `generateEdges` takes in the passage name and a list of links and creates a directed edge between the passage name and those links. The list of links is generated from `extractLinks`. `extractLinks` takes in a passage&amp;#039;s content and extracts all string content within Double Square Brackets and puts them in a list.&#xD;
&#xD;
It&amp;#039;s nice to have the graph, but there should be a quick way to see the content of each passage as well. I wrapped all the vertices of the generated graph with Tooltips so one can hover over them and see the passage content. To do this I made an association of the form `&amp;lt;|&amp;#034;Story Title&amp;#034; -&amp;gt; &amp;#034;Start Here&amp;#034;, &amp;#034;First Passage&amp;#034; -&amp;gt; &amp;#034;First Passage Content&amp;#034;, ..., &amp;#034;Last Passage&amp;#034; -&amp;gt; &amp;#034;Last Passage Content&amp;#034; |&amp;gt;`. Then I generate the output Association. The Import function outputs a list of the Tooltip Graph and the output Association.&#xD;
&#xD;
Example output:&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
## Export Procedure&#xD;
&#xD;
To export a Twine project I wrote `twineExport`. It takes an Association form of a story and exports it as an HTML fragment. One can then import it into the Twine Editor. Twine passages also have a position attribute which I&amp;#039;m trying to make use of to place them nicely in the Twine editor. The current thinking is to mimic the layout of vertices from the graph representation. (I use `twineSummary` function for this, I&amp;#039;ll share that in the next section). I can use the `GraphEmbedding` function on the graph. `GraphEmbedding` returns the coordinates of the vertices, then I just need to scale the points to orient nicely in Twine.&#xD;
&#xD;
The Left Image shows the exported file. In the Right image, I moved the passages around to show what one would get with using `GraphEmbedding`.&#xD;
&#xD;
![enter image description here][4] ![enter image description here][5]&#xD;
&#xD;
## Summary Procedure&#xD;
&#xD;
The Twine Editor has a playthrough interface so one can test their stories. I haven&amp;#039;t implemented something like this yet, but there is a simpler story explorer that I&amp;#039;ve made. The `twineSummary` function creates it. The function takes an association as its first argument and an optional string as its second argument. The default output without any options is a `GraphicsRow` where&#xD;
the first item is a dynamic passage viewer and the second item is a Button Graph. Each Button is a passage name; when clicked it will update the dynamic viewer with its respective content (An Image of this output is at the top of this post). &amp;#034;Graph&amp;#034; and &amp;#034;Export&amp;#034; are the possible options for `twineSummary`. &amp;#034;Graph&amp;#034; returns the Button Graph by itself. &amp;#034;Export&amp;#034; generates a Twine HTML file and saves it to a folder called `TwineStories` in the current notebook directory.&#xD;
&#xD;
## Macros&#xD;
&#xD;
The default markup language for Twine, called [Harlowe](https://twine2.neocities.org), has syntax for macros: commands for changing story elements and states. I have yet to support these features but have been ideating a way to work with them. Let&amp;#039;s look at the set macro as an example. To set the value of the variable `myNumber` to the value `10` we can write the following: `(set: $myNumber to 10)`. What I&amp;#039;ve been thinking is to use an association where the keys are `command` and `data`. For set it would look like this:&#xD;
&#xD;
`&amp;lt;|&amp;#034;command&amp;#034; -&amp;gt; &amp;#034;set&amp;#034;, &amp;#034;data&amp;#034; -&amp;gt; &amp;lt;|&amp;#034;Variable&amp;#034; -&amp;gt; Symbol[$myNumber], &amp;#034;Value&amp;#034; -&amp;gt; 10 |&amp;gt;|&amp;gt;`&#xD;
&#xD;
I defined a function called macroGrammar to handle this command and some others. In the `set` case I generate a string representation of setting, for example, &amp;#034;var = val&amp;#034;. Then convert that to an expression.&#xD;
&#xD;
```Mathematica&#xD;
&#xD;
macroGrammar[macroAssoc_Association] :=&#xD;
 Module[{command = macroAssoc[&amp;#034;command&amp;#034;], data = macroAssoc[&amp;#034;data&amp;#034;]},&#xD;
  Switch[command,&#xD;
   &amp;#034;set&amp;#034;,ToExpression[ToString@data[&amp;#034;Variable&amp;#034;] &amp;lt;&amp;gt; &amp;#034;=&amp;#034; &amp;lt;&amp;gt; ToString@data[&amp;#034;Value&amp;#034;]] ,&#xD;
   &amp;#034;if&amp;#034;, If[data[&amp;#034;ConditionExpression&amp;#034;], data[&amp;#034;T&amp;#034;], data[&amp;#034;E&amp;#034;]],&#xD;
   &amp;#034;print&amp;#034;, Print[data],&#xD;
   &amp;#034;either&amp;#034;, RandomChoice[data]&#xD;
   ]&#xD;
  ]&#xD;
&#xD;
&#xD;
```&#xD;
&#xD;
A list of Harlow macros can be found [here](https://twine2.neocities.org/#macro_set)&#xD;
&#xD;
&#xD;
## Future Directions&#xD;
&#xD;
I&amp;#039;d like to implement more macros. Among other types, there are conditional, printing, data and output macros. Some macros include Links to other passages, which I can&amp;#039;t support yet as they are effectively hidden from my parser. In addition to this, I need to come up with a good Passage Positioning scheme for Import to Twine. The other thing to do on the Wolfram Language side is better placement of the Vertex Labels. So for large graphs, the labels don&amp;#039;t overlap. A Twine workspace editor in Mathematica would be useful as well. As of now, one has to write the Association by hand. (of course one can always just use the Twine editor).&#xD;
&#xD;
The next step is to gradually implement these macros and continually increase the number of stories I am testing on. For each parsing or macro error in a story, I can implement a fix.&#xD;
&#xD;
My [TWINE CODE](https://github.com/dishmint/Summer2018Starter/blob/master/Project/Twine.m) is on Github!&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=example-buttongraph-3.png&amp;amp;userId=884330&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=communitypost-image-html.png&amp;amp;userId=884330&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=import-example-cpost.png&amp;amp;userId=884330&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=example-twine-import-3.png&amp;amp;userId=884330&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=example-twine-import-Ideal-3.png&amp;amp;userId=884330</description>
    <dc:creator>Faizon Zaman</dc:creator>
    <dc:date>2018-07-11T18:22:42Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1384972">
    <title>[WSC18] Shortest Path Between Two Points on a Rough Terrain</title>
    <link>https://community.wolfram.com/groups/-/m/t/1384972</link>
    <description>This project seeks to find the shortest distance between two coordinate locations on the surface of the Earth given a maximum possible slope, or threshold. I created a function called shortestDistance that takes four parameters: the first coordinate location (or city), the second coordinate location (or city), the slope threshold, and the image resolution. Using a module, I declared all of my local variables:&#xD;
&#xD;
        shortestDistance[c1_, c2_, quality_, threshold_] := &#xD;
        Module[{pos1, pos2, dist, bounds, br, center, geoRange, realPixelSize,&#xD;
            data, terrainImage, gradient, d, m, rel, xn, yn, edges, graph, v, &#xD;
            bin, del, pg, path, pix1, pix2, fullTerrain, mag, mesh, newPath, &#xD;
            dropOne, testPath, scaledLength, actualLength, $size},&#xD;
  &#xD;
After that, I stored the coordinate points in {x, y} format of the two user-entered locations into the variables &amp;#034;pos1&amp;#034; and &amp;#034;pos2&amp;#034;:&#xD;
&#xD;
        pos1 = GeoPosition[c1];&#xD;
        pos2 = GeoPosition[c2];&#xD;
&#xD;
The bounds of the image were adjusted to fit the entire area of interest. In this example, c1 represents Denver, CO and c2 represents Aspen, CO, and the adjusted terrain graph is shown below with the locations of the two cities and the midpoint between the cities.&#xD;
&#xD;
       bounds = CoordinateBounds[{pos1[[1]], pos2[[1]]}];&#xD;
        br = Max[#2 - #1 &amp;amp; @@@ bounds];&#xD;
        center = Mean[{pos1[[1]], pos2[[1]]}];&#xD;
        geoRange = Transpose[{center - br, center + br}]; &#xD;
![In this example, c1 represents Denver, CO and c2 represents Aspen, CO][1] &#xD;
&#xD;
&#xD;
and the elevation data was stored as a matrix in the variable &amp;#034;data.&amp;#034;&#xD;
&#xD;
        data = GeoElevationData[Transpose@geoRange];&#xD;
&#xD;
I created four possible pixel dimensions for the size of the newly scaled image and assigned the value to the variable &amp;#034;$size&amp;#034; (eg. choice 2-&amp;gt; {200,200} would correspond to a 200 by 200 pixel resolution). The different resolutions were added to the menu because higher resolutions mean slower runtime: the user has the option to choose between speed and the quality of the image. &#xD;
&#xD;
        $size = Replace[&#xD;
        quality, {1 -&amp;gt; {50, 50}, 2 -&amp;gt; {200, 200}, 3 -&amp;gt; {300, 300}, &#xD;
        4 -&amp;gt; {400, 400}}];&#xD;
&#xD;
Next, I created a function &amp;#034;pixelSize&amp;#034; in order to determine the real distance of the path, in miles, given the distance of the path in pixels, and the definition of the function is shown below. Here, the function takes in two arguments: the range of the pixel values for the x and y coordinates as a single list &amp;#034;geoRange&amp;#034; and a &amp;#034;resolution&amp;#034; argument representing the pixel dimensions specified by the user, which was stored in $size in the previous step. &#xD;
&#xD;
        pixelSize[geoRange_, {resolution_, _}] :=&#xD;
        Module[{x1, x2, y1, y2},&#xD;
        {{x1, x2}, {y1, y2}} = geoRange;&#xD;
        GeoDistance[&#xD;
        GeoPosition[{x1, y1}],&#xD;
        GeoPosition[{x2, y1}]&#xD;
        ]/resolution&#xD;
        ];&#xD;
&#xD;
In the function call below, realPixelSize represents the ratio of $\frac{actual}{scaled}$ pixel lengths, and the original terrain image is rescaled to an image of the user-entered pixel dimensions&#xD;
&#xD;
        realPixelSize = pixelSize[geoRange, $size];&#xD;
        terrainImage = ImageResize[Image[QuantityMagnitude[data]], $size];&#xD;
&#xD;
The image below represents the resized terrain image, with lighter areas representing higher elevations while darker areas representing lower elevations:&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
In one of the most important steps, the gradient filter is applied to the scaled terrain image:&#xD;
&#xD;
        gradient = GradientFilter[terrainImage, 1];&#xD;
&#xD;
Now for the gradient image...the image is lighter in areas with greater **slope** (unlike elevation of the terrain image) and darker in relatively flat terrain with little to no steepness.  &#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
In the next block of code, each pixel on the gradient image is connected to the four adjacent pixels, and the duplicates are deleted using the DeleteDuplicates function since every two adjacent pixels (eg. pixel A and pixel B) will be connected twice (A-&amp;gt;B and B-&amp;gt;A) before the duplicates are deleted.&#xD;
&#xD;
        d = #2 - #1 &amp;amp; @@@ geoRange;&#xD;
        m = #1 &amp;amp; @@@ geoRange;&#xD;
        rel = Round[Reverse[$size*(#[[1]] - m)/d] &amp;amp; /@ {pos1, pos2}];&#xD;
        {xn, yn} = ImageDimensions[gradient];&#xD;
        edges = DeleteDuplicatesBy[Flatten@Table[{&#xD;
              Pixel[i, j] \[UndirectedEdge] Pixel[i - 1, j],&#xD;
              Pixel[i, j] \[UndirectedEdge] Pixel[i + 1, j],&#xD;
              Pixel[i, j] \[UndirectedEdge] Pixel[i, j - 1],&#xD;
              Pixel[i, j] \[UndirectedEdge] Pixel[i, j + 1]&#xD;
              }, {i, 2, xn - 1}, {j, 2, yn - 1}], Sort];&#xD;
        graph = Graph[edges];&#xD;
        v = VertexList[graph];&#xD;
&#xD;
Here is a visualization of the connected pixels after duplicates are deleted.&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
The Binarize function is now applied to the gradient image, and all the pixel values greater than the user-inputted threshold will be replaced with a white pixel while all the pixel values less than the threshold will be replaced with a black pixel. The resulting binarized image is stored in the variable &amp;#034;bin.&amp;#034;&#xD;
&#xD;
        bin = Binarize[gradient, threshold];&#xD;
        &#xD;
![enter image description here][5]&#xD;
&#xD;
All the white pixels (pixels with gradient above threshold) will be deleted using a separate function called FastVertexDelete, for which the definition and function call are down below: &#xD;
&#xD;
----------&#xD;
&#xD;
**Side Note:**&#xD;
&#xD;
*Why wasn&amp;#039;t **VertexDelete**, a predefined function in Mathematica, used?* &#xD;
&#xD;
*VertexDelete took a long time to run, due to a possible bug in the function...to cut down runtime, a new function &amp;#034;FastVertexDelete&amp;#034; was created.*&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
**Definition of FastVertexDelete:**&#xD;
&#xD;
    FastVertexDelete[ graph_Graph, delete_List ] :=&#xD;
      With[ { dropQ = AssociationMap[ True &amp;amp;, delete ] },&#xD;
          Graph[ Complement[ VertexList @ graph, delete ],&#xD;
                 DeleteCases[ EdgeList @ graph, _[ _?dropQ, _ ] | _[ _, _?dropQ ] ]&#xD;
          ]&#xD;
      ];&#xD;
&#xD;
    FastVertexDelete[ graph_Graph, delete_ ] :=&#xD;
      FastVertexDelete[ graph, { delete } ];&#xD;
&#xD;
**Function Call:**&#xD;
&#xD;
&#xD;
        del = Pixel @@@ PixelValuePositions[bin, White];&#xD;
        {pix1, pix2} = Pixel @@@ rel;        &#xD;
        pg = FastVertexDelete[graph, Complement[Intersection[v, del], {pix1, pix2}]];&#xD;
&#xD;
The Mathematica function FindShortestPath is now implemented to find the minimum distance path between the two user-entered coordinates::&#xD;
&#xD;
        path = Replace[FindShortestPath[pg, pix1, pix2], Except[_List] -&amp;gt; {}];&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
Now for a more in-depth analysis of the path finding mechanism...&#xD;
## Visualization of FindShortestPath ##&#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
The connected &amp;#034;pixel plane&amp;#034; looks like this:&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
If a pixel is deleted using VertexDelete, &#xD;
&#xD;
    g = VertexDelete[graph, {Pixel[5, 5]}]&#xD;
&#xD;
the resulting pixel plane looks like this:&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
When FindShortestPath is applied to two randomly chosen pixels on the plane,&#xD;
&#xD;
    FindShortestPath[g, Pixel[5, 3], Pixel[5, 8]]&#xD;
&#xD;
the red dots show the shortest path. &#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
----------&#xD;
&#xD;
&#xD;
However, if there is no path, an error message is produced:&#xD;
&#xD;
        If[path === {},&#xD;
        bin = bin;&#xD;
        &amp;#034;Error: There is no path.&amp;#034;,&#xD;
&#xD;
Otherwise, a function &amp;#034;dropOne&amp;#034; is implemented in order to minimize the length of the path even further: dropOne drops points on the path (excluding starting and ending points) that will still give a path disjoint from the white pixels that have been deleted.&#xD;
&#xD;
&#xD;
        bin = ImageMultiply[bin, &#xD;
        Erosion[ReplacePixelValue[ConstantImage[White, $size],&#xD;
        List @@@ path -&amp;gt; Black], 1]];&#xD;
        fullTerrain = ImageAdjust@Image[QuantityMagnitude[data]];&#xD;
        mag = ImageDimensions[fullTerrain]/$size;&#xD;
        mesh = ImageMesh[bin, Method -&amp;gt; &amp;#034;Exact&amp;#034;, &#xD;
        DataRange -&amp;gt; Transpose[{{1, 1}, ImageDimensions[bin]}]];&#xD;
        newPath = List @@@ path[[2 ;; -2]];&#xD;
&#xD;
**Definition:**&#xD;
&#xD;
        dropOne = &#xD;
        Function[path, &#xD;
        Replace[&#xD;
        SelectFirst[Range[2, Length[path] - 1], &#xD;
        RegionDisjoint[mesh, Line[Delete[path, #]]] &amp;amp;],&#xD;
        {d_Integer :&amp;gt; Delete[path, d], _ :&amp;gt; path}&#xD;
        ]];&#xD;
&#xD;
The new, improved path, achieved using the dropOne function, is named &amp;#034;testPath&amp;#034;:&#xD;
&#xD;
        testPath = FixedPoint[dropOne, newPath];&#xD;
&#xD;
Notice how testPath improves the distance by &amp;#034;smoothening out&amp;#034; the path.&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
The scaled length of the path (aka the path length in pixels) is now determined by using the EuclideanDistance. The scaled distance is converted to actual distance in miles by using the &amp;#034;realPixelSize&amp;#034; value computed at the beginning using the pixelSize function:&#xD;
&#xD;
        scaledLength = &#xD;
        N@Total[EuclideanDistance @@@ &#xD;
        Partition[testPath, 2, 1]] (*with dropOne function*);&#xD;
        actualLength = scaledLength*realPixelSize (*in miles*);&#xD;
&#xD;
**In this example with Denver and Aspen, the length of the path before dropOne was implemented was 128 miles while the length of the path after dropOne was implemented was 117.2 miles.**&#xD;
&#xD;
A grid is created to output a list of lists, specifically, a list of images: the raw graph representing the original path, the smoothened graph representing the improved graph after the dropOne function is implemented, the gradient graph showing the shortest path, and the full terrain image with relative elevations.&#xD;
&#xD;
        Grid[{&#xD;
        {&amp;#034;Raw Graph: &amp;#034;, &#xD;
        ImageResize[HighlightImage[bin, Line[List @@@ path]], 500]},&#xD;
        {&amp;#034;Smoothened Graph: &amp;#034;, &#xD;
        ImageResize[HighlightImage[bin, Line[testPath]], 500]},&#xD;
        {&amp;#034;Gradient: &amp;#034;, &#xD;
        ImageResize[&#xD;
        HighlightImage[&#xD;
        ImageAdjust@&#xD;
        GradientFilter[terrainImage, &#xD;
        1], {Line[{##} - 0.5 &amp;amp; @@@ testPath]}], 500]},&#xD;
        {&amp;#034;Terrain with path marked in red: &amp;#034;, &#xD;
        HighlightImage[fullTerrain, {Line[mag*{##} &amp;amp; @@@ testPath]}]},&#xD;
        {&amp;#034;Distance: &amp;#034;, actualLength}}], Alignment -&amp;gt; Left&#xD;
        ]]&#xD;
&#xD;
Further Work&#xD;
-------&#xD;
&#xD;
A possible improvement that may be made is a quicker runtime: in fact, the image quality may be adjusted in my microsite in order to account for slow runtime. On the microsite, another problem is the need for the user to adjust the threshold in order to obtain the best possible graph: there should be a set numerical correlation between the actual gradient values and threshold since threshold is just a relative measurement of slope. &#xD;
&#xD;
     &#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-15at11.27.45PM.png&amp;amp;userId=1372113&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-15at11.32.54PM.png&amp;amp;userId=1372113&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-15at11.37.32PM.png&amp;amp;userId=1372113&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-15at11.40.08PM.png&amp;amp;userId=1372113&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-16at8.49.25AM.png&amp;amp;userId=1372113&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-16at8.57.29AM.png&amp;amp;userId=1372113&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-15at11.40.08PM.png&amp;amp;userId=1372113&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-16at12.23.21PM.png&amp;amp;userId=1372113&#xD;
  [9]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-16at12.28.15PM.png&amp;amp;userId=1372113&#xD;
  [10]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ScreenShot2018-07-16at8.59.46AM.png&amp;amp;userId=1372113</description>
    <dc:creator>Hee Jae Hong</dc:creator>
    <dc:date>2018-07-16T14:05:19Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1732283">
    <title>[WSC19] Visualizing Routing and Determining Optimal Paths</title>
    <link>https://community.wolfram.com/groups/-/m/t/1732283</link>
    <description>![A graph of the routes to various websites across the globe from near Boston.][1]&#xD;
&#xD;
##Background##&#xD;
&#xD;
Routers connect computer networks together and send packets to the correct location. In computer networks, packets make multiple hops to different locations in order to reach their destination. The router determines how to send the packets based on the destination IP address. An IP address is an address that is assigned to each device connected to a computer network and allows for identification and communication. Public IP addresses have a geolocation associated with them that we can look up, although they are not always entirely accurate. &#xD;
&#xD;
A routing algorithm is used in order to determine the path that will be taken in order to reach a destination effectively based on a variety of factors such as distance and network traffic. Our project uses the ping time?the round-trip time taken for a packet to go to and from your destination? in order to determine the optimal route. &#xD;
&#xD;
##Project Description##&#xD;
&#xD;
This project finds the route traveled by a packet as it makes its way to a given domain. The traceroute command was used in order to gather this data on various websites from across the globe. We could extract information about how long it took to receive a response from the servers as well as the IPv4 addresses of where our packets went. This data was then cleaned and formatted for use in visualizing a map of the results. Furthermore, a graph was created based off of these results with the nodes set to the unique locations visited by the packets and the edges weighted by the average ping time. Based off of these ping times,  I found optimal routes to destinations.&#xD;
&#xD;
##Functions##&#xD;
&#xD;
This function uses traceroute on a given domain and formats in into a list of associations. &#xD;
&#xD;
    getRoute[domain_] := &#xD;
    (&#xD;
          rawoutput = RunProcess[{&amp;#034;tracert&amp;#034;, domain}];formatted = StringSplit[(StringSplit[rawoutput[&amp;#034;StandardOutput&amp;#034;],&amp;#034;\r\n&amp;#034;][[4;;]] // StringTrim), &#xD;
          &amp;#034;       &amp;#034; |&amp;#034;     &amp;#034;|&amp;#034;    &amp;#034; |&amp;#034;   &amp;#034; | &amp;#034;  &amp;#034;][[;;-3]];&#xD;
          associations = Table[AssociationThread[{&amp;#034;index&amp;#034;, &amp;#034;time1&amp;#034;, &amp;#034;time2&amp;#034;, &amp;#034;time3&amp;#034;, &amp;#034;ip&amp;#034;} -&amp;gt; Table[formatted[[m, n]], {n, 1, 5}]], {m, 1, formatted//Length}];&#xD;
          regexIPPattern=&amp;#034;((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))&amp;#034;;&#xD;
          pingFormat = ___~~DigitCharacter~~___~~&amp;#034; ms&amp;#034;;&#xD;
          Function[u,&amp;lt;|&amp;#034;Index&amp;#034;-&amp;gt; u[&amp;#034;index&amp;#034;],&#xD;
              &amp;#034;Time1&amp;#034;-&amp;gt;If[StringContainsQ[u[&amp;#034;time1&amp;#034;], pingFormat],Quantity[First@StringCases[u[&amp;#034;time1&amp;#034;],DigitCharacter..],&#xD;
              &amp;#034;Milliseconds&amp;#034;],Missing[&amp;#034;NotAvailable&amp;#034;]],&#xD;
              &amp;#034;Time2&amp;#034;-&amp;gt;If[StringContainsQ[u[&amp;#034;time2&amp;#034;], pingFormat],Quantity[First@StringCases[u[&amp;#034;time2&amp;#034;],DigitCharacter..],&#xD;
              &amp;#034;Milliseconds&amp;#034;],Missing[&amp;#034;NotAvailable&amp;#034;]],&#xD;
              &amp;#034;Time3&amp;#034;-&amp;gt;If[StringContainsQ[u[&amp;#034;time3&amp;#034;], pingFormat],Quantity[First@StringCases[ u[&amp;#034;time3&amp;#034;],DigitCharacter..],&#xD;
              &amp;#034;Milliseconds],Missing[&amp;#034;NotAvailable&amp;#034;]],&#xD;
              &amp;#034;IP&amp;#034; -&amp;gt; With[{match=StringCases[u[&amp;#034;ip&amp;#034;],RegularExpression[regexIPPattern]-&amp;gt;&amp;#034;$1&amp;#034;]},If[match==={},Missing[&amp;#034;NotAvailable&amp;#034;],&#xD;
              Entity[&amp;#034;IPAddress&amp;#034;,First[match]]]&#xD;
          ]&#xD;
    |&amp;gt;]/@associations)&#xD;
&#xD;
This function cleans the data of missing IP addresses and timed out responses.&#xD;
&#xD;
    cleanResults[resultVar_]:=Cases[#,&amp;lt;|&amp;#034;Index&amp;#034;-&amp;gt; _,&amp;#034;Time1&amp;#034;-&amp;gt; _Quantity,&amp;#034;Time2&amp;#034;-&amp;gt; _Quantity,&amp;#034;Time3&amp;#034;-&amp;gt; _Quantity,&amp;#034;IP&amp;#034;-&amp;gt; _Entity|&amp;gt;]&amp;amp;/@resultVar&#xD;
&#xD;
This function extracts the location, in coordinates, and the average ping time, in milliseconds, from each hop in every route. If an IP address does not have a location associated with it,  I don&amp;#039;t use it in our data.&#xD;
&#xD;
    GetLocationAndMeanTime[results_] := &#xD;
        (Function[v, {First[v], v[[2]], Last[v]}] /@ &#xD;
        DeleteCases[Function[u, {Mean[ToExpression /@ QuantityMagnitude[Take[u, 3]]], &#xD;
            u[[4]][EntityProperty[&amp;#034;IPAddress&amp;#034;, &amp;#034;HostCoordinates&amp;#034;]], u[[4]]}] /@ &#xD;
                Lookup[#, {&amp;#034;Time1&amp;#034;, &amp;#034;Time2&amp;#034;, &amp;#034;Time3&amp;#034;, &amp;#034;IP&amp;#034;}], {_, _Missing, _}]) &amp;amp; /@ results&#xD;
&#xD;
The functions below plot assist in plotting the routes on a map. The colors of the routes depend on the relative ping times and  I use the color schemes found in the Wolfram Language.&#xD;
&#xD;
    GenerateElementGeoPaths[locationAndMeansElement_, colorFunction_] := &#xD;
      Flatten[Function[v, Function[u,&#xD;
            {{GeoMarker[u[[2, 2]], &#xD;
              Graphics[Disk[]], &#xD;
              &amp;#034;Scale&amp;#034; -&amp;gt; Scaled[0.015], &#xD;
              &amp;#034;Color&amp;#034; -&amp;gt; colorFunction[u[[2, 1]]]]},&#xD;
            {Thickness[0.0008], colorFunction[u[[2, 1]]], &#xD;
              GeoPath[{u[[1, 2]], u[[2, 2]]}, &amp;#034;Geodesic&amp;#034;]}}] /@ Partition[v, 2, 1]] /@ locationAndMeansElement, 1]&#xD;
&#xD;
    GenerateGeoPaths[locationAndMeans_, colorScheme_] := Block[{&#xD;
      minmax, colorFunc&#xD;
      },&#xD;
      minmax = MinMax[Flatten[locationAndMeans, 2][[All, 1]]];&#xD;
      colorFunc = ColorData[{colorScheme, minmax}];&#xD;
      &#xD;
      Flatten[GenerateElementGeoPaths[#, colorFunc] &amp;amp; /@ locationAndMeans, 1]&#xD;
    ]&#xD;
&#xD;
generateGraphs creates a graph where each unique location reached by traceroute is denoted by a node, and the edges are weighted by ping times. Coordinates are represented by the nearest city or area of population. &#xD;
&#xD;
    generateGraphs[locationAndMeans_] := Block[{&#xD;
        locations, pingTimes, uniqueLocations, locationstoNum&#xD;
      },&#xD;
      locations = (Flatten[locationAndMeans, 1])[[All, All, 2]];&#xD;
      pingTimes = Flatten@(Rest /@ (Flatten[locationAndMeans, 1])[[All, All, 1]]);&#xD;
      uniqueLocations = DeleteDuplicates@(Flatten[(Flatten[locationAndMeans, 1])[[All, All, 2]], 1]);&#xD;
      locationstoNum = Table[&#xD;
        First@Replace[locations[[m , n]], locations[[m , n]] -&amp;gt; First@Position[uniqueLocations, locations[[m , n]]]], &#xD;
        {m, Length@locations}, {n, Length@locations[[m]]}&#xD;
        ];&#xD;
      nearestCities = Table[GeoNearest[Entity[&amp;#034;City&amp;#034;], GeoPosition[uniqueLocations[[i]]]], {i, uniqueLocations // Length}];&#xD;
      graphedRoutes = Graph[&#xD;
        Flatten[Table[Table[locationstoNum[[a, b]] -&amp;gt; locationstoNum[[a, b + 1]], {b, (locationstoNum[[a]] // Length) - 1}], {a, locationstoNum // Length}]],&#xD;
        EdgeWeight -&amp;gt; pingTimes,&#xD;
        VertexLabels -&amp;gt; Table[i -&amp;gt; Placed[nearestCities[[i]], Top], {i, uniqueLocations // Length}],&#xD;
        VertexLabelStyle -&amp;gt; Directive[White, 9],&#xD;
        VertexSize -&amp;gt; 0.2,&#xD;
        EdgeStyle -&amp;gt; {Directive[Green, Arrowheads[.008]], (1 -&amp;gt; 1) -&amp;gt; Opacity[0.125]},&#xD;
        Background -&amp;gt; Black]&#xD;
      ];&#xD;
&#xD;
shortestPath returns the optimal locations a packet will go through in order to receive its destination. The input argument is a website link, which can be converted into an IP Address. After converting the IP address into coordinates, we then find the nearest city to it in the list of cities, nearestCities, that was developed in the generateGraphs function.&#xD;
&#xD;
    shortestPath[website_] := Block[{&#xD;
        destination, nearestCity, f&#xD;
      },&#xD;
      destination = GeoPosition[Entity[&amp;#034;IPAddress&amp;#034;, (First@First@HostLookup[website])][&amp;#034;HostCoordinates&amp;#034;]];&#xD;
      nearestCity = First@GeoNearest[Flatten@nearestCities, destination];&#xD;
      f[i_] := (nearestCities)[[i]];&#xD;
      Flatten@(f /@ FindShortestPath[graphedRoutes, 1, First@First@Position[Flatten@nearestCities, nearestCity]])&#xD;
      ]&#xD;
&#xD;
Collecting Data&#xD;
-------&#xD;
&#xD;
The first step was gathering data.  I found popular websites from around the world and performed traceroute on them in order to see how our packets will end up there and saved the results to a file.&#xD;
&#xD;
    resultsA = &#xD;
      getRoute /@ {&amp;#034;labanquepostale.fr&amp;#034;, &amp;#034;lemonde.fr&amp;#034;, &amp;#034;lefigaro.fr&amp;#034;, &#xD;
        &amp;#034;purepeople.com&amp;#034;, &amp;#034;marca.com&amp;#034;, &amp;#034;elmundo.es&amp;#034;, &amp;#034;elpais.com&amp;#034;, &#xD;
        &amp;#034;milanucios.com&amp;#034;, &amp;#034;pasion.com&amp;#034;, &amp;#034;caixabank.es&amp;#034;, &#xD;
        &amp;#034;mercadolibre.com.mx&amp;#034;, &amp;#034;caliente.mx&amp;#034;, &amp;#034;animeflv.net&amp;#034;, &amp;#034;unam.mx&amp;#034;, &#xD;
        &amp;#034;www.gob.mx&amp;#034;, &amp;#034;commbank.com.au&amp;#034;, &amp;#034;bom.gov.au&amp;#034;, &amp;#034;seek.com.au&amp;#034;, &#xD;
        &amp;#034;woolworths.com.au&amp;#034;, &amp;#034;carsales.com.au&amp;#034;, &amp;#034;google.ca&amp;#034;, &amp;#034;amazon.ca&amp;#034;, &#xD;
        &amp;#034;kijiji.ca&amp;#034;, &amp;#034;cbc.ca&amp;#034;, &amp;#034;desjardins.ca&amp;#034;, &amp;#034;canada.ca&amp;#034;, &amp;#034;youm7.com&amp;#034;, &#xD;
        &amp;#034;souq.com&amp;#034;, &amp;#034;masrawy.com&amp;#034;, &amp;#034;yallakora.com&amp;#034;, &amp;#034;filgoal.com&amp;#034;, &#xD;
        &amp;#034;hkjc.com&amp;#034;, &amp;#034;lihkg.com&amp;#034;, &amp;#034;on.cc&amp;#034;, &amp;#034;discuss.com.hk&amp;#034;, &#xD;
        &amp;#034;ulifestyle.com.hk&amp;#034;, &amp;#034;baidu.com&amp;#034;, &amp;#034;alibaba.com&amp;#034;, &amp;#034;taobao.com&amp;#034;, &#xD;
        &amp;#034;qq.com&amp;#034;, &amp;#034;bilibili.com&amp;#034; , &amp;#034;google.com&amp;#034;, &amp;#034;youtube.com&amp;#034;, &#xD;
        &amp;#034;facebook.com&amp;#034;, &amp;#034;amazon.com&amp;#034;, &amp;#034;yahoo.com&amp;#034;, &amp;#034;twitter.com&amp;#034;, &#xD;
        &amp;#034;ebay.com&amp;#034;, &amp;#034;instagram.com&amp;#034;, &amp;#034;wikipedia.org&amp;#034;, &amp;#034;flipkart.com&amp;#034;, &#xD;
        &amp;#034;cricbuzz.com&amp;#034;, &amp;#034;xbombo.com&amp;#034;, &amp;#034;indiatimes.com&amp;#034;, &amp;#034;news18.com&amp;#034;, &#xD;
        &amp;#034;flipkart.com&amp;#034;, &amp;#034;cricbuzz.com&amp;#034;, &amp;#034;xbombo.com&amp;#034;, &amp;#034;indiatimes.com&amp;#034;, &#xD;
        &amp;#034;news18.com&amp;#034;, &amp;#034;yad2.co.il&amp;#034;, &amp;#034;zap.co.il&amp;#034;, &amp;#034;bankhapoalim.co.il&amp;#034;, &#xD;
        &amp;#034;newsru.co.il&amp;#034;, &amp;#034;sport5.co.il&amp;#034;, &amp;#034;afip.gob.ar&amp;#034;, &amp;#034;lanacion.com.ar&amp;#034;, &#xD;
        &amp;#034;bbva.com.ar&amp;#034;, &amp;#034;bancogalicia.com.ar&amp;#034;, &amp;#034;hollywoodbets.net&amp;#034;, &#xD;
        &amp;#034;tubidy.mobi&amp;#034;, &amp;#034;mtn.co.za&amp;#034;, &amp;#034;iol.co.za&amp;#034;, &amp;#034;uol.com.br&amp;#034;, &#xD;
        &amp;#034;bet365.com&amp;#034;, &amp;#034;americanas.com.br&amp;#034;, &amp;#034;kooora.com&amp;#034;, &amp;#034;www.men.gov.ma&amp;#034;};&#xD;
&#xD;
    resultsB = &#xD;
      getRoute /@ { &amp;#034;hespress.com&amp;#034;, &amp;#034;friend.com.kp&amp;#034;, &amp;#034;ma.gov.kp&amp;#034;, &#xD;
        &amp;#034;airkoryo.com.kp&amp;#034;, &amp;#034;nta.gov.kp&amp;#034;, &amp;#034;ryongnamsan.edu.kp&amp;#034;, &#xD;
        &amp;#034;cooks.org.kp&amp;#034;, &amp;#034;sdprk.org.kp&amp;#034;, &amp;#034;gnu.rep.kp&amp;#034;, &amp;#034;korfilm.com.kp&amp;#034;, &#xD;
        &amp;#034;yandex.ru&amp;#034;, &amp;#034;ok.ru&amp;#034;, &amp;#034;avito.ru&amp;#034;, &amp;#034;gismeto.ru&amp;#034;, &amp;#034;wildberries.ru&amp;#034;, &#xD;
        &amp;#034;drom.ru&amp;#034;, &amp;#034;haraj.com.sa&amp;#034;, &amp;#034;starzplay.com&amp;#034;, &amp;#034;cimaclub.com&amp;#034;, &#xD;
        &amp;#034;moi.gov.sa&amp;#034;, &amp;#034;souq.com&amp;#034;, &amp;#034;vnexpress.net&amp;#034;, &amp;#034;zing.vn&amp;#034;, &#xD;
        &amp;#034;24h.com.vn&amp;#034;, &amp;#034;kenh14.vn&amp;#034;, &amp;#034;shopee.vn&amp;#034;, &amp;#034;baomoi.com&amp;#034;, &#xD;
        &amp;#034;ehawaii.gov&amp;#034;, &amp;#034;webmasterserviceshawaii.com&amp;#034;, &amp;#034;manoa.hawaii.edu&amp;#034;, &#xD;
        &amp;#034;alaska.gov&amp;#034;, &amp;#034;adn.com&amp;#034;, &amp;#034;uaf.edu&amp;#034;, &amp;#034;alaskawildlife.org&amp;#034;,  &#xD;
        &amp;#034;detik.com&amp;#034;, &amp;#034;shopee.co.id&amp;#034;, &amp;#034;bukalapak.com&amp;#034;, &amp;#034;kompas.com&amp;#034;, &#xD;
        &amp;#034;sermitsiaq.ag&amp;#034;, &amp;#034;banken.gl&amp;#034;, &amp;#034;tusass.gl&amp;#034;,  &amp;#034;eltiempo.com&amp;#034;, &#xD;
        &amp;#034;computrabajo.com.co&amp;#034;, &amp;#034;caracoltv.com&amp;#034;, &amp;#034;canalrcn.com&amp;#034;, &#xD;
        &amp;#034;elcomercio.pe&amp;#034;, &amp;#034;www.sunat.gob.pe&amp;#034;, &#xD;
        &amp;#034;mercadolibre.com.pe&amp;#034;, &amp;#034;larepublica.pe&amp;#034;, &amp;#034;www.viabcp.com&amp;#034;,  &#xD;
        &amp;#034;ouedkniss.com&amp;#034;};&#xD;
&#xD;
    resultsC = &#xD;
      getRoute /@ {&amp;#034;ency-education.com&amp;#034;, &amp;#034;startimes.com&amp;#034;, &amp;#034;elkhabar.com&amp;#034;, &#xD;
        &amp;#034;trademe.co.nz&amp;#034;, &amp;#034;stuff.co.nz&amp;#034;, &amp;#034;nzherald.co.nz&amp;#034;, &amp;#034;ird.govt.nz&amp;#034;, &#xD;
        &amp;#034;bet9ja.com&amp;#034;, &amp;#034;jumia.com.ng&amp;#034;, &amp;#034;nairaland.com&amp;#034;, &amp;#034;betradar.com&amp;#034;, &#xD;
        &amp;#034;ghanaweb.com&amp;#034;, &amp;#034;lightdl.xyz&amp;#034;, &amp;#034;ug.edu.gh&amp;#034;, &amp;#034;nss.gov.gh&amp;#034;, &#xD;
        &amp;#034;yandex.uz&amp;#034;, &amp;#034;mover.uz&amp;#034;, &amp;#034;olx.uz&amp;#034;, &amp;#034;gov.uz&amp;#034;, &amp;#034;xcite.com&amp;#034;, &#xD;
        &amp;#034;talabat.com&amp;#034;, &amp;#034;www.knetpay.com.kw&amp;#034;,  &amp;#034;moi.gov.kw&amp;#034;, &amp;#034;daraz.pk&amp;#034;, &#xD;
        &amp;#034;watchonlinemovies.com.pk&amp;#034;, &amp;#034;7starhd.work&amp;#034;, &amp;#034;punjab.gov.pk&amp;#034;, &#xD;
        &amp;#034;ukr.net&amp;#034;, &amp;#034;sinoptik.ua&amp;#034;, &amp;#034;rozetka.com.ua&amp;#034;, &amp;#034;prom.ua&amp;#034;, &amp;#034;mit.edu&amp;#034;, &#xD;
        &amp;#034;harvard.edu&amp;#034;, &amp;#034;princeton.edu&amp;#034;, &amp;#034;stonybrook.edu&amp;#034;, &amp;#034;columbia.edu&amp;#034;, &#xD;
        &amp;#034;stanford.edu&amp;#034;, &amp;#034;umich.edu&amp;#034;, &amp;#034;cmu.edu&amp;#034;, &amp;#034;ut.edu&amp;#034;, &amp;#034;utexas.edu&amp;#034;, &#xD;
        &amp;#034;risd.edu&amp;#034;, &amp;#034;ua.edu&amp;#034;, &amp;#034;wisc.edu&amp;#034;, &amp;#034;washington.edu&amp;#034;, &#xD;
        &amp;#034;georgetown.edu&amp;#034;, &amp;#034;uchicago.edu&amp;#034;, &amp;#034;cornell.edu&amp;#034;, &amp;#034;berkeley.edu&amp;#034;, &#xD;
        &amp;#034;vanderbilt.edu&amp;#034;, &amp;#034;phoenix.edu&amp;#034;, &amp;#034;illinois.edu&amp;#034;, &amp;#034;mines.edu&amp;#034;, &#xD;
        &amp;#034;umass.edu&amp;#034;, &amp;#034;reddit.com&amp;#034;, &amp;#034;wolfram.com&amp;#034;, &amp;#034;baidu.com&amp;#034;, &#xD;
        &amp;#034;bbc.co.uk&amp;#034;, &amp;#034;ikea.com&amp;#034;, &amp;#034;mail.ru&amp;#034;, &amp;#034;yahoo.co.jp&amp;#034;, &#xD;
        &amp;#034;minecraft.net&amp;#034;, &amp;#034;github.io&amp;#034;};&#xD;
&#xD;
    resultsD = getRoute /@ (RandomSample[(&amp;#034;151.101.&amp;#034; &amp;lt;&amp;gt; ToString[#] &amp;lt;&amp;gt; &amp;#034;.13&amp;#034; &amp;amp;) /@ Range[255], 20]);&#xD;
&#xD;
I saved these results to a file because the getRoute function can take time to run.&#xD;
&#xD;
    Get[(*whatever file path you put your results in*)];&#xD;
    totalResults = cleanResults /@ (ToExpression /@ Drop[Names[&amp;#034;results*&amp;#034;], 1]);&#xD;
    locationAndMeans = GetLocationAndMeanTime /@ totalResults;&#xD;
&#xD;
Visualizing our Data&#xD;
-------&#xD;
I generated a map with the locations plotted and connected to each other.&#xD;
&#xD;
    GeoGraphics[{{GeoStyling[&amp;#034;OutlineMap&amp;#034;,  &#xD;
        Directive[Black, &#xD;
        EdgeForm[Directive[{Thin, Opacity[0.75], Green}]]]], &#xD;
      Polygon[{EntityClass[&amp;#034;Country&amp;#034;, &amp;#034;Countries&amp;#034;], &#xD;
        Entity[&amp;#034;AdministrativeDivision&amp;#034;, {&amp;#034;Alaska&amp;#034;, &amp;#034;UnitedStates&amp;#034;}], &#xD;
        Entity[&amp;#034;GeographicRegion&amp;#034;, &amp;#034;Antarctica&amp;#034;], &#xD;
        Entity[&amp;#034;AdministrativeDivision&amp;#034;, {&amp;#034;Hawaii&amp;#034;, &#xD;
          &amp;#034;UnitedStates&amp;#034;}]}]}, {GenerateGeoPaths[locationAndMeans, &#xD;
        &amp;#034;NeonColors&amp;#034;]}}, GeoCenter -&amp;gt; Here, GeoZoomLevel -&amp;gt; 3, &#xD;
    GeoBackground -&amp;gt; LinearGradientImage[{Black, Blue, Black}]]&#xD;
&#xD;
![A graph of the routes to various websites across the globe from near Boston.][1]&#xD;
&#xD;
The greener colors represent faster ping times, while the red ping times are slower.&#xD;
&#xD;
I also generated a directed graph where locations of routers are represented by nodes. Graphs allow us to run shortest path algorithms and also allow for an interesting alternative visualization of the networks.&#xD;
&#xD;
    generateGraphs[locationAndMeans]&#xD;
&#xD;
![Graph of connections][2]&#xD;
&#xD;
![examples][3]&#xD;
Here are some examples of the shortest route required to reach a domain from my current location.&#xD;
&#xD;
##Limitations##&#xD;
There are many limitations with our results that prevent them from being fully accurate. &#xD;
&#xD;
For example, the coordinates associated with an IP Address does not always give us an accurate approximation of the host location. Also, on some hops, the nodes did not provide us with an IP Address, and consequently, they could not be used in our dataset. Additionally, in order to find the most efficient route, our algorithm relies on the current data I have already gathered, which raises the need for potentially crowdsourcing more data from the public.&#xD;
&#xD;
##Future Work##&#xD;
Potential future results include the implementation of this project in different geolocations in order to gather information and see how packets travel from different parts of the world. This could be accomplished through crowdsourcing data from people of different parts of the world.  I could also compare the optimal theoretical routes to the ones that exist in real life and examine the feasibility of implementing theoretical routes in order to design more efficient network systems. &#xD;
&#xD;
##Acknowledgements##&#xD;
I would like to thank Christian Pasquel, my mentor, for guiding and assisting me in the development of this project.&#xD;
&#xD;
https://github.com/aaieiu/WSS-Template&#xD;
&#xD;
[1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=nicemap.svg&amp;amp;userId=1724978&#xD;
&#xD;
[2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=coolgraph.svg&amp;amp;userId=1724978&#xD;
&#xD;
[3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=hi.png&amp;amp;userId=1724978</description>
    <dc:creator>Alice Liu</dc:creator>
    <dc:date>2019-07-11T23:25:57Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1137401">
    <title>[WSS17] Analyzing Mathematics Genealogy Project Database</title>
    <link>https://community.wolfram.com/groups/-/m/t/1137401</link>
    <description>Background&#xD;
----------&#xD;
The mathematics genealogy project is a website that collect data of mathematician and who is his/her adviser and student. Here one can trace their academic line all the way back to Newton&amp;#039;s era. With an impressive number of entries (213588 people by July 5th 2017), I&amp;#039;m interested to take a closer &#xD;
 look of their data to get an insight to mathematics community.&#xD;
&#xD;
The website can be accessed here: https://www.genealogy.math.ndsu.nodak.edu/index.php&#xD;
&#xD;
Data Scraping&#xD;
-------------&#xD;
First step of the project is to get accessed to the data and turn it into Wolfram Language format. My approach is by downloading the html of each page and parse it to get information that we wanted. I chose not to do XML after noticing that there are some variations in the structure of each page.&#xD;
&#xD;
Each mathematician&amp;#039;s page has a unique ID number that differentiate it from others, thus we can access all information just by changing the ID number:&#xD;
&#xD;
![enter image description here][1]&#xD;
&#xD;
 The function that I use to download each page is URLSubmit, which access the page in parallel instead of doing it sequentially. This means the functions make several request to the server and downloading the html code at once rather than accessing it one by one. It comes at the price of messing up with the order of the request (you can get ID 1, then jumping to ID 100 instead of doing it from 1-100 sequentially), but it&amp;#039;s okay since we can order it later.&#xD;
&#xD;
    receivedPages = {};&#xD;
    &#xD;
    receiveHTML[html_, id_] := Module[{},&#xD;
      AppendTo[receivedPages, {html[[1]], id}]&#xD;
      ]&#xD;
    &#xD;
    failHTML[html_, id_] := Module[{},&#xD;
      {&amp;#034;&amp;lt;p&amp;gt;You have specified an ID that does not exist in the database. \&#xD;
    Please back up and try again.&amp;lt;/p&amp;gt;&amp;#034;, id}&#xD;
      ]&#xD;
    &#xD;
        startDownload[id_] := Module[{},&#xD;
          URLSubmit[&#xD;
           &amp;#034;https://www.genealogy.math.ndsu.nodak.edu/id.php?id=&amp;#034; &amp;lt;&amp;gt; &#xD;
            ToString[id], &#xD;
           HandlerFunctions -&amp;gt; &amp;lt;|&#xD;
             &amp;#034;BodyReceived&amp;#034; -&amp;gt; (receiveHTML[#[&amp;#034;Body&amp;#034;], id] &amp;amp;), &#xD;
             &amp;#034;ConnectionFailed&amp;#034; -&amp;gt; failHTML|&amp;gt;, &#xD;
           HandlerFunctionsKeys -&amp;gt; {&amp;#034;Body&amp;#034;}]&#xD;
          ]&#xD;
&#xD;
Some caution is needed with the speed since if we make too much request at once it will crash and return an error instead. My approach is to put random pause every 5 pages (I tried to do every 10 pages before, but half of the time it gives me database error instead). Another thing to note is not to download all 200,000 pages at once. Good chances it will crash your kernel. Usually I like to to download about 10-20 thousand at once. Since it can take a while (around 20 minutes for 10,000 pages with random pause every 5), I like to use function `Monitor` to see my progress. &#xD;
&#xD;
    receivedPages = {};&#xD;
    Monitor[&#xD;
      Table[&#xD;
       startDownload[i];&#xD;
       If[Divisible[i, 5],&#xD;
        Pause[RandomReal[{0, 1}]]], {i, 1, 217304}],&#xD;
      {i, ProgressIndicator[i, {1, 217304}]}&#xD;
      ] // AbsoluteTiming&#xD;
&#xD;
All the downloaded html will go to the list `receivedPages`. Now we need to parse the html to get our data. The full description of the parser is long and tedious, so I won&amp;#039;t put it here. You can see the full code in my notebook at the end of  this post. Essentially, I&amp;#039;m mapping the function `stringParser` to  `receivedPages` to get the data base. This will be fairly big, so we want to write it to separate file in case our kernel crashes.&#xD;
&#xD;
    file = FileNameJoin[{NotebookDirectory[], &amp;#034;Final Database.m&amp;#034;}]&#xD;
    &#xD;
    stream = OpenAppend[file]&#xD;
    &#xD;
    listAssoc = Map[stringParser, receivedPages]&#xD;
    &#xD;
    writer[data_] :=&#xD;
     Module[&#xD;
      {i = Length[data], k = 1},&#xD;
      While[k &amp;lt;= i,&#xD;
       WriteString[stream, InputForm[data[[k]]]];&#xD;
       WriteString[stream, &amp;#034;,\n&amp;#034;];&#xD;
       k++&#xD;
       ]&#xD;
      ]&#xD;
    &#xD;
    writer[listAssoc]&#xD;
&#xD;
This will write the data that we have downloaded into Final Database.m (which will be created automatically). Now simply repeat the download process until we get all pages. After that, we can simply Import it to our kernel and put it as a dataset. Some important notes are: &#xD;
&#xD;
 1. The data is not properly ordered by ID. We want this to be&#xD;
    ordered as it will make calling a certain ID much faster by taking&#xD;
    the order it appears in dataset.&#xD;
 2. Some ID are not assigned to anyone. For example, by July 5th&#xD;
    2017, ID 206 is not assigned to anyone. By default the function I&#xD;
    describe will give &amp;#034;No Mathematician has been assigned to this ID&#xD;
    yet&amp;#034; in the &amp;#034;Name&amp;#034; column. Don&amp;#039;t delete it  for similar reason as&#xD;
    note 1.&#xD;
&#xD;
Analyzing Data&#xD;
--------------&#xD;
Now we get the data, it will have this structure:&#xD;
![enter image description here][2]&#xD;
&#xD;
We can start playing around. The first thing that I do is to take a histogram of those that get their title between 1950-1990.&#xD;
&#xD;
    listYear = &#xD;
     finalData[All, &amp;#034;Personal Information&amp;#034;, 1, &amp;#034;Year&amp;#034;] // Normal // &#xD;
      ToExpression&#xD;
    &#xD;
    Histogram[Select[listYear, 1950 &amp;lt; # &amp;lt; 1990 &amp;amp;]]&#xD;
&#xD;
I get the following result&#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
This is quite interesting as it seems that there are certain point in history where there is a sudden increase of mathematician. Here it happens in 1962-1970, where the gradient took a drastic changes. To figure out what happens, we need to go back 5 years before, since on average it took 5 years to get a PhD. It turns out there is an important event that happens in 1957: Sputnik! During 1950s, the US government is preparing to launch an education initiative, but after Sputnik&amp;#039;s launch in 1957 the program takes top priority realizing US is falling behind of Soviet in technology. So 1958 the US congress increased funding towards education. More info can be found here: &#xD;
&#xD;
[https://www.senate.gov/artandhistory/history/minute/Sputnik_Spurs_Passage_of_National_Defense_Education_Act.htm][4]&#xD;
&#xD;
There are other bumps, but I haven&amp;#039;t got the chance to further research it. I would love it if anyone can help to explain the sudden stop in 1970s and a huge increase in late 1980s.&#xD;
&#xD;
Next is I want to found out the country distribution of our data.&#xD;
&#xD;
    countryYear = &#xD;
     finalData[All, &amp;#034;Personal Information&amp;#034;, 1, {&amp;#034;Country&amp;#034;, &amp;#034;Year&amp;#034;}]&#xD;
    &#xD;
    amountPerCountry[year_] := Module[{data, listCountry, howMany},&#xD;
      data = countryYear[Select[#Year == ToString[year] &amp;amp;]][All, &#xD;
        &amp;#034;Country&amp;#034;];&#xD;
      listCountry = data // DeleteDuplicates // DeleteMissing;&#xD;
      howMany[country_] := &#xD;
       country -&amp;gt;  Length[Select[data, # == country &amp;amp;]];&#xD;
      Map[howMany, listCountry] // Normal // Association // Dataset&#xD;
      ]&#xD;
    &#xD;
    createChart[year_] := &#xD;
     BarChart[amountPerCountry[year][[1 ;; 20]], &#xD;
      ChartLabels -&amp;gt; Placed[Automatic, Automatic, Rotate[#, 90 Degree] &amp;amp;]]&#xD;
    &#xD;
    createMap[year_] := Module[{countryTally, countryEntities, toMap},&#xD;
      countryTally = amountPerCountry[year];&#xD;
      countryEntities = &#xD;
       Interpreter[&amp;#034;Country&amp;#034; | &amp;#034;AdministrativeDivision&amp;#034; ][&#xD;
        Keys[Normal[countryTally]]];&#xD;
      toMap = &#xD;
       AssociationThread[countryEntities -&amp;gt; Values[Normal[countryTally]]];&#xD;
      GeoRegionValuePlot[toMap, ColorFunctionScaling -&amp;gt; False, &#xD;
       ColorFunction -&amp;gt; (x \[Function] &#xD;
          ColorData[&amp;#034;DarkRainbow&amp;#034;][(x/270)^(1/4)])]&#xD;
      ]&#xD;
&#xD;
Okay, let&amp;#039;s test it on 2014 data&#xD;
![enter image description here][5]&#xD;
&#xD;
It seems that our data is heavily biased towards American, as we can see America has a gigantic figure compared to everybody and Russia is shown to be the same level as Argentina/Norwegia. This doesn&amp;#039;t seems to fit our experience where Russian plays a major part in the mathematics community. The bias probably is caused because it&amp;#039;s not popular in Russia, so  people doesn&amp;#039;t submit their information. &#xD;
&#xD;
Some other observation is the fact that majority of Africa doesn&amp;#039;t have any data. It can be either bias in database, or mathematics community really has not developed in Africa. Personally, I think it is more towards the later options, but I would love to hear opinions regarding this.&#xD;
&#xD;
One thing that I&amp;#039;m always curious is how the community develop. If we go back to history, often mathematics idea come from a certain country, then spread around to other country, which then the new country will develop their own mathematics idea. A good example is how Algebra spread Middle East to Italy by Fibonacci, which then sparks more works about the subject leading to the solution of 3rd degree polynomial. Using the database, I&amp;#039;m trying to see the progression of knowledge between country by identifying mathematician who has an adviser from different country. Since the code is somewhat long, I&amp;#039;ll just post the result, and the source code can be seen in the notebook. &#xD;
&#xD;
Here is the percentage of mathematician with foreign adviser among everyone in the database:&#xD;
![enter image description here][6]&#xD;
&#xD;
Surprisingly high number of mathematician has a foreign adviser! It seems mathematics is an international business. Still, this result might be biased since the majority of our data come from 20th Century USA. Trying the same approach towards those in 19th century, we get more conservative result:&#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
Only 8% of mathematician is confirmed to have foreign adviser in 19th century. It is still possible for this number to grow since there are 40% missing data. Still, it shows how the advent of technology makes it easier for ideas to spread. Of course, there are various things to be explored in this direction, but because of time constraint this is the result that I get so far. I would love to hear more ideas how to explore this.&#xD;
&#xD;
My last work is to create a genealogy tree of someone&amp;#039;s adviser(s). Here is the code used:&#xD;
&#xD;
    getAdvisor[id_Integer] := &#xD;
     Module[{advisor = &#xD;
        finalData[id][&amp;#034;Personal Information&amp;#034;, All, &amp;#034;Advisor&amp;#034;] // Normal //&#xD;
          Flatten},&#xD;
      ToExpression@DeleteMissing[advisor]&#xD;
      ]&#xD;
    &#xD;
    goBack[id_] := Map[id -&amp;gt; # &amp;amp;, getAdvisor[id]]&#xD;
    &#xD;
    createTree[id_, generation_] := Module[{list, i, assoc},&#xD;
      list = {{id}};&#xD;
      i = 1;&#xD;
      While[i &amp;lt;= generation,&#xD;
       list = Join[list, {Map[getAdvisor, (list[[i]] // Flatten )] } ];&#xD;
       i++&#xD;
       ];&#xD;
      assoc = Map[goBack, list // Flatten // DeleteDuplicates] // Flatten;&#xD;
      Graph[assoc,&#xD;
       VertexLabels -&amp;gt;&#xD;
        Map[# -&amp;gt; Last@StringSplit[finalData[#, &amp;#034;Name&amp;#034;]] &amp;amp;, &#xD;
         DeleteDuplicates[Join[Part[assoc, All, 1], Part[assoc, All, 2]]]&#xD;
         ]&#xD;
       ]&#xD;
      ]&#xD;
&#xD;
Out of respect of Wolfram language, here is the genealogy of Stephen Wolfram up to 10 generations&#xD;
![enter image description here][8]&#xD;
&#xD;
And that concludes my current result of exploration. For future directions, I have a list of ideas that I would like to try:&#xD;
&#xD;
 1.  Model how mathematics community develop &#xD;
 2. Explore trend of subject by country and year&#xD;
 3. Correlation between advisor&amp;#039;s and student&amp;#039;s dissertation topic&#xD;
 4. Analysis of MathSci Net&#xD;
 5. Use Machine Learning to identify person&amp;#039; s heritage from his/her name, then use it to analyze how it affects the person descendants&#xD;
&#xD;
If you have any suggestion/comments, I would love to hear it. Hope you guys enjoy the post!&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=URLPicture.png&amp;amp;userId=1136056&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Screenshot%2821%29.png&amp;amp;userId=1136056&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Histogram1950-1990.gif&amp;amp;userId=1136056&#xD;
  [4]: https://www.senate.gov/artandhistory/history/minute/Sputnik_Spurs_Passage_of_National_Defense_Education_Act.htm&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=MapHistogram2014.png&amp;amp;userId=1136056&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=PieChartAll.png&amp;amp;userId=1136056&#xD;
  [7]: http://community.wolfram.com//c/portal/getImageAttachment?filename=PieChart19thCentury.png&amp;amp;userId=1136056&#xD;
  [8]: http://community.wolfram.com//c/portal/getImageAttachment?filename=WolframGenealogy.png&amp;amp;userId=1136056</description>
    <dc:creator>Ricky Simanjuntak</dc:creator>
    <dc:date>2017-07-05T22:05:04Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1383617">
    <title>[WSC18] Producing Four-Colorings of Historical Geopolitical Maps</title>
    <link>https://community.wolfram.com/groups/-/m/t/1383617</link>
    <description>![A map of the world in 1700][2]&#xD;
&#xD;
&#xD;
**Utilizing the Brélaz Heuristic to Produce Efficient Four-Colorings of Historical Geopolitical Maps**&#xD;
&#xD;
The goal of this project was to develop a system that provides a four-coloring of historical geopolitical maps, utilizing minimum cycle completion algorithms and the Brelaz coloring heuristic. The intention here was mostly as an intellectual exercise - the functional paradigm of the Wolfram language lends itself quite nicely to implementing a four-coloring of a map, and the magnitude of data available from the Wolfram Knowledge Base allowed a very nice application of this mathematical theorem to a real-world example, and I thought it would be interesting to combine the two in an application.&#xD;
    &#xD;
#Beginnings&#xD;
&#xD;
Wolfram has a very nice collection of the polygons of historical countries in its data repository. This data was used to develop the maps of the historical countries.&#xD;
&#xD;
Unfortunately, however, the entities in &amp;#034;HistoricalCountries&amp;#034; don&amp;#039;t have a &amp;#034;BorderingCountries&amp;#034; property. This was a little bit troublesome, as it was necessary to know the bordering countries in order to color the map. A BorderingCountries function was written to remediate this.&#xD;
&#xD;
    &#xD;
    getRegion[polygon_] := &#xD;
     DiscretizeGraphics@&#xD;
      Cases[polygon, Line[a___], Infinity]&#xD;
        &#xD;
    BorderingCountries[countries_, country_, c1_, year_] :=     &#xD;
     Module[{pts, r},&#xD;
      pts = Identity @@@ &#xD;
        MeshPrimitives[getRegion[Dated[country, year][&amp;#034;Polygon&amp;#034;]], 0];&#xD;
      r = Table[Min[RegionDistance[i, pts]], {i, c1}];&#xD;
      Pick[countries, Thread[r &amp;lt; 0.03]]&#xD;
      ]&#xD;
&#xD;
This function retrieved every country within a latitude/longitude range of 0.03° that had a polygon for the given input year. This will be used later in the map generation function.&#xD;
&#xD;
#First Attempts at Coloring&#xD;
I began by declaring variables and methods for ensuring all of the countries were properly called and mapped onto Wolfram&amp;#039;s default world spread:&#xD;
&#xD;
    yearWorldMap[i_] := &#xD;
   &#xD;
     toColor[tf_] := &amp;lt;|{False, False} -&amp;gt; Red, {False, True} -&amp;gt; Blue, {True, False} -&amp;gt; Green, {True, True} -&amp;gt; Yellow|&amp;gt;[tf]&#xD;
    &#xD;
     Module[{},&#xD;
      &#xD;
      year = DateObject[List[i], &amp;#034;Year&amp;#034;, &amp;#034;Gregorian&amp;#034;, -4.`];&#xD;
      &#xD;
      inrange = &#xD;
       Keys@Select[CloudImport@CloudObject[&amp;#034;HistoricalCountries.wxf&amp;#034;], &#xD;
         yearWithinQ[year, #] &amp;amp;];&#xD;
      &#xD;
      countries = Pick[inrange, Not@*MissingQ /@ EntityValue[Dated[inrange, year], &amp;#034;Polygon&amp;#034;]];&#xD;
      &#xD;
      c1 = getRegion /@ (EntityValue[Dated[countries, year], &amp;#034;Polygon&amp;#034;]);&#xD;
      &#xD;
      countryneighbors = {#, DeleteCases[BorderingCountries[countries, #, c1, year] , #] } &amp;amp; /@ countries;&#xD;
      &#xD;
      countrybooleans = # -&amp;gt; {x[#], y[#]} &amp;amp; /@ countries;&#xD;
&#xD;
Then, the first attempt at a minimum vertex cycle algorithm was implemented (and also put into the yearWorldMap module).&#xD;
&#xD;
    eqs = And @@ (Flatten[&#xD;
         Function[{c, n}, &#xD;
           BooleanConvert[Xor[x[c], x[#]] || Xor[y[c], y[#]], &amp;#034;CNF&amp;#034;] &amp;amp; /@ &#xD;
            n] @@@ countryneighbors]);&#xD;
    &#xD;
    solution =&#xD;
      Join[Replace[&#xD;
        FindInstance[eqs, Union[Cases[eqs, _x | _y, \[Infinity]]], &#xD;
         Booleans], {{first_, ___} :&amp;gt; first, _ :&amp;gt; {}}], &#xD;
       Flatten[{x[#] -&amp;gt; True, y[#] -&amp;gt; True} &amp;amp; /@ &#xD;
         Flatten[Cases[countryneighbors, {_, {}}]]]];&#xD;
    &#xD;
    coloring = &#xD;
      Quiet[(Dated[#[[1, 1, 1]], year] -&amp;gt; &#xD;
           Lighter@Lighter@toColor[Last /@ #]) &amp;amp; /@ &#xD;
        Partition[SortBy[solution, #[[1, 1]] &amp;amp;], 2]];&#xD;
&#xD;
For early history (1000 BC to 100 BC), this algorithm was reasonably fast. However, many issues emerged during testing:&#xD;
&#xD;
 1. The threshold `r` used for the `BorderingCountries` function was a little bit strange to work with. Initially, if the `r` value was hard to obtain with the &#xD;
     cycling algorithm, because the algorithm would fail if the `r` provided was too big and returned any overlapping country polygons. However, after &#xD;
     much experimentation, I was able to get a satisfactory `r` value.&#xD;
&#xD;
 2. The development process under this algorithm was very tedious. There were many variables to keep track of, and many things broke very often. &#xD;
     For instance, whenever there was a country overlap and the computer couldn&amp;#039;t distinguish between polygons, it often defaulted to the `(True, True)` &#xD;
     condition, leaving most of the map blank and only using the color yellow when the condition applied.![enter image description here][4]&#xD;
&#xD;
 3. Perhaps the most glaring issue was that the minimum cycle algorithm became extremely slow for more recent years. This is because more &#xD;
     countries existed as time moved forward, and thus, the algorithm takes much longer to color the map (the minimum cycle vertex algorithm &#xD;
     completes in exponential runtime).&#xD;
&#xD;
#Using the Brélaz heuristic&#xD;
After much testing, I finally decided that I needed to remove the minimum vertex cycling algorithm, as it was simply too computationally expensive and inefficient to implement at the scale I desired for this project.&#xD;
&#xD;
Of course, that meant figuring out another algorithm to use.&#xD;
&#xD;
Prior to Version 11 of *Mathematica*, a graph theory package called *Combinatorica* had a simple function called `BrelazColoring` that would color a graph according to the Brélaz heuristic¹, which provides good, but not necessarily minimal colorings for a graph. As the goal for this project was to four-color a map, using the Brélaz heuristic as the basis for the coloring method was a good idea because a minimal coloring wasn&amp;#039;t *absolutely* necessary the map was a good idea.&#xD;
&#xD;
To use `BrelazColoring`, I first needed to convert my world map into a graph, color the vertices of the graph, and then apply the coloring to the map. The code I used to do so was&#xD;
    &#xD;
&#xD;
    Quiet[&amp;lt;&amp;lt; Combinatorica`]&#xD;
    rules = Thread[# -&amp;gt; Range[Length[#]]] &amp;amp;@&#xD;
    Union[Flatten[countryneighbors]];&#xD;
    edges = List /@ Join @@ Thread /@ countryneighbors /. rules;&#xD;
    vp = List /@ RandomReal[{0, 1}, {Length[rules], 2}];&#xD;
    colors = BrelazColoring[Graph[edges, vp]];&#xD;
    polys = EntityValue[Thread[Dated[rules[[All, 1]], year]], &amp;#034;Polygon&amp;#034;];&#xD;
&#xD;
This worked very well, and was able to produce accurate four-colorings of historical maps, &#xD;
&#xD;
#Making the Microsite&#xD;
What is a good function without a nice place for other people to use?&#xD;
&#xD;
As mentioned in the introduction of this post, a major portion of this project was the real-world applicability of the map function. To allow others to use it, I decided to create a microsite hosted on the Wolfram Cloud.&#xD;
&#xD;
I wanted a little bit more than a simple `FormPage`, so I added a little bit of styling to the website:&#xD;
&#xD;
    CloudDeploy[&#xD;
     FormPage[{&amp;#034;Year&amp;#034; -&amp;gt; &amp;lt;|&#xD;
         &amp;#034;Interpreter&amp;#034; -&amp;gt; Restricted[&amp;#034;Integer&amp;#034;, {-1000, 2018}], &#xD;
         &amp;#034;Help&amp;#034; -&amp;gt; &amp;#034;Use a hyphen (-) for BC years.&amp;#034;, &#xD;
         &amp;#034;Hint&amp;#034; -&amp;gt; &amp;#034;Enter a year&amp;#034;|&amp;gt;}, &#xD;
      Once[yearWorldMap[#Year], &amp;#034;Cloud&amp;#034;] &amp;amp;, &#xD;
      AppearanceRules -&amp;gt; &amp;lt;|&amp;#034;Title&amp;#034; -&amp;gt; &amp;#034;&amp;lt;b&amp;gt;Maps&amp;lt;/b&amp;gt; Throuhgout History&amp;#034;, &#xD;
        &amp;#034;Description&amp;#034; -&amp;gt; &#xD;
         &amp;#034;&amp;lt;/style&amp;gt;Enter a number to see the geopolitical map for that \&#xD;
    year. After, click below to see a video of the map changing over \&#xD;
    time.&amp;#034;, &amp;#034;SubmitLabel&amp;#034; -&amp;gt; &amp;#034;Give me the map!&amp;#034;, &#xD;
        &amp;#034;PageTheme&amp;#034; -&amp;gt; &amp;#034;Blue&amp;#034;|&amp;gt;], &amp;#034;Maps&amp;#034;, Permissions -&amp;gt; &amp;#034;Public&amp;#034;]&#xD;
&#xD;
You can access the microsite [here](https://www.wolframcloud.com/objects/nikeshmishra01/Maps).&#xD;
&#xD;
#Future Work&#xD;
As of right now, the function that generates a map only works for years ranging from 1000 BC to 1950 AD. This is because, after much experimentation, I failed to find a way to incorporate the polygon&amp;#039;s of modern countries into my code without destroying the modern map. I do intend to find a solution to this, and extend the AD range of the mapping function to 2018 (or whatever the current year, assuming I have enough cloud credits to sustain it into the future.)&#xD;
&#xD;
&#xD;
----------&#xD;
¹As a side note, the reason Brélaz got a &amp;#034;heuristic&amp;#034; and not an &amp;#034;algorithm&amp;#034; named after him is because graph coloring is computationally hard and is an NP-complete problem. In general, NP-complete problems cannot be solved by algorithms in a reasonable amount of time (they need exponentially more time to solve); however, because the Brélaz heuristic often gives such good results, it is often referred to as an algorithm; even &#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=map.jpg&amp;amp;userId=1371691&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=GoodMap.png&amp;amp;userId=1371691&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Overlapmap.png&amp;amp;userId=1371691&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Yellowmap.png&amp;amp;userId=1371691</description>
    <dc:creator>Nikesh Mishra</dc:creator>
    <dc:date>2018-07-14T04:26:14Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1728662">
    <title>[WSS19] Aggregation Systems: A stochastic approach to CA</title>
    <link>https://community.wolfram.com/groups/-/m/t/1728662</link>
    <description>![Aggregation System of a Totalistic Rule][1]&#xD;
&#xD;
&#xD;
**Aggregation System of a Totalistic Rule**&#xD;
&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
&#xD;
**All possible paths the Aggregation System can take**&#xD;
&#xD;
&#xD;
##Introduction ##&#xD;
Aggregation Systems are a stochastic analog to the Cellular Automaton. Unlike Cellular Automaton, where every step is deterministic and it grows one row at a time, Aggregation Systems grow by adding one cell at a time at randomly chosen locations. But at the same time, there are certain underlying rules similar to the Cellular Automaton rules they follow. So, it is random but has a deterministic tinge of the Cellular Automata rules. For example, one step of Rule 30 in CA and AS, &#xD;
&#xD;
&#xD;
![enter image description here][3]     &#xD;
        &#xD;
*Rule 30 CA*&#xD;
&#xD;
&#xD;
![enter image description here][4]&#xD;
&#xD;
&#xD;
*Rule 30 AS*&#xD;
 &#xD;
As you can see, the Aggregation System model basically follows the rules of the Cellular Automaton but instead of adding all the cells in the following row, it picks one at random. After around 30 steps, this is how they both look (Rule 30 of elementary Cellular Automaton). &#xD;
&#xD;
![enter image description here][5]&#xD;
&#xD;
***CA***&#xD;
&#xD;
![enter image description here][6]&#xD;
&#xD;
***AS***&#xD;
&#xD;
A lot of &amp;#034;random&amp;#034; behavior of nature could be modeled using the Outer Totalistic and Totalistic Rule Set of the Aggregation System and hence, most of the results in the following post are calculated for the Outer Totalistic Case (2D) with an initial condition of an array with one black cell at the center. &#xD;
## Aggregation System Function ##&#xD;
&#xD;
    Clear[framedAggregationSystem];&#xD;
    framedAggregationSystem[rule_, init_, steps_]:= Catch[Module[{r, p, pos, output1},Nest[&#xD;
    (&#xD;
    r=CellularAutomaton[rule,#];&#xD;
    pos= Position[r, Except[0], {Depth[init]-1}, Heads-&amp;gt;False];&#xD;
    If[pos=== {}, Throw[#]];&#xD;
    p=RandomChoice@pos;&#xD;
    output1 = ReplacePart[#,p-&amp;gt; Extract[r, p]]&#xD;
    )&amp;amp;,init,steps]]]&#xD;
&#xD;
*Running this code for Outer Totalistic Rule # 30, gives an image something like this:* &#xD;
&#xD;
![enter image description here][7]&#xD;
&#xD;
&#xD;
## Efficient implementation of the same ##&#xD;
&#xD;
But this algorithm is inefficient because one needs to define an arbitrary size of the frame to fit the Aggregation System and the algorithm goes on evaluating the white background cells even when the Aggregation System dies down. The next step was to overcome this issue. For that, I evaluated each step of the Aggregation System and evolved the frame accordingly along with the frame. So I pad the initial condition, evaluate the rule and blacken the cell, and then unpad if needed. Here&amp;#039;s the code for that: &#xD;
&#xD;
    unpad[a_]:=(ReplacePart[a,Thread[(Replace[#,All-&amp;gt;_,1]&amp;amp;/@Select[Catenate@Table[Append[ConstantArray[All,n],m],{n,0,Depth[a]-2},{m,{1,-1}}],AllTrue[Flatten[Extract[a,#]],#===0&amp;amp;]&amp;amp;])-&amp;gt;Nothing]])&#xD;
    Clear[AggregationSystem];&#xD;
    AggregationSystem[rule_, init_, steps_]:= Catch[Module[{r, p, pos, output1,output2,cent=0},Nest[&#xD;
    (output1=ArrayPad[#,1];&#xD;
    cent+=1;&#xD;
    r=CellularAutomaton[rule,output1];&#xD;
    pos= Position[r, Except[0], {Depth[init]-1}, Heads-&amp;gt;False];&#xD;
    If[pos=== {}, Throw[#]];&#xD;
    p=RandomChoice@pos;&#xD;
    output1 =output2= ReplacePart[output1,p-&amp;gt; Extract[r, p]];&#xD;
    output1=unpad[output1];&#xD;
    output1&#xD;
    )&amp;amp;,init,steps]]]&#xD;
&#xD;
&#xD;
    ArrayPlot@AggregationSystem[&amp;lt;| &amp;#034;OuterTotalisticCode&amp;#034;-&amp;gt; 30 , &amp;#034;Dimension&amp;#034;-&amp;gt; 2|&amp;gt;, CenterArray[1, {1,1}], 200]&#xD;
*Running rule 30 with this:*&#xD;
&#xD;
&#xD;
![enter image description here][8]&#xD;
&#xD;
&#xD;
This makes it highly efficient:&#xD;
&#xD;
&#xD;
![enter image description here][9]&#xD;
&#xD;
&#xD;
*TIme vs iterations of both the algorithms*&#xD;
&#xD;
## Overview of the rules ##&#xD;
The space of outer totalistic rules is about 262143. But odd rules are uninteresting as they flicker and some rules simply do not grow given the initial condition of the Center Array. Eliminating them, I was left with 65536 rules which are still large. One of the brute force ways to get some intuition and understanding about which directions to look for is to simply run all the rules and stare at them:&#xD;
&#xD;
&#xD;
![enter image description here][10]&#xD;
&#xD;
&#xD;
**First 100 Outer Totalistic Rules for about 200 iterations**&#xD;
## **TESTS AND EXPERIMENTS** ##&#xD;
&#xD;
## Dimensions##&#xD;
If one stares at the rules for a while, you realize that there is some sort of burst in the dimensions after a certain discrete rule number. This hints towards behavior during systems where there is a phase change of some sort. For example, rule 510 -&amp;gt;516:&#xD;
&#xD;
&#xD;
![enter image description here][11]&#xD;
&#xD;
&#xD;
&#xD;
This happens all the time and is not by chance. Iterating each rule 20 times and plotting the dimensions: &#xD;
&#xD;
&#xD;
![enter image description here][12]&#xD;
&#xD;
   *X and Y coordinates of rules 510 and 516 when run multiple times.*&#xD;
&#xD;
In other words, this is the result of the tinge of determinism in the rules of the Cellular Automaton applied to &amp;#034;random&amp;#034; Aggregation Systems. &#xD;
&#xD;
Plotting the dimensions for the whole rule space of Outer Totalistic:&#xD;
&#xD;
&#xD;
![enter image description here][13]&#xD;
&#xD;
&#xD;
The spikes mainly occur around the powers of 2 because that is where the rules undergo a major change in terms of the number of cells turning to black given a neighborhood. &#xD;
&#xD;
## Standard Deviation ##&#xD;
On iterating each rule a several number of times, I got a different picture almost every time as the cells are picked one at a time from a set of finite possible options. This raises the question of whether there exists some sort of a behavioral characteristic to a rule we can predict beforehand given the rule number. One of the measures to look at it is the Standard Deviation of the pixel values {0,1} after iterating a rule for a fixed number of iterations. So given, the number of iterations for each rule and the number of rules we want this result for, here&amp;#039;s the function that gives the standard deviation of the cell values: &#xD;
&#xD;
    available =  Select[Range[2^18-1],EvenQ[#] &amp;amp;&amp;amp;!IntegerQ[#/8]&amp;amp;&amp;amp;!IntegerQ[(#-10)/8]&amp;amp;];&#xD;
    stdeviationrandomavailable[iterations_, n_]:=&#xD;
    ( a = RandomSample[available, n];&#xD;
    KeyValueMap[N@StandardDeviation@#2&amp;amp;,Merge[Table[AssociationMap[AggregationSystem[&amp;lt;| &amp;#034;OuterTotalisticCode&amp;#034;-&amp;gt; # , &amp;#034;Dimension&amp;#034;-&amp;gt; 2|&amp;gt;, CenterArray[1, {50,50}], 500]&amp;amp;, a], {k,iterations}],Identity]]&#xD;
    )&#xD;
    AssociationThread[a, ArrayPlot/@stdeviationrandomavailable[10, 5]]&#xD;
**Output:**&#xD;
&#xD;
![enter image description here][14]&#xD;
&#xD;
&#xD;
Doing the same for a higher iteration value:&#xD;
&#xD;
&#xD;
![enter image description here][15]&#xD;
&#xD;
I noticed that many of the rules have a dark halo at the edges. This happens because when we run a rule a multiple number of times, the inner section almost remains the same; like a dense blob. Only at the outer parts of the system that there is an uncertainty of the positions of the cells leading to a higher standard deviation. But this is not always true as one would normally expect. For example, **Rule 2143:**&#xD;
&#xD;
 &#xD;
![enter image description here][16]&#xD;
&#xD;
&#xD;
In this case, there is uncertainty engraved in the rule from the very beginning and the standard deviation plot almost looks like a black blob. If we go on to plot something analogous to the moment of inertia in that case of these Standard deviation visuals (vs Rule Number), we get an idea as to what is the distribution of the two types of Standard Deviation representations. &#xD;
&#xD;
    datastdev = Import[&amp;#034;stdeviationdata.mx&amp;#034;];&#xD;
    ListPlot@AssociationThread[labels, Table[N[Total[Flatten@MapIndexed[#1*(EuclideanDistance[Dimensions[datastdev[[n]]]/2,#2]^2)&amp;amp;,datastdev[[n]],{2}]]], {n, 1, 3000}]]&#xD;
&#xD;
&#xD;
![enter image description here][17]&#xD;
&#xD;
&#xD;
Histogram: &#xD;
&#xD;
    Histogram[AssociationThread[labels, Table[N[Total[Flatten@MapIndexed[#1*(EuclideanDistance[Dimensions[datastdev[[n]]]/2,#2]^2)&amp;amp;,datastdev[[n]],{2}]]], {n, 1, 3000}]]]&#xD;
&#xD;
&#xD;
![enter image description here][18]&#xD;
&#xD;
&#xD;
On looking for the distribution,&#xD;
&#xD;
    FindDistribution[Table[N[Total[Flatten@MapIndexed[#1*(EuclideanDistance[Dimensions[datastdev[[n]]]/2,#2]^2)&amp;amp;,datastdev[[n]],{2}]]], {n, 1, 3000}]]&#xD;
we get the following: &#xD;
&#xD;
MixtureDistribution[{0.9262480618395671`, &#xD;
  0.07375193816043307`}, {LogNormalDistribution[10.709938521692017`, &#xD;
   0.24927531644683798`], &#xD;
  LogNormalDistribution[11.375808011619768`, 0.3116990014250025`]}]&#xD;
&#xD;
## Mean ##&#xD;
Another thing that comes to mind after Standard deviation is the mean of the rules after iterating multiple times. Similar to the standard deviation, here&amp;#039;s the code for the mean calculations:&#xD;
&#xD;
    meanrandomavailable[n_, iterations_]:=&#xD;
    (a = RandomSample[available, n];&#xD;
    KeyValueMap[ArrayPlot[N@Mean@#2, PlotLabel-&amp;gt; #1]&amp;amp;,Merge[Table[AssociationMap[AggregationSystem[&amp;lt;| &amp;#034;OuterTotalisticCode&amp;#034;-&amp;gt; # , &amp;#034;Dimension&amp;#034;-&amp;gt; 2|&amp;gt;, CenterArray[1, {45,45}], 200]&amp;amp;,a], {k,iterations}],Identity]])&#xD;
    meanrandomavailable[10,10]&#xD;
&#xD;
&#xD;
![enter image description here][19]&#xD;
&#xD;
This again tells us about the characteristic of rules. Certain rules like 159454 have a Gaussian distribution implying that they&amp;#039;re more likely to land in that particular spot than in other places. On the other hand, some rules like 193062 are by and large of the same probability everywhere implying that a cell is equally likely to land in any given area. They display a dispersed behavior in comparison to the rules like 159454. &#xD;
&#xD;
## **Confluence** ##&#xD;
Confluence is essentially a property of a rewrite system which indicates whether or not a system (observed) can be transformed or rewritten in a way that the input of an abstract rewrite pair overlaps to the same result after the following iteration. If this happens over a single rewrite rule iteration for all given states of a system, the system is said to be locally or weakly confluent and the system is said to display the Church-Rosser property. If this, occurs over multiple transformation steps, the system is said to be globally confluent. &#xD;
Confluence is usually studied in deterministic systems and the study of confluence hasn&amp;#039;t really been taken up in stochastic systems. Here, I aim to bring up an idea of confluence in the case of these stochastic Aggregation Systems. &#xD;
&#xD;
## &amp;#034;Theoretical&amp;#034; evaluation of Confluence Levels ##&#xD;
&#xD;
Given an initial condition of the Center Array and a rule, there are different states in which a system can evolve to. Some of these states can be further evolved to converge into the same state. For example, &#xD;
&#xD;
&#xD;
![enter image description here][20]&#xD;
&#xD;
&#xD;
Code for the above: &#xD;
&#xD;
    Clear[DeterministicAggregationSystem];&#xD;
    DeterministicAggregationSystem[rule_, init_]:= Catch[Module[{r, pos},Nest[&#xD;
    (&#xD;
    r=CellularAutomaton[rule,#];&#xD;
    pos= Position[r, Except[0], {Depth[init]-1}, Heads-&amp;gt;False]; &#xD;
    If[pos=== {}, Throw[#]];&#xD;
    &#xD;
    Function[p,ReplacePart[#,p-&amp;gt; Extract[r, p]]]/@pos&#xD;
    )&amp;amp;,init,1]]&#xD;
    ]&#xD;
The above fuction lists all the possible states from one iteration to the other. &#xD;
&#xD;
    &#xD;
    removeSelfLoops[g_Graph]:=Graph[DeleteCases[EdgeList[g],(DirectedEdge|UndirectedEdge)[x_,y_]/;x===y],Sequence@@Options[g]]&#xD;
    theoreticalconfluencegraph2[rule_,iters_,initI_:CenterArray[1,{5,5}]]:=Module[{graphint},&#xD;
    graphint = Graph[Labeled[#,#,Center]&amp;amp;/@VertexList[#],DeleteDuplicates@EdgeList[#]]&amp;amp;@Graph[&#xD;
    Catenate[Module[{newInit},Reap[Nest[&#xD;
    Catenate@*Map[Function[init,&#xD;
    newInit=DeterministicAggregationSystem[rule,init];&#xD;
    Sow[ArrayPlot[init,ImageSize-&amp;gt;15]\[DirectedEdge]ArrayPlot[#,ImageSize-&amp;gt;15]&amp;amp;/@newInit];&#xD;
    newInit&#xD;
    ]],&#xD;
    {initI},iters];&#xD;
    ]][[2,1]]]&#xD;
    ];&#xD;
    removeSelfLoops[graphint]&#xD;
    ]&#xD;
    g = theoreticalconfluencegraph2[&amp;lt;| &amp;#034;OuterTotalisticCode&amp;#034;-&amp;gt;30, &amp;#034;Dimension&amp;#034;-&amp;gt; 2 |&amp;gt;, 2];&#xD;
    g = HighlightGraph[g, {ReplacePart[VertexList[g][[{1,2}]],0-&amp;gt;DirectedEdge]}];&#xD;
    g = HighlightGraph[g, {ReplacePart[VertexList[g][[{2,14}]],0-&amp;gt;DirectedEdge]}];&#xD;
    g = HighlightGraph[g, {ReplacePart[VertexList[g][[{1,3}]],0-&amp;gt;DirectedEdge]}];&#xD;
    g = HighlightGraph[g, {ReplacePart[VertexList[g][[{3, 14}]],0-&amp;gt;DirectedEdge]}]&#xD;
&#xD;
The highlighted part of the graph is one of the possible paths that can be taken by the system that converge after two iterations. We calculate the probability of achieving such states since these bring the confluence to the rule. For example, there is a {1/80, 1/80 } chance to take those paths on multiple iterations. Then, we go on to calculate such probabilities for all such convergent states and take the sum. This, in essence, defines a theoretical confluence level of a particular rule.&#xD;
&#xD;
    theoreticalconfluencevalue [graph_]:= &#xD;
    (Module[{val, probs},probs = Select[AssociationMap[Apply[Function[{v1,v2},Function[path,1/Times@@(VertexOutDegree[graph,#]&amp;amp;/@Most[path])]/@FindEdgeIndependentPaths[graph,v1,v2,Infinity]]],Permutations[VertexList[graph],{2}]],Length[#]&amp;gt;1&amp;amp;];&#xD;
    Print[probs];&#xD;
    val = N[Total@Flatten@Values@probs]&#xD;
    ])&#xD;
    theoreticalconfluencevalue[g]&#xD;
&#xD;
&#xD;
![enter image description here][21]&#xD;
&#xD;
&#xD;
**Output confluence value: 0.641667**&#xD;
&#xD;
## Experimental Evaluation of weak confluence ##&#xD;
Until now, we algorithmically defined and calculated the theoretical confluence level of a given ruleset. But the speculation is that this might not be so simple after all and it is a good idea to compare it to the real Aggregation System by actually running it and fetching raw data.  &#xD;
&#xD;
## Algorithm and evaluation ##&#xD;
Given a rule set and the initial condition of the central array, two iterations of the Aggregation Systems are evaluated for a certain sample number of times (200+) and displayed as a graph. To get the confluence level in the ruleset, we first count the number of pairs of edges that point to a particular state in the second iteration from non-overlapping first iterations. We then divide this number by the total number of &amp;#034;VertexOut&amp;#034;  edges from the corresponding first iteration states. Finally, if this occurs for multiple states in the second iteration, the ratios are independently added and the resulting value is the experimental confluence level of the ruleset. &#xD;
&#xD;
    confluencegraph[rule_, iter_]:=(Module[{step1, step2, g, confgraph},&#xD;
    step1=Table[AggregationSystem[&amp;lt;| &amp;#034;OuterTotalisticCode&amp;#034;-&amp;gt; rule, &amp;#034;Dimension&amp;#034;-&amp;gt; 2 |&amp;gt;,CenterArray[1, {10, 10}], 1], {i, iter}];&#xD;
    step2 = Table[AggregationSystem[&amp;lt;| &amp;#034;OuterTotalisticCode&amp;#034;-&amp;gt; rule, &amp;#034;Dimension&amp;#034;-&amp;gt; 2 |&amp;gt;,step1[[i]], 1], {i, iter}];&#xD;
    g=Graph[Flatten[{&#xD;
    Thread[DirectedEdge[(ArrayPlot[#,ImageSize-&amp;gt;20]&amp;amp;/@step1),(ArrayPlot[#,ImageSize-&amp;gt;20]&amp;amp;/@step2)]]&#xD;
    }]];&#xD;
    confgraph = removeSelfLoops@Graph[Labeled[#,#,Center]&amp;amp;/@VertexList[g],EdgeList[g]]&#xD;
    ])&#xD;
&#xD;
&#xD;
![enter image description here][22]&#xD;
&#xD;
    confluencevalue[graph_Graph]:=Module[{keys, inOutDegree, exprob},&#xD;
    (keys=Keys@countofpairs[graph];&#xD;
    inOutDegree=AssociationMap[AssociationMap[VertexOutDegree[graph,#]&amp;amp;,DeleteCases[VertexInComponent[graph,#,1],#]]&amp;amp;,keys];&#xD;
    exprob=Merge[{countofpairs[graph],Total/@inOutDegree},#[[1]]/#[[2]]&amp;amp;];&#xD;
    Total[exprob])]&#xD;
    experimentalconfluencegraph = confluencegraph[100, 100]&#xD;
    confluencevalue[experimentalconfluencegraph]//N&#xD;
&#xD;
**Output Confluence Value: 1.24847**&#xD;
&#xD;
## Conclusion ##&#xD;
A function was successfully fabricated to give out the Aggregation System given the rule number, initial conditions, and the number of iterations (exactly like Cellular Automaton). Following that, the function was made efficient by precisely fitting it to the frame. Then, certain properties like dimensions, standard deviation, and mean were studied which revealed some behavioral patterns which hint towards natural events like phase changes in a system. Finally, the study of confluence, which is usually done on a deterministic system, was undertaken giving statistics on the &amp;#034;confluenciality&amp;#034; of a stochastic model of this type. &#xD;
&#xD;
## Future Work ##&#xD;
1. Extending the function to include 3D Aggregation Systems.&#xD;
2. Extending similar studies to a general space of initial conditions and other rule sets. &#xD;
3. Looking for interesting patterns by analyzing parameters like fractal box dimension, growth of the system with time, etc.&#xD;
4. Continue investigations on confluence in the rule space and look for stronger results.  &#xD;
&#xD;
&#xD;
  [1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=Agg_System.jpg&amp;amp;userId=1726294&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=raphhighlighted.jpg&amp;amp;userId=1726294&#xD;
  [3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img3.jpg&amp;amp;userId=1726294&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img4.jpg&amp;amp;userId=1726294&#xD;
  [5]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img5.jpg&amp;amp;userId=1726294&#xD;
  [6]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img6.jpg&amp;amp;userId=1726294&#xD;
  [7]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img7.jpg&amp;amp;userId=1726294&#xD;
  [8]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img8.jpg&amp;amp;userId=1726294&#xD;
  [9]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img9.jpg&amp;amp;userId=1726294&#xD;
  [10]: https://community.wolfram.com//c/portal/getImageAttachment?filename=totalisticrules.gif&amp;amp;userId=1726294&#xD;
  [11]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img10.jpg&amp;amp;userId=1726294&#xD;
  [12]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img11.jpg&amp;amp;userId=1726294&#xD;
  [13]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img112.jpg&amp;amp;userId=1726294&#xD;
  [14]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img13.jpg&amp;amp;userId=1726294&#xD;
  [15]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img14.jpg&amp;amp;userId=1726294&#xD;
  [16]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img15.jpg&amp;amp;userId=1726294&#xD;
  [17]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img16.jpg&amp;amp;userId=1726294&#xD;
  [18]: https://community.wolfram.com//c/portal/getImageAttachment?filename=img44.jpg&amp;amp;userId=1726294&#xD;
  [19]: https://community.wolfram.com//c/portal/getImageAttachment?filename=cmbig.jpg&amp;amp;userId=1726294&#xD;
  [20]: https://community.wolfram.com//c/portal/getImageAttachment?filename=raphhighlighted.jpg&amp;amp;userId=1726294&#xD;
  [21]: https://community.wolfram.com//c/portal/getImageAttachment?filename=k.jpg&amp;amp;userId=1726294&#xD;
  [22]: https://community.wolfram.com//c/portal/getImageAttachment?filename=expp.jpg&amp;amp;userId=1726294</description>
    <dc:creator>Kabir Khanna</dc:creator>
    <dc:date>2019-07-10T17:15:56Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1382967">
    <title>[WSC18] Sorting Networks</title>
    <link>https://community.wolfram.com/groups/-/m/t/1382967</link>
    <description>I was assigned by Stephen Wolfram to create a sorting a network that could sort a specific list. To do this, I started by analyzing the optimal sorting network for a list of 16 items, which is in fact, the largest solution that humanity has found so far.&#xD;
&#xD;
![This is 16][1]&#xD;
&#xD;
in the image above, there are two boxes, I noticed the pattern in the smallest of the two first, which in every optimal sort I checked, was used off the bat to group up sets of 4.&#xD;
&#xD;
![this is 7][2]&#xD;
&#xD;
Next, by analyzing 14,15 and 16, 14, and 15 shown below. &#xD;
&#xD;
![enter image description here][3]&#xD;
&#xD;
I derived a pattern for what was happening in the larger boxes, namely, there are beams of length 2^n or of the form {1+c,2^n+c} where c mod(2^(n+1)) &amp;lt;2^n. After this, I was prompted to create an algorithm that could automatically create a list of list of pairs that specified these connections. Essentially, I was looking for something of the form {{1,2},{3,4},{5,6},{7,8},{1,3},{2,4},{5,7},{6,8},{1,5},{2,6},{3,7},{4,8}}. The code to do this was complicated, though through perseverance I successfully did it. The code is shown below:&#xD;
&#xD;
    function1[distanceBetweenEle_, list_, finalList_] :=&#xD;
     (Module[{arc, apair, apairamid, pairs},&#xD;
       Partition[list, distanceBetweenEle, distanceBetweenEle];&#xD;
       apair = &#xD;
        Part[Partition[list, distanceBetweenEle, distanceBetweenEle], &#xD;
         Span[1, -1, 2]];&#xD;
       Map[{#, # + distanceBetweenEle} &amp;amp;, Flatten[apair]];&#xD;
       apairamid = Map[&#xD;
         Function[&#xD;
          {itemInList},&#xD;
          {itemInList, itemInList + distanceBetweenEle}&#xD;
          ],&#xD;
         Flatten[apair]&#xD;
         ];&#xD;
       pairs = Select[&#xD;
         apairamid,&#xD;
         Function[&#xD;
          {item},&#xD;
          Not[Part[item, 2] &amp;gt; Length@list]&#xD;
          ]&#xD;
         ];&#xD;
       arc = Join[finalList, pairs];&#xD;
       If [(Length[list] + 1 &amp;gt; distanceBetweenEle*2), &#xD;
        function1[distanceBetweenEle*2, list, arc], Return[arc];&#xD;
        ]]) &#xD;
&#xD;
This was a great start. Though we now had to figure out what to do for the second half of the list. So let us take a look at the ends of the optimal algorithm for 14th 15 and 16 elements.&#xD;
![This is the ends of 14-16][4]&#xD;
&#xD;
The first thing that most people should notice is that the connections follow no clear pattern. Despite this, there is one portion we will be able to exploit. If you look at the images above, you will notice that all new connections originated from the new segments. We can exploit this and proceed to only check connections from the old segment. The code for how I did this is below.&#xD;
&#xD;
    ClearAll[thingsToCheck]&#xD;
    thingsToCheck[L_, list_List, nope_] :=&#xD;
    Insert[list, {L, nope}, {#}] &amp;amp; /@ &#xD;
    Prepend[(First /@ Position[list, L | 1] + 1), 1]&#xD;
    ClearAll[mainFunction]&#xD;
    mainFunction[L_, list_List] := &#xD;
    Select[Flatten[thingsToCheck[#, list, L] &amp;amp; /@ Range[1, L - 1], 1] // &#xD;
    DeleteDuplicates, Length[#] === Length[Split[#]] &amp;amp;]&#xD;
&#xD;
Finally, I needed to implement a checker to check if the list could be sorted. No exploits were used for this segment, though in the future, presorting the first half could simplify the checker and would allow for greater number of checked permutations. The code is shown below.&#xD;
&#xD;
    ClearAll[swap]&#xD;
    swap[list_, {n_, m_}] :=&#xD;
     If[list[[n]] &amp;gt; list[[m]],&#xD;
      ReplacePart[&#xD;
       list,&#xD;
       {n -&amp;gt; Part[list, m],&#xD;
        m -&amp;gt; Part[list, n]}&#xD;
       ],&#xD;
      list&#xD;
      ]&#xD;
    &#xD;
    ClearAll[allSwapInstructions]&#xD;
    allSwapInstructions[swapInstruc_, id_] :=&#xD;
     Fold[swap, id, swapInstruc]&#xD;
    &#xD;
    ClearAll[checker]&#xD;
    checker[swapInstruc_, L_, id_] :=&#xD;
     Range[L] === allSwapInstructions[swapInstruc, id]&#xD;
&#xD;
Finally, we devised a final code snippet that connected all previous codes segments together:&#xD;
&#xD;
    ClearAll[theOnesThatWork]&#xD;
    theOnesThatWork[list_List, len_, id_, firstHalf_] :=&#xD;
     SelectFirst[Join[firstHalf, #] &amp;amp; /@ list,&#xD;
      checker[#, len, id] &amp;amp;]&#xD;
&#xD;
And we were done. Some testing is shown below:&#xD;
&#xD;
id = {5, 2, 4, 1, 3};&#xD;
step1 = mainFunction[5, {{2, 3}}]&#xD;
theOnesThatWork[step1, 5, id, function1[1, Range@5, {}]]&#xD;
step2 = Flatten[mainFunction[5, #] &amp;amp; /@ step1, 1];&#xD;
theOnesThatWork[step2, 5, Reverse[Range[5]], &#xD;
function1[1, Range@5, {}]]&#xD;
&#xD;
Special thanks to http://demonstrations.wolfram.com/SortingNetworks/&#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=ihasuhthzzzz.png&amp;amp;userId=1372143&#xD;
  [2]: http://community.wolfram.com//c/portal/getImageAttachment?filename=7.png&amp;amp;userId=1372143&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=14and15.png&amp;amp;userId=1372143&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=Endsof456.png&amp;amp;userId=1372143</description>
    <dc:creator>Sasha Kucher</dc:creator>
    <dc:date>2018-07-13T19:59:16Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1728556">
    <title>[WSS19] Implement Petri net</title>
    <link>https://community.wolfram.com/groups/-/m/t/1728556</link>
    <description>![enter image description here][1]&#xD;
&#xD;
**Introduction**&#xD;
------------&#xD;
A Petri net includes places, transitions and arcs. Arcs must go from a place to a transition or vice versa, which makes a Petri net a directed bipartite graph and the nodes represent transitions (events that may occur to cause change in states, marked by square) and places (conditions, marked by circles). These conditions make our first group of functions to check if the input structure is a Petri net, with the function named petriNetQ.&#xD;
Petri net is very useful because it is inherently graphical, good at representing concurrency and some interesting properties of nets can be expressed in terms of reachability. Hope more can be added to make the Petri net package more powerful.&#xD;
**Visualization and Animation**&#xD;
-------------------------------&#xD;
Here we have a package to make a Petri net and visualize it.&#xD;
&#xD;
    ClearAll[petriNetRun];&#xD;
    petriNetRun[pnet_, init_, step_Integer]:= Module[&#xD;
    	{current = init, g, index},&#xD;
    	current = Nest[updateFiring[pnet], current, step-1];&#xD;
    	index = First @ RandomChoice[Position[checkFiring[pnet, #, current] &amp;amp;/@ pnet[[3]], True]];&#xD;
    	If[IntegerQ[index], &#xD;
    		makeFiring[pnet, pnet[[3,index]], current], &#xD;
    		Print[&amp;#034;Dead!&amp;#034;]; Abort[]];&#xD;
    	g = petriNetInit[pnet, current];&#xD;
    	HighlightGraph[g, {pnet[[3,index]]}]&#xD;
    ]&#xD;
&#xD;
We then tried to visualize the movement of the Petri net in 15 steps.&#xD;
&#xD;
![enter image description here][2]&#xD;
&#xD;
Also for convenience, we have three different user interface to generate Petri net given Petri net data structure, chemical reactions and system of transitions.&#xD;
&#xD;
![enter image description here][3]&#xD;
![enter image description here][4]&#xD;
&#xD;
If a user gives the correct input, he or she will receive an animation of the Petri net similar to the one we display.&#xD;
**Petri net properties**&#xD;
-------------------------------&#xD;
Petri net, as a mathematical modeling language, indeed is not limited to visualize chemical processes. In fact, any mathematics model can be somewhat expressed with Petri net. However, from Wikipedia, papers written by John Baez, and StateBox archive, here are some open questions discussed with Petri net. &#xD;
The first problem is Reachability. According to Wikipedia, The reachability problem for Petri nets is to decide, given a Petri net N and a marking M, whether M can be reached from current state. This problem actually is not easy, and it was shown to be EXPSPACE-hard. But these days it turned out to be elementary. Here is a function named petriNetReachableQ.&#xD;
&#xD;
    petriNetReachableQ [ Neural Net n, init, Node m ]&#xD;
    Input: 	A Petri net named n, the initial condition of states, and the node marked as m we want to check.&#xD;
    Return: 	True if for Net n, m is reachable given the initial condition init in finite steps, else return False.&#xD;
    &#xD;
    ClearAll[petriNetReachableQ];&#xD;
    petriNetReachableQ[pnet_, init_, place_]:= Module[&#xD;
    	{states, places, assoc},&#xD;
    	states = Total[NestList[updateFiring[pnet], init , 100]];&#xD;
    	places = First @ Rest @ pnet;&#xD;
    	assoc = Association[Thread[places -&amp;gt; states]];&#xD;
    	If[assoc[place] === 0, False, True]&#xD;
    ]&#xD;
    &#xD;
An example to run petriNetReachableQ is the following:&#xD;
&#xD;
    In[61]:= petriNetReachableQ[graph, {1, 2, 0, 0, 5, 3, 0, 2}, c]&#xD;
    &#xD;
    Out[61]= True&#xD;
&#xD;
There are other properties remain discussed, such as boundedness and liveness. These are interesting graph properties we want to discuss here in Petri net.&#xD;
For a place p in a Petri Net, it is k-bounded if it never contains more than k tokens in any reachable marking. For example, traffic light nets are bounded, since every places are 1-bounded, which means the system is in safe.&#xD;
&#xD;
![enter image description here][5]&#xD;
&#xD;
    kBoundedness[Petri net pnet, initial state, key p]:&#xD;
    Input: 	Petri net named pnet, initial state of the Petri net pnet and the state key we what to check.&#xD;
    Return: 	an integer shows the boundedness of the state key.&#xD;
   &#xD;
For example, we want to check the boundedness of the red light from the Petri net we created, which is 1.&#xD;
    &#xD;
    In[63]:= kBoundedness[graph, {1, 0, 1, 0, 1}][red1]&#xD;
    &#xD;
    Out[63]= 1&#xD;
&#xD;
&#xD;
  [1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=PetrinetExample.jpeg&amp;amp;userId=1726500&#xD;
  [2]: https://community.wolfram.com//c/portal/getImageAttachment?filename=pnet.gif&amp;amp;userId=1726500&#xD;
  [3]: https://community.wolfram.com//c/portal/getImageAttachment?filename=GenInterface.jpg&amp;amp;userId=1726500&#xD;
  [4]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ChemInterface.jpg&amp;amp;userId=1726500&#xD;
  [5]: https://community.wolfram.com//c/portal/getImageAttachment?filename=1.gif&amp;amp;userId=1726500</description>
    <dc:creator>Pumeng Lyu</dc:creator>
    <dc:date>2019-07-10T13:40:12Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1733095">
    <title>[WSC19] Automatic Evaluation of Relationships Between Characters in Plays</title>
    <link>https://community.wolfram.com/groups/-/m/t/1733095</link>
    <description>Introduction&#xD;
------------&#xD;
&#xD;
Text analysis provides insight into stories that can be difficult to parse, especially when they are sufficiently large. This project aims to make a program that can use text analysis on any play in order to evaluate the relationships between characters. One can use sentiment analysis on each sentence and incorporate the frequency of these sentiments to determine a relationship&amp;#039;s health. Then, a graph with vertices representing the characters and edges representing their relationships illustrates the entire social network. The health of these relationships can be visualized with color, and frequency with width. Further operations with graphing functions can provide information on local groups within the play. In addition, accounting for who speaks to who, visualized with directed edges, allows for nuanced relationships in which feelings are not mutual.&#xD;
&#xD;
In order to test the universality of my program, I analyzed 10 plays of various time periods:  *Hamlet*, *King Lear*, *Midsummer Nights Dream*, *Romeo and Juliet*, *The Tempest*, *Oedipus the King, Oedipus at Colonus*, *Antigone*, *Death of a Salesman*, and *The Glass Menagerie*. Each play is given custom values for a negativity bias, positive tolerance, and negative tolerance so that the final graph best illustrates the play:&#xD;
&#xD;
    (* Set conditions specific to play: {play number, negativity bias, &#xD;
    positive tolerance, negative tolerance} *)&#xD;
    playConditions = &#xD;
      Table[plays[[i]] -&amp;gt; {i, 1, .30, -.30}, {i, 1, &#xD;
        Length[plays]}]; (* Default Setting *)&#xD;
    exceptions = {Values[playConditions[[1]]] -&amp;gt; {1, 1.2, .20, -.30}, &#xD;
       Values[playConditions[[2]]] -&amp;gt; {2, 1.35, .30, -.20},&#xD;
       Values[playConditions[[3]]] -&amp;gt; {3, 1.25, .40, -.30}, &#xD;
       Values[playConditions[[4]]] -&amp;gt; {4, 1.3, .30, -.30}, &#xD;
       Values[playConditions[[5]]] -&amp;gt; {5, 1.3, .30, -.30}, &#xD;
       Values[playConditions[[6]]] -&amp;gt; {6, 1.3, .30, -.30},&#xD;
       Values[playConditions[[7]]] -&amp;gt; {7, 1.3, .30, -.30}, &#xD;
       Values[playConditions[[8]]] -&amp;gt; {8, 1.3, .35, -.30}, &#xD;
       Values[playConditions[[9]]] -&amp;gt; {9, 1.3, .30, -.20}, &#xD;
       Values[playConditions[[10]]] -&amp;gt; {10, 1.3, .30, -.30}};&#xD;
    playConditions = playConditions /. exceptions;&#xD;
&#xD;
This project can be divided into two subtasks. The first is to accurately identify the speaker and recipient of a sentiment. The next is to incorporate numerous sentiment values to assess the overall health of a relationship between each pair of two characters.&#xD;
&#xD;
Determining the Characters Involved&#xD;
-----------------------------------&#xD;
&#xD;
First, correctly identifying the speaker can be easily done for plays, as each speaker is bolded: &#xD;
&#xD;
    speakerOrder = &#xD;
      Capitalize[&#xD;
       ToLowerCase@&#xD;
         StringCases[text, Shortest[&amp;#034;&amp;lt;b&amp;gt;&amp;#034; ~~ x__ ~~ &amp;#034;&amp;lt;/b&amp;gt;&amp;#034;] -&amp;gt; x] // &#xD;
        Flatten, &amp;#034;AllWords&amp;#034;];&#xD;
    nameList = speakerOrder // DeleteDuplicates;&#xD;
This code captures the speaker of each line, which allows us to split up the text into lines of the speakers. The sentences of each line correspond to the speaker of the line, and they are then split in preparation of individual sentiment analysis:&#xD;
&#xD;
    lines = StringSplit[&#xD;
         text // StringDelete[Shortest[&amp;#034;&amp;lt;i&amp;gt;&amp;#034; ~~ x__ ~~ &amp;#034;&amp;lt;/i&amp;gt;&amp;#034;]] // &#xD;
          StringDelete[Shortest[&amp;#034;[&amp;#034; ~~ x__ ~~ &amp;#034;]&amp;#034;]], &#xD;
         Shortest[&amp;#034;&amp;lt;b&amp;gt;&amp;#034; ~~ x__ ~~ &amp;#034;&amp;lt;/b&amp;gt;&amp;#034;]] // &#xD;
        StringDelete[Shortest[&amp;#034;&amp;lt;&amp;#034; ~~ x___ ~~ &amp;#034;&amp;gt;&amp;#034;]] // Rest;&#xD;
    sentences = lines // TextSentences;&#xD;
    lineLength = Length /@ sentences;&#xD;
Determining the recipient of a sentiment requires making a few assumptions. The recipient of each sentence is initially set to the speaker of the previous line. Then, searching in the order of sentences, a character name within a sentence reassigns the sentiment to the corresponding character for that sentence and all the following sentences in the same line. Finally, the list of speakers for each sentence is directed to the list of recipients of each sentence. Searching for names can be accomplished as the following:&#xD;
&#xD;
    emphasis = &#xD;
      WordFrequency[Flatten[sentences], #, IgnoreCase -&amp;gt; True] &amp;amp; /@ &#xD;
       nameList;&#xD;
    diffRecipientPos = SortBy[Position[emphasis, _?Positive], Last];&#xD;
    &#xD;
&#xD;
Calculating the Health of Relationships&#xD;
---------------------------------------&#xD;
&#xD;
First, we complete sentiment analysis on each sentence:&#xD;
&#xD;
    feelings = &#xD;
      Classify[&amp;#034;Sentiment&amp;#034;, #, &amp;#034;Probabilities&amp;#034;] &amp;amp; /@ sentences // Flatten;&#xD;
&#xD;
Using individual sentiments to judge overall relationship health, I assumed that a large number of nonstandard probabilities indicate health, and the more numerous these probabilities are the more reflective they become of the relationship. Experimentally, I created a formula which punishes uncertainty, and rewards frequency:&#xD;
&#xD;
    {pos, neu, neg} = &#xD;
      Table[feelings[[i]][#], {i, 1, Length[feelings]}] &amp;amp; /@ {&amp;#034;Positive&amp;#034;, &#xD;
        &amp;#034;Neutral&amp;#034;, &amp;#034;Negative&amp;#034;};&#xD;
    negBias = Values[playConditions][[playNum]][[2]];&#xD;
    Health = (pos - negBias*neg)/(1 + neu);&#xD;
    sentenceHealth = {finalRules[[#]], Health[[#]]} &amp;amp; /@ &#xD;
       Range[Length[Health]];&#xD;
    sentenceHealthFormat = Cases[sentenceHealth, {#, _}] &amp;amp; /@ ruleList;&#xD;
    relationshipHealth = &#xD;
      Table[Mean[&#xD;
        Table[sentenceHealthFormat[[i]][[j]][[2]], {j, 1, &#xD;
          Length[sentenceHealthFormat[[i]]]}]], {i, 1, &#xD;
        Length[sentenceHealthFormat]}];&#xD;
    (* Incorporate Frequency into Health *)&#xD;
    freq = Table[&#xD;
       Length[sentenceHealthFormat[[i]]], {i, 1, &#xD;
        Length[sentenceHealthFormat]}];&#xD;
    freqMultiplier[x_] := (Log[x] + 2)/2;&#xD;
&#xD;
Generating the Relationship Graph&#xD;
---------------------------------&#xD;
&#xD;
The positive and negative tolerance values filter out neutral and conflicted sentiments. The calculated health of each relationship can be converted into a color ranging from red to green. Blending with gray allows one to more easily visualize health as brightness instead of color:&#xD;
&#xD;
    viableRel = &#xD;
      Position[relationshipHealthFinal, &#xD;
        x_ /; x &amp;gt; posTolerance || x &amp;lt; negTolerance] // Flatten;&#xD;
    relationshipHealthFinalExc = &#xD;
      Table[relationshipHealthFinal[[i]], {i, viableRel}];&#xD;
    viableFreq = Table[freq[[i]], {i, viableRel}];&#xD;
    relationshipColors = &#xD;
     Table[Blend[{Red, Gray, Green}, (i + 1)/2], {i, &#xD;
       relationshipHealthFinalExc}]&#xD;
    viableEdges = Table[ruleList[[i]], {i, viableRel}];&#xD;
    edgeColors = &#xD;
      Table[viableEdges[[i]] -&amp;gt; relationshipColors[[i]], {i, &#xD;
        Length[viableEdges]}];&#xD;
Producing a community graph plot illustrates clusters of characters with strong feelings toward each other (not necessarily positive): &#xD;
&#xD;
![Romeo and Juliet: Relationship Network Graph][1]&#xD;
&#xD;
Conclusion&#xD;
----------&#xD;
&#xD;
The necessity of a negativity bias suggests that the Wolfram sentiment classifier may have a positivity bias.&#xD;
Also, by human evaluation of the plays and the respective relationship network graphs, Shakespearean works appear to generate the most accurate graphs. This may be due to the text structure of the different time periods: perhaps using sentiment analysis on each sentence was too large of a unit for Greek plays that employ long, winding sentences, and too small for modern plays that utilize rapid, stichomythic dialogue and interjections.&#xD;
&#xD;
Extension&#xD;
---------&#xD;
&#xD;
As such, the size of the text used for each calculation of sentiment could be a function of sentence length. Additionally, setting the values for health parameters can be automated. Furthermore, one could handle the cases of having multiple recipients for a sentiment. The most difficult avenue, though perhaps the most fruitful, would be to catch pronouns, aliases, and titles and assign them to the proper recipient. Once completed, a novel can be analyzed by using a similar process to determine the speaker in addition to the recipient of a particular sentiment.&#xD;
&#xD;
&#xD;
  [1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=RomeoJuliet0.png&amp;amp;userId=1724914</description>
    <dc:creator>Jason Zeng</dc:creator>
    <dc:date>2019-07-12T02:06:25Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/2964488">
    <title>[WSRP23] Developing pathfinding algorithms with exclusively right turns</title>
    <link>https://community.wolfram.com/groups/-/m/t/2964488</link>
    <description>![Comparison of Routes Within Washington D.C.][1]&#xD;
&#xD;
&amp;amp;[Wolfram Notebook][2]&#xD;
&#xD;
&#xD;
  [1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=7.13.23TitleImage.PNG&amp;amp;userId=2964405&#xD;
  [2]: https://www.wolframcloud.com/obj/244e570a-362b-4c38-b265-56e5db82de19</description>
    <dc:creator>Ryan Tong</dc:creator>
    <dc:date>2023-07-13T21:39:54Z</dc:date>
  </item>
  <item rdf:about="https://community.wolfram.com/groups/-/m/t/1382524">
    <title>[WSC18] Relationships between Wolfram language functions</title>
    <link>https://community.wolfram.com/groups/-/m/t/1382524</link>
    <description>![WordCloud.][1]&#xD;
&#xD;
This is a word cloud of the frequencies of the most common mathematica functions.&#xD;
&#xD;
#Introduction&#xD;
The purpose of this project was to scrape the example data from the [Wolfram Language Documentation Center][2]  and to retrieve function names from the cells, for analysis. This included looking at functions that were commonly used together, factoring a weighting system similar to TF IDF where the more a term appears overall, it has less value, and as a result, function use is balanced out accordingly. Also, a community graph plot was made, visualising connection across various functions, and attempts to group functions that have similar links, with some exciting results.&#xD;
&#xD;
#Retrieving the Data&#xD;
Since the documentation lies within the file explorer, they can be found and imported with the following code:&#xD;
&#xD;
    files = FileNames[&amp;#034;*&amp;#034;, &#xD;
      FileNameJoin@{$InstallationDirectory, &amp;#034;Documentation&amp;#034;, &amp;#034;English&amp;#034;, &#xD;
        &amp;#034;System&amp;#034;, &amp;#034;ReferencePages&amp;#034;, &amp;#034;Symbols&amp;#034;}];&#xD;
&#xD;
The data must then be refined and processed with a function that imports the cells, deletes image cases (this is because they tamper with the list value) and hold the function to ensure it does not evaluation like so:&#xD;
&#xD;
    getSymbolData[notebook_] :=&#xD;
     Module[{expressions, &#xD;
       noImages},(*Defines expressions and noImages locally*)&#xD;
      expressions = &#xD;
       NotebookImport[notebook, &#xD;
        &amp;#034;Input&amp;#034; -&amp;gt; &#xD;
         &amp;#034;HeldExpression&amp;#034;]; (*Imports one given notebook by it&amp;#039;s \&#xD;
    directory*)&#xD;
      noImages = &#xD;
       DeleteCases[expressions, HoldPattern[Image[_RawArray, ___]], &#xD;
        Infinity];(*Remove images so they don&amp;#039;t clutter the list data*)&#xD;
      &#xD;
      (*Counts up functions used inside other functions e.g Plot[Sin]*)&#xD;
      Counts@Flatten@Cases[&#xD;
         noImages,&#xD;
         (f_Symbol)[args : (_Symbol[___]) ..] :&amp;gt;&#xD;
          Cases[ &#xD;
           HoldComplete[args], (g_Symbol)[___] :&amp;gt; HoldComplete[f, g]],&#xD;
         {2, Infinity}]]&#xD;
&#xD;
With this, we can introduce functions that seek lists in the form {symbol1,symbol2) and scan across every function to create a graph of relations.&#xD;
&#xD;
    MutualFunctionUse[sym1_, sym2_, functset_] :=&#xD;
     Cases[functset, {{sym1, If[sym2 == &amp;#034;&amp;#034;, _String, sym2]}, _Integer}]&#xD;
And further shorten the data by selecting the functions that appear the most with the specified function.&#xD;
![Tada!][3]&#xD;
&#xD;
# Visualization&#xD;
&#xD;
The data above can be easily manipulated into a graph with the edge weighting being the second item in the main list and the edge connection being the first connection.&#xD;
&#xD;
    functionGraph[x_, n_, functset_] :=&#xD;
     Module[{edges, edgelabels, sizes, mutualfunctions, graph, finished},&#xD;
      mutualfunctions = functiongather[x, functset, n];&#xD;
      edges = &#xD;
       Thread[mutualfunctions[[1 ;;, 1, 1]] \[UndirectedEdge] &#xD;
         mutualfunctions[[1 ;;, 1, 2]]];&#xD;
      edgelabels = &#xD;
       Thread[Thread[&#xD;
          mutualfunctions[[1 ;;, 1, 1]] \[UndirectedEdge] &#xD;
           mutualfunctions[[1 ;;, 1, 2]]] -&amp;gt; mutualfunctions[[1 ;;, 2]]];&#xD;
      finished = &#xD;
       Thread[Part[edgelabels, All, 1] -&amp;gt; &#xD;
         Evaluate@(Placed[#, Tooltip] &amp;amp; /@ (Part[edgelabels, All, 2]))];&#xD;
      sizes = &#xD;
       Append[Thread[&#xD;
         Evaluate@mutualfunctions[[1 ;;, 1, 2]] -&amp;gt; (#*0.1 &amp;amp;) /@ &#xD;
           Floor /@ &#xD;
            Log /@ Evaluate@(SymbolFreq[#] &amp;amp; /@ &#xD;
                mutualfunctions[[1 ;;, 1, 2]])], &#xD;
        x -&amp;gt; 0.1*Floor@Log@SymbolFreq[x]];&#xD;
      &#xD;
      graph = &#xD;
       Graph[edges, VertexLabels -&amp;gt; Placed[&amp;#034;Name&amp;#034;, Center], &#xD;
        VertexSize -&amp;gt; sizes, EdgeLabels -&amp;gt; finished, Background -&amp;gt; White, &#xD;
        ImageSize -&amp;gt; Full, &#xD;
        EdgeWeight -&amp;gt; Flatten@mutualfunctions[[All, 2]]];&#xD;
      {CommunityGraphPlot[graph], &#xD;
       MatrixPlot[WeightedAdjacencyMatrix[graph]]}&#xD;
      &#xD;
       ]&#xD;
&#xD;
Most of the code above is for visual effects, such as a tooltip that appears when hovering over the graph. Most of the threading is done to describe the process before, just to connect it in the form symbol1 - symbol2 -&amp;gt; edgeWeight and the sizes were all processed through the logarithm function followed by a multiplication of 0.1 to scale nodes to size. The parameters functset is used for convenience, for example, if the user inputted a filtered version without incredibly common functions such as List to pollute the pool, it would return a different graph, and the n selects the top n used functions. The function also returns a weighted matrix plot of the graph, like a heat map which is hidden as the graph takes up the full window.&#xD;
Here is an example of function graph:&#xD;
![List is the primary function][4]&#xD;
&#xD;
The code can be further extended to process across several functions, joining to make a bigger community graph, revealing more relationships and communities like so:&#xD;
&#xD;
    allfunctionGraph[x_, functset_, n_] :=&#xD;
     Module[{edges, edgelabels, sizes, mutualfunctions, graph, finished},&#xD;
      mutualfunctions = functiongather[#, functset, n] &amp;amp; /@ x;&#xD;
      edges = &#xD;
       Thread[Flatten@mutualfunctions[[All, All, 1, 1]] \[UndirectedEdge] &#xD;
         Flatten@mutualfunctions[[All, All, 1, 2]]];&#xD;
      edgelabels = &#xD;
       Thread[Thread[(Flatten@&#xD;
             mutualfunctions[[All, All, 1, 1]] \[UndirectedEdge] &#xD;
            Flatten@mutualfunctions[[All, All, 1, 2]])] -&amp;gt; &#xD;
         Flatten@mutualfunctions[[All, All, 2]]];&#xD;
      finished = &#xD;
       Thread[Part[edgelabels, All, 1] -&amp;gt; &#xD;
         Evaluate@(Placed[#, Tooltip] &amp;amp; /@ (Part[edgelabels, All, 2]))];&#xD;
      sizes = &#xD;
       Append[Thread[&#xD;
         Evaluate@Flatten@mutualfunctions[[All, All, 1, 2]] -&amp;gt; (#*0.1 &amp;amp;) /@&#xD;
            Floor /@ &#xD;
            Log /@ Evaluate@(SymbolFreq[#] &amp;amp; /@ &#xD;
                Flatten@mutualfunctions[[All, All, 1, 2]])], &#xD;
        Thread[x -&amp;gt; 0.1*Floor /@ (Log /@ (SymbolFreq /@ x))]];&#xD;
      graph = &#xD;
       Graph[edges, VertexLabels -&amp;gt; Placed[&amp;#034;Name&amp;#034;, Tooltip], &#xD;
        VertexSize -&amp;gt; sizes, EdgeLabels -&amp;gt; finished, Background -&amp;gt; White, &#xD;
        ImageSize -&amp;gt; Full, &#xD;
        EdgeWeight -&amp;gt; Flatten@mutualfunctions[[All, All, 2]]];&#xD;
      {CommunityGraphPlot[graph], &#xD;
       MatrixPlot[WeightedAdjacencyMatrix[graph], ImageSize -&amp;gt; Full]}&#xD;
       ]&#xD;
&#xD;
The above code is just a generalization of the first function, with list processing being added to accommodate for the list of inputs. While there are no labels, function names and connections appear as one hovers over an edge/node. &#xD;
&#xD;
![More function graph][5]&#xD;
 &#xD;
The final visualization is a weighted bar chart that takes in a function and returns a bar chart with weighted values, which is the quotient of the function&amp;#039;s frequency with the specified functions and the functions general frequency across all cells. The weighting system is simple at this stage but can be improved to further avoid symbols such as List or Power polluting the sample space.&#xD;
&#xD;
![Last one][6]&#xD;
&#xD;
#Errors and alternative pathways&#xD;
Many of the issues faced were time complexity related, with inappropriate sorting algorithms being utilized which unintentionally increased the runtime far more than should be expected, for example the initial algorithm would run in a time approximately cubed to the input but could be easily optimized to run in quadratic time, which could have the potential to reduce the run time from 50 minutes to less than a minute. The unoptimized algorithm was the primary bottleneck, as importing over 5146 files with an optimized algorithm would be inefficient and would become useless if the model were to take in a larger data set from other websites or files. &#xD;
&#xD;
#Conclusion &amp;amp; Future Work&#xD;
The data-set used was small, and intentionally designed as examples, which led to much more to be desired. Other sources of function usage such as the Mathematica StackExchange or wolfram alpha would greatly expand the database and also allow for more detail graphs. This is a small stepping stone to a bigger project which entails using machine learning to register user input to understand what function they want to use, and the graph provided has insight into navigating through keywords and the desired function. Credit to Richard Hennigan for providing the scraped data and assisting me with the project.&#xD;
&#xD;
Github link to the notebook:&#xD;
https://github.com/Theorvolt/CommonlyPairedWolframFunctions&#xD;
    &#xD;
&#xD;
&#xD;
  [1]: http://community.wolfram.com//c/portal/getImageAttachment?filename=yeet.png&amp;amp;userId=1372480&#xD;
  [2]: http://reference.wolfram.com/language/&#xD;
  [3]: http://community.wolfram.com//c/portal/getImageAttachment?filename=example1.PNG&amp;amp;userId=1372480&#xD;
  [4]: http://community.wolfram.com//c/portal/getImageAttachment?filename=example2.PNG&amp;amp;userId=1372480&#xD;
  [5]: http://community.wolfram.com//c/portal/getImageAttachment?filename=example3.PNG&amp;amp;userId=1372480&#xD;
  [6]: http://community.wolfram.com//c/portal/getImageAttachment?filename=despa3to.PNG&amp;amp;userId=1372480</description>
    <dc:creator>Sai kumar Murali krishnan</dc:creator>
    <dc:date>2018-07-13T13:39:07Z</dc:date>
  </item>
</rdf:RDF>

