gonum.org/v1/gonum@v0.14.0/graph/formats/rdf/iso_canonical_example_test.go (about)

     1  // Copyright ©2020 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package rdf_test
     6  
     7  import (
     8  	"crypto/md5"
     9  	"fmt"
    10  	"log"
    11  	"os"
    12  	"sort"
    13  	"strings"
    14  	"text/tabwriter"
    15  
    16  	"gonum.org/v1/gonum/graph/formats/rdf"
    17  )
    18  
    19  func ExampleIsoCanonicalHashes_isomorphisms() {
    20  	for _, statements := range []string{
    21  		`
    22  <https://example.com/1> <https://example.com/2> <https://example.com/3> .
    23  <https://example.com/3> <https://example.com/4> <https://example.com/5> .
    24  `,
    25  		`
    26  _:a <ex:q> <ex:p> .
    27  _:b <ex:q> <ex:p> .
    28  _:c <ex:p> _:a .
    29  _:d <ex:p> _:b .
    30  _:c <ex:r> _:d .
    31  `,
    32  		`
    33  _:a1 <ex:q> <ex:p> .
    34  _:b1 <ex:q> <ex:p> .
    35  _:c1 <ex:p> _:a1 .
    36  _:d1 <ex:p> _:b1 .
    37  _:c1 <ex:r> _:d1 .
    38  `,
    39  		`
    40  # G
    41  <ex:p> <ex:q> _:a .
    42  <ex:p> <ex:q> _:b .
    43  <ex:s> <ex:p> _:a .
    44  <ex:s> <ex:r> _:c .
    45  _:c <ex:p> _:b .
    46  
    47  # H
    48  <ex:p> <ex:q> _:d .
    49  <ex:p> <ex:q> _:e .
    50  _:f <ex:p> _:d .
    51  _:f <ex:r> _:g .
    52  _:g <ex:p> _:e .
    53  `,
    54  		`
    55  _:greet <l:is> "hola"@es .
    56  `,
    57  	} {
    58  		// Decode the statement stream.
    59  		dec := rdf.NewDecoder(strings.NewReader(statements))
    60  		var s []*rdf.Statement
    61  		for {
    62  			l, err := dec.Unmarshal()
    63  			if err != nil {
    64  				break
    65  			}
    66  			s = append(s, l)
    67  		}
    68  
    69  		// Get the node label to hash look-up table.
    70  		hashes, _ := rdf.IsoCanonicalHashes(s, false, true, md5.New(), make([]byte, 16))
    71  
    72  		// Get all the blank nodes.
    73  		var blanks []string
    74  		for k := range hashes {
    75  			if strings.HasPrefix(k, "_:") {
    76  				blanks = append(blanks, k)
    77  			}
    78  		}
    79  		sort.Strings(blanks)
    80  
    81  		if len(blanks) == 0 {
    82  			fmt.Println("No blank nodes.")
    83  		} else {
    84  			w := tabwriter.NewWriter(os.Stdout, 0, 4, 1, ' ', 0)
    85  			fmt.Fprintln(w, "Node\tHash")
    86  			for _, k := range blanks {
    87  				fmt.Fprintf(w, "%s\t%032x\n", k, hashes[k])
    88  			}
    89  			w.Flush()
    90  		}
    91  		fmt.Println()
    92  	}
    93  
    94  	// Output:
    95  	//
    96  	// No blank nodes.
    97  	//
    98  	// Node Hash
    99  	// _:a  d4db6df055d5611e9d8aa6ea621561d1
   100  	// _:b  ad70e47f2b026064c7f0922060512b9a
   101  	// _:c  dafd81e6fa603d3e11c898d631e8673f
   102  	// _:d  7e318557b09444e88791721becc2a8e7
   103  	//
   104  	// Node Hash
   105  	// _:a1 d4db6df055d5611e9d8aa6ea621561d1
   106  	// _:b1 ad70e47f2b026064c7f0922060512b9a
   107  	// _:c1 dafd81e6fa603d3e11c898d631e8673f
   108  	// _:d1 7e318557b09444e88791721becc2a8e7
   109  	//
   110  	// Node Hash
   111  	// _:a  44ad49b6df3aea91ddbcef932c93e3b4
   112  	// _:b  ba3ffd8b271a8545b1a3a9042e75ce4b
   113  	// _:c  34e1bd90b6758b4a766e000128caa6a6
   114  	// _:d  eb2a47c1032f623647d0497a2ff74052
   115  	// _:e  1d9ed02f28d87e555feb904688bc2449
   116  	// _:f  d3b00d36ea503dcc8d234e4405feab81
   117  	// _:g  55127e4624c0a4fe5990933a48840af8
   118  	//
   119  	// Node    Hash
   120  	// _:greet 0d9ba18a037a3fa67e46fce821fe51b4
   121  }
   122  
   123  func ExampleIsoCanonicalHashes_isomorphicParts() {
   124  	for _, statements := range []string{
   125  		`
   126  # Part 1
   127  _:a <ex:q> <ex:p> .
   128  _:b <ex:q> <ex:p> .
   129  _:c <ex:p> _:a .
   130  _:d <ex:p> _:b .
   131  _:c <ex:r> _:d .
   132  
   133  # Part 2
   134  _:a1 <ex:q> <ex:p> .
   135  _:b1 <ex:q> <ex:p> .
   136  _:c1 <ex:p> _:a1 .
   137  _:d1 <ex:p> _:b1 .
   138  _:c1 <ex:r> _:d1 .
   139  `,
   140  	} {
   141  		// Decode the statement stream.
   142  		dec := rdf.NewDecoder(strings.NewReader(statements))
   143  		var s []*rdf.Statement
   144  		for {
   145  			l, err := dec.Unmarshal()
   146  			if err != nil {
   147  				break
   148  			}
   149  			s = append(s, l)
   150  		}
   151  
   152  		// Get the node label to hash look-up table. This time
   153  		// we will decompose the dataset into splits and not
   154  		// distinguish nodes. This will then group nodes from
   155  		// the two isomorphic parts. Otherwise each node in
   156  		// the complete dataset would get a unique hash.
   157  		hashes, _ := rdf.IsoCanonicalHashes(s, true, false, md5.New(), make([]byte, 16))
   158  
   159  		// Get all the blank nodes.
   160  		var blanks []string
   161  		for k := range hashes {
   162  			if strings.HasPrefix(k, "_:") {
   163  				blanks = append(blanks, k)
   164  			}
   165  		}
   166  		sort.Strings(blanks)
   167  
   168  		if len(blanks) == 0 {
   169  			fmt.Println("No blank nodes.")
   170  		} else {
   171  			w := tabwriter.NewWriter(os.Stdout, 0, 4, 1, ' ', 0)
   172  			fmt.Fprintln(w, "Node\tHash")
   173  			for _, k := range blanks {
   174  				fmt.Fprintf(w, "%s\t%032x\n", k, hashes[k])
   175  			}
   176  			w.Flush()
   177  		}
   178  		fmt.Println()
   179  	}
   180  
   181  	// Output:
   182  	//
   183  	// Node Hash
   184  	// _:a  d4db6df055d5611e9d8aa6ea621561d1
   185  	// _:a1 d4db6df055d5611e9d8aa6ea621561d1
   186  	// _:b  ad70e47f2b026064c7f0922060512b9a
   187  	// _:b1 ad70e47f2b026064c7f0922060512b9a
   188  	// _:c  dafd81e6fa603d3e11c898d631e8673f
   189  	// _:c1 dafd81e6fa603d3e11c898d631e8673f
   190  	// _:d  7e318557b09444e88791721becc2a8e7
   191  	// _:d1 7e318557b09444e88791721becc2a8e7
   192  }
   193  
   194  func ExampleC14n() {
   195  	for _, statements := range []string{
   196  		`
   197  _:a <ex:q> <ex:p> .
   198  _:b <ex:q> <ex:p> .
   199  _:c <ex:p> _:a .
   200  _:d <ex:p> _:b .
   201  _:c <ex:r> _:d .
   202  `,
   203  		`
   204  _:c1 <ex:p> _:a1 .
   205  _:b1 <ex:q> <ex:p> .
   206  _:d1 <ex:p> _:b1 .
   207  _:a1 <ex:q> <ex:p> .
   208  _:c1 <ex:r> _:d1 .
   209  `,
   210  	} {
   211  		// Decode the statement stream.
   212  		dec := rdf.NewDecoder(strings.NewReader(statements))
   213  		var s []*rdf.Statement
   214  		for {
   215  			l, err := dec.Unmarshal()
   216  			if err != nil {
   217  				break
   218  			}
   219  			s = append(s, l)
   220  		}
   221  
   222  		// Get the hash to term label look-up table.
   223  		_, terms := rdf.IsoCanonicalHashes(s, false, true, md5.New(), make([]byte, 16))
   224  
   225  		relabeled, err := rdf.C14n(nil, s, terms)
   226  		if err != nil {
   227  			log.Fatal(err)
   228  		}
   229  
   230  		for _, s := range relabeled {
   231  			fmt.Println(s)
   232  		}
   233  		fmt.Println()
   234  	}
   235  
   236  	// Output:
   237  	//
   238  	// _:c14n0 <ex:p> _:c14n1 .
   239  	// _:c14n1 <ex:q> <ex:p> .
   240  	// _:c14n2 <ex:q> <ex:p> .
   241  	// _:c14n3 <ex:p> _:c14n2 .
   242  	// _:c14n3 <ex:r> _:c14n0 .
   243  	//
   244  	// _:c14n0 <ex:p> _:c14n1 .
   245  	// _:c14n1 <ex:q> <ex:p> .
   246  	// _:c14n2 <ex:q> <ex:p> .
   247  	// _:c14n3 <ex:p> _:c14n2 .
   248  	// _:c14n3 <ex:r> _:c14n0 .
   249  }