Wolfram Blog×ò., 16 àâã. News, views, and ideas from the front lines at Wolfram Research. | ||||||||||||||||||||||||||||||||||||||||||||||

1. Former Astronaut Creates Virtual Copilot with Wolfram Neural Nets and a Raspberry Pi×ò., 16 àâã.[−]
2. Citizen Data Science with Civic Hacking: The Safe Drinking Water Data Challenge×ò., 09 àâã.[−]
Now with some setup out of the way (this can be tedious, but it’s important to stay organized and efficient!), we can generate some graphics:
So we again used We can see some of the values are flat along the x axis. Let’s take a look at the range of values in our variables and see if we can improve upon this:
We can see that the penalty rate has a massively higher maximum value than our other variables. So what should we do? Well, we can log the values and visualize them all in one go with
So it appears that the enforcement program didn’t really get into full force until sometime after 2015, and following preliminary actions, penalties started being issued on a massive scale. Penalty-related actions appear to also increase during summer months, perhaps when production is higher, something we’ll examine and confirm a little later. Let’s look at warnings, follow-ups and complaints on their own:
We used similar code to the previous graphic, but this time we left out our defined style and used
We see a strong pattern here of complaints, warnings and follow-ups occurring in tandem, something not all too surprising but that might indicate the effectiveness of reporting systems. ## Agriculture and Weather DataSo far, we’ve looked at one city and just a few variables in exploratory analysis. Let’s shift gears and take a look at agriculture. We can grab another dataset in the Wolfram Data Repository to very quicky visualize agricultural land use with a small chunk of code:
We can also visualize agricultural land use a different way using
Between these two visualizations, we can clearly see California’s central valley has the highest levels of agricultural land use. Now let’s use our
So for the last reporting month, we see the Rancho California Water District has the highest amount of agricultural water use. Let’s see if we can find out where in California that is by using
Looking at the first link, we can see that the water district serves the city of Temecula, portions of the city of Murrieta and Vail Lake. One of the most convenient features of the Wolfram Language is the knowledge that’s built directly into the language. (There’s a nice Wolfram U training course about the Wolfram Data Framework you can check out here.) Let’s grab a map and a satellite image to see what sort of terrain we’re dealing with:
This looks fairly rural and congruent with our data showing higher levels of agricultural water use, but this is interestingly enough not in the central valley where agricultural land use is highest, something to perhaps note for future exploration and examination. Let’s now use
We can also grab water production and agricultural use for the district and see if we have any correlations going on with weather and water use—a fairly obvious guess, but it’s always nice to show something with data. Let’s go ahead and define a legend variable first:
We’ve logged some values here, but we could also manually rescale to get a better sense of the comparisons:
And we can indeed see some dips in water production and agricultural use when rainfall increases, indicating that both usage and production are inversely correlated with rainfall and, by definition, usage and production are correlated with one another. ## Machine Learning for ClassificationOne variable that might be useful to examine in the dataset is whether or not a district is under mandatory restrictions on outdoor irrigation. Let’s use
We’ll now build a classifier with the outcome variable defined as mandatory restrictions:
We have a classifier function returned, and the Wolfram Language automatically chose But let’s take a closer look at what our automated model selection came up with using
We get back a general description of the algorithm chosen and can see the learning curves for each algorithm, indicating why gradient boosted trees was the best fit. Let’s now use
Ninety-three percent is acceptable for our purposes in exploring this dataset. We can now generate a plot to see what the rejection threshold is for achieving a higher accuracy in case we want to think about improving upon that:
And let’s pull up the classifier’s confusion matrix to see what we can glean from it:
It looks like the classifier could be improved for predicting
Again, not too terrible with predicting that at a certain point in time a given location will be under mandatory restrictions for outdoor irrigation based on the features in our dataset. As an additional line of inquiry, we could use So far, we’ve looked at some of the top water-producing districts, areas with high penalty rates and how other enforcement measures compare, the impact of rainfall on agricultural water use with some built-in data and how we might predict what areas will fall under mandatory restrictions on outdoor irrigation—a nice starting point for further explorations. ## Try It for YourselfThink you’re up for the Safe Drinking Water Data Challenge? Try it out for yourself! You can send an email to partner-program@wolfram.com and mention the Safe Drinking Water Data Challenge in the subject line to get a license to Wolfram|One. You can also access an abundance of free training resources for data science and statistics at Wolfram U. In case you get stuck, you can check out the following resources, or go over to Wolfram Community and make sure to post your analysis there as well. Additional resources: - Dataset: Periodic Groundwater Level Measurements
- Dataset: California Crop Mapping
- An Elementary Introduction to the Wolfram Language (full interactive course)
- “ Launching the Wolfram Neural Net Repository”
- “ Building the Automated Data Scientist: The New Classify and Predict”
- “ Web Scraping with the Wolfram Language, Part 1: Importing and Interpreting”
- “ How Optimistic Do You Want to Be? Bayesian Neural Network Regression with Prediction Errors”
We look forward to seeing what problems you can solve with some creativity and data science with the Wolfram Language. Download this post as a Wolfram Notebook.Êîììåíòàðèè (0) | ↑ |

3. **Computational Exploration of the Mathematics Genealogy Project in the Wolfram Language**×ò., 02 àâã.[−]

