opener-opinion-detector-base 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (261) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +101 -0
  3. data/bin/opinion-detector-base +19 -0
  4. data/core/annotation.cfg.erb +9 -0
  5. data/core/packages/KafNafParser-1.4.tar.gz +0 -0
  6. data/core/packages/VUA_pylib-1.5.tar.gz +0 -0
  7. data/core/python-scripts/LICENSE +339 -0
  8. data/core/python-scripts/README.md +226 -0
  9. data/core/python-scripts/classify_kaf_naf_file.py +499 -0
  10. data/core/python-scripts/cross_validation.py +634 -0
  11. data/core/python-scripts/generate_folds.py +134 -0
  12. data/core/python-scripts/models.cfg +10 -0
  13. data/core/python-scripts/my_templates/README +33 -0
  14. data/core/python-scripts/my_templates/templates_exp.only0.txt +6 -0
  15. data/core/python-scripts/my_templates/templates_exp.pol0.txt +10 -0
  16. data/core/python-scripts/my_templates/templates_exp.red.txt +7 -0
  17. data/core/python-scripts/my_templates/templates_exp.txt +10 -0
  18. data/core/python-scripts/my_templates/templates_holder.only0.txt +11 -0
  19. data/core/python-scripts/my_templates/templates_holder.red.txt +9 -0
  20. data/core/python-scripts/my_templates/templates_holder.txt +10 -0
  21. data/core/python-scripts/my_templates/templates_target.only0.txt +11 -0
  22. data/core/python-scripts/my_templates/templates_target.red.txt +9 -0
  23. data/core/python-scripts/my_templates/templates_target.txt +10 -0
  24. data/core/python-scripts/run_all_experiments.sh +49 -0
  25. data/core/python-scripts/run_basic.py +20 -0
  26. data/core/python-scripts/run_experiment.sh +42 -0
  27. data/core/python-scripts/scripts/__init__.py +1 -0
  28. data/core/python-scripts/scripts/config_manager.py +314 -0
  29. data/core/python-scripts/scripts/crfutils.py +215 -0
  30. data/core/python-scripts/scripts/extract_feats_relations.py +295 -0
  31. data/core/python-scripts/scripts/extract_features.py +376 -0
  32. data/core/python-scripts/scripts/feats_to_crf.exp.py +105 -0
  33. data/core/python-scripts/scripts/lexicons.py +44 -0
  34. data/core/python-scripts/scripts/link_entities_distance.py +77 -0
  35. data/core/python-scripts/scripts/relation_classifier.py +250 -0
  36. data/core/python-scripts/train.py +566 -0
  37. data/core/site-packages/pre_build/KafNafParser-1.4-py2.7.egg-info/PKG-INFO +10 -0
  38. data/core/site-packages/pre_build/KafNafParser-1.4-py2.7.egg-info/SOURCES.txt +22 -0
  39. data/core/site-packages/pre_build/KafNafParser-1.4-py2.7.egg-info/dependency_links.txt +1 -0
  40. data/core/site-packages/pre_build/KafNafParser-1.4-py2.7.egg-info/installed-files.txt +47 -0
  41. data/core/site-packages/pre_build/KafNafParser-1.4-py2.7.egg-info/top_level.txt +1 -0
  42. data/core/site-packages/pre_build/KafNafParser/KafNafParserMod.py +390 -0
  43. data/core/site-packages/pre_build/KafNafParser/KafNafParserMod.pyc +0 -0
  44. data/core/site-packages/pre_build/KafNafParser/__init__.py +14 -0
  45. data/core/site-packages/pre_build/KafNafParser/__init__.pyc +0 -0
  46. data/core/site-packages/pre_build/KafNafParser/constituency_data.py +125 -0
  47. data/core/site-packages/pre_build/KafNafParser/constituency_data.pyc +0 -0
  48. data/core/site-packages/pre_build/KafNafParser/coreference_data.py +52 -0
  49. data/core/site-packages/pre_build/KafNafParser/coreference_data.pyc +0 -0
  50. data/core/site-packages/pre_build/KafNafParser/dependency_data.py +78 -0
  51. data/core/site-packages/pre_build/KafNafParser/dependency_data.pyc +0 -0
  52. data/core/site-packages/pre_build/KafNafParser/entity_data.py +59 -0
  53. data/core/site-packages/pre_build/KafNafParser/entity_data.pyc +0 -0
  54. data/core/site-packages/pre_build/KafNafParser/external_references_data.py +41 -0
  55. data/core/site-packages/pre_build/KafNafParser/external_references_data.pyc +0 -0
  56. data/core/site-packages/pre_build/KafNafParser/feature_extractor/__init__.py +2 -0
  57. data/core/site-packages/pre_build/KafNafParser/feature_extractor/__init__.pyc +0 -0
  58. data/core/site-packages/pre_build/KafNafParser/feature_extractor/constituency.py +205 -0
  59. data/core/site-packages/pre_build/KafNafParser/feature_extractor/constituency.pyc +0 -0
  60. data/core/site-packages/pre_build/KafNafParser/feature_extractor/dependency.py +309 -0
  61. data/core/site-packages/pre_build/KafNafParser/feature_extractor/dependency.pyc +0 -0
  62. data/core/site-packages/pre_build/KafNafParser/features_data.py +131 -0
  63. data/core/site-packages/pre_build/KafNafParser/features_data.pyc +0 -0
  64. data/core/site-packages/pre_build/KafNafParser/header_data.py +127 -0
  65. data/core/site-packages/pre_build/KafNafParser/header_data.pyc +0 -0
  66. data/core/site-packages/pre_build/KafNafParser/opinion_data.py +211 -0
  67. data/core/site-packages/pre_build/KafNafParser/opinion_data.pyc +0 -0
  68. data/core/site-packages/pre_build/KafNafParser/references_data.py +23 -0
  69. data/core/site-packages/pre_build/KafNafParser/references_data.pyc +0 -0
  70. data/core/site-packages/pre_build/KafNafParser/span_data.py +63 -0
  71. data/core/site-packages/pre_build/KafNafParser/span_data.pyc +0 -0
  72. data/core/site-packages/pre_build/KafNafParser/term_data.py +111 -0
  73. data/core/site-packages/pre_build/KafNafParser/term_data.pyc +0 -0
  74. data/core/site-packages/pre_build/KafNafParser/term_sentiment_data.py +42 -0
  75. data/core/site-packages/pre_build/KafNafParser/term_sentiment_data.pyc +0 -0
  76. data/core/site-packages/pre_build/KafNafParser/text_data.py +99 -0
  77. data/core/site-packages/pre_build/KafNafParser/text_data.pyc +0 -0
  78. data/core/site-packages/pre_build/VUA_pylib-1.5-py2.7.egg-info/PKG-INFO +10 -0
  79. data/core/site-packages/pre_build/VUA_pylib-1.5-py2.7.egg-info/SOURCES.txt +14 -0
  80. data/core/site-packages/pre_build/VUA_pylib-1.5-py2.7.egg-info/dependency_links.txt +1 -0
  81. data/core/site-packages/pre_build/VUA_pylib-1.5-py2.7.egg-info/installed-files.txt +23 -0
  82. data/core/site-packages/pre_build/VUA_pylib-1.5-py2.7.egg-info/top_level.txt +1 -0
  83. data/core/site-packages/pre_build/VUA_pylib/__init__.py +1 -0
  84. data/core/site-packages/pre_build/VUA_pylib/__init__.pyc +0 -0
  85. data/core/site-packages/pre_build/VUA_pylib/common/__init__.py +1 -0
  86. data/core/site-packages/pre_build/VUA_pylib/common/__init__.pyc +0 -0
  87. data/core/site-packages/pre_build/VUA_pylib/common/common.py +28 -0
  88. data/core/site-packages/pre_build/VUA_pylib/common/common.pyc +0 -0
  89. data/core/site-packages/pre_build/VUA_pylib/corpus_reader/__init__.py +1 -0
  90. data/core/site-packages/pre_build/VUA_pylib/corpus_reader/__init__.pyc +0 -0
  91. data/core/site-packages/pre_build/VUA_pylib/corpus_reader/google_web_nl.py +156 -0
  92. data/core/site-packages/pre_build/VUA_pylib/corpus_reader/google_web_nl.pyc +0 -0
  93. data/core/site-packages/pre_build/VUA_pylib/io_utils/__init__.py +1 -0
  94. data/core/site-packages/pre_build/VUA_pylib/io_utils/__init__.pyc +0 -0
  95. data/core/site-packages/pre_build/VUA_pylib/io_utils/feature_file.py +121 -0
  96. data/core/site-packages/pre_build/VUA_pylib/io_utils/feature_file.pyc +0 -0
  97. data/core/site-packages/pre_build/VUA_pylib/lexicon/__init__.py +1 -0
  98. data/core/site-packages/pre_build/VUA_pylib/lexicon/__init__.pyc +0 -0
  99. data/core/site-packages/pre_build/VUA_pylib/lexicon/lexicon.py +72 -0
  100. data/core/site-packages/pre_build/VUA_pylib/lexicon/lexicon.pyc +0 -0
  101. data/core/site-packages/pre_build/VUKafParserPy-1.0-py2.7.egg-info/PKG-INFO +10 -0
  102. data/core/site-packages/pre_build/VUKafParserPy-1.0-py2.7.egg-info/SOURCES.txt +7 -0
  103. data/core/site-packages/pre_build/VUKafParserPy-1.0-py2.7.egg-info/dependency_links.txt +1 -0
  104. data/core/site-packages/pre_build/VUKafParserPy-1.0-py2.7.egg-info/installed-files.txt +11 -0
  105. data/core/site-packages/pre_build/VUKafParserPy-1.0-py2.7.egg-info/top_level.txt +1 -0
  106. data/core/site-packages/pre_build/VUKafParserPy/KafDataObjectsMod.py +165 -0
  107. data/core/site-packages/pre_build/VUKafParserPy/KafDataObjectsMod.pyc +0 -0
  108. data/core/site-packages/pre_build/VUKafParserPy/KafParserMod.py +439 -0
  109. data/core/site-packages/pre_build/VUKafParserPy/KafParserMod.pyc +0 -0
  110. data/core/site-packages/pre_build/VUKafParserPy/__init__.py +7 -0
  111. data/core/site-packages/pre_build/VUKafParserPy/__init__.pyc +0 -0
  112. data/core/vendor/src/crfsuite/AUTHORS +1 -0
  113. data/core/vendor/src/crfsuite/COPYING +27 -0
  114. data/core/vendor/src/crfsuite/ChangeLog +103 -0
  115. data/core/vendor/src/crfsuite/INSTALL +236 -0
  116. data/core/vendor/src/crfsuite/Makefile.am +19 -0
  117. data/core/vendor/src/crfsuite/Makefile.in +783 -0
  118. data/core/vendor/src/crfsuite/README +183 -0
  119. data/core/vendor/src/crfsuite/aclocal.m4 +9018 -0
  120. data/core/vendor/src/crfsuite/autogen.sh +38 -0
  121. data/core/vendor/src/crfsuite/compile +143 -0
  122. data/core/vendor/src/crfsuite/config.guess +1502 -0
  123. data/core/vendor/src/crfsuite/config.h.in +198 -0
  124. data/core/vendor/src/crfsuite/config.sub +1714 -0
  125. data/core/vendor/src/crfsuite/configure +14273 -0
  126. data/core/vendor/src/crfsuite/configure.in +149 -0
  127. data/core/vendor/src/crfsuite/crfsuite.sln +42 -0
  128. data/core/vendor/src/crfsuite/depcomp +630 -0
  129. data/core/vendor/src/crfsuite/example/chunking.py +49 -0
  130. data/core/vendor/src/crfsuite/example/crfutils.py +179 -0
  131. data/core/vendor/src/crfsuite/example/ner.py +270 -0
  132. data/core/vendor/src/crfsuite/example/pos.py +78 -0
  133. data/core/vendor/src/crfsuite/example/template.py +88 -0
  134. data/core/vendor/src/crfsuite/frontend/Makefile.am +29 -0
  135. data/core/vendor/src/crfsuite/frontend/Makefile.in +640 -0
  136. data/core/vendor/src/crfsuite/frontend/dump.c +116 -0
  137. data/core/vendor/src/crfsuite/frontend/frontend.vcxproj +129 -0
  138. data/core/vendor/src/crfsuite/frontend/iwa.c +273 -0
  139. data/core/vendor/src/crfsuite/frontend/iwa.h +65 -0
  140. data/core/vendor/src/crfsuite/frontend/learn.c +439 -0
  141. data/core/vendor/src/crfsuite/frontend/main.c +137 -0
  142. data/core/vendor/src/crfsuite/frontend/option.c +93 -0
  143. data/core/vendor/src/crfsuite/frontend/option.h +86 -0
  144. data/core/vendor/src/crfsuite/frontend/readdata.h +38 -0
  145. data/core/vendor/src/crfsuite/frontend/reader.c +136 -0
  146. data/core/vendor/src/crfsuite/frontend/tag.c +427 -0
  147. data/core/vendor/src/crfsuite/genbinary.sh.in +15 -0
  148. data/core/vendor/src/crfsuite/include/Makefile.am +11 -0
  149. data/core/vendor/src/crfsuite/include/Makefile.in +461 -0
  150. data/core/vendor/src/crfsuite/include/crfsuite.h +1063 -0
  151. data/core/vendor/src/crfsuite/include/crfsuite.hpp +555 -0
  152. data/core/vendor/src/crfsuite/include/crfsuite_api.hpp +400 -0
  153. data/core/vendor/src/crfsuite/include/os.h +61 -0
  154. data/core/vendor/src/crfsuite/install-sh +520 -0
  155. data/core/vendor/src/crfsuite/lib/cqdb/COPYING +28 -0
  156. data/core/vendor/src/crfsuite/lib/cqdb/Makefile.am +21 -0
  157. data/core/vendor/src/crfsuite/lib/cqdb/Makefile.in +549 -0
  158. data/core/vendor/src/crfsuite/lib/cqdb/cqdb.vcxproj +86 -0
  159. data/core/vendor/src/crfsuite/lib/cqdb/include/cqdb.h +524 -0
  160. data/core/vendor/src/crfsuite/lib/cqdb/src/cqdb.c +587 -0
  161. data/core/vendor/src/crfsuite/lib/cqdb/src/lookup3.c +976 -0
  162. data/core/vendor/src/crfsuite/lib/crf/Makefile.am +46 -0
  163. data/core/vendor/src/crfsuite/lib/crf/Makefile.in +721 -0
  164. data/core/vendor/src/crfsuite/lib/crf/crf.vcxproj +216 -0
  165. data/core/vendor/src/crfsuite/lib/crf/src/crf1d.h +353 -0
  166. data/core/vendor/src/crfsuite/lib/crf/src/crf1d_context.c +705 -0
  167. data/core/vendor/src/crfsuite/lib/crf/src/crf1d_encode.c +943 -0
  168. data/core/vendor/src/crfsuite/lib/crf/src/crf1d_feature.c +352 -0
  169. data/core/vendor/src/crfsuite/lib/crf/src/crf1d_model.c +994 -0
  170. data/core/vendor/src/crfsuite/lib/crf/src/crf1d_tag.c +550 -0
  171. data/core/vendor/src/crfsuite/lib/crf/src/crfsuite.c +492 -0
  172. data/core/vendor/src/crfsuite/lib/crf/src/crfsuite_internal.h +236 -0
  173. data/core/vendor/src/crfsuite/lib/crf/src/crfsuite_train.c +272 -0
  174. data/core/vendor/src/crfsuite/lib/crf/src/dataset.c +106 -0
  175. data/core/vendor/src/crfsuite/lib/crf/src/dictionary.c +118 -0
  176. data/core/vendor/src/crfsuite/lib/crf/src/holdout.c +80 -0
  177. data/core/vendor/src/crfsuite/lib/crf/src/logging.c +91 -0
  178. data/core/vendor/src/crfsuite/lib/crf/src/logging.h +48 -0
  179. data/core/vendor/src/crfsuite/lib/crf/src/params.c +335 -0
  180. data/core/vendor/src/crfsuite/lib/crf/src/params.h +80 -0
  181. data/core/vendor/src/crfsuite/lib/crf/src/quark.c +172 -0
  182. data/core/vendor/src/crfsuite/lib/crf/src/quark.h +46 -0
  183. data/core/vendor/src/crfsuite/lib/crf/src/rumavl.c +1107 -0
  184. data/core/vendor/src/crfsuite/lib/crf/src/rumavl.h +160 -0
  185. data/core/vendor/src/crfsuite/lib/crf/src/train_arow.c +408 -0
  186. data/core/vendor/src/crfsuite/lib/crf/src/train_averaged_perceptron.c +242 -0
  187. data/core/vendor/src/crfsuite/lib/crf/src/train_l2sgd.c +507 -0
  188. data/core/vendor/src/crfsuite/lib/crf/src/train_lbfgs.c +338 -0
  189. data/core/vendor/src/crfsuite/lib/crf/src/train_passive_aggressive.c +435 -0
  190. data/core/vendor/src/crfsuite/lib/crf/src/vecmath.h +341 -0
  191. data/core/vendor/src/crfsuite/ltmain.sh +8413 -0
  192. data/core/vendor/src/crfsuite/missing +376 -0
  193. data/core/vendor/src/crfsuite/swig/Makefile.am +13 -0
  194. data/core/vendor/src/crfsuite/swig/Makefile.in +365 -0
  195. data/core/vendor/src/crfsuite/swig/crfsuite.cpp +2 -0
  196. data/core/vendor/src/crfsuite/swig/export.i +32 -0
  197. data/core/vendor/src/crfsuite/swig/python/README +92 -0
  198. data/core/vendor/src/crfsuite/swig/python/crfsuite.py +329 -0
  199. data/core/vendor/src/crfsuite/swig/python/export_wrap.cpp +14355 -0
  200. data/core/vendor/src/crfsuite/swig/python/export_wrap.h +63 -0
  201. data/core/vendor/src/crfsuite/swig/python/prepare.sh +9 -0
  202. data/core/vendor/src/crfsuite/swig/python/sample_tag.py +52 -0
  203. data/core/vendor/src/crfsuite/swig/python/sample_train.py +68 -0
  204. data/core/vendor/src/crfsuite/swig/python/setup.py +44 -0
  205. data/core/vendor/src/crfsuite/win32/stdint.h +679 -0
  206. data/core/vendor/src/liblbfgs/AUTHORS +1 -0
  207. data/core/vendor/src/liblbfgs/COPYING +22 -0
  208. data/core/vendor/src/liblbfgs/ChangeLog +120 -0
  209. data/core/vendor/src/liblbfgs/INSTALL +231 -0
  210. data/core/vendor/src/liblbfgs/Makefile.am +10 -0
  211. data/core/vendor/src/liblbfgs/Makefile.in +638 -0
  212. data/core/vendor/src/liblbfgs/NEWS +0 -0
  213. data/core/vendor/src/liblbfgs/README +71 -0
  214. data/core/vendor/src/liblbfgs/aclocal.m4 +6985 -0
  215. data/core/vendor/src/liblbfgs/autogen.sh +38 -0
  216. data/core/vendor/src/liblbfgs/config.guess +1411 -0
  217. data/core/vendor/src/liblbfgs/config.h.in +64 -0
  218. data/core/vendor/src/liblbfgs/config.sub +1500 -0
  219. data/core/vendor/src/liblbfgs/configure +21146 -0
  220. data/core/vendor/src/liblbfgs/configure.in +107 -0
  221. data/core/vendor/src/liblbfgs/depcomp +522 -0
  222. data/core/vendor/src/liblbfgs/include/lbfgs.h +745 -0
  223. data/core/vendor/src/liblbfgs/install-sh +322 -0
  224. data/core/vendor/src/liblbfgs/lbfgs.sln +26 -0
  225. data/core/vendor/src/liblbfgs/lib/Makefile.am +24 -0
  226. data/core/vendor/src/liblbfgs/lib/Makefile.in +499 -0
  227. data/core/vendor/src/liblbfgs/lib/arithmetic_ansi.h +133 -0
  228. data/core/vendor/src/liblbfgs/lib/arithmetic_sse_double.h +294 -0
  229. data/core/vendor/src/liblbfgs/lib/arithmetic_sse_float.h +298 -0
  230. data/core/vendor/src/liblbfgs/lib/lbfgs.c +1371 -0
  231. data/core/vendor/src/liblbfgs/lib/lib.vcxproj +95 -0
  232. data/core/vendor/src/liblbfgs/ltmain.sh +6426 -0
  233. data/core/vendor/src/liblbfgs/missing +353 -0
  234. data/core/vendor/src/liblbfgs/sample/Makefile.am +15 -0
  235. data/core/vendor/src/liblbfgs/sample/Makefile.in +433 -0
  236. data/core/vendor/src/liblbfgs/sample/sample.c +81 -0
  237. data/core/vendor/src/liblbfgs/sample/sample.cpp +126 -0
  238. data/core/vendor/src/liblbfgs/sample/sample.vcxproj +105 -0
  239. data/core/vendor/src/svm_light/LICENSE.txt +59 -0
  240. data/core/vendor/src/svm_light/Makefile +105 -0
  241. data/core/vendor/src/svm_light/kernel.h +40 -0
  242. data/core/vendor/src/svm_light/svm_classify.c +197 -0
  243. data/core/vendor/src/svm_light/svm_common.c +985 -0
  244. data/core/vendor/src/svm_light/svm_common.h +301 -0
  245. data/core/vendor/src/svm_light/svm_hideo.c +1062 -0
  246. data/core/vendor/src/svm_light/svm_learn.c +4147 -0
  247. data/core/vendor/src/svm_light/svm_learn.h +169 -0
  248. data/core/vendor/src/svm_light/svm_learn_main.c +397 -0
  249. data/core/vendor/src/svm_light/svm_loqo.c +211 -0
  250. data/ext/hack/Rakefile +17 -0
  251. data/ext/hack/support.rb +88 -0
  252. data/lib/opener/opinion_detectors/base.rb +112 -0
  253. data/lib/opener/opinion_detectors/base/version.rb +7 -0
  254. data/lib/opener/opinion_detectors/configuration_creator.rb +86 -0
  255. data/lib/opener/opinion_detectors/de.rb +7 -0
  256. data/lib/opener/opinion_detectors/en.rb +7 -0
  257. data/lib/opener/opinion_detectors/it.rb +7 -0
  258. data/lib/opener/opinion_detectors/nl.rb +6 -0
  259. data/opener-opinion-detector-base.gemspec +35 -0
  260. data/pre_build_requirements.txt +3 -0
  261. metadata +374 -0
