10
$\begingroup$

House of Graphs is a fun little website that provides access to a number of interesting graphs. Unfortunately it doesn't have a readily-accessible API.

Can I still get access to the data underneath?

$\endgroup$
11
$\begingroup$

I did this one by request from Szabolcs. It was a little tough and my implementation is still only in the 1.0.0 stage, but if the demand is there I can polish up the parts of it that remain too rough. To get started, we can install the ServiceConnection like so:

PacletInstall[
 "ServiceConnection_HouseOfGraphs",
 "Site" -> 
  "http://www.wolframcloud.com/objects/b3m2a1.paclets/PacletServer"
 ]

asdasdasd

You can read through my template notebook here but I'll hit some of the highlights

Now we can ServiceConnect and get to work:

$hog = ServiceConnect["HouseOfGraphs"]

enter image description here

And see the requests I cooked in:

$hog["Requests"]

{"Authentication", "BasicSearch", "DownloadGraph", "GraphImage", \
"GraphInfo", "ID", "Information", "InvariantDefinition", \
"LastRequest", "ListInvariants", "Name", "RawRequests", \
"RequestData", "RequestParameters", "SearchParameters"}

Of these the one with the most support is the "BasicSearch":

res = $hog["BasicSearch", "invariantId" -> "Claw-Free", 
  "invariantValue" -> True]

blah

res["Graphs"] // Normal

{<|"id" -> "46", "NumNodes" -> 7, "NumEdges" -> 16|>, <|"id" -> "44", 
  "NumNodes" -> 7, "NumEdges" -> 15|>, <|"id" -> "54", 
  "NumNodes" -> 7, "NumEdges" -> 18|>, <|"id" -> "58", 
  "NumNodes" -> 7, "NumEdges" -> 21|>, <|"id" -> "50", 
  "NumNodes" -> 7, "NumEdges" -> 17|>, <|"id" -> "26", 
  "NumNodes" -> 7, "NumEdges" -> 16|>, <|"id" -> "62", 
  "NumNodes" -> 5, "NumEdges" -> 0|>, <|"id" -> "52", "NumNodes" -> 4,
   "NumEdges" -> 0|>, <|"id" -> "56", "NumNodes" -> 7, 
  "NumEdges" -> 20|>, <|"id" -> "64", "NumNodes" -> 6, 
  "NumEdges" -> 0|>}

You can specify the search "Mode" but in general it tries to auto-detect that based on the parameters you pass. You can find the supported modes like so:

Keys@$hog["SearchParameters"]

{"InvariantValue", "InvariantClass", "InvariantRange", \
"InterestingFor", "WithName"}

And the supported arguments for each "Mode" like:

Keys@$hog["SearchParameters"]["InvariantRange"]

{"invariantId", "invariantValueFrom", "invariantValueTo"}

etc.

This is actually implemented by scraping the results page for a search (I couldn't find the equivalent of "format=json"). These values I find by parsing the XMLObject of the results. To determine what the parameters were valid I did a similar thing for the primary search page:

xml = Import[
   "https://hog.grinvin.org/StartNewSearch.action", {"HTML", 
    "XMLObject"}];
Merge[
 Cases[xml, 
  XMLElement["form", 
    {___, "id" -> i_, ___},
    e_
    ] :>
   i ->
    Association@Cases[e,
      XMLElement["select", {___, "name" -> name_, ___}, o_] :>
       name ->
        Association@
         Cases[o, 
          XMLElement["option", {___, "value" -> v_, ___}, {oname_}] :>
            ToLowerCase[oname] -> v, \[Infinity]
          ],
      \[Infinity]
      ],
  \[Infinity]
  ],
 Merge[Apply[Join]]
 ]

Then I cooked this into my service connection (see the template I liked to for more details) so that we can pretend we have a REST API.

Once you have a graph you can get its properties with "GraphInfo":

info = $hog["GraphInfo", "id" -> res["Graphs", 1, "id"]]

enter image description here

And you can turn this into a proper Graph via the "matrix" structure:

AdjacencyGraph@Normal@info["Structures", "matrix"]

blah

Or we can get the "GraphImage":

img

Note that in general unless I've implemented the scrape a request will just return the XMLObject for a page. You can always scrape that yourself, though:

Cases[
   $hog["ListInvariants"], 
   XMLElement[
     "a", {"shape" -> "rect", 
      "href" -> l_?(StringStartsQ["/ShowInvariant"])}, {tag_}] :>
    tag -> ToExpression@Lookup[URLParse[l, "Query"], "id"],
   \[Infinity]
   ] // Association // Sort

<|"Acyclic" -> 1, "Average Degree" -> 2, "Bipartite" -> 3, 
 "Chromatic Number" -> 4, "Clique Number" -> 5, "Connected" -> 6, 
 "Diameter" -> 7, "Edge Connectivity" -> 8, "Girth" -> 9, 
 "Maximum Degree" -> 10, "Matching Number" -> 11, 
 "Minimum Degree" -> 12, "Minimum Dominating Set" -> 13, 
 "Number of Edges" -> 14, "Number of Vertices" -> 15, "Radius" -> 16, 
 "Regular" -> 17, "Independence Number" -> 18, 
 "Algebraic Connectivity" -> 19, "Chromatic Index" -> 20, 
 "Index" -> 21, "Laplacian Largest Eigenvalue" -> 22, 
 "Second Largest Eigenvalue" -> 23, "Smallest Eigenvalue" -> 24, 
 "Longest Induced Path" -> 25, "Number of Components" -> 26, 
 "Number of Triangles" -> 27, "Eulerian" -> 28, "Hamiltonian" -> 29, 
 "Vertex Connectivity" -> 30, "Longest Induced Cycle" -> 31, 
 "Genus" -> 32, "Claw-Free" -> 33|>

(Note that I just implemented this in the paclet so you'll actually get a good result from $hog["ListInvariants"] now)

Hope this is useful and let me know if you have questions.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.