The Mathematics Genealogy Project (MGP) is a project dedicated to the compilation of information about all mathematicians of the world, storing this information in a database and exposing it via a web-based search interface. The MGP database contains more than 230,000 mathematicians as of July 2018, and has continued to grow roughly linearly in size since its inception in 1997. In order to make this data more accessible and easily computable, we created an internal version of the MGP data using the Wolfram Language’s entity framework. Using this dataset within the Wolfram Language allows one to easily make computations and visualizations that provide interesting and sometimes unexpected insights into mathematicians and their works. Note that for the time being, these entities are defined only in our private dataset and so are not (yet) available for general use. The search interface to the MGP is illustrated in the following image. It conveniently allows searches based on a number of common fields, such as parts of a mathematician’s name, degree year, Mathematics Subject Classification (MSC) code and so on: For a quick look at the available data from the MGP, consider a search for the prolific mathematician Paul Erd?s made by specifying his first and last names in the search interface. It gives this result: Clicking the link in the search result returns a list of available data: Note that related mathematicians (i.e. advisors and advisees) present in the returned database results are hyperlinked. In contrast, other fields (such as school, degree years and so on), are not. Clearly, the MGP catalogs a wealth of information of interest to anyone wishing to study the history of mathematicians and mathematical research. Unfortunately, only relatively simple analyses of the underlying data are possible using a web-based search interface. Explore Mathematicians For those readers not familiar with the Wolfram Language entity framework, we begin by giving a number of simple examples of its use to obtain information about the "MGPPerson" entities we created. As a first simple computation, we use the EntityValue function to obtain a count of the number of people in the "MGPPerson" domain: #10005 EntityValue["MGPPerson","EntityCount"] Note that this number is smaller than the 230,000+ present in the database due to subsequent additions to the MGP. Similarly, we can return a random person: #10005 person=RandomEntity["MGPPerson"] Mousing over an “entity blob” such as in the previous example gives a tooltip showing the underlying Wolfram Language representation. We can also explicitly look at the internal structure of the entity: #10005 InputForm[person] Copying, pasting and evaluating that expression to obtain the formatted version again: #10005 Entity["MGPPerson","94172"] We now extract the domain, canonical name and common name of the entity programmatically: #10005 Through[{EntityTypeName,CanonicalName,CommonName}[person]]//InputForm We can simultaneously obtain a set of random people from the "MGPPerson" domain: #10005 RandomEntity["MGPPerson",10] To obtain a list of properties available in the "MGPPerson" domain, we again use EntityValue: #10005 properties=EntityValue["MGPPerson","Properties"] As we did for entities, we can view the internal structure of the first property: #10005 InputForm[First[properties]] We can also view the string of canonical names of all the properties: #10005 CanonicalName[properties] The URL to the relevant MGP page is available directly as its own property, which can be done concisely as: #10005 EntityValue[person,"MathematicsGenealogyProjectURL"] with an explicit EntityProperty wrapper: #10005 EntityValue[person,EntityProperty["MGPPerson","MathematicsGenealogyProjectURL"]] or using a curried syntax: #10005 person["MathematicsGenealogyProjectURL"] We can also return multiple properties: #10005 person[{"AdvisedBy","Degrees","DegreeDates","DegreeSchoolEntities"}] Another powerful feature of the Wolfram Language entity framework is the ability to create an implicitly defined Entity class: #10005 EntityClass["MGPPerson","Surname"->"Nelson"] Expanding this class, we obtain a list of people with the given surname: #10005 SortBy[EntityList[EntityClass["MGPPerson","Surname"->"Nelson"]],CommonName] To obtain an overview of data for a given person, we can copy and paste from that list and query for the "Dataset" property using a curried property syntax: #10005 Entity["MGPPerson", "174871"]["Dataset"] As a first simple computation, we use the Wolfram Language function NestGraph to produce a ten-generation-deep mathematical advisor tree for mathematician Joanna “Jo” Nelson: #10005 NestGraph[#["AdvisedBy"] ,Entity["MGPPerson", "174871"],10,VertexLabels->Placed["Name",After,Rotate[#,30 Degree,{-3.2,0}] ]] Using an implicitly defined EntityClass, let’s now look up people with the last name “Hardy”: #10005 EntityList[EntityClass["MGPPerson","Surname"->"Hardy"]] Having found the Hardy we had in mind, it is now easy to make a mathematical family tree for the descendants of G. H. Hardy, highlighting the root scholar: #10005 With[{scholar=Entity["MGPPerson", "17806"]}, HighlightGraph[ NestGraph[#["Advised"] ,scholar,2,VertexLabels->Placed["Name",After,Rotate[#,30 Degree,{-3.2,0}] ],ImageSize->Large,GraphLayout->"RadialDrawing"], scholar] ] A fun example of the sort of computation that can easily be performed using the Wolfram Language is visualizing the distribution of mathematicians based on first and last initials: #10005 Histogram3D[Select[Flatten[ToCharacterCode[#]] /@Map[RemoveDiacritics@StringTake[#,1] ,DeleteMissing[EntityValue["MGPPerson",{"GivenName","Surname"}],1,2],{2}],(65Automatic] We can now make a fit to the number of new PhD mathematicians over the period 1875–1975: #10005 fit=Fit[Select[{#1["Year"],1. Log[2,#2]} @@@phddata,1875"Year"] Now look at the national distribution of degrees awarded. Begin by again examining the structure of the data. In particular, there exist PhD theses with no institution specified in "SchoolEntity" but a country specified in "SchoolLocation": #10005 TextGrid[Take[Cases[phds=EntityValue["MGPDegree",{"Entity","DegreeType","SchoolEntity","SchoolLocation"}],{_,"Ph.D.",_Missing,_List}],5],Dividers->All] There also exist theses with more than a single country specified in "SchoolLocation": #10005 TextGrid[Cases[phds,{_,"Ph.D.",_Missing,_List?(Length[#]!=1 )}],Dividers->All] Tally the countries (excluding the pair of multiples): #10005 TextGrid[Take[countrytallies=Reverse@SortBy[Tally[Cases[phds,{_,"Ph.D.",_,{c_Entity}}:>c]],Last],UpTo[10]],Alignment->{{Left,Decimal}},Dividers->All] A total of 117 countries are represented: #10005 Length[countrytallies] Download flag images for these countries from the Wolfram Knowledgebase: #10005 Take[flagdata=Transpose[{EntityValue[countrytallies[[All,1]],"Flag"],countrytallies[[All,2]]}],5] Create an image collage of flags, with the flags sized according to the number of math PhDs: #10005 ImageCollage[Take[flagdata,40],ImagePadding->3] As another example, we can explore degrees awarded by a specific university. For example, extract mathematics degrees that have been awarded at the University of Miami since 2010: #10005 Length[umiamidegrees=EntityList[ EntityClass["MGPDegree",{ "SchoolEntity"->Entity["University", "UniversityOfMiami::9c2k9"], "Date"-> GreaterEqualThan[DateObject[{2010}]]} ]]] Create a timeline visualization: #10005 TimelinePlot[Association/@Rule@@@EntityValue[umiamidegrees,{"Advisee","Date"}],ImageSize->Large] Now consider recent US mathematics degrees. Select the theses written at US institutions since 2000: #10005 Length[USPhDs=Cases[Transpose[{ EntityList["MGPDegree"], EntityValue["MGPDegree","SchoolLocation"], EntityValue["MGPDegree","Date"] }], { th_, loc_?(ContainsExactly[{Entity["Country", "UnitedStates"]}]),DateObject[{y_?(GreaterEqualThan[2000])},___] }:>th ]] Make a table showing the top US schools by PhDs conferred: #10005 TextGrid[Take[schools=Reverse[SortBy[Tally[Flatten[EntityValue[USPhDs,"SchoolEntity"]]],Last]],12],Alignment->{{Left,Decimal}},Dividers->All] Map schools to their geographic positions: #10005 geopositions=Rule@@@DeleteMissing[Transpose[{EntityValue[schools[[All,1]],"Position"],schools[[All,2]]}],1,2]; Visualize the geographic distribution of US PhDs : #10005 GeoBubbleChart[geopositions,GeoRange->Entity["Country", "UnitedStates"]] Show mathematician thesis production as a smooth kernel histogram over the US: #10005 GeoSmoothHistogram[Flatten[Table[#1,{#2}] @@@geopositions],"Oversmooth",GeoRange->GeoVariant[Entity["Country", "UnitedStates"],Automatic]] Explore Thesis Titles We now make some explorations of the titles of mathematical theses. To begin, extract theses authored by people with the surname “Smith”: #10005 Length[smiths=EntityList[EntityClass["MGPPerson","Surname"->"Smith"]]] Create a WordCloud of words in the titles: #10005 WordCloud[DeleteStopwords[StringRiffle[EntityValue[DeleteMissing[Flatten[EntityValue[smiths,"Degrees"]]],"ThesisTitle"]]]] Now explore the titles of all theses (not just those written by Smiths) by extracting thesis titles and dates: #10005 tt=DeleteMissing[EntityValue["MGPDegree",{"Date","ThesisTitle"}],1,2]; The average string length of a thesis is remarkably constant over time: #10005 DateListPlot[{#[[1,1]],Round[Mean[StringLength[#[[All,-1]]]]]} /@SplitBy[Sort[tt],First], PlotRange->{DateObject[{#}] /@{1850,2010},All}] The longest thesis title on record is this giant: #10005 SortBy[tt,StringLength[#[[2]]] ]//Last Motivated by this, extract explicit fragments appearing in titles: #10005 tex=Cases[ImportString[#,"TeX"] /@Flatten[DeleteCases[StringCases[#2,Shortest["$"~~___~~"$"]] @@@tt,{}]],Cell[_,"InlineFormula",___],?]//Quiet; ... and display them in a word cloud: #10005 WordCloud[DisplayForm/@tex] Extract types of topological spaces mentioned in thesis titles and display them in a ranked table: #10005 TextGrid[{StringTrim[#1],#2} @@@Take[Select[Reverse[SortBy[Tally[Flatten[DeleteCases[StringCases[#2,Shortest[" ",((LetterCharacter|"_")..)~~(" space"|"Space ")]] @@@tt,{}]]],Last]], Not[StringMatchQ[#[[1]],(" of " | " in " |" and "|" the " | " on ")~~__]] ],12],Dividers->All,Alignment->{{Left,Decimal}}] Explore Mathematical Subjects Get all available Mathematics Subject Classification (MSC) category descriptions for mathematics degrees conferred by the University of Oxford and construct a word cloud from them: #10005 WordCloud[DeleteMissing[EntityValue[EntityList[EntityClass["MGPDegree","SchoolEntity"->Entity["University", "UniversityOfOxford::646mq"]]],"MSCDescription"]],ImageSize->Large] Explore the MSC distribution of recent theses. To begin, Iconize a list to use that holds MSC category names that will be used in subsequent examples: #10005 mscnames=List; Extract degrees awarded since 2010: #10005 Length[degrees2010andlater=Cases[Transpose[{EntityList["MGPDegree"],EntityValue["MGPDegree","Date" ]}],{th_,DateObject[{y_?(GreaterEqualThan[2010])},___]}:>th]] Extract the corresponding MSC numbers: #10005 degreeMSCs=DeleteMissing[EntityValue[degrees2010andlater,"MSCNumber"]]; Make a pie chart showing the distribution of MSC category names and numbers: #10005 With[{counts=Sort[Counts[degreeMSCs],Greater][[;;20]]},PieChart[Values[counts],ChartLegends->(Row[{#1,": ",#2," (",#3,")"}] @@@(Flatten/@Partition[Riffle[Keys@counts,Partition[Riffle[(Keys@counts/.mscnames),ToString/@Values@counts],2]],2])),ChartLabels->Placed[Keys@counts,"RadialCallout"],ChartStyle->24,ImageSize->Large]] Extract the MSC numbers for theses since 1990 and tally the combinations of {year, MSC}: #10005 msctallies=Tally[Sort[Cases[DeleteMissing[EntityValue["MGPDegree",{"Date","MSCNumber"}],1,2], {DateObject[{y_?(GreaterEqualThan[1990])},___],msc_}:>{y,msc}]]] Plot the distribution of MSC numbers (mouse over the graph in the attached notebook to see MSC descriptions): #10005 Graphics3D[With[{y=#[[1]],msc=ToExpression[#[[2]]],off=1/3},Tooltip[Cuboid[{msc-off,y-off,0},{msc+off,y+off,#2}], #[[2]]/.mscnames]] @@@msctallies,BoxRatios->{1,1,0.5},Axes->True, AxesLabel->{"MSC","year","thesis count"},Ticks->{None,Automatic,Automatic}] Most students do research in the same area as their advisors. Investigate systematic transitions from MSC classifications of advisors’ works to those of their students. First, write a utility function to create a list of MSC numbers for an advisor’s degrees and those of each advisee: #10005 msctransition[person_]:=Module[{msc="MSCNumber",d="Degrees",advisormsc,adviseemscs,dm=DeleteMissing}, advisormsc=#[msc] /@person[d]; adviseemscs=#[msc] /@Flatten[#[d] /@dm[Flatten[{person["Advised"]}]]]; dm[{advisormsc,{#}} /@DeleteCases[adviseemscs,Alternatives@@advisormsc],1,2]] For example, for Maurice Fr?chet: #10005 TextGrid[msctransition[Entity["MGPPerson", "17947"]]/.mscnames,Dividers->All] Find MSC transitions for degree dates after 1988: #10005 transitiondata=msctransition/@Select[DeleteMissing[ EntityValue["MGPPerson",{"Entity","DegreeDates"}],1,2],Min[#["Year"] /@#[[2]]] 1988 ][[All,1]]; #10005 transitiondataaccumulated=Tally[Flatten[Apply[Function[{a,b},Outer[DirectedEdge,a,b]], Flatten[Take[transitiondata,All],1],{1}],2]]/.mscnames; #10005 toptransitions=Select[transitiondataaccumulated,Last[#]>10 ]/.mscnames; #10005 Grid[Reverse[Take[SortBy[transitiondataaccumulated,Last],-10]],Dividers->Center,Alignment->Left] #10005 msctransitiongraph=Graph[First/@toptransitions,EdgeLabels->Placed["Name",Tooltip],VertexLabels->Placed["Name",Tooltip],GraphLayout->"HighDimensionalEmbedding"]; #10005 With[{max=Max[Last/@toptransitions]}, HighlightGraph[msctransitiongraph,Style[#1,Directive[Arrowheads[0.05(#2/max)^.5],ColorData["DarkRainbow"][(#2/max)^6.],Opacity[(#2/max)^.5],Thickness[0.005(#2/max)^.5]]] @@@transitiondataaccumulated]] Explore Advisors Construct a list of directed edges from advisors to their students: #10005 Length[advisorPairs=Flatten[Function[{a,as},DirectedEdge[a,#] /@as]@@@DeleteMissing[EntityValue["MGPPerson",{"Entity","Advised"}],1,2]]] Some edges are duplicated because the same student-advisor relationship exists for more than one degree: #10005 SelectFirst[Split[Sort[advisorPairs]],Length[#]>1 ] For example: #10005 (EntityValue[Entity["MGPPerson", "110698"],{"AdvisedBy","Degrees"}]/.e:Entity["MGPDegree",_]:>{e,e["DegreeType"]}) So build an explicit advisor graph by uniting the {advisor, advisee} pairs: #10005 advisorGraph=Graph[Union[advisorPairs],GraphLayout->None] The advisor graph contains more than 3,500 weakly connected components: #10005 Length[graphComponents=WeaklyConnectedGraphComponents[advisorGraph]] Visualize component sizes on a log-log plot: #10005 ListLogLogPlot[VertexCount/@graphComponents,Joined->True,Mesh->All,PlotRange->All] Find the size of the giant component (about 190,000 people): #10005 VertexCount[graphComponents[[1]]] Find the graph center of the second-largest component: #10005 GraphCenter[UndirectedGraph[graphComponents[[2]]]] Visualize the entire second-largest component: #10005 Graph[graphComponents[[2]],VertexLabels->"Name",ImageSize->Large] Identify the component in which David Hilbert resides: #10005 FirstPosition[VertexList/@graphComponents,Entity["MGPPerson", "7298"]][[1]] Show Hilbert’s students: #10005 With[{center=Entity["MGPPerson", "7298"]},HighlightGraph[Graph[Thread[center->AdjacencyList[graphComponents[[1]],center]],VertexLabels->"Name",ImageSize->Large],center]] As it turns out, the mathematician Gaston Darboux plays an even more central role in the advisor graph. Here is some detailed information about Darboux, whose 1886 thesis was titled “Sur les surfaces orthogonales”: #10005 Entity["MGPPerson", "34254"] ["PropertyAssociation"] And here is a picture of Darboux: #10005 Show[WikipediaData["Gaston Darboux","ImageList"]//Last,ImageSize->Small] Many mathematical constructs are named after Darboux: #10005 Select[EntityValue["MathWorld","Entities"],StringMatchQ[#[[2]],"*Darboux*"] ] ... and his name can even be used in adjectival form: #10005 StringCases[Normal[WebSearch["Darbouxian *",Method -> "Google"][All,"Snippet"]], "Darbouxian"~~" " ~~(LetterCharacter ..)~~" " ~~(LetterCharacter ..)]//Flatten//DeleteDuplicates // Column Many well-known mathematicians are in the subtree starting at Darboux. In particular, in the directed advisor graph we find a number of recent Fields Medal winners. Along the way, we also see many well-known mathematicians such as Laurent Schwartz, Alexander Grothendieck and Antoni Zygmund: #10005 {path1,path2,path3,path4}=(DirectedEdge@@@Partition[FindShortestPath[graphComponents[[1]],Entity["MGPPerson", "34254"],#],2,1]) /@ {Entity["MGPPerson", "13140"],Entity["MGPPerson", "22738"],Entity["MGPPerson", "43967"],Entity["MGPPerson", "56307"]} Using the data from the EntityStore, we build the complete subgraph starting at Darboux: #10005 adviseeedges[pList_]:=Flatten[Function[p,DirectedEdge[Last[p],#] /@ DeleteMissing[Flatten[{Last[p][advised]}]]]/@pList] #10005 advgenerations=Rest[NestList[adviseeedges,{Null->Entity["MGPPerson", "34254"]},7]]; #10005 alladv=Flatten[advgenerations]; It contains more than 14,500 mathematicians: #10005 Length[Union[Cases[alladv,_Entity,?]]]-1 Because it is a complicated graph, we display it in 3D to avoid overcrowded zones. Darboux sits approximately in the center: #10005 gr3d=Graph3D[alladv,GraphLayout->"SpringElectricalEmbedding"] We now look at the degree centrality of the nodes of this graph in a log-log plot: #10005 ListLogLogPlot[Tally[DegreeCentrality[gr3d]]] Let’s now highlight the path to that plot for Fields Medal winners: #10005 style[path_,color_]:=Style[#,color,Thickness[0.004]] /@path #10005 HighlightGraph[gr3d, Join[{Style[Entity["MGPPerson", "34254"],Orange,PointSize[Large]]}, style[path1,Darker[Red]],style[path2,Darker[Yellow]],style[path3,Purple], style[path4,Darker[Green]]]] Geographically, Darboux’s descendents are distributed around the whole world: #10005 makeGeoPath[e1_?e2_] := With[{s1=e1["DegreeSchoolEntities"],s2=e2["DegreeSchoolEntities"],d1=e1["DegreeDates"],d2=e2["DegreeDates"],color=ColorData["DarkRainbow"][(Mean[{#1[[1,1,1]],#2[[1,1,1]]}]-1870)/150] }, If[MemberQ[{s1,s2,d1,d2},_Missing,?]||s1===s2,{},{Thickness[0.001],color[d1,d2],Arrowheads[0.012],Tooltip[Arrow[GeoPath[{s1[[1]],s2[[1]]}]], Grid[{{"","advisor","advisee"},{"name",e1,e2},Column/@{{"school"},s1,s2}, Column/@{{"degree date"},d1,d2}},Dividers->Center]]}]] Here are the paths from the advisors’ schools to the advisees’ schools after four and six generations: #10005 GeoGraphics[makeGeoPath/@Flatten[Take[advgenerations,4]],GeoBackground->"StreetMapNoLabels",GeoRange->"World"]//Quiet #10005 GeoGraphics[makeGeoPath /@ Flatten[Take[advgenerations, 6]], GeoBackground -> "StreetMapNoLabels", GeoRange -> "World"] // Quiet Distribution of Intervals between the Date at Which an Advisor Received a PhD and the Date at Which That Advisor's First Student's PhD Was Awarded Extract a list of advisors and the dates at which their advisees received their PhDs: #10005 Take[AdvisorsAndStudentPhDDates=SplitBy[Sort[Flatten[Thread/@Cases[EntityValue["MGPDegree",{"Advisors","DegreeType","Date"}],{l_List,"Ph.D.",DateObject[{y_},___]}:>{l,y}],1]],First],5] This list includes multiple student PhD dates for each advisor, so select the dates of the first students’ PhDs only: #10005 Take[AdvisorsAndFirstStudentPhDDates=DeleteCases[{#[[1,1]],Min[DeleteMissing[#[[All,2]]]]} /@AdvisorsAndStudentPhDDates,{_,Infinity}],10] Now extract a list of PhD awardees and the dates of their PhDs: #10005 Take[PhDAndDates=DeleteCases[Sort[Cases[EntityValue["MGPDegree",{"Advisee","DegreeType","Date"}],{p_,"Ph.D.",DateObject[{y_},___]}:>{p,y}]],{_Missing,_}],10] Note that some advisors have more than one PhD: #10005 Select[SplitBy[PhDAndDates,First],Length[#]>1 ]//Take[#,5] //Column For example: #10005 Entity["MGPPerson", "100896"]["Degrees"] ... who has these two PhDs: #10005 EntityValue[%,{"Date","DegreeType","SchoolName"}] While having two PhDs is not unheard of, having three is unique: #10005 Tally[Length/@SplitBy[PhDAndDates,First]] In particular: #10005 Select[SplitBy[PhDAndDates,First],Length[#]===3 ] Select the first PhDs of advisees and make a set of replacement rules to their first PhD dates: #10005 Take[FirstPhDDateRules=Association[Thread[Rule@@@SplitBy[PhDAndDates,First][[All,1]]]],5] Now replace advisors by their first PhD years and subtract from the year of their first students’ PhDs: #10005 Take[times=-Subtract@@@(AdvisorsAndFirstStudentPhDDates/.FirstPhDDateRules),10] The data contains a small number of discrepancies where students allegedly received their PhDs prior to their advisors: #10005 SortBy[Select[Transpose[{AdvisorsAndFirstStudentPhDDates[[All,1]],AdvisorsAndFirstStudentPhDDates/.FirstPhDDateRules}],GreaterEqual@@#[[2]] ],-Subtract@@#[[2]] ]//Take[#,10] Removing these problematic points and plotting a histogram reveals the distribution of years between advisors’ and first advisees’ PhDs: #10005 Histogram[Cases[times,_?Positive]] We hope you have found this computational exploration of mathematical genealogy of interest. We thank Mitch Keller and the Mathematics Genealogy Project for their work compiling and maintaining this fascinating and important dataset, as well as for allowing us the opportunity to explore it using the Wolfram Language. We hope to be able to freely expose a Wolfram Data Repository version of the MGP dataset in the near future so that others may do the same.Êîììåíòàðèè (8) | ↑ |

