EntropyTest.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <?php
  2. namespace MathPHP\Tests\InformationTheory;
  3. use MathPHP\InformationTheory\Entropy;
  4. use MathPHP\Exception;
  5. class EntropyTest extends \PHPUnit\Framework\TestCase
  6. {
  7. /**
  8. * @dataProvider dataProviderForShannonEntropy
  9. */
  10. public function testShannonEntropy(array $p, $expected)
  11. {
  12. // When
  13. $H = Entropy::shannonEntropy($p);
  14. // Then
  15. $this->assertEqualsWithDelta($expected, $H, 0.001);
  16. }
  17. public function dataProviderForShannonEntropy(): array
  18. {
  19. return [
  20. // Test data created from: http://www.shannonentropy.netmark.pl/
  21. [
  22. [1],
  23. 0
  24. ],
  25. [
  26. [0.6, 0.4],
  27. 0.97095,
  28. ],
  29. [
  30. [0.514, 0.486],
  31. 0.99941,
  32. ],
  33. [
  34. [0.231, 0.385, 0.308, 0.077],
  35. 1.82625,
  36. ],
  37. // Test data from: http://www.csun.edu/~twang/595DM/Slides/Information%20&%20Entropy.pdf
  38. [
  39. [4 / 9, 3 / 9, 2 / 9],
  40. 1.5304755,
  41. ],
  42. // Test data from: http://www.cs.rochester.edu/u/james/CSC248/Lec6.pdf
  43. [
  44. [0.4, 0.1, 0.25, 0.25],
  45. 1.86,
  46. ],
  47. // Other
  48. [
  49. [1 / 2, 1 / 4, 1 / 4, 0],
  50. 3 / 2,
  51. ],
  52. ];
  53. }
  54. public function testShannonEntropyExceptionNotProbabilityDistributionThatAddsUpToOne()
  55. {
  56. // Given
  57. $p = [0.2, 0.2, 0.1];
  58. // Then
  59. $this->expectException(Exception\BadDataException::class);
  60. // When
  61. Entropy::shannonEntropy($p);
  62. }
  63. /**
  64. * @dataProvider dataProviderForShannonNatEntropy
  65. */
  66. public function testShannonNatEntropy(array $p, $expected)
  67. {
  68. // When
  69. $H = Entropy::shannonNatEntropy($p);
  70. // Then
  71. $this->assertEqualsWithDelta($expected, $H, 0.000001);
  72. }
  73. public function dataProviderForShannonNatEntropy(): array
  74. {
  75. return [
  76. [
  77. [1],
  78. 0
  79. ],
  80. [
  81. [0.6, 0.4],
  82. 0.67301166700925,
  83. ],
  84. [
  85. [0.514, 0.486],
  86. 0.69275512932254,
  87. ],
  88. [
  89. [0.231, 0.385, 0.308, 0.077],
  90. 1.2661221087912,
  91. ],
  92. [
  93. [4 / 9, 3 / 9, 2 / 9],
  94. 1.06085694715802,
  95. ],
  96. ];
  97. }
  98. public function testShannonNatEntropyExceptionNotProbabilityDistributionThatAddsUpToOne()
  99. {
  100. // Given
  101. $p = [0.2, 0.2, 0.1];
  102. // Then
  103. $this->expectException(Exception\BadDataException::class);
  104. // When
  105. Entropy::shannonNatEntropy($p);
  106. }
  107. /**
  108. * @dataProvider dataProviderForShannonHartleyEntropy
  109. */
  110. public function testShannonHartleyEntropy(array $p, $expected)
  111. {
  112. // When
  113. $H = Entropy::shannonHartleyEntropy($p);
  114. // Then
  115. $this->assertEqualsWithDelta($expected, $H, 0.000001);
  116. }
  117. public function dataProviderForShannonHartleyEntropy(): array
  118. {
  119. return [
  120. [
  121. [1],
  122. 0
  123. ],
  124. [
  125. [0.6, 0.4],
  126. 0.29228525323863,
  127. ],
  128. [
  129. [0.514, 0.486],
  130. 0.30085972997496,
  131. ],
  132. [
  133. [0.231, 0.385, 0.308, 0.077],
  134. 0.54986984526372,
  135. ],
  136. [
  137. [4 / 9, 3 / 9, 2 / 9],
  138. 0.46072431823946,
  139. ],
  140. ];
  141. }
  142. public function testShannonHartleyEntropyExceptionNotProbabilityDistributionThatAddsUpToOne()
  143. {
  144. // Given
  145. $p = [0.2, 0.2, 0.1];
  146. // Then
  147. $this->expectException(Exception\BadDataException::class);
  148. // When
  149. Entropy::shannonHartleyEntropy($p);
  150. }
  151. /**
  152. * @dataProvider dataProviderForCrossEntropy
  153. */
  154. public function testCrossEntropy(array $p, array $q, $expected)
  155. {
  156. // When
  157. $BD = Entropy::crossEntropy($p, $q);
  158. // Then
  159. $this->assertEqualsWithDelta($expected, $BD, 0.01);
  160. }
  161. public function dataProviderForCrossEntropy(): array
  162. {
  163. return [
  164. // Test data from: http://www.cs.rochester.edu/u/james/CSC248/Lec6.pdf
  165. [
  166. [0.4, 0.1, 0.25, 0.25],
  167. [0.25, 0.25, 0.25, 0.25],
  168. 2,
  169. ],
  170. [
  171. [0.4, 0.1, 0.25, 0.25],
  172. [0.4, 0.1, 0.1, 0.4],
  173. 2.02,
  174. ],
  175. ];
  176. }
  177. public function testCrossEntropyExceptionArraysDifferentLength()
  178. {
  179. // Given
  180. $p = [0.4, 0.5, 0.1];
  181. $q = [0.2, 0.8];
  182. // Then
  183. $this->expectException(Exception\BadDataException::class);
  184. // When
  185. Entropy::crossEntropy($p, $q);
  186. }
  187. public function testCrossEntropyExceptionNotProbabilityDistributionThatAddsUpToOne()
  188. {
  189. // Given
  190. $p = [0.2, 0.2, 0.1];
  191. $q = [0.2, 0.4, 0.6];
  192. // Then
  193. $this->expectException(Exception\BadDataException::class);
  194. // When
  195. Entropy::crossEntropy($p, $q);
  196. }
  197. /**
  198. * @dataProvider dataProviderForShannonEntropy
  199. */
  200. public function testJointEntropy(array $p, $expected)
  201. {
  202. // When
  203. $H = Entropy::jointEntropy($p);
  204. // Then
  205. $this->assertEqualsWithDelta($expected, $H, 0.001);
  206. }
  207. public function testJointEntropyExceptionNotProbabilityDistributionThatAddsUpToOne()
  208. {
  209. // Given
  210. $p = [0.2, 0.2, 0.1];
  211. // Then
  212. $this->expectException(Exception\BadDataException::class);
  213. // When
  214. Entropy::jointEntropy($p);
  215. }
  216. /**
  217. * @dataProvider dataProviderForRenyiEntropy
  218. */
  219. public function testRenyiEntropy(array $p, $α, $expected)
  220. {
  221. // When
  222. $H = Entropy::renyiEntropy($p, $α);
  223. // Then
  224. $this->assertEqualsWithDelta($expected, $H, 0.001);
  225. }
  226. public function dataProviderForRenyiEntropy(): array
  227. {
  228. return [
  229. [
  230. [0.4, 0.6], 0.5, 0.985352,
  231. [0.2, 0.3, 0.5], 0.8, 1.504855,
  232. ],
  233. ];
  234. }
  235. public function testRenyiEntropyExceptionNotProbabilityDistributionThatAddsUpToOne()
  236. {
  237. // Given
  238. $p = [0.2, 0.2, 0.1];
  239. $α = 0.5;
  240. // Then
  241. $this->expectException(Exception\BadDataException::class);
  242. // When
  243. Entropy::renyiEntropy($p, $α);
  244. }
  245. public function testRenyiEntropyExceptionAlphaOutOfBounds()
  246. {
  247. // Given
  248. $p = [0.4, 0.4, 0.2];
  249. $α = -3;
  250. // Then
  251. $this->expectException(Exception\OutOfBoundsException::class);
  252. // When
  253. Entropy::renyiEntropy($p, $α);
  254. }
  255. public function testRenyiEntropyExceptionAlphaEqualsOne()
  256. {
  257. // Given
  258. $p = [0.4, 0.4, 0.2];
  259. $α = 1;
  260. // Then
  261. $this->expectException(Exception\OutOfBoundsException::class);
  262. // When
  263. Entropy::renyiEntropy($p, $α);
  264. }
  265. /**
  266. * @dataProvider dataProviderForPerplexity
  267. */
  268. public function testPerplexity(array $p, $expected)
  269. {
  270. // When
  271. $H = Entropy::perplexity($p);
  272. // Then
  273. $this->assertEqualsWithDelta($expected, $H, 0.001);
  274. }
  275. public function dataProviderForPerplexity(): array
  276. {
  277. return [
  278. [
  279. [1 / 10, 1 / 10, 1 / 10, 1 / 10, 1 / 10, 1 / 10, 1 / 10, 1 / 10, 1 / 10, 1 / 10],
  280. 10
  281. ],
  282. [
  283. [1],
  284. 1
  285. ],
  286. [
  287. [0.6, 0.4],
  288. 1.960130896546316,
  289. ],
  290. [
  291. [0.514, 0.486],
  292. 1.999182253549837,
  293. ],
  294. [
  295. [0.231, 0.385, 0.308, 0.077],
  296. 3.546141242991336,
  297. ],
  298. [
  299. [4 / 9, 3 / 9, 2 / 9],
  300. 2.888810361450759,
  301. ],
  302. [
  303. [1 / 2, 1 / 4, 1 / 4, 0],
  304. 2.82842712474619,
  305. ],
  306. ];
  307. }
  308. public function testPerplexityExceptionNotProbabilityDistributionThatAddsUpToOne()
  309. {
  310. // Given
  311. $p = [0.2, 0.2, 0.1];
  312. // Then
  313. $this->expectException(Exception\BadDataException::class);
  314. // When
  315. Entropy::perplexity($p);
  316. }
  317. }