@@ -0,0 +1,1371 @@
1
+ /*
2
+ * Limited memory BFGS (L-BFGS).
3
+ *
4
+ * Copyright (c) 1990, Jorge Nocedal
5
+ * Copyright (c) 2007-2010 Naoaki Okazaki
6
+ * All rights reserved.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ /* $Id$ */
28
+
29
+ /*
30
+ This library is a C port of the FORTRAN implementation of Limited-memory
31
+ Broyden-Fletcher-Goldfarb-Shanno (L-BFGS) method written by Jorge Nocedal.
32
+ The original FORTRAN source code is available at:
33
+ http://www.ece.northwestern.edu/~nocedal/lbfgs.html
34
+
35
+ The L-BFGS algorithm is described in:
36
+ - Jorge Nocedal.
37
+ Updating Quasi-Newton Matrices with Limited Storage.
38
+ <i>Mathematics of Computation</i>, Vol. 35, No. 151, pp. 773--782, 1980.
39
+ - Dong C. Liu and Jorge Nocedal.
40
+ On the limited memory BFGS method for large scale optimization.
41
+ <i>Mathematical Programming</i> B, Vol. 45, No. 3, pp. 503-528, 1989.
42
+
43
+ The line search algorithms used in this implementation are described in:
44
+ - John E. Dennis and Robert B. Schnabel.
45
+ <i>Numerical Methods for Unconstrained Optimization and Nonlinear
46
+ Equations</i>, Englewood Cliffs, 1983.
47
+ - Jorge J. More and David J. Thuente.
48
+ Line search algorithm with guaranteed sufficient decrease.
49
+ <i>ACM Transactions on Mathematical Software (TOMS)</i>, Vol. 20, No. 3,
50
+ pp. 286-307, 1994.
51
+
52
+ This library also implements Orthant-Wise Limited-memory Quasi-Newton (OWL-QN)
53
+ method presented in:
54
+ - Galen Andrew and Jianfeng Gao.
55
+ Scalable training of L1-regularized log-linear models.
56
+ In <i>Proceedings of the 24th International Conference on Machine
57
+ Learning (ICML 2007)</i>, pp. 33-40, 2007.
58
+
59
+ I would like to thank the original author, Jorge Nocedal, who has been
60
+ distributing the effieicnt and explanatory implementation in an open source
61
+ licence.
62
+ */
63
+
64
+ #ifdef HAVE_CONFIG_H
65
+ #include <config.h>
66
+ #endif/*HAVE_CONFIG_H*/
67
+
68
+ #include <stdint.h>
69
+ #include <stdio.h>
70
+ #include <stdlib.h>
71
+ #include <math.h>
72
+
73
+ #include <lbfgs.h>
74
+
75
+ #ifdef _MSC_VER
76
+ #define inline __inline
77
+ #endif/*_MSC_VER*/
78
+
79
+ #if defined(USE_SSE) && defined(__SSE2__) && LBFGS_FLOAT == 64
80
+ /* Use SSE2 optimization for 64bit double precision. */
81
+ #include "arithmetic_sse_double.h"
82
+
83
+ #elif defined(USE_SSE) && defined(__SSE__) && LBFGS_FLOAT == 32
84
+ /* Use SSE optimization for 32bit float precision. */
85
+ #include "arithmetic_sse_float.h"
86
+
87
+ #else
88
+ /* No CPU specific optimization. */
89
+ #include "arithmetic_ansi.h"
90
+
91
+ #endif
92
+
93
+ #define min2(a, b) ((a) <= (b) ? (a) : (b))
94
+ #define max2(a, b) ((a) >= (b) ? (a) : (b))
95
+ #define max3(a, b, c) max2(max2((a), (b)), (c));
96
+
97
+ struct tag_callback_data {
98
+ int n;
99
+ void *instance;
100
+ lbfgs_evaluate_t proc_evaluate;
101
+ lbfgs_progress_t proc_progress;
102
+ };
103
+ typedef struct tag_callback_data callback_data_t;
104
+
105
+ struct tag_iteration_data {
106
+ lbfgsfloatval_t alpha;
107
+ lbfgsfloatval_t *s; /* [n] */
108
+ lbfgsfloatval_t *y; /* [n] */
109
+ lbfgsfloatval_t ys; /* vecdot(y, s) */
110
+ };
111
+ typedef struct tag_iteration_data iteration_data_t;
112
+
113
+ static const lbfgs_parameter_t _defparam = {
114
+ 6, 1e-5, 0, 1e-5,
115
+ 0, LBFGS_LINESEARCH_DEFAULT, 40,
116
+ 1e-20, 1e20, 1e-4, 0.9, 0.9, 1.0e-16,
117
+ 0.0, 0, -1,
118
+ };
119
+
120
+ /* Forward function declarations. */
121
+
122
+ typedef int (*line_search_proc)(
123
+ int n,
124
+ lbfgsfloatval_t *x,
125
+ lbfgsfloatval_t *f,
126
+ lbfgsfloatval_t *g,
127
+ lbfgsfloatval_t *s,
128
+ lbfgsfloatval_t *stp,
129
+ const lbfgsfloatval_t* xp,
130
+ const lbfgsfloatval_t* gp,
131
+ lbfgsfloatval_t *wa,
132
+ callback_data_t *cd,
133
+ const lbfgs_parameter_t *param
134
+ );
135
+
136
+ static int line_search_backtracking(
137
+ int n,
138
+ lbfgsfloatval_t *x,
139
+ lbfgsfloatval_t *f,
140
+ lbfgsfloatval_t *g,
141
+ lbfgsfloatval_t *s,
142
+ lbfgsfloatval_t *stp,
143
+ const lbfgsfloatval_t* xp,
144
+ const lbfgsfloatval_t* gp,
145
+ lbfgsfloatval_t *wa,
146
+ callback_data_t *cd,
147
+ const lbfgs_parameter_t *param
148
+ );
149
+
150
+ static int line_search_backtracking_owlqn(
151
+ int n,
152
+ lbfgsfloatval_t *x,
153
+ lbfgsfloatval_t *f,
154
+ lbfgsfloatval_t *g,
155
+ lbfgsfloatval_t *s,
156
+ lbfgsfloatval_t *stp,
157
+ const lbfgsfloatval_t* xp,
158
+ const lbfgsfloatval_t* gp,
159
+ lbfgsfloatval_t *wp,
160
+ callback_data_t *cd,
161
+ const lbfgs_parameter_t *param
162
+ );
163
+
164
+ static int line_search_morethuente(
165
+ int n,
166
+ lbfgsfloatval_t *x,
167
+ lbfgsfloatval_t *f,
168
+ lbfgsfloatval_t *g,
169
+ lbfgsfloatval_t *s,
170
+ lbfgsfloatval_t *stp,
171
+ const lbfgsfloatval_t* xp,
172
+ const lbfgsfloatval_t* gp,
173
+ lbfgsfloatval_t *wa,
174
+ callback_data_t *cd,
175
+ const lbfgs_parameter_t *param
176
+ );
177
+
178
+ static int update_trial_interval(
179
+ lbfgsfloatval_t *x,
180
+ lbfgsfloatval_t *fx,
181
+ lbfgsfloatval_t *dx,
182
+ lbfgsfloatval_t *y,
183
+ lbfgsfloatval_t *fy,
184
+ lbfgsfloatval_t *dy,
185
+ lbfgsfloatval_t *t,
186
+ lbfgsfloatval_t *ft,
187
+ lbfgsfloatval_t *dt,
188
+ const lbfgsfloatval_t tmin,
189
+ const lbfgsfloatval_t tmax,
190
+ int *brackt
191
+ );
192
+
193
+ static lbfgsfloatval_t owlqn_x1norm(
194
+ const lbfgsfloatval_t* x,
195
+ const int start,
196
+ const int n
197
+ );
198
+
199
+ static void owlqn_pseudo_gradient(
200
+ lbfgsfloatval_t* pg,
201
+ const lbfgsfloatval_t* x,
202
+ const lbfgsfloatval_t* g,
203
+ const int n,
204
+ const lbfgsfloatval_t c,
205
+ const int start,
206
+ const int end
207
+ );
208
+
209
+ static void owlqn_project(
210
+ lbfgsfloatval_t* d,
211
+ const lbfgsfloatval_t* sign,
212
+ const int start,
213
+ const int end
214
+ );
215
+
216
+
217
+ #if defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
218
+ static int round_out_variables(int n)
219
+ {
220
+ n += 7;
221
+ n /= 8;
222
+ n *= 8;
223
+ return n;
224
+ }
225
+ #endif/*defined(USE_SSE)*/
226
+
227
+ lbfgsfloatval_t* lbfgs_malloc(int n)
228
+ {
229
+ #if defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
230
+ n = round_out_variables(n);
231
+ #endif/*defined(USE_SSE)*/
232
+ return (lbfgsfloatval_t*)vecalloc(sizeof(lbfgsfloatval_t) * n);
233
+ }
234
+
235
+ void lbfgs_free(lbfgsfloatval_t *x)
236
+ {
237
+ vecfree(x);
238
+ }
239
+
240
+ void lbfgs_parameter_init(lbfgs_parameter_t *param)
241
+ {
242
+ memcpy(param, &_defparam, sizeof(*param));
243
+ }
244
+
245
+ int lbfgs(
246
+ int n,
247
+ lbfgsfloatval_t *x,
248
+ lbfgsfloatval_t *ptr_fx,
249
+ lbfgs_evaluate_t proc_evaluate,
250
+ lbfgs_progress_t proc_progress,
251
+ void *instance,
252
+ lbfgs_parameter_t *_param
253
+ )
254
+ {
255
+ int ret;
256
+ int i, j, k, ls, end, bound;
257
+ lbfgsfloatval_t step;
258
+
259
+ /* Constant parameters and their default values. */
260
+ lbfgs_parameter_t param = (_param != NULL) ? (*_param) : _defparam;
261
+ const int m = param.m;
262
+
263
+ lbfgsfloatval_t *xp = NULL;
264
+ lbfgsfloatval_t *g = NULL, *gp = NULL, *pg = NULL;
265
+ lbfgsfloatval_t *d = NULL, *w = NULL, *pf = NULL;
266
+ iteration_data_t *lm = NULL, *it = NULL;
267
+ lbfgsfloatval_t ys, yy;
268
+ lbfgsfloatval_t xnorm, gnorm, beta;
269
+ lbfgsfloatval_t fx = 0.;
270
+ lbfgsfloatval_t rate = 0.;
271
+ line_search_proc linesearch = line_search_morethuente;
272
+
273
+ /* Construct a callback data. */
274
+ callback_data_t cd;
275
+ cd.n = n;
276
+ cd.instance = instance;
277
+ cd.proc_evaluate = proc_evaluate;
278
+ cd.proc_progress = proc_progress;
279
+
280
+ #if defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
281
+ /* Round out the number of variables. */
282
+ n = round_out_variables(n);
283
+ #endif/*defined(USE_SSE)*/
284
+
285
+ /* Check the input parameters for errors. */
286
+ if (n <= 0) {
287
+ return LBFGSERR_INVALID_N;
288
+ }
289
+ #if defined(USE_SSE) && (defined(__SSE__) || defined(__SSE2__))
290
+ if (n % 8 != 0) {
291
+ return LBFGSERR_INVALID_N_SSE;
292
+ }
293
+ if ((uintptr_t)(const void*)x % 16 != 0) {
294
+ return LBFGSERR_INVALID_X_SSE;
295
+ }
296
+ #endif/*defined(USE_SSE)*/
297
+ if (param.epsilon < 0.) {
298
+ return LBFGSERR_INVALID_EPSILON;
299
+ }
300
+ if (param.past < 0) {
301
+ return LBFGSERR_INVALID_TESTPERIOD;
302
+ }
303
+ if (param.delta < 0.) {
304
+ return LBFGSERR_INVALID_DELTA;
305
+ }
306
+ if (param.min_step < 0.) {
307
+ return LBFGSERR_INVALID_MINSTEP;
308
+ }
309
+ if (param.max_step < param.min_step) {
310
+ return LBFGSERR_INVALID_MAXSTEP;
311
+ }
312
+ if (param.ftol < 0.) {
313
+ return LBFGSERR_INVALID_FTOL;
314
+ }
315
+ if (param.linesearch == LBFGS_LINESEARCH_BACKTRACKING_WOLFE ||
316
+ param.linesearch == LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE) {
317
+ if (param.wolfe <= param.ftol || 1. <= param.wolfe) {
318
+ return LBFGSERR_INVALID_WOLFE;
319
+ }
320
+ }
321
+ if (param.gtol < 0.) {
322
+ return LBFGSERR_INVALID_GTOL;
323
+ }
324
+ if (param.xtol < 0.) {
325
+ return LBFGSERR_INVALID_XTOL;
326
+ }
327
+ if (param.max_linesearch <= 0) {
328
+ return LBFGSERR_INVALID_MAXLINESEARCH;
329
+ }
330
+ if (param.orthantwise_c < 0.) {
331
+ return LBFGSERR_INVALID_ORTHANTWISE;
332
+ }
333
+ if (param.orthantwise_start < 0 || n < param.orthantwise_start) {
334
+ return LBFGSERR_INVALID_ORTHANTWISE_START;
335
+ }
336
+ if (param.orthantwise_end < 0) {
337
+ param.orthantwise_end = n;
338
+ }
339
+ if (n < param.orthantwise_end) {
340
+ return LBFGSERR_INVALID_ORTHANTWISE_END;
341
+ }
342
+ if (param.orthantwise_c != 0.) {
343
+ switch (param.linesearch) {
344
+ case LBFGS_LINESEARCH_BACKTRACKING:
345
+ linesearch = line_search_backtracking_owlqn;
346
+ break;
347
+ default:
348
+ /* Only the backtracking method is available. */
349
+ return LBFGSERR_INVALID_LINESEARCH;
350
+ }
351
+ } else {
352
+ switch (param.linesearch) {
353
+ case LBFGS_LINESEARCH_MORETHUENTE:
354
+ linesearch = line_search_morethuente;
355
+ break;
356
+ case LBFGS_LINESEARCH_BACKTRACKING_ARMIJO:
357
+ case LBFGS_LINESEARCH_BACKTRACKING_WOLFE:
358
+ case LBFGS_LINESEARCH_BACKTRACKING_STRONG_WOLFE:
359
+ linesearch = line_search_backtracking;
360
+ break;
361
+ default:
362
+ return LBFGSERR_INVALID_LINESEARCH;
363
+ }
364
+ }
365
+
366
+ /* Allocate working space. */
367
+ xp = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
368
+ g = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
369
+ gp = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
370
+ d = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
371
+ w = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
372
+ if (xp == NULL || g == NULL || gp == NULL || d == NULL || w == NULL) {
373
+ ret = LBFGSERR_OUTOFMEMORY;
374
+ goto lbfgs_exit;
375
+ }
376
+
377
+ if (param.orthantwise_c != 0.) {
378
+ /* Allocate working space for OW-LQN. */
379
+ pg = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
380
+ if (pg == NULL) {
381
+ ret = LBFGSERR_OUTOFMEMORY;
382
+ goto lbfgs_exit;
383
+ }
384
+ }
385
+
386
+ /* Allocate limited memory storage. */
387
+ lm = (iteration_data_t*)vecalloc(m * sizeof(iteration_data_t));
388
+ if (lm == NULL) {
389
+ ret = LBFGSERR_OUTOFMEMORY;
390
+ goto lbfgs_exit;
391
+ }
392
+
393
+ /* Initialize the limited memory. */
394
+ for (i = 0;i < m;++i) {
395
+ it = &lm[i];
396
+ it->alpha = 0;
397
+ it->ys = 0;
398
+ it->s = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
399
+ it->y = (lbfgsfloatval_t*)vecalloc(n * sizeof(lbfgsfloatval_t));
400
+ if (it->s == NULL || it->y == NULL) {
401
+ ret = LBFGSERR_OUTOFMEMORY;
402
+ goto lbfgs_exit;
403
+ }
404
+ }
405
+
406
+ /* Allocate an array for storing previous values of the objective function. */
407
+ if (0 < param.past) {
408
+ pf = (lbfgsfloatval_t*)vecalloc(param.past * sizeof(lbfgsfloatval_t));
409
+ }
410
+
411
+ /* Evaluate the function value and its gradient. */
412
+ fx = cd.proc_evaluate(cd.instance, x, g, cd.n, 0);
413
+ if (0. != param.orthantwise_c) {
414
+ /* Compute the L1 norm of the variable and add it to the object value. */
415
+ xnorm = owlqn_x1norm(x, param.orthantwise_start, param.orthantwise_end);
416
+ fx += xnorm * param.orthantwise_c;
417
+ owlqn_pseudo_gradient(
418
+ pg, x, g, n,
419
+ param.orthantwise_c, param.orthantwise_start, param.orthantwise_end
420
+ );
421
+ }
422
+
423
+ /* Store the initial value of the objective function. */
424
+ if (pf != NULL) {
425
+ pf[0] = fx;
426
+ }
427
+
428
+ /*
429
+ Compute the direction;
430
+ we assume the initial hessian matrix H_0 as the identity matrix.
431
+ */
432
+ if (param.orthantwise_c == 0.) {
433
+ vecncpy(d, g, n);
434
+ } else {
435
+ vecncpy(d, pg, n);
436
+ }
437
+
438
+ /*
439
+ Make sure that the initial variables are not a minimizer.
440
+ */
441
+ vec2norm(&xnorm, x, n);
442
+ if (param.orthantwise_c == 0.) {
443
+ vec2norm(&gnorm, g, n);
444
+ } else {
445
+ vec2norm(&gnorm, pg, n);
446
+ }
447
+ if (xnorm < 1.0) xnorm = 1.0;
448
+ if (gnorm / xnorm <= param.epsilon) {
449
+ ret = LBFGS_ALREADY_MINIMIZED;
450
+ goto lbfgs_exit;
451
+ }
452
+
453
+ /* Compute the initial step:
454
+ step = 1.0 / sqrt(vecdot(d, d, n))
455
+ */
456
+ vec2norminv(&step, d, n);
457
+
458
+ k = 1;
459
+ end = 0;
460
+ for (;;) {
461
+ /* Store the current position and gradient vectors. */
462
+ veccpy(xp, x, n);
463
+ veccpy(gp, g, n);
464
+
465
+ /* Search for an optimal step. */
466
+ if (param.orthantwise_c == 0.) {
467
+ ls = linesearch(n, x, &fx, g, d, &step, xp, gp, w, &cd, &param);
468
+ } else {
469
+ ls = linesearch(n, x, &fx, g, d, &step, xp, pg, w, &cd, &param);
470
+ owlqn_pseudo_gradient(
471
+ pg, x, g, n,
472
+ param.orthantwise_c, param.orthantwise_start, param.orthantwise_end
473
+ );
474
+ }
475
+ if (ls < 0) {
476
+ /* Revert to the previous point. */
477
+ veccpy(x, xp, n);
478
+ veccpy(g, gp, n);
479
+ ret = ls;
480
+ goto lbfgs_exit;
481
+ }
482
+
483
+ /* Compute x and g norms. */
484
+ vec2norm(&xnorm, x, n);
485
+ if (param.orthantwise_c == 0.) {
486
+ vec2norm(&gnorm, g, n);
487
+ } else {
488
+ vec2norm(&gnorm, pg, n);
489
+ }
490
+
491
+ /* Report the progress. */
492
+ if (cd.proc_progress) {
493
+ if ((ret = cd.proc_progress(cd.instance, x, g, fx, xnorm, gnorm, step, cd.n, k, ls))) {
494
+ goto lbfgs_exit;
495
+ }
496
+ }
497
+
498
+ /*
499
+ Convergence test.
500
+ The criterion is given by the following formula:
501
+ |g(x)| / \max(1, |x|) < \epsilon
502
+ */
503
+ if (xnorm < 1.0) xnorm = 1.0;
504
+ if (gnorm / xnorm <= param.epsilon) {
505
+ /* Convergence. */
506
+ ret = LBFGS_SUCCESS;
507
+ break;
508
+ }
509
+
510
+ /*
511
+ Test for stopping criterion.
512
+ The criterion is given by the following formula:
513
+ (f(past_x) - f(x)) / f(x) < \delta
514
+ */
515
+ if (pf != NULL) {
516
+ /* We don't test the stopping criterion while k < past. */
517
+ if (param.past <= k) {
518
+ /* Compute the relative improvement from the past. */
519
+ rate = (pf[k % param.past] - fx) / fx;
520
+
521
+ /* The stopping criterion. */
522
+ if (rate < param.delta) {
523
+ ret = LBFGS_STOP;
524
+ break;
525
+ }
526
+ }
527
+
528
+ /* Store the current value of the objective function. */
529
+ pf[k % param.past] = fx;
530
+ }
531
+
532
+ if (param.max_iterations != 0 && param.max_iterations < k+1) {
533
+ /* Maximum number of iterations. */
534
+ ret = LBFGSERR_MAXIMUMITERATION;
535
+ break;
536
+ }
537
+
538
+ /*
539
+ Update vectors s and y:
540
+ s_{k+1} = x_{k+1} - x_{k} = \step * d_{k}.
541
+ y_{k+1} = g_{k+1} - g_{k}.
542
+ */
543
+ it = &lm[end];
544
+ vecdiff(it->s, x, xp, n);
545
+ vecdiff(it->y, g, gp, n);
546
+
547
+ /*
548
+ Compute scalars ys and yy:
549
+ ys = y^t \cdot s = 1 / \rho.
550
+ yy = y^t \cdot y.
551
+ Notice that yy is used for scaling the hessian matrix H_0 (Cholesky factor).
552
+ */
553
+ vecdot(&ys, it->y, it->s, n);
554
+ vecdot(&yy, it->y, it->y, n);
555
+ it->ys = ys;
556
+
557
+ /*
558
+ Recursive formula to compute dir = -(H \cdot g).
559
+ This is described in page 779 of:
560
+ Jorge Nocedal.
561
+ Updating Quasi-Newton Matrices with Limited Storage.
562
+ Mathematics of Computation, Vol. 35, No. 151,
563
+ pp. 773--782, 1980.
564
+ */
565
+ bound = (m <= k) ? m : k;
566
+ ++k;
567
+ end = (end + 1) % m;
568
+
569
+ /* Compute the steepest direction. */
570
+ if (param.orthantwise_c == 0.) {
571
+ /* Compute the negative of gradients. */
572
+ vecncpy(d, g, n);
573
+ } else {
574
+ vecncpy(d, pg, n);
575
+ }
576
+
577
+ j = end;
578
+ for (i = 0;i < bound;++i) {
579
+ j = (j + m - 1) % m; /* if (--j == -1) j = m-1; */
580
+ it = &lm[j];
581
+ /* \alpha_{j} = \rho_{j} s^{t}_{j} \cdot q_{k+1}. */
582
+ vecdot(&it->alpha, it->s, d, n);
583
+ it->alpha /= it->ys;
584
+ /* q_{i} = q_{i+1} - \alpha_{i} y_{i}. */
585
+ vecadd(d, it->y, -it->alpha, n);
586
+ }
587
+
588
+ vecscale(d, ys / yy, n);
589
+
590
+ for (i = 0;i < bound;++i) {
591
+ it = &lm[j];
592
+ /* \beta_{j} = \rho_{j} y^t_{j} \cdot \gamma_{i}. */
593
+ vecdot(&beta, it->y, d, n);
594
+ beta /= it->ys;
595
+ /* \gamma_{i+1} = \gamma_{i} + (\alpha_{j} - \beta_{j}) s_{j}. */
596
+ vecadd(d, it->s, it->alpha - beta, n);
597
+ j = (j + 1) % m; /* if (++j == m) j = 0; */
598
+ }
599
+
600
+ /*
601
+ Constrain the search direction for orthant-wise updates.
602
+ */
603
+ if (param.orthantwise_c != 0.) {
604
+ for (i = param.orthantwise_start;i < param.orthantwise_end;++i) {
605
+ if (d[i] * pg[i] >= 0) {
606
+ d[i] = 0;
607
+ }
608
+ }
609
+ }
610
+
611
+ /*
612
+ Now the search direction d is ready. We try step = 1 first.
613
+ */
614
+ step = 1.0;
615
+ }
616
+
617
+ lbfgs_exit:
618
+ /* Return the final value of the objective function. */
619
+ if (ptr_fx != NULL) {
620
+ *ptr_fx = fx;
621
+ }
622
+
623
+ vecfree(pf);
624
+
625
+ /* Free memory blocks used by this function. */
626
+ if (lm != NULL) {
627
+ for (i = 0;i < m;++i) {
628
+ vecfree(lm[i].s);
629
+ vecfree(lm[i].y);
630
+ }
631
+ vecfree(lm);
632
+ }
633
+ vecfree(pg);
634
+ vecfree(w);
635
+ vecfree(d);
636
+ vecfree(gp);
637
+ vecfree(g);
638
+ vecfree(xp);
639
+
640
+ return ret;
641
+ }
642
+
643
+
644
+
645
+ static int line_search_backtracking(
646
+ int n,
647
+ lbfgsfloatval_t *x,
648
+ lbfgsfloatval_t *f,
649
+ lbfgsfloatval_t *g,
650
+ lbfgsfloatval_t *s,
651
+ lbfgsfloatval_t *stp,
652
+ const lbfgsfloatval_t* xp,
653
+ const lbfgsfloatval_t* gp,
654
+ lbfgsfloatval_t *wp,
655
+ callback_data_t *cd,
656
+ const lbfgs_parameter_t *param
657
+ )
658
+ {
659
+ int count = 0;
660
+ lbfgsfloatval_t width, dg;
661
+ lbfgsfloatval_t finit, dginit = 0., dgtest;
662
+ const lbfgsfloatval_t dec = 0.5, inc = 2.1;
663
+
664
+ /* Check the input parameters for errors. */
665
+ if (*stp <= 0.) {
666
+ return LBFGSERR_INVALIDPARAMETERS;
667
+ }
668
+
669
+ /* Compute the initial gradient in the search direction. */
670
+ vecdot(&dginit, g, s, n);
671
+
672
+ /* Make sure that s points to a descent direction. */
673
+ if (0 < dginit) {
674
+ return LBFGSERR_INCREASEGRADIENT;
675
+ }
676
+
677
+ /* The initial value of the objective function. */
678
+ finit = *f;
679
+ dgtest = param->ftol * dginit;
680
+
681
+ for (;;) {
682
+ veccpy(x, xp, n);
683
+ vecadd(x, s, *stp, n);
684
+
685
+ /* Evaluate the function and gradient values. */
686
+ *f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);
687
+
688
+ ++count;
689
+
690
+ if (*f > finit + *stp * dgtest) {
691
+ width = dec;
692
+ } else {
693
+ /* The sufficient decrease condition (Armijo condition). */
694
+ if (param->linesearch == LBFGS_LINESEARCH_BACKTRACKING_ARMIJO) {
695
+ /* Exit with the Armijo condition. */
696
+ return count;
697
+ }
698
+
699
+ /* Check the Wolfe condition. */
700
+ vecdot(&dg, g, s, n);
701
+ if (dg < param->wolfe * dginit) {
702
+ width = inc;
703
+ } else {
704
+ if(param->linesearch == LBFGS_LINESEARCH_BACKTRACKING_WOLFE) {
705
+ /* Exit with the regular Wolfe condition. */
706
+ return count;
707
+ }
708
+
709
+ /* Check the strong Wolfe condition. */
710
+ if(dg > -param->wolfe * dginit) {
711
+ width = dec;
712
+ } else {
713
+ /* Exit with the strong Wolfe condition. */
714
+ return count;
715
+ }
716
+ }
717
+ }
718
+
719
+ if (*stp < param->min_step) {
720
+ /* The step is the minimum value. */
721
+ return LBFGSERR_MINIMUMSTEP;
722
+ }
723
+ if (*stp > param->max_step) {
724
+ /* The step is the maximum value. */
725
+ return LBFGSERR_MAXIMUMSTEP;
726
+ }
727
+ if (param->max_linesearch <= count) {
728
+ /* Maximum number of iteration. */
729
+ return LBFGSERR_MAXIMUMLINESEARCH;
730
+ }
731
+
732
+ (*stp) *= width;
733
+ }
734
+ }
735
+
736
+
737
+
738
+ static int line_search_backtracking_owlqn(
739
+ int n,
740
+ lbfgsfloatval_t *x,
741
+ lbfgsfloatval_t *f,
742
+ lbfgsfloatval_t *g,
743
+ lbfgsfloatval_t *s,
744
+ lbfgsfloatval_t *stp,
745
+ const lbfgsfloatval_t* xp,
746
+ const lbfgsfloatval_t* gp,
747
+ lbfgsfloatval_t *wp,
748
+ callback_data_t *cd,
749
+ const lbfgs_parameter_t *param
750
+ )
751
+ {
752
+ int i, count = 0;
753
+ lbfgsfloatval_t width = 0.5, norm = 0.;
754
+ lbfgsfloatval_t finit = *f, dgtest;
755
+
756
+ /* Check the input parameters for errors. */
757
+ if (*stp <= 0.) {
758
+ return LBFGSERR_INVALIDPARAMETERS;
759
+ }
760
+
761
+ /* Choose the orthant for the new point. */
762
+ for (i = 0;i < n;++i) {
763
+ wp[i] = (xp[i] == 0.) ? -gp[i] : xp[i];
764
+ }
765
+
766
+ for (;;) {
767
+ /* Update the current point. */
768
+ veccpy(x, xp, n);
769
+ vecadd(x, s, *stp, n);
770
+
771
+ /* The current point is projected onto the orthant. */
772
+ owlqn_project(x, wp, param->orthantwise_start, param->orthantwise_end);
773
+
774
+ /* Evaluate the function and gradient values. */
775
+ *f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);
776
+
777
+ /* Compute the L1 norm of the variables and add it to the object value. */
778
+ norm = owlqn_x1norm(x, param->orthantwise_start, param->orthantwise_end);
779
+ *f += norm * param->orthantwise_c;
780
+
781
+ ++count;
782
+
783
+ dgtest = 0.;
784
+ for (i = 0;i < n;++i) {
785
+ dgtest += (x[i] - xp[i]) * gp[i];
786
+ }
787
+
788
+ if (*f <= finit + param->ftol * dgtest) {
789
+ /* The sufficient decrease condition. */
790
+ return count;
791
+ }
792
+
793
+ if (*stp < param->min_step) {
794
+ /* The step is the minimum value. */
795
+ return LBFGSERR_MINIMUMSTEP;
796
+ }
797
+ if (*stp > param->max_step) {
798
+ /* The step is the maximum value. */
799
+ return LBFGSERR_MAXIMUMSTEP;
800
+ }
801
+ if (param->max_linesearch <= count) {
802
+ /* Maximum number of iteration. */
803
+ return LBFGSERR_MAXIMUMLINESEARCH;
804
+ }
805
+
806
+ (*stp) *= width;
807
+ }
808
+ }
809
+
810
+
811
+
812
+ static int line_search_morethuente(
813
+ int n,
814
+ lbfgsfloatval_t *x,
815
+ lbfgsfloatval_t *f,
816
+ lbfgsfloatval_t *g,
817
+ lbfgsfloatval_t *s,
818
+ lbfgsfloatval_t *stp,
819
+ const lbfgsfloatval_t* xp,
820
+ const lbfgsfloatval_t* gp,
821
+ lbfgsfloatval_t *wa,
822
+ callback_data_t *cd,
823
+ const lbfgs_parameter_t *param
824
+ )
825
+ {
826
+ int count = 0;
827
+ int brackt, stage1, uinfo = 0;
828
+ lbfgsfloatval_t dg;
829
+ lbfgsfloatval_t stx, fx, dgx;
830
+ lbfgsfloatval_t sty, fy, dgy;
831
+ lbfgsfloatval_t fxm, dgxm, fym, dgym, fm, dgm;
832
+ lbfgsfloatval_t finit, ftest1, dginit, dgtest;
833
+ lbfgsfloatval_t width, prev_width;
834
+ lbfgsfloatval_t stmin, stmax;
835
+
836
+ /* Check the input parameters for errors. */
837
+ if (*stp <= 0.) {
838
+ return LBFGSERR_INVALIDPARAMETERS;
839
+ }
840
+
841
+ /* Compute the initial gradient in the search direction. */
842
+ vecdot(&dginit, g, s, n);
843
+
844
+ /* Make sure that s points to a descent direction. */
845
+ if (0 < dginit) {
846
+ return LBFGSERR_INCREASEGRADIENT;
847
+ }
848
+
849
+ /* Initialize local variables. */
850
+ brackt = 0;
851
+ stage1 = 1;
852
+ finit = *f;
853
+ dgtest = param->ftol * dginit;
854
+ width = param->max_step - param->min_step;
855
+ prev_width = 2.0 * width;
856
+
857
+ /*
858
+ The variables stx, fx, dgx contain the values of the step,
859
+ function, and directional derivative at the best step.
860
+ The variables sty, fy, dgy contain the value of the step,
861
+ function, and derivative at the other endpoint of
862
+ the interval of uncertainty.
863
+ The variables stp, f, dg contain the values of the step,
864
+ function, and derivative at the current step.
865
+ */
866
+ stx = sty = 0.;
867
+ fx = fy = finit;
868
+ dgx = dgy = dginit;
869
+
870
+ for (;;) {
871
+ /*
872
+ Set the minimum and maximum steps to correspond to the
873
+ present interval of uncertainty.
874
+ */
875
+ if (brackt) {
876
+ stmin = min2(stx, sty);
877
+ stmax = max2(stx, sty);
878
+ } else {
879
+ stmin = stx;
880
+ stmax = *stp + 4.0 * (*stp - stx);
881
+ }
882
+
883
+ /* Clip the step in the range of [stpmin, stpmax]. */
884
+ if (*stp < param->min_step) *stp = param->min_step;
885
+ if (param->max_step < *stp) *stp = param->max_step;
886
+
887
+ /*
888
+ If an unusual termination is to occur then let
889
+ stp be the lowest point obtained so far.
890
+ */
891
+ if ((brackt && ((*stp <= stmin || stmax <= *stp) || param->max_linesearch <= count + 1 || uinfo != 0)) || (brackt && (stmax - stmin <= param->xtol * stmax))) {
892
+ *stp = stx;
893
+ }
894
+
895
+ /*
896
+ Compute the current value of x:
897
+ x <- x + (*stp) * s.
898
+ */
899
+ veccpy(x, xp, n);
900
+ vecadd(x, s, *stp, n);
901
+
902
+ /* Evaluate the function and gradient values. */
903
+ *f = cd->proc_evaluate(cd->instance, x, g, cd->n, *stp);
904
+ vecdot(&dg, g, s, n);
905
+
906
+ ftest1 = finit + *stp * dgtest;
907
+ ++count;
908
+
909
+ /* Test for errors and convergence. */
910
+ if (brackt && ((*stp <= stmin || stmax <= *stp) || uinfo != 0)) {
911
+ /* Rounding errors prevent further progress. */
912
+ return LBFGSERR_ROUNDING_ERROR;
913
+ }
914
+ if (*stp == param->max_step && *f <= ftest1 && dg <= dgtest) {
915
+ /* The step is the maximum value. */
916
+ return LBFGSERR_MAXIMUMSTEP;
917
+ }
918
+ if (*stp == param->min_step && (ftest1 < *f || dgtest <= dg)) {
919
+ /* The step is the minimum value. */
920
+ return LBFGSERR_MINIMUMSTEP;
921
+ }
922
+ if (brackt && (stmax - stmin) <= param->xtol * stmax) {
923
+ /* Relative width of the interval of uncertainty is at most xtol. */
924
+ return LBFGSERR_WIDTHTOOSMALL;
925
+ }
926
+ if (param->max_linesearch <= count) {
927
+ /* Maximum number of iteration. */
928
+ return LBFGSERR_MAXIMUMLINESEARCH;
929
+ }
930
+ if (*f <= ftest1 && fabs(dg) <= param->gtol * (-dginit)) {
931
+ /* The sufficient decrease condition and the directional derivative condition hold. */
932
+ return count;
933
+ }
934
+
935
+ /*
936
+ In the first stage we seek a step for which the modified
937
+ function has a nonpositive value and nonnegative derivative.
938
+ */
939
+ if (stage1 && *f <= ftest1 && min2(param->ftol, param->gtol) * dginit <= dg) {
940
+ stage1 = 0;
941
+ }
942
+
943
+ /*
944
+ A modified function is used to predict the step only if
945
+ we have not obtained a step for which the modified
946
+ function has a nonpositive function value and nonnegative
947
+ derivative, and if a lower function value has been
948
+ obtained but the decrease is not sufficient.
949
+ */
950
+ if (stage1 && ftest1 < *f && *f <= fx) {
951
+ /* Define the modified function and derivative values. */
952
+ fm = *f - *stp * dgtest;
953
+ fxm = fx - stx * dgtest;
954
+ fym = fy - sty * dgtest;
955
+ dgm = dg - dgtest;
956
+ dgxm = dgx - dgtest;
957
+ dgym = dgy - dgtest;
958
+
959
+ /*
960
+ Call update_trial_interval() to update the interval of
961
+ uncertainty and to compute the new step.
962
+ */
963
+ uinfo = update_trial_interval(
964
+ &stx, &fxm, &dgxm,
965
+ &sty, &fym, &dgym,
966
+ stp, &fm, &dgm,
967
+ stmin, stmax, &brackt
968
+ );
969
+
970
+ /* Reset the function and gradient values for f. */
971
+ fx = fxm + stx * dgtest;
972
+ fy = fym + sty * dgtest;
973
+ dgx = dgxm + dgtest;
974
+ dgy = dgym + dgtest;
975
+ } else {
976
+ /*
977
+ Call update_trial_interval() to update the interval of
978
+ uncertainty and to compute the new step.
979
+ */
980
+ uinfo = update_trial_interval(
981
+ &stx, &fx, &dgx,
982
+ &sty, &fy, &dgy,
983
+ stp, f, &dg,
984
+ stmin, stmax, &brackt
985
+ );
986
+ }
987
+
988
+ /*
989
+ Force a sufficient decrease in the interval of uncertainty.
990
+ */
991
+ if (brackt) {
992
+ if (0.66 * prev_width <= fabs(sty - stx)) {
993
+ *stp = stx + 0.5 * (sty - stx);
994
+ }
995
+ prev_width = width;
996
+ width = fabs(sty - stx);
997
+ }
998
+ }
999
+
1000
+ return LBFGSERR_LOGICERROR;
1001
+ }
1002
+
1003
+
1004
+
1005
+ /**
1006
+ * Define the local variables for computing minimizers.
1007
+ */
1008
+ #define USES_MINIMIZER \
1009
+ lbfgsfloatval_t a, d, gamma, theta, p, q, r, s;
1010
+
1011
+ /**
1012
+ * Find a minimizer of an interpolated cubic function.
1013
+ * @param cm The minimizer of the interpolated cubic.
1014
+ * @param u The value of one point, u.
1015
+ * @param fu The value of f(u).
1016
+ * @param du The value of f'(u).
1017
+ * @param v The value of another point, v.
1018
+ * @param fv The value of f(v).
1019
+ * @param du The value of f'(v).
1020
+ */
1021
+ #define CUBIC_MINIMIZER(cm, u, fu, du, v, fv, dv) \
1022
+ d = (v) - (u); \
1023
+ theta = ((fu) - (fv)) * 3 / d + (du) + (dv); \
1024
+ p = fabs(theta); \
1025
+ q = fabs(du); \
1026
+ r = fabs(dv); \
1027
+ s = max3(p, q, r); \
1028
+ /* gamma = s*sqrt((theta/s)**2 - (du/s) * (dv/s)) */ \
1029
+ a = theta / s; \
1030
+ gamma = s * sqrt(a * a - ((du) / s) * ((dv) / s)); \
1031
+ if ((v) < (u)) gamma = -gamma; \
1032
+ p = gamma - (du) + theta; \
1033
+ q = gamma - (du) + gamma + (dv); \
1034
+ r = p / q; \
1035
+ (cm) = (u) + r * d;
1036
+
1037
+ /**
1038
+ * Find a minimizer of an interpolated cubic function.
1039
+ * @param cm The minimizer of the interpolated cubic.
1040
+ * @param u The value of one point, u.
1041
+ * @param fu The value of f(u).
1042
+ * @param du The value of f'(u).
1043
+ * @param v The value of another point, v.
1044
+ * @param fv The value of f(v).
1045
+ * @param du The value of f'(v).
1046
+ * @param xmin The maximum value.
1047
+ * @param xmin The minimum value.
1048
+ */
1049
+ #define CUBIC_MINIMIZER2(cm, u, fu, du, v, fv, dv, xmin, xmax) \
1050
+ d = (v) - (u); \
1051
+ theta = ((fu) - (fv)) * 3 / d + (du) + (dv); \
1052
+ p = fabs(theta); \
1053
+ q = fabs(du); \
1054
+ r = fabs(dv); \
1055
+ s = max3(p, q, r); \
1056
+ /* gamma = s*sqrt((theta/s)**2 - (du/s) * (dv/s)) */ \
1057
+ a = theta / s; \
1058
+ gamma = s * sqrt(max2(0, a * a - ((du) / s) * ((dv) / s))); \
1059
+ if ((u) < (v)) gamma = -gamma; \
1060
+ p = gamma - (dv) + theta; \
1061
+ q = gamma - (dv) + gamma + (du); \
1062
+ r = p / q; \
1063
+ if (r < 0. && gamma != 0.) { \
1064
+ (cm) = (v) - r * d; \
1065
+ } else if (a < 0) { \
1066
+ (cm) = (xmax); \
1067
+ } else { \
1068
+ (cm) = (xmin); \
1069
+ }
1070
+
1071
+ /**
1072
+ * Find a minimizer of an interpolated quadratic function.
1073
+ * @param qm The minimizer of the interpolated quadratic.
1074
+ * @param u The value of one point, u.
1075
+ * @param fu The value of f(u).
1076
+ * @param du The value of f'(u).
1077
+ * @param v The value of another point, v.
1078
+ * @param fv The value of f(v).
1079
+ */
1080
+ #define QUARD_MINIMIZER(qm, u, fu, du, v, fv) \
1081
+ a = (v) - (u); \
1082
+ (qm) = (u) + (du) / (((fu) - (fv)) / a + (du)) / 2 * a;
1083
+
1084
+ /**
1085
+ * Find a minimizer of an interpolated quadratic function.
1086
+ * @param qm The minimizer of the interpolated quadratic.
1087
+ * @param u The value of one point, u.
1088
+ * @param du The value of f'(u).
1089
+ * @param v The value of another point, v.
1090
+ * @param dv The value of f'(v).
1091
+ */
1092
+ #define QUARD_MINIMIZER2(qm, u, du, v, dv) \
1093
+ a = (u) - (v); \
1094
+ (qm) = (v) + (dv) / ((dv) - (du)) * a;
1095
+
1096
+ /**
1097
+ * Update a safeguarded trial value and interval for line search.
1098
+ *
1099
+ * The parameter x represents the step with the least function value.
1100
+ * The parameter t represents the current step. This function assumes
1101
+ * that the derivative at the point of x in the direction of the step.
1102
+ * If the bracket is set to true, the minimizer has been bracketed in
1103
+ * an interval of uncertainty with endpoints between x and y.
1104
+ *
1105
+ * @param x The pointer to the value of one endpoint.
1106
+ * @param fx The pointer to the value of f(x).
1107
+ * @param dx The pointer to the value of f'(x).
1108
+ * @param y The pointer to the value of another endpoint.
1109
+ * @param fy The pointer to the value of f(y).
1110
+ * @param dy The pointer to the value of f'(y).
1111
+ * @param t The pointer to the value of the trial value, t.
1112
+ * @param ft The pointer to the value of f(t).
1113
+ * @param dt The pointer to the value of f'(t).
1114
+ * @param tmin The minimum value for the trial value, t.
1115
+ * @param tmax The maximum value for the trial value, t.
1116
+ * @param brackt The pointer to the predicate if the trial value is
1117
+ * bracketed.
1118
+ * @retval int Status value. Zero indicates a normal termination.
1119
+ *
1120
+ * @see
1121
+ * Jorge J. More and David J. Thuente. Line search algorithm with
1122
+ * guaranteed sufficient decrease. ACM Transactions on Mathematical
1123
+ * Software (TOMS), Vol 20, No 3, pp. 286-307, 1994.
1124
+ */
1125
+ static int update_trial_interval(
1126
+ lbfgsfloatval_t *x,
1127
+ lbfgsfloatval_t *fx,
1128
+ lbfgsfloatval_t *dx,
1129
+ lbfgsfloatval_t *y,
1130
+ lbfgsfloatval_t *fy,
1131
+ lbfgsfloatval_t *dy,
1132
+ lbfgsfloatval_t *t,
1133
+ lbfgsfloatval_t *ft,
1134
+ lbfgsfloatval_t *dt,
1135
+ const lbfgsfloatval_t tmin,
1136
+ const lbfgsfloatval_t tmax,
1137
+ int *brackt
1138
+ )
1139
+ {
1140
+ int bound;
1141
+ int dsign = fsigndiff(dt, dx);
1142
+ lbfgsfloatval_t mc; /* minimizer of an interpolated cubic. */
1143
+ lbfgsfloatval_t mq; /* minimizer of an interpolated quadratic. */
1144
+ lbfgsfloatval_t newt; /* new trial value. */
1145
+ USES_MINIMIZER; /* for CUBIC_MINIMIZER and QUARD_MINIMIZER. */
1146
+
1147
+ /* Check the input parameters for errors. */
1148
+ if (*brackt) {
1149
+ if (*t <= min2(*x, *y) || max2(*x, *y) <= *t) {
1150
+ /* The trival value t is out of the interval. */
1151
+ return LBFGSERR_OUTOFINTERVAL;
1152
+ }
1153
+ if (0. <= *dx * (*t - *x)) {
1154
+ /* The function must decrease from x. */
1155
+ return LBFGSERR_INCREASEGRADIENT;
1156
+ }
1157
+ if (tmax < tmin) {
1158
+ /* Incorrect tmin and tmax specified. */
1159
+ return LBFGSERR_INCORRECT_TMINMAX;
1160
+ }
1161
+ }
1162
+
1163
+ /*
1164
+ Trial value selection.
1165
+ */
1166
+ if (*fx < *ft) {
1167
+ /*
1168
+ Case 1: a higher function value.
1169
+ The minimum is brackt. If the cubic minimizer is closer
1170
+ to x than the quadratic one, the cubic one is taken, else
1171
+ the average of the minimizers is taken.
1172
+ */
1173
+ *brackt = 1;
1174
+ bound = 1;
1175
+ CUBIC_MINIMIZER(mc, *x, *fx, *dx, *t, *ft, *dt);
1176
+ QUARD_MINIMIZER(mq, *x, *fx, *dx, *t, *ft);
1177
+ if (fabs(mc - *x) < fabs(mq - *x)) {
1178
+ newt = mc;
1179
+ } else {
1180
+ newt = mc + 0.5 * (mq - mc);
1181
+ }
1182
+ } else if (dsign) {
1183
+ /*
1184
+ Case 2: a lower function value and derivatives of
1185
+ opposite sign. The minimum is brackt. If the cubic
1186
+ minimizer is closer to x than the quadratic (secant) one,
1187
+ the cubic one is taken, else the quadratic one is taken.
1188
+ */
1189
+ *brackt = 1;
1190
+ bound = 0;
1191
+ CUBIC_MINIMIZER(mc, *x, *fx, *dx, *t, *ft, *dt);
1192
+ QUARD_MINIMIZER2(mq, *x, *dx, *t, *dt);
1193
+ if (fabs(mc - *t) > fabs(mq - *t)) {
1194
+ newt = mc;
1195
+ } else {
1196
+ newt = mq;
1197
+ }
1198
+ } else if (fabs(*dt) < fabs(*dx)) {
1199
+ /*
1200
+ Case 3: a lower function value, derivatives of the
1201
+ same sign, and the magnitude of the derivative decreases.
1202
+ The cubic minimizer is only used if the cubic tends to
1203
+ infinity in the direction of the minimizer or if the minimum
1204
+ of the cubic is beyond t. Otherwise the cubic minimizer is
1205
+ defined to be either tmin or tmax. The quadratic (secant)
1206
+ minimizer is also computed and if the minimum is brackt
1207
+ then the the minimizer closest to x is taken, else the one
1208
+ farthest away is taken.
1209
+ */
1210
+ bound = 1;
1211
+ CUBIC_MINIMIZER2(mc, *x, *fx, *dx, *t, *ft, *dt, tmin, tmax);
1212
+ QUARD_MINIMIZER2(mq, *x, *dx, *t, *dt);
1213
+ if (*brackt) {
1214
+ if (fabs(*t - mc) < fabs(*t - mq)) {
1215
+ newt = mc;
1216
+ } else {
1217
+ newt = mq;
1218
+ }
1219
+ } else {
1220
+ if (fabs(*t - mc) > fabs(*t - mq)) {
1221
+ newt = mc;
1222
+ } else {
1223
+ newt = mq;
1224
+ }
1225
+ }
1226
+ } else {
1227
+ /*
1228
+ Case 4: a lower function value, derivatives of the
1229
+ same sign, and the magnitude of the derivative does
1230
+ not decrease. If the minimum is not brackt, the step
1231
+ is either tmin or tmax, else the cubic minimizer is taken.
1232
+ */
1233
+ bound = 0;
1234
+ if (*brackt) {
1235
+ CUBIC_MINIMIZER(newt, *t, *ft, *dt, *y, *fy, *dy);
1236
+ } else if (*x < *t) {
1237
+ newt = tmax;
1238
+ } else {
1239
+ newt = tmin;
1240
+ }
1241
+ }
1242
+
1243
+ /*
1244
+ Update the interval of uncertainty. This update does not
1245
+ depend on the new step or the case analysis above.
1246
+
1247
+ - Case a: if f(x) < f(t),
1248
+ x <- x, y <- t.
1249
+ - Case b: if f(t) <= f(x) && f'(t)*f'(x) > 0,
1250
+ x <- t, y <- y.
1251
+ - Case c: if f(t) <= f(x) && f'(t)*f'(x) < 0,
1252
+ x <- t, y <- x.
1253
+ */
1254
+ if (*fx < *ft) {
1255
+ /* Case a */
1256
+ *y = *t;
1257
+ *fy = *ft;
1258
+ *dy = *dt;
1259
+ } else {
1260
+ /* Case c */
1261
+ if (dsign) {
1262
+ *y = *x;
1263
+ *fy = *fx;
1264
+ *dy = *dx;
1265
+ }
1266
+ /* Cases b and c */
1267
+ *x = *t;
1268
+ *fx = *ft;
1269
+ *dx = *dt;
1270
+ }
1271
+
1272
+ /* Clip the new trial value in [tmin, tmax]. */
1273
+ if (tmax < newt) newt = tmax;
1274
+ if (newt < tmin) newt = tmin;
1275
+
1276
+ /*
1277
+ Redefine the new trial value if it is close to the upper bound
1278
+ of the interval.
1279
+ */
1280
+ if (*brackt && bound) {
1281
+ mq = *x + 0.66 * (*y - *x);
1282
+ if (*x < *y) {
1283
+ if (mq < newt) newt = mq;
1284
+ } else {
1285
+ if (newt < mq) newt = mq;
1286
+ }
1287
+ }
1288
+
1289
+ /* Return the new trial value. */
1290
+ *t = newt;
1291
+ return 0;
1292
+ }
1293
+
1294
+
1295
+
1296
+
1297
+
1298
+ static lbfgsfloatval_t owlqn_x1norm(
1299
+ const lbfgsfloatval_t* x,
1300
+ const int start,
1301
+ const int n
1302
+ )
1303
+ {
1304
+ int i;
1305
+ lbfgsfloatval_t norm = 0.;
1306
+
1307
+ for (i = start;i < n;++i) {
1308
+ norm += fabs(x[i]);
1309
+ }
1310
+
1311
+ return norm;
1312
+ }
1313
+
1314
+ static void owlqn_pseudo_gradient(
1315
+ lbfgsfloatval_t* pg,
1316
+ const lbfgsfloatval_t* x,
1317
+ const lbfgsfloatval_t* g,
1318
+ const int n,
1319
+ const lbfgsfloatval_t c,
1320
+ const int start,
1321
+ const int end
1322
+ )
1323
+ {
1324
+ int i;
1325
+
1326
+ /* Compute the negative of gradients. */
1327
+ for (i = 0;i < start;++i) {
1328
+ pg[i] = g[i];
1329
+ }
1330
+
1331
+ /* Compute the psuedo-gradients. */
1332
+ for (i = start;i < end;++i) {
1333
+ if (x[i] < 0.) {
1334
+ /* Differentiable. */
1335
+ pg[i] = g[i] - c;
1336
+ } else if (0. < x[i]) {
1337
+ /* Differentiable. */
1338
+ pg[i] = g[i] + c;
1339
+ } else {
1340
+ if (g[i] < -c) {
1341
+ /* Take the right partial derivative. */
1342
+ pg[i] = g[i] + c;
1343
+ } else if (c < g[i]) {
1344
+ /* Take the left partial derivative. */
1345
+ pg[i] = g[i] - c;
1346
+ } else {
1347
+ pg[i] = 0.;
1348
+ }
1349
+ }
1350
+ }
1351
+
1352
+ for (i = end;i < n;++i) {
1353
+ pg[i] = g[i];
1354
+ }
1355
+ }
1356
+
1357
+ static void owlqn_project(
1358
+ lbfgsfloatval_t* d,
1359
+ const lbfgsfloatval_t* sign,
1360
+ const int start,
1361
+ const int end
1362
+ )
1363
+ {
1364
+ int i;
1365
+
1366
+ for (i = start;i < end;++i) {
1367
+ if (d[i] * sign[i] <= 0) {
1368
+ d[i] = 0;
1369
+ }
1370
+ }
1371
+ }