4. **New Wolfram Language Books: Don’t Stop Learning Just Because It’s Summer**Âò., 31 èþëÿ[−]

It’s not really late summer unless you’re armed with an apple and a good book. There’s been a recent slew of incredible books utilizing the capabilities of the Wolfram Language that make sure your coding knowledge never stops growing and your reading list stays stocked. (And be sure to check the farmers’ market for those apples.) ## Beginning Artificial Intelligence with the Raspberry PiYour Raspberry Pi’s standard system software comes with the Wolfram Language, and using this bundle to break into the world of AI will complete your computing platform toolbox. Read about how author Donald J. Norris uses the Wolfram Language for deep machine learning demonstrations. You can also consider ## Numerical Solutions of Initial Value Problems Using MathematicaDo you only have time for a quick read? Authors Sujaul Chowdhury and Ponkog Kumar Das have got you covered! Study numerical solutions to differential equations of elementary physics problems using Euler, second-order Runge–Kutta methods and Mathematica. The authors explore using Mathematica for dealing with complex numbers, solving linear equations and dealing with matrices—complex topics handled well in 58 pages. ## A Mathematica Primer for PhysicistsMathematica was created by a physicist, and with Jim Napolitano’s recent book you can learn how easy it is to use Mathematica for physics. Starting with the basics, this book spans across vectors and matrices, random number generation and data analysis, differential and integral calculus and beyond, all while explaining problem solving in a step-by-step fashion.
## Group Theory in Solid State Physics and Photonics: Problem Solving with MathematicaWhile group theory and its application to solid-state physics is a commonly broached topic, authors Wolfram Hergert and R. Matthias Geilhufe provide a deeper understanding through extensive use of Mathematica tools. Giving unique tools to the photonics community as well as offering a newly developed Mathematica package (GTPack, which is available for download), this book is an important addition to every physicist’s bookshelf. ## Mathematica for Bioinformatics: A Wolfram Language Approach to OmicsIf you thought Mathematica and the Wolfram Language were only useful in mathematics and physics, George Mias is here to tell you otherwise! Written using the latest version of the Wolfram Language, this book will help you learn the basics of the language and how it can be applied to bioinformatics using detailed coding examples, a wide variety of bioinformatics-specific scenarios and dynamically interactive tools built with the Wolfram Language. Geared to address the needs of the full spectrum of bioinformaticians, this book will lead you to coding expertise in under 400 pages. ## Classical Mechanics with Mathematica, second editionWith over 30 years of teaching experience, authors Antonio Romano and Addolorata Marasco have developed the perfect textbook to give students an overview of the history of classical mechanics while incorporating modern developments. After reading this two-part text, you’ll come away with an understanding of tensor algebra, Euclidean and symplectic vector spaces, Lagrangian and Hamiltonian dynamics, Hamilton–Jacobi theory and impulsive dynamics, among many other topics. This second edition has been completely revised and updated, and now includes completely new chapters as well as almost 200 exercises. Included with your purchase of this text are several downloadable Wolfram Notebooks to help your students in understanding some of the more complex materials.
## Discrete Mathematics through the Use of VilCretas PackageEnrique V?lchez Q. uses VilCretas, a package he created, to develop procedures for elementary learning of discrete mathematics. Learn about algorithm analysis, graph theory, finite-state automata and so much more using 230 commands available for addition to the Wolfram Language. This Spanish book is also available in English. ## Introduccion a la Programacion en Mathematica: para ingenieros civiles y mecánicos(Title in English: Introduction to Programming in Mathematica: For Civil and Mechanical Engineers) You already know that the Wolfram Language can be used beyond math and physics, so you may have guessed that engineering is one of the many other fields in which the language is quite useful. Luis E. Su?rez teaches readers how to use Mathematica within mechanical and civil engineering; several examples focusing on vibrations and structural mechanics are also included. ## Hands-on Start to Wolfram Mathematica with the Wolfram Language, second edition (in Chinese)With their book now available in Chinese (as well as English and Japanese), authors Cliff Hastings, Kelvin Mischo and Michael Morrison have expanded their catch-all guide to learning and understanding Mathematica. Leave any of your remaining questions behind—with this book in hand, all you’ll need to do is go forth and program! Êîììåíòàðèè (0) | ↑ |

5. **Big O and Friends: Tales of the Big, the Small and Every Scale in Between**×ò., 26 èþëÿ[−]

One of the many beautiful aspects of mathematics is that often, things that look radically different are in fact the same—or at least share a common core. On their faces, algorithm analysis, function approximation and number theory seem radically different. After all, the first is about computer programs, the second is about smooth functions and the third is about whole numbers. However, they share a common toolset: asymptotic relations and the important concept of asymptotic scale. By comparing the “important parts” of two functions—a common trick in mathematics—asymptotic analysis classifies functions based on the relative size of their absolute values near a particular point. Depending on the application, this comparison provides quantitative answers to questions such as “Which of these algorithms is fastest?” or “Is function a good approximation to function g?”. Version 11.3 of the Wolfram Language introduces six of these relations, summarized in the following table. The oldest (and probably the most familiar of the six relations) is AsymptoticLessEqual, which is commonly called big O or big Omicron. It was popularized by Paul Bachmann in the 1890s in his study of analytic number theory (though the concept had appeared earlier in the work of Paul du Bois-Reymond). At a point , is asymptotically less than or equal to , written , if for some constant for all near . This captures the notion that cannot become arbitrarily larger in magnitude than . Bachmann used this in his study of sums and the growth rate of number theoretic functions to show that he could split complicated sums into two parts: a leading part with an explicit form, and a subleading part without a concrete expression. The subleading part could, however, be shown to be asymptotically less than or equal to some other function that is, for some reason, unimportant compared with the leading part, and therefore only the leading part needed to be kept. Donald Knuth would popularize the notion of big O in computer science, using it to sort algorithms from fastest to slowest by whether the run time of one is asymptotically less than or equal to the next at infinity. AsymptoticLess, also called little O or little Omicron, came next. Introduced by Edmund Landau approximately 15 years after Bachmann’s work (leading to the name “Bachmann–Landau symbols” for asymptotic relations in certain disciplines), it quantified the notion of the unimportance of the subleading part. In particular, is asymptotically less than , written , if for all constants and all near . The condition that the inequality holds for all positive , not just a single , means that can be made arbitrarily smaller in magnitude compared to g. Thus, the essentially equals . AsymptoticLess is also important in the analysis of algorithms, as it allows strengthening statements from “algorithm a is no slower than algorithm b” to “algorithm a is faster than algorithm b.” After this point, the history becomes rather complicated, so for the time being we’ll skip to the 1970s, when Knuth popularized AsymptoticEqual (commonly called big Theta). This captures the notion that neither function is ignorable compared with the other near the point of interest. More formally, is asymptotically equal to , written , if for some constant and , for all near . After exploring these first three relations with examples, both the history and the other relations will be easily explained and understood. Consider three simple polynomials: , and . The two linear polynomials are both asymptotically less than and asymptotically less than or equal to the quadratic one at infinity: #10005 AsymptoticLessEqual[x,x^2,x->?] Even though for many values of , because eventually will become bigger and continue increasing in size: #10005 AsymptoticLess[10^5 x,x^2,x->?] On the other hand, is not asymptotically less than . Even though is always smaller, the ratio is a constant instead of going to zero: #10005 AsymptoticLess[x,10^5 x,x->?] Indeed, the two linear polynomials are asymptotically equal because their ratio stays in a fixed range away from zero: #10005 AsymptoticEqual[10^5 x,x,x->?] The linear polynomials are not asymptotically equal to the quadratic one, however: #10005 AsymptoticEqual[10^6 x,x^2,x->?] The following log-log plot illustrates the relationships among the three functions. The constant offset in the log-log scale between the two linear functions shows that they are asymptotically equal, while their smaller slopes with respect to show that the former are asymptotically less than the latter. #10005 LogLogPlot[{Abs[x],Abs[10^5 x],Abs[x^2]},{x,10,10^9},PlotLegends->"Expressions"] A typical example for the application of these examples concerns analyzing the running time of an algorithm. A classic example is the merge sort. This sort works by recursively splitting a list in two, sorting each half and then combining them in sorted order. The following diagram illustrates these steps: The time to sort elements will be the sum of some constant time to compute the middle, to sort each half and some multiple of the number of elements to combine the two halves (where and are determined by the particular computer on which the algorithm is run): #10005 reqn=T[n]==2T[n/2]+ a n +b In this particular case, solving the recurrence equation to find the time to sort elements is straightforward: #10005 t=RSolveValue[reqn, T[n],n]//Expand Irrespective of the particular values of and and the constant of summation , , and thus the algorithm is said to have run time: #10005 AsymptoticEqual[t,n Log[n],n->?,Assumptions->a>0] Any other algorithm that has run time takes roughly the same amount of time for large inputs. On the other hand, any algorithm with run time , such as radix sort, will be faster for large enough inputs, because : #10005 AsymptoticLess[n,n Log[n],n->?] Conversely, any algorithm with run time , such as bubble sort, will be slower for large inputs, as : #10005 AsymptoticLess[n Log[n],n^2,n->?] Another set of applications for AsymptoticEqual comes from convergence testing. Two functions that are asymptotically equal to each other will have the same summation or integration convergence—for example, at infinity: #10005 AsymptoticEqual[1/n,ArcCot[n], n->?] It is well known that the sum of , known as the harmonic series, diverges: #10005 DiscreteLimit[Sum[1/n,{n,1,k}],k->?] Thus, must also diverge: #10005 SumConvergence[ArcCot[n], n] Be careful: although the name AsymptoticLessEqual suggests a similarity to the familiar operator, the former is a partial order, and not all properties carry over. For example, it is the case that for any two real numbers and , either or , but it is not true that for any two functions either or : #10005 {AsymptoticLessEqual[Sin[1/x],x,x->0],AsymptoticLessEqual[x,Sin[1/x],x->0]} Similarly, if , then it is true that either or . But it is possible for to be true while both and are false: #10005 {AsymptoticLessEqual[Sin[x],1,x->?],AsymptoticLess[Sin[x],1,x->?],AsymptoticEqual[1,Sin[x],x->?]} Because AsymptoticLessEqual is a partial order, there are two possibilities for what AsymptoticGreaterEqual (also called big Omega) could mean. One option is the logical negation of AsymptoticLessEqual, i.e. iff . In the previous example, then, 1 and are each asymptotically greater than or equal to each other. This captures the notion that is never less than some fixed multiple of even if the relative sizes of the two functions change infinitely many times close to . Another sensible definition for AsymptoticGreaterEqual would be simply the notational reverse of AsymptoticLessEqual, i.e. iff . This captures the notion that is eventually no greater than some fixed multiple of in magnitude. Similar considerations apply to AsymptoticGreater, also called little Omega. Historically, Godfrey Harold Hardy and John Edensor Littlewood first used and popularized AsymptoticGreaterEqual in their seminal work on series of elliptic functions in 1910s, using the first definition. This definition is still presently used in analytic number theory. In the 1970s, Knuth proposed that the first definition is not widely used, and that the second definition would be more useful. This has become the standard in the analysis of algorithms and related fields. The Wolfram Language follows the second definition as well. Knuth also proposed using a similar definition for AsymptoticGreater, i.e. iff , which is used in computer science. The last of the newly introduced relations, AsymptoticEquivalent, also comes from Hardy’s work in the early part of the 20th century. Roughly speaking, if their ratio approaches 1 at the limit point. More formally, is asymptotically equivalent to if for all constants and all near . Put another way, iff . Hence, asymptotic equivalence captures the notion of approximation with small relative error, also called asymptotic approximation. A well-known example of such an approximation is Stirling’s approximation for the factorial function: #10005 s[n_]:=Sqrt[2? n] (n/E)^n This function is asymptotically equivalent to the factorial function: #10005 AsymptoticEquivalent[n!,s[n],n->?] This means the relative error, the size of the difference relative to the size of the factorial function, goes to zero at infinity: #10005 Underscript[?, n->?](n!-s[n])/n! Note that this is only a statement about relative error. The actual difference between and blows up at infinity: #10005 Underscript[?, n->?](n!-s[n]) Because asymptotic approximation only demands a small relative error, it can be used to approximate many more classes of functions than more familiar approximations, such as Taylor polynomials. However, by Taylor’s theorem, every differentiable function is asymptotically equivalent to each of its Taylor polynomials. For example, the following computation shows that is equivalent to each of its first three Maclaurin polynomials: #10005 {AsymptoticEquivalent[1,E^x,x->0],AsymptoticEquivalent[1+x,E^x,x->0],AsymptoticEquivalent[1+x+x^2/2,E^x,x->0]} Yet is also asymptotically equivalent to many other polynomials: #10005 AsymptoticEquivalent[1+2x,E^x,x->0] Plotting the relative errors for each of the four polynomials shows that it does go to zero for all of them: #10005 Plot[{Abs[(1-E^x)/E^x],Abs[(1+x-E^x)/E^x],Abs[(1+x+x^2/2-E^x)/E^x],Abs[(1+2x-E^x)/E^x]},{x,-.1,.1},PlotLegends->"Expressions",ImageSize->Medium] What, then, makes the first-order and second-order polynomials better than the zeroth? In the previous plot, they seem to be going to zero faster than the linear polynomials, but this needs to be made quantitative. For this, it is necessary to introduce an asymptotic scale, which is a family of functions for which . For Maclaurin series, that family is . Each monomial is, in fact, asymptotically greater than the one before: #10005 AsymptoticGreater[x^m,x^n,x->0,Assumptions->m0],AsymptoticLess[1+x-Exp[x],x,x->0],AsymptoticLess[1+x+x^2/2-Exp[x],x^2,x->0]} On the other hand, while is a valid zeroth-order approximation to at 0, it is not a valid first-order approximation: #10005 {AsymptoticLess[1+2x-Exp[x],1,x->0],AsymptoticLess[1+2x-Exp[x],x,x->0]} Indeed, is the only linear polynomial that is a first-order approximation to at 0 using the asymptotic scale . Visualizing the ratio of to and it is clear that the error is small with respect to but not with respect to . The ratio of the error to goes to 1, though any positive number would indicate is false: #10005 Plot[{Abs[1+2x-E^x],Abs[(1+2x-E^x)/x]},{x,-.1,.1},PlotLegends->"Expressions",ImageSize->Medium] The scale , often called the Taylor or power scale, is the simplest and most familiar of a huge number of different useful scales. For example, the Laurent scale is used to expand functions in the complex plane. In “Getting to the Point: Asymptotic Expansions in the Wolfram Language,” my colleague Devendra Kapadia showed how different scales arise when finding approximate solutions using the new functions AsymptoticDSolveValue and AsymptoticIntegrate. For example, the asymptotic scale (a type of Puiseux scale) comes up when solving Bessel’s equation, the asymptotic scale is needed to approximate the integraland Airy’s equation leads to the scale . We can verify that each of these indeed forms a scale by creating a small wrapper around AsymptoticGreater: #10005 AsymptoticScaleQ[list_,x_->x0_]:=And@@BlockMap[AsymptoticGreater[#1[[1]],#1[[2]],x->x0] ,list,2,1] The first few examples are asymptotic scales at 0: #10005 AsymptoticScaleQ[{1/x^2,1/x,1,x,x^2},x->0] #10005 AsymptoticScaleQ[{x^(1/2),x^(5/2),x^(9/2),x^(13/2)},x->0] The last two, however, are asymptotic scales at ?: #10005 AsymptoticScaleQ[{E^?/?^(1/2),E^?/?^(3/2),E^?/?^(5/2)},?->?] #10005 AsymptoticScaleQ[{E^(-((2 x^(3/2))/3)) x^(-1/4),E^(-((2 x^(3/2))/3)) x^(-7/4),E^(-((2 x^(3/2))/3)) x^(-13/4)},x->?] In computer science, algorithms are rated by whether they are linear, quadratic, exponential, etc. (in other words, whether their run times are asymptotically less than or equal to particular monomials, the exponential function, etc.). However, the preferred exponential scale is different— rather than . Thus, in addition to , they also consider . These are both asymptotic scales: #10005 AsymptoticScaleQ[{n^3,n^2,n,1},n->?] #10005 AsymptoticScaleQ[{2^n^4,2^n^3 ,2^n^2,2^n},n->?] Problems are then classified by the run time scale of the fastest algorithm for solving them. Those that can be solved in polynomial time are said to be in , while problems that require an exponential time algorithm are in . The famous problem asks whether the class of problems that can be verified in polynomial time can also be solved in polynomial time. If then it is theoretically possible that , i.e. all problems solvable in exponential time are verifiable in polynomial time. The power of asymptotic relations comes from the fact that they provide the means to define asymptotic scales, but the particular choice of scale and how it is used is determined by the application. In function approximation, the scales define asymptotic expansions—families of better and better asymptotic approximations using a given a scale. Depending on the function, different scales are possible. The examples in this blog illustrate power and exponential scales, but there are also logarithmic, polynomial and many other scales. In computer science, the scales are used for both theoretical and practical purposes to analyze and classify problems and programs. In number theory, scales are chosen to analyze the distribution of primes or other special numbers. But no matter what the application, the Wolfram Language gives you the tools to study them. Make sure you download your free trial of Wolfram|One in order to give Version 11.3 of the Wolfram Language a try! Download this post as a Wolfram Notebook.Êîììåíòàðèè (1) | ↑ |

