├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── Makefile.in ├── NEWS ├── README ├── aclocal.m4 ├── configure ├── configure.ac ├── depcomp ├── example └── movielens │ ├── items.tsv │ ├── movies.tsv │ ├── test.tsv │ ├── test_users.tsv │ ├── train.tsv │ ├── users.tsv │ └── validation.tsv ├── install-sh ├── missing └── src ├── Makefile.am ├── Makefile.in ├── bnprec.cc ├── bnprec.hh ├── env.hh ├── gammapoisson.hh ├── gaprec.cc ├── gaprec.hh ├── log.cc ├── log.hh ├── main.cc ├── matrix.hh ├── ratings.cc ├── ratings.hh └── roceasy.c /AUTHORS: -------------------------------------------------------------------------------- 1 | Please report bugs to Prem Gopalan. 2 | 3 | Prem Gopalan 4 | Princeton University 5 | pgopalan@cs.princeton.edu; prem.gopalan@gmail.com 6 | 7 | Francisco J. R. Ruiz 8 | University Carlos III in Madrid 9 | 10 | Rajesh Ranganath 11 | Princeton University 12 | 13 | David M. Blei 14 | Princeton University 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/premgopalan/bnprec/577ebda201533e69ccfb5b7edc149be90204f05f/ChangeLog -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, 5 | Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell commands `./configure; make; make install' should 16 | configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | HP-UX `make' updates targets which have the same time stamps as 230 | their prerequisites, which makes it generally unusable when shipped 231 | generated files such as `configure' are involved. Use GNU `make' 232 | instead. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf bug. Until the bug is fixed you can use this workaround: 313 | 314 | CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash 315 | 316 | `configure' Invocation 317 | ====================== 318 | 319 | `configure' recognizes the following options to control how it 320 | operates. 321 | 322 | `--help' 323 | `-h' 324 | Print a summary of all of the options to `configure', and exit. 325 | 326 | `--help=short' 327 | `--help=recursive' 328 | Print a summary of the options unique to this package's 329 | `configure', and exit. The `short' variant lists options used 330 | only in the top level, while the `recursive' variant lists options 331 | also present in any nested packages. 332 | 333 | `--version' 334 | `-V' 335 | Print the version of Autoconf used to generate the `configure' 336 | script, and exit. 337 | 338 | `--cache-file=FILE' 339 | Enable the cache: use and save the results of the tests in FILE, 340 | traditionally `config.cache'. FILE defaults to `/dev/null' to 341 | disable caching. 342 | 343 | `--config-cache' 344 | `-C' 345 | Alias for `--cache-file=config.cache'. 346 | 347 | `--quiet' 348 | `--silent' 349 | `-q' 350 | Do not print messages saying which checks are being made. To 351 | suppress all normal output, redirect it to `/dev/null' (any error 352 | messages will still be shown). 353 | 354 | `--srcdir=DIR' 355 | Look for the package's source code in directory DIR. Usually 356 | `configure' can determine that directory automatically. 357 | 358 | `--prefix=DIR' 359 | Use DIR as the installation prefix. *note Installation Names:: 360 | for more details, including other options available for fine-tuning 361 | the installation locations. 362 | 363 | `--no-create' 364 | `-n' 365 | Run the configure checks, but stop before creating any output 366 | files. 367 | 368 | `configure' also accepts some other, not widely useful, options. Run 369 | `configure --help' for more details. 370 | 371 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | EXTRA_DIST = scripts 3 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.11.3 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software 6 | # Foundation, Inc. 7 | # This Makefile.in is free software; the Free Software Foundation 8 | # gives unlimited permission to copy and/or distribute it, 9 | # with or without modifications, as long as this notice is preserved. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 13 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 | # PARTICULAR PURPOSE. 15 | 16 | @SET_MAKE@ 17 | VPATH = @srcdir@ 18 | pkgdatadir = $(datadir)/@PACKAGE@ 19 | pkgincludedir = $(includedir)/@PACKAGE@ 20 | pkglibdir = $(libdir)/@PACKAGE@ 21 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 22 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 23 | install_sh_DATA = $(install_sh) -c -m 644 24 | install_sh_PROGRAM = $(install_sh) -c 25 | install_sh_SCRIPT = $(install_sh) -c 26 | INSTALL_HEADER = $(INSTALL_DATA) 27 | transform = $(program_transform_name) 28 | NORMAL_INSTALL = : 29 | PRE_INSTALL = : 30 | POST_INSTALL = : 31 | NORMAL_UNINSTALL = : 32 | PRE_UNINSTALL = : 33 | POST_UNINSTALL = : 34 | subdir = . 35 | DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ 36 | $(srcdir)/Makefile.in $(top_srcdir)/configure AUTHORS COPYING \ 37 | ChangeLog INSTALL NEWS depcomp install-sh missing 38 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 39 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 40 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 41 | $(ACLOCAL_M4) 42 | am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ 43 | configure.lineno config.status.lineno 44 | mkinstalldirs = $(install_sh) -d 45 | CONFIG_CLEAN_FILES = 46 | CONFIG_CLEAN_VPATH_FILES = 47 | SOURCES = 48 | DIST_SOURCES = 49 | RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ 50 | html-recursive info-recursive install-data-recursive \ 51 | install-dvi-recursive install-exec-recursive \ 52 | install-html-recursive install-info-recursive \ 53 | install-pdf-recursive install-ps-recursive install-recursive \ 54 | installcheck-recursive installdirs-recursive pdf-recursive \ 55 | ps-recursive uninstall-recursive 56 | RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ 57 | distclean-recursive maintainer-clean-recursive 58 | AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ 59 | $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ 60 | distdir dist dist-all distcheck 61 | ETAGS = etags 62 | CTAGS = ctags 63 | DIST_SUBDIRS = $(SUBDIRS) 64 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 65 | distdir = $(PACKAGE)-$(VERSION) 66 | top_distdir = $(distdir) 67 | am__remove_distdir = \ 68 | if test -d "$(distdir)"; then \ 69 | find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ 70 | && rm -rf "$(distdir)" \ 71 | || { sleep 5 && rm -rf "$(distdir)"; }; \ 72 | else :; fi 73 | am__relativize = \ 74 | dir0=`pwd`; \ 75 | sed_first='s,^\([^/]*\)/.*$$,\1,'; \ 76 | sed_rest='s,^[^/]*/*,,'; \ 77 | sed_last='s,^.*/\([^/]*\)$$,\1,'; \ 78 | sed_butlast='s,/*[^/]*$$,,'; \ 79 | while test -n "$$dir1"; do \ 80 | first=`echo "$$dir1" | sed -e "$$sed_first"`; \ 81 | if test "$$first" != "."; then \ 82 | if test "$$first" = ".."; then \ 83 | dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ 84 | dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ 85 | else \ 86 | first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ 87 | if test "$$first2" = "$$first"; then \ 88 | dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ 89 | else \ 90 | dir2="../$$dir2"; \ 91 | fi; \ 92 | dir0="$$dir0"/"$$first"; \ 93 | fi; \ 94 | fi; \ 95 | dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ 96 | done; \ 97 | reldir="$$dir2" 98 | DIST_ARCHIVES = $(distdir).tar.gz 99 | GZIP_ENV = --best 100 | distuninstallcheck_listfiles = find . -type f -print 101 | am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ 102 | | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' 103 | distcleancheck_listfiles = find . -type f -print 104 | ACLOCAL = @ACLOCAL@ 105 | AMTAR = @AMTAR@ 106 | AUTOCONF = @AUTOCONF@ 107 | AUTOHEADER = @AUTOHEADER@ 108 | AUTOMAKE = @AUTOMAKE@ 109 | AWK = @AWK@ 110 | CC = @CC@ 111 | CCDEPMODE = @CCDEPMODE@ 112 | CFLAGS = @CFLAGS@ 113 | CPP = @CPP@ 114 | CPPFLAGS = @CPPFLAGS@ 115 | CXX = @CXX@ 116 | CXXDEPMODE = @CXXDEPMODE@ 117 | CXXFLAGS = @CXXFLAGS@ 118 | CYGPATH_W = @CYGPATH_W@ 119 | DEFS = @DEFS@ 120 | DEPDIR = @DEPDIR@ 121 | ECHO_C = @ECHO_C@ 122 | ECHO_N = @ECHO_N@ 123 | ECHO_T = @ECHO_T@ 124 | EGREP = @EGREP@ 125 | EXEEXT = @EXEEXT@ 126 | GREP = @GREP@ 127 | INSTALL = @INSTALL@ 128 | INSTALL_DATA = @INSTALL_DATA@ 129 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 130 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 131 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 132 | LDFLAGS = @LDFLAGS@ 133 | LIBOBJS = @LIBOBJS@ 134 | LIBS = @LIBS@ 135 | LTLIBOBJS = @LTLIBOBJS@ 136 | MAKEINFO = @MAKEINFO@ 137 | MKDIR_P = @MKDIR_P@ 138 | OBJEXT = @OBJEXT@ 139 | PACKAGE = @PACKAGE@ 140 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 141 | PACKAGE_NAME = @PACKAGE_NAME@ 142 | PACKAGE_STRING = @PACKAGE_STRING@ 143 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 144 | PACKAGE_URL = @PACKAGE_URL@ 145 | PACKAGE_VERSION = @PACKAGE_VERSION@ 146 | PATH_SEPARATOR = @PATH_SEPARATOR@ 147 | POW_LIB = @POW_LIB@ 148 | SET_MAKE = @SET_MAKE@ 149 | SHELL = @SHELL@ 150 | STRIP = @STRIP@ 151 | VERSION = @VERSION@ 152 | abs_builddir = @abs_builddir@ 153 | abs_srcdir = @abs_srcdir@ 154 | abs_top_builddir = @abs_top_builddir@ 155 | abs_top_srcdir = @abs_top_srcdir@ 156 | ac_ct_CC = @ac_ct_CC@ 157 | ac_ct_CXX = @ac_ct_CXX@ 158 | am__include = @am__include@ 159 | am__leading_dot = @am__leading_dot@ 160 | am__quote = @am__quote@ 161 | am__tar = @am__tar@ 162 | am__untar = @am__untar@ 163 | bindir = @bindir@ 164 | build_alias = @build_alias@ 165 | builddir = @builddir@ 166 | datadir = @datadir@ 167 | datarootdir = @datarootdir@ 168 | docdir = @docdir@ 169 | dvidir = @dvidir@ 170 | exec_prefix = @exec_prefix@ 171 | host_alias = @host_alias@ 172 | htmldir = @htmldir@ 173 | includedir = @includedir@ 174 | infodir = @infodir@ 175 | install_sh = @install_sh@ 176 | libdir = @libdir@ 177 | libexecdir = @libexecdir@ 178 | localedir = @localedir@ 179 | localstatedir = @localstatedir@ 180 | mandir = @mandir@ 181 | mkdir_p = @mkdir_p@ 182 | oldincludedir = @oldincludedir@ 183 | pdfdir = @pdfdir@ 184 | prefix = @prefix@ 185 | program_transform_name = @program_transform_name@ 186 | psdir = @psdir@ 187 | sbindir = @sbindir@ 188 | sharedstatedir = @sharedstatedir@ 189 | srcdir = @srcdir@ 190 | sysconfdir = @sysconfdir@ 191 | target_alias = @target_alias@ 192 | top_build_prefix = @top_build_prefix@ 193 | top_builddir = @top_builddir@ 194 | top_srcdir = @top_srcdir@ 195 | SUBDIRS = src 196 | EXTRA_DIST = scripts 197 | all: all-recursive 198 | 199 | .SUFFIXES: 200 | am--refresh: Makefile 201 | @: 202 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 203 | @for dep in $?; do \ 204 | case '$(am__configure_deps)' in \ 205 | *$$dep*) \ 206 | echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ 207 | $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ 208 | && exit 0; \ 209 | exit 1;; \ 210 | esac; \ 211 | done; \ 212 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ 213 | $(am__cd) $(top_srcdir) && \ 214 | $(AUTOMAKE) --gnu Makefile 215 | .PRECIOUS: Makefile 216 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 217 | @case '$?' in \ 218 | *config.status*) \ 219 | echo ' $(SHELL) ./config.status'; \ 220 | $(SHELL) ./config.status;; \ 221 | *) \ 222 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ 223 | cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ 224 | esac; 225 | 226 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 227 | $(SHELL) ./config.status --recheck 228 | 229 | $(top_srcdir)/configure: $(am__configure_deps) 230 | $(am__cd) $(srcdir) && $(AUTOCONF) 231 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 232 | $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) 233 | $(am__aclocal_m4_deps): 234 | 235 | # This directory's subdirectories are mostly independent; you can cd 236 | # into them and run `make' without going through this Makefile. 237 | # To change the values of `make' variables: instead of editing Makefiles, 238 | # (1) if the variable is set in `config.status', edit `config.status' 239 | # (which will cause the Makefiles to be regenerated when you run `make'); 240 | # (2) otherwise, pass the desired values on the `make' command line. 241 | $(RECURSIVE_TARGETS): 242 | @fail= failcom='exit 1'; \ 243 | for f in x $$MAKEFLAGS; do \ 244 | case $$f in \ 245 | *=* | --[!k]*);; \ 246 | *k*) failcom='fail=yes';; \ 247 | esac; \ 248 | done; \ 249 | dot_seen=no; \ 250 | target=`echo $@ | sed s/-recursive//`; \ 251 | list='$(SUBDIRS)'; for subdir in $$list; do \ 252 | echo "Making $$target in $$subdir"; \ 253 | if test "$$subdir" = "."; then \ 254 | dot_seen=yes; \ 255 | local_target="$$target-am"; \ 256 | else \ 257 | local_target="$$target"; \ 258 | fi; \ 259 | ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ 260 | || eval $$failcom; \ 261 | done; \ 262 | if test "$$dot_seen" = "no"; then \ 263 | $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ 264 | fi; test -z "$$fail" 265 | 266 | $(RECURSIVE_CLEAN_TARGETS): 267 | @fail= failcom='exit 1'; \ 268 | for f in x $$MAKEFLAGS; do \ 269 | case $$f in \ 270 | *=* | --[!k]*);; \ 271 | *k*) failcom='fail=yes';; \ 272 | esac; \ 273 | done; \ 274 | dot_seen=no; \ 275 | case "$@" in \ 276 | distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ 277 | *) list='$(SUBDIRS)' ;; \ 278 | esac; \ 279 | rev=''; for subdir in $$list; do \ 280 | if test "$$subdir" = "."; then :; else \ 281 | rev="$$subdir $$rev"; \ 282 | fi; \ 283 | done; \ 284 | rev="$$rev ."; \ 285 | target=`echo $@ | sed s/-recursive//`; \ 286 | for subdir in $$rev; do \ 287 | echo "Making $$target in $$subdir"; \ 288 | if test "$$subdir" = "."; then \ 289 | local_target="$$target-am"; \ 290 | else \ 291 | local_target="$$target"; \ 292 | fi; \ 293 | ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ 294 | || eval $$failcom; \ 295 | done && test -z "$$fail" 296 | tags-recursive: 297 | list='$(SUBDIRS)'; for subdir in $$list; do \ 298 | test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ 299 | done 300 | ctags-recursive: 301 | list='$(SUBDIRS)'; for subdir in $$list; do \ 302 | test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ 303 | done 304 | 305 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) 306 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 307 | unique=`for i in $$list; do \ 308 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 309 | done | \ 310 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 311 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 312 | mkid -fID $$unique 313 | tags: TAGS 314 | 315 | TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ 316 | $(TAGS_FILES) $(LISP) 317 | set x; \ 318 | here=`pwd`; \ 319 | if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ 320 | include_option=--etags-include; \ 321 | empty_fix=.; \ 322 | else \ 323 | include_option=--include; \ 324 | empty_fix=; \ 325 | fi; \ 326 | list='$(SUBDIRS)'; for subdir in $$list; do \ 327 | if test "$$subdir" = .; then :; else \ 328 | test ! -f $$subdir/TAGS || \ 329 | set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ 330 | fi; \ 331 | done; \ 332 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 333 | unique=`for i in $$list; do \ 334 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 335 | done | \ 336 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 337 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 338 | shift; \ 339 | if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ 340 | test -n "$$unique" || unique=$$empty_fix; \ 341 | if test $$# -gt 0; then \ 342 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 343 | "$$@" $$unique; \ 344 | else \ 345 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 346 | $$unique; \ 347 | fi; \ 348 | fi 349 | ctags: CTAGS 350 | CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ 351 | $(TAGS_FILES) $(LISP) 352 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 353 | unique=`for i in $$list; do \ 354 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 355 | done | \ 356 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 357 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 358 | test -z "$(CTAGS_ARGS)$$unique" \ 359 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 360 | $$unique 361 | 362 | GTAGS: 363 | here=`$(am__cd) $(top_builddir) && pwd` \ 364 | && $(am__cd) $(top_srcdir) \ 365 | && gtags -i $(GTAGS_ARGS) "$$here" 366 | 367 | distclean-tags: 368 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 369 | 370 | distdir: $(DISTFILES) 371 | $(am__remove_distdir) 372 | test -d "$(distdir)" || mkdir "$(distdir)" 373 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 374 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 375 | list='$(DISTFILES)'; \ 376 | dist_files=`for file in $$list; do echo $$file; done | \ 377 | sed -e "s|^$$srcdirstrip/||;t" \ 378 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 379 | case $$dist_files in \ 380 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 381 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 382 | sort -u` ;; \ 383 | esac; \ 384 | for file in $$dist_files; do \ 385 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 386 | if test -d $$d/$$file; then \ 387 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 388 | if test -d "$(distdir)/$$file"; then \ 389 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 390 | fi; \ 391 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 392 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 393 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 394 | fi; \ 395 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 396 | else \ 397 | test -f "$(distdir)/$$file" \ 398 | || cp -p $$d/$$file "$(distdir)/$$file" \ 399 | || exit 1; \ 400 | fi; \ 401 | done 402 | @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ 403 | if test "$$subdir" = .; then :; else \ 404 | test -d "$(distdir)/$$subdir" \ 405 | || $(MKDIR_P) "$(distdir)/$$subdir" \ 406 | || exit 1; \ 407 | fi; \ 408 | done 409 | @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ 410 | if test "$$subdir" = .; then :; else \ 411 | dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ 412 | $(am__relativize); \ 413 | new_distdir=$$reldir; \ 414 | dir1=$$subdir; dir2="$(top_distdir)"; \ 415 | $(am__relativize); \ 416 | new_top_distdir=$$reldir; \ 417 | echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ 418 | echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ 419 | ($(am__cd) $$subdir && \ 420 | $(MAKE) $(AM_MAKEFLAGS) \ 421 | top_distdir="$$new_top_distdir" \ 422 | distdir="$$new_distdir" \ 423 | am__remove_distdir=: \ 424 | am__skip_length_check=: \ 425 | am__skip_mode_fix=: \ 426 | distdir) \ 427 | || exit 1; \ 428 | fi; \ 429 | done 430 | -test -n "$(am__skip_mode_fix)" \ 431 | || find "$(distdir)" -type d ! -perm -755 \ 432 | -exec chmod u+rwx,go+rx {} \; -o \ 433 | ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ 434 | ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ 435 | ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ 436 | || chmod -R a+r "$(distdir)" 437 | dist-gzip: distdir 438 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 439 | $(am__remove_distdir) 440 | 441 | dist-bzip2: distdir 442 | tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 443 | $(am__remove_distdir) 444 | 445 | dist-lzip: distdir 446 | tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz 447 | $(am__remove_distdir) 448 | 449 | dist-lzma: distdir 450 | tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma 451 | $(am__remove_distdir) 452 | 453 | dist-xz: distdir 454 | tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz 455 | $(am__remove_distdir) 456 | 457 | dist-tarZ: distdir 458 | tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z 459 | $(am__remove_distdir) 460 | 461 | dist-shar: distdir 462 | shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz 463 | $(am__remove_distdir) 464 | 465 | dist-zip: distdir 466 | -rm -f $(distdir).zip 467 | zip -rq $(distdir).zip $(distdir) 468 | $(am__remove_distdir) 469 | 470 | dist dist-all: distdir 471 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 472 | $(am__remove_distdir) 473 | 474 | # This target untars the dist file and tries a VPATH configuration. Then 475 | # it guarantees that the distribution is self-contained by making another 476 | # tarfile. 477 | distcheck: dist 478 | case '$(DIST_ARCHIVES)' in \ 479 | *.tar.gz*) \ 480 | GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ 481 | *.tar.bz2*) \ 482 | bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ 483 | *.tar.lzma*) \ 484 | lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ 485 | *.tar.lz*) \ 486 | lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ 487 | *.tar.xz*) \ 488 | xz -dc $(distdir).tar.xz | $(am__untar) ;;\ 489 | *.tar.Z*) \ 490 | uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ 491 | *.shar.gz*) \ 492 | GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ 493 | *.zip*) \ 494 | unzip $(distdir).zip ;;\ 495 | esac 496 | chmod -R a-w $(distdir); chmod a+w $(distdir) 497 | mkdir $(distdir)/_build 498 | mkdir $(distdir)/_inst 499 | chmod a-w $(distdir) 500 | test -d $(distdir)/_build || exit 0; \ 501 | dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ 502 | && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ 503 | && am__cwd=`pwd` \ 504 | && $(am__cd) $(distdir)/_build \ 505 | && ../configure --srcdir=.. --prefix="$$dc_install_base" \ 506 | $(AM_DISTCHECK_CONFIGURE_FLAGS) \ 507 | $(DISTCHECK_CONFIGURE_FLAGS) \ 508 | && $(MAKE) $(AM_MAKEFLAGS) \ 509 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ 510 | && $(MAKE) $(AM_MAKEFLAGS) check \ 511 | && $(MAKE) $(AM_MAKEFLAGS) install \ 512 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ 513 | && $(MAKE) $(AM_MAKEFLAGS) uninstall \ 514 | && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ 515 | distuninstallcheck \ 516 | && chmod -R a-w "$$dc_install_base" \ 517 | && ({ \ 518 | (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ 519 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ 520 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ 521 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ 522 | distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ 523 | } || { rm -rf "$$dc_destdir"; exit 1; }) \ 524 | && rm -rf "$$dc_destdir" \ 525 | && $(MAKE) $(AM_MAKEFLAGS) dist \ 526 | && rm -rf $(DIST_ARCHIVES) \ 527 | && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ 528 | && cd "$$am__cwd" \ 529 | || exit 1 530 | $(am__remove_distdir) 531 | @(echo "$(distdir) archives ready for distribution: "; \ 532 | list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ 533 | sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' 534 | distuninstallcheck: 535 | @test -n '$(distuninstallcheck_dir)' || { \ 536 | echo 'ERROR: trying to run $@ with an empty' \ 537 | '$$(distuninstallcheck_dir)' >&2; \ 538 | exit 1; \ 539 | }; \ 540 | $(am__cd) '$(distuninstallcheck_dir)' || { \ 541 | echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ 542 | exit 1; \ 543 | }; \ 544 | test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ 545 | || { echo "ERROR: files left after uninstall:" ; \ 546 | if test -n "$(DESTDIR)"; then \ 547 | echo " (check DESTDIR support)"; \ 548 | fi ; \ 549 | $(distuninstallcheck_listfiles) ; \ 550 | exit 1; } >&2 551 | distcleancheck: distclean 552 | @if test '$(srcdir)' = . ; then \ 553 | echo "ERROR: distcleancheck can only run from a VPATH build" ; \ 554 | exit 1 ; \ 555 | fi 556 | @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ 557 | || { echo "ERROR: files left in build directory after distclean:" ; \ 558 | $(distcleancheck_listfiles) ; \ 559 | exit 1; } >&2 560 | check-am: all-am 561 | check: check-recursive 562 | all-am: Makefile 563 | installdirs: installdirs-recursive 564 | installdirs-am: 565 | install: install-recursive 566 | install-exec: install-exec-recursive 567 | install-data: install-data-recursive 568 | uninstall: uninstall-recursive 569 | 570 | install-am: all-am 571 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 572 | 573 | installcheck: installcheck-recursive 574 | install-strip: 575 | if test -z '$(STRIP)'; then \ 576 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 577 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 578 | install; \ 579 | else \ 580 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 581 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 582 | "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ 583 | fi 584 | mostlyclean-generic: 585 | 586 | clean-generic: 587 | 588 | distclean-generic: 589 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 590 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 591 | 592 | maintainer-clean-generic: 593 | @echo "This command is intended for maintainers to use" 594 | @echo "it deletes files that may require special tools to rebuild." 595 | clean: clean-recursive 596 | 597 | clean-am: clean-generic mostlyclean-am 598 | 599 | distclean: distclean-recursive 600 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 601 | -rm -f Makefile 602 | distclean-am: clean-am distclean-generic distclean-tags 603 | 604 | dvi: dvi-recursive 605 | 606 | dvi-am: 607 | 608 | html: html-recursive 609 | 610 | html-am: 611 | 612 | info: info-recursive 613 | 614 | info-am: 615 | 616 | install-data-am: 617 | 618 | install-dvi: install-dvi-recursive 619 | 620 | install-dvi-am: 621 | 622 | install-exec-am: 623 | 624 | install-html: install-html-recursive 625 | 626 | install-html-am: 627 | 628 | install-info: install-info-recursive 629 | 630 | install-info-am: 631 | 632 | install-man: 633 | 634 | install-pdf: install-pdf-recursive 635 | 636 | install-pdf-am: 637 | 638 | install-ps: install-ps-recursive 639 | 640 | install-ps-am: 641 | 642 | installcheck-am: 643 | 644 | maintainer-clean: maintainer-clean-recursive 645 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 646 | -rm -rf $(top_srcdir)/autom4te.cache 647 | -rm -f Makefile 648 | maintainer-clean-am: distclean-am maintainer-clean-generic 649 | 650 | mostlyclean: mostlyclean-recursive 651 | 652 | mostlyclean-am: mostlyclean-generic 653 | 654 | pdf: pdf-recursive 655 | 656 | pdf-am: 657 | 658 | ps: ps-recursive 659 | 660 | ps-am: 661 | 662 | uninstall-am: 663 | 664 | .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ 665 | install-am install-strip tags-recursive 666 | 667 | .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ 668 | all all-am am--refresh check check-am clean clean-generic \ 669 | ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ 670 | dist-lzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ 671 | distcheck distclean distclean-generic distclean-tags \ 672 | distcleancheck distdir distuninstallcheck dvi dvi-am html \ 673 | html-am info info-am install install-am install-data \ 674 | install-data-am install-dvi install-dvi-am install-exec \ 675 | install-exec-am install-html install-html-am install-info \ 676 | install-info-am install-man install-pdf install-pdf-am \ 677 | install-ps install-ps-am install-strip installcheck \ 678 | installcheck-am installdirs installdirs-am maintainer-clean \ 679 | maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ 680 | pdf-am ps ps-am tags tags-recursive uninstall uninstall-am 681 | 682 | 683 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 684 | # Otherwise a system limit (for SysV at least) may be exceeded. 685 | .NOEXPORT: 686 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/premgopalan/bnprec/577ebda201533e69ccfb5b7edc149be90204f05f/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Reference 2 | ---------- 3 | 4 | Gopalan, P., Ruiz, F. J., Ranganath, R., & Blei, D. M. (2014). Bayesian Nonparametric Poisson Factorization for Recommendation Systems. In Proceedings of the Seventeenth International Conference on Artificial Intelligence and Statistics (pp. 275-283). 5 | 6 | @inproceedings{gopalan2014bayesian, 7 | title={Bayesian Nonparametric Poisson Factorization for Recommendation Systems}, 8 | author={Gopalan, Prem and Ruiz, Francisco JR and Ranganath, Rajesh and Blei, David M}, 9 | booktitle={Proceedings of the Seventeenth International Conference on Artificial Intelligence and Statistics}, 10 | pages={275--283}, 11 | year={2014} 12 | } 13 | 14 | Installation 15 | ------------ 16 | 17 | Required libraries: gsl, gslblas, pthread 18 | 19 | On Linux/Unix run 20 | 21 | ./configure 22 | make; make install 23 | 24 | ** 25 | ** Note: UNTESTED on Mac ** 26 | ** Linux is strongly recommended. On Mac, you may run into issues. If you absolutely need it to work on Mac, let me know. 27 | ** 28 | 29 | On Mac OS, the location of the required gsl, gslblas and pthread 30 | libraries may need to be specified: 31 | 32 | ./configure LDFLAGS="-L/opt/local/lib" CPPFLAGS="-I/opt/local/include" 33 | make; make install 34 | 35 | The binary 'gaprec' will be installed in /usr/local/bin unless a 36 | different prefix is provided to configure. (See INSTALL.) 37 | 38 | GAPREC: Gamma Poisson factorization based recommendation tool 39 | -------------------------------------------------------------- 40 | 41 | **gaprec** [OPTIONS] 42 | 43 | -dir path to dataset directory with 3 files: 44 | train.tsv, test.tsv, validation.tsv 45 | (for examples, see example/movielens-1m) 46 | 47 | -m number of items 48 | -n number of users 49 | -T truncation level 50 | 51 | -rfreq assess convergence and compute other stats 52 | number of iterations 53 | default: 10 54 | 55 | -alpha set Gamma shape hyperparameter alpha (see paper) 56 | -C set Gamma scale hyperparameter c (see paper) 57 | 58 | -label add a tag to the output directory 59 | 60 | -gen-ranking generate ranking file to use in precision 61 | computation; see example 62 | 63 | 64 | Example 65 | -------- 66 | 67 | (1) ../src/gaprec -dir ../example/movielens -n 6040 -m 3900 -T 100 -rfreq 10 68 | 69 | This will write output in n6040-m3900-k100-batch-alpha1.1-scale1-vb 70 | 71 | You can change the settings for the Gamma hyperparameters alpha and c (see paper) using the -alpha and the -C options. 72 | 73 | To generate the ranking file (ranking.tsv) for precision computation, run the following: 74 | 75 | (2) cd n6040-m3900-k100-batch-alpha1.1-scale1-vb 76 | 77 | ../../src/gaprec -dir ../../example/movielens -n 6040 -m 3900 -T 100 -rfreq 10 -gen-ranking 78 | 79 | This will rank all y == 0 in training and the test.tsv pairs in 80 | decreasing order of their scores, along with the non-zero ratings from 81 | test.tsv. 82 | 83 | The output is now in a new directory within the fit. Look for ranking.tsv. 84 | 85 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.68]) 5 | AC_INIT([gaprec], [0.1], [pgopalan@cs.princeton.edu]) 6 | : ${CFLAGS="-O3"} 7 | : ${CXXFLAGS="-O3"} 8 | AM_INIT_AUTOMAKE([gaprec], [0.1]) 9 | AC_CONFIG_SRCDIR([src/env.hh]) 10 | # AC_CONFIG_HEADERS([config.h]) 11 | 12 | # Checks for programs. 13 | AC_PROG_CXX 14 | AC_PROG_CC 15 | 16 | # Checks for libraries. 17 | AC_CHECK_LIB([gslcblas], [cblas_sdot], [], [AC_MSG_ERROR([gslcblas library was not found])]) 18 | AC_CHECK_LIB([pthread], [pthread_self], [], [AC_MSG_ERROR([pthread library was not found])]) 19 | AC_CHECK_LIB([gsl], [gsl_sf_lngamma], [], [AC_MSG_ERROR([gsl library was not found])]) 20 | 21 | # Checks for header files. 22 | AC_CHECK_HEADERS([stdint.h stdlib.h string.h sys/file.h sys/time.h unistd.h]) 23 | 24 | # Checks for typedefs, structures, and compiler characteristics. 25 | AC_HEADER_STDBOOL 26 | AC_C_INLINE 27 | AC_TYPE_UINT16_T 28 | AC_TYPE_UINT32_T 29 | AC_TYPE_UINT64_T 30 | AC_TYPE_UINT8_T 31 | 32 | # Checks for library functions. 33 | AC_FUNC_MALLOC 34 | AC_FUNC_STRTOD 35 | AC_CHECK_FUNCS([gettimeofday localtime_r memset mkdir pow sqrt strerror strtol]) 36 | 37 | AC_CONFIG_FILES([Makefile src/Makefile]) 38 | AC_OUTPUT 39 | 40 | AC_ARG_ENABLE(debug, 41 | AS_HELP_STRING([--enable-debug], 42 | [enable debugging, default: no]), 43 | [case "${enableval}" in 44 | yes) debug=true ;; 45 | no) debug=false ;; 46 | *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; 47 | esac], 48 | [debug=false]) 49 | 50 | AM_CONDITIONAL(DEBUG, test x"$debug" = x"true") -------------------------------------------------------------------------------- /depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # depcomp - compile a program generating dependencies as side-effects 3 | 4 | scriptversion=2011-12-04.11; # UTC 5 | 6 | # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 7 | # 2011 Free Software Foundation, Inc. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # Originally written by Alexandre Oliva . 28 | 29 | case $1 in 30 | '') 31 | echo "$0: No command. Try \`$0 --help' for more information." 1>&2 32 | exit 1; 33 | ;; 34 | -h | --h*) 35 | cat <<\EOF 36 | Usage: depcomp [--help] [--version] PROGRAM [ARGS] 37 | 38 | Run PROGRAMS ARGS to compile a file, generating dependencies 39 | as side-effects. 40 | 41 | Environment variables: 42 | depmode Dependency tracking mode. 43 | source Source file read by `PROGRAMS ARGS'. 44 | object Object file output by `PROGRAMS ARGS'. 45 | DEPDIR directory where to store dependencies. 46 | depfile Dependency file to output. 47 | tmpdepfile Temporary file to use when outputting dependencies. 48 | libtool Whether libtool is used (yes/no). 49 | 50 | Report bugs to . 51 | EOF 52 | exit $? 53 | ;; 54 | -v | --v*) 55 | echo "depcomp $scriptversion" 56 | exit $? 57 | ;; 58 | esac 59 | 60 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 61 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 62 | exit 1 63 | fi 64 | 65 | # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. 66 | depfile=${depfile-`echo "$object" | 67 | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} 68 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 69 | 70 | rm -f "$tmpdepfile" 71 | 72 | # Some modes work just like other modes, but use different flags. We 73 | # parameterize here, but still list the modes in the big case below, 74 | # to make depend.m4 easier to write. Note that we *cannot* use a case 75 | # here, because this file can only contain one case statement. 76 | if test "$depmode" = hp; then 77 | # HP compiler uses -M and no extra arg. 78 | gccflag=-M 79 | depmode=gcc 80 | fi 81 | 82 | if test "$depmode" = dashXmstdout; then 83 | # This is just like dashmstdout with a different argument. 84 | dashmflag=-xM 85 | depmode=dashmstdout 86 | fi 87 | 88 | cygpath_u="cygpath -u -f -" 89 | if test "$depmode" = msvcmsys; then 90 | # This is just like msvisualcpp but w/o cygpath translation. 91 | # Just convert the backslash-escaped backslashes to single forward 92 | # slashes to satisfy depend.m4 93 | cygpath_u='sed s,\\\\,/,g' 94 | depmode=msvisualcpp 95 | fi 96 | 97 | if test "$depmode" = msvc7msys; then 98 | # This is just like msvc7 but w/o cygpath translation. 99 | # Just convert the backslash-escaped backslashes to single forward 100 | # slashes to satisfy depend.m4 101 | cygpath_u='sed s,\\\\,/,g' 102 | depmode=msvc7 103 | fi 104 | 105 | case "$depmode" in 106 | gcc3) 107 | ## gcc 3 implements dependency tracking that does exactly what 108 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 109 | ## it if -MD -MP comes after the -MF stuff. Hmm. 110 | ## Unfortunately, FreeBSD c89 acceptance of flags depends upon 111 | ## the command line argument order; so add the flags where they 112 | ## appear in depend2.am. Note that the slowdown incurred here 113 | ## affects only configure: in makefiles, %FASTDEP% shortcuts this. 114 | for arg 115 | do 116 | case $arg in 117 | -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; 118 | *) set fnord "$@" "$arg" ;; 119 | esac 120 | shift # fnord 121 | shift # $arg 122 | done 123 | "$@" 124 | stat=$? 125 | if test $stat -eq 0; then : 126 | else 127 | rm -f "$tmpdepfile" 128 | exit $stat 129 | fi 130 | mv "$tmpdepfile" "$depfile" 131 | ;; 132 | 133 | gcc) 134 | ## There are various ways to get dependency output from gcc. Here's 135 | ## why we pick this rather obscure method: 136 | ## - Don't want to use -MD because we'd like the dependencies to end 137 | ## up in a subdir. Having to rename by hand is ugly. 138 | ## (We might end up doing this anyway to support other compilers.) 139 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 140 | ## -MM, not -M (despite what the docs say). 141 | ## - Using -M directly means running the compiler twice (even worse 142 | ## than renaming). 143 | if test -z "$gccflag"; then 144 | gccflag=-MD, 145 | fi 146 | "$@" -Wp,"$gccflag$tmpdepfile" 147 | stat=$? 148 | if test $stat -eq 0; then : 149 | else 150 | rm -f "$tmpdepfile" 151 | exit $stat 152 | fi 153 | rm -f "$depfile" 154 | echo "$object : \\" > "$depfile" 155 | alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 156 | ## The second -e expression handles DOS-style file names with drive letters. 157 | sed -e 's/^[^:]*: / /' \ 158 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 159 | ## This next piece of magic avoids the `deleted header file' problem. 160 | ## The problem is that when a header file which appears in a .P file 161 | ## is deleted, the dependency causes make to die (because there is 162 | ## typically no way to rebuild the header). We avoid this by adding 163 | ## dummy dependencies for each header file. Too bad gcc doesn't do 164 | ## this for us directly. 165 | tr ' ' ' 166 | ' < "$tmpdepfile" | 167 | ## Some versions of gcc put a space before the `:'. On the theory 168 | ## that the space means something, we add a space to the output as 169 | ## well. hp depmode also adds that space, but also prefixes the VPATH 170 | ## to the object. Take care to not repeat it in the output. 171 | ## Some versions of the HPUX 10.20 sed can't process this invocation 172 | ## correctly. Breaking it into two sed invocations is a workaround. 173 | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ 174 | | sed -e 's/$/ :/' >> "$depfile" 175 | rm -f "$tmpdepfile" 176 | ;; 177 | 178 | hp) 179 | # This case exists only to let depend.m4 do its work. It works by 180 | # looking at the text of this script. This case will never be run, 181 | # since it is checked for above. 182 | exit 1 183 | ;; 184 | 185 | sgi) 186 | if test "$libtool" = yes; then 187 | "$@" "-Wp,-MDupdate,$tmpdepfile" 188 | else 189 | "$@" -MDupdate "$tmpdepfile" 190 | fi 191 | stat=$? 192 | if test $stat -eq 0; then : 193 | else 194 | rm -f "$tmpdepfile" 195 | exit $stat 196 | fi 197 | rm -f "$depfile" 198 | 199 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 200 | echo "$object : \\" > "$depfile" 201 | 202 | # Clip off the initial element (the dependent). Don't try to be 203 | # clever and replace this with sed code, as IRIX sed won't handle 204 | # lines with more than a fixed number of characters (4096 in 205 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 206 | # the IRIX cc adds comments like `#:fec' to the end of the 207 | # dependency line. 208 | tr ' ' ' 209 | ' < "$tmpdepfile" \ 210 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ 211 | tr ' 212 | ' ' ' >> "$depfile" 213 | echo >> "$depfile" 214 | 215 | # The second pass generates a dummy entry for each header file. 216 | tr ' ' ' 217 | ' < "$tmpdepfile" \ 218 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 219 | >> "$depfile" 220 | else 221 | # The sourcefile does not contain any dependencies, so just 222 | # store a dummy comment line, to avoid errors with the Makefile 223 | # "include basename.Plo" scheme. 224 | echo "#dummy" > "$depfile" 225 | fi 226 | rm -f "$tmpdepfile" 227 | ;; 228 | 229 | aix) 230 | # The C for AIX Compiler uses -M and outputs the dependencies 231 | # in a .u file. In older versions, this file always lives in the 232 | # current directory. Also, the AIX compiler puts `$object:' at the 233 | # start of each line; $object doesn't have directory information. 234 | # Version 6 uses the directory in both cases. 235 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 236 | test "x$dir" = "x$object" && dir= 237 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 238 | if test "$libtool" = yes; then 239 | tmpdepfile1=$dir$base.u 240 | tmpdepfile2=$base.u 241 | tmpdepfile3=$dir.libs/$base.u 242 | "$@" -Wc,-M 243 | else 244 | tmpdepfile1=$dir$base.u 245 | tmpdepfile2=$dir$base.u 246 | tmpdepfile3=$dir$base.u 247 | "$@" -M 248 | fi 249 | stat=$? 250 | 251 | if test $stat -eq 0; then : 252 | else 253 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 254 | exit $stat 255 | fi 256 | 257 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 258 | do 259 | test -f "$tmpdepfile" && break 260 | done 261 | if test -f "$tmpdepfile"; then 262 | # Each line is of the form `foo.o: dependent.h'. 263 | # Do two passes, one to just change these to 264 | # `$object: dependent.h' and one to simply `dependent.h:'. 265 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 266 | # That's a tab and a space in the []. 267 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 268 | else 269 | # The sourcefile does not contain any dependencies, so just 270 | # store a dummy comment line, to avoid errors with the Makefile 271 | # "include basename.Plo" scheme. 272 | echo "#dummy" > "$depfile" 273 | fi 274 | rm -f "$tmpdepfile" 275 | ;; 276 | 277 | icc) 278 | # Intel's C compiler understands `-MD -MF file'. However on 279 | # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c 280 | # ICC 7.0 will fill foo.d with something like 281 | # foo.o: sub/foo.c 282 | # foo.o: sub/foo.h 283 | # which is wrong. We want: 284 | # sub/foo.o: sub/foo.c 285 | # sub/foo.o: sub/foo.h 286 | # sub/foo.c: 287 | # sub/foo.h: 288 | # ICC 7.1 will output 289 | # foo.o: sub/foo.c sub/foo.h 290 | # and will wrap long lines using \ : 291 | # foo.o: sub/foo.c ... \ 292 | # sub/foo.h ... \ 293 | # ... 294 | 295 | "$@" -MD -MF "$tmpdepfile" 296 | stat=$? 297 | if test $stat -eq 0; then : 298 | else 299 | rm -f "$tmpdepfile" 300 | exit $stat 301 | fi 302 | rm -f "$depfile" 303 | # Each line is of the form `foo.o: dependent.h', 304 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 305 | # Do two passes, one to just change these to 306 | # `$object: dependent.h' and one to simply `dependent.h:'. 307 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 308 | # Some versions of the HPUX 10.20 sed can't process this invocation 309 | # correctly. Breaking it into two sed invocations is a workaround. 310 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | 311 | sed -e 's/$/ :/' >> "$depfile" 312 | rm -f "$tmpdepfile" 313 | ;; 314 | 315 | hp2) 316 | # The "hp" stanza above does not work with aCC (C++) and HP's ia64 317 | # compilers, which have integrated preprocessors. The correct option 318 | # to use with these is +Maked; it writes dependencies to a file named 319 | # 'foo.d', which lands next to the object file, wherever that 320 | # happens to be. 321 | # Much of this is similar to the tru64 case; see comments there. 322 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 323 | test "x$dir" = "x$object" && dir= 324 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 325 | if test "$libtool" = yes; then 326 | tmpdepfile1=$dir$base.d 327 | tmpdepfile2=$dir.libs/$base.d 328 | "$@" -Wc,+Maked 329 | else 330 | tmpdepfile1=$dir$base.d 331 | tmpdepfile2=$dir$base.d 332 | "$@" +Maked 333 | fi 334 | stat=$? 335 | if test $stat -eq 0; then : 336 | else 337 | rm -f "$tmpdepfile1" "$tmpdepfile2" 338 | exit $stat 339 | fi 340 | 341 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" 342 | do 343 | test -f "$tmpdepfile" && break 344 | done 345 | if test -f "$tmpdepfile"; then 346 | sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" 347 | # Add `dependent.h:' lines. 348 | sed -ne '2,${ 349 | s/^ *// 350 | s/ \\*$// 351 | s/$/:/ 352 | p 353 | }' "$tmpdepfile" >> "$depfile" 354 | else 355 | echo "#dummy" > "$depfile" 356 | fi 357 | rm -f "$tmpdepfile" "$tmpdepfile2" 358 | ;; 359 | 360 | tru64) 361 | # The Tru64 compiler uses -MD to generate dependencies as a side 362 | # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. 363 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 364 | # dependencies in `foo.d' instead, so we check for that too. 365 | # Subdirectories are respected. 366 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 367 | test "x$dir" = "x$object" && dir= 368 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 369 | 370 | if test "$libtool" = yes; then 371 | # With Tru64 cc, shared objects can also be used to make a 372 | # static library. This mechanism is used in libtool 1.4 series to 373 | # handle both shared and static libraries in a single compilation. 374 | # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. 375 | # 376 | # With libtool 1.5 this exception was removed, and libtool now 377 | # generates 2 separate objects for the 2 libraries. These two 378 | # compilations output dependencies in $dir.libs/$base.o.d and 379 | # in $dir$base.o.d. We have to check for both files, because 380 | # one of the two compilations can be disabled. We should prefer 381 | # $dir$base.o.d over $dir.libs/$base.o.d because the latter is 382 | # automatically cleaned when .libs/ is deleted, while ignoring 383 | # the former would cause a distcleancheck panic. 384 | tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 385 | tmpdepfile2=$dir$base.o.d # libtool 1.5 386 | tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 387 | tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 388 | "$@" -Wc,-MD 389 | else 390 | tmpdepfile1=$dir$base.o.d 391 | tmpdepfile2=$dir$base.d 392 | tmpdepfile3=$dir$base.d 393 | tmpdepfile4=$dir$base.d 394 | "$@" -MD 395 | fi 396 | 397 | stat=$? 398 | if test $stat -eq 0; then : 399 | else 400 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 401 | exit $stat 402 | fi 403 | 404 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 405 | do 406 | test -f "$tmpdepfile" && break 407 | done 408 | if test -f "$tmpdepfile"; then 409 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 410 | # That's a tab and a space in the []. 411 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 412 | else 413 | echo "#dummy" > "$depfile" 414 | fi 415 | rm -f "$tmpdepfile" 416 | ;; 417 | 418 | msvc7) 419 | if test "$libtool" = yes; then 420 | showIncludes=-Wc,-showIncludes 421 | else 422 | showIncludes=-showIncludes 423 | fi 424 | "$@" $showIncludes > "$tmpdepfile" 425 | stat=$? 426 | grep -v '^Note: including file: ' "$tmpdepfile" 427 | if test "$stat" = 0; then : 428 | else 429 | rm -f "$tmpdepfile" 430 | exit $stat 431 | fi 432 | rm -f "$depfile" 433 | echo "$object : \\" > "$depfile" 434 | # The first sed program below extracts the file names and escapes 435 | # backslashes for cygpath. The second sed program outputs the file 436 | # name when reading, but also accumulates all include files in the 437 | # hold buffer in order to output them again at the end. This only 438 | # works with sed implementations that can handle large buffers. 439 | sed < "$tmpdepfile" -n ' 440 | /^Note: including file: *\(.*\)/ { 441 | s//\1/ 442 | s/\\/\\\\/g 443 | p 444 | }' | $cygpath_u | sort -u | sed -n ' 445 | s/ /\\ /g 446 | s/\(.*\)/ \1 \\/p 447 | s/.\(.*\) \\/\1:/ 448 | H 449 | $ { 450 | s/.*/ / 451 | G 452 | p 453 | }' >> "$depfile" 454 | rm -f "$tmpdepfile" 455 | ;; 456 | 457 | msvc7msys) 458 | # This case exists only to let depend.m4 do its work. It works by 459 | # looking at the text of this script. This case will never be run, 460 | # since it is checked for above. 461 | exit 1 462 | ;; 463 | 464 | #nosideeffect) 465 | # This comment above is used by automake to tell side-effect 466 | # dependency tracking mechanisms from slower ones. 467 | 468 | dashmstdout) 469 | # Important note: in order to support this mode, a compiler *must* 470 | # always write the preprocessed file to stdout, regardless of -o. 471 | "$@" || exit $? 472 | 473 | # Remove the call to Libtool. 474 | if test "$libtool" = yes; then 475 | while test "X$1" != 'X--mode=compile'; do 476 | shift 477 | done 478 | shift 479 | fi 480 | 481 | # Remove `-o $object'. 482 | IFS=" " 483 | for arg 484 | do 485 | case $arg in 486 | -o) 487 | shift 488 | ;; 489 | $object) 490 | shift 491 | ;; 492 | *) 493 | set fnord "$@" "$arg" 494 | shift # fnord 495 | shift # $arg 496 | ;; 497 | esac 498 | done 499 | 500 | test -z "$dashmflag" && dashmflag=-M 501 | # Require at least two characters before searching for `:' 502 | # in the target name. This is to cope with DOS-style filenames: 503 | # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. 504 | "$@" $dashmflag | 505 | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" 506 | rm -f "$depfile" 507 | cat < "$tmpdepfile" > "$depfile" 508 | tr ' ' ' 509 | ' < "$tmpdepfile" | \ 510 | ## Some versions of the HPUX 10.20 sed can't process this invocation 511 | ## correctly. Breaking it into two sed invocations is a workaround. 512 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 513 | rm -f "$tmpdepfile" 514 | ;; 515 | 516 | dashXmstdout) 517 | # This case only exists to satisfy depend.m4. It is never actually 518 | # run, as this mode is specially recognized in the preamble. 519 | exit 1 520 | ;; 521 | 522 | makedepend) 523 | "$@" || exit $? 524 | # Remove any Libtool call 525 | if test "$libtool" = yes; then 526 | while test "X$1" != 'X--mode=compile'; do 527 | shift 528 | done 529 | shift 530 | fi 531 | # X makedepend 532 | shift 533 | cleared=no eat=no 534 | for arg 535 | do 536 | case $cleared in 537 | no) 538 | set ""; shift 539 | cleared=yes ;; 540 | esac 541 | if test $eat = yes; then 542 | eat=no 543 | continue 544 | fi 545 | case "$arg" in 546 | -D*|-I*) 547 | set fnord "$@" "$arg"; shift ;; 548 | # Strip any option that makedepend may not understand. Remove 549 | # the object too, otherwise makedepend will parse it as a source file. 550 | -arch) 551 | eat=yes ;; 552 | -*|$object) 553 | ;; 554 | *) 555 | set fnord "$@" "$arg"; shift ;; 556 | esac 557 | done 558 | obj_suffix=`echo "$object" | sed 's/^.*\././'` 559 | touch "$tmpdepfile" 560 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 561 | rm -f "$depfile" 562 | # makedepend may prepend the VPATH from the source file name to the object. 563 | # No need to regex-escape $object, excess matching of '.' is harmless. 564 | sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" 565 | sed '1,2d' "$tmpdepfile" | tr ' ' ' 566 | ' | \ 567 | ## Some versions of the HPUX 10.20 sed can't process this invocation 568 | ## correctly. Breaking it into two sed invocations is a workaround. 569 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 570 | rm -f "$tmpdepfile" "$tmpdepfile".bak 571 | ;; 572 | 573 | cpp) 574 | # Important note: in order to support this mode, a compiler *must* 575 | # always write the preprocessed file to stdout. 576 | "$@" || exit $? 577 | 578 | # Remove the call to Libtool. 579 | if test "$libtool" = yes; then 580 | while test "X$1" != 'X--mode=compile'; do 581 | shift 582 | done 583 | shift 584 | fi 585 | 586 | # Remove `-o $object'. 587 | IFS=" " 588 | for arg 589 | do 590 | case $arg in 591 | -o) 592 | shift 593 | ;; 594 | $object) 595 | shift 596 | ;; 597 | *) 598 | set fnord "$@" "$arg" 599 | shift # fnord 600 | shift # $arg 601 | ;; 602 | esac 603 | done 604 | 605 | "$@" -E | 606 | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 607 | -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | 608 | sed '$ s: \\$::' > "$tmpdepfile" 609 | rm -f "$depfile" 610 | echo "$object : \\" > "$depfile" 611 | cat < "$tmpdepfile" >> "$depfile" 612 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 613 | rm -f "$tmpdepfile" 614 | ;; 615 | 616 | msvisualcpp) 617 | # Important note: in order to support this mode, a compiler *must* 618 | # always write the preprocessed file to stdout. 619 | "$@" || exit $? 620 | 621 | # Remove the call to Libtool. 622 | if test "$libtool" = yes; then 623 | while test "X$1" != 'X--mode=compile'; do 624 | shift 625 | done 626 | shift 627 | fi 628 | 629 | IFS=" " 630 | for arg 631 | do 632 | case "$arg" in 633 | -o) 634 | shift 635 | ;; 636 | $object) 637 | shift 638 | ;; 639 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 640 | set fnord "$@" 641 | shift 642 | shift 643 | ;; 644 | *) 645 | set fnord "$@" "$arg" 646 | shift 647 | shift 648 | ;; 649 | esac 650 | done 651 | "$@" -E 2>/dev/null | 652 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" 653 | rm -f "$depfile" 654 | echo "$object : \\" > "$depfile" 655 | sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" 656 | echo " " >> "$depfile" 657 | sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" 658 | rm -f "$tmpdepfile" 659 | ;; 660 | 661 | msvcmsys) 662 | # This case exists only to let depend.m4 do its work. It works by 663 | # looking at the text of this script. This case will never be run, 664 | # since it is checked for above. 665 | exit 1 666 | ;; 667 | 668 | none) 669 | exec "$@" 670 | ;; 671 | 672 | *) 673 | echo "Unknown depmode $depmode" 1>&2 674 | exit 1 675 | ;; 676 | esac 677 | 678 | exit 0 679 | 680 | # Local Variables: 681 | # mode: shell-script 682 | # sh-indentation: 2 683 | # eval: (add-hook 'write-file-hooks 'time-stamp) 684 | # time-stamp-start: "scriptversion=" 685 | # time-stamp-format: "%:y-%02m-%02d.%02H" 686 | # time-stamp-time-zone: "UTC" 687 | # time-stamp-end: "; # UTC" 688 | # End: 689 | -------------------------------------------------------------------------------- /example/movielens/movies.tsv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/premgopalan/bnprec/577ebda201533e69ccfb5b7edc149be90204f05f/example/movielens/movies.tsv -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2011-01-19.21; # UTC 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # `make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | nl=' 45 | ' 46 | IFS=" "" $nl" 47 | 48 | # set DOITPROG to echo to test this script 49 | 50 | # Don't use :- since 4.3BSD and earlier shells don't like it. 51 | doit=${DOITPROG-} 52 | if test -z "$doit"; then 53 | doit_exec=exec 54 | else 55 | doit_exec=$doit 56 | fi 57 | 58 | # Put in absolute file names if you don't have them in your path; 59 | # or use environment vars. 60 | 61 | chgrpprog=${CHGRPPROG-chgrp} 62 | chmodprog=${CHMODPROG-chmod} 63 | chownprog=${CHOWNPROG-chown} 64 | cmpprog=${CMPPROG-cmp} 65 | cpprog=${CPPROG-cp} 66 | mkdirprog=${MKDIRPROG-mkdir} 67 | mvprog=${MVPROG-mv} 68 | rmprog=${RMPROG-rm} 69 | stripprog=${STRIPPROG-strip} 70 | 71 | posix_glob='?' 72 | initialize_posix_glob=' 73 | test "$posix_glob" != "?" || { 74 | if (set -f) 2>/dev/null; then 75 | posix_glob= 76 | else 77 | posix_glob=: 78 | fi 79 | } 80 | ' 81 | 82 | posix_mkdir= 83 | 84 | # Desired mode of installed file. 85 | mode=0755 86 | 87 | chgrpcmd= 88 | chmodcmd=$chmodprog 89 | chowncmd= 90 | mvcmd=$mvprog 91 | rmcmd="$rmprog -f" 92 | stripcmd= 93 | 94 | src= 95 | dst= 96 | dir_arg= 97 | dst_arg= 98 | 99 | copy_on_change=false 100 | no_target_directory= 101 | 102 | usage="\ 103 | Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 104 | or: $0 [OPTION]... SRCFILES... DIRECTORY 105 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 106 | or: $0 [OPTION]... -d DIRECTORIES... 107 | 108 | In the 1st form, copy SRCFILE to DSTFILE. 109 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 110 | In the 4th, create DIRECTORIES. 111 | 112 | Options: 113 | --help display this help and exit. 114 | --version display version info and exit. 115 | 116 | -c (ignored) 117 | -C install only if different (preserve the last data modification time) 118 | -d create directories instead of installing files. 119 | -g GROUP $chgrpprog installed files to GROUP. 120 | -m MODE $chmodprog installed files to MODE. 121 | -o USER $chownprog installed files to USER. 122 | -s $stripprog installed files. 123 | -t DIRECTORY install into DIRECTORY. 124 | -T report an error if DSTFILE is a directory. 125 | 126 | Environment variables override the default commands: 127 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 128 | RMPROG STRIPPROG 129 | " 130 | 131 | while test $# -ne 0; do 132 | case $1 in 133 | -c) ;; 134 | 135 | -C) copy_on_change=true;; 136 | 137 | -d) dir_arg=true;; 138 | 139 | -g) chgrpcmd="$chgrpprog $2" 140 | shift;; 141 | 142 | --help) echo "$usage"; exit $?;; 143 | 144 | -m) mode=$2 145 | case $mode in 146 | *' '* | *' '* | *' 147 | '* | *'*'* | *'?'* | *'['*) 148 | echo "$0: invalid mode: $mode" >&2 149 | exit 1;; 150 | esac 151 | shift;; 152 | 153 | -o) chowncmd="$chownprog $2" 154 | shift;; 155 | 156 | -s) stripcmd=$stripprog;; 157 | 158 | -t) dst_arg=$2 159 | # Protect names problematic for `test' and other utilities. 160 | case $dst_arg in 161 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 162 | esac 163 | shift;; 164 | 165 | -T) no_target_directory=true;; 166 | 167 | --version) echo "$0 $scriptversion"; exit $?;; 168 | 169 | --) shift 170 | break;; 171 | 172 | -*) echo "$0: invalid option: $1" >&2 173 | exit 1;; 174 | 175 | *) break;; 176 | esac 177 | shift 178 | done 179 | 180 | if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 181 | # When -d is used, all remaining arguments are directories to create. 182 | # When -t is used, the destination is already specified. 183 | # Otherwise, the last argument is the destination. Remove it from $@. 184 | for arg 185 | do 186 | if test -n "$dst_arg"; then 187 | # $@ is not empty: it contains at least $arg. 188 | set fnord "$@" "$dst_arg" 189 | shift # fnord 190 | fi 191 | shift # arg 192 | dst_arg=$arg 193 | # Protect names problematic for `test' and other utilities. 194 | case $dst_arg in 195 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 196 | esac 197 | done 198 | fi 199 | 200 | if test $# -eq 0; then 201 | if test -z "$dir_arg"; then 202 | echo "$0: no input file specified." >&2 203 | exit 1 204 | fi 205 | # It's OK to call `install-sh -d' without argument. 206 | # This can happen when creating conditional directories. 207 | exit 0 208 | fi 209 | 210 | if test -z "$dir_arg"; then 211 | do_exit='(exit $ret); exit $ret' 212 | trap "ret=129; $do_exit" 1 213 | trap "ret=130; $do_exit" 2 214 | trap "ret=141; $do_exit" 13 215 | trap "ret=143; $do_exit" 15 216 | 217 | # Set umask so as not to create temps with too-generous modes. 218 | # However, 'strip' requires both read and write access to temps. 219 | case $mode in 220 | # Optimize common cases. 221 | *644) cp_umask=133;; 222 | *755) cp_umask=22;; 223 | 224 | *[0-7]) 225 | if test -z "$stripcmd"; then 226 | u_plus_rw= 227 | else 228 | u_plus_rw='% 200' 229 | fi 230 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 231 | *) 232 | if test -z "$stripcmd"; then 233 | u_plus_rw= 234 | else 235 | u_plus_rw=,u+rw 236 | fi 237 | cp_umask=$mode$u_plus_rw;; 238 | esac 239 | fi 240 | 241 | for src 242 | do 243 | # Protect names problematic for `test' and other utilities. 244 | case $src in 245 | -* | [=\(\)!]) src=./$src;; 246 | esac 247 | 248 | if test -n "$dir_arg"; then 249 | dst=$src 250 | dstdir=$dst 251 | test -d "$dstdir" 252 | dstdir_status=$? 253 | else 254 | 255 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 256 | # might cause directories to be created, which would be especially bad 257 | # if $src (and thus $dsttmp) contains '*'. 258 | if test ! -f "$src" && test ! -d "$src"; then 259 | echo "$0: $src does not exist." >&2 260 | exit 1 261 | fi 262 | 263 | if test -z "$dst_arg"; then 264 | echo "$0: no destination specified." >&2 265 | exit 1 266 | fi 267 | dst=$dst_arg 268 | 269 | # If destination is a directory, append the input filename; won't work 270 | # if double slashes aren't ignored. 271 | if test -d "$dst"; then 272 | if test -n "$no_target_directory"; then 273 | echo "$0: $dst_arg: Is a directory" >&2 274 | exit 1 275 | fi 276 | dstdir=$dst 277 | dst=$dstdir/`basename "$src"` 278 | dstdir_status=0 279 | else 280 | # Prefer dirname, but fall back on a substitute if dirname fails. 281 | dstdir=` 282 | (dirname "$dst") 2>/dev/null || 283 | expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 284 | X"$dst" : 'X\(//\)[^/]' \| \ 285 | X"$dst" : 'X\(//\)$' \| \ 286 | X"$dst" : 'X\(/\)' \| . 2>/dev/null || 287 | echo X"$dst" | 288 | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 289 | s//\1/ 290 | q 291 | } 292 | /^X\(\/\/\)[^/].*/{ 293 | s//\1/ 294 | q 295 | } 296 | /^X\(\/\/\)$/{ 297 | s//\1/ 298 | q 299 | } 300 | /^X\(\/\).*/{ 301 | s//\1/ 302 | q 303 | } 304 | s/.*/./; q' 305 | ` 306 | 307 | test -d "$dstdir" 308 | dstdir_status=$? 309 | fi 310 | fi 311 | 312 | obsolete_mkdir_used=false 313 | 314 | if test $dstdir_status != 0; then 315 | case $posix_mkdir in 316 | '') 317 | # Create intermediate dirs using mode 755 as modified by the umask. 318 | # This is like FreeBSD 'install' as of 1997-10-28. 319 | umask=`umask` 320 | case $stripcmd.$umask in 321 | # Optimize common cases. 322 | *[2367][2367]) mkdir_umask=$umask;; 323 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 324 | 325 | *[0-7]) 326 | mkdir_umask=`expr $umask + 22 \ 327 | - $umask % 100 % 40 + $umask % 20 \ 328 | - $umask % 10 % 4 + $umask % 2 329 | `;; 330 | *) mkdir_umask=$umask,go-w;; 331 | esac 332 | 333 | # With -d, create the new directory with the user-specified mode. 334 | # Otherwise, rely on $mkdir_umask. 335 | if test -n "$dir_arg"; then 336 | mkdir_mode=-m$mode 337 | else 338 | mkdir_mode= 339 | fi 340 | 341 | posix_mkdir=false 342 | case $umask in 343 | *[123567][0-7][0-7]) 344 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 345 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 346 | ;; 347 | *) 348 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 349 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 350 | 351 | if (umask $mkdir_umask && 352 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 353 | then 354 | if test -z "$dir_arg" || { 355 | # Check for POSIX incompatibilities with -m. 356 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 357 | # other-writeable bit of parent directory when it shouldn't. 358 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 359 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 360 | case $ls_ld_tmpdir in 361 | d????-?r-*) different_mode=700;; 362 | d????-?--*) different_mode=755;; 363 | *) false;; 364 | esac && 365 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 366 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 367 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 368 | } 369 | } 370 | then posix_mkdir=: 371 | fi 372 | rmdir "$tmpdir/d" "$tmpdir" 373 | else 374 | # Remove any dirs left behind by ancient mkdir implementations. 375 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 376 | fi 377 | trap '' 0;; 378 | esac;; 379 | esac 380 | 381 | if 382 | $posix_mkdir && ( 383 | umask $mkdir_umask && 384 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 385 | ) 386 | then : 387 | else 388 | 389 | # The umask is ridiculous, or mkdir does not conform to POSIX, 390 | # or it failed possibly due to a race condition. Create the 391 | # directory the slow way, step by step, checking for races as we go. 392 | 393 | case $dstdir in 394 | /*) prefix='/';; 395 | [-=\(\)!]*) prefix='./';; 396 | *) prefix='';; 397 | esac 398 | 399 | eval "$initialize_posix_glob" 400 | 401 | oIFS=$IFS 402 | IFS=/ 403 | $posix_glob set -f 404 | set fnord $dstdir 405 | shift 406 | $posix_glob set +f 407 | IFS=$oIFS 408 | 409 | prefixes= 410 | 411 | for d 412 | do 413 | test X"$d" = X && continue 414 | 415 | prefix=$prefix$d 416 | if test -d "$prefix"; then 417 | prefixes= 418 | else 419 | if $posix_mkdir; then 420 | (umask=$mkdir_umask && 421 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 422 | # Don't fail if two instances are running concurrently. 423 | test -d "$prefix" || exit 1 424 | else 425 | case $prefix in 426 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 427 | *) qprefix=$prefix;; 428 | esac 429 | prefixes="$prefixes '$qprefix'" 430 | fi 431 | fi 432 | prefix=$prefix/ 433 | done 434 | 435 | if test -n "$prefixes"; then 436 | # Don't fail if two instances are running concurrently. 437 | (umask $mkdir_umask && 438 | eval "\$doit_exec \$mkdirprog $prefixes") || 439 | test -d "$dstdir" || exit 1 440 | obsolete_mkdir_used=true 441 | fi 442 | fi 443 | fi 444 | 445 | if test -n "$dir_arg"; then 446 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 447 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 448 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 449 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 450 | else 451 | 452 | # Make a couple of temp file names in the proper directory. 453 | dsttmp=$dstdir/_inst.$$_ 454 | rmtmp=$dstdir/_rm.$$_ 455 | 456 | # Trap to clean up those temp files at exit. 457 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 458 | 459 | # Copy the file name to the temp name. 460 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 461 | 462 | # and set any options; do chmod last to preserve setuid bits. 463 | # 464 | # If any of these fail, we abort the whole thing. If we want to 465 | # ignore errors from any of these, just make sure not to ignore 466 | # errors from the above "$doit $cpprog $src $dsttmp" command. 467 | # 468 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 469 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 470 | { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 471 | { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 472 | 473 | # If -C, don't bother to copy if it wouldn't change the file. 474 | if $copy_on_change && 475 | old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 476 | new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 477 | 478 | eval "$initialize_posix_glob" && 479 | $posix_glob set -f && 480 | set X $old && old=:$2:$4:$5:$6 && 481 | set X $new && new=:$2:$4:$5:$6 && 482 | $posix_glob set +f && 483 | 484 | test "$old" = "$new" && 485 | $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 486 | then 487 | rm -f "$dsttmp" 488 | else 489 | # Rename the file to the real destination. 490 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 491 | 492 | # The rename failed, perhaps because mv can't rename something else 493 | # to itself, or perhaps because mv is so ancient that it does not 494 | # support -f. 495 | { 496 | # Now remove or move aside any old file at destination location. 497 | # We try this two ways since rm can't unlink itself on some 498 | # systems and the destination file might be busy for other 499 | # reasons. In this case, the final cleanup might fail but the new 500 | # file should still install successfully. 501 | { 502 | test ! -f "$dst" || 503 | $doit $rmcmd -f "$dst" 2>/dev/null || 504 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 505 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 506 | } || 507 | { echo "$0: cannot unlink or rename $dst" >&2 508 | (exit 1); exit 1 509 | } 510 | } && 511 | 512 | # Now rename the file to the real destination. 513 | $doit $mvcmd "$dsttmp" "$dst" 514 | } 515 | fi || exit 1 516 | 517 | trap '' 0 518 | fi 519 | done 520 | 521 | # Local variables: 522 | # eval: (add-hook 'write-file-hooks 'time-stamp) 523 | # time-stamp-start: "scriptversion=" 524 | # time-stamp-format: "%:y-%02m-%02d.%02H" 525 | # time-stamp-time-zone: "UTC" 526 | # time-stamp-end: "; # UTC" 527 | # End: 528 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | 4 | scriptversion=2012-01-06.13; # UTC 5 | 6 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 7 | # 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 8 | # Originally by Fran,cois Pinard , 1996. 9 | 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | if test $# -eq 0; then 29 | echo 1>&2 "Try \`$0 --help' for more information" 30 | exit 1 31 | fi 32 | 33 | run=: 34 | sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' 35 | sed_minuso='s/.* -o \([^ ]*\).*/\1/p' 36 | 37 | # In the cases where this matters, `missing' is being run in the 38 | # srcdir already. 39 | if test -f configure.ac; then 40 | configure_ac=configure.ac 41 | else 42 | configure_ac=configure.in 43 | fi 44 | 45 | msg="missing on your system" 46 | 47 | case $1 in 48 | --run) 49 | # Try to run requested program, and just exit if it succeeds. 50 | run= 51 | shift 52 | "$@" && exit 0 53 | # Exit code 63 means version mismatch. This often happens 54 | # when the user try to use an ancient version of a tool on 55 | # a file that requires a minimum version. In this case we 56 | # we should proceed has if the program had been absent, or 57 | # if --run hadn't been passed. 58 | if test $? = 63; then 59 | run=: 60 | msg="probably too old" 61 | fi 62 | ;; 63 | 64 | -h|--h|--he|--hel|--help) 65 | echo "\ 66 | $0 [OPTION]... PROGRAM [ARGUMENT]... 67 | 68 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 69 | error status if there is no known handling for PROGRAM. 70 | 71 | Options: 72 | -h, --help display this help and exit 73 | -v, --version output version information and exit 74 | --run try to run the given command, and emulate it if it fails 75 | 76 | Supported PROGRAM values: 77 | aclocal touch file \`aclocal.m4' 78 | autoconf touch file \`configure' 79 | autoheader touch file \`config.h.in' 80 | autom4te touch the output file, or create a stub one 81 | automake touch all \`Makefile.in' files 82 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 83 | flex create \`lex.yy.c', if possible, from existing .c 84 | help2man touch the output file 85 | lex create \`lex.yy.c', if possible, from existing .c 86 | makeinfo touch the output file 87 | yacc create \`y.tab.[ch]', if possible, from existing .[ch] 88 | 89 | Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and 90 | \`g' are ignored when checking the name. 91 | 92 | Send bug reports to ." 93 | exit $? 94 | ;; 95 | 96 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 97 | echo "missing $scriptversion (GNU Automake)" 98 | exit $? 99 | ;; 100 | 101 | -*) 102 | echo 1>&2 "$0: Unknown \`$1' option" 103 | echo 1>&2 "Try \`$0 --help' for more information" 104 | exit 1 105 | ;; 106 | 107 | esac 108 | 109 | # normalize program name to check for. 110 | program=`echo "$1" | sed ' 111 | s/^gnu-//; t 112 | s/^gnu//; t 113 | s/^g//; t'` 114 | 115 | # Now exit if we have it, but it failed. Also exit now if we 116 | # don't have it and --version was passed (most likely to detect 117 | # the program). This is about non-GNU programs, so use $1 not 118 | # $program. 119 | case $1 in 120 | lex*|yacc*) 121 | # Not GNU programs, they don't have --version. 122 | ;; 123 | 124 | *) 125 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 126 | # We have it, but it failed. 127 | exit 1 128 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 129 | # Could not run --version or --help. This is probably someone 130 | # running `$TOOL --version' or `$TOOL --help' to check whether 131 | # $TOOL exists and not knowing $TOOL uses missing. 132 | exit 1 133 | fi 134 | ;; 135 | esac 136 | 137 | # If it does not exist, or fails to run (possibly an outdated version), 138 | # try to emulate it. 139 | case $program in 140 | aclocal*) 141 | echo 1>&2 "\ 142 | WARNING: \`$1' is $msg. You should only need it if 143 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 144 | to install the \`Automake' and \`Perl' packages. Grab them from 145 | any GNU archive site." 146 | touch aclocal.m4 147 | ;; 148 | 149 | autoconf*) 150 | echo 1>&2 "\ 151 | WARNING: \`$1' is $msg. You should only need it if 152 | you modified \`${configure_ac}'. You might want to install the 153 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 154 | archive site." 155 | touch configure 156 | ;; 157 | 158 | autoheader*) 159 | echo 1>&2 "\ 160 | WARNING: \`$1' is $msg. You should only need it if 161 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 162 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 163 | from any GNU archive site." 164 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 165 | test -z "$files" && files="config.h" 166 | touch_files= 167 | for f in $files; do 168 | case $f in 169 | *:*) touch_files="$touch_files "`echo "$f" | 170 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 171 | *) touch_files="$touch_files $f.in";; 172 | esac 173 | done 174 | touch $touch_files 175 | ;; 176 | 177 | automake*) 178 | echo 1>&2 "\ 179 | WARNING: \`$1' is $msg. You should only need it if 180 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 181 | You might want to install the \`Automake' and \`Perl' packages. 182 | Grab them from any GNU archive site." 183 | find . -type f -name Makefile.am -print | 184 | sed 's/\.am$/.in/' | 185 | while read f; do touch "$f"; done 186 | ;; 187 | 188 | autom4te*) 189 | echo 1>&2 "\ 190 | WARNING: \`$1' is needed, but is $msg. 191 | You might have modified some files without having the 192 | proper tools for further handling them. 193 | You can get \`$1' as part of \`Autoconf' from any GNU 194 | archive site." 195 | 196 | file=`echo "$*" | sed -n "$sed_output"` 197 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 198 | if test -f "$file"; then 199 | touch $file 200 | else 201 | test -z "$file" || exec >$file 202 | echo "#! /bin/sh" 203 | echo "# Created by GNU Automake missing as a replacement of" 204 | echo "# $ $@" 205 | echo "exit 0" 206 | chmod +x $file 207 | exit 1 208 | fi 209 | ;; 210 | 211 | bison*|yacc*) 212 | echo 1>&2 "\ 213 | WARNING: \`$1' $msg. You should only need it if 214 | you modified a \`.y' file. You may need the \`Bison' package 215 | in order for those modifications to take effect. You can get 216 | \`Bison' from any GNU archive site." 217 | rm -f y.tab.c y.tab.h 218 | if test $# -ne 1; then 219 | eval LASTARG=\${$#} 220 | case $LASTARG in 221 | *.y) 222 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 223 | if test -f "$SRCFILE"; then 224 | cp "$SRCFILE" y.tab.c 225 | fi 226 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 227 | if test -f "$SRCFILE"; then 228 | cp "$SRCFILE" y.tab.h 229 | fi 230 | ;; 231 | esac 232 | fi 233 | if test ! -f y.tab.h; then 234 | echo >y.tab.h 235 | fi 236 | if test ! -f y.tab.c; then 237 | echo 'main() { return 0; }' >y.tab.c 238 | fi 239 | ;; 240 | 241 | lex*|flex*) 242 | echo 1>&2 "\ 243 | WARNING: \`$1' is $msg. You should only need it if 244 | you modified a \`.l' file. You may need the \`Flex' package 245 | in order for those modifications to take effect. You can get 246 | \`Flex' from any GNU archive site." 247 | rm -f lex.yy.c 248 | if test $# -ne 1; then 249 | eval LASTARG=\${$#} 250 | case $LASTARG in 251 | *.l) 252 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 253 | if test -f "$SRCFILE"; then 254 | cp "$SRCFILE" lex.yy.c 255 | fi 256 | ;; 257 | esac 258 | fi 259 | if test ! -f lex.yy.c; then 260 | echo 'main() { return 0; }' >lex.yy.c 261 | fi 262 | ;; 263 | 264 | help2man*) 265 | echo 1>&2 "\ 266 | WARNING: \`$1' is $msg. You should only need it if 267 | you modified a dependency of a manual page. You may need the 268 | \`Help2man' package in order for those modifications to take 269 | effect. You can get \`Help2man' from any GNU archive site." 270 | 271 | file=`echo "$*" | sed -n "$sed_output"` 272 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 273 | if test -f "$file"; then 274 | touch $file 275 | else 276 | test -z "$file" || exec >$file 277 | echo ".ab help2man is required to generate this page" 278 | exit $? 279 | fi 280 | ;; 281 | 282 | makeinfo*) 283 | echo 1>&2 "\ 284 | WARNING: \`$1' is $msg. You should only need it if 285 | you modified a \`.texi' or \`.texinfo' file, or any other file 286 | indirectly affecting the aspect of the manual. The spurious 287 | call might also be the consequence of using a buggy \`make' (AIX, 288 | DU, IRIX). You might want to install the \`Texinfo' package or 289 | the \`GNU make' package. Grab either from any GNU archive site." 290 | # The file to touch is that specified with -o ... 291 | file=`echo "$*" | sed -n "$sed_output"` 292 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 293 | if test -z "$file"; then 294 | # ... or it is the one specified with @setfilename ... 295 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 296 | file=`sed -n ' 297 | /^@setfilename/{ 298 | s/.* \([^ ]*\) *$/\1/ 299 | p 300 | q 301 | }' $infile` 302 | # ... or it is derived from the source name (dir/f.texi becomes f.info) 303 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info 304 | fi 305 | # If the file does not exist, the user really needs makeinfo; 306 | # let's fail without touching anything. 307 | test -f $file || exit 1 308 | touch $file 309 | ;; 310 | 311 | *) 312 | echo 1>&2 "\ 313 | WARNING: \`$1' is needed, and is $msg. 314 | You might have modified some files without having the 315 | proper tools for further handling them. Check the \`README' file, 316 | it often tells you about the needed prerequisites for installing 317 | this package. You may also peek at any GNU archive site, in case 318 | some other package would contain this missing \`$1' program." 319 | exit 1 320 | ;; 321 | esac 322 | 323 | exit 0 324 | 325 | # Local variables: 326 | # eval: (add-hook 'write-file-hooks 'time-stamp) 327 | # time-stamp-start: "scriptversion=" 328 | # time-stamp-format: "%:y-%02m-%02d.%02H" 329 | # time-stamp-time-zone: "UTC" 330 | # time-stamp-end: "; # UTC" 331 | # End: 332 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = gaprec 2 | gaprec_SOURCES = env.hh ratings.hh ratings.cc matrix.hh main.cc log.cc log.hh gaprec.hh gaprec.cc bnprec.cc bnprec.hh gammapoisson.hh 3 | #if DEBUG 4 | #AM_CFLAGS = -g -O0 5 | #AM_CXXFLAGS = -g -O0 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /src/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.11.3 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software 6 | # Foundation, Inc. 7 | # This Makefile.in is free software; the Free Software Foundation 8 | # gives unlimited permission to copy and/or distribute it, 9 | # with or without modifications, as long as this notice is preserved. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 13 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 | # PARTICULAR PURPOSE. 15 | 16 | @SET_MAKE@ 17 | 18 | VPATH = @srcdir@ 19 | pkgdatadir = $(datadir)/@PACKAGE@ 20 | pkgincludedir = $(includedir)/@PACKAGE@ 21 | pkglibdir = $(libdir)/@PACKAGE@ 22 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 23 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 24 | install_sh_DATA = $(install_sh) -c -m 644 25 | install_sh_PROGRAM = $(install_sh) -c 26 | install_sh_SCRIPT = $(install_sh) -c 27 | INSTALL_HEADER = $(INSTALL_DATA) 28 | transform = $(program_transform_name) 29 | NORMAL_INSTALL = : 30 | PRE_INSTALL = : 31 | POST_INSTALL = : 32 | NORMAL_UNINSTALL = : 33 | PRE_UNINSTALL = : 34 | POST_UNINSTALL = : 35 | bin_PROGRAMS = gaprec$(EXEEXT) 36 | subdir = src 37 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in 38 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 39 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 40 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 41 | $(ACLOCAL_M4) 42 | mkinstalldirs = $(install_sh) -d 43 | CONFIG_CLEAN_FILES = 44 | CONFIG_CLEAN_VPATH_FILES = 45 | am__installdirs = "$(DESTDIR)$(bindir)" 46 | PROGRAMS = $(bin_PROGRAMS) 47 | am_gaprec_OBJECTS = ratings.$(OBJEXT) main.$(OBJEXT) log.$(OBJEXT) \ 48 | gaprec.$(OBJEXT) bnprec.$(OBJEXT) 49 | gaprec_OBJECTS = $(am_gaprec_OBJECTS) 50 | gaprec_LDADD = $(LDADD) 51 | DEFAULT_INCLUDES = -I.@am__isrc@ 52 | depcomp = $(SHELL) $(top_srcdir)/depcomp 53 | am__depfiles_maybe = depfiles 54 | am__mv = mv -f 55 | CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ 56 | $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) 57 | CXXLD = $(CXX) 58 | CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ 59 | -o $@ 60 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ 61 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 62 | CCLD = $(CC) 63 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ 64 | SOURCES = $(gaprec_SOURCES) 65 | DIST_SOURCES = $(gaprec_SOURCES) 66 | ETAGS = etags 67 | CTAGS = ctags 68 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 69 | ACLOCAL = @ACLOCAL@ 70 | AMTAR = @AMTAR@ 71 | AUTOCONF = @AUTOCONF@ 72 | AUTOHEADER = @AUTOHEADER@ 73 | AUTOMAKE = @AUTOMAKE@ 74 | AWK = @AWK@ 75 | CC = @CC@ 76 | CCDEPMODE = @CCDEPMODE@ 77 | CFLAGS = @CFLAGS@ 78 | CPP = @CPP@ 79 | CPPFLAGS = @CPPFLAGS@ 80 | CXX = @CXX@ 81 | CXXDEPMODE = @CXXDEPMODE@ 82 | CXXFLAGS = @CXXFLAGS@ 83 | CYGPATH_W = @CYGPATH_W@ 84 | DEFS = @DEFS@ 85 | DEPDIR = @DEPDIR@ 86 | ECHO_C = @ECHO_C@ 87 | ECHO_N = @ECHO_N@ 88 | ECHO_T = @ECHO_T@ 89 | EGREP = @EGREP@ 90 | EXEEXT = @EXEEXT@ 91 | GREP = @GREP@ 92 | INSTALL = @INSTALL@ 93 | INSTALL_DATA = @INSTALL_DATA@ 94 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 95 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 96 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 97 | LDFLAGS = @LDFLAGS@ 98 | LIBOBJS = @LIBOBJS@ 99 | LIBS = @LIBS@ 100 | LTLIBOBJS = @LTLIBOBJS@ 101 | MAKEINFO = @MAKEINFO@ 102 | MKDIR_P = @MKDIR_P@ 103 | OBJEXT = @OBJEXT@ 104 | PACKAGE = @PACKAGE@ 105 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 106 | PACKAGE_NAME = @PACKAGE_NAME@ 107 | PACKAGE_STRING = @PACKAGE_STRING@ 108 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 109 | PACKAGE_URL = @PACKAGE_URL@ 110 | PACKAGE_VERSION = @PACKAGE_VERSION@ 111 | PATH_SEPARATOR = @PATH_SEPARATOR@ 112 | POW_LIB = @POW_LIB@ 113 | SET_MAKE = @SET_MAKE@ 114 | SHELL = @SHELL@ 115 | STRIP = @STRIP@ 116 | VERSION = @VERSION@ 117 | abs_builddir = @abs_builddir@ 118 | abs_srcdir = @abs_srcdir@ 119 | abs_top_builddir = @abs_top_builddir@ 120 | abs_top_srcdir = @abs_top_srcdir@ 121 | ac_ct_CC = @ac_ct_CC@ 122 | ac_ct_CXX = @ac_ct_CXX@ 123 | am__include = @am__include@ 124 | am__leading_dot = @am__leading_dot@ 125 | am__quote = @am__quote@ 126 | am__tar = @am__tar@ 127 | am__untar = @am__untar@ 128 | bindir = @bindir@ 129 | build_alias = @build_alias@ 130 | builddir = @builddir@ 131 | datadir = @datadir@ 132 | datarootdir = @datarootdir@ 133 | docdir = @docdir@ 134 | dvidir = @dvidir@ 135 | exec_prefix = @exec_prefix@ 136 | host_alias = @host_alias@ 137 | htmldir = @htmldir@ 138 | includedir = @includedir@ 139 | infodir = @infodir@ 140 | install_sh = @install_sh@ 141 | libdir = @libdir@ 142 | libexecdir = @libexecdir@ 143 | localedir = @localedir@ 144 | localstatedir = @localstatedir@ 145 | mandir = @mandir@ 146 | mkdir_p = @mkdir_p@ 147 | oldincludedir = @oldincludedir@ 148 | pdfdir = @pdfdir@ 149 | prefix = @prefix@ 150 | program_transform_name = @program_transform_name@ 151 | psdir = @psdir@ 152 | sbindir = @sbindir@ 153 | sharedstatedir = @sharedstatedir@ 154 | srcdir = @srcdir@ 155 | sysconfdir = @sysconfdir@ 156 | target_alias = @target_alias@ 157 | top_build_prefix = @top_build_prefix@ 158 | top_builddir = @top_builddir@ 159 | top_srcdir = @top_srcdir@ 160 | gaprec_SOURCES = env.hh ratings.hh ratings.cc matrix.hh main.cc log.cc log.hh gaprec.hh gaprec.cc bnprec.cc bnprec.hh gammapoisson.hh 161 | all: all-am 162 | 163 | .SUFFIXES: 164 | .SUFFIXES: .cc .o .obj 165 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 166 | @for dep in $?; do \ 167 | case '$(am__configure_deps)' in \ 168 | *$$dep*) \ 169 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ 170 | && { if test -f $@; then exit 0; else break; fi; }; \ 171 | exit 1;; \ 172 | esac; \ 173 | done; \ 174 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ 175 | $(am__cd) $(top_srcdir) && \ 176 | $(AUTOMAKE) --gnu src/Makefile 177 | .PRECIOUS: Makefile 178 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 179 | @case '$?' in \ 180 | *config.status*) \ 181 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 182 | *) \ 183 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ 184 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ 185 | esac; 186 | 187 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 188 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 189 | 190 | $(top_srcdir)/configure: $(am__configure_deps) 191 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 192 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 193 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 194 | $(am__aclocal_m4_deps): 195 | install-binPROGRAMS: $(bin_PROGRAMS) 196 | @$(NORMAL_INSTALL) 197 | test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" 198 | @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ 199 | for p in $$list; do echo "$$p $$p"; done | \ 200 | sed 's/$(EXEEXT)$$//' | \ 201 | while read p p1; do if test -f $$p; \ 202 | then echo "$$p"; echo "$$p"; else :; fi; \ 203 | done | \ 204 | sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ 205 | -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ 206 | sed 'N;N;N;s,\n, ,g' | \ 207 | $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ 208 | { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ 209 | if ($$2 == $$4) files[d] = files[d] " " $$1; \ 210 | else { print "f", $$3 "/" $$4, $$1; } } \ 211 | END { for (d in files) print "f", d, files[d] }' | \ 212 | while read type dir files; do \ 213 | if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ 214 | test -z "$$files" || { \ 215 | echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ 216 | $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ 217 | } \ 218 | ; done 219 | 220 | uninstall-binPROGRAMS: 221 | @$(NORMAL_UNINSTALL) 222 | @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ 223 | files=`for p in $$list; do echo "$$p"; done | \ 224 | sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ 225 | -e 's/$$/$(EXEEXT)/' `; \ 226 | test -n "$$list" || exit 0; \ 227 | echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ 228 | cd "$(DESTDIR)$(bindir)" && rm -f $$files 229 | 230 | clean-binPROGRAMS: 231 | -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) 232 | gaprec$(EXEEXT): $(gaprec_OBJECTS) $(gaprec_DEPENDENCIES) $(EXTRA_gaprec_DEPENDENCIES) 233 | @rm -f gaprec$(EXEEXT) 234 | $(CXXLINK) $(gaprec_OBJECTS) $(gaprec_LDADD) $(LIBS) 235 | 236 | mostlyclean-compile: 237 | -rm -f *.$(OBJEXT) 238 | 239 | distclean-compile: 240 | -rm -f *.tab.c 241 | 242 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bnprec.Po@am__quote@ 243 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gaprec.Po@am__quote@ 244 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ 245 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ 246 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ratings.Po@am__quote@ 247 | 248 | .cc.o: 249 | @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 250 | @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 251 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 252 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 253 | @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< 254 | 255 | .cc.obj: 256 | @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` 257 | @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 258 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 259 | @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 260 | @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` 261 | 262 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) 263 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 264 | unique=`for i in $$list; do \ 265 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 266 | done | \ 267 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 268 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 269 | mkid -fID $$unique 270 | tags: TAGS 271 | 272 | TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ 273 | $(TAGS_FILES) $(LISP) 274 | set x; \ 275 | here=`pwd`; \ 276 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 277 | unique=`for i in $$list; do \ 278 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 279 | done | \ 280 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 281 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 282 | shift; \ 283 | if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ 284 | test -n "$$unique" || unique=$$empty_fix; \ 285 | if test $$# -gt 0; then \ 286 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 287 | "$$@" $$unique; \ 288 | else \ 289 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 290 | $$unique; \ 291 | fi; \ 292 | fi 293 | ctags: CTAGS 294 | CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ 295 | $(TAGS_FILES) $(LISP) 296 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 297 | unique=`for i in $$list; do \ 298 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 299 | done | \ 300 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 301 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 302 | test -z "$(CTAGS_ARGS)$$unique" \ 303 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 304 | $$unique 305 | 306 | GTAGS: 307 | here=`$(am__cd) $(top_builddir) && pwd` \ 308 | && $(am__cd) $(top_srcdir) \ 309 | && gtags -i $(GTAGS_ARGS) "$$here" 310 | 311 | distclean-tags: 312 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 313 | 314 | distdir: $(DISTFILES) 315 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 316 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 317 | list='$(DISTFILES)'; \ 318 | dist_files=`for file in $$list; do echo $$file; done | \ 319 | sed -e "s|^$$srcdirstrip/||;t" \ 320 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 321 | case $$dist_files in \ 322 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 323 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 324 | sort -u` ;; \ 325 | esac; \ 326 | for file in $$dist_files; do \ 327 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 328 | if test -d $$d/$$file; then \ 329 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 330 | if test -d "$(distdir)/$$file"; then \ 331 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 332 | fi; \ 333 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 334 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 335 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 336 | fi; \ 337 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 338 | else \ 339 | test -f "$(distdir)/$$file" \ 340 | || cp -p $$d/$$file "$(distdir)/$$file" \ 341 | || exit 1; \ 342 | fi; \ 343 | done 344 | check-am: all-am 345 | check: check-am 346 | all-am: Makefile $(PROGRAMS) 347 | installdirs: 348 | for dir in "$(DESTDIR)$(bindir)"; do \ 349 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ 350 | done 351 | install: install-am 352 | install-exec: install-exec-am 353 | install-data: install-data-am 354 | uninstall: uninstall-am 355 | 356 | install-am: all-am 357 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 358 | 359 | installcheck: installcheck-am 360 | install-strip: 361 | if test -z '$(STRIP)'; then \ 362 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 363 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 364 | install; \ 365 | else \ 366 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 367 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 368 | "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ 369 | fi 370 | mostlyclean-generic: 371 | 372 | clean-generic: 373 | 374 | distclean-generic: 375 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 376 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 377 | 378 | maintainer-clean-generic: 379 | @echo "This command is intended for maintainers to use" 380 | @echo "it deletes files that may require special tools to rebuild." 381 | clean: clean-am 382 | 383 | clean-am: clean-binPROGRAMS clean-generic mostlyclean-am 384 | 385 | distclean: distclean-am 386 | -rm -rf ./$(DEPDIR) 387 | -rm -f Makefile 388 | distclean-am: clean-am distclean-compile distclean-generic \ 389 | distclean-tags 390 | 391 | dvi: dvi-am 392 | 393 | dvi-am: 394 | 395 | html: html-am 396 | 397 | html-am: 398 | 399 | info: info-am 400 | 401 | info-am: 402 | 403 | install-data-am: 404 | 405 | install-dvi: install-dvi-am 406 | 407 | install-dvi-am: 408 | 409 | install-exec-am: install-binPROGRAMS 410 | 411 | install-html: install-html-am 412 | 413 | install-html-am: 414 | 415 | install-info: install-info-am 416 | 417 | install-info-am: 418 | 419 | install-man: 420 | 421 | install-pdf: install-pdf-am 422 | 423 | install-pdf-am: 424 | 425 | install-ps: install-ps-am 426 | 427 | install-ps-am: 428 | 429 | installcheck-am: 430 | 431 | maintainer-clean: maintainer-clean-am 432 | -rm -rf ./$(DEPDIR) 433 | -rm -f Makefile 434 | maintainer-clean-am: distclean-am maintainer-clean-generic 435 | 436 | mostlyclean: mostlyclean-am 437 | 438 | mostlyclean-am: mostlyclean-compile mostlyclean-generic 439 | 440 | pdf: pdf-am 441 | 442 | pdf-am: 443 | 444 | ps: ps-am 445 | 446 | ps-am: 447 | 448 | uninstall-am: uninstall-binPROGRAMS 449 | 450 | .MAKE: install-am install-strip 451 | 452 | .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ 453 | clean-generic ctags distclean distclean-compile \ 454 | distclean-generic distclean-tags distdir dvi dvi-am html \ 455 | html-am info info-am install install-am install-binPROGRAMS \ 456 | install-data install-data-am install-dvi install-dvi-am \ 457 | install-exec install-exec-am install-html install-html-am \ 458 | install-info install-info-am install-man install-pdf \ 459 | install-pdf-am install-ps install-ps-am install-strip \ 460 | installcheck installcheck-am installdirs maintainer-clean \ 461 | maintainer-clean-generic mostlyclean mostlyclean-compile \ 462 | mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ 463 | uninstall-am uninstall-binPROGRAMS 464 | 465 | #if DEBUG 466 | #AM_CFLAGS = -g -O0 467 | #AM_CXXFLAGS = -g -O0 468 | #endif 469 | 470 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 471 | # Otherwise a system limit (for SysV at least) may be exceeded. 472 | .NOEXPORT: 473 | -------------------------------------------------------------------------------- /src/bnprec.hh: -------------------------------------------------------------------------------- 1 | #ifndef BNPREC_HH 2 | #define BNPREC_HH 3 | 4 | #include "env.hh" 5 | #include "ratings.hh" 6 | #include "gammapoisson.hh" 7 | 8 | class BNPRec { 9 | public: 10 | BNPRec(Env &env, Ratings &ratings); 11 | ~BNPRec(); 12 | 13 | void batch_infer(); 14 | void gen_ranking_for_users(); 15 | 16 | 17 | private: 18 | void initialize(); 19 | void approx_log_likelihood() const; 20 | void compute_and_write_thetas(); 21 | 22 | void initialize_sticks(); 23 | void swap_all(); 24 | void weighted_update_all(); 25 | void compute_all_expectations(); 26 | void save_model(); 27 | void load_model(); 28 | 29 | void get_phi(uint32_t n, uint32_t m, Array &phi, double &logsum) const; 30 | void save_user_state(string s, const Matrix &mat); 31 | void save_item_state(string s, const Matrix &mat); 32 | void save_state(string s, const Array &mat); 33 | 34 | void load_validation_and_test_sets(); 35 | void compute_likelihood(bool validation); 36 | void write_user_budgets(); 37 | 38 | double elogtheta(uint32_t u, uint32_t k) const; 39 | double elogtheta_at_truncation(uint32_t u) const; 40 | double elogbeta_at_truncation(uint32_t u) const; 41 | double compute_X_at_truncation(uint32_t u) const; 42 | double compute_mult_normalizer_infsum(uint32_t u) const; 43 | double compute_sum_theta_beta() const; 44 | 45 | void update_sticks(); 46 | void update_sticks_scalar(); 47 | 48 | void set_rho(); 49 | 50 | void recompute_ebetasum(); 51 | void recompute_A(); 52 | void compute_pi(); 53 | void compute_pi(uint32_t u); 54 | double B(uint32_t u, uint32_t k, double Auk); 55 | double solve_quadratic(double a, double b, double c); 56 | double sum_of_prod_in_range(uint32_t u, uint32_t K, double &lpid_at_T); 57 | double prod_at_k(uint32_t u, uint32_t k); 58 | double compute_zusers_sum(uint32_t u, uint32_t fromk); 59 | double compute_zusers_sum2(uint32_t u, uint32_t fromk); 60 | double convert_oldpi_to_new(double logpi_at_kminus1, 61 | uint32_t u, uint32_t k) const; 62 | double convert_oldpi_to_new(uint32_t u, uint32_t k) const; 63 | 64 | double compute_scalar_rate_infsum(uint32_t u) const; 65 | double compute_scalar_rate_finitesum(uint32_t u) const; 66 | double compute_scalar_rate_infsum(uint32_t u, double lpid_at_T) const; 67 | double compute_Y(uint32_t u) const; 68 | 69 | void update_items(); 70 | void recompute_ethetasum(); 71 | 72 | void clear_state(); 73 | void recompute_sums(); 74 | uint32_t duration() const; 75 | double pair_likelihood(uint32_t p, uint32_t q, yval_t y) const; 76 | void do_on_stop(); 77 | uint32_t factorial(uint32_t n) const; 78 | double link_prob(uint32_t user, uint32_t movie) const; 79 | void auc(); 80 | void compute_top_factors(); 81 | 82 | Env &_env; 83 | Ratings &_ratings; 84 | 85 | uint32_t _n; 86 | uint32_t _m; 87 | 88 | uint32_t _k; // truncation level 89 | uint32_t _iter; 90 | 91 | double _c; 92 | double _alpha; 93 | 94 | double _beta_shape_prior; 95 | double _beta_rate_prior; 96 | 97 | GPMatrixGR _beta; // \beta for all items 98 | GPArray _s; // s_u for all users 99 | Matrix _v; // variational sticks 100 | 101 | Matrix _zusers; 102 | Matrix _zitems; 103 | Array _user_budget; 104 | Array _ebetasum; 105 | Array _ethetasum; 106 | Matrix _A; 107 | Array _scalar_finite_sums; 108 | Matrix _pi; 109 | Matrix _theta; 110 | Matrix _logpi; 111 | 112 | uArray _active_k; 113 | 114 | uint32_t _start_time; 115 | gsl_rng *_r; 116 | FILE *_af; 117 | FILE *_vf; 118 | FILE *_tf; 119 | FILE *_pf; 120 | 121 | uint32_t _nh; 122 | double _prev_h; 123 | 124 | CountMap _test_map; 125 | CountMap _validation_map; 126 | 127 | double _tau0; 128 | double _rho; 129 | double _kappa; 130 | 131 | bool _save_ranking_file; 132 | UserMap _sampled_users; 133 | }; 134 | 135 | inline uint32_t 136 | BNPRec::duration() const 137 | { 138 | time_t t = time(0); 139 | return t - _start_time; 140 | } 141 | 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /src/env.hh: -------------------------------------------------------------------------------- 1 | #ifndef ENV_HH 2 | #define ENV_HH 3 | 4 | #define __STDC_FORMAT_MACROS 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "matrix.hh" 18 | #include "log.hh" 19 | 20 | typedef uint8_t yval_t; 21 | 22 | typedef D2Array AdjMatrix; 23 | typedef D2Array Matrix; 24 | typedef D3Array D3; 25 | typedef D2Array MatrixKV; 26 | typedef D1Array KVArray; 27 | 28 | typedef std::map RatingMap; 29 | typedef std::map IDMap; 30 | typedef std::map FreqMap; 31 | typedef std::map FreqStrMap; 32 | typedef std::map StrMap; 33 | typedef std::map StrMapInv; 34 | 35 | typedef D1Array *> SparseMatrix; 36 | typedef D1Array SparseMatrixR; 37 | typedef std::vector RatingList; 38 | typedef std::map UserMap; 39 | typedef std::map MovieMap; 40 | typedef std::map BoolMap; 41 | typedef std::map DoubleMap; 42 | typedef std::map ArrayMap; 43 | typedef std::map ValMap; 44 | typedef std::map > MapVec; 45 | typedef MapVec SparseMatrix2; 46 | typedef std::map SampleMap; 47 | typedef std::map CountMap; 48 | typedef std::map ValueMap; 49 | typedef std::map StrMapInv; 50 | 51 | class Env { 52 | public: 53 | typedef enum { NETFLIX, MOVIELENS, MENDELEY, ECHONEST } Dataset; 54 | typedef enum { CREATE_TRAIN_TEST_SETS, TRAINING } Mode; 55 | Env(uint32_t N, uint32_t M, uint32_t K, string fname, 56 | bool nmi, string ground_truth_fname, uint32_t rfreq, 57 | bool strid, string label, bool alogl, double rseed, 58 | uint32_t max_iterations, bool load, string loc, 59 | bool gen_hout, 60 | double av, double bv, double cv, double dv, 61 | Env::Dataset d, bool batch, bool binary_data, 62 | bool bias, bool explore, double alpha, 63 | bool vb, bool natgrad_seq_updates, double kappa, 64 | double scale); 65 | 66 | ~Env() { fclose(_plogf); } 67 | 68 | static string prefix; 69 | static Logger::Level level; 70 | 71 | Dataset dataset; 72 | uint32_t n; // users 73 | uint32_t m; // movies 74 | uint32_t k; 75 | uint32_t t; 76 | uint32_t mini_batch_size; 77 | 78 | double a; 79 | double b; 80 | double c; 81 | double d; 82 | 83 | double alpha; 84 | double tau0; 85 | double tau1; 86 | double heldout_ratio; 87 | double validation_ratio; 88 | int reportfreq; 89 | double epsilon; 90 | double logepsilon; 91 | bool nolambda; 92 | bool strid; 93 | bool logl; 94 | uint32_t max_iterations; 95 | double seed; 96 | bool save_state_now; 97 | string datfname; 98 | string label; 99 | bool nmi; 100 | string ground_truth_fname; 101 | bool model_load; 102 | string model_location; 103 | bool gen_heldout; 104 | uint32_t online_iterations; 105 | double meanchangethresh; 106 | bool batch; 107 | Mode mode; 108 | bool binary_data; 109 | bool bias; 110 | bool explore; 111 | bool vb; 112 | bool natgrad_seq_updates; 113 | double kappa; 114 | double scale; 115 | 116 | template static void plog(string s, const T &v); 117 | static string file_str(string fname); 118 | 119 | private: 120 | static FILE *_plogf; 121 | }; 122 | 123 | 124 | template inline void 125 | Env::plog(string s, const T &v) 126 | { 127 | fprintf(_plogf, "%s: %s\n", s.c_str(), v.s().c_str()); 128 | fflush(_plogf); 129 | } 130 | 131 | template<> inline void 132 | Env::plog(string s, const double &v) 133 | { 134 | fprintf(_plogf, "%s: %.9f\n", s.c_str(), v); 135 | fflush(_plogf); 136 | } 137 | 138 | template<> inline void 139 | Env::plog(string s, const string &v) 140 | { 141 | fprintf(_plogf, "%s: %s\n", s.c_str(), v.c_str()); 142 | fflush(_plogf); 143 | } 144 | 145 | template<> inline void 146 | Env::plog(string s, const bool &v) 147 | { 148 | fprintf(_plogf, "%s: %s\n", s.c_str(), v ? "True": "False"); 149 | fflush(_plogf); 150 | } 151 | 152 | template<> inline void 153 | Env::plog(string s, const int &v) 154 | { 155 | fprintf(_plogf, "%s: %d\n", s.c_str(), v); 156 | fflush(_plogf); 157 | } 158 | 159 | template<> inline void 160 | Env::plog(string s, const unsigned &v) 161 | { 162 | fprintf(_plogf, "%s: %d\n", s.c_str(), v); 163 | fflush(_plogf); 164 | } 165 | 166 | template<> inline void 167 | Env::plog(string s, const short unsigned int &v) 168 | { 169 | fprintf(_plogf, "%s: %d\n", s.c_str(), v); 170 | fflush(_plogf); 171 | } 172 | 173 | template<> inline void 174 | Env::plog(string s, const uint64_t &v) 175 | { 176 | fprintf(_plogf, "%s: %" PRIu64 "\n", s.c_str(), v); 177 | fflush(_plogf); 178 | } 179 | 180 | #ifdef __APPLE__ 181 | template<> inline void 182 | Env::plog(string s, const long unsigned int &v) 183 | { 184 | fprintf(_plogf, "%s: %lu\n", s.c_str(), v); 185 | fflush(_plogf); 186 | } 187 | #endif 188 | 189 | inline string 190 | Env::file_str(string fname) 191 | { 192 | string s = prefix + fname; 193 | return s; 194 | } 195 | 196 | inline 197 | Env::Env(uint32_t N, uint32_t M, uint32_t K, string fname, 198 | bool nmival, string gfname, uint32_t rfreq, 199 | bool sid, string lbl, bool alogl, double rseed, 200 | uint32_t maxitr, bool load, 201 | string loc, bool gen_hout, 202 | double av, double bv, double cv, double dv, 203 | Env::Dataset datasetv, bool batchv, 204 | bool binary_datav, bool biasv, bool explore, 205 | double alphav, 206 | bool vbv, bool natgrad_seq_updatesv, 207 | double kappav, double scalev) 208 | : dataset(datasetv), 209 | n(N), 210 | m(M), 211 | k(K), 212 | t(2), 213 | alpha(alphav), 214 | mini_batch_size(1000), 215 | a(av), b(bv), c(cv), d(dv), 216 | tau0(0), 217 | tau1(0), 218 | heldout_ratio(0.2), 219 | validation_ratio(0.01), 220 | reportfreq(rfreq), 221 | epsilon(0.001), 222 | logepsilon(log(epsilon)), 223 | nolambda(true), 224 | strid(sid), 225 | logl(alogl), 226 | max_iterations(maxitr), 227 | seed(rseed), 228 | save_state_now(false), 229 | datfname(fname), 230 | label(lbl), 231 | nmi(nmival), 232 | ground_truth_fname(gfname), 233 | model_load(load), 234 | model_location(loc), 235 | gen_heldout(gen_hout), 236 | online_iterations(1), 237 | meanchangethresh(0.001), 238 | batch(batchv), 239 | mode(TRAINING), 240 | binary_data(binary_datav), 241 | bias(biasv), 242 | vb(vbv), 243 | natgrad_seq_updates(natgrad_seq_updatesv), 244 | kappa(kappav), 245 | scale(scalev) 246 | { 247 | ostringstream sa; 248 | sa << "n" << n << "-"; 249 | sa << "m" << m << "-"; 250 | sa << "k" << k; 251 | if (label != "") 252 | sa << "-" << label; 253 | else if (datfname.length() > 3) { 254 | string q = datfname.substr(0,2); 255 | if (isalpha(q[0])) 256 | sa << "-" << q; 257 | } 258 | 259 | if (a != 0.3) 260 | sa << "-a" << a; 261 | 262 | if (b != 0.3) 263 | sa << "-b" << b; 264 | 265 | if (c != 0.3) 266 | sa << "-c" << c; 267 | 268 | if (d != 0.3) 269 | sa << "-d" << d; 270 | 271 | if (batch) 272 | sa << "-batch"; 273 | else 274 | sa << "-online"; 275 | 276 | if (binary_data) 277 | sa << "-bin"; 278 | 279 | sa << "-alpha" << alpha; 280 | sa << "-scale" << scale; 281 | if (vb) 282 | sa << "-vb"; 283 | else if (natgrad_seq_updates) { 284 | sa << "-ngseq"; 285 | sa << "-kappa" << kappa; 286 | } else { 287 | sa << "-ngpar"; 288 | sa << "-kappa" << kappa; 289 | } 290 | 291 | if (bias) 292 | sa << "-bias"; 293 | 294 | if (explore) 295 | sa << "-explore"; 296 | 297 | prefix = sa.str(); 298 | level = Logger::TEST; 299 | 300 | fprintf(stdout, "+ Creating directory %s\n", prefix.c_str()); 301 | fflush(stdout); 302 | 303 | assert (Logger::initialize(prefix, "infer.log", 304 | true, level) >= 0); 305 | _plogf = fopen(file_str("/param.txt").c_str(), "w"); 306 | if (!_plogf) { 307 | printf("cannot open param file:%s\n", strerror(errno)); 308 | exit(-1); 309 | } 310 | 311 | plog("n", n); 312 | plog("k", k); 313 | plog("t", t); 314 | plog("test_ratio", heldout_ratio); 315 | plog("validation_ratio", validation_ratio); 316 | plog("seed", seed); 317 | plog("alpha", alpha); 318 | plog("scale", scale); 319 | plog("reportfreq", reportfreq); 320 | plog("natgrad_seq_updates", natgrad_seq_updates); 321 | plog("vb", vb); 322 | plog("kappa", kappa); 323 | plog("tau0", tau0); 324 | 325 | //string ndatfname = file_str("/network.dat"); 326 | //unlink(ndatfname.c_str()); 327 | //assert (symlink(datfname.c_str(), ndatfname.c_str()) >= 0); 328 | //unlink(file_str("/mutual.txt").c_str()); 329 | } 330 | 331 | /* 332 | src: http://www.delorie.com/gnu/docs/glibc/libc_428.html 333 | Subtract the `struct timeval' values X and Y, 334 | storing the result in RESULT. 335 | Return 1 if the difference is negative, otherwise 0. 336 | */ 337 | inline int 338 | timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) 339 | { 340 | /* Perform the carry for the later subtraction by updating y. */ 341 | if (x->tv_usec < y->tv_usec) { 342 | int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; 343 | y->tv_usec -= 1000000 * nsec; 344 | y->tv_sec += nsec; 345 | } 346 | if (x->tv_usec - y->tv_usec > 1000000) { 347 | int nsec = (x->tv_usec - y->tv_usec) / 1000000; 348 | y->tv_usec += 1000000 * nsec; 349 | y->tv_sec -= nsec; 350 | } 351 | 352 | /* Compute the time remaining to wait. 353 | tv_usec is certainly positive. */ 354 | result->tv_sec = x->tv_sec - y->tv_sec; 355 | result->tv_usec = x->tv_usec - y->tv_usec; 356 | 357 | /* Return 1 if result is negative. */ 358 | return x->tv_sec < y->tv_sec; 359 | } 360 | 361 | inline void 362 | timeval_add (struct timeval *result, const struct timeval *x) 363 | { 364 | result->tv_sec += x->tv_sec; 365 | result->tv_usec += x->tv_usec; 366 | 367 | if (result->tv_usec >= 1000000) { 368 | result->tv_sec++; 369 | result->tv_usec -= 1000000; 370 | } 371 | } 372 | 373 | #endif 374 | -------------------------------------------------------------------------------- /src/gammapoisson.hh: -------------------------------------------------------------------------------- 1 | #ifndef GAMMAPOISSON_HH 2 | #define GAMMAPOISSON_HH 3 | 4 | // 5 | // classes for matrices or arrays of Gamma variables 6 | // 7 | 8 | template 9 | class GPBase { 10 | public: 11 | GPBase(string name = ""): _name(name) { } 12 | virtual ~GPBase() { } 13 | virtual const T &expected_v() const = 0; 14 | virtual const T &expected_logv() const = 0; 15 | virtual uint32_t n() const = 0; 16 | virtual uint32_t k() const = 0; 17 | virtual double compute_elbo_term_helper() const = 0; 18 | virtual void save(const IDMap &m) const = 0; 19 | virtual void load() = 0; 20 | void make_nonzero(double av, double bv, 21 | double &a, double &b) const; 22 | string name() const { return _name; } 23 | double compute_elbo_term() const; 24 | private: 25 | string _name; 26 | }; 27 | typedef GPBase GPM; 28 | 29 | template inline void 30 | GPBase::make_nonzero(double av, double bv, 31 | double &a, double &b) const 32 | { 33 | assert (av >= 0 && bv >= 0); 34 | if (!(bv > .0)) 35 | b = 1e-30; 36 | else 37 | b = bv; 38 | 39 | if (!(av > .0)) 40 | a = 1e-30; 41 | else 42 | a = av; 43 | } 44 | 45 | template inline double 46 | GPBase::compute_elbo_term() const 47 | { 48 | double s = compute_elbo_term_helper(); 49 | debug("sum of %s elbo terms = %f\n", name().c_str(), s); 50 | return s; 51 | } 52 | 53 | class GPMatrix : public GPBase { 54 | public: 55 | GPMatrix(string name, double a, double b, 56 | uint32_t n, uint32_t k, 57 | gsl_rng **r): 58 | GPBase(name), 59 | _n(n), _k(k), 60 | _sprior(a), // shape 61 | _rprior(b), // rate 62 | _scurr(n,k), 63 | _snext(n,k), 64 | _rnext(n,k), 65 | _rcurr(n,k), 66 | _Ev(n,k), 67 | _Elogv(n,k), 68 | _r(r) { } 69 | virtual ~GPMatrix() {} 70 | 71 | uint32_t n() const { return _n;} 72 | uint32_t k() const { return _k;} 73 | 74 | 75 | const Matrix &shape_curr() const { return _scurr; } 76 | const Matrix &rate_curr() const { return _rcurr; } 77 | const Matrix &shape_next() const { return _snext; } 78 | const Matrix &rate_next() const { return _rnext; } 79 | const Matrix &expected_v() const { return _Ev; } 80 | const Matrix &expected_logv() const { return _Elogv; } 81 | 82 | Matrix &shape_curr() { return _scurr; } 83 | Matrix &rate_curr() { return _rcurr; } 84 | Matrix &shape_next() { return _snext; } 85 | Matrix &rate_next() { return _rnext; } 86 | Matrix &expected_v() { return _Ev; } 87 | Matrix &expected_logv() { return _Elogv; } 88 | 89 | const double sprior() const { return _sprior; } 90 | const double rprior() const { return _rprior; } 91 | 92 | void set_to_prior(); 93 | void update_shape_next(uint32_t n, const Array &sphi); 94 | void update_rate_next(const Array &u, const Array &scale); 95 | void update_rate_next(const Array &u); 96 | 97 | void swap(); 98 | void weighted_update(double rho); 99 | void compute_expectations(); 100 | void sum_rows(Array &v); 101 | void scaled_sum_rows(Array &v, const Array &scale); 102 | void initialize(); 103 | 104 | void save(const IDMap &m) const; 105 | void load(); 106 | 107 | double compute_elbo_term_helper() const; 108 | 109 | private: 110 | uint32_t _n; 111 | uint32_t _k; 112 | gsl_rng **_r; 113 | double _sprior; 114 | double _rprior; 115 | 116 | Matrix _scurr; // current variational shape posterior 117 | Matrix _snext; // to help compute gradient update 118 | Matrix _rcurr; // current variational rate posterior (global) 119 | Matrix _rnext; // help compute gradient update 120 | Matrix _Ev; // expected weights under variational 121 | // distribution 122 | Matrix _Elogv; // expected log weights 123 | }; 124 | 125 | inline void 126 | GPMatrix::set_to_prior() 127 | { 128 | _snext.set_elements(_sprior); 129 | _rnext.set_elements(_rprior); 130 | } 131 | 132 | inline void 133 | GPMatrix::update_shape_next(uint32_t n, const Array &sphi) 134 | { 135 | _snext.add_slice(n, sphi); 136 | //printf("snext = %s\n", _snext.s().c_str()); 137 | } 138 | 139 | inline void 140 | GPMatrix::update_rate_next(const Array &u, const Array &scale) 141 | { 142 | Array t(_k); 143 | for (uint32_t i = 0; i < _n; ++i) { 144 | for (uint32_t k = 0; k < _k; ++k) 145 | t[k] = u[k] * scale[i]; 146 | _rnext.add_slice(i, t); 147 | } 148 | } 149 | 150 | inline void 151 | GPMatrix::update_rate_next(const Array &u) 152 | { 153 | for (uint32_t i = 0; i < _n; ++i) 154 | _rnext.add_slice(i, u); 155 | } 156 | 157 | inline void 158 | GPMatrix::swap() 159 | { 160 | _scurr.swap(_snext); 161 | _rcurr.swap(_rnext); 162 | set_to_prior(); 163 | } 164 | 165 | inline void 166 | GPMatrix::weighted_update(double rho) 167 | { 168 | if (rho == 1) { 169 | swap(); 170 | return; 171 | } 172 | double **scurrd = _scurr.data(); 173 | double **rcurrd = _rcurr.data(); 174 | double **snextd = _snext.data(); 175 | double **rnextd = _rnext.data(); 176 | for (uint32_t i = 0; i < _n; ++i) 177 | for (uint32_t k = 0; k < _k; ++k) { 178 | scurrd[i][k] = (1 - rho) * scurrd[i][k] + rho * snextd[i][k]; 179 | rcurrd[i][k] = (1 - rho) * rcurrd[i][k] + rho * rnextd[i][k]; 180 | } 181 | set_to_prior(); 182 | } 183 | 184 | inline void 185 | GPMatrix::compute_expectations() 186 | { 187 | const double ** const ad = _scurr.const_data(); 188 | const double ** const bd = _rcurr.const_data(); 189 | double **vd1 = _Ev.data(); 190 | double **vd2 = _Elogv.data(); 191 | double a = .0, b = .0; 192 | for (uint32_t i = 0; i < _scurr.m(); ++i) 193 | for (uint32_t j = 0; j < _rcurr.n(); ++j) { 194 | make_nonzero(ad[i][j], bd[i][j], a, b); 195 | vd1[i][j] = a / b; 196 | vd2[i][j] = gsl_sf_psi(a) - log(b); 197 | } 198 | } 199 | 200 | inline void 201 | GPMatrix::sum_rows(Array &v) 202 | { 203 | const double **ev = _Ev.const_data(); 204 | for (uint32_t i = 0; i < _n; ++i) 205 | for (uint32_t k = 0; k < _k; ++k) 206 | v[k] += ev[i][k]; 207 | } 208 | 209 | inline void 210 | GPMatrix::scaled_sum_rows(Array &v, const Array &scale) 211 | { 212 | assert(scale.size() == n() && v.size() == k()); 213 | const double **ev = _Ev.const_data(); 214 | for (uint32_t i = 0; i < _n; ++i) 215 | for (uint32_t k = 0; k < _k; ++k) 216 | v[k] += ev[i][k] * scale[i]; 217 | } 218 | 219 | inline void 220 | GPMatrix::initialize() 221 | { 222 | double **ad = _scurr.data(); 223 | double **bd = _rcurr.data(); 224 | for (uint32_t i = 0; i < _n; ++i) 225 | for (uint32_t k = 0; k < _k; ++k) { 226 | ad[i][k] = _sprior + 0.01 * gsl_rng_uniform(*_r); 227 | bd[i][k] = _rprior + 0.1 * gsl_rng_uniform(*_r); 228 | } 229 | double **vd1 = _Ev.data(); 230 | double **vd2 = _Elogv.data(); 231 | 232 | for (uint32_t i = 0; i < _n; ++i) 233 | for (uint32_t k = 0; k < _k; ++k) { 234 | assert(bd[i][k]); 235 | vd1[i][k] = ad[i][k] / bd[i][k]; 236 | vd2[i][k] = gsl_sf_psi(ad[i][k]) - log(bd[i][k]); 237 | } 238 | set_to_prior(); 239 | } 240 | 241 | inline double 242 | GPMatrix::compute_elbo_term_helper() const 243 | { 244 | const double **etheta = _Ev.data(); 245 | const double **elogtheta = _Elogv.data(); 246 | const double ** const ad = shape_curr().const_data(); 247 | const double ** const bd = rate_curr().const_data(); 248 | 249 | double s = .0; 250 | for (uint32_t n = 0; n < _n; ++n) { 251 | for (uint32_t k = 0; k < _k; ++k) { 252 | s += _sprior * log(_rprior) + (_sprior - 1) * elogtheta[n][k]; 253 | s -= _rprior * etheta[n][k] + gsl_sf_lngamma(_sprior); 254 | } 255 | double a = .0, b = .0; 256 | for (uint32_t k = 0; k < _k; ++k) { 257 | make_nonzero(ad[n][k], bd[n][k], a, b); 258 | s -= a * log(b) + (a - 1) * elogtheta[n][k]; 259 | s += b * etheta[n][k] + gsl_sf_lngamma(a); 260 | } 261 | } 262 | return s; 263 | } 264 | 265 | inline void 266 | GPMatrix::save(const IDMap &m) const 267 | { 268 | string expv_fname = string("/") + name() + ".tsv"; 269 | string shape_fname = string("/") + name() + "_shape.tsv"; 270 | string rate_fname = string("/") + name() + "_scale.tsv"; 271 | _scurr.save(Env::file_str(shape_fname), m); 272 | _rcurr.save(Env::file_str(rate_fname), m); 273 | _Ev.save(Env::file_str(expv_fname), m); 274 | } 275 | 276 | inline void 277 | GPMatrix::load() 278 | { 279 | string shape_fname = name() + "_shape.tsv"; 280 | string rate_fname = name() + "_scale.tsv"; 281 | _scurr.load(shape_fname); 282 | _rcurr.load(rate_fname); 283 | compute_expectations(); 284 | } 285 | 286 | 287 | class GPMatrixGR : public GPBase { // global rates 288 | public: 289 | GPMatrixGR(string name, 290 | double a, double b, 291 | uint32_t n, uint32_t k, 292 | gsl_rng **r): 293 | GPBase(name), 294 | _n(n), _k(k), 295 | _sprior(a), // shape 296 | _rprior(b), // rate 297 | _scurr(n,k), 298 | _snext(n,k), 299 | _rnext(k), 300 | _rcurr(k), 301 | _Ev(n,k), 302 | _Elogv(n,k), 303 | _r(r) { } 304 | virtual ~GPMatrixGR() {} 305 | 306 | uint32_t n() const { return _n;} 307 | uint32_t k() const { return _k;} 308 | 309 | const Matrix &shape_curr() const { return _scurr; } 310 | const Array &rate_curr() const { return _rcurr; } 311 | const Matrix &shape_next() const { return _snext; } 312 | const Array &rate_next() const { return _rnext; } 313 | const Matrix &expected_v() const { return _Ev; } 314 | const Matrix &expected_logv() const { return _Elogv; } 315 | 316 | Matrix &shape_curr() { return _scurr; } 317 | Array &rate_curr() { return _rcurr; } 318 | Matrix &shape_next() { return _snext; } 319 | Array &rate_next() { return _rnext; } 320 | Matrix &expected_v() { return _Ev; } 321 | Matrix &expected_logv() { return _Elogv; } 322 | 323 | const double sprior() const { return _sprior; } 324 | const double rprior() const { return _rprior; } 325 | 326 | void set_to_prior(); 327 | void update_shape_next(const Array &phi); 328 | void update_shape_next(uint32_t n, const Array &sphi); 329 | 330 | void update_rate_next(const Array &u); 331 | void swap(); 332 | void weighted_update(double); 333 | void compute_expectations(); 334 | void sum_rows(Array &v); 335 | void scaled_sum_rows(Array &v, const Array &scale); 336 | void initialize(); 337 | double compute_elbo_term_helper() const; 338 | 339 | void save(const IDMap &m) const; 340 | void load(); 341 | 342 | private: 343 | uint32_t _n; 344 | uint32_t _k; 345 | gsl_rng **_r; 346 | 347 | double _sprior; 348 | double _rprior; 349 | Matrix _scurr; 350 | Matrix _snext; 351 | Array _rcurr; 352 | Array _rnext; 353 | Matrix _Ev; 354 | Matrix _Elogv; 355 | }; 356 | 357 | inline void 358 | GPMatrixGR::set_to_prior() 359 | { 360 | _snext.set_elements(_sprior); 361 | _rnext.set_elements(_rprior); 362 | } 363 | 364 | inline void 365 | GPMatrixGR::update_shape_next(uint32_t n, const Array &sphi) 366 | { 367 | _snext.add_slice(n, sphi); 368 | } 369 | 370 | inline void 371 | GPMatrixGR::update_rate_next(const Array &u) 372 | { 373 | _rnext += u; 374 | } 375 | 376 | inline void 377 | GPMatrixGR::swap() 378 | { 379 | _scurr.swap(_snext); 380 | _rcurr.swap(_rnext); 381 | set_to_prior(); 382 | } 383 | 384 | 385 | inline void 386 | GPMatrixGR::weighted_update(double rho) 387 | { 388 | if (rho == 1) { 389 | swap(); 390 | return; 391 | } 392 | double **scurrd = _scurr.data(); 393 | double *rcurrd = _rcurr.data(); 394 | double **snextd = _snext.data(); 395 | double *rnextd = _rnext.data(); 396 | 397 | for (uint32_t i = 0; i < _n; ++i) 398 | for (uint32_t k = 0; k < _k; ++k) 399 | scurrd[i][k] = (1 - rho) * scurrd[i][k] + rho * snextd[i][k]; 400 | 401 | for (uint32_t k = 0; k < _k; ++k) 402 | rcurrd[k] = (1 - rho) * rcurrd[k] + rho * rnextd[k]; 403 | 404 | set_to_prior(); 405 | } 406 | 407 | inline void 408 | GPMatrixGR::compute_expectations() 409 | { 410 | const double ** const ad = _scurr.const_data(); 411 | const double * const bd = _rcurr.const_data(); 412 | double **vd1 = _Ev.data(); 413 | double **vd2 = _Elogv.data(); 414 | double a = .0, b = .0; 415 | for (uint32_t i = 0; i < _n; ++i) 416 | for (uint32_t j = 0; j < _k; ++j) { 417 | make_nonzero(ad[i][j], bd[j], a, b); 418 | vd1[i][j] = a / b; 419 | vd2[i][j] = gsl_sf_psi(a) - log(b); 420 | } 421 | debug("name = %s, scurr = %s, rcurr = %s, Ev = %s\n", 422 | name().c_str(), 423 | _scurr.s().c_str(), 424 | _rcurr.s().c_str(), 425 | _Ev.s().c_str()); 426 | } 427 | 428 | inline void 429 | GPMatrixGR::sum_rows(Array &v) 430 | { 431 | double **ev = _Ev.data(); 432 | for (uint32_t i = 0; i < _n; ++i) 433 | for (uint32_t k = 0; k < _k; ++k) 434 | v[k] += ev[i][k]; 435 | } 436 | 437 | 438 | inline void 439 | GPMatrixGR::scaled_sum_rows(Array &v, const Array &scale) 440 | { 441 | assert(scale.size() == n() && v.size() == k()); 442 | const double **ev = _Ev.const_data(); 443 | for (uint32_t i = 0; i < _n; ++i) 444 | for (uint32_t k = 0; k < _k; ++k) 445 | v[k] += ev[i][k] * scale[i]; 446 | } 447 | 448 | 449 | inline void 450 | GPMatrixGR::initialize() 451 | { 452 | double **ad = _scurr.data(); 453 | double *bd = _rcurr.data(); 454 | for (uint32_t i = 0; i < _n; ++i) 455 | for (uint32_t k = 0; k < _k; ++k) { 456 | ad[i][k] = _sprior + 0.01 * gsl_rng_uniform(*_r); 457 | bd[k] = _rprior + 0.1 * gsl_rng_uniform(*_r); 458 | } 459 | double **vd1 = _Ev.data(); 460 | double **vd2 = _Elogv.data(); 461 | 462 | for (uint32_t i = 0; i < _n; ++i) 463 | for (uint32_t j = 0; j < _k; ++j) { 464 | assert(bd[j]); 465 | vd1[i][j] = ad[i][j] / bd[j]; 466 | vd2[i][j] = gsl_sf_psi(ad[i][j]) - log(bd[j]); 467 | } 468 | set_to_prior(); 469 | } 470 | 471 | inline double 472 | GPMatrixGR::compute_elbo_term_helper() const 473 | { 474 | const double **etheta = _Ev.const_data(); 475 | const double **elogtheta = _Elogv.const_data(); 476 | const double ** const ad = shape_curr().const_data(); 477 | const double * const bd = rate_curr().const_data(); 478 | 479 | double s = .0; 480 | for (uint32_t n = 0; n < _n; ++n) { 481 | for (uint32_t k = 0; k < _k; ++k) { 482 | s += _sprior * log(_rprior) + (_sprior - 1) * elogtheta[n][k]; 483 | s -= _rprior * etheta[n][k] + gsl_sf_lngamma(_sprior); 484 | debug("ehelper: %f:%f:%f log:%f\n", s, etheta[n][k], gsl_sf_lngamma(_sprior), elogtheta[n][k]); 485 | } 486 | double a = .0, b = .0; 487 | for (uint32_t k = 0; k < _k; ++k) { 488 | make_nonzero(ad[n][k], bd[k], a, b); 489 | s -= a * log(b) + (a - 1) * elogtheta[n][k]; 490 | s += b * etheta[n][k] + gsl_sf_lngamma(a); 491 | } 492 | } 493 | return s; 494 | } 495 | 496 | inline void 497 | GPMatrixGR::save(const IDMap &m) const 498 | { 499 | string expv_fname = string("/") + name() + ".tsv"; 500 | string shape_fname = string("/") + name() + "_shape.tsv"; 501 | string rate_fname = string("/") + name() + "_scale.tsv"; 502 | _scurr.save(Env::file_str(shape_fname), m); 503 | _rcurr.save(Env::file_str(rate_fname), m); 504 | _Ev.save(Env::file_str(expv_fname), m); 505 | } 506 | 507 | inline void 508 | GPMatrixGR::load() 509 | { 510 | string shape_fname = name() + "_shape.tsv"; 511 | string rate_fname = name() + "_scale.tsv"; 512 | _scurr.load(shape_fname); 513 | _rcurr.load(rate_fname); 514 | compute_expectations(); 515 | } 516 | 517 | class GPArray : public GPBase { 518 | public: 519 | GPArray(string name, 520 | double a, double b, 521 | uint32_t n, gsl_rng **r): 522 | GPBase(name), 523 | _n(n), 524 | _sprior(a), // shape 525 | _rprior(b), // rate 526 | _scurr(n), _snext(n), 527 | _rnext(n), _rcurr(n), 528 | _Ev(n), _Elogv(n), 529 | _r(r) { } 530 | ~GPArray() {} 531 | 532 | uint32_t n() const { return _n;} 533 | uint32_t k() const { return 0;} 534 | 535 | const Array &shape_curr() const { return _scurr; } 536 | const Array &rate_curr() const { return _rcurr; } 537 | const Array &shape_next() const { return _snext; } 538 | const Array &rate_next() const { return _rnext; } 539 | const Array &expected_v() const { return _Ev; } 540 | const Array &expected_logv() const { return _Elogv; } 541 | 542 | Array &shape_curr() { return _scurr; } 543 | Array &rate_curr() { return _rcurr; } 544 | Array &shape_next() { return _snext; } 545 | Array &rate_next() { return _rnext; } 546 | Array &expected_v() { return _Ev; } 547 | Array &expected_logv() { return _Elogv; } 548 | 549 | const double sprior() const { return _sprior; } 550 | const double rprior() const { return _rprior; } 551 | 552 | uint32_t n() { return _n; } 553 | 554 | void set_to_prior(); 555 | void update_shape_next(const Array &phi); 556 | void update_shape_next(uint32_t n, double v); 557 | void update_rate_next(const Array &v); 558 | void update_rate_next(uint32_t n, double v); 559 | void swap(); 560 | void weighted_update(double); 561 | void compute_expectations(); 562 | void initialize(); 563 | 564 | double compute_elbo_term_helper() const; 565 | 566 | void save(const IDMap &m) const; 567 | void load(); 568 | 569 | private: 570 | uint32_t _n; 571 | double _sprior; 572 | double _rprior; 573 | Array _scurr; // current variational shape posterior 574 | Array _snext; // to help compute gradient update 575 | Array _rcurr; // current variational rate posterior (global) 576 | Array _rnext; // help compute gradient update 577 | Array _Ev; // expected weights under variational 578 | // distribution 579 | Array _Elogv; // expected log weights 580 | gsl_rng **_r; 581 | }; 582 | 583 | inline void 584 | GPArray::set_to_prior() 585 | { 586 | _snext.set_elements(_sprior); 587 | _rnext.set_elements(_rprior); 588 | } 589 | 590 | inline void 591 | GPArray::update_shape_next(const Array &sphi) 592 | { 593 | assert (sphi.size() == _n); 594 | _snext += sphi; 595 | } 596 | 597 | inline void 598 | GPArray::update_shape_next(uint32_t n, double v) 599 | { 600 | _snext[n] += v; 601 | } 602 | 603 | inline void 604 | GPArray::update_rate_next(const Array &v) 605 | { 606 | assert (v.size() == _n); 607 | _rnext += v; 608 | } 609 | 610 | inline void 611 | GPArray::update_rate_next(uint32_t n, double v) 612 | { 613 | _rnext[n] += v; 614 | } 615 | 616 | inline void 617 | GPArray::swap() 618 | { 619 | _scurr.swap(_snext); 620 | _rcurr.swap(_rnext); 621 | set_to_prior(); 622 | } 623 | 624 | inline void 625 | GPArray::weighted_update(double rho) 626 | { 627 | if (rho == 1) { 628 | swap(); 629 | return; 630 | } 631 | double *scurrd = _scurr.data(); 632 | double *rcurrd = _rcurr.data(); 633 | double *snextd = _snext.data(); 634 | double *rnextd = _rnext.data(); 635 | 636 | for (uint32_t i = 0; i < _n; ++i) { 637 | scurrd[i] = (1 - rho) * scurrd[i] + rho * snextd[i]; 638 | rcurrd[i] = (1 - rho) * rcurrd[i] + rho * rnextd[i]; 639 | } 640 | set_to_prior(); 641 | } 642 | 643 | inline void 644 | GPArray::compute_expectations() 645 | { 646 | const double * const ad = _scurr.const_data(); 647 | const double * const bd = _rcurr.const_data(); 648 | double *vd1 = _Ev.data(); 649 | double *vd2 = _Elogv.data(); 650 | double a = .0, b = .0; 651 | for (uint32_t i = 0; i < _n; ++i) { 652 | make_nonzero(ad[i], bd[i], a, b); 653 | vd1[i] = a / b; 654 | vd2[i] = gsl_sf_psi(a) - log(b); 655 | } 656 | } 657 | 658 | inline void 659 | GPArray::initialize() 660 | { 661 | double *ad = _scurr.data(); 662 | double *bd = _rcurr.data(); 663 | for (uint32_t i = 0; i < _n; ++i) { 664 | ad[i] = _sprior + 0.01 * gsl_rng_uniform(*_r); 665 | bd[i] = _rprior + 0.1 * gsl_rng_uniform(*_r); 666 | } 667 | 668 | double *vd1 = _Ev.data(); 669 | double *vd2 = _Elogv.data(); 670 | 671 | double v = _rprior + _n; 672 | for (uint32_t i = 0; i < _n; ++i) { 673 | vd1[i] = ad[i] / v; 674 | vd2[i] = gsl_sf_psi(ad[i]) - log(v); 675 | } 676 | set_to_prior(); 677 | } 678 | 679 | inline double 680 | GPArray::compute_elbo_term_helper() const 681 | { 682 | const double *etheta = _Ev.const_data(); 683 | const double *elogtheta = _Elogv.const_data(); 684 | const double * const ad = shape_curr().const_data(); 685 | const double * const bd = rate_curr().const_data(); 686 | 687 | double s = .0; 688 | double a = .0, b = .0; 689 | for (uint32_t n = 0; n < _n; ++n) { 690 | make_nonzero(ad[n], bd[n], a, b); 691 | s += _sprior * log(_rprior) + (_sprior - 1) * elogtheta[n]; 692 | s -= _rprior * etheta[n] + gsl_sf_lngamma(_sprior); 693 | s -= a * log(b) + (a - 1) * elogtheta[n]; 694 | s += b * etheta[n] + gsl_sf_lngamma(a); 695 | } 696 | return s; 697 | } 698 | 699 | inline void 700 | GPArray::save(const IDMap &m) const 701 | { 702 | string expv_fname = string("/") + name() + ".tsv"; 703 | string shape_fname = string("/") + name() + "_shape.tsv"; 704 | string rate_fname = string("/") + name() + "_scale.tsv"; 705 | _scurr.save(Env::file_str(shape_fname), m); 706 | _rcurr.save(Env::file_str(rate_fname), m); 707 | _Ev.save(Env::file_str(expv_fname), m); 708 | } 709 | 710 | inline void 711 | GPArray::load() 712 | { 713 | string shape_fname = name() + "_shape.tsv"; 714 | string rate_fname = name() + "_scale.tsv"; 715 | _scurr.load(shape_fname); 716 | _rcurr.load(rate_fname); 717 | compute_expectations(); 718 | } 719 | 720 | #endif 721 | -------------------------------------------------------------------------------- /src/gaprec.hh: -------------------------------------------------------------------------------- 1 | #ifndef GAPREC_HH 2 | #define GAPREC_HH 3 | 4 | #include "env.hh" 5 | #include "ratings.hh" 6 | 7 | class GAPRec { 8 | public: 9 | GAPRec(Env &env, Ratings &ratings); 10 | ~GAPRec(); 11 | 12 | void batch_infer(); 13 | void batch_infer_bias(); 14 | void infer(); 15 | void analyze(); 16 | void analyze_factors(); 17 | void gen_ranking_for_users(); 18 | 19 | 20 | private: 21 | void initialize(); 22 | void set_to_prior_users(Matrix &a, Array &b); 23 | void set_to_prior_movies(Matrix &a, Array &b); 24 | 25 | void initialize_bias(); 26 | void set_to_prior_biases(); 27 | void update_global_state_bias(); 28 | void set_gamma_exp_bias(const Array &u, double v, Array &w1, Array &w2); 29 | double link_prob_bias(uint32_t user, uint32_t movie) const; 30 | double pair_likelihood_bias(uint32_t p, uint32_t q, yval_t y) const; 31 | 32 | 33 | void save_model(); 34 | void write_movie_list(string label, uint32_t u, const vector &movies); 35 | void write_movie_list(string label, const vector &movies); 36 | 37 | void save_user_state(string s, const Matrix &mat); 38 | void save_item_state(string s, const Matrix &mat); 39 | void save_state(string s, const Array &mat); 40 | void do_on_stop(); 41 | 42 | void load_file(string s, Matrix &mat); 43 | void load_beta_and_theta(); 44 | void load_file(string s, Array &mat); 45 | 46 | 47 | void set_etheta_sum(); 48 | void set_ebeta_sum(); 49 | void set_etheta_sum2(); 50 | void set_ebeta_sum2(); 51 | void load_validation_and_test_sets(); 52 | 53 | void set_gamma_exp(const Matrix &a, const Array &b, Matrix &v1, Matrix &v2); 54 | void set_gamma_exp_init(const Matrix &a, Matrix &v1, Matrix &v2, double v); 55 | void set_gamma_exp1(const Matrix &a, const Array &b, Matrix &v); 56 | void set_gamma_exp2(const Matrix &a, const Array &b, Matrix &v); 57 | void set_gamma_exp1_idx(uint32_t u, 58 | const Matrix &a, const Matrix &b, Matrix &v); 59 | void set_gamma_exp2_idx(uint32_t u, 60 | const Matrix &a, const Matrix &b, Matrix &v); 61 | 62 | void set_gamma_exp2_array(uint32_t u, 63 | const Matrix &a, const Array &b, Matrix &v); 64 | void set_gamma_exp1_array(uint32_t u, 65 | const Matrix &a, const Array &b, Matrix &v); 66 | 67 | void recompute_etheta_sum(const UserMap &sampled_users, 68 | const Array ðeta_sum_old); 69 | 70 | void compute_etheta_sum(const UserMap &sampled_users); 71 | void compute_ebeta_sum(const MovieMap &sampled_movies); 72 | void adjust_etheta_sum(const UserMap &sampled_users); 73 | void adjust_ebeta_sum(const MovieMap &sampled_movies); 74 | 75 | 76 | void optimize_user_rate_parameters(uint32_t n); 77 | void optimize_user_shape_parameters_helper(uint32_t n, 78 | Matrix &cphi); 79 | void optimize_user_shape_parameters(uint32_t n); 80 | void optimize_user_shape_parameters2(uint32_t n); 81 | 82 | 83 | void approx_log_likelihood(); 84 | void auc(bool bias = false); 85 | double link_prob(uint32_t user, uint32_t movie) const; 86 | 87 | void update_global_state(); 88 | double pair_likelihood(uint32_t p, uint32_t q, yval_t y) const; 89 | double pair_likelihood_binary(uint32_t p, uint32_t q, yval_t y) const; 90 | void test_likelihood(); 91 | void compute_likelihood(bool bias, bool validation); 92 | uint32_t factorial(uint32_t n) const; 93 | 94 | void init_heldout(); 95 | void set_test_sample(int s); 96 | void set_training_sample(); 97 | void set_validation_sample(int s); 98 | void get_random_rating1(Rating &r) const; 99 | void get_random_rating2(Rating &r) const; 100 | void get_random_rating3(Rating &r) const; 101 | uint32_t duration() const; 102 | bool rating_ok(const Rating &e) const; 103 | bool is_test_rating(const Rating &e) const; 104 | void write_sample(FILE *, SampleMap &m); 105 | void write_sample(FILE *, CountMap &m); 106 | void write_ebeta(uint32_t); 107 | void write_etheta(uint32_t); 108 | 109 | Env &_env; 110 | Ratings &_ratings; 111 | 112 | uint32_t _n; 113 | uint32_t _m; 114 | uint32_t _k; 115 | uint32_t _iter; 116 | 117 | double _a; 118 | double _b; 119 | double _c; 120 | double _d; 121 | 122 | time_t _start_time; 123 | 124 | Matrix _acurr; 125 | Array _bcurr; 126 | Matrix _ccurr; 127 | Array _dcurr; 128 | Matrix _anext; 129 | Array _bnext; 130 | Matrix _cnext; 131 | Array _dnext; 132 | Array _phi; 133 | 134 | Array _ucurr; 135 | Array _icurr; 136 | Array _unext; 137 | Array _inext; 138 | Array _Elogu; 139 | Array _Eu; 140 | Array _Elogi; 141 | Array _Ei; 142 | 143 | Matrix _Elogtheta; 144 | Matrix _Etheta; 145 | Matrix _Elogbeta; 146 | Matrix _Ebeta; 147 | 148 | gsl_rng *_r; 149 | FILE *_hf; 150 | FILE *_vf; 151 | FILE *_tf; 152 | FILE *_af; 153 | FILE *_pf; 154 | 155 | CountMap _test_map; 156 | RatingList _test_ratings; 157 | CountMap _validation_map; 158 | RatingList _validation_ratings; 159 | UserMap _sampled_users; 160 | UserMap _sampled_movies; 161 | 162 | Array _etheta_sum; 163 | Array _ebeta_sum; 164 | Array _etheta_sum_old; 165 | Array _ebeta_sum_old; 166 | double _tau0; 167 | double _kappa; 168 | Array _rho; 169 | 170 | uint32_t _nh; 171 | double _prev_h; 172 | bool _save_ranking_file; 173 | uArray _itemc; 174 | bool _use_rate_as_score; 175 | uint32_t _topN_by_user; 176 | }; 177 | 178 | inline uint32_t 179 | GAPRec::duration() const 180 | { 181 | time_t t = time(0); 182 | return t - _start_time; 183 | } 184 | 185 | inline bool 186 | GAPRec::rating_ok(const Rating &r) const 187 | { 188 | assert (r.first < _n && r.second < _m); 189 | const CountMap::const_iterator u = _test_map.find(r); 190 | if (u != _test_map.end()) 191 | return false; 192 | const CountMap::const_iterator w = _validation_map.find(r); 193 | if (w != _validation_map.end()) 194 | return false; 195 | return true; 196 | } 197 | 198 | inline bool 199 | GAPRec::is_test_rating(const Rating &r) const 200 | { 201 | assert (r.first < _n && r.second < _m); 202 | const CountMap::const_iterator u = _test_map.find(r); 203 | if (u != _test_map.end()) 204 | return true; 205 | return false; 206 | } 207 | 208 | 209 | 210 | #endif 211 | -------------------------------------------------------------------------------- /src/log.cc: -------------------------------------------------------------------------------- 1 | #include "log.hh" 2 | 3 | string Logger::_log_fname = "mmsb.log"; 4 | string Logger::_prefix = ""; 5 | FILE *Logger::_logfd = 0; 6 | bool Logger::_initialized = false; 7 | Logger::Level Logger::_level = DEBUG; 8 | 9 | int 10 | Logger::initialize(string prefix, string name, bool force, 11 | Level level) 12 | { 13 | if (!_initialized) { 14 | _prefix = prefix; 15 | _log_fname = name; 16 | _level = level; 17 | if (setup_logfd(force) < 0) 18 | return -1; 19 | 20 | _initialized = true; 21 | info("Setting log to %s", name.c_str()); 22 | } 23 | return 0; 24 | } 25 | 26 | int 27 | Logger::xlog(Level level, const char *format, ...) 28 | { 29 | if (!_initialized) { 30 | initialize(_prefix, string("/mmsb.log"), false); 31 | } 32 | if (level < _level) 33 | return 0; 34 | 35 | assert(_logfd); 36 | va_list ap; 37 | va_start (ap, format); 38 | string ts = get_time(); 39 | string l = get_level_str(level); 40 | fprintf(_logfd, "[%s] [%d] [%3s] ", ts.c_str(), getpid(), l.c_str()); 41 | vfprintf(_logfd, format, ap); 42 | fprintf(_logfd, "\n\n"); 43 | fflush(_logfd); 44 | va_end(ap); 45 | return 0; 46 | } 47 | 48 | string 49 | Logger::get_time() 50 | { 51 | time_t now = time(0); 52 | struct tm p; 53 | localtime_r(&now, &p); 54 | char buf[512]; 55 | strftime(buf, 512, "%b %e %T", &p); 56 | return string(buf); 57 | } 58 | 59 | string 60 | Logger::get_level_str(Level level) 61 | { 62 | string s; 63 | switch (level) { 64 | case INFO: s = "INF"; break; 65 | case DEBUG: s = "DBG"; break; 66 | case WARN: s = "WRN"; break; 67 | case ERROR: s = "ERR"; break; 68 | case FATAL: s = "FTL"; break; 69 | case TEST: s = "TST"; break; 70 | default: 71 | s = "unknown"; 72 | } 73 | return s; 74 | } 75 | 76 | int 77 | Logger::setup_logfd(bool force) 78 | { 79 | if (setup_log_dir(force) < 0) 80 | return -1; 81 | 82 | if (_logfd) { 83 | fclose(_logfd); 84 | _logfd = 0; 85 | } 86 | string fn = log_fname(); 87 | _logfd = fopen(fn.c_str(), "w"); 88 | if (_logfd) 89 | fprintf(stderr, "+ writing log to %s\n", fn.c_str()); 90 | if (!_logfd) { 91 | _logfd = fopen("/dev/null", "w"); 92 | fprintf(stderr, "+ writing log to /dev/null\n"); 93 | } 94 | return 0; 95 | } 96 | 97 | int 98 | Logger::setup_log_dir(bool force) 99 | { 100 | struct stat dirstat; 101 | if (stat(dirname().c_str(), &dirstat) != 0) { 102 | if (errno == ENOENT) { 103 | mkdir(dirname().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 104 | if (stat(dirname().c_str(), &dirstat) != 0) { 105 | fprintf(stderr, "Warning: could not create dir %s\n", 106 | dirname().c_str()); 107 | return -1; 108 | } 109 | } else { 110 | fprintf(stderr, "Warning: could not stat dir %s\n", dirname().c_str()); 111 | return -1; 112 | } 113 | } else if (!force) { 114 | fprintf(stderr, "Error: dir %s already exists\n", dirname().c_str()); 115 | return -1; 116 | } 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /src/log.hh: -------------------------------------------------------------------------------- 1 | #ifndef LOG_HH 2 | #define LOG_HH 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | using namespace std; 17 | 18 | //#define DEBUG_MODE 1 19 | 20 | #define PREFIX "log" 21 | 22 | class Logger { 23 | public: 24 | typedef enum { DEBUG = 0, TEST, INFO, WARN, ERROR, FATAL } Level; 25 | static int xlog(Level l, const char *format, ...); 26 | static int initialize(string prefix, string name, 27 | bool force_overwrite_dir, 28 | Level level = DEBUG); 29 | static string log_fname() { return dirname() + string("/") + _log_fname; } 30 | static string dirname() { return _prefix; } 31 | 32 | private: 33 | static int setup_log_dir(bool force); 34 | static int setup_logfd(bool force); 35 | static string get_time(); 36 | static string get_level_str(Level level); 37 | 38 | static FILE *_logfd; 39 | static string _log_fname; 40 | static bool _initialized; 41 | static string _prefix; 42 | static Level _level; 43 | }; 44 | 45 | 46 | #ifndef DEBUG_MODE 47 | #define debug(X, ...) 48 | #define info(X, ...) 49 | #define tst(X, ...) 50 | #define lerr(format, ...) Logger::xlog(Logger::ERROR, format, ## __VA_ARGS__) 51 | #else 52 | #define tst(format, ...) Logger::xlog(Logger::TEST, format, ## __VA_ARGS__) 53 | #define debug(format, ...) Logger::xlog(Logger::DEBUG, format, ## __VA_ARGS__) 54 | #define info(format, ...) Logger::xlog(Logger::INFO, format, ## __VA_ARGS__) 55 | #define lerr(format, ...) Logger::xlog(Logger::ERROR, format, ## __VA_ARGS__) 56 | #endif 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/main.cc: -------------------------------------------------------------------------------- 1 | #include "env.hh" 2 | #include "gaprec.hh" 3 | #include "bnprec.hh" 4 | #include "ratings.hh" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | string Env::prefix = ""; 12 | Logger::Level Env::level = Logger::DEBUG; 13 | FILE *Env::_plogf = NULL; 14 | void usage(); 15 | void test(); 16 | 17 | void postprocess(Env &); 18 | 19 | Env *env_global = NULL; 20 | volatile sig_atomic_t sig_handler_active = 0; 21 | 22 | void 23 | term_handler(int sig) 24 | { 25 | if (env_global) { 26 | printf("Got signal. Saving model state.\n"); 27 | fflush(stdout); 28 | env_global->save_state_now = 1; 29 | } else { 30 | signal(sig, SIG_DFL); 31 | raise(sig); 32 | } 33 | } 34 | 35 | int 36 | main(int argc, char **argv) 37 | { 38 | signal(SIGTERM, term_handler); 39 | if (argc <= 1) { 40 | printf("gaprec -dir -n " \ 41 | "-m -k -label \n"); 42 | exit(0); 43 | } 44 | 45 | string fname; 46 | uint32_t n = 0, m = 0; 47 | uint32_t k = 200; 48 | string ground_truth_fname; 49 | uint32_t rfreq = 1; 50 | string label; 51 | bool logl = false; 52 | uint32_t max_iterations = 1000; 53 | bool nmi = false; 54 | bool strid = false; 55 | double rand_seed = 0; 56 | 57 | bool test = false; 58 | bool batch = true; 59 | bool online = false; 60 | bool gen_heldout = false; 61 | 62 | bool model_load = false; 63 | string model_location = ""; 64 | 65 | bool hol_load = false; 66 | string hol_location = ""; 67 | 68 | bool pred_accuracy = false; 69 | bool gt_accuracy = false; 70 | bool p = false; 71 | double a = 0.3, b = 0.3, c = 0.3, d = 0.3; 72 | Env::Dataset dataset = Env::MENDELEY; 73 | bool binary_data = false; 74 | bool bias = false; 75 | bool explore = false; 76 | bool gen_ranking_for_users = false; 77 | double alpha = 1.1; 78 | double scale = 1; 79 | double kappa = 0.5; 80 | 81 | bool vb = true; 82 | bool natgrad_seq_updates = false; 83 | 84 | uint32_t i = 0; 85 | while (i <= argc - 1) { 86 | if (strcmp(argv[i], "-dir") == 0) { 87 | fname = string(argv[++i]); 88 | fprintf(stdout, "+ dir = %s\n", fname.c_str()); 89 | } else if (strcmp(argv[i], "-n") == 0) { 90 | n = atoi(argv[++i]); 91 | fprintf(stdout, "+ n = %d\n", n); 92 | } else if (strcmp(argv[i], "-p") == 0) { 93 | p = true; 94 | } else if (strcmp(argv[i], "-m") == 0) { 95 | m = atoi(argv[++i]); 96 | fprintf(stdout, "+ m = %d\n", m); 97 | } else if (strcmp(argv[i], "-T") == 0) { 98 | k = atoi(argv[++i]); 99 | fprintf(stdout, "+ k = %d\n", k); 100 | } else if (strcmp(argv[i], "-nmi") == 0) { 101 | ground_truth_fname = string(argv[++i]); 102 | fprintf(stdout, "+ ground truth fname = %s\n", 103 | ground_truth_fname.c_str()); 104 | nmi = true; 105 | } else if (strcmp(argv[i], "-rfreq") == 0) { 106 | rfreq = atoi(argv[++i]); 107 | fprintf(stdout, "+ rfreq = %d\n", rfreq); 108 | } else if (strcmp(argv[i], "-strid") == 0) { 109 | strid = true; 110 | fprintf(stdout, "+ strid mode\n"); 111 | } else if (strcmp(argv[i], "-label") == 0) { 112 | label = string(argv[++i]); 113 | } else if (strcmp(argv[i], "-logl") == 0) { 114 | logl = true; 115 | fprintf(stdout, "+ logl mode\n"); 116 | } else if (strcmp(argv[i], "-max-iterations") == 0) { 117 | max_iterations = atoi(argv[++i]); 118 | fprintf(stdout, "+ max iterations %d\n", max_iterations); 119 | } else if (strcmp(argv[i], "-seed") == 0) { 120 | rand_seed = atof(argv[++i]); 121 | fprintf(stdout, "+ random seed set to %.5f\n", rand_seed); 122 | } else if (strcmp(argv[i], "-load") == 0) { 123 | model_load = true; 124 | model_location = string(argv[++i]); 125 | fprintf(stdout, "+ loading theta from %s\n", model_location.c_str()); 126 | } else if (strcmp(argv[i], "-test") == 0) { 127 | test = true; 128 | fprintf(stdout, "+ test mode\n"); 129 | } else if (strcmp(argv[i], "-batch") == 0) { 130 | batch = true; 131 | fprintf(stdout, "+ batch inference\n"); 132 | } else if (strcmp(argv[i], "-online") == 0) { 133 | batch = false; 134 | fprintf(stdout, "+ online inference\n"); 135 | } else if (strcmp(argv[i], "-gen-heldout") == 0) { 136 | gen_heldout = true; 137 | fprintf(stdout, "+ generate held-out files from dataset\n"); 138 | } else if (strcmp(argv[i], "-pred-accuracy") == 0) { 139 | pred_accuracy = true; 140 | fprintf(stdout, "+ compute predictive accuracy\n"); 141 | } else if (strcmp(argv[i], "-gt-accuracy") == 0) { 142 | gt_accuracy = true; 143 | fprintf(stdout, "+ compute accuracy to ground truth\n"); 144 | } else if (strcmp(argv[i], "-netflix") == 0) { 145 | dataset = Env::NETFLIX; 146 | } else if (strcmp(argv[i], "-mendeley") == 0) { 147 | dataset = Env::MENDELEY; 148 | } else if (strcmp(argv[i], "-movielens") == 0) { 149 | dataset = Env::MOVIELENS; 150 | } else if (strcmp(argv[i], "-echonest") == 0) { 151 | dataset = Env::ECHONEST; 152 | } else if (strcmp(argv[i], "-a") == 0) { 153 | a = atof(argv[++i]); 154 | } else if (strcmp(argv[i], "-b") == 0) { 155 | b = atof(argv[++i]); 156 | } else if (strcmp(argv[i], "-c") == 0) { 157 | c = atof(argv[++i]); 158 | } else if (strcmp(argv[i], "-d") == 0) { 159 | d = atof(argv[++i]); 160 | } else if (strcmp(argv[i], "-binary-data") == 0) { 161 | binary_data = true; 162 | } else if (strcmp(argv[i], "-bias") == 0) { 163 | bias = true; 164 | } else if (strcmp(argv[i], "-explore") == 0) { 165 | explore = true; 166 | } else if (strcmp(argv[i], "-gen-ranking") == 0) { 167 | gen_ranking_for_users = true; 168 | } else if (strcmp(argv[i], "-alpha") == 0) { 169 | alpha = atof(argv[++i]); 170 | } else if (strcmp(argv[i], "-C") == 0) { 171 | scale = atof(argv[++i]); 172 | } else if (strcmp(argv[i], "-natgrad-par") == 0) { 173 | vb = false; 174 | natgrad_seq_updates = false; 175 | } else if (strcmp(argv[i], "-natgrad-seq") == 0) { 176 | natgrad_seq_updates = true; 177 | vb = false; 178 | } else if (strcmp(argv[i], "-kappa") == 0) { 179 | kappa = atof(argv[++i]); 180 | } else if (i > 0) { 181 | fprintf(stdout, "error: unknown option %s\n", argv[i]); 182 | assert(0); 183 | } 184 | ++i; 185 | }; 186 | 187 | Env env(n, m, k, fname, nmi, ground_truth_fname, rfreq, 188 | strid, label, logl, rand_seed, max_iterations, 189 | model_load, model_location, 190 | gen_heldout, a, b, c, d, dataset, 191 | batch, binary_data, bias, explore, alpha, 192 | vb, natgrad_seq_updates, kappa, scale); 193 | env_global = &env; 194 | if (p) { 195 | postprocess(env); 196 | exit(0); 197 | } 198 | Ratings ratings(env); 199 | if (ratings.read(fname.c_str()) < 0) { 200 | fprintf(stderr, "error reading dataset from dir %s; quitting\n", 201 | fname.c_str()); 202 | return -1; 203 | } 204 | 205 | if (gen_ranking_for_users) { 206 | BNPRec bnprec(env, ratings); 207 | bnprec.gen_ranking_for_users(); 208 | exit(0); 209 | } 210 | BNPRec bnprec(env, ratings); 211 | bnprec.batch_infer(); 212 | exit(0); 213 | } 214 | 215 | 216 | void 217 | postprocess(Env &env) 218 | { 219 | typedef D1Array KVArray; 220 | typedef std::map MapList; 221 | 222 | FILE *f = fopen("ranking.txt", "r"); 223 | if (!f) { 224 | fprintf(stderr, "error: cannot open file ranking.txt for post-processing %s", strerror(errno)); 225 | fclose(f); 226 | exit(-1); 227 | } 228 | printf("env.n = %d\n", env.n); 229 | AdjMatrix y(env.n+1, env.m+1); 230 | yval_t **yd = y.data(); 231 | MapList byuser, byitem; 232 | while (!feof(f)) { 233 | uint32_t user, item, actual; 234 | float pred; 235 | if (fscanf(f, "%u\t%u\t%f\t%u", &user, &item, &pred, &actual) < 0) 236 | break; 237 | 238 | //printf("env.m = %d, item = %d\n", env.m, item); 239 | //fflush(stdout); 240 | 241 | assert(item <= env.m); 242 | 243 | MapList::iterator i = byuser.find(user); 244 | if (i == byuser.end()) { 245 | KVArray *m = new KVArray(env.m+1); 246 | (*m)[item].first = item; 247 | (*m)[item].second = pred; 248 | byuser[user] = m; 249 | } else { 250 | KVArray *m = i->second; 251 | (*m)[item].first = item; 252 | (*m)[item].second = pred; 253 | } 254 | yd[user][item] = actual; 255 | } 256 | fclose(f); 257 | printf("+ reading done\n"); 258 | fflush(stdout); 259 | 260 | double mhits10 = 0, mhits100 = 0, mhits1000 = 0; 261 | for (MapList::const_iterator i = byuser.begin(); i != byuser.end(); ++i) { 262 | uint32_t user = i->first; 263 | KVArray *m = i->second; 264 | m->sort_by_value(); 265 | 266 | uint32_t hits10 = 0, hits100 = 0, hits1000 = 0; 267 | uint32_t c = 0; 268 | for (uint32_t j = 0; j < m->size(); ++j) { 269 | KV &kv = (*m)[j]; 270 | uint32_t item = kv.first; 271 | double pred = kv.second; 272 | if (yd[user][item] > 0) { 273 | if (c < 10) { 274 | hits10++; 275 | hits100++; 276 | hits1000++; 277 | } else if (c < 100) { 278 | hits100++; 279 | hits1000++; 280 | } else if (c < 1000) 281 | hits1000++; 282 | } 283 | //printf("%d\t%d\t%f\t%d\n", user, item, pred, yd[user][item]); 284 | //fflush(stdout); 285 | if (c > 1000) 286 | break; 287 | c++; 288 | } 289 | 290 | mhits10 += (double)hits10 / 10; 291 | mhits100 += (double)hits100 / 100; 292 | mhits1000 += (double)hits1000 / 1000; 293 | } 294 | 295 | printf("%.5f\t%.5f\t%.5f\n", 296 | (double)mhits10 / byuser.size(), 297 | (double)mhits100 / byuser.size(), 298 | (double)mhits1000 / byuser.size()); 299 | fflush(stdout); 300 | } 301 | -------------------------------------------------------------------------------- /src/ratings.cc: -------------------------------------------------------------------------------- 1 | #include "ratings.hh" 2 | #include "log.hh" 3 | #include 4 | 5 | int 6 | Ratings::read(string s) 7 | { 8 | fprintf(stdout, "+ reading ratings dataset from %s\n", s.c_str()); 9 | fflush(stdout); 10 | 11 | if (_env.mode == Env::CREATE_TRAIN_TEST_SETS) { 12 | if (_env.dataset == Env::NETFLIX) { 13 | for (uint32_t i = 0; i < _env.m; ++i) { 14 | if (read_netflix_movie(s,i+1) < 0) { 15 | lerr("error adding movie %d\n", i); 16 | return -1; 17 | } 18 | } 19 | } else if (_env.dataset == Env::MOVIELENS) 20 | read_movielens(s); 21 | else if (_env.dataset == Env::MENDELEY) 22 | read_mendeley(s); 23 | else if (_env.dataset == Env::ECHONEST) 24 | read_echonest(s); 25 | } else 26 | read_generic_train(s); 27 | 28 | char st[1024]; 29 | sprintf(st, "read %d users, %d movies, %d ratings", 30 | _curr_user_seq, _curr_movie_seq, _nratings); 31 | Env::plog("statistics", string(st)); 32 | 33 | return 0; 34 | } 35 | 36 | int 37 | Ratings::read_generic_train(string dir) 38 | { 39 | char buf[1024]; 40 | sprintf(buf, "%s/train.tsv", dir.c_str()); 41 | FILE *f = fopen(buf, "r"); 42 | if (!f) { 43 | fprintf(stderr, "error: cannot open file %s:%s", buf, strerror(errno)); 44 | fclose(f); 45 | exit(-1); 46 | } 47 | 48 | read_generic(f, NULL); 49 | fclose(f); 50 | Env::plog("training ratings", _nratings); 51 | } 52 | 53 | int 54 | Ratings::read_generic(FILE *f, CountMap *cmap) 55 | { 56 | assert(f); 57 | char b[128]; 58 | uint32_t mid = 0, uid = 0, rating = 0; 59 | while (!feof(f)) { 60 | if (fscanf(f, "%u\t%u\t%u\n", &uid, &mid, &rating) < 0) { 61 | //printf("error: unexpected lines in file\n"); 62 | fclose(f); 63 | exit(-1); 64 | } 65 | 66 | IDMap::iterator it = _user2seq.find(uid); 67 | if (it == _user2seq.end() && !add_user(uid)) { 68 | //printf("error: exceeded user limit %d, %d, %d\n", 69 | //uid, mid, rating); 70 | fflush(stdout); 71 | continue; 72 | } 73 | 74 | IDMap::iterator mt = _movie2seq.find(mid); 75 | if (mt == _movie2seq.end() && !add_movie(mid)) { 76 | //printf("error: exceeded movie limit %d, %d, %d\n", 77 | // uid, mid, rating); 78 | fflush(stdout); 79 | continue; 80 | } 81 | 82 | uint32_t m = _movie2seq[mid]; 83 | uint32_t n = _user2seq[uid]; 84 | 85 | if (rating > 0) { 86 | if (!cmap) { 87 | _nratings++; 88 | RatingMap *rm = _users2rating[n]; 89 | if (_env.binary_data) 90 | (*rm)[m] = 1; 91 | else 92 | (*rm)[m] = rating; 93 | _users[n]->push_back(m); 94 | _movies[m]->push_back(n); 95 | } else { 96 | Rating r(n,m); 97 | assert(cmap); 98 | if (_env.binary_data) 99 | (*cmap)[r] = 1; 100 | else 101 | (*cmap)[r] = rating; 102 | } 103 | } 104 | } 105 | return 0; 106 | } 107 | 108 | int 109 | Ratings::read_test_users(FILE *f, UserMap *bmap) 110 | { 111 | assert (bmap); 112 | uint32_t uid = 0; 113 | while (!feof(f)) { 114 | if (fscanf(f, "%u\n", &uid) < 0) { 115 | printf("error: unexpected lines in file\n"); 116 | exit(-1); 117 | } 118 | 119 | IDMap::iterator it = _user2seq.find(uid); 120 | if (it == _user2seq.end()) 121 | continue; 122 | assert (it != _user2seq.end()); 123 | uint32_t n = _user2seq[uid]; 124 | 125 | (*bmap)[n] = true; 126 | } 127 | Env::plog("read %d test users", bmap->size()); 128 | return 0; 129 | } 130 | 131 | int 132 | Ratings::read_echonest(string dir) 133 | { 134 | printf("reading echo nest dataset...\n"); 135 | fflush(stdout); 136 | uint32_t mcurr = 1, scurr = 1; 137 | char buf[1024]; 138 | sprintf(buf, "%s/train_triplets.txt", dir.c_str()); 139 | 140 | FILE *f = fopen(buf, "r"); 141 | if (!f) { 142 | fprintf(stderr, "error: cannot open file %s:%s", buf, strerror(errno)); 143 | fclose(f); 144 | exit(-1); 145 | } 146 | uint32_t mid = 0, uid = 0, rating = 0; 147 | char mids[512], uids[512]; 148 | char b[128]; 149 | while (!feof(f)) { 150 | if (fscanf(f, "%s\t%s\t%u\n", uids, mids, &rating) < 0) { 151 | printf("error: unexpected lines in file\n"); 152 | fclose(f); 153 | exit(-1); 154 | } 155 | 156 | StrMap::iterator uiditr = _str2id.find(uids); 157 | if (uiditr == _str2id.end()) { 158 | _str2id[uids] = scurr; 159 | scurr++; 160 | } 161 | uid = _str2id[uids]; 162 | 163 | StrMap::iterator miditr = _str2id.find(mids); 164 | if (miditr == _str2id.end()) { 165 | _str2id[mids] = mcurr; 166 | mcurr++; 167 | } 168 | mid = _str2id[mids]; 169 | 170 | IDMap::iterator it = _user2seq.find(uid); 171 | if (it == _user2seq.end() && !add_user(uid)) { 172 | printf("error: exceeded user limit %d, %d, %d\n", 173 | uid, mid, rating); 174 | fflush(stdout); 175 | continue; 176 | } 177 | 178 | IDMap::iterator mt = _movie2seq.find(mid); 179 | if (mt == _movie2seq.end() && !add_movie(mid)) { 180 | printf("error: exceeded movie limit %d, %d, %d\n", 181 | uid, mid, rating); 182 | fflush(stdout); 183 | continue; 184 | } 185 | 186 | uint32_t m = _movie2seq[mid]; 187 | uint32_t n = _user2seq[uid]; 188 | 189 | _user2str[n] = uids; 190 | _movie2str[m] = mids; 191 | 192 | if (rating > 0) { 193 | _nratings++; 194 | RatingMap *rm = _users2rating[n]; 195 | (*rm)[m] = rating; 196 | _users[n]->push_back(m); 197 | _movies[m]->push_back(n); 198 | _ratings.push_back(Rating(n,m)); 199 | } 200 | if (_nratings % 1000 == 0) { 201 | printf("\r+ read %d users, %d movies, %d ratings", 202 | _curr_user_seq, _curr_movie_seq, _nratings); 203 | fflush(stdout); 204 | } 205 | } 206 | fclose(f); 207 | return 0; 208 | } 209 | 210 | int 211 | Ratings::read_mendeley(string dir) 212 | { 213 | char buf[1024]; 214 | sprintf(buf, "%s/users.dat", dir.c_str()); 215 | 216 | info("reading from %s\n", buf); 217 | 218 | FILE *f = fopen(buf, "r"); 219 | if (!f) { 220 | fprintf(stderr, "error: cannot open file %s:%s", buf, strerror(errno)); 221 | fclose(f); 222 | exit(-1); 223 | } 224 | 225 | uint32_t uid = 1, rating = 0; 226 | char b[128]; 227 | while (!feof(f)) { 228 | vector mids; 229 | uint32_t len = 0; 230 | if (fscanf(f, "%u\t", &len) < 0) { 231 | printf("error: unexpected lines in file\n"); 232 | fclose(f); 233 | exit(-1); 234 | } 235 | 236 | uint32_t mid = 0; 237 | for (uint32_t i = 0; i < len; ++i) { 238 | if (i == len - 1) { 239 | if (fscanf(f, "%u\t", &mid) < 0) { 240 | printf("error: unexpected lines in file\n"); 241 | fclose(f); 242 | exit(-1); 243 | } 244 | mids.push_back(mid); 245 | } else { 246 | if (fscanf(f, "%u", &mid) < 0) { 247 | printf("error: unexpected lines in file\n"); 248 | fclose(f); 249 | exit(-1); 250 | } 251 | mids.push_back(mid); 252 | } 253 | } 254 | 255 | IDMap::iterator it = _user2seq.find(uid); 256 | if (it == _user2seq.end() && !add_user(uid)) { 257 | printf("error: exceeded user limit %d, %d, %d\n", 258 | uid, mid, rating); 259 | fflush(stdout); 260 | continue; 261 | } 262 | 263 | for (uint32_t idx = 0; idx < mids.size(); ++idx) { 264 | uint32_t mid = mids[idx]; 265 | IDMap::iterator mt = _movie2seq.find(mid); 266 | if (mt == _movie2seq.end() && !add_movie(mid)) { 267 | printf("error: exceeded movie limit %d, %d, %d\n", 268 | uid, mid, rating); 269 | fflush(stdout); 270 | continue; 271 | } 272 | uint32_t m = _movie2seq[mid]; 273 | uint32_t n = _user2seq[uid]; 274 | 275 | yval_t rating = 1.0; 276 | _nratings++; 277 | RatingMap *rm = _users2rating[n]; 278 | (*rm)[m] = rating; 279 | _users[n]->push_back(m); 280 | _movies[m]->push_back(n); 281 | _ratings.push_back(Rating(n,m)); 282 | } 283 | uid++; 284 | if (_nratings % 1000 == 0) { 285 | printf("\r+ read %d users, %d movies, %d ratings", 286 | _curr_user_seq, _curr_movie_seq, _nratings); 287 | fflush(stdout); 288 | } 289 | } 290 | fclose(f); 291 | return 0; 292 | } 293 | 294 | int 295 | Ratings::read_netflix_movie(string dir, uint32_t movie) 296 | { 297 | char buf[1024]; 298 | sprintf(buf, "%s/mv_%.7d.txt", dir.c_str(), movie); 299 | 300 | info("reading from %s\n", buf); 301 | 302 | FILE *f = fopen(buf, "r"); 303 | if (!f) { 304 | fprintf(stderr, "error: cannot open file %s:%s", buf, strerror(errno)); 305 | fclose(f); 306 | exit(-1); 307 | } 308 | 309 | uint32_t mid = 0; 310 | if (!fscanf(f, "%d:\n", &mid)) { 311 | fclose(f); 312 | return -1; 313 | } 314 | assert (mid == movie); 315 | 316 | IDMap::iterator mt = _movie2seq.find(mid); 317 | if (mt == _movie2seq.end() && !add_movie(mid)) { 318 | fclose(f); 319 | return 0; 320 | } 321 | 322 | uint32_t m = _movie2seq[mid]; 323 | uint32_t uid = 0, rating = 0; 324 | char b[128]; 325 | while (!feof(f)) { 326 | if (fscanf(f, "%u,%u,%*s\n", &uid, &rating, b) < 0) { 327 | printf("error: unexpected lines in file\n"); 328 | fclose(f); 329 | exit(-1); 330 | } 331 | 332 | IDMap::iterator it = _user2seq.find(uid); 333 | if (it == _user2seq.end() && !add_user(uid)) 334 | continue; 335 | 336 | uint32_t n = _user2seq[uid]; 337 | 338 | if (rating > 0) { 339 | _nratings++; 340 | RatingMap *rm = _users2rating[n]; 341 | (*rm)[m] = rating; 342 | _users[n]->push_back(m); 343 | _movies[m]->push_back(n); 344 | _ratings.push_back(Rating(n,m)); 345 | } 346 | } 347 | fclose(f); 348 | printf("\r+ read %d users, %d movies, %d ratings", 349 | _curr_user_seq, _curr_movie_seq, _nratings); 350 | fflush(stdout); 351 | return 0; 352 | } 353 | 354 | int 355 | Ratings::read_movielens(string dir) 356 | { 357 | char buf[1024]; 358 | sprintf(buf, "%s/ml-1m_train.tsv", dir.c_str()); 359 | 360 | info("reading from %s\n", buf); 361 | 362 | FILE *f = fopen(buf, "r"); 363 | if (!f) { 364 | fprintf(stderr, "error: cannot open file %s:%s", buf, strerror(errno)); 365 | fclose(f); 366 | exit(-1); 367 | } 368 | 369 | uint32_t mid = 0, uid = 0, rating = 0; 370 | char b[128]; 371 | while (!feof(f)) { 372 | if (fscanf(f, "%u\t%u\t%u\n", &uid, &mid, &rating) < 0) { 373 | printf("error: unexpected lines in file\n"); 374 | fclose(f); 375 | exit(-1); 376 | } 377 | 378 | IDMap::iterator it = _user2seq.find(uid); 379 | if (it == _user2seq.end() && !add_user(uid)) { 380 | printf("error: exceeded user limit %d, %d, %d\n", 381 | uid, mid, rating); 382 | fflush(stdout); 383 | continue; 384 | } 385 | 386 | IDMap::iterator mt = _movie2seq.find(mid); 387 | if (mt == _movie2seq.end() && !add_movie(mid)) { 388 | printf("error: exceeded movie limit %d, %d, %d\n", 389 | uid, mid, rating); 390 | fflush(stdout); 391 | continue; 392 | } 393 | 394 | uint32_t m = _movie2seq[mid]; 395 | uint32_t n = _user2seq[uid]; 396 | 397 | if (rating > 0) { 398 | _nratings++; 399 | RatingMap *rm = _users2rating[n]; 400 | (*rm)[m] = rating; 401 | _users[n]->push_back(m); 402 | _movies[m]->push_back(n); 403 | _ratings.push_back(Rating(n,m)); 404 | } 405 | } 406 | fclose(f); 407 | return 0; 408 | } 409 | 410 | 411 | void 412 | Ratings::load_movies_metadata(string s) 413 | { 414 | if (_env.dataset == Env::MOVIELENS) 415 | read_movielens_metadata(s); 416 | else if (_env.dataset == Env::NETFLIX) 417 | read_netflix_metadata(s); 418 | else if (_env.dataset == Env::MENDELEY) 419 | read_mendeley_metadata(s); 420 | } 421 | 422 | int 423 | Ratings::read_movielens_metadata(string dir) 424 | { 425 | uint32_t n = 0; 426 | char buf[1024]; 427 | sprintf(buf, "%s/movies.tsv", dir.c_str()); 428 | FILE *f = fopen(buf, "r"); 429 | assert(f); 430 | uint32_t id; 431 | char name[4096]; 432 | char type[4096]; 433 | char *line = (char *)malloc(4096); 434 | while (!feof(f)) { 435 | if (fgets(line, 4096, f) == NULL) 436 | break; 437 | uint32_t k = 0; 438 | char *p = line; 439 | const char r[3] = "#"; 440 | do { 441 | char *q = NULL; 442 | char *d = strtok_r(p, r, &q); 443 | if (q == p) 444 | break; 445 | if (k == 0) { 446 | id = atoi(d); 447 | id = _movie2seq[id]; 448 | } else if (k == 1) { 449 | strcpy(name, d); 450 | _movie_names[id] = name; 451 | lerr("%d -> %s", id, name); 452 | } else if (k == 2) { 453 | strcpy(type, d); 454 | _movie_types[id] = type; 455 | lerr("%d -> %s", id, type); 456 | } 457 | p = q; 458 | k++; 459 | } while (p != NULL); 460 | n++; 461 | debug("read %d lines\n", n); 462 | memset(line, 0, 4096); 463 | } 464 | free(line); 465 | return 0; 466 | } 467 | 468 | int 469 | Ratings::read_netflix_metadata(string dir) 470 | { 471 | uint32_t n = 0; 472 | char buf[1024]; 473 | sprintf(buf, "%s/movie_titles.txt", dir.c_str()); 474 | FILE *f = fopen(buf, "r"); 475 | assert(f); 476 | uint32_t id, year; 477 | char name[4096]; 478 | char *line = (char *)malloc(4096); 479 | while (!feof(f)) { 480 | if (fgets(line, 4096, f) == NULL) 481 | break; 482 | uint32_t k = 0; 483 | char *p = line; 484 | const char r[3] = ","; 485 | do { 486 | char *q = NULL; 487 | char *d = strtok_r(p, r, &q); 488 | if (q == p) 489 | break; 490 | if (k == 0) { 491 | id = atoi(d); 492 | lerr("%d: ", id); 493 | id = _movie2seq[id]; 494 | lerr("%d -> ", id); 495 | } else if (k == 1) { 496 | year = atoi(d); // skip 497 | lerr("%d", year); 498 | } else if (k == 2) { 499 | strcpy(name, d); 500 | _movie_names[id] = name; 501 | _movie_types[id] = ""; 502 | lerr("%d -> %s", id, name); 503 | } 504 | p = q; 505 | k++; 506 | } while (p != NULL); 507 | n++; 508 | lerr("read %d lines\n", n); 509 | memset(line, 0, 4096); 510 | } 511 | free(line); 512 | return 0; 513 | } 514 | 515 | int 516 | Ratings::read_mendeley_metadata(string dir) 517 | { 518 | uint32_t n = 0; 519 | char buf[1024]; 520 | sprintf(buf, "%s/titles.dat", dir.c_str()); 521 | FILE *f = fopen(buf, "r"); 522 | assert(f); 523 | char name[4096]; 524 | char *line = (char *)malloc(4096); 525 | uint32_t id = 0; 526 | while (!feof(f)) { 527 | if (fgets(line, 4096, f) == NULL) 528 | break; 529 | strcpy(name, line); 530 | uint32_t seq = _movie2seq[id]; 531 | _movie_names[seq] = name; 532 | id++; 533 | } 534 | lerr("read %d lines\n", n); 535 | free(line); 536 | } 537 | 538 | 539 | string 540 | Ratings::movies_by_user_s() const 541 | { 542 | ostringstream sa; 543 | sa << "\n[\n"; 544 | for (uint32_t i = 0; i < _users.size(); ++i) { 545 | IDMap::const_iterator it = _seq2user.find(i); 546 | sa << it->second << ":"; 547 | vector *v = _users[i]; 548 | if (v) { 549 | for (uint32_t j = 0; j < v->size(); ++j) { 550 | uint32_t m = v->at(j); 551 | IDMap::const_iterator mt = _seq2movie.find(m); 552 | sa << mt->second; 553 | if (j < v->size() - 1) 554 | sa << ", "; 555 | } 556 | sa << "\n"; 557 | } 558 | } 559 | sa << "]"; 560 | return sa.str(); 561 | } 562 | -------------------------------------------------------------------------------- /src/ratings.hh: -------------------------------------------------------------------------------- 1 | #ifndef RATINGS_HH 2 | #define RATINGS_HH 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "matrix.hh" 10 | #include "env.hh" 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | class Ratings { 21 | public: 22 | Ratings(Env &env): 23 | _users2rating(env.n), 24 | _users(env.n), 25 | _movies(env.m), 26 | _env(env), 27 | _curr_user_seq(0), 28 | _curr_movie_seq(0), 29 | _nratings(0), 30 | _likes(0) { } 31 | ~Ratings() { } 32 | 33 | int read(string s); 34 | const uint8_t rating_class(uint32_t v); 35 | 36 | const SparseMatrix &users() const { return _users; } 37 | SparseMatrix &users() { return _users; } 38 | 39 | const SparseMatrix &movies() const { return _movies; } 40 | SparseMatrix &movies() { return _movies; } 41 | 42 | uint32_t n() const; 43 | uint32_t m() const; 44 | uint32_t r(uint32_t i, uint32_t j) const; 45 | uint32_t nratings() const { return _nratings; } 46 | uint32_t likes() const { return _likes; } 47 | const vector &allratings() const { return _ratings; } 48 | 49 | const vector *get_users(uint32_t a); 50 | const vector *get_movies(uint32_t a); 51 | 52 | const IDMap &user2seq() const { return _user2seq; } 53 | const IDMap &seq2user() const { return _seq2user; } 54 | 55 | const IDMap &movie2seq() const { return _movie2seq; } 56 | const IDMap &seq2movie() const { return _seq2movie; } 57 | int read_generic(FILE *f, CountMap *m); 58 | void load_movies_metadata(string dir); 59 | int read_test_users(FILE *f, UserMap *); 60 | 61 | string movie_type(uint32_t movie_seq) const; 62 | string movie_name(uint32_t movie_seq) const; 63 | 64 | private: 65 | int read_generic_train(string dir); 66 | int read_netflix_movie(string dir, uint32_t movie); 67 | int read_movielens(string dir); 68 | int read_mendeley(string dir); 69 | int read_echonest(string dir); 70 | int read_movielens_metadata(string dir); 71 | int read_netflix_metadata(string dir); 72 | int read_mendeley_metadata(string dir); 73 | string movies_by_user_s() const; 74 | bool add_movie(uint32_t id); 75 | bool add_user(uint32_t id); 76 | 77 | SparseMatrixR _users2rating; 78 | SparseMatrix _users; 79 | SparseMatrix _movies; 80 | vector _ratings; 81 | 82 | Env &_env; 83 | IDMap _user2seq; 84 | IDMap _movie2seq; 85 | IDMap _seq2user; 86 | IDMap _seq2movie; 87 | StrMap _str2id; 88 | StrMapInv _user2str; 89 | StrMapInv _movie2str; 90 | uint32_t _curr_user_seq; 91 | uint32_t _curr_movie_seq; 92 | uint32_t _nratings; 93 | uint32_t _likes; 94 | StrMapInv _movie_names; 95 | StrMapInv _movie_types; 96 | }; 97 | 98 | inline uint32_t 99 | Ratings::n() const 100 | { 101 | return _users.size(); 102 | } 103 | 104 | inline uint32_t 105 | Ratings::m() const 106 | { 107 | return _movies.size(); 108 | } 109 | 110 | inline bool 111 | Ratings::add_user(uint32_t id) 112 | { 113 | if (_curr_user_seq >= _env.n) { 114 | lerr("max users %d reached", _env.n); 115 | return false; 116 | } 117 | _user2seq[id] = _curr_user_seq; 118 | _seq2user[_curr_user_seq] = id; 119 | 120 | assert (!_users[_curr_user_seq]); 121 | std::vector **v = _users.data(); 122 | v[_curr_user_seq] = new vector; 123 | RatingMap **rm = _users2rating.data(); 124 | rm[_curr_user_seq] = new RatingMap; 125 | _curr_user_seq++; 126 | return true; 127 | } 128 | 129 | inline bool 130 | Ratings::add_movie(uint32_t id) 131 | { 132 | if (_curr_movie_seq >= _env.m) { 133 | //lerr("max movies %d reached", _env.m); 134 | return false; 135 | } 136 | _movie2seq[id] = _curr_movie_seq; 137 | _seq2movie[_curr_movie_seq] = id; 138 | 139 | assert (!_movies[_curr_movie_seq]); 140 | std::vector **v = _movies.data(); 141 | v[_curr_movie_seq] = new vector; 142 | _curr_movie_seq++; 143 | return true; 144 | } 145 | 146 | inline uint32_t 147 | Ratings::r(uint32_t a, uint32_t b) const 148 | { 149 | assert (a < _env.n && b < _env.m); 150 | const RatingMap *rm = _users2rating[a]; 151 | if (!rm) { 152 | IDMap::const_iterator itr = _seq2user.find(a); 153 | if (itr == _seq2user.end()) 154 | lerr("cannot find ID for seq %d (item %d)", a, b); 155 | else 156 | lerr("a = %d (%d), b = %d, ", a, itr->second, b); 157 | } 158 | assert(rm); 159 | const RatingMap &rmc = *rm; 160 | RatingMap::const_iterator itr = rmc.find(b); 161 | return itr->second; 162 | } 163 | 164 | inline const vector * 165 | Ratings::get_users(uint32_t a) 166 | { 167 | assert (a < _movies.size()); 168 | const vector *v = _movies[a]; 169 | return v; 170 | } 171 | 172 | inline const vector * 173 | Ratings::get_movies(uint32_t a) 174 | { 175 | assert (a < _users.size()); 176 | const vector *v = _users[a]; 177 | return v; 178 | } 179 | 180 | inline const uint8_t 181 | Ratings::rating_class(uint32_t v) 182 | { 183 | return v >= 1 ? 1 : 0; 184 | } 185 | 186 | inline string 187 | Ratings::movie_name(uint32_t movie_seq) const 188 | { 189 | assert (movie_seq < _env.m); 190 | StrMapInv::const_iterator i = _movie_names.find(movie_seq); 191 | if (i != _movie_names.end()) 192 | return i->second; 193 | return ""; 194 | } 195 | 196 | inline string 197 | Ratings::movie_type(uint32_t movie_seq) const 198 | { 199 | assert (movie_seq < _env.m); 200 | StrMapInv::const_iterator i = _movie_types.find(movie_seq); 201 | if (i != _movie_types.end()) 202 | return i->second; 203 | return ""; 204 | } 205 | 206 | #endif 207 | -------------------------------------------------------------------------------- /src/roceasy.c: -------------------------------------------------------------------------------- 1 | // 2 | // SOURCE: http://www.cs.cornell.edu/Courses/cs578/2002fa/roceasy.c 3 | // Precision recall curves by Prem Gopalan, pgopalan@cs.princeton.edu 4 | // 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define MAX_ITEMS 1000000 11 | #define debug 0 12 | #define eps 1.0e-10 13 | 14 | /* 15 | To compile on unix, try "cc -o roceasy roceasy.c -lm" 16 | 17 | Input to the program is a sequence of lines, one line per 18 | case with the following format: 19 | 20 | "TRUE_VALUE whitespace PROB_CLASS_1" 21 | 22 | TRUE_VALUE is the true class (usually a 0 or 1). 23 | PROB_CLASS_1 is the probability predicted for class 1. 24 | 25 | To run roc.hw3 on the results in a file called "test_preds" 26 | 27 | roc.hw3 < test_preds 28 | 29 | The program computes the ROC Area, RMSE, and accuracy. It also 30 | will compute the x,y values for the roc graph when run using the 31 | option "-plot". You'll usually want to save the x,y values in a 32 | file to use with a plotting program: 33 | 34 | roc.hw3 -plot < test_preds > roc.plot 35 | 36 | The ROC curve is a plot of SENSITIVITY vs. 1-SPECIFICITY as the 37 | prediction threshold sweeps from 0 to 1. SENSITIVITY is also 38 | called True Positives, and 1-SPECIFICITY is called FALSE POSITIVES. 39 | 40 | A typical ROC curve for reasonably accurate predictions looks 41 | like this: 42 | 43 | | * 44 | S | * 45 | E | * 46 | N | * 47 | S | 48 | I | * 49 | T | 50 | I | * 51 | V | 52 | I | * 53 | T | 54 | Y |* 55 | - - - - - - - - - - - - - - - - - - - 56 | 1 - SPECIFICITY 57 | 58 | If there is no relationship between the prediction and truth, the 59 | ROC curve is a diagonal line with area 0.5. If the prediction 60 | strongly predicts truth, the curve rises quickly and has area near 61 | 1.0. If the prediction strongly predicts anti-truth, the ROC area 62 | is less than 0.5. 63 | 64 | Here's a definition of SPECIFICITY, SENSITIVITY, and the other 65 | error measures this program computes. (This is from Constantin's 66 | email.) 67 | 68 | MODEL PREDICTION 69 | 70 | | 1 0 | 71 | - - - + - - - - - - - - - - - + - - - - - 72 | TRUE 1 | A B | A+B 73 | OUTCOME | | 74 | 0 | C D | C+D 75 | - - - + - - - - - - - - - - - + - - - - - 76 | | A+C B+D | A+B+C+D 77 | 78 | 79 | 1 = POSITIVE 80 | 0 = NEGATIVE 81 | 82 | 83 | ACC = (A+D) /(A+B+C+D) 84 | PPV = A / (A+C) 85 | NPV = D / (B+D) 86 | SEN = A / (A+B) 87 | SPE = D / (C+D) 88 | 89 | 90 | WARNING!: This code has not been thoroughly tested. If you find 91 | an error, please email me: caruana@cs.cornell.edu 92 | 93 | */ 94 | 95 | float true[MAX_ITEMS]; 96 | float pred[MAX_ITEMS]; 97 | double mean_true, mean_pred; 98 | double p1; 99 | double sse, rmse; 100 | double pred_thresh; 101 | int a, b, c, d; 102 | double freq_thresh, threshold; 103 | double max_acc, max_acc_thresh, last_acc_thresh, acc, acc_plot; 104 | int freq_a, freq_b, freq_c, freq_d; 105 | int max_acc_a, max_acc_b, max_acc_c, max_acc_d, max_acc_count; 106 | 107 | int arg, taken, area, plot, stats, thresh, prec_opt; 108 | int ace, breyce, monti; 109 | int no_item, item; 110 | int tt, tf, ft, ff; 111 | int total_true_0, total_true_1; 112 | double sens, spec, tpf, fpf, tpf_prev, fpf_prev, roc_area; 113 | double prec_area, prec_prev; 114 | double prec; 115 | double ace_sum, breyce_sum; 116 | 117 | /* compute the accuracy using the threshold */ 118 | 119 | double accuracy (double threshold) 120 | { 121 | int a,b,c,d,item; 122 | a = 0; b = 0; c = 0; d = 0; 123 | for (item=0; item= threshold ) 128 | a++; 129 | else 130 | b++; 131 | } 132 | else 133 | /* true outcome = 0 */ 134 | { 135 | if ( pred[item] >= threshold ) 136 | c++; 137 | else 138 | d++; 139 | } 140 | return( ((double)(a+d)) / (((double)(a+b+c+d)) + eps) ); 141 | } 142 | 143 | /* partition is used by quicksort */ 144 | 145 | int partition (p,r) 146 | int p,r; 147 | { 148 | int i, j; 149 | float x, tempf; 150 | 151 | x = pred[p]; 152 | i = p - 1; 153 | j = r + 1; 154 | while (1) 155 | { 156 | do j--; while (!(pred[j] <= x)); 157 | do i++; while (!(pred[i] >= x)); 158 | if (i < j) 159 | { 160 | tempf = pred[i]; 161 | pred[i] = pred[j]; 162 | pred[j] = tempf; 163 | tempf = true[i]; 164 | true[i] = true[j]; 165 | true[j] = tempf; 166 | } 167 | else 168 | return(j); 169 | } 170 | } 171 | 172 | /* vanilla quicksort */ 173 | 174 | quicksort (p,r) 175 | int p,r; 176 | { 177 | int q; 178 | 179 | if (p < r) 180 | { 181 | q = partition (p,r); 182 | quicksort (p,q); 183 | quicksort (q+1,r); 184 | } 185 | } 186 | 187 | main (argc, argv) 188 | int argc; 189 | int **argv; 190 | 191 | { 192 | area = 1; 193 | plot = 0; 194 | stats = 1; 195 | arg = 1; 196 | prec_opt = 0; 197 | while ( arg < argc ) 198 | { 199 | if (!strcmp((char *)argv[arg], "-p") || 200 | !strcmp((char *)argv[arg], "-rocplot") || 201 | !strcmp((char *)argv[arg], "-ROCplot") || 202 | !strcmp((char *)argv[arg], "-roc_plot") || 203 | !strcmp((char *)argv[arg], "-ROC_plot") || 204 | !strcmp((char *)argv[arg], "-plot")) 205 | { 206 | plot = 1; 207 | area = 0; 208 | stats = 0; 209 | taken = 1; 210 | } else if (!strcmp((char *)argv[arg], "-prec")) { 211 | //printf("precision option set\n"); 212 | prec_opt = 1; 213 | taken = 1; 214 | stats = 0; 215 | area = 0; 216 | } 217 | if (!taken) 218 | { 219 | printf("\nWarning!: Unrecognized program option %s\n", argv[arg]); 220 | } 221 | arg++; 222 | } 223 | 224 | no_item = 0; 225 | mean_true = 0.0; 226 | mean_pred = 0.0; 227 | sse = 0.0; 228 | while ( (scanf("%f %lf", &true[no_item], &p1)) != EOF ) 229 | { 230 | /* 231 | Note that unlike the rest of the code, the RMSE calculation 232 | assumes the class is 0 or 1 and that the probabilities 233 | probably have been correctly normalized. 234 | */ 235 | pred[no_item] = p1; 236 | sse+= (true[no_item]-p1)*(true[no_item]-p1); 237 | mean_true+= true[no_item]; 238 | mean_pred+= pred[no_item]; 239 | no_item++; 240 | if ( no_item >= MAX_ITEMS ) 241 | { 242 | printf ("Aborting. Exceeded %d items.\n", MAX_ITEMS); 243 | exit(1); 244 | } 245 | } 246 | mean_true = mean_true / ((double) no_item); 247 | mean_pred = mean_pred / ((double) no_item); 248 | rmse = sqrt (sse / ((double) no_item)); 249 | 250 | if (debug) 251 | { 252 | printf("%d pats read. mean_true %6.4lf. mean_pred %6.4lf\n", no_item, mean_true, mean_pred); 253 | fflush(stdout); 254 | } 255 | 256 | total_true_0 = 0; 257 | total_true_1 = 0; 258 | for (item=0; item max_acc ) 285 | { 286 | max_acc = acc; 287 | max_acc_thresh = threshold; 288 | last_acc_thresh = threshold; 289 | max_acc_count = 1; 290 | } 291 | if ( (acc == max_acc) && (threshold != last_acc_thresh) ) 292 | { 293 | max_acc_count++; 294 | last_acc_thresh = threshold; 295 | } 296 | } 297 | 298 | /* find the prediction threshold such that the predicted number */ 299 | /* of 0's and 1's matches the observed number of true 0's and 1's */ 300 | 301 | freq_thresh = (pred[total_true_0]+pred[total_true_0-1])/2.0; 302 | 303 | /* now update some statistics using the various thresholds */ 304 | 305 | a = 0; 306 | b = 0; 307 | c = 0; 308 | d = 0; 309 | freq_a = 0; 310 | freq_b = 0; 311 | freq_c = 0; 312 | freq_d = 0; 313 | max_acc_a = 0; 314 | max_acc_b = 0; 315 | max_acc_c = 0; 316 | max_acc_d = 0; 317 | for (item=0; item= pred_thresh ) 322 | a++; 323 | else 324 | b++; 325 | if ( pred[item] >= freq_thresh ) 326 | freq_a++; 327 | else 328 | freq_b++; 329 | if ( pred[item] >= max_acc_thresh ) 330 | max_acc_a++; 331 | else 332 | max_acc_b++; 333 | } 334 | else 335 | /* true outcome = 0 */ 336 | { 337 | if ( pred[item] >= pred_thresh ) 338 | c++; 339 | else 340 | d++; 341 | if ( pred[item] >= freq_thresh ) 342 | freq_c++; 343 | else 344 | freq_d++; 345 | if ( pred[item] >= max_acc_thresh ) 346 | max_acc_c++; 347 | else 348 | max_acc_d++; 349 | } 350 | 351 | /* now let's do the ROC cruve and area */ 352 | 353 | tt = 0; 354 | tf = total_true_1; 355 | ft = 0; 356 | ff = total_true_0; 357 | 358 | sens = ((double) tt) / ((double) (tt+tf)); 359 | spec = ((double) ff) / ((double) (ft+ff)); 360 | prec = 0; 361 | tpf = sens; 362 | fpf = 1.0 - spec; 363 | if ( plot ) 364 | printf ("%6.4lf %6.4lf\n", fpf, tpf); 365 | else if ( prec_opt ) 366 | printf ("%6.4lf %6.4lf\n", sens, (prec >= 0) ? prec : .0); 367 | roc_area = 0.0; 368 | tpf_prev = tpf; 369 | fpf_prev = fpf; 370 | prec_prev = prec; 371 | prec_area = 0.0; 372 | 373 | for (item=no_item-1; item>-1; item--) 374 | { 375 | tt+= true[item]; 376 | tf-= true[item]; 377 | ft+= 1 - true[item]; 378 | ff-= 1 - true[item]; 379 | sens = ((double) tt) / ((double) (tt+tf)); 380 | spec = ((double) ff) / ((double) (ft+ff)); 381 | prec = ((double) tt) / ((double) (tt+ft)); 382 | tpf = sens; 383 | fpf = 1.0 - spec; 384 | if ( item > 0 ) 385 | if ( pred[item] != pred[item-1] ) 386 | { 387 | if ( plot ) 388 | printf ("%6.4lf %6.4lf\n", fpf, tpf); 389 | else if ( prec_opt ) 390 | printf ("%6.4lf %6.4lf\n", sens, prec); 391 | roc_area+= 0.5*(tpf+tpf_prev)*(fpf-fpf_prev); 392 | prec_area+= 0.5*(tpf+tpf_prev)*fabs(prec-prec_prev); 393 | tpf_prev = tpf; 394 | fpf_prev = fpf; 395 | prec_prev = prec; 396 | } 397 | if ( item == 0 ) 398 | { 399 | if ( plot ) 400 | printf ("%6.4lf %6.4lf\n", fpf, tpf); 401 | roc_area+= 0.5*(tpf+tpf_prev)*(fpf-fpf_prev); 402 | prec_area+= 0.5*(tpf+tpf_prev)*fabs(prec-prec_prev); 403 | } 404 | } 405 | 406 | if ( stats ) 407 | { 408 | printf ("ACC %8.5lf\n", accuracy(0.5)); 409 | printf ("RMS %8.5lf\n", rmse); 410 | printf ("ROC %8.5lf\n", roc_area); 411 | printf ("AUC-PR %8.5lf\n", prec_area); 412 | } 413 | } 414 | --------------------------------------------------------------------------------