diff --git a/Credits.txt b/Credits.txt index 02c670093..55331467d 100644 --- a/Credits.txt +++ b/Credits.txt @@ -8,6 +8,7 @@ extensively by SNAP, was started by Marko Grobelnik in 1996. The following people also contributed to the development of SNAP (in alphabetical order). +Ruth-Ann Armstrong Arijit Banerjee Austin Benson Justin Cheng @@ -19,6 +20,7 @@ Agrim Gupta Shubham Gupta Tim Hsieh Richard Hsu +Farzaan Kaiyom Chentai Kao Mario Karlovcec Nikhil Khadke @@ -26,6 +28,7 @@ Vikesh Khanna Emmanouil Kiagias Myunghwan Kim Vid Kocijan +Viswesh Krishna Saachi Jain Jason Jong Peter Lofgren @@ -52,6 +55,7 @@ Ba-Quan Truong Utkarsh Upadhyay Theodore Vasiloudis Viswajith Venugopal +Avery Wang Jaewon Yang Hao Yin David Zeng diff --git a/License.txt b/License.txt new file mode 100644 index 000000000..f07e0ccba --- /dev/null +++ b/License.txt @@ -0,0 +1,24 @@ +* Copyright (c) 2007-2019, Jure Leskovec +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of Stanford University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile.config b/Makefile.config index cfbb92ba7..b8235aec3 100644 --- a/Makefile.config +++ b/Makefile.config @@ -38,23 +38,36 @@ else ifeq ($(UNAME), Darwin) CXXFLAGS += -std=c++98 -Wall -Wno-unknown-pragmas CXXFLAGS += -O3 -DNDEBUG CLANG := $(shell g++ -v 2>&1 | grep clang | cut -d " " -f 2) - ifneq ($(CLANG), LLVM) - CXXFLAGS += -fopenmp - #CXXOPENMP += -fopenmp - else + ifeq ($(CLANG), LLVM) + CXXFLAGS += -DNOMP + CXXOPENMP = + else ifeq ($(CLANG), clang) CXXFLAGS += -DNOMP CXXOPENMP = + else + CXXFLAGS += -fopenmp + #CXXOPENMP += -fopenmp endif LDFLAGS += LIBS += + # If a dynamic library, i.e. gtest, is installed in some local directory, + # for example by Anaconda, the program might fail with 'image not found'. + # Use one of the solutions below. + # 1. set the path to the lib directory in the executable at linking time + #LDFLAGS += -Wl,-rpath,$(HOME)/miniconda3/lib + # 2. set one of the following environment variables from your shell at run time + #export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/miniconda3/lib + #export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$HOME/miniconda3/lib + #export DYLD_FALLBACK_LIBRARY_PATH=$DYLD_FALLBACK_LIBRARY_PATH:$HOME/miniconda3/lib + else ifeq ($(shell uname -o), Cygwin) # Cygwin flags CC = g++ CXXFLAGS += -Wall -D__STDC_LIMIT_MACROS CXXFLAGS += -O3 -DNDEBUG CXXOPENMP = -fopenmp - LDFLAGS += + LDFLAGS += -fopenmp LIBS += endif diff --git a/Release.txt b/Release.txt index 595c9c0a6..78ec3f21f 100644 --- a/Release.txt +++ b/Release.txt @@ -1,8 +1,84 @@ +Release Notes for SNAP + Stanford Network Analysis Platform (SNAP) is a general purpose, high -performance system for graph and network manipulation and analysis +performance system for graph and network manipulation and analysis. This file contains a high-level description of changes in SNAP releases. +Release 6.0, Dec 4, 2020 + +This is a major release, significant new functionality includes: a large family +of egonet functions, dense and sparse floating-point vector attributes, graph +union functions. + +Here is a detailed list: + +- implemented a large family of egonet functions GetEgonetHop(), + GetInEgonetHop(), GetOutEgonetHop(), GetInEgonetSub(), GetEgonetAttr(), + GetInEgonetAttr(), GetOutEgonetAttr(), GetInEgonetSubAttr() +- implemented dense and sparse floating-point vector attributes for TNEANet +- implemented graph union functions GetGraphUnion(), GetGraphUnionAttr() +- implemented a new method TSnapQueue::Sample() +- implemented AddNodeWithAttributes() and AddEdgeWithAttributes() +- improved CommunityGirvanNewman(), so that the input graph is not modified +- improved GetClustCf(), so that all output parameters are initialized +- added dummy AddEdge(), IsEdge() methods with edge IDs to TUNGraph and + TNGraph classes for compatibility with TNEANet +- changed the parameter names for GetClustCf(), which is needed for snap.py +- updated the definition of gettimeofday() for compilation of snap.py with + python 3.5 and 3.6 on Windows +- completed the implementation of aaMean policy in AggregateVector() +- defined '/' operator for TStr, which is required in AggregateVector() +- fixed the problem of GetStrVal() and AddRow() not being available in snap.py +- fixed the handling of the random generator in GenDegSeq() and GenPrefAttach() +- fixed a bug in edge attribute iterator in IntAttrValueEI() +- fixed bugs in AddIntVAttrDatE(), AppendIntVAttrDatE() +- fixed a few minor issues in the documentation +- fixed compilation problems with TTable::GetStrVal() +- improved parameters for OpenMP compilation on Cygwin and macOS +- improved doxygen parameters and updated doxyblock.py for python3 +- updated Makefiles with $(HOME) references +- updated Makefiles with additional instructions for building on Anaconda +- updated graphviz baseline files for graphviz version 2.38.0 + +Release 5.0, Aug 29, 2019 + +This is a maintenance release and brings several upgrades. + +Here is a detailed list: + +- upgraded Visual Studio files to version 2019 +- added support for g++ compiler versions 6.0+ +- modified the code for python3 support +- added a license text +- implemented rolx:FPrintNodeMappings() to determine node IDs for features +- turned on the printing of feature matrix in rolx +- removed the Visual Studio 2008 solution file + +Release 4.1, Jul 25, 2018 + +This is a minor release and brings several bug fixes and improvements. + +Here is a detailed list: + +- fixed the parsing of floating point numbers in TSsParserMP +- fixed bugs in temporal motif counting, ignore self loops +- fixed a bug in GetWeightedShortestPath() +- fixed a bug in GenRndPowerLaw(), GenDegSeq() requires a sorted vector +- fixed a crash in GetESubGraph() for multigraphs +- improved LoadPajek(), so that it can read edges without weights +- improved the parsing of integers in TSsParserMP +- improved the quality of word2vec embeddings +- added a flag for random walk output in node2vec +- defined a new type TFltVFltV for TVec +- fixed compilation errors and a few compilation warnings on macOS +- implemented GetSubGraphRenumber(), which is required by Snap.py +- implemented GetNodeTriadsAll(), which is needed by Snap.py +- implemented GetBfsEffDiamAll(), which is needed by Snap.py +- implemented GetClustCfAll(), which is needed by Snap.py +- implemented GetTriadsAll(), which is needed by Snap.py +- added 'const' to node2vec code to make it work with Snap.py + Release 4.0, Jul 27, 2017 This is a major release and brings significant new functionality: local diff --git a/doxygen/Doxyfile-dev b/doxygen/Doxyfile-dev index 683a2975d..e56bdc956 100644 --- a/doxygen/Doxyfile-dev +++ b/doxygen/Doxyfile-dev @@ -681,7 +681,7 @@ INPUT_ENCODING = UTF-8 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl -FILE_PATTERNS = +FILE_PATTERNS = *.h *.cpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. diff --git a/doxygen/Doxyfile-user b/doxygen/Doxyfile-user index 603f9120d..21f61ee59 100644 --- a/doxygen/Doxyfile-user +++ b/doxygen/Doxyfile-user @@ -681,7 +681,7 @@ INPUT_ENCODING = UTF-8 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl -FILE_PATTERNS = +FILE_PATTERNS = *.h *.cpp # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. diff --git a/doxygen/Makefile b/doxygen/Makefile index 17385555a..cbb4a7246 100644 --- a/doxygen/Makefile +++ b/doxygen/Makefile @@ -15,7 +15,7 @@ SLVER := $(VERSION) DOXYGEN = doxygen ifeq ($(shell uname), Darwin) # OS X values - DOXYGEN = /Applications/Doxygen.app/Contents/Resources/doxygen + #DOXYGEN = /Applications/Doxygen.app/Contents/Resources/doxygen endif dummy: diff --git a/doxygen/doxyblock.py b/doxygen/doxyblock.py index 2a895c42e..d86475f0f 100644 --- a/doxygen/doxyblock.py +++ b/doxygen/doxyblock.py @@ -78,10 +78,10 @@ def convert(dirpath,srcname,dstname): f.close() def insert(lines,bfile,bname): - #print "*** .%s. .%s." % (bfile, bname) + #print("*** .%s. .%s." % (bfile, bname)) if not os.path.exists(bfile): - print "*** Error: file not found - file:.%s." % (bfile) + print("*** Error: file not found - file:.%s." % (bfile)) sys.exit(1) f = open(bfile) @@ -100,14 +100,14 @@ def insert(lines,bfile,bname): # get the label match blabel = words[1] - #print "+++ .%s. .%s." % (blabel, l) + #print("+++ .%s. .%s." % (blabel, l)) if bname == blabel: found = True break if not found: f.close() - print "*** Error: block not found - file:.%s., block:.%s." % (bfile, bname) + print("*** Error: block not found - file:.%s., block:.%s." % (bfile, bname)) sys.exit(1) return @@ -128,7 +128,7 @@ def insert(lines,bfile,bname): if __name__ == '__main__': if len(sys.argv) < 3: - print "Usage: " + sys.argv[0] + " " + print("Usage: " + sys.argv[0] + " ") sys.exit(1) srcdir = sys.argv[1] diff --git a/examples/.gitignore b/examples/.gitignore index 66e457bac..2687a05c4 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -2,3 +2,5 @@ !*/Makefile */.DS_Store */*.dSYM + +Release \ No newline at end of file diff --git a/examples/Makefile b/examples/Makefile index 069c58891..35a9d8543 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,87 +1,106 @@ -# -# Makefile for non-Microsoft compilers -# - -all: MakeAll - -MakeAll: - $(MAKE) -C agmfit - $(MAKE) -C agmgen - $(MAKE) -C bigclam - $(MAKE) -C cascadegen - $(MAKE) -C cascades - $(MAKE) -C centrality - $(MAKE) -C cesna - $(MAKE) -C circles - $(MAKE) -C cliques - $(MAKE) -C coda - $(MAKE) -C community - $(MAKE) -C concomp - $(MAKE) -C flows - $(MAKE) -C forestfire - $(MAKE) -C graphgen - $(MAKE) -C graphhash - $(MAKE) -C infopath - $(MAKE) -C kcores - $(MAKE) -C knnjaccardsim - $(MAKE) -C kronem - $(MAKE) -C kronfit - $(MAKE) -C krongen - $(MAKE) -C localmotifcluster - $(MAKE) -C lshtest - $(MAKE) -C magfit - $(MAKE) -C maggen - $(MAKE) -C mkdatasets - # 'motifcluster' compilation skipped by default, it requires ARPACK - #$(MAKE) -C motifcluster - $(MAKE) -C motifs - $(MAKE) -C ncpplot - $(MAKE) -C netevol - $(MAKE) -C netinf - $(MAKE) -C netstat - $(MAKE) -C node2vec - $(MAKE) -C randwalk - $(MAKE) -C rolx - $(MAKE) -C temporalmotifs - $(MAKE) -C testgraph - -clean: - $(MAKE) clean -C agmgen - $(MAKE) clean -C agmfit - $(MAKE) clean -C bigclam - $(MAKE) clean -C cascadegen - $(MAKE) clean -C cascades - $(MAKE) clean -C centrality - $(MAKE) clean -C cesna - $(MAKE) clean -C circles - $(MAKE) clean -C cliques - $(MAKE) clean -C coda - $(MAKE) clean -C community - $(MAKE) clean -C concomp - $(MAKE) clean -C flows - $(MAKE) clean -C forestfire - $(MAKE) clean -C graphgen - $(MAKE) clean -C graphhash - $(MAKE) clean -C infopath - $(MAKE) clean -C kcores - $(MAKE) clean -C knnjaccardsim - $(MAKE) clean -C kronem - $(MAKE) clean -C kronfit - $(MAKE) clean -C krongen - $(MAKE) clean -C localmotifcluster - $(MAKE) clean -C lshtest - $(MAKE) clean -C magfit - $(MAKE) clean -C maggen - $(MAKE) clean -C mkdatasets - $(MAKE) clean -C motifcluster - $(MAKE) clean -C motifs - $(MAKE) clean -C ncpplot - $(MAKE) clean -C netevol - $(MAKE) clean -C netinf - $(MAKE) clean -C netstat - $(MAKE) clean -C node2vec - $(MAKE) clean -C randwalk - $(MAKE) clean -C rolx - $(MAKE) clean -C temporalmotifs - $(MAKE) clean -C testgraph - rm -rf Debug Release ipch +# +# Makefile for non-Microsoft compilers +# + +all: MakeAll + +MakeAll: + mkdir Release + $(MAKE) -C agmfit + $(MAKE) -C agmgen + $(MAKE) -C bigclam + $(MAKE) -C cascadegen + $(MAKE) -C cascades + $(MAKE) -C centrality + $(MAKE) -C cesna + $(MAKE) -C circles + $(MAKE) -C cliques + $(MAKE) -C coda + $(MAKE) -C community + $(MAKE) -C concomp + $(MAKE) -C flows + $(MAKE) -C forestfire + $(MAKE) -C graphgen + $(MAKE) -C graphhash + $(MAKE) -C hysgen + $(MAKE) -C infopath + $(MAKE) -C kcores + $(MAKE) -C knnjaccardsim + $(MAKE) -C kronem + $(MAKE) -C kronfit + $(MAKE) -C krongen + $(MAKE) -C localmotifcluster + $(MAKE) -C lshtest + $(MAKE) -C magfit + $(MAKE) -C maggen + $(MAKE) -C mkdatasets + # 'motifcluster' compilation skipped by default, it requires ARPACK + #$(MAKE) -C motifcluster + $(MAKE) -C motifs + $(MAKE) -C ncpplot + $(MAKE) -C netevol + $(MAKE) -C netinf + $(MAKE) -C netstat + $(MAKE) -C node2vec + $(MAKE) -C randwalk + $(MAKE) -C rolx + $(MAKE) -C temporalmotifs + $(MAKE) -C testgraph + +clean: + $(MAKE) clean -C agmgen + $(MAKE) clean -C agmfit + $(MAKE) clean -C bigclam + $(MAKE) clean -C cascadegen + $(MAKE) clean -C cascades + $(MAKE) clean -C centrality + $(MAKE) clean -C cesna + $(MAKE) clean -C circles + $(MAKE) clean -C cliques + $(MAKE) clean -C coda + $(MAKE) clean -C community + $(MAKE) clean -C concomp + $(MAKE) clean -C flows + $(MAKE) clean -C forestfire + $(MAKE) clean -C graphgen + $(MAKE) clean -C graphhash + $(MAKE) clean -C hysgen + $(MAKE) clean -C infopath + $(MAKE) clean -C kcores + $(MAKE) clean -C knnjaccardsim + $(MAKE) clean -C kronem + $(MAKE) clean -C kronfit + $(MAKE) clean -C krongen + $(MAKE) clean -C localmotifcluster + $(MAKE) clean -C lshtest + $(MAKE) clean -C magfit + $(MAKE) clean -C maggen + $(MAKE) clean -C mkdatasets + $(MAKE) clean -C motifcluster + $(MAKE) clean -C motifs + $(MAKE) clean -C ncpplot + $(MAKE) clean -C netevol + $(MAKE) clean -C netinf + $(MAKE) clean -C netstat + $(MAKE) clean -C node2vec + $(MAKE) clean -C randwalk + $(MAKE) clean -C rolx + $(MAKE) clean -C temporalmotifs + $(MAKE) clean -C testgraph + rm -rf Debug Release ipch *.tgz *.zip + +bin-linux: + mv Release Snap-$(VERSION)-Ubuntu18.04 + tar zcvf Snap-$(VERSION)-Ubuntu18.04.tgz Snap-$(VERSION)-Ubuntu18.04 + mv Snap-$(VERSION)-Ubuntu18.04 Release + +bin-mac: + mv Release Snap-$(VERSION)-macOS14.10 + tar zcvf Snap-$(VERSION)-macOS14.10.tgz Snap-$(VERSION)-macOS14.10 + mv Snap-$(VERSION)-macOS14.10 Release + +bin-win: + mv Release Snap-$(VERSION)-Win32 + zip -r Snap-$(VERSION)-Win32.zip Snap-$(VERSION)-Win32/*.exe + mv Snap-$(VERSION)-Win32 Release + diff --git a/examples/Makefile.exmain b/examples/Makefile.exmain index e1a012bf9..adf2660a2 100644 --- a/examples/Makefile.exmain +++ b/examples/Makefile.exmain @@ -1,16 +1,17 @@ -# -# Makefile for non-Microsoft compilers -# - -all: $(MAIN) - -# COMPILE -$(MAIN): $(MAIN).cpp $(DEPH) $(DEPCPP) $(EXSNAP)/Snap.o - $(CC) $(CXXFLAGS) -o $(MAIN) $(MAIN).cpp $(DEPCPP) $(EXSNAP)/Snap.o -I$(EXSNAP) -I$(EXSNAPADV) -I$(EXGLIB) -I$(EXSNAPEXP) $(LDFLAGS) $(LIBS) - -$(EXSNAP)/Snap.o: - make -C $(EXSNAP) - -clean: - rm -f *.o $(MAIN) $(MAIN).exe - rm -rf Debug Release +# +# Makefile for non-Microsoft compilers +# + +all: $(MAIN) + +# COMPILE +$(MAIN): $(MAIN).cpp $(DEPH) $(DEPCPP) $(EXSNAP)/Snap.o + $(CC) $(CXXFLAGS) -o $(MAIN) $(MAIN).cpp $(DEPCPP) $(EXSNAP)/Snap.o -I$(EXSNAP) -I$(EXSNAPADV) -I$(EXGLIB) -I$(EXSNAPEXP) $(LDFLAGS) $(LIBS) + cp $(MAIN) ../Release + +$(EXSNAP)/Snap.o: + make -C $(EXSNAP) + +clean: + rm -f *.o $(MAIN) $(MAIN).exe + rm -rf Debug Release diff --git a/examples/SnapExamples-VS08.sln b/examples/SnapExamples-VS08.sln deleted file mode 100644 index b46ce2ad0..000000000 --- a/examples/SnapExamples-VS08.sln +++ /dev/null @@ -1,178 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "agmgen", "agmgen\agmgen.vcproj", "{1BAC236F-C118-487D-8584-4E911B30080C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cascades", "cascades\cascades.vcproj", "{60E5066B-4AE0-49D0-B482-75BE307F1C04}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "centrality", "centrality\centrality.vcproj", "{6D5B617C-EFD4-11DE-A84C-189A55D89593}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cliques", "cliques\cliques.vcproj", "{CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "community", "community\community.vcproj", "{6D5B617C-EFD4-11DE-A84C-189A55D89594}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "concomp", "concomp\concomp.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "forestfire", "forestfire\forestfire.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "graphgen", "graphgen\graphgen.vcproj", "{59BC1999-6B67-414F-91B0-0D02AEAC3E1D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kcores", "kcores\kcores.vcproj", "{CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kronem", "kronem\kronem.vcproj", "{E4CDCAFA-FEA6-4F99-AF60-C565A1EC8197}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kronfit", "kronfit\kronfit.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "krongen", "krongen\krongen.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "magfit", "magfit\magfit.vcproj", "{2A3A0B57-83B1-40A3-9109-1A1C04384269}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "maggen", "maggen\maggen.vcproj", "{CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mkdatasets", "mkdatasets\mkdatasets.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "motifs", "motifs\motifs.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ncpplot", "ncpplot\ncpplot.vcproj", "{D744773B-A887-425A-A715-AADB2AE9511A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netevol", "netevol\netevol.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netstat", "netstat\netstat.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgraph", "testgraph\testgraph.vcproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1BAC236F-C118-487D-8584-4E911B30080C}.Debug|Win32.ActiveCfg = Debug|Win32 - {1BAC236F-C118-487D-8584-4E911B30080C}.Debug|Win32.Build.0 = Debug|Win32 - {1BAC236F-C118-487D-8584-4E911B30080C}.Debug|x64.ActiveCfg = Debug|Win32 - {1BAC236F-C118-487D-8584-4E911B30080C}.Release|Win32.ActiveCfg = Release|Win32 - {1BAC236F-C118-487D-8584-4E911B30080C}.Release|Win32.Build.0 = Release|Win32 - {1BAC236F-C118-487D-8584-4E911B30080C}.Release|x64.ActiveCfg = Release|Win32 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|Win32.ActiveCfg = Debug|Win32 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|Win32.Build.0 = Debug|Win32 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|x64.ActiveCfg = Debug|x64 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|x64.Build.0 = Debug|x64 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Release|Win32.ActiveCfg = Release|Win32 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Release|Win32.Build.0 = Release|Win32 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Release|x64.ActiveCfg = Release|x64 - {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Release|x64.Build.0 = Release|x64 - {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Debug|Win32.ActiveCfg = Debug|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Debug|Win32.Build.0 = Debug|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Debug|x64.ActiveCfg = Debug|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Release|Win32.ActiveCfg = Release|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Release|Win32.Build.0 = Release|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Release|x64.ActiveCfg = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Debug|Win32.ActiveCfg = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Debug|Win32.Build.0 = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Debug|x64.ActiveCfg = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Release|Win32.ActiveCfg = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Release|Win32.Build.0 = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Release|x64.ActiveCfg = Release|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Debug|Win32.ActiveCfg = Debug|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Debug|Win32.Build.0 = Debug|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Debug|x64.ActiveCfg = Debug|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Release|Win32.ActiveCfg = Release|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Release|Win32.Build.0 = Release|Win32 - {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Release|x64.ActiveCfg = Release|Win32 - {59BC1999-6B67-414F-91B0-0D02AEAC3E1D}.Debug|Win32.ActiveCfg = Debug|Win32 - {59BC1999-6B67-414F-91B0-0D02AEAC3E1D}.Debug|Win32.Build.0 = Debug|Win32 - {59BC1999-6B67-414F-91B0-0D02AEAC3E1D}.Debug|x64.ActiveCfg = Debug|Win32 - {59BC1999-6B67-414F-91B0-0D02AEAC3E1D}.Release|Win32.ActiveCfg = Release|Win32 - {59BC1999-6B67-414F-91B0-0D02AEAC3E1D}.Release|Win32.Build.0 = Release|Win32 - {59BC1999-6B67-414F-91B0-0D02AEAC3E1D}.Release|x64.ActiveCfg = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Debug|Win32.ActiveCfg = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Debug|Win32.Build.0 = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Debug|x64.ActiveCfg = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Release|Win32.ActiveCfg = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Release|Win32.Build.0 = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Release|x64.ActiveCfg = Release|Win32 - {E4CDCAFA-FEA6-4F99-AF60-C565A1EC8197}.Debug|Win32.ActiveCfg = Debug|Win32 - {E4CDCAFA-FEA6-4F99-AF60-C565A1EC8197}.Debug|Win32.Build.0 = Debug|Win32 - {E4CDCAFA-FEA6-4F99-AF60-C565A1EC8197}.Debug|x64.ActiveCfg = Debug|Win32 - {E4CDCAFA-FEA6-4F99-AF60-C565A1EC8197}.Release|Win32.ActiveCfg = Release|Win32 - {E4CDCAFA-FEA6-4F99-AF60-C565A1EC8197}.Release|Win32.Build.0 = Release|Win32 - {E4CDCAFA-FEA6-4F99-AF60-C565A1EC8197}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Release|x64.ActiveCfg = Release|Win32 - {2A3A0B57-83B1-40A3-9109-1A1C04384269}.Debug|Win32.ActiveCfg = Debug|Win32 - {2A3A0B57-83B1-40A3-9109-1A1C04384269}.Debug|Win32.Build.0 = Debug|Win32 - {2A3A0B57-83B1-40A3-9109-1A1C04384269}.Debug|x64.ActiveCfg = Debug|Win32 - {2A3A0B57-83B1-40A3-9109-1A1C04384269}.Release|Win32.ActiveCfg = Release|Win32 - {2A3A0B57-83B1-40A3-9109-1A1C04384269}.Release|Win32.Build.0 = Release|Win32 - {2A3A0B57-83B1-40A3-9109-1A1C04384269}.Release|x64.ActiveCfg = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Debug|Win32.ActiveCfg = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Debug|Win32.Build.0 = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Debug|x64.ActiveCfg = Debug|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Release|Win32.ActiveCfg = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Release|Win32.Build.0 = Release|Win32 - {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Release|x64.ActiveCfg = Release|Win32 - {D744773B-A887-425A-A715-AADB2AE9511A}.Debug|Win32.ActiveCfg = Debug|Win32 - {D744773B-A887-425A-A715-AADB2AE9511A}.Debug|Win32.Build.0 = Debug|Win32 - {D744773B-A887-425A-A715-AADB2AE9511A}.Debug|x64.ActiveCfg = Debug|Win32 - {D744773B-A887-425A-A715-AADB2AE9511A}.Release|Win32.ActiveCfg = Release|Win32 - {D744773B-A887-425A-A715-AADB2AE9511A}.Release|Win32.Build.0 = Release|Win32 - {D744773B-A887-425A-A715-AADB2AE9511A}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Release|x64.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Debug|Win32.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Debug|Win32.Build.0 = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Debug|x64.ActiveCfg = Debug|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Release|Win32.ActiveCfg = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Release|Win32.Build.0 = Release|Win32 - {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Release|x64.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/examples/SnapExamples-VS19.sln b/examples/SnapExamples-VS19.sln new file mode 100644 index 000000000..14667a445 --- /dev/null +++ b/examples/SnapExamples-VS19.sln @@ -0,0 +1,274 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ncpplot", "ncpplot\ncpplot.vcxproj", "{D744773B-A887-425A-A715-AADB2AE9511A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "forestfire", "forestfire\forestfire.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kronfit", "kronfit\kronfit.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "krongen", "krongen\krongen.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgraph", "testgraph\testgraph.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netstat", "netstat\netstat.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netevol", "netevol\netevol.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mkdatasets", "mkdatasets\mkdatasets.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "concomp", "concomp\concomp.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "centrality", "centrality\centrality.vcxproj", "{6D5B617C-EFD4-11DE-A84C-189A55D89593}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "community", "community\community.vcxproj", "{6D5B617C-EFD4-11DE-A84C-189A55D89594}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cascades", "cascades\cascades.vcxproj", "{60E5066B-4AE0-49D0-B482-75BE307F1C04}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "motifs", "motifs\motifs.vcxproj", "{345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cliques", "cliques\cliques.vcxproj", "{CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "agmgen", "agmgen\agmgen.vcxproj", "{1BAC236F-C118-487D-8584-4E911B30080C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "graphgen", "graphgen\graphgen.vcxproj", "{101ACD69-D26C-4AA9-AC8A-41199C797209}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kcores", "kcores\kcores.vcxproj", "{CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kronem", "kronem\kronem.vcxproj", "{37F61708-477C-453A-B227-E1969CE80CFC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "magfit", "magfit\magfit.vcxproj", "{23608159-9241-41FE-8D2F-87BF82F96622}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "maggen", "maggen\maggen.vcxproj", "{CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "graphhash", "graphhash\graphhash.vcxproj", "{CCB155FF-3FA8-45CF-A1DD-54770FDD2E00}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "agmfit", "agmfit\agmfit.vcxproj", "{272D305C-DE86-42A4-9F88-40C56CEAD799}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bigclam", "bigclam\bigclam.vcxproj", "{28DB5D47-AB1D-4C0A-8D80-28A873591489}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cesna", "cesna\cesna.vcxproj", "{67C001C3-4BF0-4148-AD17-5D342442232B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cascadegen", "cascadegen\cascadegen.vcxproj", "{D50C735B-84C0-4DDC-BFED-0E042DB624D2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "circles", "circles\circles.vcxproj", "{DE8DB708-94E6-4974-9E65-8C89237B75E9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "coda", "coda\coda.vcxproj", "{501FFCE2-5AD2-4F5F-85E6-B74D16952C33}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flows", "flows\flows.vcxproj", "{3ADEFCB0-0784-4043-B14B-A032F31BC79E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "infopath", "infopath\infopath.vcxproj", "{E2F8D443-E2A2-495D-B8DA-D63B4F899F26}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netinf", "netinf\netinf.vcxproj", "{B45DF0B7-664F-4D53-AB00-10A3B7BE915F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "randwalk", "randwalk\randwalk.vcxproj", "{5306FD82-52D6-4C15-97B5-F33777149529}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rolx", "rolx\rolx.vcxproj", "{54A2FDEC-58F5-4EFA-A10A-838263E89629}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D744773B-A887-425A-A715-AADB2AE9511A}.Debug|Win32.ActiveCfg = Debug|Win32 + {D744773B-A887-425A-A715-AADB2AE9511A}.Debug|Win32.Build.0 = Debug|Win32 + {D744773B-A887-425A-A715-AADB2AE9511A}.Debug|x64.ActiveCfg = Debug|Win32 + {D744773B-A887-425A-A715-AADB2AE9511A}.Release|Win32.ActiveCfg = Release|Win32 + {D744773B-A887-425A-A715-AADB2AE9511A}.Release|Win32.Build.0 = Release|Win32 + {D744773B-A887-425A-A715-AADB2AE9511A}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE09}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE08}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE07}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE03}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE04}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE05}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE06}.Release|x64.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5BD9A5FE02}.Release|x64.ActiveCfg = Release|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Debug|Win32.Build.0 = Debug|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Debug|x64.ActiveCfg = Debug|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Release|Win32.ActiveCfg = Release|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Release|Win32.Build.0 = Release|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89593}.Release|x64.ActiveCfg = Release|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Debug|Win32.Build.0 = Debug|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Debug|x64.ActiveCfg = Debug|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Release|Win32.ActiveCfg = Release|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Release|Win32.Build.0 = Release|Win32 + {6D5B617C-EFD4-11DE-A84C-189A55D89594}.Release|x64.ActiveCfg = Release|Win32 + {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|Win32.ActiveCfg = Debug|Win32 + {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|Win32.Build.0 = Debug|Win32 + {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|x64.ActiveCfg = Debug|x64 + {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Debug|x64.Build.0 = Debug|x64 + {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Release|Win32.ActiveCfg = Release|Win32 + {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Release|Win32.Build.0 = Release|Win32 + {60E5066B-4AE0-49D0-B482-75BE307F1C04}.Release|x64.ActiveCfg = Release|x64 + {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Debug|Win32.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Debug|Win32.Build.0 = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Debug|x64.ActiveCfg = Debug|Win32 + {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Release|Win32.ActiveCfg = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Release|Win32.Build.0 = Release|Win32 + {345EFCD5-A5BA-4C41-928C-AE5CD9A5FE08}.Release|x64.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Debug|Win32.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Debug|Win32.Build.0 = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Debug|x64.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Release|Win32.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Release|Win32.Build.0 = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAA}.Release|x64.ActiveCfg = Release|Win32 + {1BAC236F-C118-487D-8584-4E911B30080C}.Debug|Win32.ActiveCfg = Debug|Win32 + {1BAC236F-C118-487D-8584-4E911B30080C}.Debug|Win32.Build.0 = Debug|Win32 + {1BAC236F-C118-487D-8584-4E911B30080C}.Debug|x64.ActiveCfg = Debug|Win32 + {1BAC236F-C118-487D-8584-4E911B30080C}.Release|Win32.ActiveCfg = Release|Win32 + {1BAC236F-C118-487D-8584-4E911B30080C}.Release|Win32.Build.0 = Release|Win32 + {1BAC236F-C118-487D-8584-4E911B30080C}.Release|x64.ActiveCfg = Release|Win32 + {101ACD69-D26C-4AA9-AC8A-41199C797209}.Debug|Win32.ActiveCfg = Debug|Win32 + {101ACD69-D26C-4AA9-AC8A-41199C797209}.Debug|Win32.Build.0 = Debug|Win32 + {101ACD69-D26C-4AA9-AC8A-41199C797209}.Debug|x64.ActiveCfg = Debug|Win32 + {101ACD69-D26C-4AA9-AC8A-41199C797209}.Release|Win32.ActiveCfg = Release|Win32 + {101ACD69-D26C-4AA9-AC8A-41199C797209}.Release|Win32.Build.0 = Release|Win32 + {101ACD69-D26C-4AA9-AC8A-41199C797209}.Release|x64.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Debug|Win32.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Debug|Win32.Build.0 = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Debug|x64.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Release|Win32.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Release|Win32.Build.0 = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAB}.Release|x64.ActiveCfg = Release|Win32 + {37F61708-477C-453A-B227-E1969CE80CFC}.Debug|Win32.ActiveCfg = Debug|Win32 + {37F61708-477C-453A-B227-E1969CE80CFC}.Debug|Win32.Build.0 = Debug|Win32 + {37F61708-477C-453A-B227-E1969CE80CFC}.Debug|x64.ActiveCfg = Debug|Win32 + {37F61708-477C-453A-B227-E1969CE80CFC}.Release|Win32.ActiveCfg = Release|Win32 + {37F61708-477C-453A-B227-E1969CE80CFC}.Release|Win32.Build.0 = Release|Win32 + {37F61708-477C-453A-B227-E1969CE80CFC}.Release|x64.ActiveCfg = Release|Win32 + {23608159-9241-41FE-8D2F-87BF82F96622}.Debug|Win32.ActiveCfg = Debug|Win32 + {23608159-9241-41FE-8D2F-87BF82F96622}.Debug|Win32.Build.0 = Debug|Win32 + {23608159-9241-41FE-8D2F-87BF82F96622}.Debug|x64.ActiveCfg = Debug|Win32 + {23608159-9241-41FE-8D2F-87BF82F96622}.Release|Win32.ActiveCfg = Release|Win32 + {23608159-9241-41FE-8D2F-87BF82F96622}.Release|Win32.Build.0 = Release|Win32 + {23608159-9241-41FE-8D2F-87BF82F96622}.Release|x64.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Debug|Win32.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Debug|Win32.Build.0 = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Debug|x64.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Release|Win32.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Release|Win32.Build.0 = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2EAC}.Release|x64.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2E00}.Debug|Win32.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2E00}.Debug|Win32.Build.0 = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2E00}.Debug|x64.ActiveCfg = Debug|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2E00}.Release|Win32.ActiveCfg = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2E00}.Release|Win32.Build.0 = Release|Win32 + {CCB155FF-3FA8-45CF-A1DD-54770FDD2E00}.Release|x64.ActiveCfg = Release|Win32 + {272D305C-DE86-42A4-9F88-40C56CEAD799}.Debug|Win32.ActiveCfg = Debug|Win32 + {272D305C-DE86-42A4-9F88-40C56CEAD799}.Debug|Win32.Build.0 = Debug|Win32 + {272D305C-DE86-42A4-9F88-40C56CEAD799}.Debug|x64.ActiveCfg = Debug|Win32 + {272D305C-DE86-42A4-9F88-40C56CEAD799}.Release|Win32.ActiveCfg = Release|Win32 + {272D305C-DE86-42A4-9F88-40C56CEAD799}.Release|Win32.Build.0 = Release|Win32 + {272D305C-DE86-42A4-9F88-40C56CEAD799}.Release|x64.ActiveCfg = Release|x64 + {28DB5D47-AB1D-4C0A-8D80-28A873591489}.Debug|Win32.ActiveCfg = Debug|Win32 + {28DB5D47-AB1D-4C0A-8D80-28A873591489}.Debug|Win32.Build.0 = Debug|Win32 + {28DB5D47-AB1D-4C0A-8D80-28A873591489}.Debug|x64.ActiveCfg = Debug|Win32 + {28DB5D47-AB1D-4C0A-8D80-28A873591489}.Release|Win32.ActiveCfg = Release|Win32 + {28DB5D47-AB1D-4C0A-8D80-28A873591489}.Release|Win32.Build.0 = Release|Win32 + {28DB5D47-AB1D-4C0A-8D80-28A873591489}.Release|x64.ActiveCfg = Release|x64 + {67C001C3-4BF0-4148-AD17-5D342442232B}.Debug|Win32.ActiveCfg = Debug|Win32 + {67C001C3-4BF0-4148-AD17-5D342442232B}.Debug|Win32.Build.0 = Debug|Win32 + {67C001C3-4BF0-4148-AD17-5D342442232B}.Debug|x64.ActiveCfg = Debug|Win32 + {67C001C3-4BF0-4148-AD17-5D342442232B}.Release|Win32.ActiveCfg = Release|Win32 + {67C001C3-4BF0-4148-AD17-5D342442232B}.Release|Win32.Build.0 = Release|Win32 + {67C001C3-4BF0-4148-AD17-5D342442232B}.Release|x64.ActiveCfg = Release|Win32 + {67C001C3-4BF0-4148-AD17-5D342442232B}.Release|x64.Build.0 = Release|Win32 + {D50C735B-84C0-4DDC-BFED-0E042DB624D2}.Debug|Win32.ActiveCfg = Debug|Win32 + {D50C735B-84C0-4DDC-BFED-0E042DB624D2}.Debug|Win32.Build.0 = Debug|Win32 + {D50C735B-84C0-4DDC-BFED-0E042DB624D2}.Debug|x64.ActiveCfg = Debug|Win32 + {D50C735B-84C0-4DDC-BFED-0E042DB624D2}.Release|Win32.ActiveCfg = Release|Win32 + {D50C735B-84C0-4DDC-BFED-0E042DB624D2}.Release|Win32.Build.0 = Release|Win32 + {D50C735B-84C0-4DDC-BFED-0E042DB624D2}.Release|x64.ActiveCfg = Release|Win32 + {DE8DB708-94E6-4974-9E65-8C89237B75E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {DE8DB708-94E6-4974-9E65-8C89237B75E9}.Debug|Win32.Build.0 = Debug|Win32 + {DE8DB708-94E6-4974-9E65-8C89237B75E9}.Debug|x64.ActiveCfg = Debug|Win32 + {DE8DB708-94E6-4974-9E65-8C89237B75E9}.Release|Win32.ActiveCfg = Release|Win32 + {DE8DB708-94E6-4974-9E65-8C89237B75E9}.Release|Win32.Build.0 = Release|Win32 + {DE8DB708-94E6-4974-9E65-8C89237B75E9}.Release|x64.ActiveCfg = Release|Win32 + {501FFCE2-5AD2-4F5F-85E6-B74D16952C33}.Debug|Win32.ActiveCfg = Debug|Win32 + {501FFCE2-5AD2-4F5F-85E6-B74D16952C33}.Debug|Win32.Build.0 = Debug|Win32 + {501FFCE2-5AD2-4F5F-85E6-B74D16952C33}.Debug|x64.ActiveCfg = Debug|Win32 + {501FFCE2-5AD2-4F5F-85E6-B74D16952C33}.Release|Win32.ActiveCfg = Release|Win32 + {501FFCE2-5AD2-4F5F-85E6-B74D16952C33}.Release|Win32.Build.0 = Release|Win32 + {501FFCE2-5AD2-4F5F-85E6-B74D16952C33}.Release|x64.ActiveCfg = Release|Win32 + {3ADEFCB0-0784-4043-B14B-A032F31BC79E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3ADEFCB0-0784-4043-B14B-A032F31BC79E}.Debug|Win32.Build.0 = Debug|Win32 + {3ADEFCB0-0784-4043-B14B-A032F31BC79E}.Debug|x64.ActiveCfg = Debug|Win32 + {3ADEFCB0-0784-4043-B14B-A032F31BC79E}.Release|Win32.ActiveCfg = Release|Win32 + {3ADEFCB0-0784-4043-B14B-A032F31BC79E}.Release|Win32.Build.0 = Release|Win32 + {3ADEFCB0-0784-4043-B14B-A032F31BC79E}.Release|x64.ActiveCfg = Release|Win32 + {E2F8D443-E2A2-495D-B8DA-D63B4F899F26}.Debug|Win32.ActiveCfg = Debug|Win32 + {E2F8D443-E2A2-495D-B8DA-D63B4F899F26}.Debug|Win32.Build.0 = Debug|Win32 + {E2F8D443-E2A2-495D-B8DA-D63B4F899F26}.Debug|x64.ActiveCfg = Debug|Win32 + {E2F8D443-E2A2-495D-B8DA-D63B4F899F26}.Release|Win32.ActiveCfg = Release|Win32 + {E2F8D443-E2A2-495D-B8DA-D63B4F899F26}.Release|Win32.Build.0 = Release|Win32 + {E2F8D443-E2A2-495D-B8DA-D63B4F899F26}.Release|x64.ActiveCfg = Release|Win32 + {B45DF0B7-664F-4D53-AB00-10A3B7BE915F}.Debug|Win32.ActiveCfg = Debug|Win32 + {B45DF0B7-664F-4D53-AB00-10A3B7BE915F}.Debug|Win32.Build.0 = Debug|Win32 + {B45DF0B7-664F-4D53-AB00-10A3B7BE915F}.Debug|x64.ActiveCfg = Debug|Win32 + {B45DF0B7-664F-4D53-AB00-10A3B7BE915F}.Release|Win32.ActiveCfg = Release|Win32 + {B45DF0B7-664F-4D53-AB00-10A3B7BE915F}.Release|Win32.Build.0 = Release|Win32 + {B45DF0B7-664F-4D53-AB00-10A3B7BE915F}.Release|x64.ActiveCfg = Release|Win32 + {5306FD82-52D6-4C15-97B5-F33777149529}.Debug|Win32.ActiveCfg = Debug|Win32 + {5306FD82-52D6-4C15-97B5-F33777149529}.Debug|Win32.Build.0 = Debug|Win32 + {5306FD82-52D6-4C15-97B5-F33777149529}.Debug|x64.ActiveCfg = Debug|Win32 + {5306FD82-52D6-4C15-97B5-F33777149529}.Release|Win32.ActiveCfg = Release|Win32 + {5306FD82-52D6-4C15-97B5-F33777149529}.Release|Win32.Build.0 = Release|Win32 + {5306FD82-52D6-4C15-97B5-F33777149529}.Release|x64.ActiveCfg = Release|Win32 + {54A2FDEC-58F5-4EFA-A10A-838263E89629}.Debug|Win32.ActiveCfg = Debug|Win32 + {54A2FDEC-58F5-4EFA-A10A-838263E89629}.Debug|Win32.Build.0 = Debug|Win32 + {54A2FDEC-58F5-4EFA-A10A-838263E89629}.Debug|x64.ActiveCfg = Debug|Win32 + {54A2FDEC-58F5-4EFA-A10A-838263E89629}.Release|Win32.ActiveCfg = Release|Win32 + {54A2FDEC-58F5-4EFA-A10A-838263E89629}.Release|Win32.Build.0 = Release|Win32 + {54A2FDEC-58F5-4EFA-A10A-838263E89629}.Release|x64.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/examples/agmfit/agmfit.vcxproj b/examples/agmfit/agmfit.vcxproj index 5900178dd..9217a3a9a 100644 --- a/examples/agmfit/agmfit.vcxproj +++ b/examples/agmfit/agmfit.vcxproj @@ -1,162 +1,166 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {272D305C-DE86-42A4-9F88-40C56CEAD799} - Win32Proj - agmfit - - - - Application - true - MultiByte - - - Application - true - NotSet - - - Application - false - true - Unicode - - - Application - false - true - NotSet - - - - - - - - - - - - - - - - - - - true - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - true - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - false - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - false - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {272D305C-DE86-42A4-9F88-40C56CEAD799} + Win32Proj + agmfit + + + + Application + true + MultiByte + v142 + + + Application + true + NotSet + v142 + + + Application + false + true + MultiByte + v142 + + + Application + false + true + NotSet + v142 + + + + + + + + + + + + + + + + + + + true + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + true + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + false + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + false + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + \ No newline at end of file diff --git a/examples/agmgen/agmgen.vcxproj b/examples/agmgen/agmgen.vcxproj index 47f6f0f31..7aad9c90d 100644 --- a/examples/agmgen/agmgen.vcxproj +++ b/examples/agmgen/agmgen.vcxproj @@ -26,21 +26,25 @@ Application - NotSet + MultiByte true + v142 Application NotSet true + v142 Application NotSet + v142 Application NotSet + v142 diff --git a/examples/bigclam/bigclam.vcxproj b/examples/bigclam/bigclam.vcxproj index d40da63b6..4174025b6 100644 --- a/examples/bigclam/bigclam.vcxproj +++ b/examples/bigclam/bigclam.vcxproj @@ -1,164 +1,168 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {28DB5D47-AB1D-4C0A-8D80-28A873591489} - Win32Proj - bigclam - - - - Application - true - MultiByte - - - Application - true - NotSet - - - Application - false - true - Unicode - - - Application - false - true - NotSet - - - - - - - - - - - - - - - - - - - true - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - true - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - false - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - false - ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {28DB5D47-AB1D-4C0A-8D80-28A873591489} + Win32Proj + bigclam + + + + Application + true + MultiByte + v142 + + + Application + true + NotSet + v142 + + + Application + false + true + MultiByte + v142 + + + Application + false + true + NotSet + v142 + + + + + + + + + + + + + + + + + + + true + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + true + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + false + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + false + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + \ No newline at end of file diff --git a/examples/cascadegen/cascadegen.vcxproj b/examples/cascadegen/cascadegen.vcxproj index 46dfe36da..bdb32d262 100644 --- a/examples/cascadegen/cascadegen.vcxproj +++ b/examples/cascadegen/cascadegen.vcxproj @@ -26,21 +26,25 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 Application NotSet true + v142 Application NotSet + v142 @@ -74,6 +78,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/cascades/cascades.vcxproj b/examples/cascades/cascades.vcxproj index eaadc395e..fcf21c78a 100644 --- a/examples/cascades/cascades.vcxproj +++ b/examples/cascades/cascades.vcxproj @@ -26,21 +26,25 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 Application NotSet true + v142 Application NotSet + v142 @@ -74,6 +78,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/centrality/centrality.vcxproj b/examples/centrality/centrality.vcxproj index 1f2669c4a..aac68d060 100644 --- a/examples/centrality/centrality.vcxproj +++ b/examples/centrality/centrality.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/cesna/cesna.vcxproj b/examples/cesna/cesna.vcxproj index 9db795053..10d5bef99 100644 --- a/examples/cesna/cesna.vcxproj +++ b/examples/cesna/cesna.vcxproj @@ -20,12 +20,14 @@ Application true MultiByte + v142 Application false true MultiByte + v142 diff --git a/examples/circles/circles.vcxproj b/examples/circles/circles.vcxproj index f4dfa7747..a2225394d 100644 --- a/examples/circles/circles.vcxproj +++ b/examples/circles/circles.vcxproj @@ -26,21 +26,25 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 Application NotSet true + v142 Application NotSet + v142 @@ -74,6 +78,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/cliques/cliques.vcxproj b/examples/cliques/cliques.vcxproj index 7067aa700..aa4ed74cb 100644 --- a/examples/cliques/cliques.vcxproj +++ b/examples/cliques/cliques.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/coda/coda.vcxproj b/examples/coda/coda.vcxproj index e6a47d4d2..9d233dabc 100644 --- a/examples/coda/coda.vcxproj +++ b/examples/coda/coda.vcxproj @@ -26,21 +26,25 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 Application NotSet true + v142 Application NotSet + v142 @@ -74,6 +78,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/community/community.vcxproj b/examples/community/community.vcxproj index 0c13691f9..3869a2900 100644 --- a/examples/community/community.vcxproj +++ b/examples/community/community.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/concomp/concomp.vcxproj b/examples/concomp/concomp.vcxproj index 6a2e760f8..61aceacd8 100644 --- a/examples/concomp/concomp.vcxproj +++ b/examples/concomp/concomp.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/flows/flows.vcxproj b/examples/flows/flows.vcxproj index 4133507fe..18cfe6b70 100644 --- a/examples/flows/flows.vcxproj +++ b/examples/flows/flows.vcxproj @@ -26,21 +26,25 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 Application NotSet true + v142 Application NotSet + v142 @@ -74,6 +78,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/forestfire/forestfire.vcxproj b/examples/forestfire/forestfire.vcxproj index 7196b8c0b..1b99724ac 100644 --- a/examples/forestfire/forestfire.vcxproj +++ b/examples/forestfire/forestfire.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/graphgen/graphgen.vcxproj b/examples/graphgen/graphgen.vcxproj index 659627452..895ea287a 100644 --- a/examples/graphgen/graphgen.vcxproj +++ b/examples/graphgen/graphgen.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/graphhash/graphhash.vcxproj b/examples/graphhash/graphhash.vcxproj index 2178faea0..e56e94ab6 100644 --- a/examples/graphhash/graphhash.vcxproj +++ b/examples/graphhash/graphhash.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath); + Disabled diff --git a/examples/hysgen/.gitignore b/examples/hysgen/.gitignore new file mode 100644 index 000000000..d3e8766ce --- /dev/null +++ b/examples/hysgen/.gitignore @@ -0,0 +1,40 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +hysgen_main +*.sh + +# Other +*_cmtyvv_* +*_cmty_* +backups/ +results/ \ No newline at end of file diff --git a/examples/hysgen/.idea/.gitignore b/examples/hysgen/.idea/.gitignore new file mode 100644 index 000000000..13566b81b --- /dev/null +++ b/examples/hysgen/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/examples/hysgen/LICENSE b/examples/hysgen/LICENSE new file mode 100644 index 000000000..fff0a81e4 --- /dev/null +++ b/examples/hysgen/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2022, Bahman Pedrood +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/examples/hysgen/Makefile b/examples/hysgen/Makefile new file mode 100644 index 000000000..4fa872837 --- /dev/null +++ b/examples/hysgen/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for this SNAP example +# - modify Makefile.ex when creating a new SNAP example +# +# implements: +# all (default), clean +# + +include ../../Makefile.config +include Makefile.ex +include ../Makefile.exmain diff --git a/examples/hysgen/Makefile.ex b/examples/hysgen/Makefile.ex new file mode 100644 index 000000000..4419799f0 --- /dev/null +++ b/examples/hysgen/Makefile.ex @@ -0,0 +1,9 @@ +## Main application file +MAIN = hysgen_main +DEPH = $(EXSNAPADV)/hysgen.h +DEPCPP = $(EXSNAPADV)/hysgen.cpp +#CXXFLAGS += $(CXXOPENMP) +#CXXFLAGS += -g -rdynamic +#CXXFLAGS += -ggdb +#CXXFLAGS += -ggdb3 -rdynamic + diff --git a/examples/hysgen/README.txt b/examples/hysgen/README.txt new file mode 100644 index 000000000..85866d069 --- /dev/null +++ b/examples/hysgen/README.txt @@ -0,0 +1,51 @@ +======================================================================== + Hypergraph Simultaneous Generators (HySGen) +======================================================================== + +This program fits a probabilistic generative model to undirected, unweighted +hypergraphs to detect overlapping communities (node clusters) in hypergraphs. +It takes a hyperedge list, the number of communities to be discovered, +and several optional arguments as input, to produce a list of communities. +The details of the model and the community inference algorithm are described +in the following paper: + +B. Pedrood, C. Domeniconi, and K. Laskey. "Hypergraph Simultaneous Generators." AISTATS 2022. + +This code works under Windows with Cygwin with GCC, Mac OS X, Linux and other +Unix variants with GCC. To use with Visual Studio, you have to create a new +project for this program. Make sure that a C++ compiler is installed on the +system. Makefiles are provided, so you can complie the code in the command +line with the following command: + make all + +///////////////////////////////////////////////////////////////////////////// + +Parameters: + -i: Input [hyper]edgelist file url. + -o: Output file url + name prefix for the discovered communities. + -c: The number of communities to detect. + -op: Output file performance plot (Default: empty for no plot). + -ci: Community initialization file url (Default: empty). + -l: Url for node names file (Default: empty). + -mc: Minimum size of the communities(Default: 3). + -rs: Random Seed. + -xi: Maximum number of iterations (Default: 1000). + -ic: Initial membership value for the seed communities (Default: 0.1). + -in: The default membership value of each node to all the communities (Default: 0.03). + -rp: Ratio of initial memberships to be randomly perturbed (Default: 0.0). + -rw: Weight for l-1 regularization on learning the model parameters (Default: 0.005) + -sz: Initial step size for backtracking line search (Default: 0.05). + -sa: Control parameter for backtracking line search (Default: 0.1). + -sr: Step-size reduction ratio for backtracking line search (Default: 0.5). + -th: Cut-off threshold for the final community membership values (Default: the l-1 regularization value). + +///////////////////////////////////////////////////////////////////////////// + +Usage: + +Discover 2 communities from the synthtic hypergraph (under synthetic_data/): + +./hysgen_main -i:./synthetic_data/synthetic.hyperedges -o:./synthetic_res -c:2 -th:0.1 -rs:1 + + +** For real-world hypergraph data please visit https://github.com/bpedrood/HySGen diff --git a/examples/hysgen/hysgen_main.cpp b/examples/hysgen/hysgen_main.cpp new file mode 100644 index 000000000..bf7573aa7 --- /dev/null +++ b/examples/hysgen/hysgen_main.cpp @@ -0,0 +1,86 @@ +#include "hysgen.h" +#include "agm.h" + +int main(int argc, char* argv[]) { + Env = TEnv(argc, argv, TNotify::StdNotify); + Env.PrepArgs(TStr::Fmt("HySGen. build: %s, %s. Time: %s", __TIME__, __DATE__, TExeTm::GetCurTm())); + TExeTm ExeTm; + + Try + + const TStr InFNm = Env.GetIfArgPrefixStr("-i:", "./synthetic_data/synthetic.hyperedges", "Input [hyper]edgelist file url."); + const TStr OutFPrx = Env.GetIfArgPrefixStr("-o:", "./synthetic_res", "Output file url + name prefix for the discovered communities."); + int OptComs = Env.GetIfArgPrefixInt("-c:", 2, "The number of communities to detect."); + const TStr OutPlt = Env.GetIfArgPrefixStr("-op:", "", "Output file performance plot (empty for no plot)."); + const TStr InitComFNm = Env.GetIfArgPrefixStr("-ci:", "", "Community initialization file url."); + const TStr LabelFNm = Env.GetIfArgPrefixStr("-l:", "", "Input file name for node names (Node ID, Node label)."); + const int MinComSize = Env.GetIfArgPrefixInt("-mc:", 3, "Minimum size of the communities."); + const int RndSeed = Env.GetIfArgPrefixInt("-rs:", 0, "Random Seed."); + int MaxIter = Env.GetIfArgPrefixInt("-xi:", 1000, "Maximum number of iterations."); + const double InitComS = Env.GetIfArgPrefixFlt("-ic:", 0.1, "Initial membership value for the initially assigned communities."); + const double InitNulS = Env.GetIfArgPrefixFlt("-in:", 0.0, "The default membership value of each node to all the communities."); + double PerturbDensity = Env.GetIfArgPrefixFlt("-rp:", 0.0, "Ratio of initial memberships to be randomly perturbed."); + const double RegCoef = Env.GetIfArgPrefixFlt("-rw:", 0.005, "Weight for l-1 regularization on learning the model parameters."); + const double StepSize = Env.GetIfArgPrefixFlt("-sz:", 1.0, "Initial step size for backtracking line search."); + const double StepCtrlParam = Env.GetIfArgPrefixFlt("-sa:", 1.0, "Control parameter for backtracking line search."); + const double StepReductionRatio = Env.GetIfArgPrefixFlt("-sr:", 0.5, "Step-size reduction ratio for backtracking line search."); + const double Threshold = Env.GetIfArgPrefixFlt("-th:", MAX(0.01, RegCoef), "Cut-off threshold for the final community membership values."); + + + PHGraph G; + TIntStrH NIDNameH, NIDEdgelistnameH; + TStrIntH NameNIdH, EdgelistnameNIdH; + TStrHash NodeNameH; + TVec WckVV; + TVec EstCmtyVH; + TVec EstCmtyVV; + if (InFNm.IsSuffix(".hgraph")) { + TFIn GFIn(InFNm); + G = THGraph::Load(GFIn); + } else { + G = THysgenUtil::LoadEdgeList(InFNm, NodeNameH); + NIDNameH.Gen(NodeNameH.Len()); NIDEdgelistnameH.Gen(NodeNameH.Len()); + NameNIdH.Gen(NodeNameH.Len()); EdgelistnameNIdH.Gen(NodeNameH.Len()); + for (int s = 0; s < NodeNameH.Len(); s++) { + NIDNameH.AddDat(s, NodeNameH.GetKey(s)); + NIDEdgelistnameH.AddDat(s, NodeNameH.GetKey(s)); + NameNIdH.AddDat(NodeNameH.GetKey(s), s); + EdgelistnameNIdH.AddDat(NodeNameH.GetKey(s), s); + } + } + if (LabelFNm.Len() > 0) { + TSsParser Ss(LabelFNm, ssfTabSep); + while (Ss.Next()) { + if (Ss.Len() > 1) {NIDNameH.AddDat(NameNIdH.GetDat(Ss[0]), Ss.GetFld(1)); } + } + } + printf("HyperGraph: %d Nodes %d Edges\n", G->GetNodes(), G->GetEdges()); + + TIntV NIDV; + G->GetNIdV(NIDV); + + TExeTm RunTm; + THysgen Optimizer(G, RndSeed, InitComS, InitNulS); + Optimizer.ComInit(OptComs, MinComSize, PerturbDensity); + if (InitComFNm.Len() > 0) { + Optimizer.LoadComInit(InitComFNm); + } + Optimizer.SetRegCoef(RegCoef); + + Optimizer.GetCmtyVV(EstCmtyVH, EstCmtyVV, WckVV, InitNulS, MinComSize); + THysgenUtil::DumpCmtyVH(OutFPrx + "_cmtyvv_init.txt", EstCmtyVH, NIDNameH, THysgenUtil::Alphabetical); + + Optimizer.MLEGradAscent(1.0, MaxIter * G->GetNodes(), OutPlt, StepSize, StepCtrlParam, StepReductionRatio); + Optimizer.GetCmtyVV(EstCmtyVH, EstCmtyVV, WckVV, Threshold, MinComSize); + + THysgenUtil::DumpCmtyVH(OutFPrx + "_cmty_SrtById_IdValues.txt", EstCmtyVH, NIDEdgelistnameH, THysgenUtil::Alphabetical); + THysgenUtil::DumpCmtyVH(OutFPrx + "_cmty_SrtByVals_IdValues.txt", EstCmtyVH, NIDEdgelistnameH, THysgenUtil::Value); + THysgenUtil::DumpCmtyVH(OutFPrx + "_cmty_SrtByVals_NameValues.txt", EstCmtyVH, NIDNameH, THysgenUtil::Value); + THysgenUtil::DumpCmtyVV(OutFPrx + "_cmty_SrtByName_Names.txt", EstCmtyVV, NIDNameH); + + Catch + + printf("\nrun time: %s (%s)\n", ExeTm.GetTmStr(), TSecTm::GetCurTm().GetTmStr().CStr()); + + return 0; +} diff --git a/examples/hysgen/stdafx.cpp b/examples/hysgen/stdafx.cpp new file mode 100644 index 000000000..35bb8a661 --- /dev/null +++ b/examples/hysgen/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// cesna.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/examples/hysgen/stdafx.h b/examples/hysgen/stdafx.h new file mode 100644 index 000000000..a862fc663 --- /dev/null +++ b/examples/hysgen/stdafx.h @@ -0,0 +1,5 @@ +#pragma once + +#include "targetver.h" + +#include "Snap.h" diff --git a/examples/hysgen/synthetic_data/ground_truth_comms.txt b/examples/hysgen/synthetic_data/ground_truth_comms.txt new file mode 100644 index 000000000..1f5dd52c4 --- /dev/null +++ b/examples/hysgen/synthetic_data/ground_truth_comms.txt @@ -0,0 +1,2 @@ +1 2 3 4 5 11 12 13 14 15 21 22 23 24 25 +7 8 9 10 17 18 19 20 27 28 29 30 diff --git a/examples/hysgen/synthetic_data/synthetic.description b/examples/hysgen/synthetic_data/synthetic.description new file mode 100644 index 000000000..23ae046b5 --- /dev/null +++ b/examples/hysgen/synthetic_data/synthetic.description @@ -0,0 +1,11 @@ +Supposed Scenario: + +It's the first day of an academic year. Student gatherings have been recorded from some point during the spring semester last year. Assume there exist two communities of CS student and history students; the only social communities to which they belong. The members of these two communities are specified in the file "ground_truth_comms.txt". +The hypergraph for this example is a network of recorded gatherings in the university in the timeline mentioned before. Each gathering corresponds to a hyperedge that connects the attending students. The hypergraph is saved in "synthetic.hyperedges", where each line corresponds to the ID of the nodes in a hyperedge. +A regular graph equivalent of the hypergraph is represented in "synthetic.edges", where the list of the edges are stored. This graph is created by mapping a k-clique to a hyperedge of size k. + + +################################# +Community detection complication: + +There are two large hyperedges in the hypergraph that make the problem of discoverying the communities complicated, which correspond to two outdoor welcome parties for the students. Nodes 36 through 71 in this hyperedges represent some passerbys who are not students, only joined the parties to enjoy the music, game and free food. Nodes 76 to 87 are new students, half (6) CS and half (6) histroy. The new students should not be correctly identified because the only gatherings they had so far has been an orientation, which has been gathered with 3 senior students of each major to talk about the dept for them; and of course the gathering of welcome party. In the party, they are divided into partiy groups (4-8) that are independent of their major. diff --git a/examples/hysgen/synthetic_data/synthetic.edges b/examples/hysgen/synthetic_data/synthetic.edges new file mode 100644 index 000000000..052c1aea0 --- /dev/null +++ b/examples/hysgen/synthetic_data/synthetic.edges @@ -0,0 +1,3996 @@ +14 15 +15 14 +14 16 +16 14 +14 17 +17 14 +14 18 +18 14 +14 23 +23 14 +14 24 +24 14 +14 25 +25 14 +14 26 +26 14 +14 27 +27 14 +14 28 +28 14 +14 31 +31 14 +14 32 +32 14 +14 33 +33 14 +14 34 +34 14 +14 35 +35 14 +14 13 +13 14 +14 12 +12 14 +14 7 +7 14 +14 36 +36 14 +14 37 +37 14 +14 38 +38 14 +14 39 +39 14 +14 40 +40 14 +14 41 +41 14 +14 42 +42 14 +14 43 +43 14 +14 44 +44 14 +14 45 +45 14 +14 46 +46 14 +14 47 +47 14 +14 48 +48 14 +14 49 +49 14 +14 50 +50 14 +14 51 +51 14 +14 52 +52 14 +14 53 +53 14 +14 54 +54 14 +14 55 +55 14 +14 76 +76 14 +14 77 +77 14 +14 78 +78 14 +14 79 +79 14 +15 16 +16 15 +15 17 +17 15 +15 18 +18 15 +15 23 +23 15 +15 24 +24 15 +15 25 +25 15 +15 26 +26 15 +15 27 +27 15 +15 28 +28 15 +15 31 +31 15 +15 32 +32 15 +15 33 +33 15 +15 34 +34 15 +15 35 +35 15 +15 13 +13 15 +15 12 +12 15 +15 7 +7 15 +15 36 +36 15 +15 37 +37 15 +15 38 +38 15 +15 39 +39 15 +15 40 +40 15 +15 41 +41 15 +15 42 +42 15 +15 43 +43 15 +15 44 +44 15 +15 45 +45 15 +15 46 +46 15 +15 47 +47 15 +15 48 +48 15 +15 49 +49 15 +15 50 +50 15 +15 51 +51 15 +15 52 +52 15 +15 53 +53 15 +15 54 +54 15 +15 55 +55 15 +15 76 +76 15 +15 77 +77 15 +15 78 +78 15 +15 79 +79 15 +16 17 +17 16 +16 18 +18 16 +16 23 +23 16 +16 24 +24 16 +16 25 +25 16 +16 26 +26 16 +16 27 +27 16 +16 28 +28 16 +16 31 +31 16 +16 32 +32 16 +16 33 +33 16 +16 34 +34 16 +16 35 +35 16 +16 13 +13 16 +16 12 +12 16 +16 7 +7 16 +16 36 +36 16 +16 37 +37 16 +16 38 +38 16 +16 39 +39 16 +16 40 +40 16 +16 41 +41 16 +16 42 +42 16 +16 43 +43 16 +16 44 +44 16 +16 45 +45 16 +16 46 +46 16 +16 47 +47 16 +16 48 +48 16 +16 49 +49 16 +16 50 +50 16 +16 51 +51 16 +16 52 +52 16 +16 53 +53 16 +16 54 +54 16 +16 55 +55 16 +16 76 +76 16 +16 77 +77 16 +16 78 +78 16 +16 79 +79 16 +17 18 +18 17 +17 23 +23 17 +17 24 +24 17 +17 25 +25 17 +17 26 +26 17 +17 27 +27 17 +17 28 +28 17 +17 31 +31 17 +17 32 +32 17 +17 33 +33 17 +17 34 +34 17 +17 35 +35 17 +17 13 +13 17 +17 12 +12 17 +17 7 +7 17 +17 36 +36 17 +17 37 +37 17 +17 38 +38 17 +17 39 +39 17 +17 40 +40 17 +17 41 +41 17 +17 42 +42 17 +17 43 +43 17 +17 44 +44 17 +17 45 +45 17 +17 46 +46 17 +17 47 +47 17 +17 48 +48 17 +17 49 +49 17 +17 50 +50 17 +17 51 +51 17 +17 52 +52 17 +17 53 +53 17 +17 54 +54 17 +17 55 +55 17 +17 76 +76 17 +17 77 +77 17 +17 78 +78 17 +17 79 +79 17 +18 23 +23 18 +18 24 +24 18 +18 25 +25 18 +18 26 +26 18 +18 27 +27 18 +18 28 +28 18 +18 31 +31 18 +18 32 +32 18 +18 33 +33 18 +18 34 +34 18 +18 35 +35 18 +18 13 +13 18 +18 12 +12 18 +18 7 +7 18 +18 36 +36 18 +18 37 +37 18 +18 38 +38 18 +18 39 +39 18 +18 40 +40 18 +18 41 +41 18 +18 42 +42 18 +18 43 +43 18 +18 44 +44 18 +18 45 +45 18 +18 46 +46 18 +18 47 +47 18 +18 48 +48 18 +18 49 +49 18 +18 50 +50 18 +18 51 +51 18 +18 52 +52 18 +18 53 +53 18 +18 54 +54 18 +18 55 +55 18 +18 76 +76 18 +18 77 +77 18 +18 78 +78 18 +18 79 +79 18 +23 24 +24 23 +23 25 +25 23 +23 26 +26 23 +23 27 +27 23 +23 28 +28 23 +23 31 +31 23 +23 32 +32 23 +23 33 +33 23 +23 34 +34 23 +23 35 +35 23 +23 13 +13 23 +23 12 +12 23 +23 7 +7 23 +23 36 +36 23 +23 37 +37 23 +23 38 +38 23 +23 39 +39 23 +23 40 +40 23 +23 41 +41 23 +23 42 +42 23 +23 43 +43 23 +23 44 +44 23 +23 45 +45 23 +23 46 +46 23 +23 47 +47 23 +23 48 +48 23 +23 49 +49 23 +23 50 +50 23 +23 51 +51 23 +23 52 +52 23 +23 53 +53 23 +23 54 +54 23 +23 55 +55 23 +23 76 +76 23 +23 77 +77 23 +23 78 +78 23 +23 79 +79 23 +24 25 +25 24 +24 26 +26 24 +24 27 +27 24 +24 28 +28 24 +24 31 +31 24 +24 32 +32 24 +24 33 +33 24 +24 34 +34 24 +24 35 +35 24 +24 13 +13 24 +24 12 +12 24 +24 7 +7 24 +24 36 +36 24 +24 37 +37 24 +24 38 +38 24 +24 39 +39 24 +24 40 +40 24 +24 41 +41 24 +24 42 +42 24 +24 43 +43 24 +24 44 +44 24 +24 45 +45 24 +24 46 +46 24 +24 47 +47 24 +24 48 +48 24 +24 49 +49 24 +24 50 +50 24 +24 51 +51 24 +24 52 +52 24 +24 53 +53 24 +24 54 +54 24 +24 55 +55 24 +24 76 +76 24 +24 77 +77 24 +24 78 +78 24 +24 79 +79 24 +25 26 +26 25 +25 27 +27 25 +25 28 +28 25 +25 31 +31 25 +25 32 +32 25 +25 33 +33 25 +25 34 +34 25 +25 35 +35 25 +25 13 +13 25 +25 12 +12 25 +25 7 +7 25 +25 36 +36 25 +25 37 +37 25 +25 38 +38 25 +25 39 +39 25 +25 40 +40 25 +25 41 +41 25 +25 42 +42 25 +25 43 +43 25 +25 44 +44 25 +25 45 +45 25 +25 46 +46 25 +25 47 +47 25 +25 48 +48 25 +25 49 +49 25 +25 50 +50 25 +25 51 +51 25 +25 52 +52 25 +25 53 +53 25 +25 54 +54 25 +25 55 +55 25 +25 76 +76 25 +25 77 +77 25 +25 78 +78 25 +25 79 +79 25 +26 27 +27 26 +26 28 +28 26 +26 31 +31 26 +26 32 +32 26 +26 33 +33 26 +26 34 +34 26 +26 35 +35 26 +26 13 +13 26 +26 12 +12 26 +26 7 +7 26 +26 36 +36 26 +26 37 +37 26 +26 38 +38 26 +26 39 +39 26 +26 40 +40 26 +26 41 +41 26 +26 42 +42 26 +26 43 +43 26 +26 44 +44 26 +26 45 +45 26 +26 46 +46 26 +26 47 +47 26 +26 48 +48 26 +26 49 +49 26 +26 50 +50 26 +26 51 +51 26 +26 52 +52 26 +26 53 +53 26 +26 54 +54 26 +26 55 +55 26 +26 76 +76 26 +26 77 +77 26 +26 78 +78 26 +26 79 +79 26 +27 28 +28 27 +27 31 +31 27 +27 32 +32 27 +27 33 +33 27 +27 34 +34 27 +27 35 +35 27 +27 13 +13 27 +27 12 +12 27 +27 7 +7 27 +27 36 +36 27 +27 37 +37 27 +27 38 +38 27 +27 39 +39 27 +27 40 +40 27 +27 41 +41 27 +27 42 +42 27 +27 43 +43 27 +27 44 +44 27 +27 45 +45 27 +27 46 +46 27 +27 47 +47 27 +27 48 +48 27 +27 49 +49 27 +27 50 +50 27 +27 51 +51 27 +27 52 +52 27 +27 53 +53 27 +27 54 +54 27 +27 55 +55 27 +27 76 +76 27 +27 77 +77 27 +27 78 +78 27 +27 79 +79 27 +28 31 +31 28 +28 32 +32 28 +28 33 +33 28 +28 34 +34 28 +28 35 +35 28 +28 13 +13 28 +28 12 +12 28 +28 7 +7 28 +28 36 +36 28 +28 37 +37 28 +28 38 +38 28 +28 39 +39 28 +28 40 +40 28 +28 41 +41 28 +28 42 +42 28 +28 43 +43 28 +28 44 +44 28 +28 45 +45 28 +28 46 +46 28 +28 47 +47 28 +28 48 +48 28 +28 49 +49 28 +28 50 +50 28 +28 51 +51 28 +28 52 +52 28 +28 53 +53 28 +28 54 +54 28 +28 55 +55 28 +28 76 +76 28 +28 77 +77 28 +28 78 +78 28 +28 79 +79 28 +31 32 +32 31 +31 33 +33 31 +31 34 +34 31 +31 35 +35 31 +31 13 +13 31 +31 12 +12 31 +31 7 +7 31 +31 36 +36 31 +31 37 +37 31 +31 38 +38 31 +31 39 +39 31 +31 40 +40 31 +31 41 +41 31 +31 42 +42 31 +31 43 +43 31 +31 44 +44 31 +31 45 +45 31 +31 46 +46 31 +31 47 +47 31 +31 48 +48 31 +31 49 +49 31 +31 50 +50 31 +31 51 +51 31 +31 52 +52 31 +31 53 +53 31 +31 54 +54 31 +31 55 +55 31 +31 76 +76 31 +31 77 +77 31 +31 78 +78 31 +31 79 +79 31 +32 33 +33 32 +32 34 +34 32 +32 35 +35 32 +32 13 +13 32 +32 12 +12 32 +32 7 +7 32 +32 36 +36 32 +32 37 +37 32 +32 38 +38 32 +32 39 +39 32 +32 40 +40 32 +32 41 +41 32 +32 42 +42 32 +32 43 +43 32 +32 44 +44 32 +32 45 +45 32 +32 46 +46 32 +32 47 +47 32 +32 48 +48 32 +32 49 +49 32 +32 50 +50 32 +32 51 +51 32 +32 52 +52 32 +32 53 +53 32 +32 54 +54 32 +32 55 +55 32 +32 76 +76 32 +32 77 +77 32 +32 78 +78 32 +32 79 +79 32 +33 34 +34 33 +33 35 +35 33 +33 13 +13 33 +33 12 +12 33 +33 7 +7 33 +33 36 +36 33 +33 37 +37 33 +33 38 +38 33 +33 39 +39 33 +33 40 +40 33 +33 41 +41 33 +33 42 +42 33 +33 43 +43 33 +33 44 +44 33 +33 45 +45 33 +33 46 +46 33 +33 47 +47 33 +33 48 +48 33 +33 49 +49 33 +33 50 +50 33 +33 51 +51 33 +33 52 +52 33 +33 53 +53 33 +33 54 +54 33 +33 55 +55 33 +33 76 +76 33 +33 77 +77 33 +33 78 +78 33 +33 79 +79 33 +34 35 +35 34 +34 13 +13 34 +34 12 +12 34 +34 7 +7 34 +34 36 +36 34 +34 37 +37 34 +34 38 +38 34 +34 39 +39 34 +34 40 +40 34 +34 41 +41 34 +34 42 +42 34 +34 43 +43 34 +34 44 +44 34 +34 45 +45 34 +34 46 +46 34 +34 47 +47 34 +34 48 +48 34 +34 49 +49 34 +34 50 +50 34 +34 51 +51 34 +34 52 +52 34 +34 53 +53 34 +34 54 +54 34 +34 55 +55 34 +34 76 +76 34 +34 77 +77 34 +34 78 +78 34 +34 79 +79 34 +35 13 +13 35 +35 12 +12 35 +35 7 +7 35 +35 36 +36 35 +35 37 +37 35 +35 38 +38 35 +35 39 +39 35 +35 40 +40 35 +35 41 +41 35 +35 42 +42 35 +35 43 +43 35 +35 44 +44 35 +35 45 +45 35 +35 46 +46 35 +35 47 +47 35 +35 48 +48 35 +35 49 +49 35 +35 50 +50 35 +35 51 +51 35 +35 52 +52 35 +35 53 +53 35 +35 54 +54 35 +35 55 +55 35 +35 76 +76 35 +35 77 +77 35 +35 78 +78 35 +35 79 +79 35 +13 12 +12 13 +13 7 +7 13 +13 36 +36 13 +13 37 +37 13 +13 38 +38 13 +13 39 +39 13 +13 40 +40 13 +13 41 +41 13 +13 42 +42 13 +13 43 +43 13 +13 44 +44 13 +13 45 +45 13 +13 46 +46 13 +13 47 +47 13 +13 48 +48 13 +13 49 +49 13 +13 50 +50 13 +13 51 +51 13 +13 52 +52 13 +13 53 +53 13 +13 54 +54 13 +13 55 +55 13 +13 76 +76 13 +13 77 +77 13 +13 78 +78 13 +13 79 +79 13 +12 7 +7 12 +12 36 +36 12 +12 37 +37 12 +12 38 +38 12 +12 39 +39 12 +12 40 +40 12 +12 41 +41 12 +12 42 +42 12 +12 43 +43 12 +12 44 +44 12 +12 45 +45 12 +12 46 +46 12 +12 47 +47 12 +12 48 +48 12 +12 49 +49 12 +12 50 +50 12 +12 51 +51 12 +12 52 +52 12 +12 53 +53 12 +12 54 +54 12 +12 55 +55 12 +12 76 +76 12 +12 77 +77 12 +12 78 +78 12 +12 79 +79 12 +7 36 +36 7 +7 37 +37 7 +7 38 +38 7 +7 39 +39 7 +7 40 +40 7 +7 41 +41 7 +7 42 +42 7 +7 43 +43 7 +7 44 +44 7 +7 45 +45 7 +7 46 +46 7 +7 47 +47 7 +7 48 +48 7 +7 49 +49 7 +7 50 +50 7 +7 51 +51 7 +7 52 +52 7 +7 53 +53 7 +7 54 +54 7 +7 55 +55 7 +7 76 +76 7 +7 77 +77 7 +7 78 +78 7 +7 79 +79 7 +36 37 +37 36 +36 38 +38 36 +36 39 +39 36 +36 40 +40 36 +36 41 +41 36 +36 42 +42 36 +36 43 +43 36 +36 44 +44 36 +36 45 +45 36 +36 46 +46 36 +36 47 +47 36 +36 48 +48 36 +36 49 +49 36 +36 50 +50 36 +36 51 +51 36 +36 52 +52 36 +36 53 +53 36 +36 54 +54 36 +36 55 +55 36 +36 76 +76 36 +36 77 +77 36 +36 78 +78 36 +36 79 +79 36 +37 38 +38 37 +37 39 +39 37 +37 40 +40 37 +37 41 +41 37 +37 42 +42 37 +37 43 +43 37 +37 44 +44 37 +37 45 +45 37 +37 46 +46 37 +37 47 +47 37 +37 48 +48 37 +37 49 +49 37 +37 50 +50 37 +37 51 +51 37 +37 52 +52 37 +37 53 +53 37 +37 54 +54 37 +37 55 +55 37 +37 76 +76 37 +37 77 +77 37 +37 78 +78 37 +37 79 +79 37 +38 39 +39 38 +38 40 +40 38 +38 41 +41 38 +38 42 +42 38 +38 43 +43 38 +38 44 +44 38 +38 45 +45 38 +38 46 +46 38 +38 47 +47 38 +38 48 +48 38 +38 49 +49 38 +38 50 +50 38 +38 51 +51 38 +38 52 +52 38 +38 53 +53 38 +38 54 +54 38 +38 55 +55 38 +38 76 +76 38 +38 77 +77 38 +38 78 +78 38 +38 79 +79 38 +39 40 +40 39 +39 41 +41 39 +39 42 +42 39 +39 43 +43 39 +39 44 +44 39 +39 45 +45 39 +39 46 +46 39 +39 47 +47 39 +39 48 +48 39 +39 49 +49 39 +39 50 +50 39 +39 51 +51 39 +39 52 +52 39 +39 53 +53 39 +39 54 +54 39 +39 55 +55 39 +39 76 +76 39 +39 77 +77 39 +39 78 +78 39 +39 79 +79 39 +40 41 +41 40 +40 42 +42 40 +40 43 +43 40 +40 44 +44 40 +40 45 +45 40 +40 46 +46 40 +40 47 +47 40 +40 48 +48 40 +40 49 +49 40 +40 50 +50 40 +40 51 +51 40 +40 52 +52 40 +40 53 +53 40 +40 54 +54 40 +40 55 +55 40 +40 76 +76 40 +40 77 +77 40 +40 78 +78 40 +40 79 +79 40 +41 42 +42 41 +41 43 +43 41 +41 44 +44 41 +41 45 +45 41 +41 46 +46 41 +41 47 +47 41 +41 48 +48 41 +41 49 +49 41 +41 50 +50 41 +41 51 +51 41 +41 52 +52 41 +41 53 +53 41 +41 54 +54 41 +41 55 +55 41 +41 76 +76 41 +41 77 +77 41 +41 78 +78 41 +41 79 +79 41 +42 43 +43 42 +42 44 +44 42 +42 45 +45 42 +42 46 +46 42 +42 47 +47 42 +42 48 +48 42 +42 49 +49 42 +42 50 +50 42 +42 51 +51 42 +42 52 +52 42 +42 53 +53 42 +42 54 +54 42 +42 55 +55 42 +42 76 +76 42 +42 77 +77 42 +42 78 +78 42 +42 79 +79 42 +43 44 +44 43 +43 45 +45 43 +43 46 +46 43 +43 47 +47 43 +43 48 +48 43 +43 49 +49 43 +43 50 +50 43 +43 51 +51 43 +43 52 +52 43 +43 53 +53 43 +43 54 +54 43 +43 55 +55 43 +43 76 +76 43 +43 77 +77 43 +43 78 +78 43 +43 79 +79 43 +44 45 +45 44 +44 46 +46 44 +44 47 +47 44 +44 48 +48 44 +44 49 +49 44 +44 50 +50 44 +44 51 +51 44 +44 52 +52 44 +44 53 +53 44 +44 54 +54 44 +44 55 +55 44 +44 76 +76 44 +44 77 +77 44 +44 78 +78 44 +44 79 +79 44 +45 46 +46 45 +45 47 +47 45 +45 48 +48 45 +45 49 +49 45 +45 50 +50 45 +45 51 +51 45 +45 52 +52 45 +45 53 +53 45 +45 54 +54 45 +45 55 +55 45 +45 76 +76 45 +45 77 +77 45 +45 78 +78 45 +45 79 +79 45 +46 47 +47 46 +46 48 +48 46 +46 49 +49 46 +46 50 +50 46 +46 51 +51 46 +46 52 +52 46 +46 53 +53 46 +46 54 +54 46 +46 55 +55 46 +46 76 +76 46 +46 77 +77 46 +46 78 +78 46 +46 79 +79 46 +47 48 +48 47 +47 49 +49 47 +47 50 +50 47 +47 51 +51 47 +47 52 +52 47 +47 53 +53 47 +47 54 +54 47 +47 55 +55 47 +47 76 +76 47 +47 77 +77 47 +47 78 +78 47 +47 79 +79 47 +48 49 +49 48 +48 50 +50 48 +48 51 +51 48 +48 52 +52 48 +48 53 +53 48 +48 54 +54 48 +48 55 +55 48 +48 76 +76 48 +48 77 +77 48 +48 78 +78 48 +48 79 +79 48 +49 50 +50 49 +49 51 +51 49 +49 52 +52 49 +49 53 +53 49 +49 54 +54 49 +49 55 +55 49 +49 76 +76 49 +49 77 +77 49 +49 78 +78 49 +49 79 +79 49 +50 51 +51 50 +50 52 +52 50 +50 53 +53 50 +50 54 +54 50 +50 55 +55 50 +50 76 +76 50 +50 77 +77 50 +50 78 +78 50 +50 79 +79 50 +51 52 +52 51 +51 53 +53 51 +51 54 +54 51 +51 55 +55 51 +51 76 +76 51 +51 77 +77 51 +51 78 +78 51 +51 79 +79 51 +52 53 +53 52 +52 54 +54 52 +52 55 +55 52 +52 76 +76 52 +52 77 +77 52 +52 78 +78 52 +52 79 +79 52 +53 54 +54 53 +53 55 +55 53 +53 76 +76 53 +53 77 +77 53 +53 78 +78 53 +53 79 +79 53 +54 55 +55 54 +54 76 +76 54 +54 77 +77 54 +54 78 +78 54 +54 79 +79 54 +55 76 +76 55 +55 77 +77 55 +55 78 +78 55 +55 79 +79 55 +76 77 +77 76 +76 78 +78 76 +76 79 +79 76 +77 78 +78 77 +77 79 +79 77 +78 79 +79 78 +22 21 +21 22 +22 11 +11 22 +22 2 +2 22 +22 1 +1 22 +22 3 +3 22 +22 4 +4 22 +22 5 +5 22 +22 8 +8 22 +22 9 +9 22 +22 10 +10 22 +22 20 +20 22 +22 19 +19 22 +22 29 +29 22 +22 30 +30 22 +22 6 +6 22 +22 56 +56 22 +22 57 +57 22 +22 58 +58 22 +22 59 +59 22 +22 60 +60 22 +22 61 +61 22 +22 62 +62 22 +22 63 +63 22 +22 64 +64 22 +22 65 +65 22 +22 66 +66 22 +22 67 +67 22 +22 68 +68 22 +22 69 +69 22 +22 70 +70 22 +22 71 +71 22 +22 72 +72 22 +22 73 +73 22 +22 74 +74 22 +22 75 +75 22 +22 80 +80 22 +22 81 +81 22 +22 82 +82 22 +22 83 +83 22 +22 84 +84 22 +22 85 +85 22 +22 86 +86 22 +22 87 +87 22 +21 11 +11 21 +21 2 +2 21 +21 1 +1 21 +21 3 +3 21 +21 4 +4 21 +21 5 +5 21 +21 8 +8 21 +21 9 +9 21 +21 10 +10 21 +21 20 +20 21 +21 19 +19 21 +21 29 +29 21 +21 30 +30 21 +21 6 +6 21 +21 56 +56 21 +21 57 +57 21 +21 58 +58 21 +21 59 +59 21 +21 60 +60 21 +21 61 +61 21 +21 62 +62 21 +21 63 +63 21 +21 64 +64 21 +21 65 +65 21 +21 66 +66 21 +21 67 +67 21 +21 68 +68 21 +21 69 +69 21 +21 70 +70 21 +21 71 +71 21 +21 72 +72 21 +21 73 +73 21 +21 74 +74 21 +21 75 +75 21 +21 80 +80 21 +21 81 +81 21 +21 82 +82 21 +21 83 +83 21 +21 84 +84 21 +21 85 +85 21 +21 86 +86 21 +21 87 +87 21 +11 2 +2 11 +11 1 +1 11 +11 3 +3 11 +11 4 +4 11 +11 5 +5 11 +11 8 +8 11 +11 9 +9 11 +11 10 +10 11 +11 20 +20 11 +11 19 +19 11 +11 29 +29 11 +11 30 +30 11 +11 6 +6 11 +11 56 +56 11 +11 57 +57 11 +11 58 +58 11 +11 59 +59 11 +11 60 +60 11 +11 61 +61 11 +11 62 +62 11 +11 63 +63 11 +11 64 +64 11 +11 65 +65 11 +11 66 +66 11 +11 67 +67 11 +11 68 +68 11 +11 69 +69 11 +11 70 +70 11 +11 71 +71 11 +11 72 +72 11 +11 73 +73 11 +11 74 +74 11 +11 75 +75 11 +11 80 +80 11 +11 81 +81 11 +11 82 +82 11 +11 83 +83 11 +11 84 +84 11 +11 85 +85 11 +11 86 +86 11 +11 87 +87 11 +2 1 +1 2 +2 3 +3 2 +2 4 +4 2 +2 5 +5 2 +2 8 +8 2 +2 9 +9 2 +2 10 +10 2 +2 20 +20 2 +2 19 +19 2 +2 29 +29 2 +2 30 +30 2 +2 6 +6 2 +2 56 +56 2 +2 57 +57 2 +2 58 +58 2 +2 59 +59 2 +2 60 +60 2 +2 61 +61 2 +2 62 +62 2 +2 63 +63 2 +2 64 +64 2 +2 65 +65 2 +2 66 +66 2 +2 67 +67 2 +2 68 +68 2 +2 69 +69 2 +2 70 +70 2 +2 71 +71 2 +2 72 +72 2 +2 73 +73 2 +2 74 +74 2 +2 75 +75 2 +2 80 +80 2 +2 81 +81 2 +2 82 +82 2 +2 83 +83 2 +2 84 +84 2 +2 85 +85 2 +2 86 +86 2 +2 87 +87 2 +1 3 +3 1 +1 4 +4 1 +1 5 +5 1 +1 8 +8 1 +1 9 +9 1 +1 10 +10 1 +1 20 +20 1 +1 19 +19 1 +1 29 +29 1 +1 30 +30 1 +1 6 +6 1 +1 56 +56 1 +1 57 +57 1 +1 58 +58 1 +1 59 +59 1 +1 60 +60 1 +1 61 +61 1 +1 62 +62 1 +1 63 +63 1 +1 64 +64 1 +1 65 +65 1 +1 66 +66 1 +1 67 +67 1 +1 68 +68 1 +1 69 +69 1 +1 70 +70 1 +1 71 +71 1 +1 72 +72 1 +1 73 +73 1 +1 74 +74 1 +1 75 +75 1 +1 80 +80 1 +1 81 +81 1 +1 82 +82 1 +1 83 +83 1 +1 84 +84 1 +1 85 +85 1 +1 86 +86 1 +1 87 +87 1 +3 4 +4 3 +3 5 +5 3 +3 8 +8 3 +3 9 +9 3 +3 10 +10 3 +3 20 +20 3 +3 19 +19 3 +3 29 +29 3 +3 30 +30 3 +3 6 +6 3 +3 56 +56 3 +3 57 +57 3 +3 58 +58 3 +3 59 +59 3 +3 60 +60 3 +3 61 +61 3 +3 62 +62 3 +3 63 +63 3 +3 64 +64 3 +3 65 +65 3 +3 66 +66 3 +3 67 +67 3 +3 68 +68 3 +3 69 +69 3 +3 70 +70 3 +3 71 +71 3 +3 72 +72 3 +3 73 +73 3 +3 74 +74 3 +3 75 +75 3 +3 80 +80 3 +3 81 +81 3 +3 82 +82 3 +3 83 +83 3 +3 84 +84 3 +3 85 +85 3 +3 86 +86 3 +3 87 +87 3 +4 5 +5 4 +4 8 +8 4 +4 9 +9 4 +4 10 +10 4 +4 20 +20 4 +4 19 +19 4 +4 29 +29 4 +4 30 +30 4 +4 6 +6 4 +4 56 +56 4 +4 57 +57 4 +4 58 +58 4 +4 59 +59 4 +4 60 +60 4 +4 61 +61 4 +4 62 +62 4 +4 63 +63 4 +4 64 +64 4 +4 65 +65 4 +4 66 +66 4 +4 67 +67 4 +4 68 +68 4 +4 69 +69 4 +4 70 +70 4 +4 71 +71 4 +4 72 +72 4 +4 73 +73 4 +4 74 +74 4 +4 75 +75 4 +4 80 +80 4 +4 81 +81 4 +4 82 +82 4 +4 83 +83 4 +4 84 +84 4 +4 85 +85 4 +4 86 +86 4 +4 87 +87 4 +5 8 +8 5 +5 9 +9 5 +5 10 +10 5 +5 20 +20 5 +5 19 +19 5 +5 29 +29 5 +5 30 +30 5 +5 6 +6 5 +5 56 +56 5 +5 57 +57 5 +5 58 +58 5 +5 59 +59 5 +5 60 +60 5 +5 61 +61 5 +5 62 +62 5 +5 63 +63 5 +5 64 +64 5 +5 65 +65 5 +5 66 +66 5 +5 67 +67 5 +5 68 +68 5 +5 69 +69 5 +5 70 +70 5 +5 71 +71 5 +5 72 +72 5 +5 73 +73 5 +5 74 +74 5 +5 75 +75 5 +5 80 +80 5 +5 81 +81 5 +5 82 +82 5 +5 83 +83 5 +5 84 +84 5 +5 85 +85 5 +5 86 +86 5 +5 87 +87 5 +8 9 +9 8 +8 10 +10 8 +8 20 +20 8 +8 19 +19 8 +8 29 +29 8 +8 30 +30 8 +8 6 +6 8 +8 56 +56 8 +8 57 +57 8 +8 58 +58 8 +8 59 +59 8 +8 60 +60 8 +8 61 +61 8 +8 62 +62 8 +8 63 +63 8 +8 64 +64 8 +8 65 +65 8 +8 66 +66 8 +8 67 +67 8 +8 68 +68 8 +8 69 +69 8 +8 70 +70 8 +8 71 +71 8 +8 72 +72 8 +8 73 +73 8 +8 74 +74 8 +8 75 +75 8 +8 80 +80 8 +8 81 +81 8 +8 82 +82 8 +8 83 +83 8 +8 84 +84 8 +8 85 +85 8 +8 86 +86 8 +8 87 +87 8 +9 10 +10 9 +9 20 +20 9 +9 19 +19 9 +9 29 +29 9 +9 30 +30 9 +9 6 +6 9 +9 56 +56 9 +9 57 +57 9 +9 58 +58 9 +9 59 +59 9 +9 60 +60 9 +9 61 +61 9 +9 62 +62 9 +9 63 +63 9 +9 64 +64 9 +9 65 +65 9 +9 66 +66 9 +9 67 +67 9 +9 68 +68 9 +9 69 +69 9 +9 70 +70 9 +9 71 +71 9 +9 72 +72 9 +9 73 +73 9 +9 74 +74 9 +9 75 +75 9 +9 80 +80 9 +9 81 +81 9 +9 82 +82 9 +9 83 +83 9 +9 84 +84 9 +9 85 +85 9 +9 86 +86 9 +9 87 +87 9 +10 20 +20 10 +10 19 +19 10 +10 29 +29 10 +10 30 +30 10 +10 6 +6 10 +10 56 +56 10 +10 57 +57 10 +10 58 +58 10 +10 59 +59 10 +10 60 +60 10 +10 61 +61 10 +10 62 +62 10 +10 63 +63 10 +10 64 +64 10 +10 65 +65 10 +10 66 +66 10 +10 67 +67 10 +10 68 +68 10 +10 69 +69 10 +10 70 +70 10 +10 71 +71 10 +10 72 +72 10 +10 73 +73 10 +10 74 +74 10 +10 75 +75 10 +10 80 +80 10 +10 81 +81 10 +10 82 +82 10 +10 83 +83 10 +10 84 +84 10 +10 85 +85 10 +10 86 +86 10 +10 87 +87 10 +20 19 +19 20 +20 29 +29 20 +20 30 +30 20 +20 6 +6 20 +20 56 +56 20 +20 57 +57 20 +20 58 +58 20 +20 59 +59 20 +20 60 +60 20 +20 61 +61 20 +20 62 +62 20 +20 63 +63 20 +20 64 +64 20 +20 65 +65 20 +20 66 +66 20 +20 67 +67 20 +20 68 +68 20 +20 69 +69 20 +20 70 +70 20 +20 71 +71 20 +20 72 +72 20 +20 73 +73 20 +20 74 +74 20 +20 75 +75 20 +20 80 +80 20 +20 81 +81 20 +20 82 +82 20 +20 83 +83 20 +20 84 +84 20 +20 85 +85 20 +20 86 +86 20 +20 87 +87 20 +19 29 +29 19 +19 30 +30 19 +19 6 +6 19 +19 56 +56 19 +19 57 +57 19 +19 58 +58 19 +19 59 +59 19 +19 60 +60 19 +19 61 +61 19 +19 62 +62 19 +19 63 +63 19 +19 64 +64 19 +19 65 +65 19 +19 66 +66 19 +19 67 +67 19 +19 68 +68 19 +19 69 +69 19 +19 70 +70 19 +19 71 +71 19 +19 72 +72 19 +19 73 +73 19 +19 74 +74 19 +19 75 +75 19 +19 80 +80 19 +19 81 +81 19 +19 82 +82 19 +19 83 +83 19 +19 84 +84 19 +19 85 +85 19 +19 86 +86 19 +19 87 +87 19 +29 30 +30 29 +29 6 +6 29 +29 56 +56 29 +29 57 +57 29 +29 58 +58 29 +29 59 +59 29 +29 60 +60 29 +29 61 +61 29 +29 62 +62 29 +29 63 +63 29 +29 64 +64 29 +29 65 +65 29 +29 66 +66 29 +29 67 +67 29 +29 68 +68 29 +29 69 +69 29 +29 70 +70 29 +29 71 +71 29 +29 72 +72 29 +29 73 +73 29 +29 74 +74 29 +29 75 +75 29 +29 80 +80 29 +29 81 +81 29 +29 82 +82 29 +29 83 +83 29 +29 84 +84 29 +29 85 +85 29 +29 86 +86 29 +29 87 +87 29 +30 6 +6 30 +30 56 +56 30 +30 57 +57 30 +30 58 +58 30 +30 59 +59 30 +30 60 +60 30 +30 61 +61 30 +30 62 +62 30 +30 63 +63 30 +30 64 +64 30 +30 65 +65 30 +30 66 +66 30 +30 67 +67 30 +30 68 +68 30 +30 69 +69 30 +30 70 +70 30 +30 71 +71 30 +30 72 +72 30 +30 73 +73 30 +30 74 +74 30 +30 75 +75 30 +30 80 +80 30 +30 81 +81 30 +30 82 +82 30 +30 83 +83 30 +30 84 +84 30 +30 85 +85 30 +30 86 +86 30 +30 87 +87 30 +6 56 +56 6 +6 57 +57 6 +6 58 +58 6 +6 59 +59 6 +6 60 +60 6 +6 61 +61 6 +6 62 +62 6 +6 63 +63 6 +6 64 +64 6 +6 65 +65 6 +6 66 +66 6 +6 67 +67 6 +6 68 +68 6 +6 69 +69 6 +6 70 +70 6 +6 71 +71 6 +6 72 +72 6 +6 73 +73 6 +6 74 +74 6 +6 75 +75 6 +6 80 +80 6 +6 81 +81 6 +6 82 +82 6 +6 83 +83 6 +6 84 +84 6 +6 85 +85 6 +6 86 +86 6 +6 87 +87 6 +56 57 +57 56 +56 58 +58 56 +56 59 +59 56 +56 60 +60 56 +56 61 +61 56 +56 62 +62 56 +56 63 +63 56 +56 64 +64 56 +56 65 +65 56 +56 66 +66 56 +56 67 +67 56 +56 68 +68 56 +56 69 +69 56 +56 70 +70 56 +56 71 +71 56 +56 72 +72 56 +56 73 +73 56 +56 74 +74 56 +56 75 +75 56 +56 80 +80 56 +56 81 +81 56 +56 82 +82 56 +56 83 +83 56 +56 84 +84 56 +56 85 +85 56 +56 86 +86 56 +56 87 +87 56 +57 58 +58 57 +57 59 +59 57 +57 60 +60 57 +57 61 +61 57 +57 62 +62 57 +57 63 +63 57 +57 64 +64 57 +57 65 +65 57 +57 66 +66 57 +57 67 +67 57 +57 68 +68 57 +57 69 +69 57 +57 70 +70 57 +57 71 +71 57 +57 72 +72 57 +57 73 +73 57 +57 74 +74 57 +57 75 +75 57 +57 80 +80 57 +57 81 +81 57 +57 82 +82 57 +57 83 +83 57 +57 84 +84 57 +57 85 +85 57 +57 86 +86 57 +57 87 +87 57 +58 59 +59 58 +58 60 +60 58 +58 61 +61 58 +58 62 +62 58 +58 63 +63 58 +58 64 +64 58 +58 65 +65 58 +58 66 +66 58 +58 67 +67 58 +58 68 +68 58 +58 69 +69 58 +58 70 +70 58 +58 71 +71 58 +58 72 +72 58 +58 73 +73 58 +58 74 +74 58 +58 75 +75 58 +58 80 +80 58 +58 81 +81 58 +58 82 +82 58 +58 83 +83 58 +58 84 +84 58 +58 85 +85 58 +58 86 +86 58 +58 87 +87 58 +59 60 +60 59 +59 61 +61 59 +59 62 +62 59 +59 63 +63 59 +59 64 +64 59 +59 65 +65 59 +59 66 +66 59 +59 67 +67 59 +59 68 +68 59 +59 69 +69 59 +59 70 +70 59 +59 71 +71 59 +59 72 +72 59 +59 73 +73 59 +59 74 +74 59 +59 75 +75 59 +59 80 +80 59 +59 81 +81 59 +59 82 +82 59 +59 83 +83 59 +59 84 +84 59 +59 85 +85 59 +59 86 +86 59 +59 87 +87 59 +60 61 +61 60 +60 62 +62 60 +60 63 +63 60 +60 64 +64 60 +60 65 +65 60 +60 66 +66 60 +60 67 +67 60 +60 68 +68 60 +60 69 +69 60 +60 70 +70 60 +60 71 +71 60 +60 72 +72 60 +60 73 +73 60 +60 74 +74 60 +60 75 +75 60 +60 80 +80 60 +60 81 +81 60 +60 82 +82 60 +60 83 +83 60 +60 84 +84 60 +60 85 +85 60 +60 86 +86 60 +60 87 +87 60 +61 62 +62 61 +61 63 +63 61 +61 64 +64 61 +61 65 +65 61 +61 66 +66 61 +61 67 +67 61 +61 68 +68 61 +61 69 +69 61 +61 70 +70 61 +61 71 +71 61 +61 72 +72 61 +61 73 +73 61 +61 74 +74 61 +61 75 +75 61 +61 80 +80 61 +61 81 +81 61 +61 82 +82 61 +61 83 +83 61 +61 84 +84 61 +61 85 +85 61 +61 86 +86 61 +61 87 +87 61 +62 63 +63 62 +62 64 +64 62 +62 65 +65 62 +62 66 +66 62 +62 67 +67 62 +62 68 +68 62 +62 69 +69 62 +62 70 +70 62 +62 71 +71 62 +62 72 +72 62 +62 73 +73 62 +62 74 +74 62 +62 75 +75 62 +62 80 +80 62 +62 81 +81 62 +62 82 +82 62 +62 83 +83 62 +62 84 +84 62 +62 85 +85 62 +62 86 +86 62 +62 87 +87 62 +63 64 +64 63 +63 65 +65 63 +63 66 +66 63 +63 67 +67 63 +63 68 +68 63 +63 69 +69 63 +63 70 +70 63 +63 71 +71 63 +63 72 +72 63 +63 73 +73 63 +63 74 +74 63 +63 75 +75 63 +63 80 +80 63 +63 81 +81 63 +63 82 +82 63 +63 83 +83 63 +63 84 +84 63 +63 85 +85 63 +63 86 +86 63 +63 87 +87 63 +64 65 +65 64 +64 66 +66 64 +64 67 +67 64 +64 68 +68 64 +64 69 +69 64 +64 70 +70 64 +64 71 +71 64 +64 72 +72 64 +64 73 +73 64 +64 74 +74 64 +64 75 +75 64 +64 80 +80 64 +64 81 +81 64 +64 82 +82 64 +64 83 +83 64 +64 84 +84 64 +64 85 +85 64 +64 86 +86 64 +64 87 +87 64 +65 66 +66 65 +65 67 +67 65 +65 68 +68 65 +65 69 +69 65 +65 70 +70 65 +65 71 +71 65 +65 72 +72 65 +65 73 +73 65 +65 74 +74 65 +65 75 +75 65 +65 80 +80 65 +65 81 +81 65 +65 82 +82 65 +65 83 +83 65 +65 84 +84 65 +65 85 +85 65 +65 86 +86 65 +65 87 +87 65 +66 67 +67 66 +66 68 +68 66 +66 69 +69 66 +66 70 +70 66 +66 71 +71 66 +66 72 +72 66 +66 73 +73 66 +66 74 +74 66 +66 75 +75 66 +66 80 +80 66 +66 81 +81 66 +66 82 +82 66 +66 83 +83 66 +66 84 +84 66 +66 85 +85 66 +66 86 +86 66 +66 87 +87 66 +67 68 +68 67 +67 69 +69 67 +67 70 +70 67 +67 71 +71 67 +67 72 +72 67 +67 73 +73 67 +67 74 +74 67 +67 75 +75 67 +67 80 +80 67 +67 81 +81 67 +67 82 +82 67 +67 83 +83 67 +67 84 +84 67 +67 85 +85 67 +67 86 +86 67 +67 87 +87 67 +68 69 +69 68 +68 70 +70 68 +68 71 +71 68 +68 72 +72 68 +68 73 +73 68 +68 74 +74 68 +68 75 +75 68 +68 80 +80 68 +68 81 +81 68 +68 82 +82 68 +68 83 +83 68 +68 84 +84 68 +68 85 +85 68 +68 86 +86 68 +68 87 +87 68 +69 70 +70 69 +69 71 +71 69 +69 72 +72 69 +69 73 +73 69 +69 74 +74 69 +69 75 +75 69 +69 80 +80 69 +69 81 +81 69 +69 82 +82 69 +69 83 +83 69 +69 84 +84 69 +69 85 +85 69 +69 86 +86 69 +69 87 +87 69 +70 71 +71 70 +70 72 +72 70 +70 73 +73 70 +70 74 +74 70 +70 75 +75 70 +70 80 +80 70 +70 81 +81 70 +70 82 +82 70 +70 83 +83 70 +70 84 +84 70 +70 85 +85 70 +70 86 +86 70 +70 87 +87 70 +71 72 +72 71 +71 73 +73 71 +71 74 +74 71 +71 75 +75 71 +71 80 +80 71 +71 81 +81 71 +71 82 +82 71 +71 83 +83 71 +71 84 +84 71 +71 85 +85 71 +71 86 +86 71 +71 87 +87 71 +72 73 +73 72 +72 74 +74 72 +72 75 +75 72 +72 80 +80 72 +72 81 +81 72 +72 82 +82 72 +72 83 +83 72 +72 84 +84 72 +72 85 +85 72 +72 86 +86 72 +72 87 +87 72 +73 74 +74 73 +73 75 +75 73 +73 80 +80 73 +73 81 +81 73 +73 82 +82 73 +73 83 +83 73 +73 84 +84 73 +73 85 +85 73 +73 86 +86 73 +73 87 +87 73 +74 75 +75 74 +74 80 +80 74 +74 81 +81 74 +74 82 +82 74 +74 83 +83 74 +74 84 +84 74 +74 85 +85 74 +74 86 +86 74 +74 87 +87 74 +75 80 +80 75 +75 81 +81 75 +75 82 +82 75 +75 83 +83 75 +75 84 +84 75 +75 85 +85 75 +75 86 +86 75 +75 87 +87 75 +80 81 +81 80 +80 82 +82 80 +80 83 +83 80 +80 84 +84 80 +80 85 +85 80 +80 86 +86 80 +80 87 +87 80 +81 82 +82 81 +81 83 +83 81 +81 84 +84 81 +81 85 +85 81 +81 86 +86 81 +81 87 +87 81 +82 83 +83 82 +82 84 +84 82 +82 85 +85 82 +82 86 +86 82 +82 87 +87 82 +83 84 +84 83 +83 85 +85 83 +83 86 +86 83 +83 87 +87 83 +84 85 +85 84 +84 86 +86 84 +84 87 +87 84 +85 86 +86 85 +85 87 +87 85 +86 87 +87 86 +6 16 +16 6 +6 26 +26 6 +7 8 +8 7 +8 17 +17 8 +8 18 +18 8 +7 9 +9 7 +8 27 +27 8 +9 17 +17 9 +9 18 +18 9 +9 27 +27 9 +18 19 +19 18 +19 28 +28 19 +29 29 +29 29 +18 20 +20 18 +27 19 +19 27 +27 30 +30 27 +29 7 +7 29 +7 10 +10 7 +17 30 +30 17 +30 7 +7 30 +27 10 +10 27 +28 9 +9 28 +28 20 +20 28 +20 17 +17 20 +18 29 +29 18 +8 28 +28 8 +10 18 +18 10 +10 28 +28 10 +20 27 +27 20 +27 29 +29 27 +28 29 +29 28 +17 19 +19 17 +28 30 +30 28 +2 12 +12 2 +11 12 +12 11 +12 21 +21 12 +12 22 +22 12 +22 23 +23 22 +22 24 +24 22 +3 13 +13 3 +4 13 +13 4 +1 13 +13 1 +2 13 +13 2 +3 15 +15 3 +4 15 +15 4 +21 24 +24 21 +21 25 +25 21 +22 25 +25 22 +13 22 +22 13 +14 22 +22 14 +15 22 +22 15 +1 25 +25 1 +5 25 +25 5 +5 13 +13 5 +13 21 +21 13 +15 2 +2 15 +24 4 +4 24 +24 2 +2 24 +12 4 +4 12 +4 14 +14 4 +2 14 +14 2 +1 14 +14 1 +14 21 +21 14 +11 14 +14 11 +11 24 +24 11 +11 25 +25 11 +25 2 +2 25 +25 4 +4 25 +3 23 +23 3 +11 13 +13 11 +11 15 +15 11 +21 23 +23 21 +30 18 +18 30 +30 12 +12 30 +30 14 +14 30 +30 76 +76 30 +30 77 +77 30 +30 78 +78 30 +30 79 +79 30 +17 11 +11 17 +17 80 +80 17 +17 81 +81 17 +17 82 +82 17 +17 83 +83 17 +17 84 +84 17 +17 85 +85 17 +17 86 +86 17 +17 87 +87 17 +18 11 +11 18 +18 80 +80 18 +18 81 +81 18 +18 82 +82 18 +18 83 +83 18 +18 84 +84 18 +18 85 +85 18 +18 86 +86 18 +18 87 +87 18 +11 76 +76 11 +11 77 +77 11 +11 78 +78 11 +11 79 +79 11 +12 80 +80 12 +12 81 +81 12 +12 82 +82 12 +12 83 +83 12 +12 84 +84 12 +12 85 +85 12 +12 86 +86 12 +12 87 +87 12 +14 80 +80 14 +14 81 +81 14 +14 82 +82 14 +14 83 +83 14 +14 84 +84 14 +14 85 +85 14 +14 86 +86 14 +14 87 +87 14 +76 80 +80 76 +76 81 +81 76 +76 82 +82 76 +76 83 +83 76 +76 84 +84 76 +76 85 +85 76 +76 86 +86 76 +76 87 +87 76 +77 80 +80 77 +77 81 +81 77 +77 82 +82 77 +77 83 +83 77 +77 84 +84 77 +77 85 +85 77 +77 86 +86 77 +77 87 +87 77 +78 80 +80 78 +78 81 +81 78 +78 82 +82 78 +78 83 +83 78 +78 84 +84 78 +78 85 +85 78 +78 86 +86 78 +78 87 +87 78 +79 80 +80 79 +79 81 +81 79 +79 82 +82 79 +79 83 +83 79 +79 84 +84 79 +79 85 +85 79 +79 86 +86 79 +79 87 +87 79 diff --git a/examples/hysgen/synthetic_data/synthetic.hyperedges b/examples/hysgen/synthetic_data/synthetic.hyperedges new file mode 100644 index 000000000..278133758 --- /dev/null +++ b/examples/hysgen/synthetic_data/synthetic.hyperedges @@ -0,0 +1,55 @@ +14 15 16 17 18 23 24 25 26 27 28 31 32 33 34 35 13 12 7 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 76 77 78 79 +22 21 11 2 1 3 4 5 8 9 10 20 19 29 30 6 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 80 81 82 83 84 85 86 87 +6 16 26 +7 8 17 18 +7 8 9 17 18 27 +8 17 +8 9 +9 10 19 20 +10 20 +18 19 28 +28 29 30 +27 28 +17 28 +18 19 20 +10 19 20 29 30 +27 19 30 +29 7 10 +17 30 7 +27 8 10 +28 9 20 17 +7 18 29 +8 10 18 20 27 28 29 +7 17 27 +8 18 28 +9 19 29 +10 20 30 +7 8 9 10 +17 18 19 20 +27 28 29 30 +2 11 12 +1 11 +11 12 21 22 +11 22 +12 13 14 +14 23 24 +22 23 +22 23 24 +13 14 15 25 +3 4 13 +2 3 +1 2 13 +3 4 15 +21 22 24 25 +12 13 14 15 22 23 24 25 +1 5 25 13 21 +22 15 24 12 4 2 14 +5 4 21 +1 14 21 +11 14 24 25 2 4 +3 13 23 +4 14 24 +1 2 3 4 5 +11 12 13 14 15 +21 22 23 24 25 +30 17 18 11 12 14 76 77 78 79 80 81 82 83 84 85 86 87 diff --git a/examples/hysgen/targetver.h b/examples/hysgen/targetver.h new file mode 100644 index 000000000..6fe8eb79e --- /dev/null +++ b/examples/hysgen/targetver.h @@ -0,0 +1,13 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + diff --git a/examples/infopath/infopath.vcxproj b/examples/infopath/infopath.vcxproj index 258cc7dea..f8c945864 100644 --- a/examples/infopath/infopath.vcxproj +++ b/examples/infopath/infopath.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/kcores/kcores.vcxproj b/examples/kcores/kcores.vcxproj index a015cbcb1..3fe2a8e5c 100644 --- a/examples/kcores/kcores.vcxproj +++ b/examples/kcores/kcores.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/kronem/kronem.vcxproj b/examples/kronem/kronem.vcxproj index 54707b9b8..1caf1ea18 100644 --- a/examples/kronem/kronem.vcxproj +++ b/examples/kronem/kronem.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/kronfit/kronfit.vcxproj b/examples/kronfit/kronfit.vcxproj index beba4f838..bb20156b4 100644 --- a/examples/kronfit/kronfit.vcxproj +++ b/examples/kronfit/kronfit.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/krongen/krongen.vcxproj b/examples/krongen/krongen.vcxproj index 235798d8c..12837395a 100644 --- a/examples/krongen/krongen.vcxproj +++ b/examples/krongen/krongen.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/magfit/magfit.vcxproj b/examples/magfit/magfit.vcxproj index 36139afdf..a602141e5 100644 --- a/examples/magfit/magfit.vcxproj +++ b/examples/magfit/magfit.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/maggen/maggen.vcxproj b/examples/maggen/maggen.vcxproj index 77da99d5f..491a81fe0 100644 --- a/examples/maggen/maggen.vcxproj +++ b/examples/maggen/maggen.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application NotSet + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/mkdatasets/mkdatasets.vcxproj b/examples/mkdatasets/mkdatasets.vcxproj index ef72d85ed..4226f37bb 100644 --- a/examples/mkdatasets/mkdatasets.vcxproj +++ b/examples/mkdatasets/mkdatasets.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/motifs/motifs.vcxproj b/examples/motifs/motifs.vcxproj index eeb27075d..eacd72de9 100644 --- a/examples/motifs/motifs.vcxproj +++ b/examples/motifs/motifs.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/ncpplot/ncpplot.vcxproj b/examples/ncpplot/ncpplot.vcxproj index cbf57a9e0..73014852a 100644 --- a/examples/ncpplot/ncpplot.vcxproj +++ b/examples/ncpplot/ncpplot.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/netevol/netevol.vcxproj b/examples/netevol/netevol.vcxproj index 3c0e41062..7b9604b78 100644 --- a/examples/netevol/netevol.vcxproj +++ b/examples/netevol/netevol.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/netinf/netinf.vcxproj b/examples/netinf/netinf.vcxproj index 4236fe6c4..ff85b91f5 100644 --- a/examples/netinf/netinf.vcxproj +++ b/examples/netinf/netinf.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/netstat/netstat.vcxproj b/examples/netstat/netstat.vcxproj index 51512ca27..a1bfd7870 100644 --- a/examples/netstat/netstat.vcxproj +++ b/examples/netstat/netstat.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/node2vec/ReadMe.txt b/examples/node2vec/ReadMe.txt index c39d46bb8..d053290ff 100644 --- a/examples/node2vec/ReadMe.txt +++ b/examples/node2vec/ReadMe.txt @@ -25,6 +25,7 @@ Inout hyperparameter. Default is 1 (-q:) Verbose output. (-v) Graph is directed. (-dr) Graph is weighted. (-w) +Output random walks instead of embeddings. (-ow) ///////////////////////////////////////////////////////////////////////////// diff --git a/examples/node2vec/node2vec.cpp b/examples/node2vec/node2vec.cpp index cda12c6ce..1b0b75cc4 100644 --- a/examples/node2vec/node2vec.cpp +++ b/examples/node2vec/node2vec.cpp @@ -8,7 +8,8 @@ void ParseArgs(int& argc, char* argv[], TStr& InFile, TStr& OutFile, int& Dimensions, int& WalkLen, int& NumWalks, int& WinSize, int& Iter, - bool& Verbose, double& ParamP, double& ParamQ, bool& Directed, bool& Weighted) { + bool& Verbose, double& ParamP, double& ParamQ, bool& Directed, bool& Weighted, + bool& OutputWalks) { Env = TEnv(argc, argv, TNotify::StdNotify); Env.PrepArgs(TStr::Fmt("\nAn algorithmic framework for representational learning on graphs.")); InFile = Env.GetIfArgPrefixStr("-i:", "graph/karate.edgelist", @@ -32,6 +33,7 @@ void ParseArgs(int& argc, char* argv[], TStr& InFile, TStr& OutFile, Verbose = Env.IsArgStr("-v", "Verbose output."); Directed = Env.IsArgStr("-dr", "Graph is directed."); Weighted = Env.IsArgStr("-w", "Graph is weighted."); + OutputWalks = Env.IsArgStr("-ow", "Output random walks instead of embeddings."); } void ReadGraph(TStr& InFile, bool& Directed, bool& Weighted, bool& Verbose, PWNet& InNet) { @@ -65,8 +67,22 @@ void ReadGraph(TStr& InFile, bool& Directed, bool& Weighted, bool& Verbose, PWNe } } -void WriteOutput(TStr& OutFile, TIntFltVH& EmbeddingsHV) { +void WriteOutput(TStr& OutFile, TIntFltVH& EmbeddingsHV, TVVec& WalksVV, + bool& OutputWalks) { TFOut FOut(OutFile); + if (OutputWalks) { + for (int64 i = 0; i < WalksVV.GetXDim(); i++) { + for (int64 j = 0; j < WalksVV.GetYDim(); j++) { + FOut.PutInt(WalksVV(i,j)); + if(j+1==WalksVV.GetYDim()) { + FOut.PutLn(); + } else { + FOut.PutCh(' '); + } + } + } + return; + } bool First = 1; for (int i = EmbeddingsHV.FFirstKeyId(); EmbeddingsHV.FNextKeyId(i);) { if (First) { @@ -89,14 +105,15 @@ int main(int argc, char* argv[]) { TStr InFile,OutFile; int Dimensions, WalkLen, NumWalks, WinSize, Iter; double ParamP, ParamQ; - bool Directed, Weighted, Verbose; + bool Directed, Weighted, Verbose, OutputWalks; ParseArgs(argc, argv, InFile, OutFile, Dimensions, WalkLen, NumWalks, WinSize, - Iter, Verbose, ParamP, ParamQ, Directed, Weighted); + Iter, Verbose, ParamP, ParamQ, Directed, Weighted, OutputWalks); PWNet InNet = PWNet::New(); TIntFltVH EmbeddingsHV; + TVVec WalksVV; ReadGraph(InFile, Directed, Weighted, Verbose, InNet); node2vec(InNet, ParamP, ParamQ, Dimensions, WalkLen, NumWalks, WinSize, Iter, - Verbose, EmbeddingsHV); - WriteOutput(OutFile, EmbeddingsHV); + Verbose, OutputWalks, WalksVV, EmbeddingsHV); + WriteOutput(OutFile, EmbeddingsHV, WalksVV, OutputWalks); return 0; } diff --git a/examples/randwalk/randwalk.vcxproj b/examples/randwalk/randwalk.vcxproj index 51bcb80b9..d578255fc 100644 --- a/examples/randwalk/randwalk.vcxproj +++ b/examples/randwalk/randwalk.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/examples/rolx/rolx.vcxproj b/examples/rolx/rolx.vcxproj index 6e7072c71..5762c50e6 100644 --- a/examples/rolx/rolx.vcxproj +++ b/examples/rolx/rolx.vcxproj @@ -28,23 +28,27 @@ Application true MultiByte + v142 Application true NotSet + v142 Application false true - Unicode + MultiByte + v142 Application false true NotSet + v142 diff --git a/examples/rolx/testrolx.cpp b/examples/rolx/testrolx.cpp index 93540dbc8..0d2b9a72f 100644 --- a/examples/rolx/testrolx.cpp +++ b/examples/rolx/testrolx.cpp @@ -23,9 +23,12 @@ int main(int argc, char* argv[]) { TIntFtrH Features = ExtractFeatures(Graph); TIntIntH NodeIdMtxIdH = CreateNodeIdMtxIdxHash(Features); TFltVV V = ConvertFeatureToMatrix(Features, NodeIdMtxIdH); - //printf("saving features...\n"); - //FPrintMatrix(V, "v.txt"); + printf("saving features...\n"); + FPrintMatrix(V, "v.txt"); printf("feature matrix is saved in v.txt\n"); + printf("saving node mappings: feature line -> node ID...\n"); + FPrintNodeMappings(NodeIdMtxIdH, "mappings.txt"); + printf("node mappings are saved to mappings.txt\n"); TFlt MnError = TFlt::Mx; TFltVV FinalG, FinalF; int NumRoles = -1; diff --git a/examples/temporalmotifs/temporalmotifsmain.cpp b/examples/temporalmotifs/temporalmotifsmain.cpp index d639e1cc2..375f14fe2 100644 --- a/examples/temporalmotifs/temporalmotifsmain.cpp +++ b/examples/temporalmotifs/temporalmotifsmain.cpp @@ -35,8 +35,8 @@ int main(int argc, char* argv[]) { FILE* output_file = fopen(output.CStr(), "wt"); for (int i = 0; i < counts.m(); i++) { for (int j = 0; j < counts.n(); j++) { - int count = counts(i, j); - fprintf(output_file, "%d", count); + uint64 count = counts(i, j); + fprintf(output_file, "%s", TUInt64::GetStr(count).CStr()); if (j < counts.n() - 1) { fprintf(output_file, " "); } } fprintf(output_file, "\n"); diff --git a/examples/testgraph/testgraph.vcxproj b/examples/testgraph/testgraph.vcxproj index 4f626bc26..df8518c95 100755 --- a/examples/testgraph/testgraph.vcxproj +++ b/examples/testgraph/testgraph.vcxproj @@ -18,12 +18,14 @@ Application - NotSet + MultiByte true + v142 Application MultiByte + v142 @@ -45,6 +47,9 @@ false ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + + ..\..\glib-core;..\..\snap-core;..\..\snap-adv;$(IncludePath) + Disabled diff --git a/glib-core/base.cpp b/glib-core/base.cpp index 410e56031..6f1296888 100644 --- a/glib-core/base.cpp +++ b/glib-core/base.cpp @@ -56,7 +56,7 @@ int _daylight = 0; #endif #if defined(WIN32_LEAN_AND_MEAN) -int gettimeofday(struct timeval * tp, struct timezone * tzp) +int gettimeofday(struct timeval *tp, void *tzp) { // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); diff --git a/glib-core/base.h b/glib-core/base.h index 3d83e44cb..f89040e66 100644 --- a/glib-core/base.h +++ b/glib-core/base.h @@ -81,7 +81,7 @@ #if defined(WIN32_LEAN_AND_MEAN) #include - int gettimeofday(struct timeval * tp, struct timezone * tzp); + int gettimeofday(struct timeval *tp, void *tzp); #endif // word size @@ -139,6 +139,7 @@ #ifdef GLib_CYGWIN #define timezone _timezone + #define _OPENMP #endif //#ifdef GLib_MACOSX diff --git a/glib-core/bd.cpp b/glib-core/bd.cpp index c363a93fd..0c3adf1c8 100644 --- a/glib-core/bd.cpp +++ b/glib-core/bd.cpp @@ -4,7 +4,9 @@ ///////////////////////////////////////////////// // Mathmatical-Errors -#if defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__==0x0530) +#if defined(__GNUC__) && (__GNUC__ >= 6) +// skips matherr handling as matherr not supported in g++ 6 or later +#elif defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__==0x0530) int std::_matherr(struct math_exception* e){ e->retval=0; return 1; diff --git a/glib-core/bd.h b/glib-core/bd.h index 4b63d250a..411acf2ce 100644 --- a/glib-core/bd.h +++ b/glib-core/bd.h @@ -58,6 +58,21 @@ typedef ptrdiff_t ssize_t; typedef size_t TSize; #define TSizeMx SIZE_MAX +#if 0 +// op RS 2023/02/27, Ubuntu 18.10 works fine without this code +///////////////////////////////////////////////// +// For Ubuntu >= 18.04 +#if defined(GLib_GLIBC) || defined(GLib_BSD) +struct __exception { + int type; /* Exception type */ + char* name; /* Name of function causing exception */ + double arg1; /* 1st argument to function */ + double arg2; /* 2nd argument to function */ + double retval; /* Function return value */ +}; +#endif +#endif + ///////////////////////////////////////////////// // Localization typedef enum {lUndef, lUs, lSi} TLoc; diff --git a/glib-core/ds.h b/glib-core/ds.h index eb3224d2e..90c525680 100644 --- a/glib-core/ds.h +++ b/glib-core/ds.h @@ -1567,6 +1567,7 @@ typedef TVec TStrVIntPrV; typedef TVec TFltIntIntIntQuV; typedef TVec TIntStrIntIntQuV; typedef TVec TIntIntPrPrV; +typedef TVec TFltVFltV; //#////////////////////////////////////////////// /// Vector Pool. ##TVecPool diff --git a/glib-core/dt.h b/glib-core/dt.h index e9a53fbee..c0d578c48 100644 --- a/glib-core/dt.h +++ b/glib-core/dt.h @@ -458,6 +458,9 @@ class TStr{ TRStr* NewRStr=new TRStr(RStr->CStr(), CStr); RStr->UnRef(); RStr=NewRStr; RStr->MkRef(); Optimize(); return *this;} + TStr& operator/(const int& N){ + // no-op, this definition is required by the aaMean table aggregation + return *this;} bool operator==(const TStr& Str) const { return (RStr==Str.RStr)||(strcmp(RStr->CStr(), Str.RStr->CStr())==0);} bool operator==(const char* CStr) const { @@ -877,8 +880,8 @@ template class TNum{ TNum& operator=(const Base& _Val){ Val = _Val; return *this; } TNum& operator++(){ ++Val; return *this; } // prefix TNum& operator--(){ --Val; return *this; } // prefix - TNum operator++(Base){ TNum oldVal = Val; Val++; return oldVal; } // postfix - TNum operator--(Base){ TNum oldVal = Val; Val--; return oldVal; } // postfix + TNum operator++(int){ TNum oldVal = Val; Val++; return oldVal; } // postfix + TNum operator--(int){ TNum oldVal = Val; Val--; return oldVal; } // postfix Base& operator()() { return Val; } int GetMemUsed() const { return sizeof(TNum); } diff --git a/glib-core/linalg.cpp b/glib-core/linalg.cpp index f69d4c6c3..9768041a2 100644 --- a/glib-core/linalg.cpp +++ b/glib-core/linalg.cpp @@ -705,7 +705,7 @@ void TNumericalStuff::SymetricToTridiag(TFltVV& a, int n, TFltV& d, TFltV& e) { e[j]=g=e[j]-hh*f; for (k=1;k<=j;k++) { //Reduce a, equation (11.2.13). a(j-1,k-1) -= (f*e[k]+g*a(i-1,k-1)); - Assert(_isnan(a(j-1,k-1)) == 0); + Assert(_isnan(static_cast(a(j-1,k-1))) == 0); } } } @@ -727,7 +727,7 @@ void TNumericalStuff::SymetricToTridiag(TFltVV& a, int n, TFltV& d, TFltV& e) { g += a(i-1,k-1)*a(k-1,j-1); for (k=1;k<=l;k++) { a(k-1,j-1) -= g*a(k-1,i-1); - Assert(_isnan(a(k-1,j-1)) == 0); + Assert(_isnan(static_cast(a(k-1,j-1))) == 0); } } } diff --git a/glib-core/ssmp.cpp b/glib-core/ssmp.cpp index aaa547ec1..b8dca4acb 100644 --- a/glib-core/ssmp.cpp +++ b/glib-core/ssmp.cpp @@ -163,27 +163,33 @@ int TSsParserMP::GetIntFromFldV(TVec& FieldsV, const int& FldN) { c++; } if (Minus) { _Val = -_Val; } - //if (*c != 0) { return -1; } + if (*c != 0 && !TCh::IsWs(*c)) { return -1; } return _Val; } double TSsParserMP::GetFltFromFldV(TVec& FieldsV, const int& FldN) { // parsing format {ws} [+/-] +{d} ([.]{d}) ([E|e] [+/-] +{d}) const char *c = FieldsV[FldN]; + /* skip whitespace at the beginning */ while (TCh::IsWs(*c)) { c++; } + /* skip the sign */ if (*c=='+' || *c=='-') { c++; } + /* error, if not a digit or '.' */ if (! TCh::IsNum(*c) && *c!='.') { return -1; } + /* skip digits */ while (TCh::IsNum(*c)) { c++; } if (*c == '.') { c++; while (TCh::IsNum(*c)) { c++; } } + /* skip exponent */ if (*c=='e' || *c == 'E') { c++; if (*c == '+' || *c == '-' ) { c++; } if (! TCh::IsNum(*c)) { return -1; } while (TCh::IsNum(*c)) { c++; } } - if (*c != 0) { return -1; } + if (*c != 0 && !TCh::IsWs(*c)) { return -1; } return atof(FieldsV[FldN]); } + diff --git a/glib-core/tm.h b/glib-core/tm.h index 9bd009df0..816135e87 100644 --- a/glib-core/tm.h +++ b/glib-core/tm.h @@ -354,16 +354,16 @@ typedef TVec TStrTmPrV; // Execution-Time class TExeTm{ private: - int LastTick; + double LastTick; public: TExeTm(): LastTick(0) { Tick(); } TExeTm(const TExeTm& Tm): LastTick(Tm.LastTick) { } TExeTm& operator=(const TExeTm& Tm){ LastTick=Tm.LastTick; return *this;} - void Tick(){LastTick=(int)clock();} - int GetTime() const {return int(clock()-LastTick);} - double GetSecs() const {return double(clock()-LastTick)/double(CLOCKS_PER_SEC);} + void Tick(){LastTick=(double)clock();} + int GetTime() const {return int((double) clock()-LastTick);} + double GetSecs() const {return (double(clock())-LastTick)/double(CLOCKS_PER_SEC);} int GetSecInt() { return TFlt::Round(GetSecs()); } const char* GetStr() const {return GetTmStr();} TStr GetStr2() const {return GetTmStr();} diff --git a/snap-adv/biasedrandomwalk.cpp b/snap-adv/biasedrandomwalk.cpp index 7ad884aa7..d71b7111a 100644 --- a/snap-adv/biasedrandomwalk.cpp +++ b/snap-adv/biasedrandomwalk.cpp @@ -34,6 +34,17 @@ void GetNodeAlias(TFltV& PTblV, TIntVFltVPr& NTTable) { OverV.Add(Large); } } + while(UnderV.Len() > 0){ + int64 curr = UnderV.Last(); + UnderV.DelLast(); + UTbl[curr]=1; + } + while(OverV.Len() > 0){ + int64 curr = OverV.Last(); + OverV.DelLast(); + UTbl[curr]=1; + } + } //Get random element using alias sampling method @@ -44,8 +55,8 @@ int64 AliasDrawInt(TIntVFltVPr& NTTable, TRnd& Rnd) { return Y < NTTable.GetVal2()[X] ? X : NTTable.GetVal1()[X]; } -void PreprocessNode (PWNet& InNet, double& ParamP, double& ParamQ, - TWNet::TNodeI NI, int64& NCnt, bool& Verbose) { +void PreprocessNode (PWNet& InNet, const double& ParamP, const double& ParamQ, + TWNet::TNodeI NI, int64& NCnt, const bool& Verbose) { if (Verbose && NCnt%100 == 0) { printf("\rPreprocessing progress: %.2lf%% ",(double)NCnt*100/(double)(InNet->GetNodes()));fflush(stdout); } @@ -83,7 +94,7 @@ void PreprocessNode (PWNet& InNet, double& ParamP, double& ParamQ, } //Preprocess transition probabilities for each path t->v->x -void PreprocessTransitionProbs(PWNet& InNet, double& ParamP, double& ParamQ, bool& Verbose) { +void PreprocessTransitionProbs(PWNet& InNet, const double& ParamP, const double& ParamQ, const bool& Verbose) { for (TWNet::TNodeI NI = InNet->BegNI(); NI < InNet->EndNI(); NI++) { InNet->SetNDat(NI.GetId(),TIntIntVFltVPrH()); } @@ -117,7 +128,7 @@ int64 PredictMemoryRequirements(PWNet& InNet) { } //Simulates a random walk -void SimulateWalk(PWNet& InNet, int64 StartNId, int& WalkLen, TRnd& Rnd, TIntV& WalkV) { +void SimulateWalk(PWNet& InNet, int64 StartNId, const int& WalkLen, TRnd& Rnd, TIntV& WalkV) { WalkV.Add(StartNId); if (WalkLen == 1) { return; } if (InNet->GetNI(StartNId).GetOutDeg() == 0) { return; } diff --git a/snap-adv/biasedrandomwalk.h b/snap-adv/biasedrandomwalk.h index ea0840146..fb868ca8a 100644 --- a/snap-adv/biasedrandomwalk.h +++ b/snap-adv/biasedrandomwalk.h @@ -5,10 +5,10 @@ typedef TNodeEDatNet TWNet; typedef TPt PWNet; ///Preprocesses transition probabilities for random walks. Has to be called once before SimulateWalk calls -void PreprocessTransitionProbs(PWNet& InNet, double& ParamP, double& ParamQ, bool& verbose); +void PreprocessTransitionProbs(PWNet& InNet, const double& ParamP, const double& ParamQ, const bool& verbose); ///Simulates one walk and writes it into Walk vector -void SimulateWalk(PWNet& InNet, int64 StartNId, int& WalkLen, TRnd& Rnd, TIntV& Walk); +void SimulateWalk(PWNet& InNet, int64 StartNId, const int& WalkLen, TRnd& Rnd, TIntV& Walk); //Predicts approximate memory required for preprocessing the graph int64 PredictMemoryRequirements(PWNet& InNet); diff --git a/snap-adv/hysgen.cpp b/snap-adv/hysgen.cpp new file mode 100644 index 000000000..f6557e107 --- /dev/null +++ b/snap-adv/hysgen.cpp @@ -0,0 +1,1052 @@ +#include "stdafx.h" +#include "hysgen.h" + +void THysgenUtil::DumpCmtyVV(const TStr OutFNm, TVec& CmtyVV, TIntStrH& NIDNmH) { + FILE* F = fopen(OutFNm.CStr(), "wt"); + for (int c = 0; c < CmtyVV.Len(); c++) { + fprintf(F, "\n\n*** COMMUNITY #%d, Length=%d ***\n", c+1, CmtyVV[c].Len()); + for (int u = 0; u < CmtyVV[c].Len(); u++) { + if (NIDNmH.IsKey(CmtyVV[c][u])){ + fprintf(F, "%s\t", NIDNmH.GetDat(CmtyVV[c][u]).CStr()); + } + else { + fprintf(F, "%d\t", (int) CmtyVV[c][u]); + } + } + fprintf(F, "\n"); + } + fclose(F); +} +void THysgenUtil::DumpCmtyVH(const TStr OutFNm, TVec& CmtyVH, TIntStrH& NIDNmH, Criteria Crit) { + FILE* F = fopen(OutFNm.CStr(), "wt"); + int UId; + for (int c = 0; c < CmtyVH.Len(); c++) { + fprintf(F, "\n\n*** COMMUNITY #%d, Length=%d ***\n", c+1, CmtyVH[c].Len()); + TIntV SortedV; + if (Crit == Alphabetical) { + TIntStrH SortedCNames; + for (TIntFltH::TIter NI = CmtyVH[c].BegI(); NI < CmtyVH[c].EndI(); NI++) { + SortedCNames.AddDat(NI.GetKey(), NIDNmH.GetDat(NI.GetKey())); + } + SortedCNames.SortByDat(); + for (TIntStrH::TIter NI = SortedCNames.BegI(); + NI < SortedCNames.EndI(); NI++) { + SortedV.Add(NI.GetKey()); + } + } else { + CmtyVH[c].SortByDat(false); + CmtyVH[c].GetKeyV(SortedV); + } + for (TIntV ::TIter NI = SortedV.BegI(); NI < SortedV.EndI(); NI++) { + UId = NI->Val; + if (NIDNmH.IsKey(UId)){ + fprintf(F, "%s: ", NIDNmH.GetDat(UId).CStr()); + } + else { + fprintf(F, "%d: ", UId); + } + fprintf(F, "%f,\t", (double) CmtyVH[c].GetDat(UId)); + } + fprintf(F, "\n"); + } + fclose(F); +} + +PHGraph THysgenUtil::LoadEdgeList(const TStr& InFNm, TStrHash& NodeNameH, + TSsFmt SsFmt) { + TSsParser Ss(InFNm, SsFmt); + PHGraph PG = THGraph::New(); + THGraph& G = *PG; + TStrHash StrSet(Mega(1), true); + int EIdCtr = 0; + int RedunEdgesCnt = 0; + std::string Curr; + while (Ss.Next()) { + TIntSet NIdH; + NIdH.Gen(Ss.Len()); + if (Ss.Len() == 0) { continue; } + Curr = Ss[0]; + if (Curr.compare(0,1, "#") == 0) { continue; } // Comments are allowed in the file + for (int i = 0; i < Ss.Len(); i++){ + int ENId = StrSet.AddKey(Ss[i]); + if (! G.IsNode(ENId)) { G.AddNode(ENId, Ss[i]); } + NIdH.AddKey(ENId); + } + if (G.AddEdge(NIdH,EIdCtr) >= 0) { + EIdCtr++; + } else {RedunEdgesCnt++; } + } + printf("\nNumber of redundant edges: %d:\n", RedunEdgesCnt); + NodeNameH = StrSet; + NodeNameH.Pack(); + G.Defrag(); + return PG; +} + +template +double THysgenUtil::GetConductance(const PHGraph& Graph, const TIntSet& CmtyS, + const int N2Edges) { + TIntV NeiNV; + int Vol = 0, Cut = 0; + double Phi = 0.0; + for (int i = 0; i < CmtyS.Len(); i++) { + if (! Graph->IsNode(CmtyS[i])) { continue; } + THGraph::TNodeI NI = Graph->GetNI(CmtyS[i]); + NI.GetNbrNodes(NeiNV); + for (int nei = 0; nei < NeiNV.Len(); nei++) { + if (! CmtyS.IsKey(NeiNV[nei])) { Cut += 1; } + } + Vol += NI.Get2Edges(); + } + int N2Edges2 = N2Edges * 2; + if (Vol != N2Edges2) { + if (N2Edges2 - Vol < Vol) { Phi = Cut / double (N2Edges2 - Vol); } + else if (Vol == 0) { Phi = 0.0; } + else { Phi = Cut / double(Vol); } + } else { + if (Vol == N2Edges2) { Phi = 1.0; } + } + return Phi; +} + +template +void THysgenUtil::GetNbhCom(const PHGraph& Graph, const int NID, TIntSet& NBCmtyS) { + THGraph::TNodeI NI = Graph->GetNI(NID); + NBCmtyS.Gen(NI.GetNbrNodes() + 1); + NBCmtyS.AddKey(NID); + for (int e = 0; e < NI.GetNbrNodes(); e++) { + NBCmtyS.AddKey(NI.GetNbrNId(e)); + } +} + +template +void THysgenUtil::GetPhiNIdPrV(const PHGraph &G, TFltIntPrV &PhiNIdPrV, const int MinComSiz) { + PhiNIdPrV.Gen(G->GetNodes(), 0); + const int N2Edges = G->Get2Edges(); + TExeTm RunTm; + //compute conductance of neighborhood community + for (THGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { + TIntSet NBCmty(NI.GetNbrNodes() + 1); + double Phi; + if (NI.GetNbrNodes() < MinComSiz) { + Phi = 1.0; + } else { + THysgenUtil::GetNbhCom(G, NI.GetId(), NBCmty); + Phi = THysgenUtil::GetConductance(G, NBCmty, N2Edges); + } + PhiNIdPrV.Add(TFltIntPr(Phi, NI.GetId())); + } + PhiNIdPrV.Sort(true); + fflush(stdout); +} + +void THysgenUtil::GetBinLocs(const int& DecNum, TIntV& LocsV, const TIntV& NodMapV) { + int MaxShift = ceil(TMath::Log2((double) DecNum+1)); + int NumCopy = DecNum; + for (int j = 0; j < MaxShift; j++) { + if ( NumCopy / 2.0 != floor(NumCopy / 2.0) ) { + LocsV.Add(NodMapV[j]); + } + NumCopy = int(NumCopy / 2.0); + } +} + +void THysgen::SetGraph(const PHGraph& GraphPt) { + HONEIdsV.Gen(GraphPt->GetNodes()); + HONNIdsV.Gen(GraphPt->GetNodes()); + HOKIDSV.Gen(GraphPt->GetNodes()); + TIntV NIDV; + GraphPt->GetNIdV(NIDV); + NIdToIdx.Gen(NIDV.Len()); + NIdToIdx.AddKeyV(NIDV); + // check that nodes IDs are {0,1,..,Nodes-1} + G = TSnap::GetSubGraph(GraphPt, NIDV); + for (int nid = 0; nid < G->GetNodes(); nid++) { + IAssert(G->IsNode(nid)); + } + PrNoCom = 1.0 / (double) G->GetNodes(); + if (1.0 / PrNoCom > sqrt(TFlt::Mx)) { PrNoCom = 0.99 / sqrt(TFlt::Mx); } // to prevent overflow + NegWgt = 1.0; +} + +void THysgen::LoadComInit(const TStr& InFNm, TSsFmt SsFmt) { + TSsParser Ss(InFNm, SsFmt); + TVec ComsVH; + TStrSet NodsInFile(G->GetNodes()); + // int CId = 0; + std::string Curr; + printf("Loading community initializations from file ...\n"); + while (Ss.Next()) { + if (Ss.Len() == 0) { continue; } + Curr = Ss[0]; + if (Curr.compare(0,1, "#") == 0 || Curr.compare(0,1, "*") == 0) { continue; } // Comments are allowed in the file + TStrFltH CurComH; + for (int i = 0; i < Ss.Len(); i++){ + Curr = Ss[i]; + TStr NName; double SN; + int SepLoc = Curr.find_first_of(":"); + if (SepLoc == -1) { + NName = Curr.c_str(); + SN = InitVal; + } else { + NName = Curr.substr(0, SepLoc).c_str(); + SN = strtod(Curr.substr(SepLoc + 2, 8).c_str(), NULL); + } + CurComH.AddDat(NName, SN); + NodsInFile.AddKey(NName); + } + ComsVH.Add(CurComH); + } + for (int c = 0; c < ComsVH.Len(); c++) { + for (THGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { + AddNCom(NI.GetId(), c, InitNullS); + if (ComsVH[c].IsKey(NI.GetName())) { + AddNCom(NI.GetId(), c, ComsVH[c].GetDat(NI.GetName())); + } + } + } + printf("\n"); + for (int c = 0; c < GetNumComs(); c++) { + printf("comm %d:\t\t", c); + for (THGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { + if (GetNCom(NI.GetId(),c) > InitNullS) { + printf("%s,%0.2f\t",NI.GetName().CStr(), GetNCom(NI.GetId(),c)); + } + } + printf("\n"); + } + printf("\n Likelihood of the initial community memberships from the file is: %f\n", Likelihood()); +} + +void THysgen::ComInit(const int InitComs, const int MinComSiz, const double PerturbDens) { + IAssertR(InitVal>0.0 || InitNullS>0.0, "Error: At least one of -ic or -in " + "parameters should be set > 0. Cannot start without any initalization."); + S.Gen(G->GetNodes()); + time_t InitTime = time(NULL); + printf("\n** Initializing the communities and the parameters is started...\n"); + NumCIdNV.Gen(InitComs); + NumComs = InitComs; + if (InitNullS > 0.0) { + UniformComInit(InitComs); + InitTime = time(NULL); + InitEdgeProb(); + } + if (InitNullS != InitVal) { + InitTime = time(NULL); + NeighborComInit(MinComSiz, InitNullS==0.0); + if (InitNullS==0.0) { + InitTime = time(NULL); + InitEdgeProb(); + } + } + if (InitNullS != InitVal) { + RandomComPerturb(PerturbDens); + } else { RandomComPerturb(); } + printf("\n** Initializations finsihed [%lu sec]\n", time(NULL) - InitTime); +} + +void THysgen::UniformComInit(const int InitComs) { + for (int c=0; c < NumComs; c++) { + for (THGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { + AddNCom(NI.GetId(), c, InitNullS, true); + } + } +} + +void THysgen::RandomComPerturb(double Density) { + if (Density <= 0.0) { return; } + for (int c=0; c < NumComs; c++) { + for (THGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { + if (GetNCom(NI.GetId(), c) == 0) { continue; } // Reserve for later usages + if (Rnd.GetUniDev() < Density) { AddNCom(NI.GetId(), c, InitVal*Rnd.GetUniDev()); } + } + } +} + +void THysgen::NeighborComInit(const int MinComSiz, const bool& IsInit) { + TFltIntPrV PhiNIdPrV; + THysgenUtil::GetPhiNIdPrV(G, PhiNIdPrV, MinComSiz); + NeighborComInit(PhiNIdPrV, IsInit); +} +void THysgen::NeighborComInit(TFltIntPrV& PhiNIdPrV, const bool& IsInit) { + PhiNIdPrV.Sort(true); + TIntV NIdV; + TIntV EIdV; + THGraph::TNodeI NI; + THGraph::TEdgeI EI; + TIntSet InvalidNIDS(S.Len()); + //choose nodes with local minimum in conductance + TIntV NumCIdNDefV(NumComs, 0); + int CurCID = 0; + for (int ui = 0; ui < PhiNIdPrV.Len(); ui++) { + if (PhiNIdPrV[ui].Val1 == 0.0) { // Isolated nodes are of no interest. + continue; + } + int UID = PhiNIdPrV[ui].Val2; + fflush(stdout); + if (InvalidNIDS.IsKey(UID)) { continue; } + //add the node and its neighbors to the current community + AddNCom(UID, CurCID, InitVal, IsInit); + InvalidNIDS.AddKey(UID); + NI = G->GetNI(UID); + fflush(stdout); + NI.GetNbrNodes(NIdV); + AddNCom(NIdV, CurCID, InitVal, IsInit); + NumCIdNDefV[CurCID] = NIdV.Len()+1; + InvalidNIDS.AddKeyV(NIdV); + CurCID++; + if (CurCID >= NumComs) { break; } + fflush(stdout); + } + if (NumComs > CurCID) { + printf("%d communities needed to fill randomly\n", NumComs - CurCID); + } + for (int c = 0; c < NumCIdNV.Len(); c++) { + if (NumCIdNDefV[c] == 0) { + printf("Empty communities remained after initialization. " + "Members are getting assigned randomly!!\n\n"); + int ComSz = 10; + for (int u = 0; u < ComSz; u++) { + int UID = Rnd.GetUniDevInt(G->GetNodes()); + AddNCom(UID, c, InitVal, IsInit); + } + } + } +} + +void THysgen::InitEdgeProb(){ + TInt NId; + TInt CIterKey; + ProbEdgCommHH.Gen(G->GetEdges()); + ProbNotEdgH.Gen(G->GetEdges()); + ProbEdgH.Gen(G->GetEdges()); + ProbENoiseV.Gen(G->GetNodes(),1); + ProbENoiseV[0] = 1; + // Initializing the DP Matrix with zeros, to prevent new memory assignment in each use. + int DPMatSize = NumComs + (SNoise>0); // If there is an active SNoise, must be counted in the matrix. + AuxDPEdgVV.Gen(DPMatSize); + for (int i = 0; i < DPMatSize; i++) { + AuxDPEdgVV[i].Gen(DPMatSize); + for (int j = 0; j < DPMatSize; j++) { + AuxDPEdgVV[i][j] = 0.0; + } + } + // INITIALIZING the SAVED EDGE PROBABILITIES (For lower computation) + for (THGraph::TEdgeI EI = G->BegEI(); EI < G->EndEI(); EI++) { + TIntV NumMmbrsInEdgV(NumComs); + TIntFltH ProdH(NumComs);// S[v][1,..,C] + TIntV NeiNV; + EI.GetNodesV(NeiNV); + for (int n = 0; n < NeiNV.Len(); n++) { + NId = NeiNV[n]; + for (TIntFltH::TIter SNI = S[NId].BegI(); SNI < S[NId].EndI(); SNI++) { + CIterKey = SNI.GetKey(); + if (!ProdH.IsKey(CIterKey)) { ProdH.AddDat(CIterKey, 1.0); } + ProdH.AddDat(CIterKey, ProdH.GetDat(CIterKey)*SNI.GetDat()); + NumMmbrsInEdgV[CIterKey] ++; + } + } + /// If at least one node in the edge has a ZERO membership to a + /// community, the product of node memberships for that edge should + /// be zero. + /// Note that when NumMmbrsInEdgV[CId]==0, ProdH is not instantiated for + /// that CId, so we shouldn't try to remove it. + for (int CId = 0; CId < NumComs; CId++){ + if (NumMmbrsInEdgV[CId] > 0 && NumMmbrsInEdgV[CId] < NeiNV.Len()) { + ProdH.DelKey(CId); + } + } + AddECom(EI.GetId(), ProdH); + } + if (InitNullS > 0.0) { InitPrAllEdgesS(InitNullS, true); + } else { InitPrAllEdgesS(InitVal, false); } +} + +void THysgen::UpdateUEdgesProb(const int& UId, const int& CId, const double& SUNew){ + double SUOld = GetNCom(UId,CId); + TIntV EIdV; + TIntFltH ProbEH; + double PrECOld; + double PrECNew; + int EId; + G->GetNI(UId).GetEIDs(EIdV); + for (int e = 0; e < EIdV.Len(); e++) { + EId = EIdV[e]; + if (SUOld < DBL_EPSILON) { + TIntV ENodesV; + G->GetEI(EId).GetNbrNodes(ENodesV); + PrECNew = SUNew; + for (int n = 0; n < ENodesV.Len(); n++) { + if (ENodesV[n] == UId) { continue; } + PrECNew *= GetNCom(ENodesV[n], CId); + } + } else { + PrECOld = GetECom(EId, CId); + PrECNew = PrECOld*SUNew/SUOld; + } + if (PrECNew > 0.0) { + AddECom(EId, CId, PrECNew); + } else { + DelECom(EId, CId); + } + } +} + +void THysgen::InitPrAllEdgesS(const double& DefVal, const bool& IsEqualComms){ + if (SumPrPsblEdgesPow_nVV.Len()==0) { + SumPrPsblEdgesPow_nVV.Gen(NumCIdNV.Len(), 0.0); + } else { + SumPrPsblEdgesPow_nVV.Clr(); + SumPrPsblEdgesPow_nVV.Gen(NumCIdNV.Len(), 0.0); + } + TFlt SToN = 1.0; + for (int c=0; c=1) + TFltV PsiV; + PsiV.Add(1.0); + SToN = 1.0; + for (int n=1; (n <= MinTayN && PsiV[n-1] > 0.0) || (n<=TayN && PsiV[n-1]>TayThresh) ; n++){ //n: Taylor coefficient order + SToN *= DefVal; + PsiV.Add(pow(SToN+1.0, NumCIdNV[c]) - 1); + } + SumPrPsblEdgesPow_nVV.Add(PsiV); + if (IsEqualComms && NumCIdNV.Len()>1) { + for (int c=1; c 0.0) || + (n <= TayN && PsiV[n-1]>TayThresh); n++){ + if (n >= PsiV.Len()) { + PsiV.Add(0.0); + } + SToNOld *= SNOld; SToNNew *= SNNew; + PsiV[n] = ((SToNNew+1.0)/(SToNOld+1.0)) * + (SumPrPsblEdgesPow_nVV[CID][n]-SToNOld) + SToNNew; + nLast = n; + } + if (IsApplyChange) { + for (int n = 1; n <= nLast; n++) { + if (n >= SumPrPsblEdgesPow_nVV[CID].Len()) { + SumPrPsblEdgesPow_nVV[CID].Add(-1.0); + } + SumPrPsblEdgesPow_nVV[CID][n] = PsiV[n]; + } + nLast++; + while (nLast < SumPrPsblEdgesPow_nVV[CID].Len()) { + SumPrPsblEdgesPow_nVV[CID][nLast] = 0.0; + nLast++; + } + } +} + +double THysgen::PredictAllCEdgesS(const int &UID, const int &CID, + const bool IsLikelihood, const bool Verbose){ + double SCoef = 1.0; + double LikCoef = 1.0; + double S_uc = GetNCom(UID,CID); + double SPowN = 1.0; + if (!IsLikelihood){ + if (S_uc <= 0.0) { return SumPrPsblEdgesPow_nVV[CID][1]; } + else { SCoef = 1.0/S_uc; } + } + if (S_uc<=0.0 && IsLikelihood) { return 0.0; } + double Val = 0.0; + double Val_n; + if (Verbose) { + printf("### PredictAllCEdgesS for node %d and comm %d :\n", UID, CID); + } + for (int n=1; nTayThresh; n++){ + if (IsLikelihood) { LikCoef = -n; } + SPowN *= S_uc; + Val_n = SCoef * (SPowN/(1+SPowN)) * (SumPrPsblEdgesPow_nVV[CID][n] - SPowN) / LikCoef; + Val += Val_n; + if(Verbose){ + printf("\t --- (n=%d): %f\n", n , Val_n); + } + } + return Val; +} + +double THysgen::PredictAllCEdgesS(const int &UID, const int &CID, const double& SNNew, + const bool IsLikelihood, const bool Verbose){ + IAssertR(IsLikelihood,"This Overload of function is only designed for computing the likelihood, not gradient!\n"); + double SCoef = 1.0; + double LikCoef; + double SPowN = 1.0; + if (SNNew <= 0.0) { return 0.0; } // Just for easier computation and clearer presentation of the logic in code. + double Val = 0.0; + double Val_n; + if (Verbose) { + printf("### PredictAllCEdgesS for node %d and comm %d :\n", UID, CID); + } + TFltV PsiV(SumPrPsblEdgesPow_nVV[CID].Len()); + UpdatePrAllEdgesS(PsiV, UID, CID, SNNew, false); + for (int n=1; nTayThresh; n++){ // n=0 is voided in the formulation + LikCoef = -n; + SPowN *= SNNew; + Val_n = SCoef * (SPowN/(1.0+SPowN)) * (PsiV[n] - SPowN) / LikCoef; + Val += Val_n; + if(Verbose){ + printf("\t --- (n=%d): %f\n", n , Val_n); + } + } + return Val; +} + +double THysgen::PredictAllCEdgesS_direct(const int &UID, const int &CID, + const bool IsLikelihood, const bool Verbose) { + double Psi_c = 0.0; + double S_uc = GetNCom(UID,CID); + if (S_uc <= 0.0 && IsLikelihood) { return 0.0; } + TIntV CNodesV(S.Len(),0); + for (int nod=0; nod < S.Len(); nod++) { + if (GetNCom(nod, CID) > 0.0 || nod==UID) {CNodesV.Add(nod);} + } + TInt NPsbEdges = pow(2, CNodesV.Len()); + for (int e=0; eGetEI(EId).Len()); + if (PrECNew>=0.0 && ProbNotEdgH.IsKey(EId) && ProbNotEdgH.GetDat(EId)()==-1.0) { + TIntFltH& ProdH = ProbEdgCommHH.GetDat(EId); // ProbEdgCommHH already updated from previous steps. + ProbEdgH.AddDat(EId, GetPrEPrecision(ProdH, AuxDPEdgVV, PrENoise)); + if (1.0 - ProbEdgH.GetDat(EId) < 1.0) { // if PrE large enough + ProbNotEdgH.AddDat(EId, 1.0 - ProbEdgH.GetDat(EId)); + } + return; + } + double PrNotE; + if (PrECOld < 1.0){ + PrNotE = ProbNotEdgH.GetDat(EId) * (1.0 - PrECNew) / (1.0 - PrECOld); + } else { + PrNotE = 1.0 - PrENoise; + for (TIntFltH::TIter HI = ProbEdgCommHH.GetDat(EId).BegI(); + HI < ProbEdgCommHH.GetDat(EId).EndI(); HI++) { + PrNotE *= 1.0 - HI.GetDat(); + } + } + ProbNotEdgH.AddDat(EId, PrNotE); + ProbEdgH.AddDat(EId, 1-PrNotE); + if (PrNotE >= 1.0) { + TIntFltH& ProdH = ProbEdgCommHH.GetDat(EId); + ProbEdgH.AddDat(EId, GetPrEPrecision(ProdH, AuxDPEdgVV, PrENoise)); + ProbNotEdgH.AddDat(EId,-1.0); + } +} + +double THysgen::DotProduct(const TIntFltH& UV, const TIntFltH& VV) { + double DP = 0.0; + for (TIntFltH::TIter HI = VV.BegI(); HI < VV.EndI(); HI++) { + if (UV.IsKey(HI.GetKey())) { + DP += UV.GetDat(HI.GetKey()) * HI.GetDat(); + } + } + return DP; +} + +void THysgen::SetCmtyVV(const TVec& CmtyVV) { + S.Gen(G->GetNodes()); + NumCIdNV.Gen(CmtyVV.Len()); + NumComs = CmtyVV.Len(); + for (int c = 0; c < CmtyVV.Len(); c++) { + for (int u = 0; u < CmtyVV[c].Len(); u++) { + int UID = CmtyVV[c][u]; + if (! NIdToIdx.IsKey(UID)) { continue; } + AddNCom(NIdToIdx.GetKeyId(UID), c, 1.0); + } + } +} + +double THysgen::Likelihood() { + TExeTm ExeTm; + double L = 0.0; + for (int u = 0; u < S.Len(); u++) { + double LU = LikelihoodForRow(u); + L += LU; + } + return L ; +} + +double THysgen::LikelihoodForRow(const int UID) { + return LikelihoodForRow(UID, S[UID]); +} +double THysgen::LikelihoodForRow(const int UID, const TIntFltH &SU) { + bool IsSUpdated = false; + if (S[UID].Len() != SU.Len()) { + IsSUpdated = true; + } else { + for (int CID = 0; CID < NumComs; CID++){ + if (!S[UID].IsKey(CID) && !SU.IsKey(CID)) {continue;} + if ( (S[UID].IsKey(CID) && !SU.IsKey(CID)) || + (!S[UID].IsKey(CID) && SU.IsKey(CID)) || + abs(S[UID].GetDat(CID) - SU.GetDat(CID)) > DBL_MIN ) { + IsSUpdated = true; + break; + } + } + } + double L = 0.0; + const bool IsLikelihood = true; + THGraph::TNodeI NI = G->GetNI(UID); + TIntV EIdV; + NI.GetEIDs(EIdV); + TFlt SumLgPrNotUEdges = 0.0; // For the NOT side, Noise source has no effect, not included. + for (int e = 0; e < NI.GetDeg(); e++) { + int EId = EIdV[e]; + TIntFltH PrENewCH; + if (HONNIdsV[UID].IsKey(EId)) { continue; } +// if (IsSUpdated){ + L += log(GetPrE(EId, UID, SU, PrENewCH)); + for (TIntFltH::TIter PrECI = PrENewCH.BegI(); PrECI < PrENewCH.EndI(); PrECI++){ + SumLgPrNotUEdges += log(1.0 - PrECI.GetDat()); + } +// } else { /////// For faster but less accurate computations uncomment +// L += log(GetPrE(EId)); +// for (TIntFltH::TIter UCI = SU.BegI(); UCI < SU.EndI(); UCI++){ +// SumLgPrNotUEdges += log(1.0 - GetECom(EId, UCI.GetKey())); +// } +// } + } + TFlt SumAllPsbl = 0.0; + for (TIntFltH::TIter UCI = SU.BegI(); UCI < SU.EndI(); UCI++) { + if (IsSUpdated) { + SumAllPsbl += PredictAllCEdgesS(UID, UCI.GetKey(), UCI.GetDat(), IsLikelihood); + } else { + SumAllPsbl += PredictAllCEdgesS(UID, UCI.GetKey(), IsLikelihood); + } + } + L += NegWgt * (SumAllPsbl - SumLgPrNotUEdges); + // Add L1 regularization + if (RegCoef > 0.0) { + L -= RegCoef * Sum(SU); + } + return L; +} + +void THysgen::GradientForRow(const int UId, TIntFltH &GradNod) { + GradNod.Gen(GetNumComs()); + THGraph::TNodeI NI = G->GetNI(UId); + int NDeg = NI.GetDeg(); + TIntV EIdV; + NI.GetEIDs(EIdV); + TIntFltH PredEH(NDeg); + TFltV PredECMinusUV(GetNumComs()); + TFltV GradV(GetNumComs()); + TIntV CIDV(GetNumComs()); + TIntV NIdV; + TInt NId; + TInt EId; + for (int e = 0; e < NDeg; e++) { + EId = EIdV[e]; + if (HONEIdsV[UId].IsKey(EId)) { continue; } + PredEH.AddDat(EId, GetPrE(EId)); + } + for (int CId = 0; CId < NumComs; CId++) { + double Val = 0.0; + for (int e = 0; e < NDeg; e++) { + EId = EIdV[e]; + if (HONEIdsV[UId].IsKey(EId)) { continue; } + if (GetNCom(UId, CId) > 0.0) { + PredECMinusUV[CId] = + GetECom(EId, CId) / GetNCom(UId, CId); + } else { + PredECMinusUV[CId] = 1.0; + G->GetEI(EId).GetNodesV(NIdV); + for (int m = 0; m < NIdV.Len(); m++) { + NId = NIdV[m]; + if (NId != UId) { PredECMinusUV[CId] *= GetNCom(NId, CId); } + } + } + double PrENoise = GetENoiseProb(G->GetEI(EId).Len()); + if (GetECom(EId, CId) >= 1.0 || (1.0 - GetECom(EId, CId) <= 0.0)) { + double PredENotCId = 1.0 - PrENoise; + for (int c2 = 0; c2 < NumComs; c2++) { + if (c2 == CId) { continue; } + PredENotCId *= 1.0 - GetECom(EId, c2); + } + Val += PredECMinusUV[CId] * PredENotCId / PredEH.GetDat(EId); + } + else { + double PrNotENotC = (1.0 - PredEH.GetDat(EId)) / (1.0 - GetECom(EId, CId)); + Val += + PredECMinusUV[CId] * PrNotENotC / PredEH.GetDat(EId); + } + Val += NegWgt * (PredECMinusUV[CId] / + (1.0 - GetECom(EId, CId))); + } + Val -= NegWgt * PredictAllCEdgesS(UId, CId, false); + CIDV[CId] = CId; + GradV[CId] = Val; + } + for (int c = 0; c < GradV.Len(); c++) { + GradNod.AddDat(CIDV[c], GradV[CIDV[c]]); + } +} + +void THysgen::GetCmtyVV(TVec& CmtyVH, TVec& CmtyVV, TVec& WckVV, + const double Thres, const int MinSz) { + CmtyVH.Gen(NumComs, 0.0); + CmtyVV.Gen(NumComs, 0.0); + for (int CId = 0; CId < NumComs; CId++) { + TIntFltH NIDSucH(S.Len()); + TIntV CmtyV; + for (int u = 0; u < S.Len(); u++) { + int NID = NIdToIdx[u]; + if (GetNCom(u, CId) > Thres) { + NIDSucH.AddDat(NID, GetNCom(u, CId)); + } + } + NIDSucH.SortByDat(false); + NIDSucH.GetKeyV(CmtyV); + if (CmtyV.Len() < MinSz) { continue; } + CmtyVH.Add(NIDSucH); + CmtyVV.Add(CmtyV); + } + if ( NumComs != CmtyVV.Len()) { + printf("Unsorted Community vector generated. %d communities are ommitted\n", + NumComs.Val - CmtyVV.Len()); + } +} + +void THysgen::GetCmtyVVUnSorted(TVec& CmtyVV) { + GetCmtyVVUnSorted(CmtyVV, sqrt(2.0 * (double) G->GetEdges() / G->GetNodes() / G->GetNodes()), 3); +} + +void THysgen::GetCmtyVVUnSorted(TVec& CmtyVV, const double Thres, const int MinSz) { + CmtyVV.Gen(NumComs, 0.0); + for (int c = 0; c < NumComs; c++) { + TIntV CmtyV; + for (int u = 0; u < G->GetNodes(); u++) { + if (GetNCom(u, c) > Thres) { CmtyV.Add(NIdToIdx[u]); } + } + if (CmtyV.Len() >= MinSz) { CmtyVV.Add(CmtyV); } + } + if ( NumComs != CmtyVV.Len()) { + printf("*Sorted* Community vector generated. %d communities are ommitted\n", + NumComs.Val - CmtyVV.Len()); + } +} + +/// Armijo–Goldstein backtracking line search +double THysgen::GetStepSizeByLineSearch(const int UID, const TIntFltH &DeltaH, + const double &stepSize, + const double &CtrlParam, + const double &ReductionRatio, + const int MaxIter) { + double StepSize = stepSize; + double NewVal; + bool ShouldReduce = true; + while (ShouldReduce) { + ShouldReduce = false; + for (TIntFltH::TIter CI = DeltaH.BegI(); CI < DeltaH.EndI(); CI++) { + int CID = CI.GetKey(); + NewVal = GetNCom(UID, CID) + StepSize * CI.GetDat(); + if ((NewVal < MinVal || NewVal > MaxVal)) { + StepSize *= ReductionRatio; + ShouldReduce = true; + break; + } + } + } + double InitLikelihood = LikelihoodForRow(UID); + double FinalLikelihood = 0.0; + // double ChangeVal; + TIntFltH SearchVecH; + for(int iter = 0; iter < MaxIter; iter++) { + TIntFltH NewVarH; + GetUpdatedNodP(NewVarH, SearchVecH, UID, DeltaH, StepSize); + FinalLikelihood = LikelihoodForRow(UID, NewVarH); + double DotProd = DotProduct(SearchVecH, SearchVecH); + if (FinalLikelihood < InitLikelihood + CtrlParam * StepSize * DotProd || + isinf(FinalLikelihood)) { + // ***** True Armijo Rule: + StepSize *= ReductionRatio; + } else { + break; + } + if (iter == MaxIter - 1 || DotProd < 0.00001) { + StepSize = 0.0; + break; + } + } + return StepSize; +} + +int THysgen::MLEGradAscent(const double& Thres, const int& MaxIter, const TStr PlotNm, + const double StepSize, const double StepCtrlParam, const double StepReductionRatio) { + int NegLikPermits = MaxIter/3; + int MaxIterLineSearch = 100; + time_t InitTime = time(NULL); + time_t InitIterTime; + TExeTm ExeTm, CheckTm; + int iter = 0; + TIntFltPrV IterLV; + THGraph::TNodeI UI; + double PrevL = Likelihood(), CurL = 0.0, DiffL; + printf("\n0 iterations (iter/#nodes = 0) {[INITIAL] Likelihood: %.4e}\n",PrevL); + TIntV NIdxV(S.Len(), 0); + for (int i = 0; i < S.Len(); i++) { NIdxV.Add(i); } + TIntFltH GradUH; + TFltV Last5; + double SumLast5 = 0; + while(iter < MaxIter) { + InitIterTime = time(NULL); + NIdxV.Shuffle(Rnd); + for (int ui = 0; ui < S.Len(); ui++, iter++) { + int u = NIdxV[ui]; + GradientForRow(u, GradUH); + if (Norm2(GradUH) < 1e-4) { continue; } + TIntFltH GradAdjustedH; + TIntFltH SearchVecH; + NormalizeIfLarge(GradUH, GradAdjustedH); + bool IsAnyValidChange = RmvWeakDirections(u, GradAdjustedH); + if (! IsAnyValidChange) { continue; } + double LearnRate = GetStepSizeByLineSearch(u, GradAdjustedH, StepSize, + StepCtrlParam, + StepReductionRatio, + MaxIterLineSearch); + if (LearnRate <= DBL_MIN) { continue; } + TIntFltH SNew; + GetUpdatedNodP(SNew, u, GradAdjustedH, LearnRate); + double NewSuc; + for (int CID = 0; CID < NumComs; CID++) { + if (! SNew.IsKey(CID)) { + NewSuc = 0.0; + } else { + NewSuc = SNew.GetDat(CID); + } + if (NewSuc < DBL_EPSILON) { + DelNCom(u, CID); + } else { + AddNCom(u, CID, NewSuc); + } + } + if (! PlotNm.Empty() && (iter + 1) % G->GetNodes() == 0) { + IterLV.Add(TIntFltPr(iter, Likelihood())); + } + } + CurL = Likelihood(); + DiffL = CurL - PrevL; + PrevL = CurL; + double AdjDiffL = (abs(DiffL) < 1000.0) ? abs(DiffL) : 1000.0; + Last5.Add(AdjDiffL); + SumLast5 += AdjDiffL; + if (Last5.Len() > 5) { + SumLast5 -= Last5[0]; + Last5.Del(0); + } + if (fabs(CurL) < 1e9) { + if (fabs(DiffL) < 1e9) { + printf("\r%d iterations (iter/#nodes = %d) {Likelihood: %.4f, Diff: %.4f} [%lu/%lu sec]\n", + iter, iter/G->GetNodes(), CurL, DiffL, time(NULL) - InitIterTime, time(NULL) - InitTime); + } else { + printf("\r%d iterations (iter/#nodes = %d) {Likelihood: %.4f, Diff: %.4e} [%lu/%lu sec]\n", + iter, iter/G->GetNodes(), CurL, DiffL, time(NULL) - InitIterTime, time(NULL) - InitTime); + } + } else { + if (fabs(DiffL) < 1e9) { + printf("\r%d iterations (iter/#nodes = %d) {Likelihood: %.4e, Diff: %.4f} [%lu/%lu sec]\n", + iter, iter/G->GetNodes(), CurL, DiffL, time(NULL) - InitIterTime, time(NULL) - InitTime); + } else { + printf("\r%d iterations (iter/#nodes = %d) {Likelihood: %.4e, Diff: %.4e} [%lu/%lu sec]\n", + iter, iter/G->GetNodes(), CurL, DiffL, time(NULL) - InitIterTime, time(NULL) - InitTime); + } + } + printf("\n"); + fflush(stdout); + if (DiffL < 0.0) { // If the likelihood goes negative several times, then we are actually converged, so stop! + if (NegLikPermits <= 0) { break; } + NegLikPermits --; + } + if (SumLast5/Last5.Len() <= Thres) { + printf("The average of last five differences < threshold. Iterations end...\n"); + break; + } + } + printf("\n"); + printf("MLE for Lambda completed with %d iterations(%s)\n", iter, ExeTm.GetTmStr()); + if (! PlotNm.Empty()) { + TGnuPlot::PlotValV(IterLV, PlotNm + ".likelihood_Q"); + } + return iter; +} + +double THysgen::GetPrE(const int &EId, const int &UId, const TIntFltH &SUNewH, + TIntFltH &PrEOutCH) { + double PrENoise = GetENoiseProb(G->GetEI(EId).Len()); + double SUOld; + double SUNew; + double PrECOld; + double PrENew = 1.0 - PrENoise; + int SCId; + for (TIntFltH::TIter SCI = SUNewH.BegI(); SCI < SUNewH.EndI(); SCI++) { + SCId = SCI.GetKey(); + SUNew = SCI.GetDat(); + SUOld = GetNCom(UId, SCId); + if (SUOld < DBL_EPSILON) { + TIntV ENodesV; + G->GetEI(EId).GetNbrNodes(ENodesV); + double PrEC = SUNew; + for (int n = 0; n < ENodesV.Len(); n++) { + if (ENodesV[n] == UId) { continue; } + PrEC *= GetNCom(ENodesV[n], SCId); + } + PrEOutCH.AddDat(SCId, PrEC); + } else { + PrECOld = GetECom(EId, SCId); + PrEOutCH.AddDat(SCId, PrECOld * SUNew / SUOld); + } + PrENew *= 1.0 - PrEOutCH.GetDat(SCId); + } + if (PrENew < 1.0) { PrENew = 1.0 - PrENew; } + else { + PrENew = GetPrEPrecision(PrEOutCH, AuxDPEdgVV, PrENoise); + } + return PrENew; +} + +double THysgen::GetPrEPrecision(const TIntFltH &ECH, TVec &DPMatVV, + const double PrENoise) { + int NumEC = ECH.Len(); + TFltV ECV(NumEC); + ECH.GetDatV(ECV); + if (PrENoise > 0.0) { ECV.Add(PrENoise); NumEC++; } + /// Only the diagonal entries need to be reset + for (int i=1; i= 0; j--) { + DPMatVV[0][j] = DPMatVV[0][j + 1] + ECV[j]; + } + for (int i=1; i=0; j--) { + DPMatVV[i][j] = ECV[j] * DPMatVV[i-1][j+1] + DPMatVV[i][j+1]; + } + } + double prob = 0.0; + double SignCoef = 1.0; + for (int i=0; i1) { + prob = DBL_MIN; + } + return prob; +} + +void THysgen::GetUpdatedNodP(TIntFltH &SNew, const int &UID, const TIntFltH& GradUH, + double &StepSize) { + TIntFltH SearchVecOut; + GetUpdatedNodP(SNew, SearchVecOut, UID, GradUH, StepSize); +} + +void THysgen::GetUpdatedNodP(TIntFltH &SNew, TIntFltH& SearchVecOut, const int& UID, + const TIntFltH& GradUH, double& StepSize) { + for (int CID = 0; CID < NumComs; CID++) { + if (GradUH.IsKey(CID)) { + double Change = StepSize * GradUH.GetDat(CID); + /// Add L1 regularization + if (RegCoef>0.0 && GetNCom(UID, CID)>0.0) { + Change -= - RegCoef; + } + double NewSuc = GetNCom(UID, CID) + Change; + if (NewSuc < DBL_EPSILON) { + NewSuc = MinVal; + } else if (NewSuc >= MaxVal - TayThresh) { + NewSuc = MaxVal - TayThresh; + } + Change = NewSuc - GetNCom(UID, CID); + if (NewSuc >= DBL_EPSILON) { + SNew.AddDat(CID, NewSuc); + } + SearchVecOut.AddDat(CID, Change); + } else { + if (GetNCom(UID, CID) > 0.0) { + double NewSuc; + if (GetNCom(UID, CID) >= MaxVal - TayThresh) { + NewSuc = MaxVal - TayThresh; + } else { + NewSuc = GetNCom(UID, CID); + } + SNew.AddDat(CID, NewSuc); + } + } + } +} + +bool THysgen::AcceptStepSA(const int &UID, const TIntFltH &SNew, const int &Iter, + const int &MaxIter, const double &SAParamK) { + double T0 = 100.0; + double T = T0/((double)Iter+1.0); + double OldLikelihood = LikelihoodForRow(UID); + double NewLikelihood = LikelihoodForRow(UID, SNew); + double DeltaE = - (NewLikelihood-OldLikelihood); + double PrAccept = exp(-DeltaE/(SAParamK*T)); + if (Rnd.GetUniDev() < PrAccept) { return true; } + return false; +} + +bool THysgen::RmvWeakDirections(const int &UId, TIntFltH &GradH) { + bool IsEligible = false; + THashSet BadDirH; + for (TIntFltH::TIter CI = GradH.BegI(); CI < GradH.EndI(); CI++) { + if ((GetNCom(UId, CI.GetKey()) < DBL_EPSILON && CI.GetDat() < DBL_EPSILON) || + (1.0 - GetNCom(UId, CI.GetKey()) < DBL_EPSILON && CI.GetDat() > DBL_EPSILON)) { + BadDirH.AddKey(CI.GetKey()); + } else { + IsEligible = true; + } + } + if (BadDirH.Len() > 0) { + for (THashSet::TIter CId = BadDirH.BegI(); + CId < BadDirH.EndI(); CId++) { + GradH.DelKey(CId.GetKey()); + } + } + return IsEligible; +} + diff --git a/snap-adv/hysgen.h b/snap-adv/hysgen.h new file mode 100644 index 000000000..fd7a61c4e --- /dev/null +++ b/snap-adv/hysgen.h @@ -0,0 +1,385 @@ +#ifndef Pedrood_CmntyHyper_h +#define Pedrood_CmntyHyper_h +#include +#include "Snap.h" +#include +#include + + +class THysgenUtil { +public: + enum Criteria {Alphabetical, Value}; + static void DumpCmtyVV(const TStr OutFNm, TVec& CmtyVV, TIntStrH& NIDNmH); + static void DumpCmtyVH(const TStr OutFNm, TVec& CmtyVH, + TIntStrH& NIDNmH, Criteria Crit=Value); + static PHGraph LoadEdgeList(const TStr& InFNm, TStrHash& NodeNameH, + const TSsFmt SsFmt = ssfTabSep); + + template + static double GetConductance(const PHGraph& Graph, const TIntSet& CmtyS, const int N2Edges); + + template + static void GetNbhCom(const PHGraph& Graph, const int NID, TIntSet& NBCmtyS); + + template + static void GetPhiNIdPrV(const PHGraph &G, TFltIntPrV &PhiNIdPrV, const int MinComSiz); + + static void GetBinLocs(const int& DecNum, TIntV& LocsV, const TIntV& NodMapV); + + static double Min(double N1, double N2) { + return (N1 < N2) ? N1 : N2; + } + static bool IsEqual(const double Num1, const double Num2) { + return abs(Num1 - Num2) < TFlt::Eps; + } +}; + +class THysgen { +private: + PHGraph G; ///< The graph to fit + TVec S; ///< Membership of node \c NId to each of the communities + ///< Product of the membership of all the nodes in edge \c EId to community \c CId + ///< value saved for efficient calculation. + THash ProbEdgCommHH; + ///< Prob that no community generates Edge \c EId. Used for efficient calculation. + THash ProbNotEdgH; + ///< Prob that SOME community generates Edge \c EId. + ///< Used to compensate when numerical precision of the "double" datatype + ///< is not sufficient for error-free computation of ProbNotEdgH. + THash ProbEdgH; + ///< Auxiliary Matrix of (C+1, C+1) to help in the proposed DP to compute the Edge probability + TVec AuxDPEdgVV; + TFltV ProbENoiseV; ///< Prob that an edge \c EId is generated by noise (leak) + TRnd Rnd; ///< Random number generator + TIntSet NIdToIdx; + TInt NumComs; ///< The total number of communities + TIntV NumCIdNV; ///< Number of nodes (members) in each community + TIntSet HOEIDS; //Set of edges to hold out for cross validation + TVec HONEIdsV; ///< For each node, this keeps the ID of neighboring hold out Edges + TVec HONNIdsV; ///< For each node, this keeps the ID of Nodes in the neighboring hold out Edges + TVec HOKIDSV; ///< set of attribute index (k) to hold out + TInt MinTayN; ///< Minimum Number of terms in Taylor expansion that we like to expand. + TInt TayN; ///< MAXIMUM Number of terms in Taylor expansion that we like to expand. + TFlt TayThresh; ///< Minimum value that a term (n) in Taylor expansion must have to be stored. + TVec SumPrPsblEdgesPow_nVV; + TFlt SNoise; + TFlt ThreshLearnRate; +public: + TFlt InitVal; ///< default value of S for community initialization + TFlt InitNullS; ///< Default membership value for all the nodes to the noise community + TFlt MinVal; ///< minimum value of S + TFlt MaxVal; ///< maximum value of S (for numerical reasons) + TFlt NegWgt; + TFlt RegCoef; ///< L1 regularization coefficient + TFlt PrNoCom; +private: + void GetUpdatedNodP(TIntFltH &SNew, const int &UID, const TIntFltH& GradUH, + double &StepSize); + void GetUpdatedNodP(TIntFltH &SNew, TIntFltH& SearchVecOut, const int& UID, + const TIntFltH& GradUH, double& StepSize); + bool AcceptStepSA(const int &UID, const TIntFltH &SNew, const int &Iter, + const int &MaxIter, const double &SAParamK); + bool RmvWeakDirections(const int &UId, TIntFltH &GradH); + void InitEdgeProb(); + void UpdateUEdgesProb(const int& UId, const int& CId, const double& SUNew); + void InitPrAllEdgesS(const double& DefVal, const bool& IsEqualComms=false); + void UpdatePrAllEdgesS(const int &UID, const int &CID, const double& SNNew); + void UpdatePrAllEdgesS(TFltV &PsiV, const int &UID, const int &CID, + const double& SNNew, const bool IsApplyChange); + void UpdatePrAllEdgesS(const int &UID, const int &CID, const TFltV& SNodNewV){ + UpdatePrAllEdgesS(UID, CID, SNodNewV[CID]); + } + double PredictAllCEdgesS_direct(const int &UID, const int &CID, + const bool IsLikelihood = false, const bool Verbose= false); + double PredictAllCEdgesS(const int &UID, const int &CID, + const bool IsLikelihood = false, const bool Verbose=false); + double PredictAllCEdgesS(const int &UID, const int &CID, const double& SNNew, + const bool IsLikelihood = true, const bool Verbose=false); + void UpdateProbNotEdgH(const int &EId, const double &PrECNew, + const double &PrECOld); + + +public: + explicit THysgen(const PHGraph &GraphPt, const int RndSeed = 0, + const double InitCVal = 0.1, const double InitNulS = 0.03, + const double NoiseConstS = 0.01) : + Rnd(RndSeed), MinTayN(10), TayN(50), TayThresh(0.00001), + SNoise(NoiseConstS), InitVal(InitCVal), InitNullS(InitNulS), + MinVal(0.0), MaxVal(1.0), NegWgt(1.0), RegCoef(0.0) { + SNoise = (InitNulS>0.0) ? THysgenUtil::Min(NoiseConstS, InitNulS / 2.0) : NoiseConstS; + ThreshLearnRate = TayThresh / GraphPt->GetNodes(); + SetGraph(GraphPt); + } + void Save(TSOut& SOut) { + G->Save(SOut); + S.Save(SOut); + ProbEdgCommHH.Save(SOut); + ProbNotEdgH.Save(SOut); + ProbEdgH.Save(SOut); + AuxDPEdgVV.Save(SOut); + ProbENoiseV.Save(SOut); + NIdToIdx.Save(SOut); + RegCoef.Save(SOut); + NumComs.Save(SOut); + NumCIdNV.Save(SOut); + HONEIdsV.Save(SOut); + HONNIdsV.Save(SOut); + HOKIDSV.Save(SOut); + TayN.Save(SOut); + MinTayN.Save(SOut); + TayThresh.Save(SOut); + SumPrPsblEdgesPow_nVV.Save(SOut); + InitVal.Save(SOut); + MinVal.Save(SOut); + MaxVal.Save(SOut); + NegWgt.Save(SOut); + PrNoCom.Save(SOut); + InitNullS.Save(SOut); + } + void Load(TSIn& SIn, const int& RndSeed = 0) { + G->Load(SIn); + S.Load(SIn); + ProbEdgCommHH.Load(SIn); + ProbNotEdgH.Load(SIn); + ProbEdgH.Load(SIn); + AuxDPEdgVV.Load(SIn); + ProbENoiseV.Load(SIn); + NIdToIdx.Load(SIn); + RegCoef.Load(SIn); + NumComs.Load(SIn); + NumCIdNV.Load(SIn); + HONEIdsV.Load(SIn); + HONNIdsV.Load(SIn); + HOKIDSV.Load(SIn); + TayN.Load(SIn); + MinTayN.Load(SIn); + TayThresh.Load(SIn); + SumPrPsblEdgesPow_nVV.Load(SIn); + InitVal.Load(SIn); + MinVal.Load(SIn); + MaxVal.Load(SIn); + NegWgt.Load(SIn); + PrNoCom.Load(SIn); + InitNullS.Load(SIn); + } + + void SetGraph(const PHGraph& GraphPt); + void SetRegCoef(const double _RegCoef) { RegCoef = _RegCoef; } + double GetRegCoef() { return RegCoef; } + void LoadComInit(const TStr& InFNm, TSsFmt SsFmt=ssfTabSep); + void ComInit(const int InitComs, const int MinComSiz=5, const double PerturbDens=0.0); + void UniformComInit(const int InitComs); + void RandomComPerturb(double Density = 1.0); + /// Initialize with the neighborhood communities (Gleich et.al. KDD'12) + void NeighborComInit(const int MinComSiz, const bool& IsInit = false); + void NeighborComInit(TFltIntPrV& PhiNIdPrV, const bool& IsInit = false); + TInt GetNumComs() { return NumComs; } + void SetCmtyVV(const TVec& CmtyVV); + double Likelihood(); + double LikelihoodForRow(const int UID); + double LikelihoodForRow(const int UID, const TIntFltH &SU); + void GradientForRow(const int UId, TIntFltH &GradNod); + + /// Dump community affiliation into a text file with node names + void GetCmtyVV(TVec& CmtyVH, TVec& CmtyVV, TVec& WckVV, + const double Thres, const int MinSz = 3); + void GetCmtyVV(TVec& CmtyVH, TVec& CmtyVV, TVec& WckVV, + const int MinSz = 3) { + printf("\n+-+-+-+- Threshold = %f -+-+-+-+\n", + sqrt(2.0 * (double) G->GetEdges() / G->GetNodes() / G->GetNodes())); + GetCmtyVV(CmtyVH, CmtyVV, WckVV, + sqrt(2.0 * (double) G->GetEdges() / G->GetNodes() / G->GetNodes()), MinSz); + } + void GetCmtyVV(TVec& CmtyVH, TVec& CmtyVV, + const double Thres, const int MinSz = 3) { + TVec TmpV; + GetCmtyVV(CmtyVH, CmtyVV, TmpV, Thres, MinSz); + } + void GetCmtyVV(TVec& CmtyVH, TVec& CmtyVV) { + TVec TmpVV; + GetCmtyVV(CmtyVH, CmtyVV, TmpVV, + sqrt(2.0 * (double) G->GetEdges() / G->GetNodes() / G->GetNodes()), 3); + } + void GetCmtyVVUnSorted(TVec& CmtyVV); + void GetCmtyVVUnSorted(TVec& CmtyVV, const double Thres, const int MinSz = 3); + + double GetStepSizeByLineSearch(const int UID, const TIntFltH &DeltaH, + const double &stepSize, + const double &CtrlParam, + const double &ReductionRatio, + const int MaxIter); + + int MLEGradAscent(const double& Thres, const int& MaxIter, const TStr PlotNm, + const double StepSize = 0.3, const double StepCtrlParam = 0.3, + const double StepReductionRatio = 0.3); + + void inline GetNCom(TIntFltH& NIdH, const int& NID) { + NIdH = S[NID]; + } + double inline GetNCom(const int& NID, const int& CID) { + if (S[NID].IsKey(CID)) { + return S[NID].GetDat(CID); + } else { + return 0.0; + } + } + + void inline DelNCom(const int &UID, const int &CID) { + if (S[UID].IsKey(CID)) { + UpdatePrAllEdgesS(UID, CID, 0.0); + UpdateUEdgesProb(UID, CID, 0.0); + S[UID].DelKey(CID); + NumCIdNV[CID] --; + } + } + + void inline AddNCom(const TIntV& NIdV, const int& CID, const double& Val, const bool& IsInit = false) { + for (int ui = 0; ui < NIdV.Len(); ui++){ + AddNCom(NIdV[ui], CID, Val, IsInit); + } + } + void inline AddNCom(const int& UId, const int& CID, const double& Val, const bool& IsInit = false) { + if (Val < DBL_EPSILON) { + DelNCom(UId, CID); + return; + } + if (!IsInit){ + UpdatePrAllEdgesS(UId, CID, Val); + UpdateUEdgesProb(UId, CID, Val); + } + if (S[UId].IsKey(CID)) { + NumCIdNV[CID] --; + } + S[UId].AddDat(CID, Val); + NumCIdNV[CID] ++; + } + + double inline GetPrE(const int &EId) { + if (THysgenUtil::IsEqual(ProbNotEdgH.GetDat(EId)(), -1.0)) { + return ProbEdgH.GetDat(EId)(); + } + return 1.0 - ProbNotEdgH.GetDat(EId); + } + /// Computes Prob(EId) when SUNewH is different from S[UId]. + /// @param PrEOutCH is an output vector of \prod_{v \in e} S_vc for each c + double GetPrE(const int &EId, const int &UId, const TIntFltH &SUNewH, + TIntFltH &PrEOutCH); + + static double GetPrEPrecision(const TIntFltH &ECH, TVec &DPMatVV, + const double PrENoise); + + double inline GetENoiseProb(const int Size) { + if (Size > ProbENoiseV.Len()) { AddENoiseProb(Size); } + return ProbENoiseV[Size]; + } + + void inline AddENoiseProb(const int Size) { + for (int i = ProbENoiseV.Len(); i <= Size; i++) { + ProbENoiseV[i] = ProbENoiseV[i-1] * SNoise; + } + } + + template + double inline GetECom(const TInt1 &EId, const TInt2 &CId) { + if (ProbEdgCommHH.IsKey(EId) && ProbEdgCommHH.GetDat(EId).IsKey(CId)) { + return ProbEdgCommHH.GetDat(EId).GetDat(CId); + } + else { + return 0.0; + } + } + + void inline AddECom(const int& EId, const TIntFltH& ProdH) { + double PrENoise = GetENoiseProb(G->GetEI(EId).Len()); + double PrNotE = 1.0 - PrENoise; + if (ProdH.Len() != 0) { + ProbEdgCommHH.AddDat(EId, ProdH); + for (TIntFltH::TIter HI = ProdH.BegI(); HI < ProdH.EndI(); HI++) { + PrNotE *= 1.0 - HI.GetDat(); + } + } else { + if (ProbEdgCommHH.IsKey(EId)) { + ProbEdgCommHH.DelKey(EId); + } + } + if (PrNotE >= 1.0) { + ProbEdgH.AddDat(EId, GetPrEPrecision(ProdH, AuxDPEdgVV, PrENoise)); + ProbNotEdgH.AddDat(EId,-1.0); + return; + } + ProbNotEdgH.AddDat(EId,PrNotE); + ProbEdgH.AddDat(EId,1-PrNotE); + } + void inline AddECom(const int& EId, const int& CId, const double& PrECNew) { + if (PrECNew <= 0.0) { + DelECom(EId, CId); + return; + } + double PrECOld = GetECom(EId, CId); + if (! ProbEdgCommHH.IsKey(EId)) { + TIntFltH EmptyEProdH(NumComs); + ProbEdgCommHH.AddDat(EId, EmptyEProdH); + } + ProbEdgCommHH.GetDat(EId).AddDat(CId, PrECNew); + UpdateProbNotEdgH(EId, PrECNew, PrECOld); + } + + void inline DelECom(const int& EId, const int& CId) { + double PrECOld = GetECom(EId, CId); + if (PrECOld > 0.0) { + ProbEdgCommHH.GetDat(EId).DelKey(CId); + UpdateProbNotEdgH(EId, 0.0, PrECOld); + } + } + + static double DotProduct(const TIntFltH& UV, const TIntFltH& VV); + double inline DotProduct(const int& UID, const int& VID) { + return DotProduct(S[UID], S[VID]); + } + + void inline Normalize(const TIntFltH& UV, TIntFltH& UVNmd) { + double Nrm = Norm2(UV); + for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) { + UVNmd.AddDat(HI.GetKey(), HI.GetDat()/Nrm); + } + } + void inline Normalize(TIntFltH& UV) { + double Nrm = Norm2(UV); + for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) { + UV.AddDat(HI.GetKey(), HI.GetDat()/Nrm); + } + } + void inline NormalizeIfLarge(const TIntFltH& UV, TIntFltH& UVNmd) { + double Nrm = Norm2(UV); + if (Nrm >1.0) { Normalize(UV, UVNmd); } + else { + for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) { + UVNmd.AddDat(HI.GetKey(), HI.GetDat()); + } + } + } + + double inline Sum(const TIntFltH& UV) { + double N = 0.0; + for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) { + N += HI.GetDat(); + } + return N; + } + + double inline Norm2(const TIntFltH& UV) { + double N = 0.0; + for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) { + N += HI.GetDat() * HI.GetDat(); + } + return sqrt(N); + } + + double inline Sigmoid(const double X) { + return 1.0 / ( 1.0 + exp(-X)); + } + +}; + + +#endif diff --git a/snap-adv/n2v.cpp b/snap-adv/n2v.cpp index 1e7eadcdc..3e51fe8ae 100644 --- a/snap-adv/n2v.cpp +++ b/snap-adv/n2v.cpp @@ -1,9 +1,11 @@ #include "stdafx.h" #include "n2v.h" -void node2vec(PWNet& InNet, double& ParamP, double& ParamQ, int& Dimensions, - int& WalkLen, int& NumWalks, int& WinSize, int& Iter, bool& Verbose, - TIntFltVH& EmbeddingsHV) { +void node2vec(PWNet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + const bool& OutputWalks, TVVec& WalksVV, + TIntFltVH& EmbeddingsHV) { //Preprocess transition probabilities PreprocessTransitionProbs(InNet, ParamP, ParamQ, Verbose); TIntV NIdsV; @@ -12,7 +14,7 @@ void node2vec(PWNet& InNet, double& ParamP, double& ParamQ, int& Dimensions, } //Generate random walks int64 AllWalks = (int64)NumWalks * NIdsV.Len(); - TVVec WalksVV(AllWalks,WalkLen); + WalksVV = TVVec(AllWalks,WalkLen); TRnd Rnd(time(NULL)); int64 WalksDone = 0; for (int64 i = 0; i < NumWalks; i++) { @@ -35,12 +37,27 @@ void node2vec(PWNet& InNet, double& ParamP, double& ParamQ, int& Dimensions, fflush(stdout); } //Learning embeddings - LearnEmbeddings(WalksVV, Dimensions, WinSize, Iter, Verbose, EmbeddingsHV); + if (!OutputWalks) { + LearnEmbeddings(WalksVV, Dimensions, WinSize, Iter, Verbose, EmbeddingsHV); + } } -void node2vec(PNGraph& InNet, double& ParamP, double& ParamQ, int& Dimensions, - int& WalkLen, int& NumWalks, int& WinSize, int& Iter, bool& Verbose, - TIntFltVH& EmbeddingsHV) { +void node2vec(PWNet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntFltVH& EmbeddingsHV) { + TVVec WalksVV; + bool OutputWalks = 0; + node2vec(InNet, ParamP, ParamQ, Dimensions, WalkLen, NumWalks, WinSize, + Iter, Verbose, OutputWalks, WalksVV, EmbeddingsHV); +} + + +void node2vec(const PNGraph& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + const bool& OutputWalks, TVVec& WalksVV, + TIntFltVH& EmbeddingsHV) { PWNet NewNet = PWNet::New(); for (TNGraph::TEdgeI EI = InNet->BegEI(); EI < InNet->EndEI(); EI++) { if (!NewNet->IsNode(EI.GetSrcNId())) { NewNet->AddNode(EI.GetSrcNId()); } @@ -48,12 +65,24 @@ void node2vec(PNGraph& InNet, double& ParamP, double& ParamQ, int& Dimensions, NewNet->AddEdge(EI.GetSrcNId(), EI.GetDstNId(), 1.0); } node2vec(NewNet, ParamP, ParamQ, Dimensions, WalkLen, NumWalks, WinSize, Iter, - Verbose, EmbeddingsHV); + Verbose, OutputWalks, WalksVV, EmbeddingsHV); } -void node2vec(PNEANet& InNet, double& ParamP, double& ParamQ, - int& Dimensions, int& WalkLen, int& NumWalks, int& WinSize, int& Iter, bool& Verbose, - TIntFltVH& EmbeddingsHV) { +void node2vec(const PNGraph& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntFltVH& EmbeddingsHV) { + TVVec WalksVV; + bool OutputWalks = 0; + node2vec(InNet, ParamP, ParamQ, Dimensions, WalkLen, NumWalks, WinSize, + Iter, Verbose, OutputWalks, WalksVV, EmbeddingsHV); +} + +void node2vec(const PNEANet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + const bool& OutputWalks, TVVec& WalksVV, + TIntFltVH& EmbeddingsHV) { PWNet NewNet = PWNet::New(); for (TNEANet::TEdgeI EI = InNet->BegEI(); EI < InNet->EndEI(); EI++) { if (!NewNet->IsNode(EI.GetSrcNId())) { NewNet->AddNode(EI.GetSrcNId()); } @@ -61,5 +90,16 @@ void node2vec(PNEANet& InNet, double& ParamP, double& ParamQ, NewNet->AddEdge(EI.GetSrcNId(), EI.GetDstNId(), InNet->GetFltAttrDatE(EI,"weight")); } node2vec(NewNet, ParamP, ParamQ, Dimensions, WalkLen, NumWalks, WinSize, Iter, - Verbose, EmbeddingsHV); + Verbose, OutputWalks, WalksVV, EmbeddingsHV); +} + +void node2vec(const PNEANet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntFltVH& EmbeddingsHV) { + TVVec WalksVV; + bool OutputWalks = 0; + node2vec(InNet, ParamP, ParamQ, Dimensions, WalkLen, NumWalks, WinSize, + Iter, Verbose, OutputWalks, WalksVV, EmbeddingsHV); } + diff --git a/snap-adv/n2v.h b/snap-adv/n2v.h index 80fc1047f..44bb60aac 100644 --- a/snap-adv/n2v.h +++ b/snap-adv/n2v.h @@ -8,17 +8,41 @@ #include "word2vec.h" /// Calculates node2vec feature representation for nodes and writes them into EmbeddinsHV, see http://arxiv.org/pdf/1607.00653v1.pdf -void node2vec(PWNet& InNet, double& ParamP, double& ParamQ, int& Dimensions, - int& WalkLen, int& NumWalks, int& WinSize, int& Iter, bool& Verbose, - TIntFltVH& EmbeddingsHV); +void node2vec(PWNet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + const bool& OutputWalks, TVVec& WalksVV, + TIntFltVH& EmbeddingsHV); + +/// Version without walk output flag. For backward compatibility. +void node2vec(PWNet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntFltVH& EmbeddingsHV); /// Version for unweighted graphs -void node2vec(PNGraph& InNet, double& ParamP, double& ParamQ, int& Dimensions, - int& WalkLen, int& NumWalks, int& WinSize, int& Iter, bool& Verbose, - TIntFltVH& EmbeddingsHV); +void node2vec(const PNGraph& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + const bool& OutputWalks, TVVec& WalksVV, + TIntFltVH& EmbeddingsHV); + +/// Version for unweighted graphs without walk output flag. For backward compatibility. +void node2vec(const PNGraph& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntFltVH& EmbeddingsHV); /// Version for weighted graphs. Edges must have TFlt attribute "weight" -void node2vec(PNEANet& InNet, double& ParamP, double& ParamQ, int& Dimensions, - int& WalkLen, int& NumWalks, int& WinSize, int& Iter, bool& Verbose, +void node2vec(const PNEANet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, + const bool& OutputWalks, TVVec& WalksVV, + TIntFltVH& EmbeddingsHV); + +/// Version for weighted graphs. Edges must have TFlt attribute "weight". No walk output flag. For backward compatibility. +void node2vec(const PNEANet& InNet, const double& ParamP, const double& ParamQ, + const int& Dimensions, const int& WalkLen, const int& NumWalks, + const int& WinSize, const int& Iter, const bool& Verbose, TIntFltVH& EmbeddingsHV); #endif //N2V_H diff --git a/snap-adv/rolx.cpp b/snap-adv/rolx.cpp index ee73cd455..f726fb77c 100644 --- a/snap-adv/rolx.cpp +++ b/snap-adv/rolx.cpp @@ -448,6 +448,17 @@ void FPrintMatrix(const TFltVV& Matrix, const TStr& Path) { fclose(Fp); } +void FPrintNodeMappings(const TIntIntH& NodeIdMtxIdxH, const TStr& Path) { + FILE *Fp; + Fp = fopen(Path.CStr(), "w"); + fprintf(Fp, "# mappings from the feature line numbers to node IDs\n"); + for (int i = 0; i < NodeIdMtxIdxH.Len(); i++) { + int NodeId = GetNodeId(i, NodeIdMtxIdxH); + fprintf(Fp, "%d %d\n", i, NodeId); + } + fclose(Fp); +} + void FPrintRoles(const TIntIntH& Roles, const TStr& Path) { FILE *Fp; Fp = fopen(Path.CStr(), "w"); diff --git a/snap-adv/rolx.h b/snap-adv/rolx.h index f40df25e5..7bcf1ef1c 100644 --- a/snap-adv/rolx.h +++ b/snap-adv/rolx.h @@ -80,6 +80,8 @@ void PlotRoles(const PUNGraph Graph, const TIntIntH& Roles); void PrintRoles(const TIntIntH& Roles); /// Prints feature matrix to file. void FPrintMatrix(const TFltVV& Matrix, const TStr& Path); +/// Prints node mappings to file, feature line -> node ID +void FPrintNodeMappings(const TIntIntH& NodeIdMtxIdxH, const TStr& Path); /// Prints found roles to file. void FPrintRoles(const TIntIntH& Roles, const TStr& Path); diff --git a/snap-adv/temporalmotifs.cpp b/snap-adv/temporalmotifs.cpp index d78674872..04fbcdad3 100644 --- a/snap-adv/temporalmotifs.cpp +++ b/snap-adv/temporalmotifs.cpp @@ -27,7 +27,9 @@ TempMotifCounter::TempMotifCounter(const TStr& filename) { int src = data_ptr->GetIntValAtRowIdx(src_idx, row_idx).Val; int dst = data_ptr->GetIntValAtRowIdx(dst_idx, row_idx).Val; int tim = data_ptr->GetIntValAtRowIdx(tim_idx, row_idx).Val; - temporal_data_[src](dst).Add(tim); + // Do not include self loops as they do not appear in the definition of + // temporal motifs. + if (src != dst) { temporal_data_[src](dst).Add(tim); } } } @@ -137,7 +139,7 @@ void TempMotifCounter::Count3TEdge23Node(double delta, Counter2D& counts) { counts(1, 1) = mid_counts(1, 0, 0); counts(1, 4) = pos_counts(1, 0, 0); counts(1, 5) = pos_counts(1, 0, 1); - counts(2, 0) = mid_counts(0, 0, 1); + counts(2, 0) = mid_counts(0, 1, 0); counts(2, 1) = mid_counts(0, 1, 1); counts(2, 2) = pos_counts(0, 1, 0); counts(2, 3) = pos_counts(0, 1, 1); diff --git a/snap-adv/word2vec.cpp b/snap-adv/word2vec.cpp index ec01f082d..273652738 100644 --- a/snap-adv/word2vec.cpp +++ b/snap-adv/word2vec.cpp @@ -44,13 +44,23 @@ void InitUnigramTable(TIntV& Vocab, TIntV& KTable, TFltV& UTable) { UnderV.DelLast(); OverV.DelLast(); KTable[Small] = Large; - UTable[Large] = UTable[Large] + UTable[Small] - 1; + UTable[Large] = (UTable[Large] + UTable[Small]) - 1; if (UTable[Large] < 1) { UnderV.Add(Large); } else { OverV.Add(Large); } } + while(UnderV.Len() > 0){ + int64 curr = UnderV.Last(); + UnderV.DelLast(); + UTable[curr]=1; + } + while(OverV.Len() > 0){ + int64 curr = OverV.Last(); + OverV.DelLast(); + UTable[curr]=1; + } } int64 RndUnigramInt(TIntV& KTable, TFltV& UTable, TRnd& Rnd) { @@ -60,7 +70,7 @@ int64 RndUnigramInt(TIntV& KTable, TFltV& UTable, TRnd& Rnd) { } //Initialize negative embeddings -void InitNegEmb(TIntV& Vocab, int& Dimensions, TVVec& SynNeg) { +void InitNegEmb(TIntV& Vocab, const int& Dimensions, TVVec& SynNeg) { SynNeg = TVVec(Vocab.Len(),Dimensions); for (int64 i = 0; i < SynNeg.GetXDim(); i++) { for (int j = 0; j < SynNeg.GetYDim(); j++) { @@ -70,7 +80,7 @@ void InitNegEmb(TIntV& Vocab, int& Dimensions, TVVec& SynNeg) { } //Initialize positive embeddings -void InitPosEmb(TIntV& Vocab, int& Dimensions, TRnd& Rnd, TVVec& SynPos) { +void InitPosEmb(TIntV& Vocab, const int& Dimensions, TRnd& Rnd, TVVec& SynPos) { SynPos = TVVec(Vocab.Len(),Dimensions); for (int64 i = 0; i < SynPos.GetXDim(); i++) { for (int j = 0; j < SynPos.GetYDim(); j++) { @@ -79,9 +89,11 @@ void InitPosEmb(TIntV& Vocab, int& Dimensions, TRnd& Rnd, TVVec& Sy } } -void TrainModel(TVVec& WalksVV, int& Dimensions, int& WinSize, int& Iter, bool& Verbose, - TIntV& KTable, TFltV& UTable, int64& WordCntAll, TFltV& ExpTable, double& Alpha, - int64 CurrWalk, TRnd& Rnd, TVVec& SynNeg, TVVec& SynPos) { +void TrainModel(TVVec& WalksVV, const int& Dimensions, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntV& KTable, TFltV& UTable, int64& WordCntAll, TFltV& ExpTable, + double& Alpha, int64 CurrWalk, TRnd& Rnd, + TVVec& SynNeg, TVVec& SynPos) { TFltV Neu1V(Dimensions); TFltV Neu1eV(Dimensions); int64 AllWords = WalksVV.GetXDim()*WalksVV.GetYDim(); @@ -145,8 +157,9 @@ void TrainModel(TVVec& WalksVV, int& Dimensions, int& WinSize, int& } -void LearnEmbeddings(TVVec& WalksVV, int& Dimensions, int& WinSize, - int& Iter, bool& Verbose, TIntFltVH& EmbeddingsHV) { +void LearnEmbeddings(TVVec& WalksVV, const int& Dimensions, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntFltVH& EmbeddingsHV) { TIntIntH RnmH; TIntIntH RnmBackH; int64 NNodes = 0; diff --git a/snap-adv/word2vec.h b/snap-adv/word2vec.h index 00b53d459..88ca253dd 100644 --- a/snap-adv/word2vec.h +++ b/snap-adv/word2vec.h @@ -2,8 +2,9 @@ #define WORD_2_VEC_H ///Learns embeddings using SGD, Skip-gram with negative sampling. -void LearnEmbeddings(TVVec& WalksVV, int& Dimensions, int& WinSize, - int& Iter, bool& Verbose, TIntFltVH& EmbeddingsHV); +void LearnEmbeddings(TVVec& WalksVV, const int& Dimensions, + const int& WinSize, const int& Iter, const bool& Verbose, + TIntFltVH& EmbeddingsHV); //Max x for e^x. Value taken from original word2vec code. const int MaxExp = 6; diff --git a/snap-core/anf.h b/snap-core/anf.h index 42597f500..d007eac40 100644 --- a/snap-core/anf.h +++ b/snap-core/anf.h @@ -74,7 +74,7 @@ void TGraphAnf::InitAnfBits(TAnfBitV& BitV) { IAssertR(VSize <= TInt::Mx, TStr::Fmt("Your graph is too large for Approximate Neighborhood Function, %s is larger than %d", TUInt64::GetStr(VSize).CStr(),TInt::Mx)); - printf("size %d\n", static_cast(VSize)); + //printf("size %d\n", static_cast(VSize)); BitV.Gen((const int)VSize); IAssert(BitV.BegI() != NULL); BitV.PutAll(0); int SetBit = 0; diff --git a/snap-core/bfsdfs.h b/snap-core/bfsdfs.h index 9c60136de..108e40cb2 100644 --- a/snap-core/bfsdfs.h +++ b/snap-core/bfsdfs.h @@ -27,9 +27,11 @@ template int GetBfsFullDiam(const PGraph& Graph, const int& NTest template double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir=false); /// Returns the (approximation of the) Effective Diameter and the Diameter of a graph (by performing BFS from NTestNodes random starting nodes). ##GetBfsEffDiam2 template double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiamX, int& FullDiamX); -/// Returns the (approximation of the) Effective Diameter, the Diameter and the Average Shortest Path length in a graph (by performing BFS from NTestNodes random starting nodes). GetBfsEffDiam3 +/// Returns the (approximation of the) Effective Diameter, the Diameter and the Average Shortest Path length in a graph (by performing BFS from NTestNodes random starting nodes). ##GetBfsEffDiam3 template double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiamX, int& FullDiamX, double& AvgSPLX); -/// Use the whole graph (all edges) to measure the shortest path lengths but only report the path lengths between nodes in the SubGraphNIdV. GetBfsEffDiam4 +/// Returns the (approximation of the) Effective Diameter, the Diameter and the Average Shortest Path length in a graph (by performing BFS from NTestNodes random starting nodes). ##GetBfsEffDiamAll +template double GetBfsEffDiamAll(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiamX, int& FullDiamX, double& AvgSPLX); +/// Use the whole graph (all edges) to measure the shortest path lengths but only report the path lengths between nodes in the SubGraphNIdV. ##GetBfsEffDiam4 template double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const TIntV& SubGraphNIdV, const bool& IsDir, double& EffDiamX, int& FullDiamX); // TODO: Implement in the future @@ -435,6 +437,11 @@ double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsD return EffDiam; } +template +double GetBfsEffDiamAll(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiam, int& FullDiam, double& AvgSPL) { + return GetBfsEffDiam(Graph, NTestNodes, IsDir, EffDiam, FullDiam, AvgSPL); +} + template double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const TIntV& SubGraphNIdV, const bool& IsDir, double& EffDiam, int& FullDiam) { EffDiam = -1; diff --git a/snap-core/centr.cpp b/snap-core/centr.cpp index c124ec1a6..e566b140c 100644 --- a/snap-core/centr.cpp +++ b/snap-core/centr.cpp @@ -687,8 +687,8 @@ int findMinimum(TIntV& Frontier, TIntFltH& NIdDistH) { int min_index = 0; for (int i = 0; i < Frontier.Len(); i++) { int NId = Frontier.GetVal(i); - if (NIdDistH[NId] < minimum) { - minimum = NIdDistH[NId]; + if (NIdDistH.GetDat(NId) < minimum) { + minimum = NIdDistH.GetDat(NId); min_index = i; } } @@ -714,8 +714,8 @@ const PNEANet Graph, const int& SrcNId, TIntFltH& NIdDistH, const TFltV& Attr) { NIdDistH.AddDat(DstNId, NIdDistH.GetDat(NId) + Attr[EId]); frontier.Add(DstNId); } else { - if (NIdDistH[DstNId] > NIdDistH.GetDat(NId) + Attr[EId]) { - NIdDistH[DstNId] = NIdDistH.GetDat(NId) + Attr[EId]; + if (NIdDistH.GetDat(DstNId) > NIdDistH.GetDat(NId) + Attr[EId]) { + NIdDistH.GetDat(DstNId) = NIdDistH.GetDat(NId) + Attr[EId]; } } } diff --git a/snap-core/cmty.cpp b/snap-core/cmty.cpp index 8dbc9fce6..e2717c78e 100644 --- a/snap-core/cmty.cpp +++ b/snap-core/cmty.cpp @@ -310,9 +310,11 @@ double InfomapOnlineIncrement(PUNGraph& Graph, int n1, int n2, TIntFltH& PAlpha, // Maximum modularity clustering by Girvan-Newman algorithm (slow) // Girvan M. and Newman M. E. J., Community structure in social and biological networks, Proc. Natl. Acad. Sci. USA 99, 7821-7826 (2002) double CommunityGirvanNewman(PUNGraph& Graph, TCnComV& CmtyV) { + PUNGraph LocalGraph = TSnap::ConvertGraph(Graph, false); + TIntH OutDegH; - const int NEdges = Graph->GetEdges(); - for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { + const int NEdges = LocalGraph->GetEdges(); + for (TUNGraph::TNodeI NI = LocalGraph->BegNI(); NI < LocalGraph->EndNI(); NI++) { OutDegH.AddDat(NI.GetId(), NI.GetOutDeg()); } double BestQ = -1; // modularity @@ -320,8 +322,8 @@ double CommunityGirvanNewman(PUNGraph& Graph, TCnComV& CmtyV) { CmtyV.Clr(); TIntV Cmty1, Cmty2; while (true) { - TSnapDetail::CmtyGirvanNewmanStep(Graph, Cmty1, Cmty2); - const double Q = TSnapDetail::_GirvanNewmanGetModularity(Graph, OutDegH, NEdges, CurCmtyV); + TSnapDetail::CmtyGirvanNewmanStep(LocalGraph, Cmty1, Cmty2); + const double Q = TSnapDetail::_GirvanNewmanGetModularity(LocalGraph, OutDegH, NEdges, CurCmtyV); //printf("current modularity: %f\n", Q); if (Q > BestQ) { BestQ = Q; diff --git a/snap-core/conv.cpp b/snap-core/conv.cpp index df6d1670f..5232121cd 100644 --- a/snap-core/conv.cpp +++ b/snap-core/conv.cpp @@ -49,7 +49,7 @@ int LoadMode(TModeNet& Graph, PTable Table, const TStr& NCol, Graph.AddFltAttrDatN(NVal, Table->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph.AddStrAttrDatN(NVal, Table->GetStrVal(Index, CurrRowIdx), ColName); + Graph.AddStrAttrDatN(NVal, Table->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -117,7 +117,7 @@ int LoadCrossNet(TCrossNet& Graph, PTable Table, const TStr& SrcCol, const TStr& Graph.AddFltAttrDatE(CurrRowIdx, Table->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph.AddStrAttrDatE(CurrRowIdx, Table->GetStrVal(Index, CurrRowIdx), ColName); + Graph.AddStrAttrDatE(CurrRowIdx, Table->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -125,4 +125,4 @@ int LoadCrossNet(TCrossNet& Graph, PTable Table, const TStr& SrcCol, const TStr& return 1; } -}; //namespace TSnap \ No newline at end of file +}; //namespace TSnap diff --git a/snap-core/conv.h b/snap-core/conv.h index 6fae553e0..e0dddaf7c 100644 --- a/snap-core/conv.h +++ b/snap-core/conv.h @@ -131,7 +131,7 @@ PGraph ToNetwork(PTable Table, Graph->AddFltAttrDatE(CurrRowIdx, Table->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrVal(Index, CurrRowIdx), ColName); + Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -1010,7 +1010,7 @@ inline PGraphMP ToNetworkMP(PTable Table, Graph->AddFltAttrDatE(RowId, Table->FltCols[Index][RowId], ColName); break; case atStr: - Graph->AddStrAttrDatE(RowId, Table->GetStrVal(Index, RowId), ColName); + Graph->AddStrAttrDatE(RowId, Table->GetStrValIdx(Index, RowId), ColName); break; } } @@ -1047,7 +1047,7 @@ inline PGraphMP ToNetworkMP(PTable Table, Graph->AddFltAttrDatE(RowId, Table->FltCols[Index][RowId], ColName); break; case atStr: - Graph->AddStrAttrDatE(RowId, Table->GetStrVal(Index, RowId), ColName); + Graph->AddStrAttrDatE(RowId, Table->GetStrValIdx(Index, RowId), ColName); break; } } @@ -1635,7 +1635,7 @@ PGraph ToNetwork(PTable Table, Graph->AddFltAttrDatE(CurrRowIdx, Table->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrVal(Index, CurrRowIdx), ColName); + Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -1993,7 +1993,7 @@ inline PGraphMP ToNetworkMP(PTable Table, Graph->AddFltAttrDatE(CurrRowIdx, Table->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrVal(Index, CurrRowIdx), ColName); + Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -2081,7 +2081,7 @@ PGraph ToNetwork(PTable Table, Graph->AddFltAttrDatE(CurrRowIdx, Table->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrVal(Index, CurrRowIdx), ColName); + Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -2113,7 +2113,7 @@ PGraph ToNetwork(PTable Table, Graph->AddFltAttrDatN(NId, NodeTable->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph->AddStrAttrDatN(NId, NodeTable->GetStrVal(Index, CurrRowIdx), ColName); + Graph->AddStrAttrDatN(NId, NodeTable->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -2475,7 +2475,7 @@ inline PGraphMP ToNetworkMP(PTable Table, Graph->AddFltAttrDatE(CurrRowIdx, Table->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrVal(Index, CurrRowIdx), ColName); + Graph->AddStrAttrDatE(CurrRowIdx, Table->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } @@ -2506,7 +2506,7 @@ inline PGraphMP ToNetworkMP(PTable Table, Graph->AddFltAttrDatN(NId, NodeTable->FltCols[Index][CurrRowIdx], ColName); break; case atStr: - Graph->AddStrAttrDatN(NId, NodeTable->GetStrVal(Index, CurrRowIdx), ColName); + Graph->AddStrAttrDatN(NId, NodeTable->GetStrValIdx(Index, CurrRowIdx), ColName); break; } } diff --git a/snap-core/doc/bfsdfs.h.txt b/snap-core/doc/bfsdfs.h.txt index 795c8d3fe..875076f29 100644 --- a/snap-core/doc/bfsdfs.h.txt +++ b/snap-core/doc/bfsdfs.h.txt @@ -39,14 +39,12 @@ @param IsDir false: ignore edge directions and consider edges/paths as undirected (in case they are directed). /// +/// GetBfsEffDiamAll + This function is a duplicate. It is required by Snap.py. + @param IsDir false: ignore edge directions and consider edges/paths as undirected (in case they are directed). +/// + /// GetBfsEffDiam4 @param IsDir false: ignore edge directions and consider edges/paths as undirected (in case they are directed). /// - - - - - - - diff --git a/snap-core/doc/network.h.txt b/snap-core/doc/network.h.txt index 2de8b243f..939fd8f0e 100644 --- a/snap-core/doc/network.h.txt +++ b/snap-core/doc/network.h.txt @@ -319,7 +319,11 @@ Adds the key int value pair to the corresponding edge attribute value vector. /// /// TNEANet::AddIntVAttrDatE -Adds the key intv value pair to the corresponding edge attribute value vector. +Adds the key integer vector value pair to the corresponding edge attribute value vector. +/// + +/// TNEANet::AddFltVAttrDatE +Adds the key float vector value pair to the corresponding edge attribute value vector. /// /// TNEANet::AddStrAttrDatE diff --git a/snap-core/doc/subgraph.h.txt b/snap-core/doc/subgraph.h.txt index fffa09f11..456bb457b 100644 --- a/snap-core/doc/subgraph.h.txt +++ b/snap-core/doc/subgraph.h.txt @@ -5,6 +5,13 @@ Node IDs are preserved. Nodes in the resulting subgraph have the same node IDs as nodes in Graph. /// +/// TSnap::GetSubGraphRenumber +The resulting subgraph contains all the nodes from Graph, which have +node IDs in the NIdV vector and all the edges with both nodes in NIdV. +The nodes in the resulting subgraph are renumbered sequentially from 0 to N-1. +This function is required by Snap.py. +/// + /// TSnap::GetSubGraph-1 The resulting subgraph contains all the nodes from Graph, which have node IDs in the NIdV vector and all the edges with both nodes in NIdV. diff --git a/snap-core/doc/triad.h.txt b/snap-core/doc/triad.h.txt index 062916d58..d1f456704 100644 --- a/snap-core/doc/triad.h.txt +++ b/snap-core/doc/triad.h.txt @@ -11,14 +11,21 @@ Considers the graph as undirected. /// TSnap::GetClustCf2 Considers the graph as undirected. @param DegToCCfV Vector of pairs (degree, avg. clustering coefficient of nodes of that degree). +@param ClosedTriads On return contains the number of closed triads. +@param OpenTriads On return contains the number of open triads. @param SampleNodes If !=-1 then compute clustering coefficient only for a random sample of SampleNodes nodes. Useful for approximate but quick computations. /// -/// TSnap::GetNodeClustCf +/// TSnap::GetClustCfAll Considers the graph as undirected. +This function is a duplicate. It is required by Snap.py. +@param DegToCCfV Vector of pairs (degree, avg. clustering coefficient of nodes of that degree). +@param ClosedTriads On return contains the number of closed triads. +@param OpenTriads On return contains the number of open triads. +@param SampleNodes If !=-1 then compute clustering coefficient only for a random sample of SampleNodes nodes. Useful for approximate but quick computations. /// -/// TSnap::GetClustCf1 +/// TSnap::GetNodeClustCf Considers the graph as undirected. /// @@ -33,6 +40,12 @@ Considers the graph as undirected. @param SampleNodes If !=-1 then compute triads only for a random sample of SampleNodes nodes. Useful for approximate but quick computations. /// +/// TSnap::GetTriadsAll +Considers the graph as undirected. +This function is a duplicate. It is required by Snap.py. +@param SampleNodes If !=-1 then compute triads only for a random sample of SampleNodes nodes. Useful for approximate but quick computations. +/// + /// TSnap::GetTriads2 Considers the graph as undirected. @param NIdCOTriadV Triple (node id, open triads: number of pairs of node's neighbors that are not connected, closed triads: number of pairs of node's neighbors that are connected between themselves). @@ -54,8 +67,17 @@ Considers the graph as undirected. Considers the graph as undirected. @param Graph Input graph @param NId Input node -@param ClosedNTriadsX On return contains the number of closed triads -@param OpenNTriadsX On return contains the number of open triads +@param ClosedNTriadsX On return contains the number of closed triads. +@param OpenNTriadsX On return contains the number of open triads. +/// + +/// TSnap::GetNodeTriadsAll +Considers the graph as undirected. +This function is a duplicate. It is required by Snap.py. +@param Graph Input graph +@param NId Input node +@param ClosedNTriadsX On return contains the number of closed triads. +@param OpenNTriadsX On return contains the number of open triads. /// /// TSnap::GetNodeTriads3 @@ -63,9 +85,9 @@ Considers the graph as undirected. @param Graph Input graph @param NId Input node @param GroupSet Input set with node neighbors -@param InGroupEdgesX On return contains the number of triads (NId, G1, G2), where G1 and G2 are in GroupSet -@param InOutGroupEdgesX On return contains the number of triads (NId, G1, O1), where G1 is in GroupSet and O1 not in GroupSet -@param OutGroupEdgesX On return contains the number of triads (NId, O1, O2), where O1 and O2 are not in GroupSet +@param InGroupEdgesX On return contains the number of triads (NId, G1, G2), where G1 and G2 are in GroupSet. +@param InOutGroupEdgesX On return contains the number of triads (NId, G1, O1), where G1 is in GroupSet and O1 not in GroupSet. +@param OutGroupEdgesX On return contains the number of triads (NId, O1, O2), where O1 and O2 are not in GroupSet. /// /// TSnap::GetTriadParticip diff --git a/snap-core/gbase.cpp b/snap-core/gbase.cpp index 0853939d3..d33a4e55b 100644 --- a/snap-core/gbase.cpp +++ b/snap-core/gbase.cpp @@ -11,6 +11,7 @@ TStr GetFlagStr(const TGraphFlag& GraphFlag) { case gfEdgeDat : return "EdgeDat"; case gfSources : return "Sources"; case gfBipart : return "Bipartite"; + case gfHyperGraph : return "Hypergraph"; default: FailR("Unknown graph type"); }; return TStr(); @@ -56,4 +57,4 @@ void TUnionFind::Dump() { printf(" %d\t%d\n", int(KIdSetH.GetKey(i)), Find(KIdSetH.GetKey(i))); } printf("\n"); -} +} \ No newline at end of file diff --git a/snap-core/gbase.h b/snap-core/gbase.h index 22934df18..5828677e1 100644 --- a/snap-core/gbase.h +++ b/snap-core/gbase.h @@ -14,6 +14,7 @@ typedef enum TGraphFlag_ { gfEdgeDat, ///< network with data on edges gfSources, ///< nodes only store out-edges (but not in-edges). See TBigNet gfBipart, ///< bipartite graph + gfHyperGraph, ///< undirected, unweighted ypergraph (THGraph) gfMx ///< sentinel, last value for iteration } TGraphFlag; @@ -34,6 +35,8 @@ template struct IsEdgeDat { enum { Val = 0 }; }; template struct IsSources { enum { Val = 0 }; }; /// Tests (at compile time) if the graph is a bipartite graph type. template struct IsBipart { enum { Val = 0 }; }; +/// Tests (at compile time) if the graph is a hypergraph. +template struct IsHyperGraph { enum { Val = 0 }; }; /// For quick testing of the properties of the graph/network object (see TGraphFlag). #define HasGraphFlag(TGraph, Flag) \ @@ -42,7 +45,8 @@ template struct IsBipart { enum { Val = 0 }; }; (Flag)==gfNodeDat ? TSnap::IsNodeDat::Val : \ (Flag)==gfEdgeDat ? TSnap::IsEdgeDat::Val : \ (Flag)==gfSources ? TSnap::IsSources::Val : \ - (Flag)==gfBipart ? TSnap::IsBipart::Val : 0) + (Flag)==gfBipart ? TSnap::IsBipart::Val : \ + (Flag)==gfHyperGraph ? TSnap::IsHyperGraph::Val : 0) #if 0 // RS 2013/08/19, commented out IsDerivedFrom, it is not called anywhere @@ -173,6 +177,19 @@ class TSnapQueue { /// Returns the value of the ValN element in the queue, but does not remove the element. const TVal& operator[](const int& ValN) const { return ValV[First+ValN]; } + // Randomly samples num elements from Queue and adds them to the front. + void Sample(const int num, TRnd& Rnd=TInt::Rnd) { + const int size = Last - First; + int loc; + TVal temp; + for (int i = 0; i < num && i < size; ++i) { + loc = Rnd.GetUniDevInt(size - i) + First + i; + temp = ValV[loc]; + ValV[loc] = ValV[First + i]; + ValV[First + i] = temp; + } + } + /// Deletes all elements from the queue. void Clr(const bool& DoDel=true) { ValV.Clr(DoDel); First=Last=0; } void Gen(const int& MxVals, const int& MaxFirst=1024) { diff --git a/snap-core/ggen.cpp b/snap-core/ggen.cpp index 264c6ce26..9fcdfa7f5 100644 --- a/snap-core/ggen.cpp +++ b/snap-core/ggen.cpp @@ -46,15 +46,18 @@ PUNGraph GenRndPowerLaw(const int& Nodes, const double& PowerExp, const bool& Co // use configuration model -- fast but does not exactly obey the degree sequence return GenConfModel(DegSeqV, Rnd); } else { + DegSeqV.Sort(); + DegSeqV.Reverse(); PUNGraph G = TSnap::GenDegSeq(DegSeqV, Rnd); return TSnap::GenRewire(G, 10, Rnd); } } -/// Generates a random graph with exact degree sequence DegSeqV. -/// The generated graph has no self loops. The graph generation process -/// simulates the Configuration Model but if a duplicate edge occurs, we find a -/// random edge, break it and reconnect it with the duplicate. +/// Generates a random graph with exact degree sequence \c DegSeqV. \c DegSeqV +/// must be sorted in descending order. The generated graph has no self loops. +/// The graph generation process simulates the Configuration Model, +/// but if a duplicate edge occurs, we find a random edge, break it and +/// reconnect it with the duplicate. PUNGraph GenDegSeq(const TIntV& DegSeqV, TRnd& Rnd) { const int Nodes = DegSeqV.Len(); PUNGraph GraphPt = TUNGraph::New(); @@ -72,8 +75,8 @@ PUNGraph GenDegSeq(const TIntV& DegSeqV, TRnd& Rnd) { IAssert(DegSum % 2 == 0); while (! DegH.Empty()) { // pick random nodes and connect - const int NId1 = DegH.GetKey(DegH.GetRndKeyId(TInt::Rnd, 0.5)); - const int NId2 = DegH.GetKey(DegH.GetRndKeyId(TInt::Rnd, 0.5)); + const int NId1 = DegH.GetKey(DegH.GetRndKeyId(Rnd, 0.5)); + const int NId2 = DegH.GetKey(DegH.GetRndKeyId(Rnd, 0.5)); IAssert(DegH.IsKey(NId1) && DegH.IsKey(NId2)); if (NId1 == NId2) { if (DegH.GetDat(NId1) == 1) { continue; } @@ -320,7 +323,7 @@ PUNGraph GenPrefAttach(const int& Nodes, const int& NodeOutDeg, TRnd& Rnd) { for (int node = 2; node < Nodes; node++) { NodeSet.Clr(false); while (NodeSet.Len() < NodeOutDeg && NodeSet.Len() < node) { - NodeSet.AddKey(NIdV[TInt::Rnd.GetUniDevInt(NIdV.Len())]); + NodeSet.AddKey(NIdV[Rnd.GetUniDevInt(NIdV.Len())]); } const int N = Graph.AddNode(); for (int i = 0; i < NodeSet.Len(); i++) { diff --git a/snap-core/ggen.h b/snap-core/ggen.h index 3283fc8f7..32ab29086 100644 --- a/snap-core/ggen.h +++ b/snap-core/ggen.h @@ -200,7 +200,7 @@ PGraph GenBaraHierar(const int& Levels, const bool& IsDir) { // add edges to the center //const int LevPow = (int)TMath::Round(TMath::Power(5,lev-1)); for (int n = MxNId; n < Graph.GetNodes(); n++) { - typename PGraph::TObj::TNodeI NI = Graph.GetNI(n); + //typename PGraph::TObj::TNodeI NI = Graph.GetNI(n); const int SrcId = n; int Pow = 1; bool Skip = false; for (int p = 1; p <= lev; p++) { diff --git a/snap-core/gio.h b/snap-core/gio.h index 7fc7eca33..e4ab0dbde 100644 --- a/snap-core/gio.h +++ b/snap-core/gio.h @@ -191,9 +191,10 @@ PGraph LoadPajek(const TStr& InFNm) { if (Ss.Len()>0 && Ss[0][0] == '%') { continue; } // comment if (Ss.Len()>0 && Ss[0][0] == '*') { break; } if (EdgeList) { - // - if (Ss.Len() >= 3 && Ss.IsInt(0) && Ss.IsInt(1)) { - Graph->AddEdge(Ss.GetInt(0), Ss.GetInt(1)); } + // [ ] + if (Ss.Len() >= 2 && Ss.IsInt(0) && Ss.IsInt(1)) { + Graph->AddEdge(Ss.GetInt(0), Ss.GetInt(1)); + } } else { // ... const int SrcNId = Ss.GetInt(0); diff --git a/snap-core/graph.cpp b/snap-core/graph.cpp index 707f0fcc9..cf94f3a35 100644 --- a/snap-core/graph.cpp +++ b/snap-core/graph.cpp @@ -880,3 +880,222 @@ PBPGraph TBPGraph::GetSmallGraph() { return BP; } +///////////////////////////////////////////////// +// Hypergraph +bool THGraph::HasFlag(const TGraphFlag& Flag) const { + return HasGraphFlag(THGraph::TNet, Flag); +} + +// Add a node of ID NId to the graph. +int THGraph::AddNode(int NId, TStr NName) { + if (NId == -1) { + NId = MxNId; MxNId++; + } else { + IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId)); + MxNId = TMath::Mx(NId+1, MxNId()); + } + NodeH.AddDat(NId, TNode(NId, NName)); + return NId; +} + +// Add a node of ID NId to the graph. +int THGraph::AddNodeUnchecked(int NId, TStr NName) { + if (IsNode(NId)) { return -1;} + MxNId = TMath::Mx(NId+1, MxNId()); + NodeH.AddDat(NId, TNode(NId, NName)); + return NId; +} + +// Delete node of ID NId from the graph. +void THGraph::DelNode(const int& NId) { + AssertR(IsNode(NId), TStr::Fmt("NodeId %d does not exist", NId)); + TNode& Node = GetNode(NId); + int EId = Node.EIdV.GetVal(0); + int NumNei; + TIntSet& ENIdsHS = GetEdge(EId).NeiNIdSH; + for (int e = 0; e < Node.GetDeg(); e++) { + // Remove node from neighboring nodes' neighbor list: + EId = Node.EIdV.GetVal(e); + ENIdsHS = GetEdge(EId).NeiNIdSH; + int iKey; + for (int i=0; i < ENIdsHS.Len(); i++) { + iKey = ENIdsHS.GetKey(i); + if (iKey == NId) { continue; } + GetNode(iKey).DelNeighbor(NId); + } + /// Adjust N2Edges + NumNei = ENIdsHS.Len(); + N2Edges = N2Edges - (NumNei*(NumNei-1))/2 + ((NumNei-1)*(NumNei-2))/2; + // Remove NId from contributing edges/Delete edges with NId with size of 2: + if (ENIdsHS.Len() > 2) { + GetEdge(EId).NeiNIdSH.DelKey(NId); + } else { DelEdge(EId); } + // Remove node from HGraph (list of nodes): + NodeH.DelKey(NId); + } + delete &Node; +} + +void THGraph::TNode::UpdEInfo(const int& EId, const TIntSet& ENodesHS){ + if (! EIdV.IsIn(EId)) { + EIdV.Add(EId); + for (int j = 0; j < ENodesHS.Len(); j++) { + if (Id == ENodesHS.GetKey(j)) { continue; } + if (! NbrNIdENumH.IsKey(ENodesHS.GetKey(j))) { + NbrNIdENumH.AddDat(ENodesHS.GetKey(j), 1); + } else { + NbrNIdENumH.AddDat(ENodesHS.GetKey(j), 1 + NbrNIdENumH.GetDat(ENodesHS.GetKey(j))); + } + } + } +} + +inline THGraph::TEdge::TEdge( THGraph* GraphPt, const TIntSet& NodeIdsHS) { + TInt EIdCandidate = GraphPt->NEdges; + while (GraphPt->EdgeH.IsKey(EIdCandidate)) { EIdCandidate++; } + TEdge(EIdCandidate, NodeIdsHS, GraphPt); +} + +inline THGraph::TEdge::TEdge( THGraph* GraphPt, const TIntV& NodeIdsV) { + TInt EIdCandidate = GraphPt->NEdges; + while (GraphPt->EdgeH.IsKey(EIdCandidate)) { EIdCandidate++; } + TEdge(EIdCandidate, NodeIdsV, GraphPt); +} + +void THGraph::TEdge::UpdNEInfo(const TIntSet& ENodesHS){ + for (int i = 0; i < ENodesHS.Len(); i++) { + Graph->GetNode(ENodesHS.GetKey(i)).UpdEInfo(Id, ENodesHS); + } +} + +bool THGraph::IsEdge(const TIntSet& NIdH) { + if (NIdH.Len() < 2) { return false; } + if (! IsNode(NIdH.GetKey(0))) { return false; } + int NId = NIdH.GetKey(0); + TIntSet SharedEIdsH; + NodeH.GetDat(NId).GetEIDs(SharedEIdsH); + for (int n = 1; n< NIdH.Len(); n++){ + int N1Id = NIdH.GetKey(n); + TIntSet NeiEIdH; + NodeH.GetDat(N1Id).GetEIDs(NeiEIdH); + TIntersect(SharedEIdsH, NeiEIdH); + if (SharedEIdsH.Len()==0) { return false; } + } + for (THashSetKeyI e = SharedEIdsH.BegI(); e < SharedEIdsH.EndI(); e++) { + if(GetEI(e.GetKey()).Len() == NIdH.Len()) { + return true; + } + } + return false; +} + +/// Add an edge between the nodes in NodeIdsHS set. +int THGraph::AddEdge(const TIntSet& NIdH, int& EId) { + if (IsEdge(NIdH)) { return -1; } + EId = TMath::Mx(EId, MxEId()); + MxEId = EId + 1; + IAssertR(!IsEdgeId(EId), TStr::Fmt("EdgeId %d already exists", EId)); + EdgeH.AddDat(EId, TEdge(EId, NIdH, this)); + EdgeH.GetDat(EId).UpdNEInfo(NIdH); + NEdges++; + N2Edges += (NIdH.Len() * (NIdH.Len()-1))/2; + return EId; +} + +int THGraph::AssertNodes(const TIntSet& NodesIS) { + int NKey; + for (int N=0; N < NodesIS.Len(); N++) { + NKey = NodesIS.GetKey(N); + if (! IsNode(NKey)) {return NKey;} + } + return -1; +} + +void THGraph::DelEdge(const int& EId) { + IAssertR(IsEdgeId(EId), TStr::Fmt("EdgeId %d not found", EId)); + TIntSet NodeIdsHS = GetEdge(EId).NeiNIdSH; + int iKey, jKey; + for (int i=NodeIdsHS.FFirstKeyId(); NodeIdsHS.FNextKeyId(i); ) { + iKey = NodeIdsHS.GetKey(i); + for (int j=NodeIdsHS.FFirstKeyId(); NodeIdsHS.FNextKeyId(j); ) { + if (i==j) { continue; } + jKey = NodeIdsHS.GetKey(j); + GetNode(iKey).DelNeighbor(jKey); + } + } + EdgeH.DelKey(EId); + int ESize = GetEdge(EId).NeiNIdSH.Len(); + NEdges--; + N2Edges -= (ESize*(ESize-1))/2; + delete &GetEdge(EId); +} + +// Get a vector IDs of all nodes in the graph. +void THGraph::GetNIdV(TIntV& NIdV) const { + NIdV.Gen(GetNodes(), 0); + for (int N=NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) { + NIdV.Add(NodeH.GetKey(N)); } +} + +// Defragment the graph. +void THGraph::Defrag(const bool& OnlyNodeLinks) { + int nKey; + for (int n = EdgeH.FFirstKeyId(); EdgeH.FNextKeyId(n); ) { + nKey = EdgeH.GetKey(n); + if (! EdgeH.GetDat(nKey).NeiNIdSH.IsKeyIdEqKeyN()) { + EdgeH.GetDat(nKey).NeiNIdSH.Defrag(); + } + } + for (int n = NodeH.FFirstKeyId(); NodeH.FNextKeyId(n); ) { + nKey = NodeH.GetKey(n); + NodeH.GetDat(nKey).EIdV.Pack(); + if (! NodeH.GetDat(nKey).NbrNIdENumH.IsKeyIdEqKeyN()) { + NodeH.GetDat(nKey).NbrNIdENumH.Defrag(); + } + } + if (! OnlyNodeLinks) { + if (! NodeH.IsKeyIdEqKeyN()){ NodeH.Defrag(); } + if (! EdgeH.IsKeyIdEqKeyN()){ EdgeH.Defrag(); } + } +} + +void THGraph::PrintEdge(const int EId) { + if (! EdgeH.IsKey(EId)) { + printf("\nEdge Not Found!\n"); + } + TIntV NV; + TStr EStr("Edge nodes: "); + EdgeH.GetDat(EId).GetNodesV(NV); + for (int i = 0; i < NV.Len(); i++) { + EStr += (" " + NV[i].GetStr()); + } + EStr += "\n"; + printf(EStr.GetCStr()); +} + +// Print the graph in a human readable form to an output stream OutF. +void THGraph::Dump(FILE *OutF) const { + const int NodePlaces = (int) ceil(log10((double) GetNodes())); + int NKey; + for (int N = NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) { + NKey = NodeH.GetKey(N); + const TNode& Node = NodeH.GetDat(NKey); + fprintf(OutF, " %*d [%d] ", NodePlaces, Node.GetId(), Node.GetDeg()); + for (int edge = 0; edge < Node.GetDeg(); edge++) { + fprintf(OutF, " %*d", NodePlaces, Node.GetNbrNId(edge)); } + fprintf(OutF, "\n"); + } + fprintf(OutF, "\n"); +} + +// Return a small hypergraph on 5 nodes and 5 edges. +PHGraph THGraph::GetSmallGraph() { + PHGraph Graph = THGraph::New(); + for (int i = 0; i < 5; i++) { Graph->AddNode(i); } + TIntV EV(3); + int el[] = {0,1,3}; + for (int i = 0; i < 3; i++) + EV.Add(el[i]); + Graph->AddEdge(EV); + return Graph; +} diff --git a/snap-core/graph.h b/snap-core/graph.h index 13f51ab7e..8128edad2 100644 --- a/snap-core/graph.h +++ b/snap-core/graph.h @@ -3,12 +3,16 @@ class TUNGraph; class TBPGraph; +/// [Undirected] hypergraph +class THGraph; //TODO:class TUNEGraph; -- undirected multigraph /// Pointer to an undirected graph (TUNGraph) typedef TPt PUNGraph; /// Pointer to a bipartitegraph graph (TBPGraph) typedef TPt PBPGraph; +/// Pointer to a hypergraph graph (THGraph) +typedef TPt PHGraph; //#////////////////////////////////////////////// /// Directed graphs @@ -151,7 +155,7 @@ class TUNGraph { TUNGraph(TSIn& SIn) : MxNId(SIn), NEdges(SIn), NodeH(SIn) { } /// Saves the graph to a (binary) stream SOut. - void Save(TSOut& SOut) const { MxNId.Save(SOut); NEdges.Save(SOut); NodeH.Save(SOut); } + void Save(TSOut& SOut) const { MxNId.Save(SOut); NEdges.Save(SOut); NodeH.Save(SOut); SOut.Flush(); } /// Static constructor that returns a pointer to the graph. Call: PUNGraph Graph = TUNGraph::New(). static PUNGraph New() { return new TUNGraph(); } /// Static constructor that returns a pointer to the graph and reserves enough memory for Nodes nodes and Edges edges. ##TUNGraph::New @@ -199,6 +203,8 @@ class TUNGraph { int GetEdges() const; /// Adds an edge between node IDs SrcNId and DstNId to the graph. ##TUNGraph::AddEdge int AddEdge(const int& SrcNId, const int& DstNId); + /// Adds an edge between node IDs SrcNId and DstNId to the graph, ignores EId (for compatibility with TNEANet). + int AddEdge(const int& SrcNId, const int& DstNId, const int& EId) { return AddEdge(SrcNId, DstNId); } /// Adds an edge between node IDs SrcNId and DstNId to the graph. ##TUNGraph::AddEdgeUnchecked int AddEdgeUnchecked(const int& SrcNId, const int& DstNId); /// Adds an edge between node IDs SrcNId and DstNId to the graph. If nodes do not exists, create them. @@ -209,6 +215,8 @@ class TUNGraph { void DelEdge(const int& SrcNId, const int& DstNId); /// Tests whether an edge between node IDs SrcNId and DstNId exists in the graph. bool IsEdge(const int& SrcNId, const int& DstNId) const; + /// Tests whether an edge EId exists in the graph (for compatibility with TNEANet), always returns false. + bool IsEdge(const int& EId) const { return false; } /// Returns an iterator referring to the first edge in the graph. TEdgeI BegEI() const { TNodeI NI = BegNI(); TEdgeI EI(NI, EndNI(), 0); if (GetNodes() != 0 && (NI.GetOutDeg()==0 || NI.GetId()>NI.GetOutNId(0))) { EI++; } return EI; } /// Returns an iterator referring to the past-the-end edge in the graph. @@ -377,7 +385,7 @@ class TNGraph { /// Constructor that loads the graph from a (binary) stream SIn. TNGraph(TSIn& SIn) : MxNId(SIn), NodeH(SIn) { } /// Saves the graph to a (binary) stream SOut. - void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); } + void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); SOut.Flush(); } /// Static constructor that returns a pointer to the graph. Call: PNGraph Graph = TNGraph::New(). static PNGraph New() { return new TNGraph(); } /// Static constructor that returns a pointer to the graph and reserves enough memory for Nodes nodes and Edges edges. ##TNGraph::New @@ -428,6 +436,8 @@ class TNGraph { int GetEdges() const; /// Adds an edge from node SrcNId to node DstNId to the graph. ##TNGraph::AddEdge int AddEdge(const int& SrcNId, const int& DstNId); + /// Adds an edge between node IDs SrcNId and DstNId to the graph, ignores EId (for compatibility with TNEANet). + int AddEdge(const int& SrcNId, const int& DstNId, const int& EId) { return AddEdge(SrcNId, DstNId); } /// Adds an edge from node SrcNId to node DstNId to the graph. ##TNGraph::AddEdgeUnchecked int AddEdgeUnchecked(const int& SrcNId, const int& DstNId); /// Adds an edge from node IDs SrcNId to node DstNId to the graph. If nodes do not exist, create them. @@ -438,6 +448,8 @@ class TNGraph { void DelEdge(const int& SrcNId, const int& DstNId, const bool& IsDir = true); /// Tests whether an edge from node IDs SrcNId to DstNId exists in the graph. bool IsEdge(const int& SrcNId, const int& DstNId, const bool& IsDir = true) const; + /// Tests whether an edge EId exists in the graph (for compatibility with TNEANet), always returns false. + bool IsEdge(const int& EId) const { return false; } /// Returns an iterator referring to the first edge in the graph. TEdgeI BegEI() const { TNodeI NI=BegNI(); while(NI struct IsBipart { enum { Val = 1 }; }; } +//#////////////////////////////////////////////// +/// Hypergraph. +class THGraph { +public: + typedef THGraph TNet; + typedef TPt PNet; +public: + class TNode { + private: + TInt Id; + TStr Name; + TIntV EIdV; // Vector of Edge IDs + THash NbrNIdENumH; + public: + TNode() : Id(-1), Name(""), EIdV(), NbrNIdENumH() { } + TNode(const int& NId) : Id(NId), Name(""), EIdV(), NbrNIdENumH() { } + TNode(const int& NId, const TStr& NName) : Id(NId), Name(NName), EIdV(), NbrNIdENumH() { } + TNode(const TNode& Node) : Id(Node.Id), Name(Node.Name), EIdV(Node.EIdV), NbrNIdENumH(Node.NbrNIdENumH) { } + TNode(TSIn& SIn) : Id(SIn), Name(SIn), EIdV(SIn), NbrNIdENumH(SIn) { } + void Save(TSOut& SOut) const { Id.Save(SOut); Name.Save(SOut); EIdV.Save(SOut); NbrNIdENumH.Save(SOut);} + int GetId() const { return Id; } + TStr GetName() const { return Name; } + int GetNbrNodes() const { return NbrNIdENumH.Len(); } + void GetNbrNodes(TIntV& VNbrV) const { NbrNIdENumH.GetKeyV(VNbrV); } + void GetNbrEdges(TIntV& ENbrV) const { ENbrV = EIdV; } + int GetDeg() const { return EIdV.Len(); } + int GetInDeg() const { return GetDeg(); } + int GetOutDeg() const { return GetDeg(); } + int GetNbrEId(const int& NE) const { return EIdV[NE]; } // Returns N-th neighboring edge. + int GetNbrNId(const int& NN) const { return NbrNIdENumH.GetKey(NN); } // Returns N-th neighboring node. + bool IsNbrNId(const int& NId) const { return HasNeiN(NId); } + bool IsInNId(const int& NId) const { return HasNeiN(NId); } + bool IsOutNId(const int& NId) const { return HasNeiN(NId); } + void SortNIdV() { NbrNIdENumH.SortByKey();} + bool HasNeiN(const TNode &Node) const { return NbrNIdENumH.IsKey(Node.GetId()); } //Checks for a neighboring node Node. + bool HasNeiN(const int& NId) const { return NbrNIdENumH.IsKey(NId); } //Checks for a neighboring node Node. + void UpdEInfo(const int& EId, const TIntSet& ENodesHS); + void GetEIDs(TIntV& NeiEIdV) const { NeiEIdV=EIdV; } // Returns the edges containing the Node. + void GetEIDs(TIntSet& NeiEIdH) const {TIntSet EH(EIdV); NeiEIdH=EH; } // Returns the edges containing the Node. + int GetEdges() const { return GetDeg(); } // Returns the number of edges containing the Node. + int Get2Edges() const { return (NbrNIdENumH.Len() * (NbrNIdENumH.Len()-1))/2; } // Returns the number of edges containing the Node. + void AddNeighbor(const int& NId) { + if (NbrNIdENumH.IsKey(NId)) { + NbrNIdENumH.AddDat(NId, NbrNIdENumH.GetDat(NId)+1); + }else { + NbrNIdENumH.AddDat(NId,1); + } + } + int DelNeighbor(const int& NId) { + if (NbrNIdENumH.IsKey(NId)) { + if (NbrNIdENumH.GetDat(NId)>1) { + NbrNIdENumH.AddDat(NId, NbrNIdENumH.GetDat(NId)-1); + } else { + NbrNIdENumH.DelKey(NId); + } + } + return NbrNIdENumH.GetDat(NId); + } + bool operator == (const TNode& Node) const { + TIntV* ThisNNeiV; + TIntV* InpNNeiV; + GetNbrNodes(*ThisNNeiV); Node.GetNbrNodes(*InpNNeiV); + if (*ThisNNeiV == *InpNNeiV && EIdV == Node.EIdV) { + IAssertR(Id != Node.Id, "All node's neighbors are the same, but IDs don't match."); + IAssertR(Name.EqI(Node.Name), "All node's neighbors are the same, but Names don't match."); + return true; + } + return false; + } +// ~TNode() {} + friend class THGraph; + }; + /// Node Iterator + class TNodeI { + private: + typedef THash::TIter THashIter; + THashIter NodeHI; + public: + TNodeI() : NodeHI() { } + TNodeI(const THashIter& NodeHIter) : NodeHI(NodeHIter) { } + TNodeI(const TNodeI& NodeI) : NodeHI(NodeI.NodeHI) { } + TNodeI& operator = (const TNodeI& NodeI) { NodeHI = NodeI.NodeHI; return *this; } + TNodeI& operator++ (int) { NodeHI++; return *this; } + TNodeI& operator-- (int) { NodeHI--; return *this; } + bool operator < (const TNodeI& NodeI) const { return NodeHI < NodeI.NodeHI; } + bool operator == (const TNodeI& NodeI) const { return NodeHI == NodeI.NodeHI; } + /// Returns ID of the current node. + int GetId() const { return NodeHI.GetDat().GetId(); } + TStr GetName() const { return NodeHI.GetDat().GetName(); } + /// Returns number of neighboring nodes of the current node. + int GetNbrNodes() const { return NodeHI.GetDat().GetNbrNodes(); } + void GetNbrNodes(TIntV& VNbrV) const { NodeHI.GetDat().GetNbrNodes(VNbrV); } + /// Returns the ID on neighboring edges. + void GetEIDs(TIntV& NeiEIdV) { NodeHI.GetDat().GetEIDs(NeiEIdV); } + void GetEIDs(TIntSet& NeiEIdH) { NodeHI.GetDat().GetEIDs(NeiEIdH); } + /// Returns degree of the current node. + int GetDeg() const { return NodeHI.GetDat().GetDeg(); } + /// Returns in-degree of the current node (returns same as value GetDeg() since the graph is undirected). + int GetInDeg() const { return NodeHI.GetDat().GetInDeg(); } + /// Returns out-degree of the current node (returns same as value GetDeg() since the graph is undirected). + int GetOutDeg() const { return NodeHI.GetDat().GetOutDeg(); } + /// Returns ID of NodeN-th neighboring node. + int GetNbrNId(const int& NodeN) const { return NodeHI.GetDat().GetNbrNId(NodeN); } + /// Tests whether node with ID NId points to the current node. + bool HasNeiInN(const int& NId) const { return NodeHI.GetDat().IsInNId(NId); } + /// Tests whether the current node points to node with ID NId. + bool HasNeiOutN(const int& NId) const { return NodeHI.GetDat().IsOutNId(NId); } + /// Tests whether node with ID NId is a neighbor of the current node. + bool HasNeiN(const int& NId) const { return NodeHI.GetDat().IsNbrNId(NId); } + /// Returns number of [2]edges if being flatten to a regular graph. + int Get2Edges() const { return NodeHI.GetDat().Get2Edges(); } + /// Query a neighboring edge by Edge Id. + bool HasEdge(const int& EId) { + TIntV EV = NodeHI.GetDat().EIdV; + for (int i = 0; i < EV.Len(); i++) { + if (EId == EV[i]) { return true; } + return false; + } + } + friend class THGraph; + }; + class TEdge { + private: + TInt Id; + TIntSet NeiNIdSH; + THGraph* Graph; + public: + TEdge() { TEdge(NULL); } + TEdge(THGraph* GraphPt) : Id(-1), NeiNIdSH(), Graph(GraphPt) { } + TEdge(const int& EId, const TIntSet& NodesIDsH, THGraph* GraphPt) : Id(EId), NeiNIdSH(NodesIDsH), Graph(GraphPt) { } + TEdge(const int& EId, const TIntV& NodesIDsV, THGraph* GraphPt) : Id(EId), NeiNIdSH(NodesIDsV), Graph(GraphPt) { } + TEdge(const TEdge& Edge) : Id(Edge.Id), NeiNIdSH(Edge.NeiNIdSH), Graph(Edge.Graph) { } + TEdge(THGraph* GraphPt, const TIntSet& NodeIdsHS); + TEdge(THGraph* GraphPt, const TIntV& NodeIdsV); + TEdge(TSIn& SIn) : Id(SIn), NeiNIdSH(SIn), Graph(NULL) { } + TEdge(TSIn& SIn, THGraph* GraphPt) : Id(SIn), NeiNIdSH(SIn), Graph(GraphPt) { } + TEdge(const THashSet& NIdH, const int& EId) { + TIntV NIdV; + NIdH.GetKeyV(NIdV); + TEdge(EId, NIdV, Graph); + } + void Save(TSOut& SOut) const { Id.Save(SOut); NeiNIdSH.Save(SOut); } + /// Gets edge ID. + int GetId() const { return Id; } + /// Gets the number of including nodes. + int Len() const { return NeiNIdSH.Len(); } + /// Gets the nodes included in the edge. + void GetNodesV(TIntV& NeiV) const { NeiNIdSH.GetKeyV(NeiV); } + /// Gets a vector of including nodes' Ids. + void GetNbrNodes(TIntV& NIdsV) { NeiNIdSH.GetKeyV(NIdsV);} + bool HasNode(const TNode& Node) const { return NeiNIdSH.IsKey(Node.GetId()); } // Checks the edge for node Node. + void UpdNEInfo(const TIntSet& ENodesHS); +// ~TEdge() {} + friend class THGraph; + }; + /// Edge iterator. Only forward iteration (operator++) is supported. + class TEdgeI { + private: + typedef THash::TIter THashIter; + THashIter EdgeHI; + public: + TEdgeI() : EdgeHI() { } + TEdgeI(const THashIter& EdgeHIter) : EdgeHI(EdgeHIter) { } + TEdgeI(const TEdgeI& EdgeI) : EdgeHI(EdgeI.EdgeHI) { } + TEdgeI& operator = (const TEdgeI& EdgeI) { if (this!=&EdgeI) { EdgeHI=EdgeI.EdgeHI; } return *this; } + TEdgeI& operator ++ (int) { EdgeHI++; return *this; } + bool operator < (const TEdgeI& EdgeI) const { return EdgeHI < EdgeI.EdgeHI; } + bool operator == (const TEdgeI& EdgeI) const { return EdgeHI == EdgeI.EdgeHI; } + /// Gets edge ID. + int GetId() const { return EdgeHI.GetDat().GetId(); } + TEdge GetEdge() {return EdgeHI.GetDat();} + /// Gets the nodes included in the edge. + void GetNodesV(TIntV& NeiV) const { EdgeHI.GetDat().GetNodesV(NeiV); } + /// Get ID of Neighboring Nodes of the edge with id EId + void GetNbrNodes(TIntV& NIDV) { EdgeHI.GetDat().GetNbrNodes(NIDV); } + /// Gets the number of including nodes. + int Len() const { return EdgeHI.GetDat().Len(); } + int GetDeg() const { return Len(); } + friend class THGraph; + }; +private: + TCRef CRef; + TInt MxNId, MxEId, NEdges, N2Edges; + THash NodeH; + THash EdgeH; +private: + TNode& GetNode(const int& NId) { return NodeH.GetDat(NId); } + const TNode& GetNode(const int& NId) const { return NodeH.GetDat(NId); } + TEdge& GetEdge(const int& EId) { return EdgeH.GetDat(EId); } + const TEdge& GetEdge(const int& EId) const { return EdgeH.GetDat(EId); } + int AssertNodes(const TIntSet& NodesIS); + /// To be utilized for preventing addition of duplicate hyperedges. + static void TIntersect(TIntSet& S, const TIntSet& S2) { + /// S <- Intersect(S, S2) + TIntV MarkDel(S.Len(),0); //todo maybe remove if inneffective (comparing to before) + for (THashSetKeyI i = S.BegI(); i < S.EndI(); i++) { + if (!S2.IsKey(i.GetKey())) { MarkDel.Add(i.GetKey()); } + } + if (MarkDel.Len() > 0) { for (int j = 0; j < MarkDel.Len(); j++) S.DelKey(MarkDel[j]); } + } +public: + THGraph() : CRef(), MxNId(0), MxEId(0), NEdges(0), N2Edges(0), NodeH(), EdgeH() { } + /// Constructor that reserves enough memory for a graph of Nodes nodes and Edges edges. + explicit THGraph(const int& Nodes, const int& Edges) : MxNId(0), NEdges(0), N2Edges(0) { Reserve(Nodes, Edges); } + THGraph(const THGraph& Graph) : MxNId(Graph.MxNId), MxEId(Graph.MxEId), NEdges(Graph.NEdges), N2Edges(Graph.N2Edges), NodeH(Graph.NodeH), EdgeH(Graph.EdgeH) { } + /// Constructor that loads the graph from a (binary) stream SIn. + THGraph(TSIn& SIn) : MxNId(SIn), MxEId(SIn), NEdges(SIn), N2Edges(SIn), NodeH(SIn), EdgeH(SIn) { } + /// Saves the graph to a (binary) stream SOut. + void Save(TSOut& SOut) const { MxNId.Save(SOut); MxEId.Save(SOut); NEdges.Save(SOut); N2Edges.Save(SOut); NodeH.Save(SOut); EdgeH.Save(SOut); } + /// Static constructor that returns a pointer to the graph. Call: PUNGraph Graph = THGraph::New(). + static PHGraph New() { return new THGraph(); } + /// Static constructor that returns a pointer to the graph and reserves enough memory for Nodes nodes and Edges edges. + static PHGraph New(const int& Nodes, const int& Edges) { return new THGraph(Nodes, Edges); } + /// Static constructor that loads the graph from a stream SIn and returns a pointer to it. + static PHGraph Load(TSIn& SIn) { return PHGraph(new THGraph(SIn)); } + /// Allows for run-time checking the type of the graph (see the TGraphFlag for flags). + bool HasFlag(const TGraphFlag& Flag) const; + THGraph& operator = (const THGraph& Graph) { + if (this!=&Graph) { MxNId=Graph.MxNId; MxEId=Graph.MxEId; NEdges=Graph.NEdges; N2Edges=Graph.N2Edges; NodeH=Graph.NodeH; EdgeH=Graph.EdgeH; } return *this; } + /// Returns the number of nodes in the graph. + int GetNodes() const { return NodeH.Len(); } + /// Adds a node of ID NId to the network, noop if the node already exists. + int AddNodeUnchecked(int NId = -1, TStr NName = ""); + /// Adds a node of ID NId and Name NName to the graph. + int AddNode(int NId = -1, TStr NName = ""); + /// Adds a node of ID NodeI.GetId() to the graph. + int AddNode(const TNodeI& NodeI) { return AddNode(NodeI.GetId(), NodeI.GetName()); } + /// Deletes node of ID NId from the graph. + void DelNode(const int& NId); + /// Deletes node of ID NodeI.GetId() from the graph. + void DelNode(const TNode& NodeI) { DelNode(NodeI.GetId()); } + /// Tests whether ID NId is a node. + bool IsNode(const int& NId) const { return NodeH.IsKey(NId); } + /// Returns an iterator referring to the first node in the graph. + TNodeI BegNI() const { return TNodeI(NodeH.BegI()); } + /// Returns an iterator referring to the past-the-end node in the graph. + TNodeI EndNI() const { return TNodeI(NodeH.EndI()); } + /// Returns an iterator referring to the node of ID NId in the graph. + TNodeI GetNI(const int& NId) const { return TNodeI(NodeH.GetI(NId)); } + /// Returns an ID that is larger than any node ID in the graph. + int GetMxNId() const { return MxNId; } + int GetVNbrNodes(int& NId) const { return GetNode(NId).GetNbrNodes(); } + void GetVNbrEdges(int& NId, TIntV& EIDV) const { return GetNode(NId).GetNbrEdges(EIDV); } + /// Returns the number of edges in the graph. + int GetEdges() const { return EdgeH.Len(); } + /// Returns the number of equivalent 2-edges in the graph. + int Get2Edges() const { return N2Edges; } + /// Get ID of Neighboring Nodes of the edge with id EId + void GetENbrNodes(int EId, TIntV& NIDV) { GetEdge(EId).GetNbrNodes(NIDV); } + /// Adds an edge between the nodes in NodeIdsHS set + int AddEdge(const THash& NodeIdsHS){ + TIntV NIdV; + NodeIdsHS.GetKeyV(NIdV); + return AddEdge(NIdV); + } + int AddEdge(const TIntSet& NIdH, int& EId); + int AddEdge(const TIntSet& NIdH){ int _EId = -1; return AddEdge(NIdH, _EId); } + int AddEdge(const TIntV& NodeV) { TIntSet NodeIdsHS(NodeV); return AddEdge(NodeIdsHS); } + int AddEdge(const TEdgeI& EI){ + int _EId = EI.GetId(); + return AddEdge(EI.EdgeHI.GetDat().NeiNIdSH, _EId); + } + int AddEdge(const TEdgeI& EI, int& EId){ return AddEdge(EI.EdgeHI.GetDat().NeiNIdSH, EId); } + /// Deletes the edge with id=EId. + void DelEdge(const int& EId); + void DelEdge(const TEdge& Edge) { DelEdge(Edge.Id); } + /// Tests whether an edge with edge ID EId exists in the graph. + bool IsEdgeId(const int& EId) const { return EdgeH.IsKey(EId); } + /// Tests whether an edge exactly with the nodes specified in the input. + bool IsEdge(const TIntSet& NIdH); + /// Returns an iterator referring to the first edge in the graph. + TEdgeI BegEI() const { return TEdgeI(EdgeH.BegI()); } + /// Returns an iterator referring to the past-the-end edge in the graph. + TEdgeI EndEI() const { return TEdgeI(EdgeH.EndI()); } + /// Returns an iterator referring to edge with edge ID EId. + TEdgeI GetEI(const int& EId) const { return TEdgeI(EdgeH.GetI(EId)); } + /// Returns an ID of a random node in the graph. + int GetRndNId(TRnd& Rnd=TInt::Rnd) { return NodeH.GetKey(NodeH.GetRndKeyId(Rnd, 0.8)); } + /// Returns an interator referring to a random node in the graph. + TNodeI GetRndNI(TRnd& Rnd=TInt::Rnd) { return GetNI(GetRndNId(Rnd)); } + /// Returns an ID of a random edge in the graph. + int GetRndEId(TRnd& Rnd=TInt::Rnd) { return EdgeH.GetKey(EdgeH.GetRndKeyId(Rnd, 0.8)); } + /// Returns an interator referring to a random edge in the graph. + TEdgeI GetRndEI(TRnd& Rnd=TInt::Rnd) { return GetEI(GetRndEId(Rnd)); } + /// Returns a random edge in the graph. + TEdge GetRndEdge(TRnd& Rnd=TInt::Rnd) { return GetEdge(GetRndEId(Rnd)); } + /// Gets a vector IDs of all nodes in the graph. + void GetNIdV(TIntV& NIdV) const; + // Get a vector IDs of all edges in the graph. + void GetEIdV(TIntV& EIdV) const { EdgeH.GetKeyV(EIdV); } + /// Tests whether the graph is empty (has zero nodes). + bool Empty() const { return GetNodes()==0; } + /// Deletes all nodes and edges from the graph. + void Clr() { MxNId=0; MxEId=0; NEdges=0; N2Edges=0; NodeH.Clr(); EdgeH.Clr(); } + /// Reserves memory for a graph of Nodes nodes and Edges edges. + void Reserve(const int& Nodes, const int& Edges) { + if (Nodes>0) { NodeH.Gen(Nodes/2); } if (Edges>0) { EdgeH.Gen(Edges/2); } + } + /// Defragments the graph. + void Defrag(const bool& OnlyNodeLinks=false); + /// Checks the graph data structure for internal consistency. + bool IsOk(const bool& ThrowExcept=true) const; + /// Print the graph in a human readable form to an output stream OutF. + void Dump(FILE *OutF=stdout) const; + /// Returns a small graph on 5 nodes and 5 edges. + static PHGraph GetSmallGraph(); + void PrintEdge(const int EId); + friend class TPt; +}; + diff --git a/snap-core/gsvd.cpp b/snap-core/gsvd.cpp index fd8891570..83705ae4e 100644 --- a/snap-core/gsvd.cpp +++ b/snap-core/gsvd.cpp @@ -258,7 +258,7 @@ void GetSngVec(const PNGraph& Graph, TFltV& LeftSV, TFltV& RightSV) { IsAllValVNeg(RightSV, true); } -void GetSngVec(const PNGraph& Graph, const int& SngVecs, TFltV& SngValV, TVec& LeftSV, TVec& RightSV) { +void GetSngVec(const PNGraph& Graph, const int& SngVecs, TFltV& SngValV, TFltVFltV& LeftSV, TFltVFltV& RightSV) { const int Nodes = Graph->GetNodes(); SngValV.Clr(); LeftSV.Clr(); @@ -343,7 +343,8 @@ void GetEigVec(const PUNGraph& Graph, TFltV& EigVecV) { } // to get first few eigenvectors -void GetEigVec(const PUNGraph& Graph, const int& EigVecs, TFltV& EigValV, TVec& EigVecV) { +//void GetEigVec(const PUNGraph& Graph, const int& EigVecs, TFltV& EigValV, TVec& EigVecV) { +void GetEigVec(const PUNGraph& Graph, const int& EigVecs, TFltV& EigValV, TFltVFltV& EigVecV) { const int Nodes = Graph->GetNodes(); // Lanczos TUNGraphMtx GraphMtx(Graph); diff --git a/snap-core/gsvd.h b/snap-core/gsvd.h index dfc88c210..b350ad29c 100644 --- a/snap-core/gsvd.h +++ b/snap-core/gsvd.h @@ -56,14 +56,15 @@ void GetSngVals(const PNGraph& Graph, const int& SngVals, TFltV& SngValV); void GetSngVec(const PNGraph& Graph, TFltV& LeftSV, TFltV& RightSV); /// Computes the singular values and left and right singular vectors of the adjacency matrix representing a directed Graph. /// @param SngVecs Number of singular values/vectors to compute. -void GetSngVec(const PNGraph& Graph, const int& SngVecs, TFltV& SngValV, TVec& LeftSV, TVec& RightSV); +void GetSngVec(const PNGraph& Graph, const int& SngVecs, TFltV& SngValV, TFltVFltV& LeftSV, TFltVFltV& RightSV); /// Computes top EigVals eigenvalues of the adjacency matrix representing a given undirected Graph. void GetEigVals(const PUNGraph& Graph, const int& EigVals, TFltV& EigValV); /// Computes the leading eigenvector of the adjacency matrix representing a given undirected Graph. void GetEigVec(const PUNGraph& Graph, TFltV& EigVecV); /// Computes top EigVecs eigenvalues and eigenvectors of the adjacency matrix representing a given undirected Graph. -void GetEigVec(const PUNGraph& Graph, const int& EigVecs, TFltV& EigValV, TVec& EigVecV); +//void GetEigVec(const PUNGraph& Graph, const int& EigVecs, TFltV& EigValV, TVec& EigVecV); +void GetEigVec(const PUNGraph& Graph, const int& EigVecs, TFltV& EigValV, TFltVFltV& EigVecV); /// Computes Inverse participation ratio of a given graph. /// See Spectra of "real-world" graphs: Beyond the semicircle law by Farkas, Derenyi, Barabasi and Vicsek void GetInvParticipRat(const PUNGraph& Graph, int MaxEigVecs, int TimeLimit, TFltPrV& EigValIprV); diff --git a/snap-core/mmnet.h b/snap-core/mmnet.h index 17f6e4584..d08b1afe7 100644 --- a/snap-core/mmnet.h +++ b/snap-core/mmnet.h @@ -59,7 +59,7 @@ class TModeNet : public TNEANet { public: /// Saves the graph to a (binary) stream SOut. void Save(TSOut& SOut) const { - TNEANet::Save(SOut); ModeId.Save(SOut); NeighborTypes.Save(SOut); } + TNEANet::Save(SOut); ModeId.Save(SOut); NeighborTypes.Save(SOut); SOut.Flush(); } /// Loads graph from shared memory. void LoadShM(TShMIn & ShMIn) { TNEANet::LoadNetworkShM(ShMIn); @@ -336,7 +336,7 @@ class TCrossNet { /// Saves the TCrossNet to the binary stream. void Save(TSOut& SOut) const { CrossH.Save(SOut); MxEId.Save(SOut); Mode1.Save(SOut); Mode2.Save(SOut); IsDirect.Save(SOut); CrossNetId.Save(SOut); KeyToIndexTypeE.Save(SOut); IntDefaultsE.Save(SOut); StrDefaultsE.Save(SOut); FltDefaultsE.Save(SOut); VecOfIntVecsE.Save(SOut); - VecOfStrVecsE.Save(SOut); VecOfFltVecsE.Save(SOut); } + VecOfStrVecsE.Save(SOut); VecOfFltVecsE.Save(SOut); SOut.Flush(); } /// Loads network from shared memory stream. void LoadShM(TShMIn& ShMIn) { CrossH.LoadShM(ShMIn); @@ -601,9 +601,9 @@ class TMMNet { int DelCrossNet(const TStr& CrossNet); /// Saves the TMMNet to binary stream. - void Save(TSOut& SOut) const {MxModeId.Save(SOut); MxCrossNetId.Save(SOut); TModeNetH.Save(SOut); + void Save(TSOut& SOut) const { MxModeId.Save(SOut); MxCrossNetId.Save(SOut); TModeNetH.Save(SOut); TCrossNetH.Save(SOut); ModeIdToNameH.Save(SOut); ModeNameToIdH.Save(SOut); CrossIdToNameH.Save(SOut); - CrossNameToIdH.Save(SOut); } + CrossNameToIdH.Save(SOut); SOut.Flush(); } /// Loads the TMMNet from binary stream. static PMMNet Load(TSIn& SIn) { return PMMNet(new TMMNet(SIn)); } /// Loads network from mmapped shared memory. diff --git a/snap-core/network.cpp b/snap-core/network.cpp index 2cbaae15a..9d401682d 100644 --- a/snap-core/network.cpp +++ b/snap-core/network.cpp @@ -32,10 +32,14 @@ void TNEANet::LoadNetworkShM(TShMIn& ShMIn) { LoadVecOfVecFunctor vec_of_vec_fn; VecOfIntVecVecsN.LoadShM(ShMIn, vec_of_vec_fn); VecOfIntVecVecsE.LoadShM(ShMIn, vec_of_vec_fn); + VecOfFltVecVecsN.LoadShM(ShMIn, vec_of_vec_fn); + VecOfFltVecVecsE.LoadShM(ShMIn, vec_of_vec_fn); LoadHashOfVecFunctor hash_of_vec_fn; VecOfIntHashVecsN.LoadShM(ShMIn, hash_of_vec_fn); VecOfIntHashVecsE.LoadShM(ShMIn, hash_of_vec_fn); + VecOfFltHashVecsN.LoadShM(ShMIn, hash_of_vec_fn); + VecOfFltHashVecsE.LoadShM(ShMIn, hash_of_vec_fn); /* Attributes are complicated so load these straight */ SAttrN.Load(ShMIn); @@ -137,6 +141,37 @@ void TNEANet::IntVAttrValueNI(const TInt& NId, TStrIntPrH::TIter NodeHI, TVec(); + while (!NodeHI.IsEnd()) { + if (NodeHI.GetDat().Val1 == FltVType) { + Names.Add(NodeHI.GetKey()); + } + NodeHI++; + } +} + +void TNEANet::FltVAttrValueNI(const TInt& NId, TStrIntPrH::TIter NodeHI, TVec& Values) const { + Values = TVec(); + while (!NodeHI.IsEnd()) { + if (NodeHI.GetDat().Val1 == FltVType) { + TInt index = NodeHI.GetDat().Val2; + TStr attr = NodeHI.GetKey(); + TInt loc = CheckDenseOrSparseN(attr); + if (loc == 1) { + TFltV val = this->VecOfFltVecVecsN.GetVal(index).GetVal(NodeH.GetKeyId(NId)); + if (val.Len() != 0) Values.Add(val); + } else { + const THash& NewHash = VecOfFltHashVecsN[index]; + if (NewHash.IsKey(NodeH.GetKeyId(NId))) { + Values.Add(NewHash[NodeH.GetKeyId(NId)]); + } + } + } + NodeHI++; + } +} + void TNEANet::StrAttrNameNI(const TInt& NId, TStrIntPrH::TIter NodeHI, TStrV& Names) const { Names = TVec(); while (!NodeHI.IsEnd()) { @@ -184,7 +219,8 @@ bool TNEANet::IsAttrDeletedN(const int& NId, const TStr& attr) const { bool StrDel = IsStrAttrDeletedN(NId, attr); bool FltDel = IsFltAttrDeletedN(NId, attr); bool IntVDel = IsIntVAttrDeletedN(NId, attr); - return IntDel || StrDel || FltDel || IntVDel; + bool FltVDel = IsFltVAttrDeletedN(NId, attr); + return IntDel || StrDel || FltDel || IntVDel || FltVDel; } bool TNEANet::IsIntAttrDeletedN(const int& NId, const TStr& attr) const { @@ -195,6 +231,10 @@ bool TNEANet::IsIntVAttrDeletedN(const int& NId, const TStr& attr) const { return NodeAttrIsIntVDeleted(NId, KeyToIndexTypeN.GetI(attr)); } +bool TNEANet::IsFltVAttrDeletedN(const int& NId, const TStr& attr) const { + return NodeAttrIsFltVDeleted(NId, KeyToIndexTypeN.GetI(attr)); +} + bool TNEANet::IsStrAttrDeletedN(const int& NId, const TStr& attr) const { return NodeAttrIsStrDeleted(NId, KeyToIndexTypeN.GetI(attr)); } @@ -227,6 +267,14 @@ bool TNEANet::NodeAttrIsIntVDeleted(const int& NId, const TStrIntPrH::TIter& Nod this->KeyToIndexTypeN.GetDat(NodeHI.GetKey()).Val2).GetVal(NodeH.GetKeyId(NId))); } +bool TNEANet::NodeAttrIsFltVDeleted(const int& NId, const TStrIntPrH::TIter& NodeHI) const { + if (NodeHI.GetDat().Val1 != FltVType) { + return false; + } + return (TFltV() == this->VecOfFltVecVecsN.GetVal( + this->KeyToIndexTypeN.GetDat(NodeHI.GetKey()).Val2).GetVal(NodeH.GetKeyId(NId))); +} + bool TNEANet::NodeAttrIsStrDeleted(const int& NId, const TStrIntPrH::TIter& NodeHI) const { if (NodeHI.GetDat().Val1 != StrType) { return false; @@ -291,7 +339,7 @@ void TNEANet::IntAttrValueEI(const TInt& EId, TStrIntPrH::TIter EdgeHI, TIntV& V Values = TVec(); while (!EdgeHI.IsEnd()) { if (EdgeHI.GetDat().Val1 == IntType && !EdgeAttrIsIntDeleted(EId, EdgeHI)) { - TInt val = (this->VecOfIntVecsE.GetVal(EdgeHI.GetDat().Val2).GetVal(EId)); + TInt val = (this->VecOfIntVecsE[EdgeHI.GetDat().Val2].GetVal(EdgeH.GetKeyId(EId))); Values.Add(val); } EdgeHI++; @@ -329,6 +377,37 @@ void TNEANet::IntVAttrValueEI(const TInt& EId, TStrIntPrH::TIter EdgeHI, TVec(); + while (!EdgeHI.IsEnd()) { + if (EdgeHI.GetDat().Val1 == FltVType) { + Names.Add(EdgeHI.GetKey()); + } + EdgeHI++; + } +} + +void TNEANet::FltVAttrValueEI(const TInt& EId, TStrIntPrH::TIter EdgeHI, TVec& Values) const { + Values = TVec(); + while (!EdgeHI.IsEnd()) { + if (EdgeHI.GetDat().Val1 == FltVType) { + TInt index = EdgeHI.GetDat().Val2; + TStr attr = EdgeHI.GetKey(); + TInt loc = CheckDenseOrSparseE(attr); + if (loc == 1) { + TFltV val = this->VecOfFltVecVecsE.GetVal(index).GetVal(EdgeH.GetKeyId(EId)); + if (val.Len() != 0) Values.Add(val); + } else { + const THash& NewHash = VecOfFltHashVecsE[index]; + if (NewHash.IsKey(EdgeH.GetKeyId(EId))) { + Values.Add(NewHash[EdgeH.GetKeyId(EId)]); + } + } + } + EdgeHI++; + } +} + void TNEANet::StrAttrNameEI(const TInt& EId, TStrIntPrH::TIter EdgeHI, TStrV& Names) const { Names = TVec(); while (!EdgeHI.IsEnd()) { @@ -376,7 +455,8 @@ bool TNEANet::IsAttrDeletedE(const int& EId, const TStr& attr) const { bool IntVDel = IsIntVAttrDeletedE(EId, attr); bool StrDel = IsStrAttrDeletedE(EId, attr); bool FltDel = IsFltAttrDeletedE(EId, attr); - return IntDel || StrDel || FltDel || IntVDel; + bool FltVDel = IsFltVAttrDeletedE(EId, attr); + return IntDel || StrDel || FltDel || IntVDel || FltVDel; } bool TNEANet::IsIntAttrDeletedE(const int& EId, const TStr& attr) const { @@ -387,6 +467,10 @@ bool TNEANet::IsIntVAttrDeletedE(const int& EId, const TStr& attr) const { return EdgeAttrIsIntVDeleted(EId, KeyToIndexTypeE.GetI(attr)); } +bool TNEANet::IsFltVAttrDeletedE(const int& EId, const TStr& attr) const { + return EdgeAttrIsFltVDeleted(EId, KeyToIndexTypeE.GetI(attr)); +} + bool TNEANet::IsStrAttrDeletedE(const int& EId, const TStr& attr) const { return EdgeAttrIsStrDeleted(EId, KeyToIndexTypeE.GetI(attr)); } @@ -400,7 +484,8 @@ bool TNEANet::EdgeAttrIsDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) bool IntVDel = EdgeAttrIsIntVDeleted(EId, EdgeHI); bool StrDel = EdgeAttrIsStrDeleted(EId, EdgeHI); bool FltDel = EdgeAttrIsFltDeleted(EId, EdgeHI); - return IntDel || StrDel || FltDel || IntVDel; + bool FltVDel = EdgeAttrIsFltVDeleted(EId, EdgeHI); + return IntDel || StrDel || FltDel || IntVDel || FltVDel; } bool TNEANet::EdgeAttrIsIntDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) const { @@ -415,6 +500,12 @@ bool TNEANet::EdgeAttrIsIntVDeleted(const int& EId, const TStrIntPrH::TIter& Edg this->KeyToIndexTypeE.GetDat(EdgeHI.GetKey()).Val2).GetVal(EdgeH.GetKeyId(EId))); } +bool TNEANet::EdgeAttrIsFltVDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) const { + return (EdgeHI.GetDat().Val1 == FltVType && + TFltV() == this->VecOfFltVecVecsE.GetVal( + this->KeyToIndexTypeE.GetDat(EdgeHI.GetKey()).Val2).GetVal(EdgeH.GetKeyId(EId))); +} + bool TNEANet::EdgeAttrIsStrDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) const { return (EdgeHI.GetDat().Val1 == StrType && GetStrAttrDefaultE(EdgeHI.GetKey()) == this->VecOfStrVecsE.GetVal( @@ -525,6 +616,15 @@ int TNEANet::AddAttributes(const int NId) { IntVecV.Ins(KeyId, TIntV()); } } + for (i = 0; i < VecOfFltVecVecsN.Len(); i++) { + TVec& FltVecV = VecOfFltVecVecsN[i]; + int KeyId = NodeH.GetKeyId(NId); + if (FltVecV.Len() > KeyId) { + FltVecV[KeyId] = TFltV(); + } else { + FltVecV.Ins(KeyId, TFltV()); + } + } return NId; } @@ -555,13 +655,24 @@ void TNEANet::DelNode(const int& NId) { TVec& IntVecV = VecOfIntVecVecsE[i]; IntVecV[EdgeH.GetKeyId(EId)] = TIntV(); } - EdgeH.DelKey(EId); + for (i = 0; i < VecOfFltVecVecsE.Len(); i++) { + TVec& FltVecV = VecOfFltVecVecsE[i]; + FltVecV[EdgeH.GetKeyId(EId)] = TFltV(); + } for (i = 0; i < VecOfIntHashVecsE.Len(); i++) { THash& IntHashV = VecOfIntHashVecsE[i]; if (IntHashV.IsKey(EdgeH.GetKeyId(EId))) { IntHashV.DelKey(EdgeH.GetKeyId(EId)); } } + for (i = 0; i < VecOfFltHashVecsE.Len(); i++) { + THash& FltHashV = VecOfFltHashVecsE[i]; + if (FltHashV.IsKey(EdgeH.GetKeyId(EId))) { + FltHashV.DelKey(EdgeH.GetKeyId(EId)); + } + } + EdgeH.DelKey(EId); + } for (int in = 0; in < Node.GetInDeg(); in++) { const int EId = Node.GetInEId(in); @@ -585,12 +696,22 @@ void TNEANet::DelNode(const int& NId) { TVec& IntVecV = VecOfIntVecVecsE[i]; IntVecV[EdgeH.GetKeyId(EId)] = TIntV(); } + for (i = 0; i < VecOfFltVecVecsE.Len(); i++) { + TVec& FltVecV = VecOfFltVecVecsE[i]; + FltVecV[EdgeH.GetKeyId(EId)] = TFltV(); + } for (i = 0; i < VecOfIntHashVecsE.Len(); i++) { THash& IntHashV = VecOfIntHashVecsE[i]; if (IntHashV.IsKey(EdgeH.GetKeyId(EId))) { IntHashV.DelKey(EdgeH.GetKeyId(EId)); } } + for (i = 0; i < VecOfFltHashVecsE.Len(); i++) { + THash& FltHashV = VecOfFltHashVecsE[i]; + if (FltHashV.IsKey(EdgeH.GetKeyId(EId))) { + FltHashV.DelKey(EdgeH.GetKeyId(EId)); + } + } EdgeH.DelKey(EId); } @@ -610,12 +731,22 @@ void TNEANet::DelNode(const int& NId) { TVec& IntVecV = VecOfIntVecVecsN[i]; IntVecV[NodeH.GetKeyId(NId)] = TIntV(); } + for (i = 0; i < VecOfFltVecVecsN.Len(); i++) { + TVec& FltVecV = VecOfFltVecVecsN[i]; + FltVecV[NodeH.GetKeyId(NId)] = TFltV(); + } for (i = 0; i < VecOfIntHashVecsN.Len(); i++) { THash& IntHashV = VecOfIntHashVecsN[i]; if (IntHashV.IsKey(NodeH.GetKeyId(NId))) { IntHashV.DelKey(NodeH.GetKeyId(NId)); } } + for (i = 0; i < VecOfFltHashVecsN.Len(); i++) { + THash& FltHashV = VecOfFltHashVecsN[i]; + if (FltHashV.IsKey(NodeH.GetKeyId(NId))) { + FltHashV.DelKey(NodeH.GetKeyId(NId)); + } + } NodeH.DelKey(NId); } @@ -653,6 +784,11 @@ int TNEANet::AddEdge(const int& SrcNId, const int& DstNId, int EId) { IntVecV.Ins(EdgeH.GetKeyId(EId), TIntV()); } + for (i = 0; i < VecOfFltVecVecsE.Len(); i++) { + TVec& FltVecV = VecOfFltVecVecsE[i]; + FltVecV.Ins(EdgeH.GetKeyId(EId), TFltV()); + } + for (i = 0; i < VecOfStrVecsE.Len(); i++) { TVec& StrVec = VecOfStrVecsE[i]; int KeyId = EdgeH.GetKeyId(EId); @@ -728,6 +864,10 @@ void TNEANet::DelEdge(const int& SrcNId, const int& DstNId, const bool& IsDir) { } bool TNEANet::IsEdge(const int& SrcNId, const int& DstNId, int& EId, const bool& IsDir) const { + if (! IsNode(SrcNId) || ! IsNode(DstNId)) { + return false; + } + const TNode& SrcNode = GetNode(SrcNId); for (int edge = 0; edge < SrcNode.GetOutDeg(); edge++) { const TEdge& Edge = GetEdge(SrcNode.GetOutEId(edge)); @@ -872,6 +1012,7 @@ void TNEANet::Dump(FILE *OutF) const { for (int i = 0; i < IntAttrE.Len(); i++) { fprintf(OutF, " %*i", EdgePlaces, IntAttrE[i]()); } + TStrV StrAttrE; StrAttrValueEI(EdgeI.GetId(), StrAttrE); fprintf(OutF, " eas[%d]", StrAttrE.Len()); @@ -937,6 +1078,31 @@ int TNEANet::AddIntVAttrDatN(const int& NId, const TIntV& value, const TStr& att return 0; } +int TNEANet::AddFltVAttrDatN(const int& NId, const TFltV& value, const TStr& attr, TBool UseDense) { + if (!IsNode(NId)) { + // AddNode(NId); + return -1; + } + + TInt location = CheckDenseOrSparseN(attr); + if (location==-1) { + AddFltVAttrN(attr, UseDense); + location = CheckDenseOrSparseN(attr); + } + + if (UseDense) { + IAssertR(location != 0, TStr::Fmt("NodeId %d exists for %s in sparse representation", NId, attr.CStr())); + TVec& NewVec = VecOfFltVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2]; + NewVec[NodeH.GetKeyId(NId)] = value; + } else { + IAssertR(location != 1, TStr::Fmt("NodeId %d exists for %s in dense representation", NId, attr.CStr())); + THash& NewHash = VecOfFltHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2]; + NewHash.AddDat(NodeH.GetKeyId(NId), value); + } + + return 0; +} + int TNEANet::AppendIntVAttrDatN(const int& NId, const TInt& value, const TStr& attr, TBool UseDense) { if (!IsNode(NId)) { // AddNode(NId); @@ -959,6 +1125,32 @@ int TNEANet::AppendIntVAttrDatN(const int& NId, const TInt& value, const TStr& a return 0; } + +int TNEANet::AppendFltVAttrDatN(const int& NId, const TFlt& value, const TStr& attr, TBool UseDense) { + if (!IsNode(NId)) { + // AddNode(NId); + return -1; + } + + TInt location = CheckDenseOrSparseN(attr); + + + if (location==-1) { + AddFltVAttrN(attr, UseDense); + location = CheckDenseOrSparseN(attr); + } + if (UseDense) { + IAssertR(location != 0, TStr::Fmt("NodeId %d exists for %s in sparse representation", NId, attr.CStr())); + TVec& NewVec = VecOfFltVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2]; + NewVec[NodeH.GetKeyId(NId)].Add(value); + } else { + IAssertR(location != 1, TStr::Fmt("NodeId %d exists for %s in dense representation", NId, attr.CStr())); + THash& NewHash = VecOfFltHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2]; + NewHash[NodeH.GetKeyId(NId)].Add(value); + } + return 0; +} + int TNEANet::DelFromIntVAttrDatN(const int& NId, const TInt& value, const TStr& attr) { TInt CurrLen; if (!IsNode(NId)) { @@ -984,6 +1176,32 @@ int TNEANet::DelFromIntVAttrDatN(const int& NId, const TInt& value, const TStr& return 0; } + +int TNEANet::DelFromFltVAttrDatN(const int& NId, const TFlt& value, const TStr& attr) { + TInt CurrLen; + if (!IsNode(NId)) { + // AddNode(NId); + return -1; + } + TInt location = CheckDenseOrSparseN(attr); + if (location != -1) { + if (location == 1) { + TVec& NewVec = VecOfFltVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2]; + if (!NewVec[NodeH.GetKeyId(NId)].DelIfIn(value)) { + return -1; + } + } else { + THash& NewHash = VecOfFltHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2]; + if (!NewHash[NodeH.GetKeyId(NId)].DelIfIn(value)) { + return -1; + } + } + } else { + return -1; + } + return 0; +} + int TNEANet::AddStrAttrDatN(const int& NId, const TStr& value, const TStr& attr) { int i; TInt CurrLen; @@ -1055,7 +1273,7 @@ int TNEANet::AddIntAttrDatE(const int& EId, const TInt& value, const TStr& attr) } int TNEANet::AddIntVAttrDatE(const int& EId, const TIntV& value, const TStr& attr, TBool UseDense) { - if (!IsNode(EId)) { + if (!IsEdge(EId)) { // AddNode(NId); return -1; } @@ -1076,8 +1294,32 @@ int TNEANet::AddIntVAttrDatE(const int& EId, const TIntV& value, const TStr& att return 0; } + +int TNEANet::AddFltVAttrDatE(const int& EId, const TFltV& value, const TStr& attr, TBool UseDense) { + if (!IsEdge(EId)) { + // AddNode(NId); + return -1; + } + TInt location = CheckDenseOrSparseE(attr); + + if (location==-1) { + AddFltVAttrE(attr, UseDense); + location = CheckDenseOrSparseE(attr); + } + if (UseDense) { + IAssertR(location != 0, TStr::Fmt("EdgeID %d exists for %s in sparse representation", EId, attr.CStr())); + TVec& NewVec = VecOfFltVecVecsE[KeyToIndexTypeE.GetDat(attr).Val2]; + NewVec[EdgeH.GetKeyId(EId)] = value; + } else { + IAssertR(location != 1, TStr::Fmt("NodeId %d exists for %s in dense representation", EId, attr.CStr())); + THash& NewHash = VecOfFltHashVecsE[KeyToIndexTypeE.GetDat(attr).Val2]; + NewHash.AddDat(EdgeH.GetKeyId(EId), value); + } + return 0; +} + int TNEANet::AppendIntVAttrDatE(const int& EId, const TInt& value, const TStr& attr, TBool UseDense) { - if (!IsNode(EId)) { + if (!IsEdge(EId)) { // AddNode(NId); return -1; } @@ -1095,6 +1337,26 @@ int TNEANet::AppendIntVAttrDatE(const int& EId, const TInt& value, const TStr& a return 0; } + +int TNEANet::AppendFltVAttrDatE(const int& EId, const TFlt& value, const TStr& attr, TBool UseDense) { + if (!IsEdge(EId)) { + // AddNode(NId); + return -1; + } + TInt location = CheckDenseOrSparseE(attr); + if (location==-1) return -1; + if (UseDense) { + IAssertR(location != 0, TStr::Fmt("Edge %d exists for %s in sparse representation", EId, attr.CStr())); + TVec& NewVec = VecOfFltVecVecsE[KeyToIndexTypeE.GetDat(attr).Val2]; + NewVec[EdgeH.GetKeyId(EId)].Add(value); + } else { + IAssertR(location != 1, TStr::Fmt("Edge %d exists for %s in dense representation", EId, attr.CStr())); + THash& NewHash = VecOfFltHashVecsE[KeyToIndexTypeE.GetDat(attr).Val2]; + NewHash[EdgeH.GetKeyId(EId)].Add(value); + } + return 0; +} + int TNEANet::AddStrAttrDatE(const int& EId, const TStr& value, const TStr& attr) { int i; TInt CurrLen; @@ -1160,6 +1422,13 @@ TIntV TNEANet::GetIntVAttrDatN(const int& NId, const TStr& attr) const { else return VecOfIntHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)]; } + +TFltV TNEANet::GetFltVAttrDatN(const int& NId, const TStr& attr) const { + TInt location = CheckDenseOrSparseN(attr); + if (location != 0) return VecOfFltVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)]; + else return VecOfFltHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)]; +} + TStr TNEANet::GetStrAttrDatN(const int& NId, const TStr& attr) { return VecOfStrVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)]; } @@ -1198,6 +1467,13 @@ TIntV TNEANet::GetIntVAttrDatE(const int& EId, const TStr& attr) { else return VecOfIntHashVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)]; } + +TFltV TNEANet::GetFltVAttrDatE(const int& EId, const TStr& attr) { + TInt location = CheckDenseOrSparseE(attr); + if (location != 0) return VecOfFltVecVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)]; + else return VecOfFltHashVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)]; +} + TStr TNEANet::GetStrAttrDatE(const int& EId, const TStr& attr) { return VecOfStrVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)]; } @@ -1226,6 +1502,7 @@ int TNEANet::GetAttrIndE(const TStr& attr) { return KeyToIndexTypeE.GetDat(attr).Val2.Val; } + int TNEANet::DelAttrDatN(const int& NId, const TStr& attr) { TInt vecType = KeyToIndexTypeN(attr).Val1; if (vecType == IntType) { @@ -1238,6 +1515,10 @@ int TNEANet::DelAttrDatN(const int& NId, const TStr& attr) { TInt location = CheckDenseOrSparseN(attr); if (location == 0) VecOfIntHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)] = TIntV(); else VecOfIntVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)] = TIntV(); + } else if (vecType == FltVType) { // added by Avery + TInt location = CheckDenseOrSparseN(attr); + if (location == 0) VecOfFltHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)] = TFltV(); + else VecOfFltVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2][NodeH.GetKeyId(NId)] = TFltV(); } else { return -1; } @@ -1257,6 +1538,10 @@ int TNEANet::DelAttrDatE(const int& EId, const TStr& attr) { TInt location = CheckDenseOrSparseE(attr); if (location == 0) VecOfIntHashVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)] = TIntV(); else VecOfIntVecVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)] = TIntV(); + } else if (vecType == FltVType) { + TInt location = CheckDenseOrSparseE(attr); + if (location == 0) VecOfFltHashVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)] = TFltV(); + else VecOfFltVecVecsE[KeyToIndexTypeE.GetDat(attr).Val2][EdgeH.GetKeyId(EId)] = TFltV(); } else { return -1; } @@ -1300,6 +1585,24 @@ int TNEANet::AddIntVAttrN(const TStr& attr, TBool UseDense){ return 0; } +int TNEANet::AddFltVAttrN(const TStr& attr, TBool UseDense){ + TInt CurrLen; + if (UseDense) { + CurrLen = VecOfFltVecVecsN.Len(); + KeyToIndexTypeN.AddDat(attr, TIntPr(FltVType, CurrLen)); + KeyToDenseN.AddDat(attr, true); + TVec NewVec = TVec(MxNId); + VecOfFltVecVecsN.Add(NewVec); + } else { + CurrLen = VecOfFltHashVecsN.Len(); + KeyToIndexTypeN.AddDat(attr, TIntPr(FltVType, CurrLen)); + KeyToDenseN.AddDat(attr, false); + THash NewHash; + VecOfFltHashVecsN.Add(NewHash); + } + return 0; +} + int TNEANet::AddStrAttrN(const TStr& attr, TStr defaultValue) { int i; TInt CurrLen; @@ -1377,6 +1680,24 @@ int TNEANet::AddIntVAttrE(const TStr& attr, TBool UseDense){ return 0; } +int TNEANet::AddFltVAttrE(const TStr& attr, TBool UseDense){ + TInt CurrLen; + if (UseDense) { + CurrLen = VecOfFltVecVecsE.Len(); + KeyToIndexTypeE.AddDat(attr, TIntPr(FltVType, CurrLen)); + KeyToDenseE.AddDat(attr, true); + TVec NewVec = TVec(MxEId); + VecOfFltVecVecsE.Add(NewVec); + } else { + CurrLen = VecOfFltHashVecsE.Len(); + KeyToIndexTypeE.AddDat(attr, TIntPr(FltVType, CurrLen)); + KeyToDenseE.AddDat(attr, false); + THash NewHash; + VecOfFltHashVecsE.Add(NewHash); + } + return 0; +} + int TNEANet::AddStrAttrE(const TStr& attr, TStr defaultValue) { int i; TInt CurrLen; @@ -1437,6 +1758,11 @@ int TNEANet::DelAttrN(const TStr& attr) { if (location == 1) VecOfIntVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2] = TVec(); else VecOfIntHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2] = THash(); KeyToDenseN.DelKey(attr); + } else if (vecType == FltVType) { + TInt location = CheckDenseOrSparseN(attr); + if (location == 1) VecOfFltVecVecsN[KeyToIndexTypeN.GetDat(attr).Val2] = TVec(); + else VecOfFltHashVecsN[KeyToIndexTypeN.GetDat(attr).Val2] = THash(); + KeyToDenseN.DelKey(attr); } else { return -1; } diff --git a/snap-core/network.h b/snap-core/network.h index c61a0f15b..63bca22b7 100644 --- a/snap-core/network.h +++ b/snap-core/network.h @@ -159,7 +159,7 @@ class TNodeNet { TNodeNet(TSIn& SIn) : MxNId(SIn), NodeH(SIn) { } virtual ~TNodeNet() { } /// Saves the network to a (binary) stream SOut. - virtual void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); } + virtual void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); SOut.Flush(); } /// Static constructor that returns a pointer to the network. Call: TPt > Net = TNodeNet::New(). static PNet New() { return PNet(new TNodeNet()); } /// Static constructor that loads the network from a stream SIn and returns a pointer to it. @@ -608,7 +608,7 @@ class TNodeEDatNet { TNodeEDatNet(TSIn& SIn) : MxNId(SIn), NodeH(SIn) { } virtual ~TNodeEDatNet() { } /// Saves the network to a (binary) stream SOut. - virtual void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); } + virtual void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); SOut.Flush(); } /// Static constructor that returns a pointer to the network. Call: TPt > Net = TNodeEDatNet::New(). static PNet New() { return PNet(new TNet()); } /// Static constructor that loads the network from a stream SIn and returns a pointer to it. @@ -1183,7 +1183,7 @@ class TNodeEdgeNet { TNodeEdgeNet(TSIn& SIn) : MxNId(SIn), MxEId(SIn), NodeH(SIn), EdgeH(SIn) { } virtual ~TNodeEdgeNet() { } /// Saves the network to a (binary) stream SOut. - virtual void Save(TSOut& SOut) const { MxNId.Save(SOut); MxEId.Save(SOut); NodeH.Save(SOut); EdgeH.Save(SOut); } + virtual void Save(TSOut& SOut) const { MxNId.Save(SOut); MxEId.Save(SOut); NodeH.Save(SOut); EdgeH.Save(SOut); SOut.Flush(); } /// Static constructor that returns a pointer to the network. ##TNodeEdgeNet::New() static PNet New() { return PNet(new TNet()); } /// Static constructor that loads the network from a stream SIn and returns a pointer to it. @@ -1794,6 +1794,31 @@ class TNEANet { friend class TNEANet; }; + class TAFltVI { + private: + typedef TVec::TIter TFltVVecIter; + TFltVVecIter HI; + bool IsDense; + typedef THash::TIter TFltHVecIter; + TFltHVecIter HHI; + bool isNode; + TStr attr; + const TNEANet *Graph; + public: + TAFltVI() : HI(), IsDense(), HHI(), attr(), Graph(NULL) { } + TAFltVI(const TFltVVecIter& HIter, const TFltHVecIter& HHIter, TStr attribute, bool isEdgeIter, const TNEANet* GraphPt, bool is_dense) : HI(HIter), IsDense(is_dense), HHI(HHIter), attr(), Graph(GraphPt) { + isNode = !isEdgeIter; attr = attribute; + } + TAFltVI(const TAFltVI& I) : HI(I.HI), IsDense(I.IsDense), HHI(I.HHI), attr(I.attr), Graph(I.Graph) { isNode = I.isNode; } + TAFltVI& operator = (const TAFltVI& I) { HI = I.HI; HHI = I.HHI, Graph=I.Graph; isNode = I.isNode; attr = I.attr; return *this; } + bool operator < (const TAFltVI& I) const { return HI == I.HI ? HHI < I.HHI : HI < I.HI; } + bool operator == (const TAFltVI& I) const { return HI == I.HI && HHI == I.HHI; } + /// Returns an attribute of the node. + TFltV GetDat() const { return IsDense? HI[0] : HHI.GetDat(); } + TAFltVI& operator++(int) { if (IsDense) {HI++;} else {HHI++;} return *this; } + friend class TNEANet; + }; + /// Node/edge string attribute iterator. Iterates through all nodes/edges for one string attribute. class TAStrI { private: @@ -1878,8 +1903,10 @@ class TNEANet { TVec VecOfStrVecsN, VecOfStrVecsE; TVec VecOfFltVecsN, VecOfFltVecsE; TVec > VecOfIntVecVecsN, VecOfIntVecVecsE; + TVec > VecOfFltVecVecsN, VecOfFltVecVecsE; TVec > VecOfIntHashVecsN, VecOfIntHashVecsE; - enum { IntType, StrType, FltType, IntVType }; + TVec > VecOfFltHashVecsN, VecOfFltHashVecsE; + enum { IntType, StrType, FltType, IntVType, FltVType }; TAttr SAttrN; TAttr SAttrE; @@ -1938,27 +1965,39 @@ class TNEANet { StrDefaultsN(), StrDefaultsE(), FltDefaultsN(), FltDefaultsE(), VecOfIntVecsN(), VecOfIntVecsE(), VecOfStrVecsN(), VecOfStrVecsE(), VecOfFltVecsN(), VecOfFltVecsE(), VecOfIntVecVecsN(), VecOfIntVecVecsE(), - VecOfIntHashVecsN(), VecOfIntHashVecsE(), SAttrN(), SAttrE(){ } + VecOfFltVecVecsN(), VecOfFltVecVecsE(), + VecOfIntHashVecsN(), VecOfIntHashVecsE(), + VecOfFltHashVecsN(), VecOfFltHashVecsE(), + SAttrN(), SAttrE(){ } /// Constructor that reserves enough memory for a graph of nodes and edges. explicit TNEANet(const int& Nodes, const int& Edges) : CRef(), MxNId(0), MxEId(0), NodeH(), EdgeH(), KeyToIndexTypeN(), KeyToIndexTypeE(), KeyToDenseN(), KeyToDenseE(), IntDefaultsN(), IntDefaultsE(), StrDefaultsN(), StrDefaultsE(), FltDefaultsN(), FltDefaultsE(), VecOfIntVecsN(), VecOfIntVecsE(), VecOfStrVecsN(), VecOfStrVecsE(), VecOfFltVecsN(), VecOfFltVecsE(), VecOfIntVecVecsN(), VecOfIntVecVecsE(), - VecOfIntHashVecsN(), VecOfIntHashVecsE(), SAttrN(), SAttrE() + VecOfFltVecVecsN(), VecOfFltVecVecsE(), + VecOfIntHashVecsN(), VecOfIntHashVecsE(), + VecOfFltHashVecsN(), VecOfFltHashVecsE(), + SAttrN(), SAttrE() { Reserve(Nodes, Edges); } TNEANet(const TNEANet& Graph) : MxNId(Graph.MxNId), MxEId(Graph.MxEId), NodeH(Graph.NodeH), EdgeH(Graph.EdgeH), KeyToIndexTypeN(), KeyToIndexTypeE(), KeyToDenseN(), KeyToDenseE(), IntDefaultsN(), IntDefaultsE(), StrDefaultsN(), StrDefaultsE(), FltDefaultsN(), FltDefaultsE(), VecOfIntVecsN(), VecOfIntVecsE(), VecOfStrVecsN(), VecOfStrVecsE(), VecOfFltVecsN(), VecOfFltVecsE(), VecOfIntVecVecsN(), VecOfIntVecVecsE(), - VecOfIntHashVecsN(), VecOfIntHashVecsE(), SAttrN(), SAttrE() { } + VecOfFltVecVecsN(), VecOfFltVecVecsE(), + VecOfIntHashVecsN(), VecOfIntHashVecsE(), + VecOfFltHashVecsN(), VecOfFltHashVecsE(), + SAttrN(), SAttrE() { } /// Constructor for loading the graph from a (binary) stream SIn. TNEANet(TSIn& SIn) : MxNId(SIn), MxEId(SIn), NodeH(SIn), EdgeH(SIn), KeyToIndexTypeN(SIn), KeyToIndexTypeE(SIn), KeyToDenseN(SIn), KeyToDenseE(SIn), IntDefaultsN(SIn), IntDefaultsE(SIn), StrDefaultsN(SIn), StrDefaultsE(SIn), FltDefaultsN(SIn), FltDefaultsE(SIn), VecOfIntVecsN(SIn), VecOfIntVecsE(SIn), VecOfStrVecsN(SIn),VecOfStrVecsE(SIn), - VecOfFltVecsN(SIn), VecOfFltVecsE(SIn), VecOfIntVecVecsN(SIn), VecOfIntVecVecsE(SIn), VecOfIntHashVecsN(SIn), VecOfIntHashVecsE(SIn), + VecOfFltVecsN(SIn), VecOfFltVecsE(SIn), VecOfIntVecVecsN(SIn), VecOfIntVecVecsE(SIn), + VecOfFltVecVecsN(SIn), VecOfFltVecVecsE(SIn), + VecOfIntHashVecsN(SIn), VecOfIntHashVecsE(SIn), + VecOfFltHashVecsN(SIn), VecOfFltHashVecsE(SIn), SAttrN(SIn), SAttrE(SIn) { } protected: TNEANet(const TNEANet& Graph, bool modeSubGraph) : MxNId(Graph.MxNId), MxEId(Graph.MxEId), @@ -1966,14 +2005,22 @@ class TNEANet { IntDefaultsN(Graph.IntDefaultsN), IntDefaultsE(Graph.IntDefaultsE), StrDefaultsN(Graph.StrDefaultsN), StrDefaultsE(Graph.StrDefaultsE), FltDefaultsN(Graph.FltDefaultsN), FltDefaultsE(Graph.FltDefaultsE), VecOfIntVecsN(Graph.VecOfIntVecsN), VecOfIntVecsE(Graph.VecOfIntVecsE), VecOfStrVecsN(Graph.VecOfStrVecsN), VecOfStrVecsE(Graph.VecOfStrVecsE), VecOfFltVecsN(Graph.VecOfFltVecsN), VecOfFltVecsE(Graph.VecOfFltVecsE), - VecOfIntVecVecsN(), VecOfIntVecVecsE(Graph.VecOfIntVecVecsE), VecOfIntHashVecsN(), VecOfIntHashVecsE(Graph.VecOfIntHashVecsE) { } + VecOfIntVecVecsN(), VecOfIntVecVecsE(Graph.VecOfIntVecVecsE), + VecOfFltVecVecsN(), VecOfFltVecVecsE(Graph.VecOfFltVecVecsE), + VecOfIntHashVecsN(), VecOfIntHashVecsE(Graph.VecOfIntHashVecsE), + VecOfFltHashVecsN(), VecOfFltHashVecsE(Graph.VecOfFltHashVecsE) + { } TNEANet(bool copyAll, const TNEANet& Graph) : MxNId(Graph.MxNId), MxEId(Graph.MxEId), NodeH(Graph.NodeH), EdgeH(Graph.EdgeH), KeyToIndexTypeN(Graph.KeyToIndexTypeN), KeyToIndexTypeE(Graph.KeyToIndexTypeE), KeyToDenseN(Graph.KeyToDenseN), KeyToDenseE(Graph.KeyToDenseE), IntDefaultsN(Graph.IntDefaultsN), IntDefaultsE(Graph.IntDefaultsE), StrDefaultsN(Graph.StrDefaultsN), StrDefaultsE(Graph.StrDefaultsE), FltDefaultsN(Graph.FltDefaultsN), FltDefaultsE(Graph.FltDefaultsE), VecOfIntVecsN(Graph.VecOfIntVecsN), VecOfIntVecsE(Graph.VecOfIntVecsE), VecOfStrVecsN(Graph.VecOfStrVecsN), VecOfStrVecsE(Graph.VecOfStrVecsE), VecOfFltVecsN(Graph.VecOfFltVecsN), VecOfFltVecsE(Graph.VecOfFltVecsE), - VecOfIntVecVecsN(Graph.VecOfIntVecVecsN), VecOfIntVecVecsE(Graph.VecOfIntVecVecsE), VecOfIntHashVecsN(Graph.VecOfIntHashVecsN), VecOfIntHashVecsE(Graph.VecOfIntHashVecsE), SAttrN(Graph.SAttrN), SAttrE(Graph.SAttrE) { } - // virtual ~TNEANet() { } + VecOfIntVecVecsN(Graph.VecOfIntVecVecsN), VecOfIntVecVecsE(Graph.VecOfIntVecVecsE), + VecOfFltVecVecsN(Graph.VecOfFltVecVecsN), VecOfFltVecVecsE(Graph.VecOfFltVecVecsE), + VecOfIntHashVecsN(Graph.VecOfIntHashVecsN), VecOfIntHashVecsE(Graph.VecOfIntHashVecsE), + VecOfFltHashVecsN(Graph.VecOfFltHashVecsN), VecOfFltHashVecsE(Graph.VecOfFltHashVecsE), + SAttrN(Graph.SAttrN), SAttrE(Graph.SAttrE) { } + // virtual ~TNEANet() { }cd .. public: /// Saves the graph to a (binary) stream SOut. Expects data structures for sparse attributes. void Save(TSOut& SOut) const { @@ -1987,8 +2034,11 @@ class TNEANet { VecOfStrVecsN.Save(SOut); VecOfStrVecsE.Save(SOut); VecOfFltVecsN.Save(SOut); VecOfFltVecsE.Save(SOut); VecOfIntVecVecsN.Save(SOut); VecOfIntVecVecsE.Save(SOut); + VecOfFltVecVecsN.Save(SOut); VecOfFltVecVecsE.Save(SOut); VecOfIntHashVecsN.Save(SOut); VecOfIntHashVecsE.Save(SOut); - SAttrN.Save(SOut); SAttrE.Save(SOut); } + VecOfFltHashVecsN.Save(SOut); VecOfFltHashVecsE.Save(SOut); + SAttrN.Save(SOut); SAttrE.Save(SOut); + SOut.Flush(); } /// Saves the graph to a (binary) stream SOut. Available for backwards compatibility. void Save_V1(TSOut& SOut) const { MxNId.Save(SOut); MxEId.Save(SOut); NodeH.Save(SOut); EdgeH.Save(SOut); @@ -1998,7 +2048,8 @@ class TNEANet { FltDefaultsN.Save(SOut); FltDefaultsE.Save(SOut); VecOfIntVecsN.Save(SOut); VecOfIntVecsE.Save(SOut); VecOfStrVecsN.Save(SOut); VecOfStrVecsE.Save(SOut); - VecOfFltVecsN.Save(SOut); VecOfFltVecsE.Save(SOut); } + VecOfFltVecsN.Save(SOut); VecOfFltVecsE.Save(SOut); + SOut.Flush(); } /// Saves the graph without any sparse data structures. Available for backwards compatibility void Save_V2(TSOut& SOut) const { MxNId.Save(SOut); MxEId.Save(SOut); NodeH.Save(SOut); EdgeH.Save(SOut); @@ -2010,7 +2061,9 @@ class TNEANet { VecOfStrVecsN.Save(SOut); VecOfStrVecsE.Save(SOut); VecOfFltVecsN.Save(SOut); VecOfFltVecsE.Save(SOut); VecOfIntVecVecsN.Save(SOut); VecOfIntVecVecsE.Save(SOut); - SAttrN.Save(SOut); SAttrE.Save(SOut); } + VecOfFltVecVecsN.Save(SOut); VecOfFltVecVecsE.Save(SOut); + SAttrN.Save(SOut); SAttrE.Save(SOut); + SOut.Flush(); } /// Static cons returns pointer to graph. Ex: PNEANet Graph=TNEANet::New(). static PNEANet New() { return PNEANet(new TNEANet()); } /// Static constructor that returns a pointer to the graph and reserves enough memory for Nodes nodes and Edges edges. ##TNEANet::New @@ -2028,7 +2081,7 @@ class TNEANet { Graph->FltDefaultsN.Load(SIn); Graph->FltDefaultsE.Load(SIn); Graph->VecOfIntVecsN.Load(SIn); Graph->VecOfIntVecsE.Load(SIn); Graph->VecOfStrVecsN.Load(SIn); Graph->VecOfStrVecsE.Load(SIn); - Graph->VecOfFltVecsN.Load(SIn); Graph->VecOfFltVecsE.Load(SIn); + Graph->VecOfFltVecsN.Load(SIn); Graph->VecOfFltVecsE.Load(SIn); return Graph; } @@ -2045,6 +2098,7 @@ class TNEANet { Graph->VecOfStrVecsN.Load(SIn); Graph->VecOfStrVecsE.Load(SIn); Graph->VecOfFltVecsN.Load(SIn); Graph->VecOfFltVecsE.Load(SIn); Graph->VecOfIntVecVecsN.Load(SIn); Graph->VecOfIntVecVecsE.Load(SIn); + Graph->VecOfFltVecVecsN.Load(SIn); Graph->VecOfFltVecVecsE.Load(SIn); Graph->SAttrN.Load(SIn); Graph->SAttrE.Load(SIn); return Graph; } @@ -2058,7 +2112,7 @@ class TNEANet { return PNEANet(Network); } - void ConvertToSparse() { + void ConvertToSparse() { TInt VecLength = VecOfIntVecVecsN.Len(); THash::TIter iter; if (VecLength != 0) { @@ -2095,6 +2149,42 @@ class TNEANet { } } VecOfIntVecVecsE.Clr(); + + VecLength = VecOfFltVecVecsN.Len(); + if (VecLength != 0) { + VecOfFltHashVecsN = TVec >(VecLength); + for (iter = KeyToIndexTypeN.BegI(); !iter.IsEnd(); iter=iter.Next()) { + if (iter.GetDat().Val1 == FltVType) { + TStr attribute = iter.GetKey(); + TInt index = iter.GetDat().Val2(); + for (int i=0; i 0) { + VecOfFltHashVecsN[index].AddDat(TInt(i), VecOfFltVecVecsN[index][i]); + } + } + KeyToDenseN.AddDat(attribute, TBool(false)); + } + } + } + VecOfFltVecVecsN.Clr(); + + VecLength = VecOfFltVecVecsE.Len(); + if (VecLength != 0) { + VecOfFltHashVecsE = TVec >(VecLength); + for (iter = KeyToIndexTypeE.BegI(); !iter.IsEnd(); iter=iter.Next()) { + if (iter.GetDat().Val1 == FltVType) { + TStr attribute = iter.GetKey(); + TInt index = iter.GetDat().Val2(); + for (int i=0; i 0) { + VecOfFltHashVecsE[index].AddDat(TInt(i), VecOfFltVecVecsE[index][i]); + } + } + KeyToDenseE.AddDat(attribute, TBool(false)); + } + } + } + VecOfFltVecVecsE.Clr(); } @@ -2189,8 +2279,60 @@ class TNEANet { return TAIntVI(HI, HHI, attr, false, this, IsDense); } + /// Returns an iterator referring to the first node's flt attribute. + TAFltVI BegNAFltVI(const TStr& attr) const { + TVec::TIter HI = NULL; + THash::TIter HHI; + TInt location = CheckDenseOrSparseN(attr); + TBool IsDense = true; + if (location != -1) { + TInt index = KeyToIndexTypeN.GetDat(attr).Val2; + if (location == 1) { + HI = VecOfFltVecVecsN[index].BegI(); + } else { + IsDense = false; + HHI = VecOfFltHashVecsN[index].BegI(); + } + } + return TAFltVI(HI, HHI, attr, false, this, IsDense); + } + /// Returns an iterator referring to the past-the-end node's attribute. + TAFltVI EndNAFltVI(const TStr& attr) const { + TVec::TIter HI = NULL; + THash::TIter HHI; + TInt location = CheckDenseOrSparseN(attr); + TBool IsDense = true; + if (location != -1) { + TInt index = KeyToIndexTypeN.GetDat(attr).Val2; + if (location == 1) { + HI = VecOfFltVecVecsN[index].EndI(); + } else { + IsDense = false; + HHI = VecOfFltHashVecsN[index].EndI(); + } + } + return TAFltVI(HI, HHI, attr, false, this, IsDense); + } + /// Returns an iterator referring to the node of ID NId in the graph. + TAFltVI GetNAFltVI(const TStr& attr, const int& NId) const { + TVec::TIter HI = NULL; + THash::TIter HHI; + TInt location = CheckDenseOrSparseN(attr); + TBool IsDense = true; + if (location != -1) { + TInt index = KeyToIndexTypeN.GetDat(attr).Val2; + if (location == 1) { + HI = VecOfFltVecVecsN[index].GetI(NodeH.GetKeyId(NId)); + } else { + IsDense = false; + HHI = VecOfFltHashVecsN[index].GetI(NodeH.GetKeyId(NId)); + } + } + return TAFltVI(HI, HHI, attr, false, this, IsDense); + } + /// Returns an iterator referring to the first node's str attribute. TAStrI BegNAStrI(const TStr& attr) const { @@ -2239,6 +2381,15 @@ class TNEANet { IntVAttrValueNI(NId, KeyToIndexTypeN.BegI(), Values);} void IntVAttrValueNI(const TInt& NId, TStrIntPrH::TIter NodeHI, TVec& Values) const; + /// Returns a vector of flt attr names for node NId. + void FltVAttrNameNI(const TInt& NId, TStrV& Names) const { + FltVAttrNameNI(NId, KeyToIndexTypeN.BegI(), Names);} + void FltVAttrNameNI(const TInt& NId, TStrIntPrH::TIter NodeHI, TStrV& Names) const; + /// Returns a vector of flt values for node NId. + void FltVAttrValueNI(const TInt& NId, TVec& Values) const { + FltVAttrValueNI(NId, KeyToIndexTypeN.BegI(), Values);} + void FltVAttrValueNI(const TInt& NId, TStrIntPrH::TIter NodeHI, TVec& Values) const; + /// Returns a vector of str attr names for node NId. void StrAttrNameNI(const TInt& NId, TStrV& Names) const { @@ -2284,6 +2435,15 @@ class TNEANet { IntVAttrValueEI(EId, KeyToIndexTypeE.BegI(), Values);} void IntVAttrValueEI(const TInt& EId, TStrIntPrH::TIter EdgeHI, TVec& Values) const; + /// Returns a vector of flt attr names for edge EId. + void FltVAttrNameEI(const TInt& EId, TStrV& Names) const { + FltVAttrNameEI(EId, KeyToIndexTypeE.BegI(), Names);} + void FltVAttrNameEI(const TInt& EId, TStrIntPrH::TIter EdgeHI, TStrV& Names) const; + /// Returns a vector of attr values for edge EId. + void FltVAttrValueEI(const TInt& EId, TVec& Values) const { + FltVAttrValueEI(EId, KeyToIndexTypeE.BegI(), Values);} + void FltVAttrValueEI(const TInt& EId, TStrIntPrH::TIter EdgeHI, TVec& Values) const; + /// Returns a vector of str attr names for node NId. void StrAttrNameEI(const TInt& EId, TStrV& Names) const { @@ -2367,6 +2527,58 @@ class TNEANet { return TAIntVI(HI, HHI, attr, true, this, IsDense); } + /// Returns an iterator referring to the first edge's int attribute. + TAFltVI BegEAFltVI(const TStr& attr) const { + TVec::TIter HI = NULL; + THash::TIter HHI; + TInt location = CheckDenseOrSparseE(attr); + TBool IsDense = true; + if (location != -1) { + TInt index = KeyToIndexTypeE.GetDat(attr).Val2; + if (location == 1) { + HI = VecOfFltVecVecsE[index].BegI(); + } else { + IsDense = false; + HHI = VecOfFltHashVecsE[index].BegI(); + } + } + return TAFltVI(HI, HHI, attr, true, this, IsDense); + } + /// Returns an iterator referring to the past-the-end edge's attribute. + TAFltVI EndEAFltVI(const TStr& attr) const { + TVec::TIter HI = NULL; + THash::TIter HHI; + TInt location = CheckDenseOrSparseE(attr); + TBool IsDense = true; + if (location != -1) { + TInt index = KeyToIndexTypeE.GetDat(attr).Val2; + if (location == 1) { + HI = VecOfFltVecVecsE[index].EndI(); + } else { + IsDense = false; + HHI = VecOfFltHashVecsE[index].EndI(); + } + } + return TAFltVI(HI, HHI, attr, true, this, IsDense); + } + /// Returns an iterator referring to the edge of ID EId in the graph. + TAFltVI GetEAFltVI(const TStr& attr, const int& EId) const { + TVec::TIter HI = NULL; + THash::TIter HHI; + TInt location = CheckDenseOrSparseE(attr); + TBool IsDense = true; + if (location != -1) { + TInt index = KeyToIndexTypeE.GetDat(attr).Val2; + if (location == 1) { + HI = VecOfFltVecVecsE[index].GetI(EdgeH.GetKeyId(EId)); + } else { + IsDense = false; + HHI = VecOfFltHashVecsE[index].GetI(EdgeH.GetKeyId(EId)); + } + } + return TAFltVI(HI, HHI, attr, true, this, IsDense); + } + /// Returns an iterator referring to the first edge's str attribute. TAStrI BegEAStrI(const TStr& attr) const { return TAStrI(VecOfStrVecsE[KeyToIndexTypeE.GetDat(attr).Val2].BegI(), attr, true, this); } @@ -2443,6 +2655,7 @@ class TNEANet { StrDefaultsN.Clr(); StrDefaultsE.Clr(); FltDefaultsN.Clr(); FltDefaultsE.Clr(); VecOfIntVecsN.Clr(); VecOfIntVecsE.Clr(); VecOfStrVecsN.Clr(); VecOfStrVecsE.Clr(); VecOfFltVecsN.Clr(); VecOfFltVecsE.Clr(); VecOfIntVecVecsN.Clr(); VecOfIntVecVecsE.Clr(); + VecOfFltVecVecsN.Clr(); VecOfFltVecVecsE.Clr(); SAttrN.Clr(); SAttrE.Clr();} /// Reserves memory for a graph of Nodes nodes and Edges edges. void Reserve(const int& Nodes, const int& Edges) { @@ -2454,24 +2667,40 @@ class TNEANet { /// Print the graph in a human readable form to an output stream OutF. void Dump(FILE *OutF=stdout) const; - /// Attribute based add function for attr to Int value. ##TNEANet::AddIntAttrDatN + /// Attribute based add function for attr to Int value. int AddIntAttrDatN(const TNodeI& NodeI, const TInt& value, const TStr& attr) { return AddIntAttrDatN(NodeI.GetId(), value, attr); } int AddIntAttrDatN(const int& NId, const TInt& value, const TStr& attr); - /// Attribute based add function for attr to Str value. ##TNEANet::AddStrAttrDatN + /// Attribute based add function for attr to Str value. int AddStrAttrDatN(const TNodeI& NodeI, const TStr& value, const TStr& attr) { return AddStrAttrDatN(NodeI.GetId(), value, attr); } int AddStrAttrDatN(const int& NId, const TStr& value, const TStr& attr); - /// Attribute based add function for attr to Flt value. ##TNEANet::AddFltAttrDatN + /// Attribute based add function for attr to Flt value. int AddFltAttrDatN(const TNodeI& NodeI, const TFlt& value, const TStr& attr) { return AddFltAttrDatN(NodeI.GetId(), value, attr); } int AddFltAttrDatN(const int& NId, const TFlt& value, const TStr& attr); - /// Attribute based add function for attr to IntV value. ##TNEANet::AddIntVAttrDatN + /// Attribute based add function for attr to IntV value. int AddIntVAttrDatN(const TNodeI& NodeI, const TIntV& value, const TStr& attr) { return AddIntVAttrDatN(NodeI.GetId(), value, attr); } int AddIntVAttrDatN(const int& NId, const TIntV& value, const TStr& attr, TBool UseDense=true); + /// Attribute based add function for attr to FltV value. + int AddFltVAttrDatN(const TNodeI& NodeI, const TFltV& value, const TStr& attr) { return AddFltVAttrDatN(NodeI.GetId(), value, attr); } + int AddFltVAttrDatN(const int& NId, const TFltV& value, const TStr& attr, TBool UseDense=true); + + + /// Appends value onto the TIntV attribute for the given node. int AppendIntVAttrDatN(const TNodeI& NodeI, const TInt& value, const TStr& attr) { return AppendIntVAttrDatN(NodeI.GetId(), value, attr); } int AppendIntVAttrDatN(const int& NId, const TInt& value, const TStr& attr, TBool UseDense=true); /// Deletes value from the TIntV attribute for the given node. int DelFromIntVAttrDatN(const TNodeI& NodeI, const TInt& value, const TStr& attr) { return DelFromIntVAttrDatN(NodeI.GetId(), value, attr); } int DelFromIntVAttrDatN(const int& NId, const TInt& value, const TStr& attr); + + /// Appends value onto the TFltV attribute for the given node. + int AppendFltVAttrDatN(const TNodeI& NodeI, const TFlt& value, const TStr& attr) { return AppendFltVAttrDatN(NodeI.GetId(), value, attr); } + int AppendFltVAttrDatN(const int& NId, const TFlt& value, const TStr& attr, TBool UseDense=true); + /// Deletes value from the TFltV attribute for the given node. + int DelFromFltVAttrDatN(const TNodeI& NodeI, const TFlt& value, const TStr& attr) { return DelFromFltVAttrDatN(NodeI.GetId(), value, attr); } + int DelFromFltVAttrDatN(const int& NId, const TFlt& value, const TStr& attr); + + + /// Attribute based add function for attr to Int value. ##TNEANet::AddIntAttrDatE int AddIntAttrDatE(const TEdgeI& EdgeI, const TInt& value, const TStr& attr) { return AddIntAttrDatE(EdgeI.GetId(), value, attr); } int AddIntAttrDatE(const int& EId, const TInt& value, const TStr& attr); @@ -2481,12 +2710,22 @@ class TNEANet { /// Attribute based add function for attr to Flt value. ##TNEANet::AddFltAttrDatE int AddFltAttrDatE(const TEdgeI& EdgeI, const TFlt& value, const TStr& attr) { return AddFltAttrDatE(EdgeI.GetId(), value, attr); } int AddFltAttrDatE(const int& EId, const TFlt& value, const TStr& attr); + + /// Attribute based add function for attr to IntV value. ##TNEANet::AddIntVAttrDatE int AddIntVAttrDatE(const TEdgeI& EdgeI, const TIntV& value, const TStr& attr) { return AddIntVAttrDatE(EdgeI.GetId(), value, attr); } int AddIntVAttrDatE(const int& EId, const TIntV& value, const TStr& attr, TBool UseDense=true); /// Appends value onto the TIntV attribute for the given node. int AppendIntVAttrDatE(const TEdgeI& EdgeI, const TInt& value, const TStr& attr) { return AppendIntVAttrDatE(EdgeI.GetId(), value, attr); } int AppendIntVAttrDatE(const int& EId, const TInt& value, const TStr& attr, TBool UseDense=true); + + /// Attribute based add function for attr to TFltV value. ##TNEANet::AddFltVAttrDatE + int AddFltVAttrDatE(const TEdgeI& EdgeI, const TFltV& value, const TStr& attr) { return AddFltVAttrDatE(EdgeI.GetId(), value, attr); } + int AddFltVAttrDatE(const int& EId, const TFltV& value, const TStr& attr, TBool UseDense=true); + /// Appends value onto the TFltV attribute for the given node. + int AppendFltVAttrDatE(const TEdgeI& EdgeI, const TFlt& value, const TStr& attr) { return AppendFltVAttrDatE(EdgeI.GetId(), value, attr); } + int AppendFltVAttrDatE(const int& EId, const TFlt& value, const TStr& attr, TBool UseDense=true); + /// Gets the value of int attr from the node attr value vector. TInt GetIntAttrDatN(const TNodeI& NodeI, const TStr& attr) { return GetIntAttrDatN(NodeI.GetId(), attr); } TInt GetIntAttrDatN(const int& NId, const TStr& attr); @@ -2501,6 +2740,10 @@ class TNEANet { TIntV GetIntVAttrDatN(const TNodeI& NodeI, const TStr& attr) const { return GetIntVAttrDatN(NodeI.GetId(), attr); } TIntV GetIntVAttrDatN(const int& NId, const TStr& attr) const; + /// Gets the value of the fltv attr from the node attr value vector. + TFltV GetFltVAttrDatN(const TNodeI& NodeI, const TStr& attr) const { return GetFltVAttrDatN(NodeI.GetId(), attr); } + TFltV GetFltVAttrDatN(const int& NId, const TStr& attr) const; + /// Gets the index of the node attr value vector specified by \c attr (same as GetAttrIndN for compatibility reasons). int GetIntAttrIndN(const TStr& attr); /// Gets the index of the node attr value vector specified by \c attr. @@ -2534,6 +2777,10 @@ class TNEANet { TIntV GetIntVAttrDatE(const TEdgeI& EdgeI, const TStr& attr) { return GetIntVAttrDatE(EdgeI.GetId(), attr); } TIntV GetIntVAttrDatE(const int& EId, const TStr& attr); + /// Gets the value of the fltv attr from the edge attr value vector. + TFltV GetFltVAttrDatE(const TEdgeI& EdgeI, const TStr& attr) { return GetFltVAttrDatE(EdgeI.GetId(), attr); } + TFltV GetFltVAttrDatE(const int& EId, const TStr& attr); + /// Gets the index of the edge attr value vector specified by \c attr (same as GetAttrIndE for compatibility reasons). int GetIntAttrIndE(const TStr& attr); /// Gets the index of the edge attr value vector specified by \c attr. @@ -2570,6 +2817,9 @@ class TNEANet { /// Adds a new IntV node attribute to the hashmap. int AddIntVAttrN(const TStr& attr, TBool UseDense=true); + /// Adds a new FltV node attribute to the hashmap. + int AddFltVAttrN(const TStr& attr, TBool UseDense=true); + /// Adds a new Int edge attribute to the hashmap. int AddIntAttrE(const TStr& attr, TInt defaultValue=TInt::Mn); /// Adds a new Str edge attribute to the hashmap. @@ -2579,6 +2829,9 @@ class TNEANet { /// Adds a new IntV edge attribute to the hashmap. int AddIntVAttrE(const TStr& attr, TBool UseDense=true); + /// Adds a new FltV edge attribute to the hashmap. + int AddFltVAttrE(const TStr& attr, TBool UseDense=true); + /// Removes all the values for node attr. int DelAttrN(const TStr& attr); /// Removes all the values for edge attr. @@ -2590,6 +2843,8 @@ class TNEANet { bool IsIntAttrDeletedN(const int& NId, const TStr& attr) const; /// Returns true if IntV \c attr exists for node \c NId and is an empty vector. bool IsIntVAttrDeletedN(const int& NId, const TStr& attr) const; + /// Returns true if FltV \c attr exists for node \c NId and is an empty vector. + bool IsFltVAttrDeletedN(const int& NId, const TStr& attr) const; /// Returns true if Str \c attr exists for node \c NId and has default value. bool IsStrAttrDeletedN(const int& NId, const TStr& attr) const; /// Returns true if Flt \c attr exists for node \c NId and has default value. @@ -2601,6 +2856,8 @@ class TNEANet { bool NodeAttrIsIntDeleted(const int& NId, const TStrIntPrH::TIter& NodeHI) const; /// Returns true if NId attr deleted value for current node int vector attr iterator. bool NodeAttrIsIntVDeleted(const int& NId, const TStrIntPrH::TIter& NodeHI) const; + /// Returns true if NId attr deleted value for current node int vector attr iterator. + bool NodeAttrIsFltVDeleted(const int& NId, const TStrIntPrH::TIter& NodeHI) const; /// Returns true if NId attr deleted value for current node str attr iterator. bool NodeAttrIsStrDeleted(const int& NId, const TStrIntPrH::TIter& NodeHI) const; /// Returns true if NId attr deleted value for current node flt attr iterator. @@ -2612,6 +2869,8 @@ class TNEANet { bool IsIntAttrDeletedE(const int& EId, const TStr& attr) const; /// Returns true if IntV \c attr exists for edge \c EId and is an empty vector. bool IsIntVAttrDeletedE(const int& EId, const TStr& attr) const; + /// Returns true if FltV \c attr exists for edge \c EId and is an empty vector. + bool IsFltVAttrDeletedE(const int& EId, const TStr& attr) const; /// Returns true if Str \c attr exists for edge \c NId and has default value. bool IsStrAttrDeletedE(const int& EId, const TStr& attr) const; /// Returns true if Flt \c attr exists for edge \c NId and has default value. @@ -2623,6 +2882,8 @@ class TNEANet { bool EdgeAttrIsIntDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) const; /// Returns true if EId attr deleted for current edge int vector attr iterator. bool EdgeAttrIsIntVDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) const; + /// Returns true if EId attr deleted for current edge flt vector attr iterator. + bool EdgeAttrIsFltVDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) const; /// Returns true if EId attr deleted for current edge str attr iterator. bool EdgeAttrIsStrDeleted(const int& EId, const TStrIntPrH::TIter& EdgeHI) const; /// Returns true if EId attr deleted for current edge flt attr iterator. @@ -3054,9 +3315,10 @@ class TUndirNet { TUndirNet(TSIn& SIn) : MxNId(SIn), NEdges(SIn), NodeH(SIn), SAttrN(SIn), SAttrE(SIn) { } /// Saves the network to a (binary) stream SOut. Expects data structures for sparse attributes. void Save(TSOut& SOut) const { MxNId.Save(SOut); NEdges.Save(SOut); NodeH.Save(SOut); - SAttrN.Save(SOut); SAttrE.Save(SOut); } + SAttrN.Save(SOut); SAttrE.Save(SOut); + SOut.Flush(); } /// Saves the network to a (binary) stream SOut. Available for backwards compatibility. - void Save_V1(TSOut& SOut) const { MxNId.Save(SOut); NEdges.Save(SOut); NodeH.Save(SOut); } + void Save_V1(TSOut& SOut) const { MxNId.Save(SOut); NEdges.Save(SOut); NodeH.Save(SOut); SOut.Flush(); } /// Static constructor that returns a pointer to the network. Call: PUndirNet Graph = TUndirNet::New(). static PUndirNet New() { return new TUndirNet(); } /// Static constructor that returns a pointer to the network and reserves enough memory for Nodes nodes and Edges edges. ##TUndirNet::New @@ -3526,9 +3788,9 @@ class TDirNet { /// Constructor that loads the network from a (binary) stream SIn. TDirNet(TSIn& SIn) : MxNId(SIn), NodeH(SIn), SAttrN(SIn), SAttrE(SIn) { } /// Saves the network to a (binary) stream SOut. Expects data structures for sparse attributes. - void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); SAttrN.Save(SOut); SAttrE.Save(SOut); } + void Save(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); SAttrN.Save(SOut); SAttrE.Save(SOut); SOut.Flush(); } /// Saves the network to a (binary) stream SOut. Available for backwards compatibility. - void Save_V1(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); } + void Save_V1(TSOut& SOut) const { MxNId.Save(SOut); NodeH.Save(SOut); SOut.Flush(); } /// Static constructor that returns a pointer to the network. Call: PDirNet Graph = TDirNet::New(). static PDirNet New() { return new TDirNet(); } /// Static constructor that returns a pointer to the network and reserves enough memory for Nodes nodes and Edges edges. ##TDirNet::New diff --git a/snap-core/sim.cpp b/snap-core/sim.cpp index dcfd03955..f6ed4939c 100644 --- a/snap-core/sim.cpp +++ b/snap-core/sim.cpp @@ -184,7 +184,7 @@ PNEANet KNNJaccard(PNGraph Graph, int K) { PNEANet KNN = TNEANet::New(); int sum_neighbors = 0; - int ct; + int ct = 0; int end; end = Graph->GetNodes(); TIntV* Neighbors_old = new TIntV(); diff --git a/snap-core/subgraph.cpp b/snap-core/subgraph.cpp index 7b2b2fae1..00a70d18c 100644 --- a/snap-core/subgraph.cpp +++ b/snap-core/subgraph.cpp @@ -79,6 +79,29 @@ PNGraph GetSubGraph(const PNGraph& Graph, const TIntV& NIdV, const bool& Renumbe return NewGraphPt; } +PHGraph GetSubGraph(const TPt& Graph, const TIntV& NIdV) { + PHGraph NewGraphPt = THGraph::New(); + THGraph& NewGraph = *NewGraphPt; + NewGraph.Reserve(NIdV.Len(), -1); + for (int n = 0; n < NIdV.Len(); n++) { + if (Graph->IsNode(NIdV[n])) { + NewGraph.AddNode(Graph->GetNI(NIdV[n])); + } + } + bool EdgeAddable; + TIntV NeiNIdV; + for (THGraph::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { + EdgeAddable = true; + EI.GetEdge().GetNbrNodes(NeiNIdV); + for (int e=0; e < NeiNIdV.Len(); e++) { + if (!NewGraph.IsNode(NeiNIdV[e])) { EdgeAddable = false; break; } + } + if (EdgeAddable) { NewGraph.AddEdge(EI); } + } + NewGraph.Defrag(); + return NewGraphPt; +} + PUNGraph GetEgonet(const PUNGraph& Graph, const int CtrNId, int& ArndEdges) { PUNGraph NewGraphPt = TUNGraph::New(); TUNGraph& NewGraph = *NewGraphPt; @@ -140,4 +163,411 @@ PNGraph GetEgonet(const PNGraph& Graph, const int CtrNId, int& InEdges, int& Out return NewGraphPt; } +void AddNodeWithAttributes(const PNEANet& Graph1, PNEANet& Graph2, const int NId) { + Graph2->AddNode(NId); + // Copy Int Attributes + TStrV IntAttrNames; + TIntV IntAttrValues; + Graph1->IntAttrNameNI(NId, IntAttrNames); + Graph1->IntAttrValueNI(NId, IntAttrValues); + for (int i = 0; i < IntAttrNames.Len(); i++) { + Graph2->AddIntAttrDatN(NId, IntAttrValues[i], IntAttrNames[i]); + } + // Copy Float Attributes + TStrV FltAttrNames; + TFltV FltAttrValues; + Graph1->FltAttrNameNI(NId, FltAttrNames); + Graph1->FltAttrValueNI(NId, FltAttrValues); + for (int i = 0; i < FltAttrNames.Len(); i++) { + Graph2->AddFltAttrDatN(NId, FltAttrValues[i], FltAttrNames[i]); + } + // Copy Str Attributes + TStrV StrAttrNames; + TStrV StrAttrValues; + Graph1->StrAttrNameNI(NId, StrAttrNames); + Graph1->StrAttrValueNI(NId, StrAttrValues); + for (int i = 0; i < StrAttrNames.Len(); i++) { + Graph2->AddStrAttrDatN(NId, StrAttrValues[i], StrAttrNames[i]); + } + // Copy IntV Attributes + TStrV IntVAttrNames; + TVec IntVAttrValues; + Graph1->IntVAttrNameNI(NId, IntVAttrNames); + Graph1->IntVAttrValueNI(NId, IntVAttrValues); + for (int i = 0; i < IntVAttrNames.Len(); i++) { + Graph2->AddIntVAttrDatN(NId, IntVAttrValues[i], IntVAttrNames[i]); + } +} + +void AddEdgeWithAttributes(const PNEANet &Graph1, PNEANet &Graph2, const int EId) { + const TNEANet::TEdgeI EI = Graph1->GetEI(EId); + Graph2->AddEdge(EI); + //const int EId = Graph2->GetEId(NId, NbrId); + // Copy Int Attributes + TStrV IntAttrNames; + TIntV IntAttrValues; + Graph1->IntAttrNameEI(EId, IntAttrNames); + Graph1->IntAttrValueEI(EId, IntAttrValues); + for (int i = 0; i < IntAttrNames.Len(); i++) { + Graph2->AddIntAttrDatE(EId, IntAttrValues[i], IntAttrNames[i]); + } + // Copy Float Attributes + TStrV FltAttrNames; + TFltV FltAttrValues; + Graph1->FltAttrNameEI(EId, FltAttrNames); + Graph1->FltAttrValueEI(EId, FltAttrValues); + for (int i = 0; i < FltAttrNames.Len(); i++) { + Graph2->AddFltAttrDatE(EId, FltAttrValues[i], FltAttrNames[i]); + } + // Copy Str Attributes + TStrV StrAttrNames; + TStrV StrAttrValues; + Graph1->StrAttrNameEI(EId, StrAttrNames); + Graph1->StrAttrValueEI(EId, StrAttrValues); + for (int i = 0; i < StrAttrNames.Len(); i++) { + Graph2->AddStrAttrDatE(EId, StrAttrValues[i], StrAttrNames[i]); + } + // Copy IntV Attributes + TStrV IntVAttrNames; + TVec IntVAttrValues; + Graph1->IntVAttrNameEI(EId, IntVAttrNames); + Graph1->IntVAttrValueEI(EId, IntVAttrValues); + for (int i = 0; i < IntVAttrNames.Len(); i++) { + Graph2->AddIntVAttrDatE(EId, IntVAttrValues[i], IntVAttrNames[i]); + } +} + +void AddEdgeWithAttributes(const PNEANet &Graph1, PNEANet &Graph2, const int NId, const int NbrId) { + Graph2->AddEdge(NId, NbrId); + const int EId1 = Graph1->GetEId(NId, NbrId); + const int EId2 = Graph2->GetEId(NId, NbrId); + // Copy Int Attributes + TStrV IntAttrNames; + TIntV IntAttrValues; + Graph1->IntAttrNameEI(EId1, IntAttrNames); + Graph1->IntAttrValueEI(EId1, IntAttrValues); + for (int i = 0; i < IntAttrNames.Len(); i++) { + Graph2->AddIntAttrDatE(EId2, IntAttrValues[i], IntAttrNames[i]); + } + // Copy Float Attributes + TStrV FltAttrNames; + TFltV FltAttrValues; + Graph1->FltAttrNameEI(EId1, FltAttrNames); + Graph1->FltAttrValueEI(EId1, FltAttrValues); + for (int i = 0; i < FltAttrNames.Len(); i++) { + Graph2->AddFltAttrDatE(EId2, FltAttrValues[i], FltAttrNames[i]); + } + // Copy Str Attributes + TStrV StrAttrNames; + TStrV StrAttrValues; + Graph1->StrAttrNameEI(EId1, StrAttrNames); + Graph1->StrAttrValueEI(EId1, StrAttrValues); + for (int i = 0; i < StrAttrNames.Len(); i++) { + Graph2->AddStrAttrDatE(EId2, StrAttrValues[i], StrAttrNames[i]); + } + // Copy IntV Attributes + TStrV IntVAttrNames; + TVec IntVAttrValues; + Graph1->IntVAttrNameEI(EId1, IntVAttrNames); + Graph1->IntVAttrValueEI(EId1, IntVAttrValues); + for (int i = 0; i < IntVAttrNames.Len(); i++) { + Graph2->AddIntVAttrDatE(EId2, IntVAttrValues[i], IntVAttrNames[i]); + } +} + +PNEANet GetEgonetAttr(const PNEANet &Graph, const int CtrNId, const int Radius) { + PNEANet NewGraphPt = PNEANet::New(); + TNEANet &NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + AddNodeWithAttributes(Graph, NewGraphPt, CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const TNEANet::TNodeI &Node = Graph->GetNI(NId); + for (int i = 0; i < Node.GetInDeg(); ++i) { + const int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { + AddNodeWithAttributes(Graph, NewGraphPt, InNId); + Queue2.Push(InNId); + } + const int InEId = Node.GetInEId(i); + if (!NewGraph.IsEdge(InEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, InEId); + } + } + for (int i = 0; i < Node.GetOutDeg(); ++i) { + const int OutNId = Node.GetOutNId(i); + if (!NewGraph.IsNode(OutNId)) { + AddNodeWithAttributes(Graph, NewGraphPt, OutNId); + Queue2.Push(OutNId); + } + const int OutEId = Node.GetOutEId(i); + if (!NewGraph.IsEdge(OutEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, OutEId); + } + } + for (int i = 0; i < Node.GetInDeg(); ++i) { + int InNId = Node.GetInNId(i); + const TNEANet::TNodeI &InNode = Graph->GetNI(InNId); + for (int j = 0; j < InNode.GetInDeg(); ++j) { + int NbrInNId = InNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + const int NbrInEId = InNode.GetInEId(j); + if (!NewGraph.IsEdge(NbrInEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, NbrInEId); + } + } + } + for (int j = 0; j < InNode.GetOutDeg(); ++j) { + int NbrOutNId = InNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + const int NbrOutEId = InNode.GetOutEId(j); + if (!NewGraph.IsEdge(NbrOutEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, NbrOutEId); + } + } + } + } + for (int i = 0; i < Node.GetOutDeg(); ++i) { + int OutNId = Node.GetOutNId(i); + const TNEANet::TNodeI &OutNode = Graph->GetNI(OutNId); + for (int j = 0; j < OutNode.GetInDeg(); ++j) { + int NbrInNId = OutNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + const int NbrInEId = OutNode.GetInEId(j); + if (!NewGraph.IsEdge(NbrInEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, NbrInEId); + } + } + } + for (int j = 0; j < OutNode.GetOutDeg(); ++j) { + int NbrOutNId = OutNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + const int NbrOutEId = OutNode.GetOutEId(j); + if (!NewGraph.IsEdge(NbrOutEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, NbrOutEId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +PNEANet GetInEgonetAttr(const PNEANet &Graph, const int CtrNId, const int Radius) { + PNEANet NewGraphPt = PNEANet::New(); + TNEANet &NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + AddNodeWithAttributes(Graph, NewGraphPt, CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const TNEANet::TNodeI &Node = Graph->GetNI(NId); + for (int i = 0; i < Node.GetInDeg(); ++i) { + const int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { + AddNodeWithAttributes(Graph, NewGraphPt, InNId); + Queue2.Push(InNId); + } + const int InEId = Node.GetInEId(i); + if (!NewGraph.IsEdge(InEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, InEId); + } + } + for (int i = 0; i < Node.GetInDeg(); ++i) { + int InNId = Node.GetInNId(i); + const TNEANet::TNodeI &InNode = Graph->GetNI(InNId); + for (int j = 0; j < InNode.GetInDeg(); ++j) { + int NbrInNId = InNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + const int NbrInEId = InNode.GetInEId(j); + if (!NewGraph.IsEdge(NbrInEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, NbrInEId); + } + } + } + for (int j = 0; j < InNode.GetOutDeg(); ++j) { + int NbrOutNId = InNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + const int NbrOutEId = InNode.GetOutEId(j); + if (!NewGraph.IsEdge(NbrOutEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, NbrOutEId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +PNEANet GetOutEgonetAttr(const PNEANet &Graph, const int CtrNId, const int Radius) { + PNEANet NewGraphPt = PNEANet::New(); + TNEANet &NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + AddNodeWithAttributes(Graph, NewGraphPt, CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const TNEANet::TNodeI &Node = Graph->GetNI(NId); + for (int i = 0; i < Node.GetOutDeg(); ++i) { + const int OutNId = Node.GetOutNId(i); + if (!NewGraph.IsNode(OutNId)) { + AddNodeWithAttributes(Graph, NewGraphPt, OutNId); + Queue2.Push(OutNId); + } + const int OutEId = Node.GetOutEId(i); + if (!NewGraph.IsEdge(OutEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, OutEId); + } + } + for (int i = 0; i < Node.GetOutDeg(); ++i) { + int OutNId = Node.GetOutNId(i); + const TNEANet::TNodeI &OutNode = Graph->GetNI(OutNId); + for (int j = 0; j < OutNode.GetInDeg(); ++j) { + int NbrInNId = OutNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + const int InEId = OutNode.GetInEId(j); + if (!NewGraph.IsEdge(InEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, InEId); + } + } + } + for (int j = 0; j < OutNode.GetOutDeg(); ++j) { + int NbrOutNId = OutNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + const int OutEId = OutNode.GetOutEId(j); + if (!NewGraph.IsEdge(OutEId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, OutEId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +// TODO RS 2020/10/05, multiple edges between two nodes are not handled correctly +PNEANet GetInEgonetSubAttr(const PNEANet &Graph, const int CtrNId, const int Radius, const int MaxNum, const float percent) { + PNEANet NewGraphPt = TNEANet::New(); + TNEANet& NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + TSnapQueue sampleQueue; + AddNodeWithAttributes(Graph, NewGraphPt, CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + bool usePercent = (percent != -1.0); + int numSamples = MaxNum; + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const TNEANet::TNodeI &Node = Graph->GetNI(NId); + sampleQueue.Clr(true); + for (int i = 0; i < Node.GetInDeg(); ++i) { + const int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { + sampleQueue.Push(InNId); + } + } + if (usePercent) { + numSamples = (int) (percent * sampleQueue.Len()); + } + sampleQueue.Sample(numSamples); + for (int i = 0; i < numSamples && !sampleQueue.Empty(); ++i) { + const int InNId = sampleQueue.Top(); + sampleQueue.Pop(); + if (!NewGraph.IsNode(InNId)) { + AddNodeWithAttributes(Graph, NewGraphPt, InNId); + Queue2.Push(InNId); + } + if (!NewGraph.IsEdge(InNId, NId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, InNId, NId); + } + } + for (int i = 0; i < Node.GetInDeg(); ++i) { + int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { continue; } + const TNEANet::TNodeI &InNode = Graph->GetNI(InNId); + for (int j = 0; j < InNode.GetInDeg(); ++j) { + int NbrInNId = InNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + if (!NewGraph.IsEdge(NbrInNId, InNId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, NbrInNId, InNId); + } + } + } + for (int j = 0; j < InNode.GetOutDeg(); ++j) { + int NbrOutNId = InNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + if (!NewGraph.IsEdge(InNId, NbrOutNId)) { + AddEdgeWithAttributes(Graph, NewGraphPt, InNId, NbrOutNId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +PNEANet GetGraphUnionAttr(PNEANet &DstGraph, const PNEANet &SrcGraph) { + for (PNEANet::TObj::TNodeI NI = SrcGraph->BegNI(); NI < SrcGraph->EndNI(); NI++) { + if (!DstGraph->IsNode(NI.GetId())) { + AddNodeWithAttributes(SrcGraph, DstGraph, NI.GetId()); + } + } + for (PNEANet::TObj::TEdgeI EI = SrcGraph->BegEI(); EI < SrcGraph->EndEI(); EI++) { + if (!DstGraph->IsEdge(EI.GetSrcNId(), EI.GetDstNId())) { + AddEdgeWithAttributes(SrcGraph, DstGraph, EI.GetSrcNId(), EI.GetDstNId()); + } + } + return DstGraph; +} + +PNEANet GetGraphIntersectionAttr(const PNEANet &Graph, const PNEANet &Graph0){ + PNEANet IntersectionGraph = PNEANet::New(); + for (PNEANet::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { + if (Graph0->IsNode(NI.GetId()) && ! IntersectionGraph->IsNode(NI.GetId())) { + AddNodeWithAttributes(Graph, IntersectionGraph, NI.GetId()); + } + } + for (PNEANet::TObj::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { + if (Graph0->IsEdge(EI.GetSrcNId(), EI.GetDstNId()) && ! IntersectionGraph->IsEdge(EI.GetSrcNId(), EI.GetDstNId())) { + AddEdgeWithAttributes(Graph, IntersectionGraph, EI.GetSrcNId(), EI.GetDstNId()); + } + } + return IntersectionGraph; +} } // namespace TSnap diff --git a/snap-core/subgraph.h b/snap-core/subgraph.h index eecc03535..fedaf3856 100644 --- a/snap-core/subgraph.h +++ b/snap-core/subgraph.h @@ -11,6 +11,8 @@ namespace TSnap { // node subgraphs /// Returns an induced subgraph of graph Graph with NIdV nodes. ##TSnap::GetSubGraph template PGraph GetSubGraph(const PGraph& Graph, const TIntV& NIdV); +/// Returns an induced subgraph of graph Graph with NIdV nodes with an node renumbering. ##TSnap::GetSubGraph +template PGraph GetSubGraphRenumber(const PGraph& Graph, const TIntV& NIdV); /// Returns an induced subgraph of an undirected graph Graph with NIdV nodes with an optional node renumbering. ##TSnap::GetSubGraph-1 PUNGraph GetSubGraph(const PUNGraph& Graph, const TIntV& NIdV, const bool& RenumberNodes=false); // Returns an induced subgraph of a directed graph Graph with NIdV nodes with an optional node renumbering. ##TSnap::GetSubGraph-2 @@ -18,6 +20,9 @@ PNGraph GetSubGraph(const PNGraph& Graph, const TIntV& NIdV, const bool& Renumbe // TODO ROK 2012/08/15 PNGraph GetSubGraph is not documented by doxygen. // It is combined with PUNGraph GetSubGraph. +/// Returns an induced subgraph of a hypergraph Graph with NIdV nodes. +PHGraph GetSubGraph(const TPt& Graph, const TIntV& NIdV); + // edge subgraphs /// Returns a subgraph of graph Graph with EIdV edges. ##TSnap::GetESubGraph template PGraph GetESubGraph(const PGraph& Graph, const TIntV& EIdV); @@ -46,11 +51,41 @@ template PGraph GetRndSubGraph(const PGraph& Graph, const int& NNo /// Returns a random subgraph of graph Graph with NEdges edges. ##TSnap::GetRndESubGraph template PGraph GetRndESubGraph(const PGraph& Graph, const int& NEdges); -// get egonet of a center node +// Get 1st degree egonet of a center node /// Returns the egonet of node CtrNId as center in undirected graph Graph. And returns number of edges around the egonet. -PUNGraph GetEgonet(const PUNGraph& Graph, const int CtrNId, int& ArndEdges); +PUNGraph GetEgonet(const PUNGraph& Graph, const int CtrNId, int& ArndEdgesX); /// Returns the egonet of node CtrNId as center in directed graph Graph. And returns number of edges go in and out the egonet. -PNGraph GetEgonet(const PNGraph& Graph, const int CtrNId, int& InEdges, int& OutEdges); +PNGraph GetEgonet(const PNGraph& Graph, const int CtrNId, int& InEgoEdgesX, int& OutEgoEdgesX); + +// Get egonet for given radius +/// Returns the egonet of node CtrNId as center for a Graph for a given radius. +template PGraph GetEgonetHop(const PGraph &Graph, const int CtrNId, const int Radius); +/// Returns the in-egonet of node CtrNId as center in directed graph Graph for a given radius. +template PGraph GetInEgonetHop(const PGraph& Graph, const int CtrNId, const int Radius); +/// Returns the out-egonet of node CtrNId as center in directed graph Graph for a given radius. +template PGraph GetOutEgonetHop(const PGraph &Graph, const int CtrNId, const int Radius); + +/// Returns the complete egonet of at given radius and copies node and edge attributes +PNEANet GetEgonetAttr(const PNEANet &Graph, const int CtrNId, const int Radius); +/// Returns the in-egonet of at given radius and copies node and edge attributes +PNEANet GetInEgonetAttr(const PNEANet &Graph, const int CtrNId, const int Radius); +/// Returns the out-egonet of at given radius and copies node and edge attributes +PNEANet GetOutEgonetAttr(const PNEANet &Graph, const int CtrNId, const int Radius); + +/// Returns the randomly sampled in-egonet with nodes sampled based on percentage, if percent != -1.0, or MaxNum nodes otherwise. +template PGraph GetInEgonetSub(const PGraph &Graph, const int CtrNId, const int Radius, const int MaxNum = 2, const float percent = -1.0); +/// Returns the randomly sampled egonet with nodes sampled based on percentage or raw number, copying attributes +PNEANet GetInEgonetSubAttr(const PNEANet &Graph, const int CtrNId, const int Radius, const int MaxNum, const float percent); + +/// Modifies DstGraph so that it is the union of SrcGraph and DstGraph and returns a copy of DstGraph. +template PGraph GetGraphUnion(PGraph& DstGraph, const PGraph& SrcGraph); +/// Modifies DstGraph with attributes so that it is the union of SrcGraph and DstGraph and returns a copy of DstGraph. +PNEANet GetGraphUnionAttr(PNEANet &DstGraph, const PNEANet &SrcGraph); + +/// Returns a graph that is the intersection of Graph and Graph0 +template PGraph GetGraphIntersection(const PGraph& Graph, const PGraph& Graph0); +/// Returns a graph with attributes that is the intersection of Graph and Graph0 +PNEANet GetGraphIntersectionAttr(const PNEANet &Graph, const PNEANet &Graph0); ///////////////////////////////////////////////// // Implementation @@ -114,6 +149,11 @@ PGraph GetSubGraph(const PGraph& Graph, const TIntV& NIdV) { ::Do(Graph, NIdV); } +template +PGraph GetSubGraphRenumber(const PGraph& Graph, const TIntV& NIdV) { + return GetSubGraph(Graph, NIdV, true); +} + template PGraph GetESubGraph(const PGraph& Graph, const TIntV& EIdV) { CAssert(HasGraphFlag(typename PGraph::TObj, gfMultiGraph)); @@ -140,17 +180,18 @@ PGraph GetESubGraph(const PGraph& Graph, const TIntPrV& EdgeV) { PGraph NewGraphPt = PGraph::TObj::New(); typename PGraph::TObj& NewGraph = *NewGraphPt; NewGraph.Reserve(-1, EdgeV.Len()); + for (int edge = 0; edge < EdgeV.Len(); edge++) { const int SrcNId = EdgeV[edge].Val1; const int DstNId = EdgeV[edge].Val2; - const typename PGraph::TObj::TEdgeI EI = Graph->GetEI(SrcNId, DstNId); - if (! NewGraph.IsNode(EI.GetSrcNId())) { - NewGraph.AddNode(Graph->GetNI(EI.GetSrcNId())); + if (! NewGraph.IsNode(SrcNId)) { + NewGraph.AddNode(Graph->GetNI(SrcNId)); } - if (! NewGraph.IsNode(EI.GetDstNId())) { - NewGraph.AddNode(Graph->GetNI(EI.GetDstNId())); + if (! NewGraph.IsNode(DstNId)) { + NewGraph.AddNode(Graph->GetNI(DstNId)); } - NewGraph.AddEdge(EI); + + NewGraph.AddEdge(SrcNId, DstNId); } return NewGraphPt; } @@ -373,4 +414,295 @@ PGraph GetRndESubGraph(const PGraph& Graph, const int& NEdges) { return GetESubGraph(Graph, EdgeV); } + +// Egonet templatized functions + +template +PGraph GetEgonetHop(const PGraph &Graph, const int CtrNId, const int Radius) { + PGraph NewGraphPt = PGraph::TObj::New(); + typename PGraph::TObj& NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + NewGraph.AddNode(CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const typename PGraph::TObj::TNodeI &Node = Graph->GetNI(NId); + for (int i = 0; i < Node.GetInDeg(); ++i) { + const int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { + NewGraph.AddNode(InNId); + Queue2.Push(InNId); + } + if (!NewGraph.IsEdge(InNId, NId)) { + NewGraph.AddEdge(InNId, NId); + } + } + for (int i = 0; i < Node.GetOutDeg(); ++i) { + const int OutNId = Node.GetOutNId(i); + if (!NewGraph.IsNode(OutNId)) { + NewGraph.AddNode(OutNId); + Queue2.Push(OutNId); + } + if (!NewGraph.IsEdge(NId, OutNId)) { + NewGraph.AddEdge(NId, OutNId); + } + } + for (int i = 0; i < Node.GetInDeg(); ++i) { + int InNId = Node.GetInNId(i); + const typename PGraph::TObj::TNodeI &InNode = Graph->GetNI(InNId); + for (int j = 0; j < InNode.GetInDeg(); ++j) { + int NbrInNId = InNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + if (!NewGraph.IsEdge(NbrInNId, InNId)) { + NewGraph.AddEdge(NbrInNId, InNId); + } + } + } + for (int j = 0; j < InNode.GetOutDeg(); ++j) { + int NbrOutNId = InNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + if (!NewGraph.IsEdge(InNId, NbrOutNId)) { + NewGraph.AddEdge(InNId, NbrOutNId); + } + } + } + } + for (int i = 0; i < Node.GetOutDeg(); ++i) { + int OutNId = Node.GetOutNId(i); + const typename PGraph::TObj::TNodeI &OutNode = Graph->GetNI(OutNId); + for (int j = 0; j < OutNode.GetInDeg(); ++j) { + int NbrInNId = OutNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + if (!NewGraph.IsEdge(NbrInNId, OutNId)) { + NewGraph.AddEdge(NbrInNId, OutNId); + } + } + } + for (int j = 0; j < OutNode.GetOutDeg(); ++j) { + int NbrOutNId = OutNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + if (!NewGraph.IsEdge(OutNId, NbrOutNId)) { + NewGraph.AddEdge(OutNId, NbrOutNId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +template +PGraph GetInEgonetHop(const PGraph &Graph, const int CtrNId, const int Radius) { + PGraph NewGraphPt = PGraph::TObj::New(); + typename PGraph::TObj& NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + NewGraph.AddNode(CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const typename PGraph::TObj::TNodeI &Node = Graph->GetNI(NId); + for (int i = 0; i < Node.GetInDeg(); ++i) { + const int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { + NewGraph.AddNode(InNId); + Queue2.Push(InNId); + } + if (!NewGraph.IsEdge(InNId, NId)) { + NewGraph.AddEdge(InNId, NId); + } + } + for (int i = 0; i < Node.GetInDeg(); ++i) { + int InNId = Node.GetInNId(i); + const typename PGraph::TObj::TNodeI &InNode = Graph->GetNI(InNId); + for (int j = 0; j < InNode.GetInDeg(); ++j) { + int NbrInNId = InNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + if (!NewGraph.IsEdge(NbrInNId, InNId)) { + NewGraph.AddEdge(NbrInNId, InNId); + } + } + } + for (int j = 0; j < InNode.GetOutDeg(); ++j) { + int NbrOutNId = InNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + if (!NewGraph.IsEdge(InNId, NbrOutNId)) { + NewGraph.AddEdge(InNId, NbrOutNId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +template +PGraph GetOutEgonetHop(const PGraph &Graph, const int CtrNId, const int Radius) { + PGraph NewGraphPt = PGraph::TObj::New(); + typename PGraph::TObj& NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + NewGraph.AddNode(CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const typename PGraph::TObj::TNodeI &Node = Graph->GetNI(NId); + for (int i = 0; i < Node.GetOutDeg(); ++i) { + const int OutNId = Node.GetOutNId(i); + if (!NewGraph.IsNode(OutNId)) { + NewGraph.AddNode(OutNId); + Queue2.Push(OutNId); + } + if (!NewGraph.IsEdge(NId, OutNId)) { + NewGraph.AddEdge(NId, OutNId); + } + } + for (int i = 0; i < Node.GetOutDeg(); ++i) { + int OutNId = Node.GetOutNId(i); + const typename PGraph::TObj::TNodeI &OutNode = Graph->GetNI(OutNId); + for (int j = 0; j < OutNode.GetInDeg(); ++j) { + int NbrInNId = OutNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + if (!NewGraph.IsEdge(NbrInNId, OutNId)) { + NewGraph.AddEdge(NbrInNId, OutNId); + } + } + } + for (int j = 0; j < OutNode.GetOutDeg(); ++j) { + int NbrOutNId = OutNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + if (!NewGraph.IsEdge(OutNId, NbrOutNId)) { + NewGraph.AddEdge(OutNId, NbrOutNId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +template +PGraph GetInEgonetSub(const PGraph &Graph, const int CtrNId, const int Radius, const int MaxNum, const float percent) { + PGraph NewGraphPt = PGraph::TObj::New(); + typename PGraph::TObj& NewGraph = *NewGraphPt; + TSnapQueue Queue1; + TSnapQueue Queue2; + TSnapQueue tempSwapQueue; + TSnapQueue sampleQueue; + NewGraph.AddNode(CtrNId); + Queue1.Clr(false); + Queue1.Push(CtrNId); + bool usePercent = (percent != -1.0); + int numSamples = MaxNum; + for (int r = 0; r < Radius; ++r) { + while (!Queue1.Empty()) { + const int NId = Queue1.Top(); + Queue1.Pop(); + const typename PGraph::TObj::TNodeI &Node = Graph->GetNI(NId); + sampleQueue.Clr(true); + for (int i = 0; i < Node.GetInDeg(); ++i) { + const int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { + sampleQueue.Push(InNId); + } + } + if (usePercent) { + numSamples = (int) (percent * sampleQueue.Len()); + } + sampleQueue.Sample(numSamples); + for (int i = 0; i < numSamples && !sampleQueue.Empty(); ++i) { + const int InNId = sampleQueue.Top(); + sampleQueue.Pop(); + if (!NewGraph.IsNode(InNId)) { + NewGraph.AddNode(InNId); + Queue2.Push(InNId); + } + if (!NewGraph.IsEdge(InNId, NId)) { + NewGraph.AddEdge(InNId, NId); + } + } + for (int i = 0; i < Node.GetInDeg(); ++i) { + int InNId = Node.GetInNId(i); + if (!NewGraph.IsNode(InNId)) { continue; } + const typename PGraph::TObj::TNodeI &InNode = Graph->GetNI(InNId); + for (int j = 0; j < InNode.GetInDeg(); ++j) { + int NbrInNId = InNode.GetInNId(j); + if (NewGraph.IsNode(NbrInNId)) { + if (!NewGraph.IsEdge(NbrInNId, InNId)) { + NewGraph.AddEdge(NbrInNId, InNId); + } + } + } + for (int j = 0; j < InNode.GetOutDeg(); ++j) { + int NbrOutNId = InNode.GetOutNId(j); + if (NewGraph.IsNode(NbrOutNId)) { + if (!NewGraph.IsEdge(InNId, NbrOutNId)) { + NewGraph.AddEdge(InNId, NbrOutNId); + } + } + } + } + } + tempSwapQueue = Queue1; + Queue1 = Queue2; + Queue2 = tempSwapQueue; + } + return NewGraphPt; +} + +template +PGraph GetGraphUnion(PGraph& DstGraph, const PGraph& SrcGraph) { + for (typename PGraph::TObj::TNodeI NI = SrcGraph->BegNI(); NI < SrcGraph->EndNI(); NI++) { + if (! DstGraph->IsNode(NI.GetId())) { + DstGraph->AddNode(NI.GetId()); + } + } + for (typename PGraph::TObj::TEdgeI EI = SrcGraph->BegEI(); EI < SrcGraph->EndEI(); EI++) { + if (! DstGraph->IsEdge(EI.GetSrcNId(), EI.GetDstNId())) { + DstGraph->AddEdge(EI.GetSrcNId(), EI.GetDstNId()); + } + } + return DstGraph; +} + +template +PGraph GetGraphIntersection(const PGraph& Graph, const PGraph& Graph0) { + PGraph IntersectionGraph = PGraph::TObj::New(); + for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { + if (Graph0->IsNode(NI.GetId()) && ! IntersectionGraph->IsNode(NI.GetId())) { + IntersectionGraph->AddNode(NI.GetId()); + } + } + for (typename PGraph::TObj::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { + if (Graph0->IsEdge(EI.GetSrcNId(), EI.GetDstNId()) && ! IntersectionGraph->IsEdge(EI.GetSrcNId(), EI.GetDstNId())) { + IntersectionGraph->AddEdge(EI.GetSrcNId(), EI.GetDstNId()); + } + } + return IntersectionGraph; +} } // namespace TSnap diff --git a/snap-core/table.cpp b/snap-core/table.cpp index 786e1ded8..c5848abd6 100644 --- a/snap-core/table.cpp +++ b/snap-core/table.cpp @@ -161,7 +161,7 @@ TFlt TRowIterator::GetFltAttr(TInt ColIdx) const { } TStr TRowIterator::GetStrAttr(TInt ColIdx) const { - return Table->GetStrVal(ColIdx, CurrRowIdx); + return Table->GetStrValIdx(ColIdx, CurrRowIdx); } TInt TRowIterator::GetIntAttr(const TStr& Col) const { @@ -254,7 +254,7 @@ TFlt TRowIteratorWithRemove::GetNextFltAttr(TInt ColIdx) const { } TStr TRowIteratorWithRemove::GetNextStrAttr(TInt ColIdx) const { - return Table->GetStrVal(ColIdx, GetNextRowIdx()); + return Table->GetStrValIdx(ColIdx, GetNextRowIdx()); } TInt TRowIteratorWithRemove::GetNextIntAttr(const TStr& Col) const { @@ -955,7 +955,7 @@ TTableContext* TTable::ChangeContext(TTableContext* NewContext) { for (TRowIterator RowI = BegRI(); RowI < EndRI(); RowI++) { TInt RowIdx = RowI.GetRowIdx(); // get the string - TStr Key = GetStrVal(ColIdx, RowIdx); + TStr Key = GetStrValIdx(ColIdx, RowIdx); // add the string to the new context TInt KeyId = TInt(NewContext->StringVals.AddKey(Key)); // change the value in the table @@ -1225,7 +1225,7 @@ void TTable::GroupingSanityCheck(const TStr& GroupBy, const TAttrType& AttrType) void TTable::GroupByIntColMP(const TStr& GroupBy, THashMP& Grouping, TBool UsePhysicalIds) const { timeval timer0; gettimeofday(&timer0, NULL); - double t1 = timer0.tv_sec + (timer0.tv_usec/1000000.0); + //double t1 = timer0.tv_sec + (timer0.tv_usec/1000000.0); //printf("X\n"); TInt IdColIdx = GetColIdx(IdColName); TInt GroupByColIdx = GetColIdx(GroupBy); @@ -1256,8 +1256,8 @@ void TTable::GroupByIntColMP(const TStr& GroupBy, THashMP& Grouping } } gettimeofday(&timer0, NULL); - double t2 = timer0.tv_sec + (timer0.tv_usec/1000000.0); - printf("Grouping time: %f\n", t2 - t1); + //double t2 = timer0.tv_sec + (timer0.tv_usec/1000000.0); + //printf("Grouping time: %f\n", t2 - t1); //double endAdd = omp_get_wtime(); //printf("Add time = %f\n", endAdd-endGen); } @@ -3046,7 +3046,7 @@ void TTable::SelectAtomicConst(const TStr& Col, const TPrimitive& Val, TPredComp #endif for(TRowIterator RowI = BegRI(); RowI < EndRI(); RowI++){ if (RowI.CompareAtomicConst(ColIdx, Val, Cmp)) { - SelectedTable->AddRow(RowI); + SelectedTable->AddRowI(RowI); } } #ifdef USE_OPENMP @@ -3075,8 +3075,8 @@ inline TInt TTable::CompareRows(TInt R1, TInt R2, const TAttrType& CompareByType return 0; } case atStr:{ - TStr S1 = GetStrVal(CompareByIndex, R1); - TStr S2 = GetStrVal(CompareByIndex, R2); + TStr S1 = GetStrValIdx(CompareByIndex, R1); + TStr S2 = GetStrValIdx(CompareByIndex, R2); int CmpRes = strcmp(S1.CStr(), S2.CStr()); return (Asc ? CmpRes : -CmpRes); } @@ -3405,7 +3405,7 @@ inline void TTable::AddEdgeAttributes(PNEANet& Graph, int RowId) { Graph->AddFltAttrDatE(RowId, FltCols[Index][RowId], ColName); break; case atStr: - Graph->AddStrAttrDatE(RowId, GetStrVal(Index, RowId), ColName); + Graph->AddStrAttrDatE(RowId, GetStrValIdx(Index, RowId), ColName); break; } } @@ -3435,7 +3435,7 @@ inline void TTable::AddNodeAttributes(TInt NId, TStrV NodeAttrV, TInt RowId, THa } else { if (!NodeStrAttrs.IsKey(NId)) { NodeStrAttrs.AddKey(NId); } if (!NodeStrAttrs.GetDat(NId).IsKey(ColAttr)) { NodeStrAttrs.GetDat(NId).AddKey(ColAttr); } - NodeStrAttrs.GetDat(NId).GetDat(ColAttr).Add(GetStrVal(ColId, RowId)); + NodeStrAttrs.GetDat(NId).GetDat(ColAttr).Add(GetStrValIdx(ColId, RowId)); } } } @@ -4292,7 +4292,7 @@ void TTable::UpdateFltFromTable(const TStr& KeyAttr, const TStr& UpdateAttr, con // can ONLY be called when a table is being initialised (before IDs are allocated) -void TTable::AddRow(const TRowIterator& RI) { +void TTable::AddRowI(const TRowIterator& RI) { for (TInt c = 0; c < Sch.Len(); c++) { TStr ColName = GetSchemaColName(c); if (ColName == IdColName) { continue; } @@ -4314,7 +4314,7 @@ void TTable::AddRow(const TRowIterator& RI) { UpdateTableForNewRow(); } -void TTable::AddRow(const TIntV& IntVals, const TFltV& FltVals, const TStrV& StrVals) { +void TTable::AddRowV(const TIntV& IntVals, const TFltV& FltVals, const TStrV& StrVals) { for (TInt c = 0; c < IntVals.Len(); c++) { IntCols[c].Add(IntVals[c]); } @@ -4550,7 +4550,7 @@ PTable TTable::Union(const TTable& Table) { // this part should be made faster by adding all the rows in one go for (TRowIterator it = Table.BegRI(); it < Table.EndRI(); it++) { if (!Collisions.IsKey(it.GetRowIdx())) { - result->AddRow(it); + result->AddRowI(it); } } @@ -4580,7 +4580,7 @@ PTable TTable::Intersection(const TTable& Table) { // this part should be made faster by adding all the rows in one go for (TRowIterator it = Table.BegRI(); it < Table.EndRI(); it++) { if (Collisions.IsKey(it.GetRowIdx())) { - result->AddRow(it); + result->AddRowI(it); } } result->InitIds(); @@ -4605,7 +4605,7 @@ PTable TTable::Minus(TTable& Table) { // this part should be made faster by adding all the rows in one go for (TRowIterator it = BegRI(); it < EndRI(); it++) { if (!Collisions.IsKey(it.GetRowIdx())) { - result->AddRow(it); + result->AddRowI(it); } } result->InitIds(); diff --git a/snap-core/table.h b/snap-core/table.h index ff598eaf9..310efad7a 100644 --- a/snap-core/table.h +++ b/snap-core/table.h @@ -599,7 +599,7 @@ class TTable { return Context->StringVals.GetKey(Val); } /// Gets the value in column with id \c ColIdx at row \c RowIdx. - TStr GetStrVal(TInt ColIdx, TInt RowIdx) const { + TStr GetStrValIdx(TInt ColIdx, TInt RowIdx) const { return TStr(Context->StringVals.GetKey(StrColMaps[ColIdx][RowIdx])); } /// Adds \c Val in column with id \c ColIdx. @@ -659,9 +659,9 @@ class TTable { void ConcatTable(const PTable& T) {AddTable(*T); Reindex(); } /// Adds row corresponding to \c RI. - void AddRow(const TRowIterator& RI); + void AddRowI(const TRowIterator& RI); /// Adds row with values corresponding to the given vectors by type. - void AddRow(const TIntV& IntVals, const TFltV& FltVals, const TStrV& StrVals); + void AddRowV(const TIntV& IntVals, const TFltV& FltVals, const TStrV& StrVals); /***** Utility functions for building graph from TTable *****/ /// Adds names of columns to be used as graph attributes. @@ -944,7 +944,7 @@ class TTable { return T; } /// Adds row with values taken from given TTableRow. - void AddRow(const TTableRow& Row) { AddRow(Row.GetIntVals(), Row.GetFltVals(), Row.GetStrVals()); }; + void AddRow(const TTableRow& Row) { AddRowV(Row.GetIntVals(), Row.GetFltVals(), Row.GetStrVals()); }; /// Returns the context. TTableContext* GetContext() { @@ -971,7 +971,7 @@ class TTable { } /// Gets the value of string attribute \c ColName at row \c RowIdx. TStr GetStrVal(const TStr& ColName, const TInt& RowIdx) const { - return GetStrVal(GetColIdx(ColName), RowIdx); + return GetStrValIdx(GetColIdx(ColName), RowIdx); } /// Gets the integer mapping of the string at column \c ColIdx at row \c RowIdx. @@ -986,7 +986,7 @@ class TTable { /// Gets the value of the string attribute at column \c ColIdx at row \c RowIdx. TStr GetStrValById(TInt ColIdx, TInt RowIdx) const { - return GetStrVal(ColIdx, RowIdx); + return GetStrValIdx(ColIdx, RowIdx); } /// Gets the value of the string attribute at column \c ColName at row \c RowIdx. @@ -1444,7 +1444,7 @@ T TTable::AggregateVector(TVec& V, TAttrAggr Policy) { for (TInt i = 1; i < V.Len(); i++) { Res = Res + V[i]; } - //Res = Res / V.Len(); // TODO: Handle Str case separately? + Res = Res / V.Len(); return Res; } case aaMedian: { diff --git a/snap-core/triad.h b/snap-core/triad.h index 0fd57a972..74a928df7 100644 --- a/snap-core/triad.h +++ b/snap-core/triad.h @@ -11,16 +11,20 @@ template double GetClustCf(const PGraph& Graph, int SampleNodes=- /// Computes the distribution of average clustering coefficient. ##TSnap::GetClustCf1 template double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int SampleNodes=-1); /// Computes the distribution of average clustering coefficient as well as the number of open and closed triads in the graph. ##TSnap::GetClustCf2 -template double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriadsX, int64& OpenTriadsX, int SampleNodes=-1); +template double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriads, int64& OpenTriads, int SampleNodes=-1); +/// Computes the distribution of average clustering coefficient as well as the number of open and closed triads in the graph. ##TSnap::GetClustCfAll +template double GetClustCfAll(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriadsX, int64& OpenTriadsX, int SampleNodes=-1); /// Returns clustering coefficient of a particular node. ##TSnap::GetNodeClustCf template double GetNodeClustCf(const PGraph& Graph, const int& NId); -/// Computes clustering coefficient of each node of the Graph. ##TSnap::GetClustCf1 +/// Computes clustering coefficient of each node of the Graph. ##TSnap::GetNodeClustCf template void GetNodeClustCf(const PGraph& Graph, TIntFltH& NIdCCfH); /// Returns the number of triangles in a graph. ##TSnap::GetTriads template int64 GetTriads(const PGraph& Graph, int SampleNodes=-1); /// Computes the number of Closed and Open triads. ##TSnap::GetTriads1 template int64 GetTriads(const PGraph& Graph, int64& ClosedTriadsX, int64& OpenTriadsX, int SampleNodes); +/// Computes the number of Closed and Open triads. ##TSnap::GetTriadsAll +template int64 GetTriadsAll(const PGraph& Graph, int64& ClosedTriadsX, int64& OpenTriadsX, int SampleNodes=-1); /// Computes the number of open and close triads for every node of the network. ##TSnap::GetTriads2 template void GetTriads(const PGraph& Graph, TIntTrV& NIdCOTriadV, int SampleNodes=-1); /// Counts the number of edges that participate in at least one triad. ##TSnap::GetTriadEdges @@ -30,6 +34,8 @@ template int GetTriadEdges(const PGraph& Graph, int SampleEdges=- template int GetNodeTriads(const PGraph& Graph, const int& NId); /// Returns number of Open and Closed triads a node \c NId participates in. ##TSnap::GetNodeTriads1 template int GetNodeTriads(const PGraph& Graph, const int& NId, int& ClosedNTriadsX, int& OpenNTriadsX); +/// Returns number of Open and Closed triads a node \c NId participates in. ##TSnap::GetNodeTriadsAll +template int GetNodeTriadsAll(const PGraph& Graph, const int& NId, int& ClosedNTriadsX, int& OpenNTriadsX); /// Returns the number of triads between a node \c NId and a subset of its neighbors \c GroupSet. ##TSnap::GetNodeTriads3 template int GetNodeTriads(const PGraph& Graph, const int& NId, const TIntSet& GroupSet, int& InGroupEdgesX, int& InOutGroupEdgesX, int& OutGroupEdgesX); @@ -75,6 +81,10 @@ template double GetClustCf(const PGraph& Graph, int SampleNodes) template double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int SampleNodes) { TIntTrV NIdCOTriadV; GetTriads(Graph, NIdCOTriadV, SampleNodes); + if (NIdCOTriadV.Empty()) { + DegToCCfV.Clr(false); + return 0.0; + } THash DegSumCnt; double SumCcf = 0.0; for (int i = 0; i < NIdCOTriadV.Len(); i++) { @@ -98,6 +108,12 @@ template double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriads, int64& OpenTriads, int SampleNodes) { TIntTrV NIdCOTriadV; GetTriads(Graph, NIdCOTriadV, SampleNodes); + if (NIdCOTriadV.Empty()) { + DegToCCfV.Clr(false); + ClosedTriads = 0; + OpenTriads = 0; + return 0.0; + } THash DegSumCnt; double SumCcf = 0.0; int64 closedTriads = 0; @@ -125,6 +141,11 @@ double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriads, return SumCcf / double(NIdCOTriadV.Len()); } +template +double GetClustCfAll(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriads, int64& OpenTriads, int SampleNodes) { + return GetClustCf(Graph, DegToCCfV, ClosedTriads, OpenTriads, SampleNodes); +} + template double GetNodeClustCf(const PGraph& Graph, const int& NId) { int Open, Closed; @@ -168,6 +189,11 @@ int64 GetTriads(const PGraph& Graph, int64& ClosedTriads, int64& OpenTriads, int return ClosedTriads; } +template +int64 GetTriadsAll(const PGraph& Graph, int64& ClosedTriads, int64& OpenTriads, int SampleNodes) { + return GetTriads(Graph, ClosedTriads, OpenTriads, SampleNodes); +} + // Function pretends that the graph is undirected (count unique connected triples of nodes) // This implementation is slower, it uses hash tables directly template @@ -551,6 +577,11 @@ int GetNodeTriads(const PGraph& Graph, const int& NId, int& ClosedTriads, int& O return ClosedTriads; } +template +int GetNodeTriadsAll(const PGraph& Graph, const int& NId, int& ClosedTriads, int& OpenTriads) { + return GetNodeTriads(Graph, NId, ClosedTriads, OpenTriads); +} + // Node NId and a subset of its neighbors GroupSet // InGroupEdges ... triads (NId, g1, g2), where g1 and g2 are in GroupSet // InOutGroupEdges ... triads (NId, g1, o1), where g1 in GroupSet and o1 not in GroupSet diff --git a/test/Makefile b/test/Makefile index 7bb3cdb68..0f8679f1e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -8,10 +8,14 @@ # Compile and run all the tests: # make run # +# Note: +# graphviz test files were generated with graphviz version 2.38.0 include ../Makefile.config CXXFLAGS += $(CXXOPENMP) LIBS += -lgtest +# use the following line for linking the static library +#LIBS += $(HOME)/miniconda3/lib/libgtest.a ## Main application file MAIN = run-all-tests diff --git a/test/graphviz/base_ngraph_Circo.gif b/test/graphviz/base_ngraph_Circo.gif deleted file mode 100644 index 84a442d8c..000000000 Binary files a/test/graphviz/base_ngraph_Circo.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Circo.png b/test/graphviz/base_ngraph_Circo.png index f24efd01a..2d21c8167 100644 Binary files a/test/graphviz/base_ngraph_Circo.png and b/test/graphviz/base_ngraph_Circo.png differ diff --git a/test/graphviz/base_ngraph_Circo.ps b/test/graphviz/base_ngraph_Circo.ps index 5510f8a59..8d9da41b5 100644 Binary files a/test/graphviz/base_ngraph_Circo.ps and b/test/graphviz/base_ngraph_Circo.ps differ diff --git a/test/graphviz/base_ngraph_Circo_col.gif b/test/graphviz/base_ngraph_Circo_col.gif deleted file mode 100644 index ab07ed481..000000000 Binary files a/test/graphviz/base_ngraph_Circo_col.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Circo_col.png b/test/graphviz/base_ngraph_Circo_col.png index 1b3d84525..dfcdf6af1 100644 Binary files a/test/graphviz/base_ngraph_Circo_col.png and b/test/graphviz/base_ngraph_Circo_col.png differ diff --git a/test/graphviz/base_ngraph_Circo_col.ps b/test/graphviz/base_ngraph_Circo_col.ps index de9f6e6dd..9177de844 100644 Binary files a/test/graphviz/base_ngraph_Circo_col.ps and b/test/graphviz/base_ngraph_Circo_col.ps differ diff --git a/test/graphviz/base_ngraph_Dot.gif b/test/graphviz/base_ngraph_Dot.gif deleted file mode 100644 index d9ce682a4..000000000 Binary files a/test/graphviz/base_ngraph_Dot.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Dot.png b/test/graphviz/base_ngraph_Dot.png index 6dd8c823d..faeae7b98 100644 Binary files a/test/graphviz/base_ngraph_Dot.png and b/test/graphviz/base_ngraph_Dot.png differ diff --git a/test/graphviz/base_ngraph_Dot.ps b/test/graphviz/base_ngraph_Dot.ps index 7ab15ce49..966ec1238 100644 Binary files a/test/graphviz/base_ngraph_Dot.ps and b/test/graphviz/base_ngraph_Dot.ps differ diff --git a/test/graphviz/base_ngraph_Dot_col.gif b/test/graphviz/base_ngraph_Dot_col.gif deleted file mode 100644 index daf0d4274..000000000 Binary files a/test/graphviz/base_ngraph_Dot_col.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Dot_col.png b/test/graphviz/base_ngraph_Dot_col.png index 4f7590542..9c2a99974 100644 Binary files a/test/graphviz/base_ngraph_Dot_col.png and b/test/graphviz/base_ngraph_Dot_col.png differ diff --git a/test/graphviz/base_ngraph_Dot_col.ps b/test/graphviz/base_ngraph_Dot_col.ps index 2fde499bb..fc27d13cb 100644 Binary files a/test/graphviz/base_ngraph_Dot_col.ps and b/test/graphviz/base_ngraph_Dot_col.ps differ diff --git a/test/graphviz/base_ngraph_Neato.gif b/test/graphviz/base_ngraph_Neato.gif deleted file mode 100644 index 0f86ff7fe..000000000 Binary files a/test/graphviz/base_ngraph_Neato.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Neato.png b/test/graphviz/base_ngraph_Neato.png index 19f3dc70f..3a20db3bd 100644 Binary files a/test/graphviz/base_ngraph_Neato.png and b/test/graphviz/base_ngraph_Neato.png differ diff --git a/test/graphviz/base_ngraph_Neato.ps b/test/graphviz/base_ngraph_Neato.ps index e4ef4f2cd..b216e94d7 100644 Binary files a/test/graphviz/base_ngraph_Neato.ps and b/test/graphviz/base_ngraph_Neato.ps differ diff --git a/test/graphviz/base_ngraph_Neato_col.gif b/test/graphviz/base_ngraph_Neato_col.gif deleted file mode 100644 index 4f4562fa2..000000000 Binary files a/test/graphviz/base_ngraph_Neato_col.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Neato_col.png b/test/graphviz/base_ngraph_Neato_col.png index efc863036..1f4d35766 100644 Binary files a/test/graphviz/base_ngraph_Neato_col.png and b/test/graphviz/base_ngraph_Neato_col.png differ diff --git a/test/graphviz/base_ngraph_Neato_col.ps b/test/graphviz/base_ngraph_Neato_col.ps index f112adad7..bfadc0448 100644 Binary files a/test/graphviz/base_ngraph_Neato_col.ps and b/test/graphviz/base_ngraph_Neato_col.ps differ diff --git a/test/graphviz/base_ngraph_Twopi.gif b/test/graphviz/base_ngraph_Twopi.gif deleted file mode 100644 index 7902a0873..000000000 Binary files a/test/graphviz/base_ngraph_Twopi.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Twopi.png b/test/graphviz/base_ngraph_Twopi.png index f1f9cba0e..d36c72cb6 100644 Binary files a/test/graphviz/base_ngraph_Twopi.png and b/test/graphviz/base_ngraph_Twopi.png differ diff --git a/test/graphviz/base_ngraph_Twopi.ps b/test/graphviz/base_ngraph_Twopi.ps index b0decda42..86bcb0a7a 100644 Binary files a/test/graphviz/base_ngraph_Twopi.ps and b/test/graphviz/base_ngraph_Twopi.ps differ diff --git a/test/graphviz/base_ngraph_Twopi_col.gif b/test/graphviz/base_ngraph_Twopi_col.gif deleted file mode 100644 index 342a753c7..000000000 Binary files a/test/graphviz/base_ngraph_Twopi_col.gif and /dev/null differ diff --git a/test/graphviz/base_ngraph_Twopi_col.png b/test/graphviz/base_ngraph_Twopi_col.png index 17ab8576d..f0d63fe4d 100644 Binary files a/test/graphviz/base_ngraph_Twopi_col.png and b/test/graphviz/base_ngraph_Twopi_col.png differ diff --git a/test/graphviz/base_ngraph_Twopi_col.ps b/test/graphviz/base_ngraph_Twopi_col.ps index a31a281f1..701eb23a2 100644 Binary files a/test/graphviz/base_ngraph_Twopi_col.ps and b/test/graphviz/base_ngraph_Twopi_col.ps differ diff --git a/test/graphviz/base_ungraph_Circo.gif b/test/graphviz/base_ungraph_Circo.gif deleted file mode 100644 index 8bc67f4ab..000000000 Binary files a/test/graphviz/base_ungraph_Circo.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Circo.png b/test/graphviz/base_ungraph_Circo.png index 9fe6366ea..ed4d3f556 100644 Binary files a/test/graphviz/base_ungraph_Circo.png and b/test/graphviz/base_ungraph_Circo.png differ diff --git a/test/graphviz/base_ungraph_Circo.ps b/test/graphviz/base_ungraph_Circo.ps index b5305bb37..075072c42 100644 Binary files a/test/graphviz/base_ungraph_Circo.ps and b/test/graphviz/base_ungraph_Circo.ps differ diff --git a/test/graphviz/base_ungraph_Circo_col.gif b/test/graphviz/base_ungraph_Circo_col.gif deleted file mode 100644 index 9023f0b65..000000000 Binary files a/test/graphviz/base_ungraph_Circo_col.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Circo_col.png b/test/graphviz/base_ungraph_Circo_col.png index fd65a9e13..a3d4cdab1 100644 Binary files a/test/graphviz/base_ungraph_Circo_col.png and b/test/graphviz/base_ungraph_Circo_col.png differ diff --git a/test/graphviz/base_ungraph_Circo_col.ps b/test/graphviz/base_ungraph_Circo_col.ps index 24854983d..49b7a3115 100644 Binary files a/test/graphviz/base_ungraph_Circo_col.ps and b/test/graphviz/base_ungraph_Circo_col.ps differ diff --git a/test/graphviz/base_ungraph_Dot.gif b/test/graphviz/base_ungraph_Dot.gif deleted file mode 100644 index d14427c0b..000000000 Binary files a/test/graphviz/base_ungraph_Dot.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Dot.png b/test/graphviz/base_ungraph_Dot.png index 5dfb7e2d2..eb181bdcd 100644 Binary files a/test/graphviz/base_ungraph_Dot.png and b/test/graphviz/base_ungraph_Dot.png differ diff --git a/test/graphviz/base_ungraph_Dot.ps b/test/graphviz/base_ungraph_Dot.ps index a4c4c7dfd..58b9c8597 100644 Binary files a/test/graphviz/base_ungraph_Dot.ps and b/test/graphviz/base_ungraph_Dot.ps differ diff --git a/test/graphviz/base_ungraph_Dot_col.gif b/test/graphviz/base_ungraph_Dot_col.gif deleted file mode 100644 index 4f78f21bd..000000000 Binary files a/test/graphviz/base_ungraph_Dot_col.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Dot_col.png b/test/graphviz/base_ungraph_Dot_col.png index 7e1aabd89..a7d9c5b13 100644 Binary files a/test/graphviz/base_ungraph_Dot_col.png and b/test/graphviz/base_ungraph_Dot_col.png differ diff --git a/test/graphviz/base_ungraph_Dot_col.ps b/test/graphviz/base_ungraph_Dot_col.ps index 907b2d05a..474e622b3 100644 Binary files a/test/graphviz/base_ungraph_Dot_col.ps and b/test/graphviz/base_ungraph_Dot_col.ps differ diff --git a/test/graphviz/base_ungraph_Neato.gif b/test/graphviz/base_ungraph_Neato.gif deleted file mode 100644 index bbc4c97c0..000000000 Binary files a/test/graphviz/base_ungraph_Neato.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Neato.png b/test/graphviz/base_ungraph_Neato.png index 228a6a32e..f2944d84b 100644 Binary files a/test/graphviz/base_ungraph_Neato.png and b/test/graphviz/base_ungraph_Neato.png differ diff --git a/test/graphviz/base_ungraph_Neato.ps b/test/graphviz/base_ungraph_Neato.ps index 10a4cd241..bcd50fb3a 100644 Binary files a/test/graphviz/base_ungraph_Neato.ps and b/test/graphviz/base_ungraph_Neato.ps differ diff --git a/test/graphviz/base_ungraph_Neato_col.gif b/test/graphviz/base_ungraph_Neato_col.gif deleted file mode 100644 index 19d7285e9..000000000 Binary files a/test/graphviz/base_ungraph_Neato_col.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Neato_col.png b/test/graphviz/base_ungraph_Neato_col.png index e6d275e42..cdecb7f7f 100644 Binary files a/test/graphviz/base_ungraph_Neato_col.png and b/test/graphviz/base_ungraph_Neato_col.png differ diff --git a/test/graphviz/base_ungraph_Neato_col.ps b/test/graphviz/base_ungraph_Neato_col.ps index c41308a8b..2449b48d2 100644 Binary files a/test/graphviz/base_ungraph_Neato_col.ps and b/test/graphviz/base_ungraph_Neato_col.ps differ diff --git a/test/graphviz/base_ungraph_Twopi.gif b/test/graphviz/base_ungraph_Twopi.gif deleted file mode 100644 index c6fc7bbf8..000000000 Binary files a/test/graphviz/base_ungraph_Twopi.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Twopi.png b/test/graphviz/base_ungraph_Twopi.png index b7af54576..e5edb8ab6 100644 Binary files a/test/graphviz/base_ungraph_Twopi.png and b/test/graphviz/base_ungraph_Twopi.png differ diff --git a/test/graphviz/base_ungraph_Twopi.ps b/test/graphviz/base_ungraph_Twopi.ps index 40cf679d4..48b56b6bc 100644 Binary files a/test/graphviz/base_ungraph_Twopi.ps and b/test/graphviz/base_ungraph_Twopi.ps differ diff --git a/test/graphviz/base_ungraph_Twopi_col.gif b/test/graphviz/base_ungraph_Twopi_col.gif deleted file mode 100644 index 040225fae..000000000 Binary files a/test/graphviz/base_ungraph_Twopi_col.gif and /dev/null differ diff --git a/test/graphviz/base_ungraph_Twopi_col.png b/test/graphviz/base_ungraph_Twopi_col.png index 4abf42116..9566cb290 100644 Binary files a/test/graphviz/base_ungraph_Twopi_col.png and b/test/graphviz/base_ungraph_Twopi_col.png differ diff --git a/test/graphviz/base_ungraph_Twopi_col.ps b/test/graphviz/base_ungraph_Twopi_col.ps index 2b1b6e62c..091371fcb 100644 Binary files a/test/graphviz/base_ungraph_Twopi_col.ps and b/test/graphviz/base_ungraph_Twopi_col.ps differ diff --git a/test/test-TNEANet.cpp b/test/test-TNEANet.cpp index a7e95ffaa..cbb01f7d2 100644 --- a/test/test-TNEANet.cpp +++ b/test/test-TNEANet.cpp @@ -206,6 +206,489 @@ TEST(TNEANet, IntVAttr) { } +// Tests AddIntVAttrDatN/E, GetIntVAttrDatN/E, AppendIntVAttrDatN/E +TEST(TNEANet, IntVAttr2) { + PNEANet Graph = TNEANet::New(); + TIntV test; + int numNodes = 10; + Graph->AddIntVAttrN("size"); + Graph->AddIntVAttrN("single"); + + for (int i = 0; i < 10; ++i) { + Graph->AddNode(i); + TIntV size(i); + Graph->AddIntVAttrDatN(i, size, "size"); + + TIntV single; + single.Add(i); + Graph->AddIntVAttrDatN(i, single, "single"); + } + + for (int i = 0; i < 10; ++i) { + TIntV size_check = Graph->GetIntVAttrDatN(i, "size"); + TIntV single_check = Graph->GetIntVAttrDatN(i, "single"); + + TIntV size(i); + TIntV single; + single.Add(i); + + EXPECT_EQ(size, size_check); + EXPECT_EQ(single, single_check); + + Graph->AppendIntVAttrDatN(i, -i, "single"); + single.Add(-i); + + single_check = Graph->GetIntVAttrDatN(i, "single"); + EXPECT_EQ(single, single_check); + } + + Graph->AddIntVAttrE("cost"); + Graph->AddIntVAttrE("reward"); + + + for (int i = 0; i < 10; i++) { + for (int j = i+1; j < 10; j++) { + EXPECT_EQ(Graph->IsEdge(i, j), false); + TInt edgeID = Graph->AddEdge(i, j); + EXPECT_EQ(Graph->IsEdge(edgeID), true); + + TIntV costs; + costs.Add(i+j); + + Graph->AddIntVAttrDatE(edgeID, costs, "cost"); + Graph->AppendIntVAttrDatE(edgeID, i+j, "cost"); + costs.Add(i+j); + Graph->AddIntVAttrDatE(edgeID, costs, "reward"); + + TIntV cost_val = Graph->GetIntVAttrDatE(edgeID, "cost"); + TIntV reward_val = Graph->GetIntVAttrDatE(edgeID, "reward"); + + EXPECT_EQ(cost_val.Len(), 2); + EXPECT_EQ(reward_val.Len(), 2); + + for (int d = 0; d < 2; d++) { + EXPECT_EQ(cost_val[d], i+j); + EXPECT_EQ(reward_val[d], i+j); + } + } + } + + for (int i = 0; i < 10; i++) { + for (int j = i+1; j < 10; j++) { + TInt edgeID = Graph->GetEId(i, j); + EXPECT_EQ(Graph->IsEdge(edgeID), true); + + TIntV cost_val = Graph->GetIntVAttrDatE(edgeID, "cost"); + TIntV reward_val = Graph->GetIntVAttrDatE(edgeID, "reward"); + + EXPECT_EQ(cost_val.Len(), 2); + EXPECT_EQ(reward_val.Len(), 2); + + for (int d = 0; d < 2; d++) { + EXPECT_EQ(cost_val[d], i+j); + EXPECT_EQ(reward_val[d], i+j); + } + } + } +} + +// Avery +TEST(TNEANet, FltVAttr) { + PNEANet Graph; + Graph = TNEANet::New(); + int i; + TFltV test; + int numNodes = 10; + Graph->AddNode(0); + for (i = 1; i < numNodes; i++) { + Graph->AddNode(i); + Graph->AddEdge(i-1, i); + } + TStr TestAttr("Test1"); + Graph->AddFltVAttrN(TestAttr); + for (i = 0; i < numNodes; i++) { + test = Graph->GetFltVAttrDatN(i, TestAttr); + EXPECT_EQ(0, test.Len()); + } + + TFltV testVB; + for (i = 0; i < numNodes; i++) { + testVB.Add(i); + } + const TFltV testV = testVB; + Graph->AddFltVAttrDatN(0, testV, TestAttr); + test = Graph->GetFltVAttrDatN(0, TestAttr); + EXPECT_EQ(numNodes, test.Len()); + + for (i = 0; i < numNodes; i++) { + EXPECT_EQ(test[i], i + 0.0); + } + + Graph->AppendFltVAttrDatN(0, numNodes, TestAttr); + test = Graph->GetFltVAttrDatN(0, TestAttr); + EXPECT_EQ(numNodes+1, test.Len()); + for (i = 0; i < numNodes+1; i++) { + EXPECT_EQ(test[i], i + 0.0); + } + + Graph->DelAttrDatN(0, TestAttr); + for (i = 0; i < numNodes; i++) { + test = Graph->GetFltVAttrDatN(i, TestAttr); + EXPECT_EQ(0, test.Len()); + } +} + +// Tests AddIntVAttrDatN/E, GetIntVAttrDatN/E, AppendIntVAttrDatN/E +TEST(TNEANet, FltVAttr2) { + PNEANet Graph = TNEANet::New(); + TFltV test; + int numNodes = 10; + Graph->AddFltVAttrN("size"); + Graph->AddFltVAttrN("single"); + + for (int i = 0; i < 10; ++i) { + Graph->AddNode(i); + TFltV size(i); + Graph->AddFltVAttrDatN(i, size, "size"); + + TFltV single; + single.Add(i + 0.5); + Graph->AddFltVAttrDatN(i, single, "single"); + } + + for (int i = 0; i < 10; ++i) { + TFltV size_check = Graph->GetFltVAttrDatN(i, "size"); + TFltV single_check = Graph->GetFltVAttrDatN(i, "single"); + + TFltV size(i); + TFltV single; + single.Add(i + 0.5); + + EXPECT_EQ(size, size_check); + EXPECT_EQ(single, single_check); + + Graph->AppendFltVAttrDatN(i, -i + 0.5, "single"); + single.Add(-i + 0.5); + + single_check = Graph->GetFltVAttrDatN(i, "single"); + EXPECT_EQ(single, single_check); + } + + Graph->AddFltVAttrE("cost"); + Graph->AddFltVAttrE("reward"); + + for (int i = 0; i < 10; i++) { + for (int j = i+1; j < 10; j++) { + EXPECT_EQ(Graph->IsEdge(i, j), false); + TInt edgeID = Graph->AddEdge(i, j); + EXPECT_EQ(Graph->IsEdge(edgeID), true); + + TFltV costs; + costs.Add(i+j+0.5); + + Graph->AddFltVAttrDatE(edgeID, costs, "cost"); + Graph->AppendFltVAttrDatE(edgeID, i+j+0.5, "cost"); + costs.Add(i+j+0.5); + Graph->AddFltVAttrDatE(edgeID, costs, "reward"); + + + TFltV cost_val = Graph->GetFltVAttrDatE(edgeID, "cost"); + TFltV reward_val = Graph->GetFltVAttrDatE(edgeID, "reward"); + + EXPECT_EQ(cost_val.Len(), 2); + EXPECT_EQ(reward_val.Len(), 2); + + for (int d = 0; d < 2; d++) { + EXPECT_FLOAT_EQ(cost_val[d], i+j+0.5); + EXPECT_FLOAT_EQ(reward_val[d], i+j+0.5); + } + } + } + + for (int i = 0; i < 10; i++) { + for (int j = i+1; j < 10; j++) { + TInt edgeID = Graph->GetEId(i, j); + EXPECT_EQ(Graph->IsEdge(edgeID), true); + + TFltV cost_val = Graph->GetFltVAttrDatE(edgeID, "cost"); + TFltV reward_val = Graph->GetFltVAttrDatE(edgeID, "reward"); + + EXPECT_EQ(cost_val.Len(), 2); + EXPECT_EQ(reward_val.Len(), 2); + + for (int d = 0; d < 2; d++) { + EXPECT_FLOAT_EQ(cost_val[d], i+j+0.5); + EXPECT_FLOAT_EQ(reward_val[d], i+j+0.5); + } + } + } +} + +TEST(TNEANet, IntVDelAttr) { + PNEANet Graph = TNEANet::New(); + TIntV test; + int numNodes = 10; + Graph->AddIntVAttrN("nodeAttrEmpty"); + Graph->AddIntVAttrN("nodeAttrOne"); + Graph->AddIntVAttrN("edgeAttrEmpty"); + Graph->AddIntVAttrN("edgeAttrOne"); + + for (int i = 0; i < 10; ++i) { + Graph->AddNode(i); + + TIntV single; + single.Add(i); + single.Add(i+1); + Graph->AddIntVAttrDatN(i, single, "nodeAttrOne"); + + if (i > 0) { + TInt edgeID = Graph->AddEdge(i-1, i); + single.Add(i-1); + Graph->AddIntVAttrDatE(edgeID, single, "edgeAttrOne"); + } + } + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Graph->DelFromIntVAttrDatN(i, i, "nodeAttrOne"), 0); + EXPECT_EQ(Graph->DelFromIntVAttrDatN(i, i, "nodeAttrEmpty"), -1); + EXPECT_EQ(Graph->DelFromIntVAttrDatN(i, i, "nodeAttrOne"), -1); + + TIntV vec = Graph->GetIntVAttrDatN(i, "nodeAttrOne"); + EXPECT_EQ(vec.Len(), 1); + EXPECT_EQ(vec[0], i+1); + } + + // what about for the edges? + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Graph->IsAttrDeletedN(i, "nodeAttrOne"), false); + EXPECT_EQ(Graph->IsIntVAttrDeletedN(i, "nodeAttrOne"), false); + Graph->DelAttrDatN(i, "nodeAttrOne"); + EXPECT_EQ(Graph->IsAttrDeletedN(i, "nodeAttrOne"), true); + EXPECT_EQ(Graph->IsIntVAttrDeletedN(i, "nodeAttrOne"), true); + + TIntV vec = Graph->GetIntVAttrDatN(i, "nodeAttrOne"); + EXPECT_EQ(vec.Len(), 0); + } + + for (int i = 1; i < 10; ++i) { + TInt edgeID = Graph->GetEId(i-1, i); + EXPECT_EQ(Graph->IsAttrDeletedE(edgeID, "edgeAttrOne"), false); + EXPECT_EQ(Graph->IsIntVAttrDeletedE(edgeID, "edgeAttrOne"), false); + Graph->DelAttrDatE(edgeID, "edgeAttrOne"); + EXPECT_EQ(Graph->IsAttrDeletedE(edgeID, "edgeAttrOne"), true); + EXPECT_EQ(Graph->IsIntVAttrDeletedE(edgeID, "edgeAttrOne"), true); + + TIntV vec = Graph->GetIntVAttrDatE(edgeID, "edgeAttrOne"); + EXPECT_EQ(vec.Len(), 0); + } +} + +TEST(TNEANet, FltVDelAttr) { + PNEANet Graph = TNEANet::New(); + TFltV test; + int numNodes = 10; + Graph->AddFltVAttrN("nodeAttrEmpty"); + Graph->AddFltVAttrN("nodeAttrOne"); + Graph->AddFltVAttrN("edgeAttrEmpty"); + Graph->AddFltVAttrN("edgeAttrOne"); + + for (int i = 0; i < 10; ++i) { + Graph->AddNode(i); + + TFltV single; + single.Add(i-1.5); + single.Add(i+1.5); + Graph->AddFltVAttrDatN(i, single, "nodeAttrOne"); + + if (i > 0) { + TInt edgeID = Graph->AddEdge(i-1, i); + single.Add(i-1); + Graph->AddFltVAttrDatE(edgeID, single, "edgeAttrOne"); + } + } + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Graph->DelFromFltVAttrDatN(i, i-1.5, "nodeAttrOne"), 0); + EXPECT_EQ(Graph->DelFromFltVAttrDatN(i, i-1.5, "nodeAttrEmpty"), -1); + EXPECT_EQ(Graph->DelFromFltVAttrDatN(i, i-1.5, "nodeAttrOne"), -1); + + TFltV vec = Graph->GetFltVAttrDatN(i, "nodeAttrOne"); + EXPECT_EQ(vec.Len(), 1); + EXPECT_FLOAT_EQ(vec[0], i+1.5); + } + + // what about for the edges? + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Graph->IsAttrDeletedN(i, "nodeAttrOne"), false); + EXPECT_EQ(Graph->IsFltVAttrDeletedN(i, "nodeAttrOne"), false); + Graph->DelAttrDatN(i, "nodeAttrOne"); + EXPECT_EQ(Graph->IsAttrDeletedN(i, "nodeAttrOne"), true); + EXPECT_EQ(Graph->IsFltVAttrDeletedN(i, "nodeAttrOne"), true); + + TFltV vec = Graph->GetFltVAttrDatN(i, "nodeAttrOne"); + EXPECT_EQ(vec.Len(), 0); + } + + for (int i = 1; i < 10; ++i) { + TInt edgeID = Graph->GetEId(i-1, i); + EXPECT_EQ(Graph->IsAttrDeletedE(edgeID, "edgeAttrOne"), false); + EXPECT_EQ(Graph->IsFltVAttrDeletedE(edgeID, "edgeAttrOne"), false); + Graph->DelAttrDatE(edgeID, "edgeAttrOne"); + EXPECT_EQ(Graph->IsAttrDeletedE(edgeID, "edgeAttrOne"), true); + EXPECT_EQ(Graph->IsFltVAttrDeletedE(edgeID, "edgeAttrOne"), true); + + TFltV vec = Graph->GetFltVAttrDatE(edgeID, "edgeAttrOne"); + EXPECT_EQ(vec.Len(), 0); + } +} + +TEST(TNEANet, IntVIterator) { + PNEANet Graph = TNEANet::New(); + int numNodes = 10; + TStr TestAttrNodes("path"); + TStr TestAttrEdges("line"); + TStr TestAttrNodesSparse("path_sparse"); + TStr TestAttrEdgesSparse("line_sparse"); + Graph->AddIntVAttrN(TestAttrNodes); + Graph->AddIntVAttrE(TestAttrEdges); + Graph->AddIntVAttrN(TestAttrNodesSparse, false); + Graph->AddIntVAttrE(TestAttrEdgesSparse, false); + + Graph->AddNode(0); + for (int i = 1; i < numNodes; i++) { + Graph->AddNode(i); + Graph->AddEdge(i-1, i); + } + + for (int i = 0; i < numNodes; i++) { + TIntV testVB; + testVB.Add(i); + Graph->AddIntVAttrDatN(i, testVB, TestAttrNodes); + Graph->AddIntVAttrDatN(i, testVB, TestAttrNodesSparse, false); + + if (i > 0) { + TInt edgeID = Graph->GetEId(i-1, i); + Graph->AddIntVAttrDatE(edgeID, testVB, TestAttrEdges); + Graph->AddIntVAttrDatE(edgeID, testVB, TestAttrEdgesSparse, false); + } + } + + int count = 0; + TVec > nodeAttrs = TVec >(); + TVec > edgeAttrs = TVec >(); + TVec > nodeAttrsSparse = TVec >(); + TVec > edgeAttrsSparse = TVec >(); + + for (TNEANet::TAIntVI NI = Graph->BegNAIntVI(TestAttrNodes); NI < Graph->EndNAIntVI(TestAttrNodes); NI++) { + nodeAttrs.Add(NI.GetDat()); + } + + for (TNEANet::TAIntVI EI = Graph->BegEAIntVI(TestAttrEdges); EI < Graph->EndEAIntVI(TestAttrEdges); EI++) { + edgeAttrs.Add(EI.GetDat()); + } + + for (TNEANet::TAIntVI NI = Graph->BegNAIntVI(TestAttrNodesSparse); NI < Graph->EndNAIntVI(TestAttrNodesSparse); NI++) { + nodeAttrsSparse.Add(NI.GetDat()); + } + + for (TNEANet::TAIntVI EI = Graph->BegEAIntVI(TestAttrEdgesSparse); EI < Graph->EndEAIntVI(TestAttrEdgesSparse); EI++) { + edgeAttrsSparse.Add(EI.GetDat()); + } + + EXPECT_EQ(nodeAttrs.Len(), numNodes); + EXPECT_EQ(edgeAttrs.Len(), numNodes-1); + EXPECT_EQ(nodeAttrsSparse.Len(), numNodes); + EXPECT_EQ(edgeAttrsSparse.Len(), numNodes-1); + + for (int i = 0; i < numNodes; i++) { + TIntV testVB; + testVB.Add(i); + EXPECT_EQ(nodeAttrs.IsIn(testVB), true); + EXPECT_EQ(nodeAttrsSparse.IsIn(testVB), true); + + if (i > 0) { + EXPECT_EQ(edgeAttrs.IsIn(testVB), true); + EXPECT_EQ(edgeAttrsSparse.IsIn(testVB), true); + } + } + +} + +TEST(TNEANet, FltVIterator) { + PNEANet Graph = TNEANet::New(); + int numNodes = 10; + TStr TestAttrNodes("path"); + TStr TestAttrEdges("line"); + TStr TestAttrNodesSparse("path_sparse"); + TStr TestAttrEdgesSparse("line_sparse"); + Graph->AddFltVAttrN(TestAttrNodes); + Graph->AddFltVAttrE(TestAttrEdges); + Graph->AddFltVAttrN(TestAttrNodesSparse, false); + Graph->AddFltVAttrE(TestAttrEdgesSparse, false); + + Graph->AddNode(0); + for (int i = 1; i < numNodes; i++) { + Graph->AddNode(i); + Graph->AddEdge(i-1, i); + } + + for (int i = 0; i < numNodes; i++) { + TFltV testVB; + testVB.Add(i+0.5); + Graph->AddFltVAttrDatN(i, testVB, TestAttrNodes); + Graph->AddFltVAttrDatN(i, testVB, TestAttrNodesSparse, false); + + if (i > 0) { + TInt edgeID = Graph->GetEId(i-1, i); + Graph->AddFltVAttrDatE(edgeID, testVB, TestAttrEdges); + Graph->AddFltVAttrDatE(edgeID, testVB, TestAttrEdgesSparse, false); + } + } + + int count = 0; + TVec > nodeAttrs = TVec >(); + TVec > edgeAttrs = TVec >(); + TVec > nodeAttrsSparse = TVec >(); + TVec > edgeAttrsSparse = TVec >(); + + for (TNEANet::TAFltVI NI = Graph->BegNAFltVI(TestAttrNodes); NI < Graph->EndNAFltVI(TestAttrNodes); NI++) { + nodeAttrs.Add(NI.GetDat()); + } + + for (TNEANet::TAFltVI EI = Graph->BegEAFltVI(TestAttrEdges); EI < Graph->EndEAFltVI(TestAttrEdges); EI++) { + edgeAttrs.Add(EI.GetDat()); + } + + for (TNEANet::TAFltVI NI = Graph->BegNAFltVI(TestAttrNodesSparse); NI < Graph->EndNAFltVI(TestAttrNodesSparse); NI++) { + nodeAttrsSparse.Add(NI.GetDat()); + } + + for (TNEANet::TAFltVI EI = Graph->BegEAFltVI(TestAttrEdgesSparse); EI < Graph->EndEAFltVI(TestAttrEdgesSparse); EI++) { + edgeAttrsSparse.Add(EI.GetDat()); + } + + EXPECT_EQ(nodeAttrs.Len(), numNodes); + EXPECT_EQ(edgeAttrs.Len(), numNodes-1); + EXPECT_EQ(nodeAttrsSparse.Len(), numNodes); + EXPECT_EQ(edgeAttrsSparse.Len(), numNodes-1); + + for (int i = 0; i < numNodes; i++) { + TFltV testVB; + testVB.Add(i + 0.5); + EXPECT_EQ(nodeAttrs.IsIn(testVB), true); + EXPECT_EQ(nodeAttrsSparse.IsIn(testVB), true); + + if (i > 0) { + EXPECT_EQ(edgeAttrs.IsIn(testVB), true); + EXPECT_EQ(edgeAttrsSparse.IsIn(testVB), true); + } + } + +} + + // Test node, edge attribute functionality TEST(TNEANet, ManipulateNodesEdgeAttributes) { int NNodes = 1000; @@ -584,7 +1067,9 @@ TEST(TNEANet, AddSAttrN) { PNEANet Graph; Graph = TNEANet::New(); TInt AttrId; + //std::cout << "NO crash?" << std::endl; int status = Graph->AddSAttrN("TestInt", atInt, AttrId); + //std::cout << "NO crash?" << std::endl; EXPECT_EQ(0, status); EXPECT_EQ(0, AttrId.Val); status = Graph->AddSAttrN("TestFlt", atFlt, AttrId); diff --git a/test/test-bfsdfs.cpp b/test/test-bfsdfs.cpp index 246fd19a5..630312a74 100644 --- a/test/test-bfsdfs.cpp +++ b/test/test-bfsdfs.cpp @@ -94,6 +94,11 @@ void TestFullBfsDfs() { EXPECT_TRUE(FullDiam == 1); EXPECT_TRUE(AvgDiam > 0.9980 - EPSILON && AvgDiam < 0.9980 + EPSILON); + EffDiam = GetBfsEffDiamAll (G, NTestNodes, IsDir, EffDiam, FullDiam, AvgDiam); + EXPECT_TRUE(EffDiam > 0.8 - EPSILON && EffDiam < 0.95 + EPSILON); + EXPECT_TRUE(FullDiam == 1); + EXPECT_TRUE(AvgDiam > 0.9980 - EPSILON && AvgDiam < 0.9980 + EPSILON); + TIntV SubGraphNIdV; for (int i = 0; i < NTestNodes; i++) { SubGraphNIdV.Add(G->GetRndNId()); diff --git a/test/test-gviz.cpp b/test/test-gviz.cpp index d0e7e0a1a..62cf496d1 100644 --- a/test/test-gviz.cpp +++ b/test/test-gviz.cpp @@ -57,6 +57,7 @@ TEST(GVizTest, DrawGViz) { else { TSnap::DrawGViz(UNGraph1, TGVizLayout(i), FNameTest, LNames[i], true); } + // Check if file exists EXPECT_TRUE(fileExists(FNameTest.CStr())); @@ -141,7 +142,7 @@ TEST(GVizTest, DrawGVizColor) { true, NIdColorH); } } - + // Check if file exists EXPECT_TRUE(fileExists(FNameTest.CStr())); } diff --git a/test/test-subgraph.cpp b/test/test-subgraph.cpp index 67c34c45c..93fa26b7a 100644 --- a/test/test-subgraph.cpp +++ b/test/test-subgraph.cpp @@ -5,6 +5,9 @@ PUNGraph GetTestTUNGraph(); PNGraph GetTestTNGraph(); PNEGraph GetTestTNEGraph(); +PNEANet GetTestTNEANet(); +PUNGraph GetUPetersen(); +PNGraph GetDPetersen(); TPt > GetTestTNodeEDatNet(); TPt > GetTestTNodeEdgeNet(); @@ -14,6 +17,7 @@ TEST(subgraph, TestSubTUNGraphs) { PUNGraph Graph1; PUNGraph Graph2; PUNGraph Graph3; + PUNGraph Graph4; int i; TIntV NIdV; TIntV NIdV1; @@ -41,6 +45,10 @@ TEST(subgraph, TestSubTUNGraphs) { Graph3 = TSnap::GetSubGraph(Graph, NIdV1, true); EXPECT_EQ(10,Graph3->GetNodes()); EXPECT_EQ(10,Graph3->GetEdges()); + + Graph4 = TSnap::GetSubGraphRenumber(Graph, NIdV1); + EXPECT_EQ(10,Graph4->GetNodes()); + EXPECT_EQ(10,Graph4->GetEdges()); } // Test subgraphs @@ -49,6 +57,7 @@ TEST(subgraph, TestSubTNGraphs) { PNGraph Graph1; PNGraph Graph2; PNGraph Graph3; + PNGraph Graph4; int i; TIntV NIdV; TIntV NIdV1; @@ -76,6 +85,10 @@ TEST(subgraph, TestSubTNGraphs) { Graph3 = TSnap::GetSubGraph(Graph, NIdV1, true); EXPECT_EQ(10,Graph3->GetNodes()); EXPECT_EQ(10,Graph3->GetEdges()); + + Graph4 = TSnap::GetSubGraphRenumber(Graph, NIdV1); + EXPECT_EQ(10,Graph4->GetNodes()); + EXPECT_EQ(10,Graph4->GetEdges()); } // Test subgraphs @@ -305,6 +318,689 @@ TEST(subgraph, TestGetRndGraphs) { EXPECT_EQ(10,NGraph3->GetEdges()); } +// Test GetEgonet +TEST(subgraph, TestGetEgonet) { + + PUNGraph UGraph = GetUPetersen(); + for (int i = 0; i < 10; i++) { + int Edges; + PUNGraph Ego = TSnap::GetEgonet(UGraph, i, Edges); + EXPECT_EQ(4, Ego->GetNodes()); + EXPECT_EQ(3, Ego->GetEdges()); + EXPECT_EQ(6, Edges); + } + + PNGraph Graph = GetDPetersen(); + for (int i = 0; i < 10; i++) { + int EdgesIn, EdgesOut; + PNGraph Ego = TSnap::GetEgonet(Graph, i, EdgesIn, EdgesOut); + EXPECT_EQ(4, Ego->GetNodes()); + EXPECT_EQ(3, Ego->GetEdges()); + if (i < 5) { + EXPECT_EQ(2, EdgesIn); + EXPECT_EQ(4, EdgesOut); + } else { + EXPECT_EQ(4, EdgesIn); + EXPECT_EQ(2, EdgesOut); + } + } +} + +// Test TNGraph GetEgoNetHop +TEST(subgraph, TestGetInEgonetHopTNGraph) { + // Test on TNSmall Graph + PNGraph Small = TNGraph::GetSmallGraph(); + PNGraph ego1 = TSnap::GetInEgonetHop(Small, 4, 1); + EXPECT_EQ(2, ego1->GetNodes()); + EXPECT_EQ(1, ego1->GetEdges()); + PNGraph ego2 = TSnap::GetInEgonetHop(Small, 4, 2); + EXPECT_EQ(4, ego2->GetNodes()); + EXPECT_EQ(4, ego2->GetEdges()); + PNGraph ego3 = TSnap::GetInEgonetHop(Small, 4, 3); + EXPECT_EQ(5, ego3->GetNodes()); + EXPECT_EQ(6, ego3->GetEdges()); + + // Middle Size TN graph + PNGraph Middle = TNGraph::New(); + for (int i = 0; i < 6; i++) { + Middle->AddNode(i); + } + for (int i = 0; i < 6; i++) { + Middle->AddEdge(i, (i + 1) % 6); + Middle->AddEdge(i, (i + 2) % 6); + } + EXPECT_EQ(12, Middle->GetEdges()); + PNGraph midego2 = TSnap::GetInEgonetHop(Middle, 0, 2); + EXPECT_EQ(5, midego2->GetNodes()); + EXPECT_EQ(8, midego2->GetEdges()); + PNGraph midego3 = TSnap::GetInEgonetHop(Middle, 0, 3); + EXPECT_EQ(6, midego3->GetNodes()); + EXPECT_EQ(12, midego3->GetEdges()); + + // Larger TN Graph + PNGraph Graph; + PNGraph Graph0; + PNGraph Graph1; + PNGraph Graph2; + PNGraph Graph3; + PNGraph Graph4; + PNGraph Graph5; + PNGraph Graph6; + PNGraph Graph7; + + Graph = GetTestTNGraph(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetHop(Graph, 0, 0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + + Graph1 = TSnap::GetInEgonetHop(Graph, 3, 1); + EXPECT_EQ(4, Graph1->GetNodes()); + EXPECT_EQ(6, Graph1->GetEdges()); + + Graph2 = TSnap::GetInEgonetHop(Graph, 6, 2); + EXPECT_EQ(7, Graph2->GetNodes()); + EXPECT_EQ(15, Graph2->GetEdges()); + + Graph3 = TSnap::GetInEgonetHop(Graph, 9, 3); + EXPECT_EQ(10, Graph3->GetNodes()); + EXPECT_EQ(24, Graph3->GetEdges()); + + Graph4 = TSnap::GetInEgonetHop(Graph, 12, 4); + EXPECT_EQ(13, Graph4->GetNodes()); + EXPECT_EQ(33, Graph4->GetEdges()); + + Graph5 = TSnap::GetInEgonetHop(Graph, 15, 5); + EXPECT_EQ(16, Graph5->GetNodes()); + EXPECT_EQ(42, Graph5->GetEdges()); + + Graph6 = TSnap::GetInEgonetHop(Graph, 18, 6); + EXPECT_EQ(19, Graph6->GetNodes()); + EXPECT_EQ(54, Graph6->GetEdges()); + + Graph7 = TSnap::GetInEgonetHop(Graph, 1, 7); + EXPECT_EQ(20, Graph7->GetNodes()); + EXPECT_EQ(60, Graph7->GetEdges()); +} + +// Test TUNGraph GetInEgonetHop +TEST(subgraph, TestGetInEgonetHopTUNGraph) { + PUNGraph Graph; + PUNGraph Graph0; + PUNGraph Graph1; + PUNGraph Graph2; + PUNGraph Graph3; + PUNGraph Graph4; + + Graph = GetTestTUNGraph(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetHop(Graph, 3, 0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + + Graph1 = TSnap::GetInEgonetHop(Graph, 0, 1); + EXPECT_EQ(7, Graph1->GetNodes()); + EXPECT_EQ(15, Graph1->GetEdges()); + + Graph2 = TSnap::GetInEgonetHop(Graph, 7, 2); + EXPECT_EQ(13, Graph2->GetNodes()); + EXPECT_EQ(33, Graph2->GetEdges()); + + Graph3 = TSnap::GetInEgonetHop(Graph, 19, 3); + EXPECT_EQ(19, Graph3->GetNodes()); + EXPECT_EQ(54, Graph3->GetEdges()); + + Graph4 = TSnap::GetInEgonetHop(Graph, 8, 4); + EXPECT_EQ(20, Graph4->GetNodes()); + EXPECT_EQ(60, Graph4->GetEdges()); +} + +// Test TNEANet GetInEgonetAttr +TEST(subgraph, TestGetInEgonetsAttr) { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + PNEANet Graph3; + PNEANet Graph4; + PNEANet Graph5; + PNEANet Graph6; + PNEANet Graph7; + const TStr s = "id"; + + Graph = GetTestTNEANet(); + //Graph->Dump(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetAttr(Graph, 0, 0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + for (TNEANet::TNodeI NI = Graph0->BegNI(); NI < Graph0->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph0->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph0->BegEI(); EI < Graph0->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph0->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph1 = TSnap::GetInEgonetAttr(Graph, 3, 1); + //Graph1->Dump(); + EXPECT_EQ(4, Graph1->GetNodes()); + EXPECT_EQ(6, Graph1->GetEdges()); + for (TNEANet::TNodeI NI = Graph1->BegNI(); NI < Graph1->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph1->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph1->BegEI(); EI < Graph1->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph1->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph2 = TSnap::GetInEgonetAttr(Graph, 6, 2); + EXPECT_EQ(7, Graph2->GetNodes()); + EXPECT_EQ(15, Graph2->GetEdges()); + for (TNEANet::TNodeI NI = Graph2->BegNI(); NI < Graph2->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph2->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph2->BegEI(); EI < Graph2->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph2->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph3 = TSnap::GetInEgonetAttr(Graph, 9, 3); + EXPECT_EQ(10, Graph3->GetNodes()); + EXPECT_EQ(24, Graph3->GetEdges()); + for (TNEANet::TNodeI NI = Graph3->BegNI(); NI < Graph3->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph3->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph3->BegEI(); EI < Graph3->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph3->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph4 = TSnap::GetInEgonetAttr(Graph, 12, 4); + EXPECT_EQ(13, Graph4->GetNodes()); + EXPECT_EQ(33, Graph4->GetEdges()); + for (TNEANet::TNodeI NI = Graph4->BegNI(); NI < Graph4->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph4->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph4->BegEI(); EI < Graph4->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph4->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph5 = TSnap::GetInEgonetAttr(Graph, 15, 5); + EXPECT_EQ(16, Graph5->GetNodes()); + EXPECT_EQ(42, Graph5->GetEdges()); + for (TNEANet::TNodeI NI = Graph5->BegNI(); NI < Graph5->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph5->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph5->BegEI(); EI < Graph5->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph5->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph6 = TSnap::GetInEgonetAttr(Graph, 18, 6); + EXPECT_EQ(19, Graph6->GetNodes()); + EXPECT_EQ(54, Graph6->GetEdges()); + for (TNEANet::TNodeI NI = Graph6->BegNI(); NI < Graph6->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph6->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph6->BegEI(); EI < Graph6->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph6->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph7 = TSnap::GetInEgonetAttr(Graph, 1, 7); + EXPECT_EQ(20, Graph7->GetNodes()); + EXPECT_EQ(60, Graph7->GetEdges()); + for (TNEANet::TNodeI NI = Graph7->BegNI(); NI < Graph7->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph7->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph7->BegEI(); EI < Graph7->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph7->GetIntAttrDatE(EI.GetId(), s)); + } +} + +// Test TUNGraph GetInEgonetSub +TEST(subgraph, TestGetInEgonetSubTUNGraph) { + PUNGraph Graph; + PUNGraph Graph0; + PUNGraph Graph1; + PUNGraph Graph2; + + Graph = GetTestTUNGraph(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetSub(Graph, 3, 0, 2, 1.0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + + Graph1 = TSnap::GetInEgonetSub(Graph, 0, 1, 3, -1.0); + EXPECT_EQ(4, Graph1->GetNodes()); + EXPECT_LE(4, Graph1->GetEdges()); + EXPECT_GE(6, Graph1->GetEdges()); + + Graph2 = TSnap::GetInEgonetSub(Graph, 0, 1, 0, 0.9); + EXPECT_EQ(6, Graph2->GetNodes()); + EXPECT_LE(10, Graph2->GetEdges()); + EXPECT_GE(12, Graph2->GetEdges()); +} + +// Test TUNGraph GetInEgonetSub +TEST(subgraph, TestGetInEgonetSubTNGraph) { + PNGraph Graph; + PNGraph Graph0; + PNGraph Graph1; + PNGraph Graph2; + + Graph = GetTestTNGraph(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetSub(Graph, 3, 0, 2, 1.0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + + Graph1 = TSnap::GetInEgonetSub(Graph, 0, 1, 2, -1.0); + EXPECT_EQ(3, Graph1->GetNodes()); + EXPECT_EQ(3, Graph1->GetEdges()); + + Graph2 = TSnap::GetInEgonetSub(Graph, 0, 1, 0, 0.9); + EXPECT_EQ(3, Graph2->GetNodes()); + EXPECT_EQ(3, Graph2->GetEdges()); +} + +// Test TNEANet GetInEgonetSub +TEST(subgraph, TestGetInEgonetSubTNEANet) { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + + Graph = GetTestTNEANet(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetSub(Graph, 3, 0, 2, 1.0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + + Graph1 = TSnap::GetInEgonetSub(Graph, 0, 1, 2, -1.0); + EXPECT_EQ(3, Graph1->GetNodes()); + EXPECT_EQ(3, Graph1->GetEdges()); + + Graph2 = TSnap::GetInEgonetSub(Graph, 0, 1, 0, 0.9); + EXPECT_EQ(3, Graph2->GetNodes()); + EXPECT_EQ(3, Graph2->GetEdges()); +} + +// Test TNEANet GetEgonetAttr +TEST(subgraph, TestGetEgonetAttr) { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + const TStr s = "id"; + + Graph = GetTestTNEANet(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetEgonetAttr(Graph, 3, 0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + for (TNEANet::TNodeI NI = Graph0->BegNI(); NI < Graph0->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph0->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph0->BegEI(); EI < Graph0->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph0->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph1 = TSnap::GetEgonetAttr(Graph, 4, 1); + EXPECT_EQ(7, Graph1->GetNodes()); + EXPECT_EQ(15, Graph1->GetEdges()); + for (TNEANet::TNodeI NI = Graph1->BegNI(); NI < Graph1->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph1->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph1->BegEI(); EI < Graph1->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph1->GetIntAttrDatE(EI.GetId(), s)); + } + + Graph2 = TSnap::GetEgonetAttr(Graph, 4, 2); + EXPECT_EQ(13, Graph2->GetNodes()); + EXPECT_EQ(33, Graph2->GetEdges()); + for (TNEANet::TNodeI NI = Graph2->BegNI(); NI < Graph2->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph2->GetIntAttrDatN(NI.GetId(), s)); + } + for (TNEANet::TEdgeI EI = Graph2->BegEI(); EI < Graph2->EndEI(); EI++) { + EXPECT_EQ(EI.GetSrcNId() + EI.GetDstNId(), Graph2->GetIntAttrDatE(EI.GetId(), s)); + } +} + +// Test TNEANet GetInEgonetAttr +TEST(subgraph, TestGetInEgonetAttr) { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + const TStr s = "id"; + + Graph = GetTestTNEANet(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetAttr(Graph, 3, 0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + for (TNEANet::TNodeI NI = Graph0->BegNI(); NI < Graph0->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph0->GetIntAttrDatN(NI.GetId(), s)); + } + + Graph1 = TSnap::GetInEgonetAttr(Graph, 4, 1); + EXPECT_EQ(4, Graph1->GetNodes()); + EXPECT_EQ(6, Graph1->GetEdges()); + for (TNEANet::TNodeI NI = Graph1->BegNI(); NI < Graph1->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph1->GetIntAttrDatN(NI.GetId(), s)); + } + + Graph2 = TSnap::GetInEgonetAttr(Graph, 4, 2); + EXPECT_EQ(7, Graph2->GetNodes()); + EXPECT_EQ(15, Graph2->GetEdges()); + for (TNEANet::TNodeI NI = Graph2->BegNI(); NI < Graph2->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph2->GetIntAttrDatN(NI.GetId(), s)); + } +} + +// Test TNEANet GetOutEgonetAttr +TEST(subgraph, TestGetOutEgonetAttr) { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + const TStr s = "id"; + + Graph = GetTestTNEANet(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetOutEgonetAttr(Graph, 3, 0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + for (TNEANet::TNodeI NI = Graph0->BegNI(); NI < Graph0->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph0->GetIntAttrDatN(NI.GetId(), s)); + } + + Graph1 = TSnap::GetOutEgonetAttr(Graph, 4, 1); + EXPECT_EQ(4, Graph1->GetNodes()); + EXPECT_EQ(6, Graph1->GetEdges()); + for (TNEANet::TNodeI NI = Graph1->BegNI(); NI < Graph1->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph1->GetIntAttrDatN(NI.GetId(), s)); + } + + Graph2 = TSnap::GetOutEgonetAttr(Graph, 4, 2); + EXPECT_EQ(7, Graph2->GetNodes()); + EXPECT_EQ(15, Graph2->GetEdges()); + for (TNEANet::TNodeI NI = Graph2->BegNI(); NI < Graph2->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph2->GetIntAttrDatN(NI.GetId(), s)); + } +} + +// Test TNEANet GetInEgonetSubAttr +TEST(subgraph, TestGetInEgonetSubAttr) { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + const TStr s = "id"; + + Graph = GetTestTNEANet(); + EXPECT_EQ(20, Graph->GetNodes()); + EXPECT_EQ(60, Graph->GetEdges()); + + Graph0 = TSnap::GetInEgonetSubAttr(Graph, 3, 0, 2, 1.0); + EXPECT_EQ(1, Graph0->GetNodes()); + EXPECT_EQ(0, Graph0->GetEdges()); + for (TNEANet::TNodeI NI = Graph0->BegNI(); NI < Graph0->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph0->GetIntAttrDatN(NI.GetId(), s)); + } + + Graph1 = TSnap::GetInEgonetSubAttr(Graph, 0, 1, 2, -1.0); + EXPECT_EQ(3, Graph1->GetNodes()); + EXPECT_EQ(3, Graph1->GetEdges()); + for (TNEANet::TNodeI NI = Graph1->BegNI(); NI < Graph1->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph1->GetIntAttrDatN(NI.GetId(), s)); + } + + Graph2 = TSnap::GetInEgonetSubAttr(Graph, 0, 1, 0, 0.9); + EXPECT_EQ(3, Graph2->GetNodes()); + EXPECT_EQ(3, Graph2->GetEdges()); + for (TNEANet::TNodeI NI = Graph2->BegNI(); NI < Graph2->EndNI(); NI++) { + EXPECT_EQ(NI.GetId(), Graph2->GetIntAttrDatN(NI.GetId(), s)); + } +} + +// Test PGraph GetGraphUnion +TEST(subgraph, TestGetGraphUnion) { + //Undirected graph + PUNGraph Graph = TUNGraph::New(); + PUNGraph Graph0 = TUNGraph::New(); + + for (int i = 0; i < 5; i++) { + Graph->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,(i+1) % 5); + Graph->AddEdge(i,(i+2) % 5); + } + for (int i = 3; i < 8; i++) { + Graph0->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph0->AddEdge(i + 3,((i+1) % 5) + 3); + } + TSnap::GetGraphUnion(Graph, Graph0); + EXPECT_EQ(8, Graph->GetNodes()); + EXPECT_EQ(14, Graph->GetEdges()); + + //Directed graph + PNGraph Graph1 = TNGraph::New(); + PNGraph Graph2 = TNGraph::New(); + for (int i = 0; i < 4; i++) { + Graph1->AddNode(i); + } + for (int i = 1; i < 5; i++) { + Graph2->AddNode(i); + } + + Graph1->AddEdge(0, 1); + Graph1->AddEdge(1, 2); + Graph2->AddEdge(1, 2); + Graph2->AddEdge(2, 1); + Graph1->AddEdge(2, 3); + Graph2->AddEdge(2, 3); + Graph1->AddEdge(3, 2); + Graph2->AddEdge(3, 4); + Graph2->AddEdge(1, 4); + + TSnap::GetGraphUnion(Graph1, Graph2); + EXPECT_EQ(5, Graph1->GetNodes()); + EXPECT_EQ(7, Graph1->GetEdges()); + + //Directed multigraph + PNEANet Graph3 = TNEANet::New(); + PNEANet Graph4 = TNEANet::New(); + int EId = 0; + for (int i = 0; i < 4; i++) { + Graph3->AddNode(i); + } + for (int i = 1; i < 5; i++) { + Graph4->AddNode(i); + } + + Graph3->AddEdge(0, 1, EId++); + Graph3->AddEdge(1, 2, EId++); + Graph4->AddEdge(1, 2, EId++); + Graph4->AddEdge(2, 1, EId++); + Graph3->AddEdge(2, 3, EId); + Graph4->AddEdge(2, 3, EId++); + Graph3->AddEdge(3, 2, EId++); + Graph4->AddEdge(3, 4, EId++); + Graph4->AddEdge(1, 4, EId++); + + TSnap::GetGraphUnion(Graph3, Graph4); + EXPECT_EQ(5, Graph3->GetNodes()); + EXPECT_EQ(7, Graph3->GetEdges()); +} + + +// Test PGraph GetGraphUnionAttr +TEST(subgraph, TestGetGraphUnionAttr) { + PNEANet Graph = PNEANet::New(); + PNEANet Graph0 = PNEANet::New(); + + TStr s = "id"; + int EId; + for (int i = 0; i < 6; i++) { + Graph->AddNode(i); + Graph->AddIntAttrDatN(i, i, s); + } + + for (int i = 3; i < 9; i++) { + Graph0->AddNode(i); + Graph0->AddIntAttrDatN(i, i, s); + } + + for (int i = 0; i < 6; i++) { + EId = Graph->AddEdge(i, (i + 2) % 6); + Graph->AddIntAttrDatE(EId, (i + 2) % 6, s); + EId = Graph->AddEdge(i, (i + 5) % 6); + Graph->AddIntAttrDatE(EId, (i + 5) % 6, s); + } + + for (int i = 0; i < 6; i++) { + EId = Graph0->AddEdge(i + 3, ((i + 3) % 6) + 3); + Graph0->AddIntAttrDatE(EId, ((i + 3) % 6) + 3, s); + EId = Graph0->AddEdge(i + 3, ((i + 4) % 6) + 3); + Graph0->AddIntAttrDatE(EId, ((i + 4) % 6) + 3, s); + } + + TSnap::GetGraphUnionAttr(Graph, Graph0); + EXPECT_EQ(9, Graph->GetNodes()); + EXPECT_EQ(24, Graph->GetEdges()); +} + +// Test PGraph GetGraphIntersection +TEST(subgraph, TestGetGraphIntersection) { + //Undirected graph + PUNGraph Graph = TUNGraph::New(); + PUNGraph Graph0 = TUNGraph::New(); + + for (int i = 0; i < 5; i++) { + Graph->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,(i + 1) % 5); + Graph->AddEdge(i,(i + 2) % 5); + } + + for (int i = 2; i < 6; i++) { + Graph0->AddNode(i); + } + for (int i = 0; i < 4; i++) { + Graph0->AddEdge(i + 2, ((i + 1) % 4) + 2); + Graph0->AddEdge(i + 2, ((i + 2) % 4) + 2); + } + + PUNGraph IntersectionGraph = TSnap::GetGraphIntersection(Graph, Graph0); + EXPECT_EQ(3, IntersectionGraph->GetNodes()); + EXPECT_EQ(3, IntersectionGraph->GetEdges()); + + //Directed graph + PNGraph Graph1 = TNGraph::New(); + PNGraph Graph2 = TNGraph::New(); + + for (int i = 0; i < 8; i++) { + Graph1->AddNode(i); + } + for (int i = 0; i < 8; i++) { + Graph1->AddEdge(i, (i + 1) % 8); + Graph1->AddEdge((i + 1) % 8, i); + } + + for (int i = 2; i < 6; i++) { + Graph2->AddNode(i); + } + for (int i = 0; i < 4; i++) { + Graph2->AddEdge(i + 2, ((i + 1) % 4) + 2); + Graph2->AddEdge(i + 2, ((i + 2) % 4) + 2); + } + + PNGraph IntersectionGraph0 = TSnap::GetGraphIntersection(Graph1, Graph2); + EXPECT_EQ(4, IntersectionGraph0->GetNodes()); + EXPECT_EQ(3, IntersectionGraph0->GetEdges()); + + //Directed multigraph + PNEANet Graph3 = TNEANet::New(); + PNEANet Graph4 = TNEANet::New(); + int EId3 = 0; + int EId4 = 1; + + for (int i = 0; i < 4; i++) { + Graph3->AddNode(i); + } + for (int i = 0; i < 3; i++) { + Graph3->AddEdge(i, i + 1, EId3++); + } + Graph3->AddEdge(1, 0, EId3++); + Graph3->AddEdge(1, 2, EId3++); + Graph3->AddEdge(3, 2, EId3++); + + for (int i = 1; i < 5; i++) { + Graph4->AddNode(i); + } + for (int i = 1; i < 4; i++) { + Graph4->AddEdge(i + 1, i, EId4 + 3); + Graph4->AddEdge(i, i + 1, EId4++); + } + + PNEANet IntersectionGraph1 = TSnap::GetGraphIntersection(Graph3, Graph4); + EXPECT_EQ(3, IntersectionGraph1->GetNodes()); + EXPECT_EQ(3, IntersectionGraph1->GetEdges()); +} + +// Test PNEANet GetGraphIntersectionAttr +TEST(subgraph, TestGetGraphIntersectionAttr) { + PNEANet Graph = PNEANet::New(); + PNEANet Graph0 = PNEANet::New(); + + TStr s = "id"; + int EId; + for (int i = 0; i < 7; i++) { + Graph->AddNode(i); + Graph->AddIntAttrDatN(i, i, s); + } + + for (int i = 2; i < 9; i++) { + Graph0->AddNode(i); + Graph0->AddIntAttrDatN(i, i, s); + } + + for (int i = 0; i < 7; i++) { + EId = Graph->AddEdge(i, (i + 2) % 7); + Graph->AddIntAttrDatE(EId, (i + 2) % 7, s); + EId = Graph->AddEdge(i, (i + 3) % 7); + Graph->AddIntAttrDatE(EId, (i + 3) % 7, s); + } + + for (int i = 0; i < 7; i++) { + EId = Graph0->AddEdge(i + 2, ((i + 3) % 7) + 2); + Graph0->AddIntAttrDatE(EId, ((i + 3) % 7) + 2, s); + } + + PNEANet IntersectionGraph = TSnap::GetGraphIntersectionAttr(Graph, Graph0); + EXPECT_EQ(5, IntersectionGraph->GetNodes()); + EXPECT_EQ(3, IntersectionGraph->GetEdges()); +} + // Generate TUNGraph PUNGraph GetTestTUNGraph() { PUNGraph Graph = TUNGraph::New(); @@ -339,6 +1035,31 @@ PNGraph GetTestTNGraph() { return Graph; } +// Generate TNEANet +PNEANet GetTestTNEANet() { + PNEANet Graph = PNEANet::New(); + TStr s = "id"; + int EId; + + for (int i = 0; i < 20; i++) { + Graph->AddNode(i); + Graph->AddIntAttrDatN(i, i, s); + } + + for (int i = 0; i < 20; i++) { + EId = Graph->AddEdge(i, (i + 1) % 20); + Graph->AddIntAttrDatE(EId, i + (i + 1) % 20, s); + + EId = Graph->AddEdge(i, (i + 2) % 20); + Graph->AddIntAttrDatE(EId, i + (i + 2) % 20, s); + + EId = Graph->AddEdge(i, (i + 3) % 20); + Graph->AddIntAttrDatE(EId, i + (i + 3) % 20, s); + } + + return Graph; +} + // Generate TNEGraph PNEGraph GetTestTNEGraph() { PNEGraph Graph = TNEGraph::New(); @@ -359,6 +1080,46 @@ PNEGraph GetTestTNEGraph() { return Graph; } +// Generate TUNGraph Petersen graph +PUNGraph GetUPetersen() { + PUNGraph Graph = TUNGraph::New(); + + for (int i = 0; i < 10; i++) { + Graph->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,(i+1) % 5); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i + 5,(i+2) % 5 + 5); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,i + 5); + } + + return Graph; +} + +// Generate TNGraph Petersen graph +PNGraph GetDPetersen() { + PNGraph Graph = TNGraph::New(); + + for (int i = 0; i < 10; i++) { + Graph->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,(i+1) % 5); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i + 5,(i+2) % 5 + 5); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,i + 5); + } + + return Graph; +} + // Generate TNodeEDatNet TPt > GetTestTNodeEDatNet() { TPt > Net; diff --git a/test/test-triad.cpp b/test/test-triad.cpp index 03ec04925..66634c856 100644 --- a/test/test-triad.cpp +++ b/test/test-triad.cpp @@ -57,6 +57,10 @@ TEST(triad, TestGetTriadsOpenClosed) { EXPECT_EQ(ExpClosedTr, ClosedTr); EXPECT_EQ(ExpOpenTr, OpenTr); + TSnap::GetTriadsAll(GraphTUN, ClosedTr, OpenTr); + EXPECT_EQ(ExpClosedTr, ClosedTr); + EXPECT_EQ(ExpOpenTr, OpenTr); + // TNGraph should be treated as TUNGraph for calculations PNGraph GraphTN = TriadGetTestTNGraph(); ClosedTr = 0; @@ -66,6 +70,10 @@ TEST(triad, TestGetTriadsOpenClosed) { EXPECT_EQ(ExpClosedTr, ClosedTr); EXPECT_EQ(ExpOpenTr, OpenTr); + TSnap::GetTriadsAll(GraphTN, ClosedTr, OpenTr); + EXPECT_EQ(ExpClosedTr, ClosedTr); + EXPECT_EQ(ExpOpenTr, OpenTr); + // TNEGraph should be treated as TUNGraph for calculations PNEGraph GraphTNE = TriadGetTestTNEGraph(); ClosedTr = 0; @@ -74,6 +82,10 @@ TEST(triad, TestGetTriadsOpenClosed) { TSnap::GetTriads(GraphTNE, ClosedTr, OpenTr); EXPECT_EQ(ExpClosedTr, ClosedTr); EXPECT_EQ(ExpOpenTr, OpenTr); + + TSnap::GetTriadsAll(GraphTNE, ClosedTr, OpenTr); + EXPECT_EQ(ExpClosedTr, ClosedTr); + EXPECT_EQ(ExpOpenTr, OpenTr); } // Test GetTriads for Whole Graph (Only Closed) @@ -184,6 +196,11 @@ TEST(triad, TestGetClustCfDistCO) { EXPECT_EQ(ExpClosedTr, ClosedTr); EXPECT_EQ(ExpOpenTr, OpenTr); + TSnap::GetClustCfAll(GraphTUN, DegToCCfV, ClosedTr, OpenTr); + TestDegToCCfVector(DegToCCfV); + EXPECT_EQ(ExpClosedTr, ClosedTr); + EXPECT_EQ(ExpOpenTr, OpenTr); + // TNGraph should be treated as TUNGraph for calculations PNGraph GraphTN = TriadGetTestTNGraph(); DegToCCfV.Clr(); @@ -195,6 +212,11 @@ TEST(triad, TestGetClustCfDistCO) { EXPECT_EQ(ExpClosedTr, ClosedTr); EXPECT_EQ(ExpOpenTr, OpenTr); + TSnap::GetClustCfAll(GraphTN, DegToCCfV, ClosedTr, OpenTr); + TestDegToCCfVector(DegToCCfV); + EXPECT_EQ(ExpClosedTr, ClosedTr); + EXPECT_EQ(ExpOpenTr, OpenTr); + // TNEGraph is not treated the same! Be careful with multigraphs PNEGraph GraphTNE = TriadGetTestTNEGraph(); DegToCCfV.Clr(); @@ -225,6 +247,31 @@ TEST(triad, TestGetClustCfDistCO) { } EXPECT_EQ(ExpClosedTr, ClosedTr); EXPECT_EQ(ExpOpenTr, OpenTr); + + TSnap::GetClustCfAll(GraphTNE, DegToCCfV, ClosedTr, OpenTr); + for (TFltPr *Pair = DegToCCfV.BegI(); Pair < DegToCCfV.EndI(); Pair++) { + double Diff = Pair->Val2 - 5.0/9.0; // Used for case 4 + Diff = (Diff < 0) ? -1.0*Diff : Diff; // Used for case 4 + switch ((int) Pair->Val1) { + case 2: + EXPECT_EQ(1.0, Pair->Val2); + break; + case 4: + EXPECT_GT(0.00001, Diff); // Due to floats being imprecise + break; + case 7: + EXPECT_EQ(2.0/3.0, Pair->Val2); + break; + case 15: + EXPECT_EQ(0.3, Pair->Val2); + break; + default: + ASSERT_FALSE(true); // Shouldn't have degrees other than listed + break; + } + } + EXPECT_EQ(ExpClosedTr, ClosedTr); + EXPECT_EQ(ExpOpenTr, OpenTr); } // Test GetNodeClustCf (Specific Node) @@ -332,6 +379,9 @@ TEST(triad, TestGetNodeCOTriads) { TSnap::GetNodeTriads(GraphTUN, i, ClosedTr, OpenTr); VerifyClosedTriads(i, ClosedTr); VerifyOpenTriads(i, OpenTr); + TSnap::GetNodeTriadsAll(GraphTUN, i, ClosedTr, OpenTr); + VerifyClosedTriads(i, ClosedTr); + VerifyOpenTriads(i, OpenTr); } // Test TNGraph which is treated same as undirected. @@ -341,6 +391,9 @@ TEST(triad, TestGetNodeCOTriads) { TSnap::GetNodeTriads(GraphTN, i, ClosedTr, OpenTr); VerifyClosedTriads(i, ClosedTr); VerifyOpenTriads(i, OpenTr); + TSnap::GetNodeTriadsAll(GraphTN, i, ClosedTr, OpenTr); + VerifyClosedTriads(i, ClosedTr); + VerifyOpenTriads(i, OpenTr); } // Test TNEGraph which is treated same as undirected. @@ -350,6 +403,9 @@ TEST(triad, TestGetNodeCOTriads) { TSnap::GetNodeTriads(GraphTNE, i, ClosedTr, OpenTr); VerifyClosedTriads(i, ClosedTr); VerifyOpenTriads(i, OpenTr); + TSnap::GetNodeTriadsAll(GraphTNE, i, ClosedTr, OpenTr); + VerifyClosedTriads(i, ClosedTr); + VerifyOpenTriads(i, OpenTr); } } diff --git a/tutorials/demo-subgraph.cpp b/tutorials/demo-subgraph.cpp index c246740dc..dc99af744 100644 --- a/tutorials/demo-subgraph.cpp +++ b/tutorials/demo-subgraph.cpp @@ -3,6 +3,7 @@ PUNGraph GetTestTUNGraph(); PNGraph GetTestTNGraph(); PNEGraph GetTestTNEGraph(); +PNEANet GetTestTNEANet(); TPt > GetTestTNodeEDatNet(); TPt > GetTestTNodeEdgeNet(); @@ -328,6 +329,417 @@ void TestGetRndGraphs() { printf("\n"); } +// Test TNGraph GetEgoNetHop +void TestGetInEgonetHopTNGraph() { + // Test on TNSmall Graph + PNGraph Small = TNGraph::GetSmallGraph(); + PNGraph ego1 = TSnap::GetInEgonetHop(Small, 4, 1); + PrintGraph("small-ego1", ego1); + PNGraph ego2 = TSnap::GetInEgonetHop(Small, 4, 2); + PrintGraph("small-ego2", ego2); + PNGraph ego3 = TSnap::GetInEgonetHop(Small, 4, 3); + PrintGraph("small-ego3", ego3); + + // Middle Size TN graph + PNGraph Middle = TNGraph::New(); + for (int i = 0; i < 6; i++) { + Middle->AddNode(i); + } + for (int i = 0; i < 6; i++) { + Middle->AddEdge(i, (i + 1) % 6); + Middle->AddEdge(i, (i + 2) % 6); + } + PrintGraph("Mid-size TNGraph", Middle); + PNGraph midego2 = TSnap::GetInEgonetHop(Middle, 0, 2); + PrintGraph("Mid-size Ego2", midego2); + PNGraph midego3 = TSnap::GetInEgonetHop(Middle, 0, 3); + PrintGraph("Mid-size Ego3", midego3); + + // Larger TN Graph + PNGraph Graph; + PNGraph Graph0; + PNGraph Graph1; + PNGraph Graph2; + PNGraph Graph3; + PNGraph Graph4; + PNGraph Graph5; + PNGraph Graph6; + PNGraph Graph7; + + Graph = GetTestTNGraph(); + PrintGraph("Large TNGraph", Graph); + + Graph0 = TSnap::GetInEgonetHop(Graph, 0, 0); + PrintGraph("Large TNGraph - Ego 0", Graph0); + + Graph1 = TSnap::GetInEgonetHop(Graph, 3, 1); + PrintGraph("Large TNGraph - Ego 1", Graph1); + + Graph2 = TSnap::GetInEgonetHop(Graph, 6, 2); + PrintGraph("Large TNGraph - Ego 2", Graph2); + + Graph3 = TSnap::GetInEgonetHop(Graph, 9, 3); + PrintGraph("Large TNGraph - Ego 3", Graph3); + + Graph4 = TSnap::GetInEgonetHop(Graph, 12, 4); + PrintGraph("Large TNGraph - Ego 4", Graph4); + + Graph5 = TSnap::GetInEgonetHop(Graph, 15, 5); + PrintGraph("Large TNGraph - Ego 5", Graph5); + + Graph6 = TSnap::GetInEgonetHop(Graph, 18, 6); + PrintGraph("Large TNGraph - Ego 6", Graph6); + + Graph7 = TSnap::GetInEgonetHop(Graph, 1, 7); + PrintGraph("Large TNGraph - Ego 7", Graph7); +} + +// Test TUNGraph GetInEgonetHop +void TestGetInEgonetHopTUNGraph() { + PUNGraph Graph; + PUNGraph Graph0; + PUNGraph Graph1; + PUNGraph Graph2; + PUNGraph Graph3; + PUNGraph Graph4; + + Graph = GetTestTUNGraph(); + PrintGraph("Large TUNGraph", Graph); + + Graph0 = TSnap::GetInEgonetHop(Graph, 3, 0); + PrintGraph("Large TUNGraph - Ego 0", Graph0); + + Graph1 = TSnap::GetInEgonetHop(Graph, 0, 1); + PrintGraph("Large TUNGraph - Ego 1", Graph1); + + Graph2 = TSnap::GetInEgonetHop(Graph, 7, 2); + PrintGraph("Large TUNGraph - Ego 2", Graph1); + + Graph3 = TSnap::GetInEgonetHop(Graph, 19, 3); + PrintGraph("Large TUNGraph - Ego 3", Graph1); + + Graph4 = TSnap::GetInEgonetHop(Graph, 8, 4); + PrintGraph("Large TUNGraph - Ego 4", Graph4); +} + +// Test TNEANet GetInEgonetAttr +void TestGetInEgonetsAttr() { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + + Graph = GetTestTNEANet(); + + Graph0 = TSnap::GetInEgonetAttr(Graph, 0, 0); + PrintGraph("TNEANet w/ Attr - Ego 0", Graph0); + + Graph1 = TSnap::GetInEgonetAttr(Graph, 3, 1); + PrintGraph("TNEANet w/ Attr - Ego 1", Graph1); + + Graph2 = TSnap::GetInEgonetAttr(Graph, 6, 2); + PrintGraph("TNEANet w/ Attr - Ego 2", Graph2); +} + +// Test TUNGraph GetInEgonetSub +void TestGetInEgonetSubTUNGraph() { + PUNGraph Graph; + PUNGraph Graph1; + PUNGraph Graph2; + + Graph = GetTestTUNGraph(); + + Graph1 = TSnap::GetInEgonetSub(Graph, 0, 1, 3, -1.0); + PrintGraph("TUNGraph - Ego 1 - Sub 3", Graph1); + + Graph2 = TSnap::GetInEgonetSub(Graph, 0, 1, 0, 0.9); + PrintGraph("TUNGraph - Ego 1 - Sub 90%", Graph2); +} + +// Test TUNGraph GetInEgonetSub +void TestGetInEgonetSubTNGraph() { + PNGraph Graph; + PNGraph Graph1; + PNGraph Graph2; + + Graph = GetTestTNGraph(); + + Graph1 = TSnap::GetInEgonetSub(Graph, 0, 1, 2, -1.0); + PrintGraph("TNGraph - Ego 1 - Sub 2", Graph1); + + Graph2 = TSnap::GetInEgonetSub(Graph, 0, 1, 0, 0.9); + PrintGraph("TNGraph - Ego 1 - Sub 90%", Graph2); +} + +// Test TNEANet GetInEgonetSub +void TestGetInEgonetSubTNEANet() { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + + Graph = GetTestTNEANet(); + + Graph0 = TSnap::GetInEgonetSub(Graph, 3, 0, 2, 1.0); + + Graph1 = TSnap::GetInEgonetSub(Graph, 0, 1, 2, -1.0); + + Graph2 = TSnap::GetInEgonetSub(Graph, 0, 1, 0, 0.9); +} + +// Test TNEANet GetInEgonetSubAttr +void TestGetInEgonetSubAttr() { + PNEANet Graph; + PNEANet Graph0; + PNEANet Graph1; + PNEANet Graph2; + + Graph = GetTestTNEANet(); + + Graph1 = TSnap::GetInEgonetSubAttr(Graph, 0, 1, 2, -1.0); + PrintGraph("TNEANet w/ Attr - Ego 1 - Sub 2", Graph1); + + Graph2 = TSnap::GetInEgonetSubAttr(Graph, 0, 1, 0, 0.9); + PrintGraph("TNEANet w/ Attr - Ego 1 - Sub 90%", Graph2); +} + +// Test PGraph GetGraphUnion +void TestGetGraphUnion() { + //Undirected graph + PUNGraph Graph = TUNGraph::New(); + PUNGraph Graph0 = TUNGraph::New(); + + for (int i = 0; i < 5; i++) { + Graph->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,(i+1) % 5); + Graph->AddEdge(i,(i+2) % 5); + } + for (int i = 3; i < 8; i++) { + Graph0->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph0->AddEdge(i + 3,((i+1) % 5) + 3); + } + + PrintGraph("TUNGraph DstGraph before union", Graph); + PrintGraph("TUNGraph SrcGraph before union", Graph0); + + TSnap::GetGraphUnion(Graph, Graph0); + PrintGraph("TUNGraph DstGraph after union", Graph); + + //Directed graph + PNGraph Graph1 = TNGraph::New(); + PNGraph Graph2 = TNGraph::New(); + for (int i = 0; i < 4; i++) { + Graph1->AddNode(i); + } + for (int i = 1; i < 5; i++) { + Graph2->AddNode(i); + } + + Graph1->AddEdge(0, 1); + Graph1->AddEdge(1, 2); + Graph2->AddEdge(1, 2); + Graph2->AddEdge(2, 1); + Graph1->AddEdge(2, 3); + Graph2->AddEdge(2, 3); + Graph1->AddEdge(3, 2); + Graph2->AddEdge(3, 4); + Graph2->AddEdge(1, 4); + + PrintGraph("TNGraph DstGraph before union", Graph1); + PrintGraph("TNGraph SrcGraph before union", Graph2); + + TSnap::GetGraphUnion(Graph1, Graph2); + PrintGraph("TNGraph DstGraph after union", Graph1); + + //Directed multi-graph + PNEANet Graph3 = TNEANet::New(); + PNEANet Graph4 = TNEANet::New(); + int EId = 0; + for (int i = 0; i < 4; i++) { + Graph3->AddNode(i); + } + for (int i = 1; i < 5; i++) { + Graph4->AddNode(i); + } + + Graph3->AddEdge(0, 1, EId++); + Graph3->AddEdge(1, 2, EId++); + Graph4->AddEdge(1, 2, EId++); + Graph4->AddEdge(2, 1, EId++); + Graph3->AddEdge(2, 3, EId); + Graph4->AddEdge(2, 3, EId++); + Graph3->AddEdge(3, 2, EId++); + Graph4->AddEdge(3, 4, EId++); + Graph4->AddEdge(1, 4, EId++); + + PrintGraph("TNEANet DstGraph before union", Graph3); + PrintGraph("TNEANet SrcGraph before union", Graph4); + + TSnap::GetGraphUnion(Graph3, Graph4); + PrintGraph("TNEANet DstGraph after union", Graph3); +} + + +// Test PNEANet GetGraphUnionAttr +void TestGetGraphUnionAttr() { + PNEANet Graph = PNEANet::New(); + PNEANet Graph0 = PNEANet::New(); + + TStr s = "id"; + int EId; + for (int i = 0; i < 6; i++) { + Graph->AddNode(i); + Graph->AddIntAttrDatN(i, i, s); + } + + for (int i = 3; i < 9; i++) { + Graph0->AddNode(i); + Graph0->AddIntAttrDatN(i, i, s); + } + + for (int i = 0; i < 6; i++) { + EId = Graph->AddEdge(i, (i + 2) % 6); + Graph->AddIntAttrDatE(EId, (i + 2) % 6, s); + EId = Graph->AddEdge(i, (i + 5) % 6); + Graph->AddIntAttrDatE(EId, (i + 5) % 6, s); + } + + for (int i = 0; i < 6; i++) { + EId = Graph0->AddEdge(i + 3, ((i + 3) % 6) + 3); + Graph0->AddIntAttrDatE(EId, ((i + 3) % 6) + 3, s); + EId = Graph0->AddEdge(i + 3, ((i + 4) % 6) + 3); + Graph0->AddIntAttrDatE(EId, ((i + 4) % 6) + 3, s); + } + PrintGraph("PNEANet DstGraph before union", Graph); + PrintGraph("PNEANet SrcGraph before union", Graph0); + + TSnap::GetGraphUnionAttr(Graph, Graph0); + PrintGraph("PNEANet DstGraph after union", Graph); +} + +// Test PGraph GetGraphIntersection +void TestGetGraphIntersection() { + //Undirected graph + PUNGraph Graph = TUNGraph::New(); + PUNGraph Graph0 = TUNGraph::New(); + + for (int i = 0; i < 5; i++) { + Graph->AddNode(i); + } + for (int i = 0; i < 5; i++) { + Graph->AddEdge(i,(i+1) % 5); + Graph->AddEdge(i,(i+2) % 5); + } + + for (int i = 2; i < 6; i++) { + Graph0->AddNode(i); + } + for (int i = 0; i < 4; i++) { + Graph0->AddEdge(i + 2, ((i + 1) % 4) + 2); + Graph0->AddEdge(i + 2, ((i + 2) % 4) + 2); + } + + PrintGraph("PUNGraph Graph", Graph); + PrintGraph("PUNGraph Graph0", Graph0); + + PUNGraph IntersectionGraph = TSnap::GetGraphIntersection(Graph, Graph0); + PrintGraph("PUNGraph - Intersection of Graph and Graph0", IntersectionGraph); + + //Directed graph + PNGraph Graph1 = TNGraph::New(); + PNGraph Graph2 = TNGraph::New(); + + for (int i = 0; i < 8; i++) { + Graph1->AddNode(i); + } + for (int i = 0; i < 8; i++) { + Graph1->AddEdge(i, (i + 1) % 8); + Graph1->AddEdge((i + 1) % 8, i); + } + + for (int i = 2; i < 6; i++) { + Graph2->AddNode(i); + } + for (int i = 0; i < 4; i++) { + Graph2->AddEdge(i + 2, ((i + 1) % 4) + 2); + Graph2->AddEdge(i + 2, ((i + 2) % 4) + 2); + } + + PrintGraph("PNGraph Graph1", Graph1); + PrintGraph("PNGraph Graph2", Graph2); + + PNGraph IntersectionGraph0 = TSnap::GetGraphIntersection(Graph1, Graph2); + PrintGraph("PNGraph - Intersection of Graph1 and Graph2", IntersectionGraph0); + + //Directed multigraph + PNEANet Graph3 = TNEANet::New(); + PNEANet Graph4 = TNEANet::New(); + int EId3 = 0; + int EId4 = 1; + + for (int i = 0; i < 4; i++) { + Graph3->AddNode(i); + } + for (int i = 0; i < 3; i++) { + Graph3->AddEdge(i, i + 1, EId3++); + } + Graph3->AddEdge(1, 0, EId3++); + Graph3->AddEdge(1, 2, EId3++); + Graph3->AddEdge(3, 2, EId3++); + + for (int i = 1; i < 5; i++) { + Graph4->AddNode(i); + } + for (int i = 1; i < 4; i++) { + Graph4->AddEdge(i + 1, i, EId4 + 3); + Graph4->AddEdge(i, i + 1, EId4++); + } + + PrintGraph("PNEANet Graph3", Graph3); + PrintGraph("PNEANet Graph4", Graph4); + + PNEANet IntersectionGraph1 = TSnap::GetGraphIntersection(Graph3, Graph4); + PrintGraph("PNEANet - Intersection of Graph3 and Graph4 ", IntersectionGraph1); +} + +// Test PNEANet GetGraphIntersectionAttr +void TestGetGraphIntersectionAttr() { + PNEANet Graph = PNEANet::New(); + PNEANet Graph0 = PNEANet::New(); + TStr s = "id"; + int EId; + + for (int i = 0; i < 7; i++) { + Graph->AddNode(i); + Graph->AddIntAttrDatN(i, i, s); + } + for (int i = 0; i < 7; i++) { + EId = Graph->AddEdge(i, (i + 2) % 7); + Graph->AddIntAttrDatE(EId, (i + 2) % 7, s); + EId = Graph->AddEdge(i, (i + 3) % 7); + Graph->AddIntAttrDatE(EId, (i + 3) % 7, s); + } + + for (int i = 2; i < 9; i++) { + Graph0->AddNode(i); + Graph0->AddIntAttrDatN(i, i, s); + } + for (int i = 0; i < 7; i++) { + EId = Graph0->AddEdge(i + 2, ((i + 3) % 7) + 2); + Graph0->AddIntAttrDatE(EId, ((i + 3) % 7) + 2, s); + } + + PrintGraph("PNEANet Graph before intersection", Graph); + PrintGraph("PNEANet Graph0 before intersection", Graph0); + + PNEANet IntersectionGraph = TSnap::GetGraphIntersectionAttr(Graph, Graph0); + PrintGraph("PNEANet - Intersection of Graph and Graph0", IntersectionGraph); +} + // Generate TUNGraph PUNGraph GetTestTUNGraph() { PUNGraph Graph = TUNGraph::New(); @@ -362,6 +774,26 @@ PNGraph GetTestTNGraph() { return Graph; } +// Generate TNEANet +PNEANet GetTestTNEANet() { + PNEANet Graph = PNEANet::New(); + TStr s = "id"; + + for (int i = 0; i < 20; i++) { + Graph->AddNode(i); + Graph->AddIntAttrDatN(i, i, s); + } + + for (int i = 0; i < 20; i++) { + Graph->AddEdge(i, (i + 1) % 20); + Graph->AddEdge(i, (i + 2) % 20); + Graph->AddEdge(i, (i + 3) % 20); + } + + return Graph; +} + + // Generate TNEGraph PNEGraph GetTestTNEGraph() { PNEGraph Graph = TNEGraph::New(); @@ -451,5 +883,16 @@ int main(int argc, char* argv[]) { TestConvertSubGraphs(); TestConvertESubGraphs(); TestGetRndGraphs(); + TestGetInEgonetHopTNGraph(); + TestGetInEgonetHopTUNGraph(); + TestGetInEgonetsAttr(); + TestGetInEgonetSubTUNGraph(); + TestGetInEgonetSubTNGraph(); + TestGetInEgonetSubTNEANet(); + TestGetInEgonetSubAttr(); + TestGetGraphUnion(); + TestGetGraphUnionAttr(); + TestGetGraphIntersection(); + TestGetGraphIntersectionAttr(); }