6. **Four Minecraft Projects with the Wolfram Language**Âò., 24 èþëÿ[−]

A couple of weeks ago I shared a package for controlling the Raspberry Pi version of Minecraft from Mathematica (either on the Pi or from another computer). You can control the Minecraft API from lots of languages, but the Wolfram Language is very well aligned to this task—both because the rich, literate, multiparadigm style of the language makes it great for learning coding, and because its high-level data and computation features let you get exciting results very quickly. Today, I wanted to share four fun Minecraft project ideas that I had, together with simple code for achieving them. There are also some ideas for taking the projects further. If you haven’t already installed the MinecraftLink package, follow the instructions here. Rendering a Photo in Minecraft The Minecraft world is made up of blocks of different colors and textures. If we arrange these appropriately, we can use the colors to create grainy pictures. I want to automate this process of converting pictures to Minecraft blocks. The first step is to start a new world in Minecraft on the Raspberry Pi, then load the MinecraftLink package: #10005 ImageQ]],{Entity["MinecraftBlock", "Glass"],Entity["MinecraftBlock", "Leaves"],Entity["MinecraftBlock", "Cobweb"],Entity["MinecraftBlock", "Sand"],Entity["MinecraftBlock", "Gravel"],Entity["MinecraftBlock", "Snow"],Entity["MinecraftBlock", "Fire"],Entity["MinecraftBlock", "WaterStationary"]}] Here are the images that we have: #10005 Magnify[{#["Image"],#} /@available,0.6] Most blocks (subject to lighting) are the same on all faces, but a few have different textures on their side faces than their top faces. I plan to look at all blocks from the side, so I want to figure out what the blocks’ average side-face color is. To do this, I created the following mask for the position of the side-face pixels of the gold block: #10005 mask=Erosion[DominantColors[,4,"CoverageImage"][[2]],2] Because all the images have the same shape and viewpoint, I can apply that mask to every block to pick out their front-face pixels: #10005 mask RemoveAlphaChannel[Entity["MinecraftBlock","WoodBirch"]["Image"]] To make sure I am using a like-for-like measurement, I remove the transparency layer (AlphaChannel) and put them all into the same color space. Then I just ask for the average pixel value and convert that back to an average color (working in HSB color gives more perceptually correct averaging of colors): #10005 averageColor[block_]:=Hue[ImageMeasurements[ColorConvert[RemoveAlphaChannel[block["Image"],LightBlue],"HSB"],"Mean",Masking->mask]] #10005 colors=Map[averageColor,available] We can now look at our available palette: #10005 ChromaticityPlot[colors] You can see from this plot of colors in the visible color space that we have rather poor coverage of high-saturation colors, and something of a gap around the green/cyan border, but this is what we have to work with. Now we need a function that takes a color and picks out the block name that is nearest in color. The Wolfram Language already knows about perceptual color distance, so Nearest handles this directly: #10005 getName[color_]:=First[Nearest[MapThread[Rule,{colors,available}],color]]; For example, the block that is closest to pure red is wool orange: #10005 getName[Red] Now we need a function that will take a picture and drop its resolution to make it more “blocky” and simplify the image to use only the colors that are available to us: #10005 toBlockColors[img_,size_]:=ColorQuantize[ImageResize[img,size],colors]; Let’s now apply that to a well-known picture: #10005 toBlockColors[,50] Now we just have to count through the pixels of that image, find the name of the block with the nearest color to the pixel and place it in the corresponding place in the Minecraft world: #10005 putPicture[{x0_,y0_,z0_},img_]:= Block[{dims=ImageDimensions[img]}, Do[ MinecraftSetBlock[{dims[[1]]-x+x0,y+y0,z0},getName[RGBColor[ImageValue[img,{x,y}]]]], {x,dims[[1]]},{y,dims[[2]]}]]; Find a big open space... And run the program on a simple image: #10005 putPicture[{30,0,0},toBlockColors[,50]] You can use Import to bring images into the system, but the Wolfram Language provides lots of images as part of its Entity system. For example, you can fetch famous works of art: #10005 Entity["Artwork", "AmericanGothic::GrantWood"]["Image"] Here is a detail from American Gothic (Grant Wood’s sister) in blocks: #10005 putPicture[{30,0,0},toBlockColors[ImageTake[Entity["Artwork", "AmericanGothic::GrantWood"]["Image"],{25,75},{10,50}],50]] You can even, at an incredibly low frame rate, make an outdoor movie theater by streaming frames from your webcam onto the wall. Here is me working on this blog post! #10005 While[True,putPicture[{30,0,0},toBlockColors[CurrentImage[],50]]] An interesting challenge would be to reverse this process to generate a map of the Minecraft world. You would need to scan the surface block type at every position in the Minecraft world and use the color map created to color a single pixel of the output map. Recreating the Real World in Minecraft This project sounds quite hard, but thanks to the built-in data in the Wolfram Language, it is actually very simple. Let’s suppose I want to create my home country of the United Kingdom in Minecraft. All I need to do is place a grid of blocks at heights that correspond to heights of the land in the United Kingdom. We can get that data from the Wolfram Language with GeoElevationData: #10005 ListPlot3D[Reverse/@GeoElevationData[Entity["Country", "UnitedKingdom"]],PlotRange->{-10000,20000},Mesh->False] You will see that the data includes underwater values, so we will need to handle those differently to make the shape recognizable. Also, we don’t need anywhere near as much resolution (GeoElevationData can go to a resolution of a few meters in some places). We need something more like this: #10005 ListPlot3D[Reverse/@GeoElevationData[Entity["Country", "UnitedKingdom"],GeoZoomLevel->3],PlotRange->{0,5000},Mesh->False] Now let’s make that into blocks. Let’s assume I will choose the minimum and maximum heights of our output. For any given position, I need to create a column of blocks. If the height is positive, this should be solid blocks up to the height, and air above. If the height is negative, then it is solid up to the point, water above that until we reach a given sea level value and then air above that. #10005 createMapColumn[{x_,y_,z_},seaLevel_,min_,max_]:=(MinecraftSetBlock[{{x,min,z},{x,y,z}},"Dirt"];If[y>=seaLevel,MinecraftSetBlock[{{x,y,z},{x,max,z}},Entity["MinecraftBlock", "Air"]], MinecraftSetBlock[{{x,y,z},{x,seaLevel-1,z}},Entity["MinecraftBlock", "WaterStationary"]];MinecraftSetBlock[{{x,seaLevel,z},{x,max,z}},"Air"]]); Now we just need to create a column for each position in our elevation data. All the work is in transforming the numbers. The reversing and transposing is to get the coordinates to line up with the compass correctly, QuantityMagnitude gets rid of units, and the rest is vertical scaling: #10005 MinecraftElevationPlot[data0_,{x0_,seaLevel_,z0_}, maxHeight_:5]:= Block[{data=QuantityMagnitude[Reverse[Map[Reverse,Transpose[data0]]]],scale, min,dims}, dims=Dimensions[data]; scale= maxHeight/Max[Flatten[data]]; min= Round[scale*Min[Flatten[data]]]; Do[createMapColumn[{Round[x0+i],Floor[scale data[[i,j]]+seaLevel],z0+j},Round[seaLevel], seaLevel+min,Round[maxHeight+seaLevel]],{i,dims[[1]]},{j,dims[[2]]}]] Before we start, we can use the following code to clear a large, flat area to work on and put the camera high in the air above the action: #10005 MinecraftSetBlock[{{-40,-10,-40},{40,0,40}},"Grass"]; MinecraftSetBlock[{{-40,0,-40},{40,50,40}},"Air"]; #10005 MinecraftSetCamera["Fixed"]; MinecraftSetCamera[{0,25,0}] And now we can place the map: #10005 MinecraftElevationPlot[GeoElevationData[Entity["Country", "UnitedKingdom"],GeoZoomLevel->2],{-15,0,-15},5] You can just see that the land is higher in mountainous Scotland. You can see that better with the camera in the usual position, but the coastline becomes harder to see. Alternatively, here is the view of the north ridge of Mount Everest, as seen from the summit: #10005 MinecraftSetCamera["Normal"] MinecraftElevationPlot[GeoElevationData[GeoDisk[Entity["Mountain", "MountEverest"],3 mi],GeoZoomLevel->9],{-15,-18,-15},30] A nicer version of this might switch materials at different heights to give you snowcapped mountains, or sandy beaches. I will leave that for you to add. Rendering a CT Scan in Minecraft If you are unlucky enough to need an MRI or CT scan, then you might end up with 3D image data such as this built-in example: #10005 Show[ExampleData[{"TestImage3D","CThead"}],BoxRatios->1] This might seem complex, but it is actually a simpler problem than the photo renderer we did earlier, because color isn’t very meaningful in the CT world. Our simplest approach is just to drop the scan’s resolution, and convert it into either air or blocks. #10005 Binarize[ImageResize[ExampleData[{"TestImage3D","CThead"}],{80,80,80}]] We can easily find the coordinates of all the solid voxels, which we can use to place blocks in our world: #10005 Position[ImageData[%],1] We can wrap all of that into a single function, and add in an initial position in the Minecraft world. I added the small pause because if you run this code from a desktop computer, it will flood the Minecraft server with more requests than it can handle, and Minecraft will drop some of the blocks: #10005 fixCoordinates[{a_,b_,c_}]:={c,-a,b} (*Mapping coordinate systems*) #10005 minecraftImage3D[img_Image3D,pos_List,block_,threshold_:Automatic]:=( MinecraftSetBlock[{pos,pos+ImageDimensions[img]},"Air"];Map[(Pause[0.01];MinecraftSetBlock[pos+#,block]) ,fixCoordinates/@Position[ImageData[Binarize[img,threshold]],1]];) And here it is in action with the head: #10005 minecraftImage3D[ ImageResize[ExampleData[{"TestImage3D","CThead"}],{40,40,40}],{0,40,0},"GoldBlock"] But one thing to understand with 3D images is that there is information “inside” the image at every level, so if we change the threshold for binarizing then we can pick out just the denser bone material and make a skull: #10005 Binarize[ImageResize[ExampleData[{"TestImage3D","CThead"}],{80,80,80}],0.4] #10005 minecraftImage3D[ ImageResize[ExampleData[{"TestImage3D","CThead"}],{40,40,40}],{0,40,0},"GoldBlock",0.4] An interesting extension would be to establish three levels of density and use the glass block type to put a transparent skin on the skull. I will leave that for you to do. You can find DICOM images on the web that can be imported into the Wolfram Language with Import, but beware—some of those can be quite large files. Automatic Pyramid Building The final project is about creating new game behavior. My idea is to create a special block combination that triggers an automatic action. Specifically, when you place a gold block on top of a glowstone block, a large pyramid will be built for you. The first step is to scan the surface blocks around a specific point for gold and return a list of surface gold block positions found: #10005 scanForGold[{x0_,y0_,z0_}]:=Block[{goldPos={}, height = MinecraftGetHeight[{x,z}]}, Do[Pause[0.1];If[MinecraftGetBlock[{x,height-1,z}]===Entity["MinecraftBlock","GoldBlock"],AppendTo[goldPos,{x,height-1,z}]],{x,x0-1,x0+1},{z,z0-1,z0+1}]; goldPos]; Next, we look under each of the gold blocks that we found and see if any have glowstone under them: #10005 checkGoldForGlowstone[goldPos_]:=FirstCase[goldPos,{x_,y_,z_}/;MinecraftGetBlock[{x,y-1,z}]===Entity["MinecraftBlock","GlowstoneBlock"]] Now we need a function that performs the resulting actions. It posts a message, removes the two special blocks and sets the pyramid: #10005 pyramidActions[found_]:=(MinecraftChat["Building Pyramid"]; MinecraftSetBlock[{found,found-{0,1,0}},"Air"]; MinecraftSetBlock[found-{0,1,0},"GoldBlock",Pyramid[],RasterSize->12]); We can now put all of that together into one function that scans around the current player and runs the actions on the first matching location. The PreemptProtect is a bit subtle. Because I am going to run this as a background task, I need to make sure that I don’t perform two actions at once, as the messages going back and forth to the Minecraft server may get muddled: #10005 pyramidCheck[]:=PreemptProtect[Block[{found=checkGoldForGlowstone[scanForGold[MinecraftGetTile[]]]},If[Not[MissingQ[found]],pyramidActions[found]]]] All that is left is to run this code repeatedly every five seconds: #10005 task=SessionSubmit[ScheduledTask[pyramidCheck[],5]] I place the blocks like this... ... walk up within one block of the special column and wait for a couple of seconds, until this happens... To stop the task, you can evaluate... #10005 TaskRemove[task] Well, that’s the end of my short series on Minecraft coding in the Wolfram Language. There are lots of fun knowledge domains and computation areas that I could have injected into Minecraft. I had thought of using reading surface blocks and constructing a 3D mini-map of the world using the Wolfram Language’s data visualization, or creating a solar system of orbiting planets using the differential equation solver. I also considered creating a terrain generator using 3D cellular automata or fractals. But I do have a day job to do, so I will leave those for others to try. Do post your own project ideas or code on Wolfram Community. Download this post as a Wolfram Notebook.Êîììåíòàðèè (0) | ↑ |

