(in-package db.agraph.user)

(load (compile-file "sna-utilities.lisp"))

(register-namespace "f" "http://www.franz.com/ont/")

(enable-print-decoded t)

(index-status-report)

;;;; small sample graphs

;;; centrality measures 

(build-star-graph 7)
(setf group (select0 ?x (q- ?x !rdf:type !sna:node)))

(print+ "star" 
	(group-degree-centrality group 'linksToOrFrom)
	(group-closeness-centrality group 'linksToOrFrom)
	(group-betweenness-centrality group 'linksToOrFrom)
	(graph-density group 'linksToOrFrom))

(build-circle-graph 7)
(setf group (select0 ?x (q- ?x !rdf:type !sna:node)))

(print+ "circle" 
	(group-degree-centrality group 'linksToOrFrom)
	(group-closeness-centrality group 'linksToOrFrom)
	(group-betweenness-centrality group 'linksToOrFrom)
	(graph-density group 'linksToOrFrom))

(build-line-graph 7)
(setf group (select0 ?x (q- ?x !rdf:type !sna:node)))

(print+ "line" 
	(group-degree-centrality group 'linksToOrFrom)
	(group-closeness-centrality group 'linksToOrFrom)
	(group-betweenness-centrality group 'linksToOrFrom)
	(graph-density group 'linksToOrFrom))

;;;; cliques

(build-graph-7.1)

(cliques !sna:1 'linksToOrFrom)

(cliques !sna:3 'linksToOrFrom :minimum-size 4)

;; too many results ?
(cliques !sna:3 'linksToOrFrom)


;;; funny social network

#+(or)
(create-network 5000 40 "/tmp/sna-1e4")

(open-triple-store "/tmp/sna-1e4")

(triple-count)

;;;; search

(sna-generator knows () (:undirected :p !f:knows))

(bidirectional-search !f:person-0 !f:person-1 'knows)

(db.agraph::bidirectional-distance 		      
 *db* !f:person-0 !f:person-1 'knows)

;; random searching
;; roughly the diameter of the graph
(time 
 (let ((total 0)
       (count 0))
   (loop repeat 100 do
	(let* ((s (random-person))
	       (e (random-person))
	       (distance (length (bidirectional-search
				  s e 'knows))))
	  (incf total distance)
	  (incf count)
	  #+(or)
	  (format t "~&~a ~a ~d"
		  s e distance)))
   (format t "~&Average ~a" (round-to (/ total count) 3))))


(depth-first-search
 !f:person-0 !f:person-1 'knows :maximum-depth 20)

(breadth-first-search
 !f:person-0 !f:person-1 'knows :maximum-depth 20)

;;;;;

;;;; degrees and neighbors

(sna-generator intimate-with () (:undirected :p !f:intimate-with))
(sna-generator ate-with () (:undirected :p !f:ate-with))
(sna-generator kissed-with () (:undirected :p !f:kissed-with))

(nodal-neighbors !f:person-1743 'knows)

(nodal-neighbors !f:person-1743 'ate-with)

(nodal-neighbors !f:person-1743 'kissed-with)

(nodal-neighbors !f:person-1743 'intimate-with)

(nodal-in-degree !f:person-1743 'kissed-with)

(nodal-in-neighbors !f:person-1743 'kissed-with)

(nodal-out-neighbors !f:person-1743 'kissed-with)

;;;; ego groups

;; who has 1743 slept with?
(ego-group
 !f:person-1743
 1
 'intimate-with)

;; partners of partners (of partners)
(loop for depth from 1 to 4 collect
	   (list depth 
		 (length 
		  (ego-group
		   !f:person-1743
		   depth
		   'intimate-with))))



;; who do you know and who do they know (and who do they know..)
(loop for depth from 1 to 3 collect
	   (list depth 
		 (length
		  (ego-group
		   !f:person-1743
		   depth
		   'knows))))

; ((1 45) (2 1638) (3 9986))

;;;;

;; no manage a trois here!
(cliques 
 !f:person-1743 
 'intimate-with)

;; can we find one in the first hundred?

(loop for i from 1 to 100
     for cliques = (cliques 
		    (intern-person i) 
		    'intimate-with
		    :minimum-size 3)
    when cliques collect (list i cliques))

;; study buddies
(cliques 
 !f:person-1743 
 'knows)

;; just one
(cliques 
 !f:person-1743 'knows
 :minimum-size 4)
 
;;;; centrality measures

(setf actor      !f:person-1743
      generator  'intimate-with
      group      (ego-group actor 2 generator))


;; how central is 1743 to their intimate group?
;; use degree
(actor-degree-centrality actor group generator)

(loop repeat 5 do
     (let* ((other (random-element group))
	    (other-centrality
	     (actor-degree-centrality other group generator)))
       (print+ "Other: " other ", centrality: " other-centrality)))

;; use closeness
(actor-closeness-centrality actor group generator)

(loop repeat 5 do
     (let* ((other (random-element group))
	    (other-centrality
	     (actor-closeness-centrality other group generator)))
       (print+ "Other: " other ", centrality: " other-centrality)))


;; use betweenness
(actor-betweenness-centrality actor group generator)

(loop repeat 5 do
     (let* ((other (random-element group))
	    (other-centrality
	     (actor-betweenness-centrality other group generator)))
       (print+ "Other: " other ", centrality: " other-centrality)))
