*! version on 1.0 27feb2020

/*
 luvain_gcd generates a toy example of a weighted graph. It takes an integer as
 an argument and it then generates a graph of pairs of numbers from one to the
 its argument weighted by their gcd-1.
 This means co-primes are not connected and high weights mean high gcd. When you
 subsequently apply the luvain clustering module you can gain insight and intuition
 into the luvain clustering method.
 This program is a quicky so it is probably inefficient and will not scale. Then
 again it does not have to. Values of 10,20 etc are the easisets to interpret.
*/

program def luvain_gcd
	version 16.0

	syntax anything(name=nn)

	*check python-louvain is present
	 capture confirm integer number `nn'
	if _rc != 0 {

		di as smcl "Argument should be integer."
		exit
	}
	clear
	python: from sfi import Macro as macro
	python: nn = int(macro.getLocal('nn'))
	python: luvain_gcd(nn)
	qui tostring *node, replace


end


*** Python below here


version 16.0
python:

def luvain_gcd(g):

	import itertools
	import math
	import pandas as pd

	from sfi import Data as data

	#this is the empty set.
	myset = set()
	#loop over cartesian product
	for i in itertools.product([i for i in range(1,nn+1)],[i for i in range(1,nn+1)]):
		#add to set
		myset.add(frozenset(i))


	#drop the self edges
	edges = set()
	for i in myset:
		if len(i)==2:
			edges.add(i)

	#now go back to list of lists
	edges = [list(i) for i in edges]

	#this will hold our weighted graph
	g=[]
	# for every edge add the gcd of its nodes minus one if non-zero
	for edge in edges:
		if  math.gcd(edge[0],edge[1])-1 != 0:
			g.append([edge[0],edge[1], math.gcd(edge[0],edge[1])-1])
	g = pd.DataFrame.from_records(g, columns=["snode","tnode","weight"])
	#now we create the dataset
	data.setObsTotal(len(g))
	data.addVarInt('snode')
	data.store('snode',range(len(g)),g['snode'].to_list())
	data.addVarInt('tnode')
	data.store('tnode',range(len(g)),g['tnode'].to_list())
	data.addVarInt('weight')
	data.store('weight',range(len(g)),g['weight'].to_list())

end