7. **Getting to the Point: Asymptotic Expansions in the Wolfram Language**×ò., 19 èþëÿ[−]

Asymptotic expansions have played a key role in the development of fields such as aerodynamics, quantum physics and mathematical analysis, as they allow us to bridge the gap between intricate theories and practical calculations. Indeed, the leading term in such an expansion often gives more insight into the solution of a problem than a long and complicated exact solution. Version 11.3 of the Wolfram Language introduces two new functions, AsymptoticDSolveValue and AsymptoticIntegrate, which compute asymptotic expansions for differential equations and integrals, respectively. Here, I would like to give you an introduction to asymptotic expansions using these new functions. The history of asymptotic expansions can be traced back to the seventeenth century, when Isaac Newton, Gottfried Leibniz and others used infinite series for computing derivatives and integrals in calculus. Infinite series continued to be used during the eighteenth century for computing tables of logarithms, power series representations of functions and the values of constants such as ?. The mathematicians of this era were aware that many series that they encountered were divergent. However, they were dazzled by the power of divergent series for computing numerical approximations, as illustrated by the Stirling series for Gamma, and hence they adopted a pragmatic view on the issue of divergence. It was only in the nineteenth century that Augustin-Louis Cauchy and others gave a rigorous theory of convergence. Some of these rigorists regarded divergent series as the devil’s invention and sought to ban their use in mathematics forever! Fortunately, eighteenth-century pragmatism ultimately prevailed when Henri Poincar? introduced the notion of an asymptotic expansion in 1886. Asymptotic expansions refer to formal series with the property that a truncation of such a series after a certain number of terms provides a good approximation for a function near a point. They include convergent power series as well as a wide variety of divergent series, some of which will appear in the discussion of AsymptoticDSolveValue and AsymptoticIntegrate that follows. As a first example for AsymptoticDSolveValue, consider the linear differential equation for Cos: #10005 deqn={(y^??)[x]+y[x]==0,y[0]==1,(y^?)[0]==0}; The following input returns a Taylor series expansion up to order 8 around 0 for the cosine function: #10005 sol = AsymptoticDSolveValue[deqn, y[x], {x, 0, 8}] Here is a plot that compares the approximate solution with the exact solution : #10005 Plot[Evaluate[{sol, Cos[x]}], {x, 0, 3 ?}, PlotRange -> {-2, 5},PlotLegends->"Expressions"] Notice that the Taylor expansion agrees with the exact solution for a limited range of near 0 (as required by the definition of an asymptotic expansion), but then starts to grow rapidly due to the polynomial nature of the approximation. In this case, one can get progressively better approximations simply by increasing the number of terms in the series. The approximate solution then wraps itself over larger portions of the graph for the exact solution: #10005 nsol[n_]:=Callout[AsymptoticDSolveValue[{y''[x]+y[x]==0,y[0]==1,y'[0]==0},y[x],{x,0,n}],n] #10005 Plot[{nsol[4],nsol[8],nsol[12],nsol[16],nsol[20],Cos[x]}//Evaluate,{x,0,3Pi},PlotRange->{-2,5}] Next, consider Bessel’s equation of order , which is given by: #10005 besseleqn= x^2 (y^??)[x]+x (y^?)[x]+(x^2-1/4) y[x]==0; This linear equation has a singularity at in the sense that when , the order of the differential equation decreases because the term in becomes 0. However, this singularity is regarded as a mild problem because dividing each term in the equation by results in a pole of order 1 in the term for and a pole of order 2 for . We say that is a regular singular point for the differential equation and, in such cases, there is a Frobenius series solution that is computed here: #10005 sol=AsymptoticDSolveValue[besseleqn,y[x],{x,0,24}] Notice that there are fractional powers in the solution, and that only the second component has a singularity at . The following plot shows the regular and singular components of the solution: #10005 Plot[{sol /. {C[1] -> 1, C[2] -> 0}, sol /. {C[1] -> 0, C[2] ->1}}//Evaluate, {x, 0,3?}, PlotRange -> {-2, 2}, WorkingPrecision -> 20,PlotLegends->{"regular solution", "singular solution"}] These solutions are implemented as BesselJ and BesselY, respectively, in the Wolfram Language, with a particular choice of constant multiplying factor : #10005 Series[{BesselJ[1/2,x],-BesselY[1/2,x]},{x,0,8}]//Normal As a final example of a linear differential equation, let us consider the Airy equation, which is given by: #10005 airyode=(y^??)[x]-x y[x]==0; This equation has an irregular singular point at , which may be seen by setting , and then letting approach 0, so that approaches . At such a point, one needs to go beyond the Frobenius scale, and the solution consists of asymptotic series with exponential factors: #10005 AsymptoticDSolveValue[airyode, y[x], {x, ?, 3}] The components of this solution correspond to the asymptotic expansions for AiryAi and AiryBi at Infinity: #10005 s1 = Normal[Series[AiryAi[x], {x, ?, 4}]] #10005 s2 = Normal[Series[AiryBi[x], {x, ?, 4}]] The following plot shows that the approximation is very good for large values of : #10005 Plot[Evaluate[{AiryAi[x], AiryBi[x], s1, s2}], {x, -3, 3}, PlotLegends -> {AiryAi[x], AiryBi[x], "s1", "s2"}, PlotStyle -> Thickness[0.008]] The asymptotic analysis of nonlinear differential equations is a very difficult problem in general. Perhaps the most useful result in this area is the Cauchy–Kovalevskaya theorem, which guarantees the existence of Taylor series solutions for initial value problems related to analytic differential equations. AsymptoticDSolveValue computes such a solution for the following first-order nonlinear differential with an initial condition. Quiet is used to suppress the message that there are really two branches of the solution in this case: #10005 eqn={3 (y^?)[x]^2+4 x (y^?)[x]-y[x]+x^2==0,y[0]==1}; #10005 sol=AsymptoticDSolveValue[eqn, y[x],{x,0,37}]//Quiet Notice that only three terms are returned in the solution shown, although 37 terms were requested in the input. This seems surprising at first, but the confusion is cleared when the solution is substituted in the equation, as in the following: ? eqn /. {y -> Function[{x}, Evaluate[sol]]} // Simplify Thus, the asymptotic expansion is actually an exact solution! This example shows that, occasionally, asymptotic methods can provide efficient means of finding solutions belonging to particular classes of functions. In that example, the asymptotic method gives an exact polynomial solution. The examples that we have considered so far have involved expansions with respect to the independent variable . However, many problems in applied mathematics also involve a small or large parameter ?, and in this case, it is natural to consider asymptotic expansions with respect to the parameter. These problems are called perturbation problems and the parameter is called the perturbation parameter, since a change in its value may have a dramatic effect on the system. Modern perturbation theory received a major impetus after the German engineer Ludwig Prandtl introduced the notion of a boundary layer for fluid flow around a surface to simplify the Navier–Stokes equations of fluid dynamics. Prandtl’s idea was to divide the flow field into two regions: one inside the boundary layer, dominated by viscosity and creating the majority of the drag; and one outside the boundary layer, where viscosity can be neglected without significant effects on the solution. The following animation shows the boundary layer in the case of smooth, laminar flow of a fluid around an aerofoil. Prandtl’s work revolutionized the field of aerodynamics, and during the decades that followed, simple examples of perturbation problems were created to gain insight into the difficult mathematics underlying boundary layer theory. An important class of such examples are the so-called singular perturbation problems for ordinary differential equations, in which the order of the equation decreases when the perturbation parameter is set to 0. For instance, consider the following second-order boundary value problem: #10005 eqn={? (y^??)[x]+2 (y^?)[x]+y[x]==0,y[0]==0,y[1]==1/2}; When ? is 0, the order of the differential equation decreases from 2 to 1, and hence this is a singular perturbation problem. Next, for a fixed small value of the parameter, the nature of the solution depends on the relative scales for and , and the solution can be regarded as being composed of a boundary layer near the left endpoint 0, where ? is much larger than , and an outer region near the right endpoint 1, where is much larger than . For this example, AsymptoticDSolveValue returns a perturbation solution with respect to : #10005 psol = AsymptoticDSolveValue[eqn, y[x], x, {?, 0, 1}] For this example, an exact solution can be computed using DSolveValue as follows: #10005 dsol = DSolveValue[eqn, y[x], x] The exact solution is clearly more complicated than the leading term approximation from the perturbation expansion, and yet the two solutions agree in a very remarkable manner, as seen from the plots shown here (the exact solution has been shifted vertically by 0.011 to distinguish it from the approximation!): #10005 Plot[Evaluate[{psol,dsol+0.011}/. {?->1/30}],{x,0,1},PlotStyle->{Red,Blue}] In fact, the approximate solution approaches the exact solution asymptotically as ? approaches 0. More formally, these solutions are asymptotically equivalent: #10005 AsymptoticEquivalent[dsol, psol,?->0,Direction->-1,Assumptions->0 Axis, FillingStyle -> Yellow] Laplace’s method gives the following simple result for the leading term in the integral of from 0 to Infinity, for large values of the parameter : #10005 AsymptoticIntegrate[f[x], {x, 0, ?}, {?, ?, 1}] The following inputs compare the value of the approximation for with the numerical result given by NIntegrate: #10005 % /. {? -> 30.} #10005 NIntegrate[Exp[-30 (x^2-2 x)] (1+x)^(5/2),{x,0,?}] The leading term approximation is reasonably accurate, but one can obtain a better approximation by computing an extra term: #10005 AsymptoticIntegrate[f[x], {x, 0, ?}, {?, ?, 2}] The approximate answer now agrees very closely with the result from NIntegrate: #10005 % /. {? -> 30.} The British mathematicians Sir George Gabriel Stokes and Lord Kelvin modified Laplace’s method so that it applies to oscillatory integrals in which the phase (exponent of the oscillatory factor) depends on a parameter. The essential idea of their method is to exploit the cancellation of sinusoids for large values of the parameter everywhere except in a neighborhood of stationary points for the phase. Hence this technique is called the method of stationary phase. As an illustration of this approach, consider the oscillatory function defined by: #10005 f[x_]:=E^(I ? Sin[t]) The following plot of the real part of this function for a large value of shows the cancellations except in the neighborhood of , where has a maximum: #10005 Plot[Re[f[x]/. {?->50}],{t,0,?},Filling->Axis,FillingStyle->Yellow] The method of stationary phase gives a first-order approximation for this integral: #10005 int =AsymptoticIntegrate[f[t],{t,0,?},{?,?,1}] This rather simple approximation compares quite well with the result from numerical integration for a large value of : #10005 int/. ?->5000. #10005 NIntegrate[Exp[I 5000 Sin[t]],{t,0,?},MinRecursion->20,MaxRecursion->20] As noted in the introduction, a divergent asymptotic expansion can still provide a useful approximation for a problem. We will illustrate this idea by using the following example, which computes eight terms in the expansion for an integral with respect to the parameter : #10005 aint=AsymptoticIntegrate[E^(-t)/(1+x t),{t,0,Infinity},{x,0,8}] The term in the asymptotic expansion is given by: #10005 a[n_]:=(-1)^n n! x^n #10005 Table[a[n],{n,0,8}] SumConvergence informs us that this series is divergent for all nonzero values of : #10005 SumConvergence[a[n],n] However, for any fixed value of sufficiently near 0 (say, ), the truncated series gives a very good approximation: #10005 aint/.x-> 0.05 #10005 NIntegrate[E^(-t)/(1 + 0.05 t),{t,0,Infinity}] On the other hand, the approximation gives very poor results for the same value of when we take a large number of terms, as in the case of 150 terms: #10005 AsymptoticIntegrate[E^(-t)/(1 + x t), {t, 0, Infinity}, {x, 0, 150}]/.{x-> 0.05`20} Thus, a divergent asymptotic expansion will provide excellent approximations if we make a judicious choice for the number of terms. Contrary to the case of convergent series, the approximation typically does not improve with the number of terms, i.e. more is not always better! Finally, we note that the exact result for this integral can be obtained either by using Integrate or Borel regularization: #10005 Integrate[E^(-t)/(1+x t),{t,0,Infinity},Assumptions-> x>0] #10005 Sum[a[n],{n,0,Infinity},Regularization->"Borel"] Both these results give essentially the same numerical value as the asymptotic expansion with eight terms: #10005 {%,%%}/.x-> 0.05 In connection with the previous example, it is worth mentioning that Dutch mathematician Thomas Jan Stieltjes studied divergent series related to various integrals in his PhD thesis from 1886, and is regarded as one of the founders of asymptotic expansions along with Henri Poincar?. As a concluding example for asymptotic approximations of integrals, consider the following definite integral involving GoldenRatio, which cannot be done in the sense that an answer cannot presently be found using Integrate: #10005 Integrate[1/(Sqrt[1+x^4](1+x^GoldenRatio)),{x,0,?}] This example was sent to me by an advanced user, John Snyder, shortly after the release of Version 11.3. John, who is always interested in trying new features after each release, decided to try the example using AsymptoticIntegrate after replacing GoldenRatio with a parameter ?, as shown here: #10005 sol=AsymptoticIntegrate[1/(Sqrt[1+x^4](1+x^?)),{x,0,?},{?,0,4}] He noticed that the result is independent of ?, and soon realized that the GoldenRatio in the original integrand is just a red herring. He confirmed this by verifying that the value of the approximation up to 80 decimal places agrees with the result from numerical integration: #10005 N[sol, 80] #10005 NIntegrate[1/(Sqrt[1+x^4](1+x^GoldenRatio)),{x,0,?},WorkingPrecision->80] Finally, as noted by John, the published solution for the integral is exactly equal to the asymptotic result. So AsymptoticIntegrate has allowed us to compute an exact solution with essentially no effort! Surprising results such as this one suggest that asymptotic expansions are an excellent tool for experimentation and discovery using the Wolfram Language, and we at Wolfram look forward to developing functions for asymptotic expansions of sums, difference equations and algebraic equations in Version 12. I hope that you have enjoyed this brief introduction to asymptotic expansions and encourage you to download a trial version of Version 11.3 to try out the examples in the post. An upcoming post will discuss asymptotic relations, which are used extensively in computer science and elsewhere. Download this post as a Wolfram Notebook.Êîììåíòàðèè (3) | ↑ |

8. **Why Is Sickle Cell Anemia Common in Areas with Malaria? Teaching Life Science with Modeling**×ò., 12 èþëÿ[−]

Life science teaches us to answer everything from “How can vaccines be used to indirectly protect people who haven’t been immunized?” to “Why are variations in eye color almost exclusively present among humans and domesticated animals?” You can now learn to answer these questions by using modeling with Wolfram’s virtual labs. Virtual labs are interactive course materials that are used to make teaching come alive, provide an easy way to study different concepts and promote student curiosity.
Two such virtual labs were created by MathCore’s summer intern, Anna Palmer, based on learning objectives from biology units 3 and 4 of the Victorian Certificate of Education (VCE) in the state of Victoria, Australia. Hear her talk about how she created them: ## Population Models in GeneticsYou’ve probably seen or heard about commercial kits where you send in a DNA sample to a company that then tells you about different things, such as your ancestry or predispositions for different diseases and genetic traits. Increasingly, we have become interested in our own genes and what stories our traits can tell us about ourselves and our ancestors. But we seldom stop to think how these genetic traits came to be in the first place. To understand the ancestry that genetic kits tell you about, we need to go back to biology class. We need to understand how different traits, such as eye color, evolve in populations over time; the most well-known cases of this are natural selection and Darwin’s famous phrase “survival of the fittest.” But what do these actually mean?
Contrary to what you may think, “survival of the fittest” does not just mean that only the fittest members of a species will survive, but rather, it refers to the ability of an organism to survive to reproduction. If an organism does not survive to reproduction, it cannot pass on its genes to the next generation. Thus, if a group of organisms with a particular trait has a decreased chance of surviving to reproduction, there is a decreased chance that the genes for this trait will be passed on to the next generation. This in turn may lead to the extinction of the trait. As Anna mentioned in the video, she created a system model that explains this. In the following model, two populations with different traits (A and B) compete for the same resources. The different traits will be differently adapted to the environment, and not all born with a particular trait will reach maturity. If they reach maturity, however, they will pass on their genes to a new generation.
By running this model, biology students can experiment with how different things in the model affect the outcome. In the virtual lab, this model has been embedded in a Wolfram Language notebook that contains explanations, questions and interactive interfaces using the
By playing around with the interface, students can explore how even very slight differences in the survivability can cause a particular trait to overtake another within just a few generations. With this, students can try different “what-if” scenarios and instantly see if the results match their hypotheses. Apart from ancestry, many people are also interested in knowing if they are predisposed toward certain diseases or not. There are many genes that influence just this. For example, a genetic variance causing sickle cell anemia actually protects against another disease, malaria. This explains why the gene for sickle cell anemia is found in about 7% of the population in malaria-stricken regions, but is virtually nonexistent elsewhere. In the same virtual lab, a model that explains this relationship is included.
In teaching, visualizing the complex relationship between two different diseases might be hard to do on paper; with a model and the Wolfram Language, it’s easy. Wolfram SystemModeler and the Wolfram Language make it possible for students to interact with the simulations, try different scenarios and set up experiments to instantly see if the results match their hypotheses.
We made this virtual lab available to students, educators and hobbyists alike. You can download the notebook here and learn about population genetics for yourself. In the download, you will find models of the scenarios described here, as well as a notebook providing you with the background and exercises that you can complete. ## Population Models in Infectious DiseasesOne of the things I really like about using SystemModeler is how easy it is to reuse the components you have created. This is especially useful in education, where the same concept can be found in many different settings. As an example, the types of population models that were used for the previous virtual lab are not only useful to illustrate genetic changes across multiple generations; among other things, they can also be used to explain how infectious diseases spread within populations. Anna developed a virtual lab for this too.
The most well known of these models, the susceptible-infectious-recovered (SIR) model, describes a disease that transmits from an infected person to a susceptible person. After a certain amount of time, the infected person recovers from the disease and can’t be infected again. In these types of diseases, our immune system is what keeps us from falling back into the infected category. The SIR model has proven very useful at explaining everything from smallpox to seasonal influenza. By getting vaccinated, you take a shortcut that moves you from the susceptible stage into the recovered stage, without going through the infected stage. This is illustrated in the “With Vaccination” model shown above. In this virtual lab, interactive interfaces that allow the students to adjust things such as the rate of infections, the duration of the sickness and the vaccinated rate are provided:
By comparing two scenarios (no vaccination and low vaccination), students can use the model to explain and understand things such as herd immunity. Even though there is a larger percentage of susceptible people in the first scenario, there is clearly a lower rate of infection since the vaccinated people provide an indirect form of immunity to the non-immune individuals, called herd immunity. Of course, this exercise (together with other exercises explaining infectious diseases) is available as a virtual lab that can be used by students, educators and hobbyists alike. You can download the virtual lab notebook here and learn about it for yourself! Biology and genetics are just two of the areas where we have created virtual labs to explain different concepts, and we are looking to create even more. Do you have a good idea for an educational area where modeling could be applied? Let us know by sending us an email at wsmcourseware@wolfram.com. Êîììåíòàðèè (0) | ↑ |

9. **Programming Minecraft on the Raspberry Pi**×ò., 05 èþëÿ[−]

The standard Raspbian software on the Raspberry Pi comes with a basic implementation of Minecraft and a full implementation of the Wolfram Language. Combining the two provides a fun playground for learning coding. If you are a gamer, you can use the richness of the Wolfram Language to programmatically generate all kinds of interesting structures in the game world, or to add new capabilities to the game. If you are a coder, then you can consider Minecraft just as a fun 3D rendering engine for the output of your code. Installation The first step is to make sure that you have all the right components. Make sure that you have the latest version of Raspbian and the Wolfram Language. You do this by connecting your Raspberry Pi to the network, opening the Terminal app and typing the following: sudo apt-get update. sudo apt-get dist-upgrade Now open Mathematica on the Pi, or another computer, and type: #10005 PacletInstall["MinecraftLink"] followed by Shift + Return to evaluate it. If all went well, we are ready to start. Using the Link The MinecraftLink library adds a small set of new commands to the Wolfram Language for connecting to a running Raspberry Pi Minecraft game. Start by launching Minecraft on the Raspberry Pi, and then start a fresh game or open an existing one. In the Wolfram Language, load the library by evaluating the following: #10005 50] Anything you can create in the Wolfram Language can be made into blocks. Here is a plot of the function Sin[x]: #10005 MinecraftSetBlock[pos,"Dirt",Plot[Sin[x],{x,0,12},Axes->False],RasterSize->18] #10005 MinecraftSetBlock[pos,"Air",Plot[Sin[x],{x,0,12},Axes->False],RasterSize->18] You can also control the orientation of rasterized images with an option Orientation. If the content is a 3D geometry, then it will be rasterized in 3D: #10005 MinecraftSetBlock[pos,"Wood",Sphere[],RasterSize->50] #10005 MinecraftSetBlock[pos,"Air",Sphere[],RasterSize->50] There are lots of 3D geometry primitives, and they can be combined in many ways. Here are some cuboids, a pyramid and a sphere to make a house: #10005 (*Main house frame*)MinecraftSetBlock[{pos,pos+{8,3,8}},"Wood"]; (*Windows*)MinecraftSetBlock[{pos+{1,0,0},pos+{7,3,8}},"Glass"]; (*Make it hollow*)MinecraftSetBlock[{pos+{1,0,1},pos+{7,3,7}},"Air"]; (*Add a doorway*)MinecraftSetBlock[{pos+{4,0,0},pos+{4,1,0}},"Air"]; (*Add a roof*) MinecraftSetBlock[pos+{0,4,0},"WoodPlanksSpruce",Pyramid[],RasterSize->12]; (*Decorate with gold ball*) MinecraftSetBlock[pos+{3,8,2},"GoldBlock",Sphere[],RasterSize->5];) OK, I’m not much of an architect! We can look at our creation from the air by controlling the camera: #10005 MinecraftSetCamera["Fixed"]; MinecraftSetCamera[{0,25,6}]; #10005 MinecraftSetCamera["Normal"] Reacting to Events Finally, we can interact with blocks that you hit using the right mouse button while holding a sword. The left mouse button just places and smashes blocks, but the right mouse button creates events that wait for us to read and act on them. You can read these with: #10005 MinecraftHitHistory[] This shows that since the game started, I have done two of these special hits, each time on the same block at {–1, 2, 2}, on face number 1 (the top of the block). I am player 1, but there could be multiple players. I can fetch these pieces of information by position and name. For example, HitHistory[–1] is the last hit, and we extract its "Position" information and use that coordinate in MinecraftGetBlock to discover the type of block that was most recently hit: #10005 MinecraftGetBlock[HitHistory[-1]["Position"]] And we can clear the data with: #10005 MinecraftClearHits[] As a simple example, let’s monitor this list every second and create an explosive “super hit.” I will define the explosion first. It is a function that takes a position and places a large sphere of air at that position: #10005 explosion[event_]:=MinecraftSetBlock[event["Position"]-{2,2,2},"Air",Ball[],RasterSize->8]; Now I create a scheduled task to run every second, and apply that function to the hit history: #10005 task=SessionSubmit[ ScheduledTask[ Map[explosion,MinecraftHitHistory[]];MinecraftClearHits[],1]] And now when I strike the ground in front of my house with my sword, using the right mouse button, a huge hole appears... I can remove the monitoring task with: #10005 TaskRemove[task] There are a few more commands in the MinecraftLink package that you can read about in the documentation after you have installed the link. As well as giving you a simple programming interface to Minecraft, similar to other languages, the Wolfram Language contains hundreds of high-level functions that let you develop much more exciting projects quickly; you might want to check out some of the 3D geometry, 3D image processing and built-in data sources as a starting point. I will return soon with a few projects of my own. Download this post as a Wolfram Notebook.Êîììåíòàðèè (6) | ↑ |

10. **The Shape of the Vote: Exploring Congressional Districts with Computation**Âò., 26 èþíÿ[−]

In the past few decades, the process of redistricting has moved squarely into the computational realm, and with it the political practice of gerrymandering. But how can one solve the problem of equal representation mathematically? And what can be done to test the fairness of districts? In this post I’ll take a deeper dive with the Wolfram Language—using data exploration with Import and Association, built-in knowledge through the Entity framework and various GeoGraphics visualizations to better understand how redistricting works, where issues can arise and how to identify the effects of gerrymandering.
Rules of Apportionment
In the US House of Representatives, each state is assigned a number of representatives based on its population through the process of apportionment (or reapportionment). On the surface, the rules for this process are simple: each state gets at least one representative, and representative seats must be redistributed at least once per decennial census.
Apportionment has been tried using various mathematical methods throughout history. Since the 1940 Census, representatives have been assigned using the method of equal proportions (the Huntington–Hill method). This means that the next available slot goes to the state with the highest priority , defined as:
#10005
TraditionalForm[Subscript[A, n]==P/GeometricMean[{n,n-1}]]
where P is the population of the state and n is the number of districts already assigned to the state. You might recognize the denominator as the geometric mean of and . It’s straightforward to implement symbolically:
#10005
Priority[pop_,n_]:=N[pop/GeometricMean[{n,n-1}]]
Formula in hand, I’d like to run a simulation to compare to the current apportionment plan. First I’ll pull the 2010 population data from the Wolfram Knowledgebase (excluding the District of Columbia):
#10005
states=Complement[all US states with District of Columbia administrative divisions["Entities"],{Entity["AdministrativeDivision", {"DistrictOfColumbia", "UnitedStates"}]}];
#10005
statenames=StringDrop[#["Name"],-15] /@states;
#10005
popdata=AssociationThread[statenames->Table[QuantityMagnitude[Dated[s,2010]["Population"]],{s,states}]];
#10005
RandomChoice[Normal@popdata]
It’s worth noting that these population counts are slightly different from the official reapportionment numbers, which include overseas residents for each state. The discrepancy is too small to make a difference in my apportionment computations, but it could be a topic for a more detailed exploration.
To start my simulation, I give each state one representative. The initial 50 are actually assigned before applying the formula, so I’ll set those initial priority values at Infinity:
#10005
init=Thread[statenames->?];
From there, districts are assigned based on successively smaller priority values. Historically, no state has received more than 55 seats, so I’ll set the upper limit at 60:
#10005
pvalues=Flatten@Table[Normal@Priority[popdata,i],{i,2,60}];
Since only 435 seats are available, the rest can be dropped:
#10005
app=TakeLargestBy[Join[init,pvalues],Values[#] ,435];
Here’s a function that displays the apportionment data on a map:
#10005
DistrictWeightMap[apportionment_]:=GeoRegionValuePlot[KeyMap[Interpreter["USState"],apportionment]//Normal,GeoRange->Entity["Country", "UnitedStates"],GeoProjection->"Mercator",GeoLabels->(Text[Style[#4,FontFamily->"Arabic Transparent",White,Medium],#3] ),
ImageSize->1200,ColorFunction->(Which[#540,
GeoLabels->(Text[Style[#4,"Text",White,10,FontFamily->"Arabic Transparent"],#3] ),ColorRules->({_?Positive->Green,_?Negative->Red,_->Gray})]
If I reapportion using the current population estimates, Texas and South Carolina both gain a seat, while Wisconsin and Pennsylvania both lose one:
#10005
latestpopdata=AssociationThread[statenames->Table[QuantityMagnitude[s["Population"]],{s,states}]];
#10005
latestpvalues=Flatten@Table[Normal@Priority[latestpopdata,i],{i,2,60}];
#10005
latestapp=TakeLargestBy[Join[init,latestpvalues],Values[#] ,435];
#10005
DistrictDifferenceMap[ReverseSort@Counts[Keys@latestapp],ReverseSort@Counts[Keys@app]]
But population growth also affects the apportionment process in other ways. While the number of districts increased steadily for many years, it has remained essentially constant at 435 since 1913 (a limit codified in 1929). As a result, modern representatives have much larger constituencies than in the past—on average, these have nearly quadrupled over the last century:
#10005
uspophistory=Dated[Entity["Country", "UnitedStates"],All]["Population"];
#10005
DateListPlot[TimeSeriesWindow[uspophistory,{"1918",Today}]/435.,ColorFunction->"DarkRainbow",PlotRange->Full,PlotTheme->"Detailed"]
Some states also end up with much more populous districts than others. Many have argued that this violates the established “one person, one vote” principle by, for instance, giving voters in Wyoming (with around 500,000 voters per representative) more federal voting power than those in Montana (with about 900,000 voters per representative):
#10005
popperdist=ReverseSort@Association@Table[Interpreter["USState"][s]->N[popdata[s]/Counts[Keys@app][s]],{s,statenames}];
#10005
GeoRegionValuePlot[popperdist,GeoProjection->"Mercator",GeoRange->Entity["Country", "UnitedStates"],ColorFunction->"TemperatureMap"]
A Congressional Apportionment Amendment was drafted (but never ratified) that set an initial guideline of “[not] less than one Representative for every forty thousand persons.” Here’s what the breakdown would look like if we used that guideline today:
#10005
newapp=TakeLargestBy[Join[init,Flatten@Table[Normal[Priority[#,i] /@popdata],{i,2,1000}]],Values[#] ,Floor[Total[popdata]/40000.]];
#10005
DistrictWeightMap[newapp]
While the original limitation of 40,000 citizens per representative is perhaps no longer viable (one can imagine how chaotic an 8,000-member legislature would be), adding more seats certainly reduces the population spread among the districts:
#10005
newpopperdist=ReverseSort@Association@Table[Interpreter["USState"][s]->N[popdata[s]/Counts[Keys@newapp][s]],{s,statenames}];
#10005
GeoRegionValuePlot[newpopperdist,GeoProjection->"Mercator",GeoRange->Entity["Country", "UnitedStates"],ColorFunction->"TemperatureMap"]
Of course, apportionment is just the first step. Adding more seats would also mean adding more districts—and that would likely make the next stage a lot more complicated.
Redistricting by the Numbers
Since populations migrate and fluctuate, government officials are constitutionally required to redraw congressional districts following reapportionment. On its surface, this seems straightforward: divide each state into areas of equal population. But the reality can be deceptively complex.
First, using a naive approach, the number of ways to divide a population into equal parts is huge. Suppose you wanted to split a group of 50 people into non-overlapping groups of 10:
#10005
Times@@Binomial[Range[50.,10,-10],10]/2
This issue scales up with the size of the population; with the current population of the US, the number of ways to divide it into 435 equal districts (ignoring all other constraints) is truly astounding:
#10005
(Times@@Binomial[Range[#1,#2,-#2],#2]/#2!) @@{QuantityMagnitude[Entity["Country", "UnitedStates"]["Population"]],435}
Then there’s the problem of actually drawing sensible districts with roughly equal population in each state. Congressional maps are usually drawn and approved by state legislatures, who must meet varying requirements for contiguousness, compactness and other qualities associated with “fair” districts. In a recent Wolfram Community post, Professor Marco Thiel explores a computational approach to drawing unbiased districts; here is how his algorithm splits up Iowa:
The latest district maps are available through the Wolfram Knowledgebase:
#10005
current=KeyDrop[GroupBy[EntityList["USCongressionalDistrict"],#["USState"] ],{"DistrictOfColumbia",Missing["NotApplicable"],Missing["NotAvailable"]}];
This makes it easy to (roughly) check the equal population requirement; the districts within each state differ by less than one percent, on average:
#10005
distpop=Table[DeleteMissing[#["Population"] /@current[s]],{s,statenames}];
#10005
Mean@Table[If[Length[v]>1,N@StandardDeviation[v]/Mean@v,0.],{v,distpop}]
In some cases, the maps have a nice geometric aesthetic, with shapes that fit together like a children’s puzzle. This type of map tends to follow county lines, only straying when necessary to satisfy the equal population requirement. The quintessential example of this is Iowa:
#10005
iacounties=EntityClass["AdministrativeDivision", "USCountiesIowa"];
#10005
Show[GeoListPlot[List/@current["Iowa"],PlotLegends->None],GeoListPlot[iacounties,PlotStyle->Directive[EdgeForm[Blue],FaceForm[Opacity[0]]]]]
Unfortunately, this isn’t the case in most states. By contrast, here is North Carolina’s notoriously jagged map:
#10005
nccounties=EntityClass["AdministrativeDivision", "USCountiesNorthCarolina"];
#10005
Show[GeoListPlot[List/@current["NorthCarolina"],PlotLegends->None],GeoListPlot[nccounties,PlotStyle->Directive[EdgeForm[Blue],FaceForm[Opacity[0]]]]]
This kind of irregular shape is considered one of the main indications of deliberate manipulation of districts (and indeed, North Carolina’s map is currently being contested in court), but that’s not to say that every oddly shaped district is gerrymandered. Crooked borders often evolve slowly as the demography of areas change subtly over time.
Drawing on Experience: Historical Maps
I wanted to dig a bit deeper, so I thought I’d take a look at historical congressional maps that are readily available for viewing and analysis. The TIGER/Shapefile format (with a .zip extension) can be directly imported for a GeoGraphics object containing all the districts combined:
#10005
Import["http://cdmaps.polisci.ucla.edu/shp/districts001.zip"]
For inspecting individual districts, the files also contain detailed data in key-value pairs. I like using Association in this situation, since it lets me reference elements by name:
#10005
c1=Association@First@Import["http://cdmaps.polisci.ucla.edu/shp/districts001.zip","Data"];
#10005
Keys@c1
The "LabeledData" element contains ordered information about individual districts:
#10005
ld=Association@c1["LabeledData"];
Keys@ld
From there, I can create entries that associate each state name with its district numbers and geometry:
#10005
entries=
#[[3]]|>|> /@
Transpose[{
ld["STATENAME"],
ld["DISTRICT"],
Polygon[Cases[#,_GeoPosition,All]] /@c1["Geometry"]
}];
Lastly, I consolidate all entries from each state:
#10005
statenames=Union[Keys@entries]//Flatten;
#10005
districts=Association@Table[Merge[Sort@Select[entries,StringMatchQ[First@Keys@#,s] ],Association],{s,statenames}];
From here, I can easily examine districts on a per-state basis:
#10005
GeoListPlot[List/@Values@districts["Virginia"],PlotLegends->None]
Here is the original districting map for the entire country, drawn by the First United States Congress:
#10005
Show@@Table[GeoListPlot[List/@Values@d,PlotLegends->None],{d,districts}]
I put it all together into a function that can import the full district data from any past Congress into an Association for easy exploration:
#10005
CongressionalMapData[congressnumber_]:=
Module[{baseURL="http://cdmaps.polisci.ucla.edu/shp/",raw,ld,entries,statenames},raw=Association@First@Import[baseURL"districts"StringPadLeft[ToString[congressnumber],3,"0"]".zip","Data"];
ld=Association@raw["LabeledData"];
entries=
#[[3]]|>|> /@Transpose[{ld["STATENAME"],ld["DISTRICT"],
Polygon[Cases[#,_GeoPosition,All]] /@raw["Geometry"]}];
statenames=Union[Keys@entries]//Flatten;
Association@Table[Merge[Sort@Select[entries,StringMatchQ[First@Keys@#,s] ],Association],{s,statenames}]
]
Rather than having to reference by Congress number, it’s easier to reference by year:
#10005
CongressNumber[year_]:=Floor[(year-1787)/2.]
CongressionalMapData[year_?(#>1700 )]:=CongressionalMapData[CongressNumber[year]]
Lastly, here’s a function for visualizing all districts in a state:
#10005
DistrictMap[statedata_]:=GeoListPlot[Table[{s},{s,statedata}],GeoLabels->(Tooltip[#1,FirstPosition[statedata,#1][[1,1]]] ),PlotLegends->None]
This makes it easy to look at individual districts for a given state and year. Looking at the map from 100 years ago, I was surprised to learn that Illinois used to have over 70% more districts:
#10005
dist1918=CongressionalMapData[1918];
#10005
N@Length@current["Illinois"]/Length@dist1918["Illinois"]
This included one “at-large” representative that represented the entire state, rather than a particular district or area. In this data, such districts are numbered “0”:
#10005
GeoGraphics[dist1918["Illinois",0]]
In general, it seems like the population has shifted away from the Midwest region:
#10005
DistrictDifferenceMap[Length/@current,Length/@dist1918]
Importing the full set of maps took me about 40 minutes and most of the RAM on my laptop:
#10005
allmaps=Table[CongressionalMapData[cnum],{cnum,114}];
Here’s a complete history of reapportionment counts:
#10005
frames = Table[{DistrictWeightMap[Length /@ Values /@ allmaps[[i]]],
1789 + 2 i - 1}, {i, 114}];
ListAnimate[Labeled[#1, Style[#2, "Section"], Top] @@@ frames]
With the full dataset, I can look at the history of districts for a particular state, which can give some insights about its development. New York is an interesting case: it started with 10 districts, and continued gaining seats with population growth until it peaked at 44 districts in the mid-20th century. Since then, it’s been losing seats due to population shifts and the 435-member cap on the House. The map has changed nearly every ten-year cycle, indicating that internal demographics have shifted as well:
#10005
nydists=Table[{i,allmaps[[CongressNumber[i],"New York"]]},{i,1793,2013,10}];
#10005
ListAnimate[
Labeled[DistrictMap[#2],
Style[ToString[#1] ": " Capitalize@IntegerName[Length[#2]]
" Districts", "Section"], Top] @@@ nydists,
AnimationRepetitions -> 1,
AnimationRunning -> False]
New Hampshire sits on the other end of the spectrum, having gone through only minimal changes since its original map. It actually kept the same two-district plan for the eight cycles between 1880 and 1960. The simplest explanation is that, unlike New York, this state’s demographics have remained fairly constant (and its population growth average):
#10005
nhdists=Table[{i,allmaps[[CongressNumber[i],"New Hampshire"]]},{i,1793,2013,10}];
#10005
ListAnimate[
Labeled[DistrictMap[#2],
Style[ToString[#1] ": " Capitalize@IntegerName[Length[#2]]
If[Length[#2] == 1, " District", " Districts"], "Section"],
Top] @@@ nhdists,
AnimationRepetitions -> 1,
AnimationRunning -> False]
The maps also illustrate some notable historical events. When the American Civil War broke out, Virginia seceded from the Union. But a group of Unionists in the northwestern part of the state broke from this decision, taking three districts from the state to form West Virginia:
#10005
GeoListPlot[{Values[CongressionalMapData[1859]["Virginia"]],
Values[CongressionalMapData[1863]["West Virginia"]]}]
And of course, when the war was over, the two states remained separate:
#10005
GeoListPlot[{Values[CongressionalMapData[1869]["Virginia"]],
Values[CongressionalMapData[1869]["West Virginia"]]}]
After the war, population counts grew in many southern states because of freed slaves, giving them more national voting power:
#10005
dist1859=CongressionalMapData[1859];
dist1873=CongressionalMapData[1873];
#10005
DistrictDifferenceMap[Length/@dist1873,Length/@dist1859]
In the late 20th century, some states started adjusting maps to create majority-minority districts designed to ensure appropriate representation and voting power for minority groups (as required by the Voting Rights Act of 1965). Opponents of this practice claim that it constitutes racial gerrymandering; in some cases, the Supreme Court has agreed.
For instance, after gaining three seats in 1990, Texas attempted to draw new majority-minority districts to represent both Hispanic and African American voters. In Bush v. Vera, the court ruled that two of the new districts (the 29th and 30th) and one newly manipulated district (the 18th) violated compactness principles too severely:
#10005
dist1993=CongressionalMapData[1993];
Row@Table[Labeled[GeoGraphics[{Green,dist1993["Texas",i]},ImageSize->150],Style[i,"Text",Darker@Green,Bold],Top],{i,{18,29,30}}]
Legislators were forced to redraw the maps:
#10005
dist1997=CongressionalMapData[1997];
Row@Table[Labeled[GeoGraphics[{Green,dist1997["Texas",i]},ImageSize->150],Style[i,"Text",Darker@Green,Bold],Top],{i,{18,29,30}}]
This indicates that while some level of affirmative racial gerrymandering may be acceptable, the shape of a district must still be sensible. Of course, plenty of minority-majority districts exist naturally because of concentrated minority populations. Many of these are in southern regions with large African American populations:
#10005
mm=Import["https://en.wikipedia.org/wiki/List_of_majority-minority_United_States_congressional_districts","Data"];
aalist=mm[[1,1,4,3;;27]];
GeoRegionValuePlot[Table[
current[[StringDelete[aalist[[d,3]]," "],aalist[[d,4]]]]->Quantity[aalist[[d,2]]],{d,Length@aalist}],GeoRange->{{40.,25.}, {-95.,-75.}},GeoProjection->"Mercator"]
There are also a number of southwest regions with Hispanic/Latino-majority districts:
#10005
hisplist=mm[[1,1,6,3;;27]];
GeoRegionValuePlot[Table[
current[[StringDelete[hisplist[[d,3]]," "],hisplist[[d,4]]]]->Quantity[hisplist[[d,2]]],{d,Length@hisplist}],GeoRange->{{38,25},{-120,-95}},GeoProjection->"Mercator"]
Maps are sometimes adjusted to preserve “communities of interest,” such as separating rural and urban populations or keeping a major business in the same district as its workers. States with large metropolitan areas can be especially difficult to draw lines for because of the high population density in those areas. Here in Illinois, the city of Chicago makes up a full 21% of the population:
#10005
N[Entity["City", {"Chicago", "Illinois", "UnitedStates"}]["Population"]/Entity["AdministrativeDivision", {"Illinois", "UnitedStates"}]["Population"]]
A look at the map shows that the city itself sprawls across nearly half the state’s 18 districts in order to distribute that population:
#10005
Show[GeoListPlot[List/@Most[current["Illinois"]],PlotLegends->None],
GeoGraphics[{FaceForm[Directive[Opacity[1.],Black]],EdgeForm[White],Entity["City", {"Chicago", "Illinois", "UnitedStates"}]["Polygon"]}],GeoRange->Entity["City", {"Chicago", "Illinois", "UnitedStates"}]]
Looking at historic maps of the area, it’s clear this wasn’t always the case. Just after the Civil War, the state had 14 districts, with Chicago mostly enclosed in just one:
#10005
dist1865=CongressionalMapData[1865];
Length@dist1865["Illinois"]
#10005
Show[GeoListPlot[List/@Values@dist1865["Illinois"],PlotLegends->None],
GeoGraphics[{FaceForm[Directive[Opacity[1.],Black]],EdgeForm[White],Dated[Entity["City", {"Chicago", "Illinois", "UnitedStates"}],1823]["Polygon"]}],GeoRange->Entity["City", {"Chicago", "Illinois", "UnitedStates"}]]
From this perspective, it’s also clear that the current Illinois districts fall into the “jagged” category, which is often the case when mapmakers start using more complex factors to draw their maps. Since modern redistricting is often done using heavy-duty GIS software with detailed maps and high-resolution census data overlays, it can be difficult to tell what the reasoning was for districts’ shapes—or what kinds of manipulation might have taken place. But there’s growing concern that these manipulations might be damaging to the democratic process.
Gerrymandering and the Supreme Court
Throughout America’s 200-year history, countless legislative bodies (and at least one independent commission) have been accused of partisan gerrymandering—and some of these accusations have gone all the way to the Supreme Court. But to explore this issue effectively, I need to look at more than just maps.
I found comprehensive election data in PDF format from the Clerk of the House. I tried various methods for importing these; in the end I created a package that uses string patterns to sort through election information:
#10005
(KeySort@N[#/Total[#]] /@ilvotes)[[All,1]]],ColorFunction->(Blend[{Red,Blue},#] ),
PlotRange->{0,1}],
GeoGraphics[{FaceForm[Directive[Opacity[1.],Green]],EdgeForm[White],Entity["City", {"Chicago", "Illinois", "UnitedStates"}]["Polygon"]}]]
And aside from a few “purple” bi-state areas, the irregular districts in Chicago appear to tip the balance for Democrats. While no case has been brought forth in Illinois, most critics point to the earmuff-shaped fourth district as a prime example of extreme gerrymandering:
#10005
GeoGraphics[{Green,Polygon@current[["Illinois",4]]}]
Shape-based arguments have historically dominated in gerrymandering cases, and it’s easy to see why—literally. Anyone can look and get a general sense of how complex a shape is. But there are also some geometric tests for measuring the compactness of a district. In his Community post, Marco Thiel tests out a few techniques that involve computing the ratio of a region’s area to the area of a circumscribed shape:
The range considered acceptable for each test can be subjective, but each measure gives a value between 0 and 1. Looking at the distribution of each test among the states, you can get a good sense of what’s average:
#10005
Multicolumn[{CloudGet["https://wolfr.am/vF9vSryp"],
CloudGet["https://wolfr.am/vF9vSHh1"],
CloudGet["https://wolfr.am/vF9vT2uh"],
CloudGet["https://wolfr.am/vF9vTegh"]}, ItemSize -> Full]
Here are some of the least compact districts in the country, according to Marco’s computations:
Application of these and similar geometric tests has led several courts to strike down district maps that lack compactness (like in Texas). But there’s no single way to measure compactness, and some odd shapes are due to natural boundaries and other non-political factors.
Aside from that, both legislators and courts have been reluctant to make any strong statements about partisan gerrymandering because of the inherent political implications: any law or ruling that seems to favor a particular party could be highly criticized. So the fact that the Supreme Court took two cases on this topic (in addition to one on racial gerrymandering) is a pretty big deal.
The first case, Gill v. Whitford, takes a practical approach to the problem: if partisan gerrymandering is the issue, they reason, perhaps it needs a partisan-based solution. Originating in a Wisconsin state court, the plaintiffs presented a case in October 2017 based on a new measure of partisan bias proposed by Nicholas Stephanopoulos and Eric McGhee called efficiency gap. The formula is best summarized as the difference in the total number of wasted votes for each party—including votes cast for a losing candidate and surplus votes cast for a winning candidate—over the total votes cast:
#10005
TraditionalForm[EG==(HoldForm@(Subscript[lost, A]+Subscript[surplus, A])-HoldForm@(Subscript[lost, B]+Subscript[surplus, B]))/(total votes)]
By assuming equal population per district and a two-party system, this formula is conveniently reduced to the difference between a party’s seat margin (percentage of seats over 50%) and twice its vote margin:
#10005
TraditionalForm[EG=="seat margin" - 2 *"vote margin"]
From the data I collected, I can easily compute the seat margins and vote margins:
#10005
SeatMargin[electiondata_]:=With[{pv=PartyVotes[electiondata]},N@(Counts[Flatten@Keys[TakeLargest[#,1] /@pv]]-Length@pv/2)/Length@pv]
VoteMargin[electiondata_]:=N@#/Total[#] @Merge[PartyVotes[electiondata],Total]-.5
For congressional districts, the efficiency gap is given in seats. Here's an implementation of the simplified efficiency gap formula with positive numbers indicating a Democratic advantage and negative indicating a Republican advantage:
#10005
EfficiencyGap[electiondata_]:=Length[GroupBy[electiondata,"District"]] *(KeySort[SeatMargin[electiondata]]-2 KeySort[VoteMargin[electiondata]])
From a legal standpoint, the argument is that the “wasted” votes constitute a violation of the voters’ rights under the Equal Protection Clause. According to the authors, an advantage of two or more seats could indicate district manipulation in a given state. The paper points out a few states with large congressional efficiency gaps in recent cycles:
#10005
Table[With[{data=GroupBy[RepresentativeVotesDataset[state,{1998,2016}],"Year"]},DateListPlot[Transpose[{DateRange[{1998},{2016},2yr],Table[EfficiencyGap@data[[i]],{i,Length@data}][[All,1]]}],PlotTheme->"Scientific"]],{state,{"Michigan","Michigan","North Carolina","Ohio","Pennsylvania","Texas","Virginia"}}]
Although Gill v. Whitford deals with state legislative districts, Wisconsin’s congressional districts seem to show a strong trend toward Republican dominance over the past 20 years as well:
#10005
widata=GroupBy[RepresentativeVotesDataset["Wisconsin",{1998,2016}],"Year"];
#10005
DateListPlot[Transpose[{DateRange[{1998},{2016},2yr],Table[EfficiencyGap@widata[[i]],{i,Length@widata}][[All,1]]}],PlotTheme->"Scientific"]
You can see this effect on the maps, where many previously contentious areas now run more solidly red:
#10005
widists=Table[CongressionalMapData[i]["Wisconsin"],{i,2000,2016,4}];
#10005
wivotes=Table[PartyVotes[RepresentativeVotesDataset["Wisconsin",i]],{i,2000,2016,4}];
#10005
Grid[{Text/@Range[2000,2016,4],
Table[GeoRegionValuePlot[Thread[Values[widists[[i]]]->(KeySort@N[#/Total[#]] /@wivotes[[i]])[[All,1]]],
PlotLegends->None,
ColorFunction->(Blend[{Red,Blue},#] ),
ImageSize->100],{i,Length@widists}]}]
In Benisek v. Lamone (coming from Maryland), the legal argument instead hinges on the First Amendment: casting a vote is considered a form of expression (i.e. speech), and the claim is that the offending district “dilutes the votes” of Republican voters, thus reducing the value of those voters’ speech. While this case presents no particular standard for computing the extent of partisan gerrymandering, it does provide a fresh legal route for applying any standard that might be instated. Either way, the efficiency gap test shows a rather prominent Democratic trend in Maryland:
#10005
mddata=GroupBy[RepresentativeVotesDataset["Maryland",{1998,2016}],"Year"];
#10005
DateListPlot[Transpose[{DateRange[{1998},{2016},2yr],Table[KeySort@EfficiencyGap@mddata[[i]],{i,Length@mddata}][[All,1]]}],PlotTheme->"Scientific"]
And a look at the district in question shows that its latest map is far from compact:
#10005
mddists=Table[CongressionalMapData[i]["Maryland"],{i,2000,2016,8}];
#10005
mdvotes=Table[PartyVotes[RepresentativeVotesDataset["Maryland",i]],{i,2000,2016,8}];
#10005
Grid[{Text/@Range[2000,2016,8],GeoGraphics/@Transpose[{GeoStyling[Blend[{Red,Blue},#]] /@(KeySort@N[#/Total[#]] /@mdvotes[[All,6]])[[All,1]],mddists[[All,6]]}]}]
The Supreme Court also picked up another case in January 2018, this time about racial gerrymandering. Like Bush v. Vera, the case comes from Texas, but this time it’s centered around negative racial gerrymandering. Republican lawmakers are appealing a lower court’s ruling that the state’s latest maps discriminate against racial minorities. The efficiency gap doesn’t exactly translate to this case, but one could conceive of a similar measure based on the wasted votes of racial minorities.
Suffice it to say, the gerrymandering issue is coming to a head. With these three cases combined—as well as recent decisions in North Carolina and Pennsylvania, a ballot initiative in Michigan and all kinds of academic discussions around the country—the stage is set for the Supreme Court to make changes in how redistricting is regulated. Unfortunately, they’ve opted to pass on both partisan gerrymandering cases on technical grounds, so we will likely have to wait until next session to get a major decision.
Gerrymandering is a complex subject with a deep history, and this post only scratches the surface. Exploring with the Wolfram Language helped me pull everything together easily and discover a lot of intricacies I wouldn’t have otherwise found. Now that I've collected all the data in one place, I invite you to do your own exploration. Go find out the history of your district, explore measures of fairness and partition states as you see fit—just don’t forget to go out and vote this November!
Download this post as a Wolfram Notebook.
Ìåäèà: 1.video/mp4 2.video/mp4 3.video/mp4 Êîììåíòàðèè (9) | ↑ |

Powered by RSSfeedReader

Âñå çàãîëîâêè

Books (1)

Computational Thinking (3)

Data Analysis and Visualization (3)

Data Repository (1)

Design (2)

Developer Insights (2)

Education (1)

Machine Learning (1)

Mathematics (3)

Other Application Areas (6)

Raspberry Pi (3)

Recreational Computation (4)

Software Development (3)

SystemModeler (1)

Wolfram Language (3)

Âñå çàãîëîâêè

2018-08-16, ×ò. (1)

2018-08-09, ×ò. (1)

2018-08-02, ×ò. (1)

2018-07-31, Âò. (1)

2018-07-26, ×ò. (1)

2018-07-24, Âò. (1)

2018-07-19, ×ò. (1)

2018-07-12, ×ò. (1)

2018-07-05, ×ò. (1)

2018-06-26, Âò. (1)

Âñå çàãîëîâêè

Aaron Enright (1)

Brian Wood (1)

Chapin Langenheim (1)

Devendra Kapadia (1)

Erez Kaminski (1)

Itai Seggev (1)

Jon McLoone (2)

Patrik Ekenberg (1)

Swede White (1)