OTMulti_ex_metrics.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /* OTMulti_ex_metrics.cpp
  2. *
  3. * Copyright (C) 2014-2018 Paul Boersma
  4. * Forked from OTGrammar_ex_metrics.cpp, Copyright (C) 2001-2007,2009,2011,2012 Paul Boersma
  5. *
  6. * This code is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This code is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. * See the GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "OTMulti.h"
  20. #define WSP 1
  21. #define FtNonfinal 2
  22. #define Iambic 3
  23. #define Parse 4
  24. #define FootBin 5
  25. #define WFL 6
  26. #define WFR 7
  27. #define Main_L 8
  28. #define Main_R 9
  29. #define AFL 10
  30. #define AFR 11
  31. #define Nonfinal 12
  32. #define Trochaic 13
  33. #define FootBimoraic 14
  34. #define FootBisyllabic 15
  35. #define Peripheral 16
  36. #define MainNonfinal 17
  37. #define HeadNonfinal 18
  38. #define Clash 19
  39. #define Lapse 20
  40. #define WeightByPosition 21
  41. #define MoraicConsonant 22
  42. #define NUMBER_OF_CONSTRAINTS 22
  43. static const conststring32 constraintNames [1+NUMBER_OF_CONSTRAINTS] { 0,
  44. U"WSP", U"FtNonfinal", U"Iambic", U"Parse", U"FootBin", U"WFL", U"WFR", U"Main-L", U"Main-R", U"AFL", U"AFR", U"Nonfinal",
  45. U"Trochaic", U"FtBimor", U"FtBisyl", U"Peripheral", U"MainNonfinal", U"HeadNonfinal", U"*Clash", U"*Lapse", U"WeightByPosition", U"*C\\mu" };
  46. static void addCandidate (OTMulti me, conststring32 underlyingForm, integer numberOfSyllables, int stress [],
  47. bool footedToTheLeft [], bool footedToTheRight [], int surfaceWeightPattern [],
  48. int overtFormsHaveSecondaryStress)
  49. {
  50. static const conststring32 syllable [] { U"L", U"L1", U"L2", U"H", U"H1", U"H2", U"K", U"K1", U"K2", U"J", U"J1", U"J2" };
  51. static const conststring32 syllableWithoutSecondaryStress [] { U"L", U"L1", U"L", U"H", U"H1", U"H", U"K", U"K1", U"K", U"J", U"J1", U"J" };
  52. char32 string [150];
  53. str32cpy (string, underlyingForm);
  54. str32cat (string, U" /");
  55. for (integer isyll = 1; isyll <= numberOfSyllables; isyll ++) {
  56. if (isyll > 1)
  57. str32cat (string, U" ");
  58. if (footedToTheRight [isyll] || (! footedToTheLeft [isyll] && stress [isyll] != 0))
  59. str32cat (string, U"(");
  60. str32cat (string, syllable [stress [isyll] + 3 * (surfaceWeightPattern [isyll] - 1)]);
  61. if (footedToTheLeft [isyll] || (! footedToTheRight [isyll] && stress [isyll] != 0))
  62. str32cat (string, U")");
  63. }
  64. str32cat (string, U"/ [");
  65. for (integer isyll = 1; isyll <= numberOfSyllables; isyll ++) {
  66. if (isyll > 1)
  67. str32cat (string, U" ");
  68. str32cat (string, ( overtFormsHaveSecondaryStress ? syllable : syllableWithoutSecondaryStress )
  69. [stress [isyll] + 3 * (surfaceWeightPattern [isyll] - 1)]);
  70. }
  71. str32cat (string, U"]");
  72. my candidates [++ my numberOfCandidates]. string = Melder_dup (string);
  73. }
  74. static void fillSurfaceWeightPattern (OTMulti me, conststring32 underlyingForm, integer numberOfSyllables, int stress [],
  75. bool footedToTheLeft [], bool footedToTheRight [], int underlyingWeightPattern [],
  76. int overtFormsHaveSecondaryStress)
  77. {
  78. int surfaceWeightPattern [1+7], minSurfaceWeight [1+7], maxSurfaceWeight [1+7];
  79. int weight1, weight2, weight3, weight4, weight5;
  80. for (integer isyll = 1; isyll <= numberOfSyllables; isyll ++) {
  81. if (underlyingWeightPattern [isyll] < 3) {
  82. minSurfaceWeight [isyll] = maxSurfaceWeight [isyll] = underlyingWeightPattern [isyll]; // L -> L; H -> H
  83. } else {
  84. minSurfaceWeight [isyll] = 3, maxSurfaceWeight [isyll] = 4; // C -> { J, K }
  85. }
  86. }
  87. surfaceWeightPattern [6] = surfaceWeightPattern [7] = 1; // constant L
  88. for (weight1 = minSurfaceWeight [1]; weight1 <= maxSurfaceWeight [1]; weight1 ++) {
  89. surfaceWeightPattern [1] = weight1;
  90. for (weight2 = minSurfaceWeight [2]; weight2 <= maxSurfaceWeight [2]; weight2 ++) {
  91. surfaceWeightPattern [2] = weight2;
  92. if (numberOfSyllables == 2) {
  93. addCandidate (me, underlyingForm, 2, stress, footedToTheLeft, footedToTheRight, surfaceWeightPattern, overtFormsHaveSecondaryStress);
  94. } else for (weight3 = minSurfaceWeight [3]; weight3 <= maxSurfaceWeight [3]; weight3 ++) {
  95. surfaceWeightPattern [3] = weight3;
  96. if (numberOfSyllables == 3) {
  97. addCandidate (me, underlyingForm, 3, stress, footedToTheLeft, footedToTheRight, surfaceWeightPattern, overtFormsHaveSecondaryStress);
  98. } else for (weight4 = minSurfaceWeight [4]; weight4 <= maxSurfaceWeight [4]; weight4 ++) {
  99. surfaceWeightPattern [4] = weight4;
  100. if (numberOfSyllables == 4) {
  101. addCandidate (me, underlyingForm, 4, stress, footedToTheLeft, footedToTheRight, surfaceWeightPattern, overtFormsHaveSecondaryStress);
  102. } else for (weight5 = minSurfaceWeight [5]; weight5 <= maxSurfaceWeight [5]; weight5 ++) {
  103. surfaceWeightPattern [5] = weight5;
  104. addCandidate (me, underlyingForm, numberOfSyllables, stress, footedToTheLeft, footedToTheRight, surfaceWeightPattern, overtFormsHaveSecondaryStress);
  105. }
  106. }
  107. }
  108. }
  109. }
  110. }
  111. static void path (OTMulti me, conststring32 underlyingForm, integer numberOfSyllables, int stress [],
  112. int startingSyllable, bool footedToTheLeft_in [], bool footedToTheRight_in [], int underlyingWeightPattern [],
  113. int overtFormsHaveSecondaryStress)
  114. {
  115. bool footedToTheLeft [10], footedToTheRight [10];
  116. integer isyll;
  117. /* Localize all arguments. */
  118. for (isyll = 1; isyll <= startingSyllable; isyll ++) {
  119. footedToTheLeft [isyll] = footedToTheLeft_in [isyll];
  120. footedToTheRight [isyll] = footedToTheRight_in [isyll];
  121. }
  122. for (isyll = startingSyllable + 1; isyll <= numberOfSyllables; isyll ++)
  123. footedToTheLeft [isyll] = footedToTheRight [isyll] = 0;
  124. if (startingSyllable > numberOfSyllables) {
  125. fillSurfaceWeightPattern (me, underlyingForm, numberOfSyllables, stress, footedToTheLeft, footedToTheRight, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  126. } else {
  127. path (me, underlyingForm, numberOfSyllables, stress, startingSyllable + 1,
  128. footedToTheLeft, footedToTheRight, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  129. if (stress [startingSyllable] == 0 && startingSyllable < numberOfSyllables && stress [startingSyllable + 1] != 0) {
  130. footedToTheLeft [startingSyllable + 1] = true;
  131. footedToTheRight [startingSyllable] = true;
  132. path (me, underlyingForm, numberOfSyllables, stress, startingSyllable + 1,
  133. footedToTheLeft, footedToTheRight, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  134. footedToTheLeft [startingSyllable + 1] = false;
  135. footedToTheRight [startingSyllable] = false;
  136. }
  137. if (stress [startingSyllable] == 0 && startingSyllable > 1 && stress [startingSyllable - 1] != 0
  138. && ! footedToTheLeft [startingSyllable - 1])
  139. {
  140. footedToTheRight [startingSyllable - 1] = true;
  141. footedToTheLeft [startingSyllable] = true;
  142. path (me, underlyingForm, numberOfSyllables, stress, startingSyllable + 1,
  143. footedToTheLeft, footedToTheRight, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  144. }
  145. }
  146. }
  147. static void fillOvertStressPattern (OTMulti me, conststring32 underlyingForm, integer numberOfSyllables, int stress [], int underlyingWeightPattern [],
  148. int overtFormsHaveSecondaryStress)
  149. {
  150. bool footedToTheLeft [10], footedToTheRight [10];
  151. for (int isyll = 1; isyll <= numberOfSyllables; isyll ++)
  152. footedToTheLeft [isyll] = footedToTheRight [isyll] = 0;
  153. path (me, underlyingForm, numberOfSyllables, stress, 1, footedToTheLeft, footedToTheRight, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  154. }
  155. static int numberOfCandidates_noCodas [1+7] { 0, 1, 6, 24, 88, 300, 984, 3136 };
  156. static int numberOfCandidates_codas [1+7] { 0, 1, 24, 192, 1408, 9600, 984, 3136 };
  157. static void fillTableau (OTMulti me, integer numberOfSyllables, int underlyingWeightPattern [], int overtFormsHaveSecondaryStress, int includeCodas) {
  158. char32 underlyingForm [100];
  159. str32cpy (underlyingForm, U"|");
  160. for (integer isyll = 1; isyll <= numberOfSyllables; isyll ++) {
  161. static const conststring32 syllable_noCodas [] = { U"", U"L", U"H" };
  162. static const conststring32 syllable_codas [] = { U"", U"cv", U"cv:", U"cvc" };
  163. if (isyll > 1)
  164. str32cat (underlyingForm, includeCodas ? U"." : U" ");
  165. str32cat (underlyingForm, ( includeCodas ? syllable_codas : syllable_noCodas ) [underlyingWeightPattern [isyll]]);
  166. }
  167. str32cat (underlyingForm, U"|");
  168. for (integer mainStressed = 1; mainStressed <= numberOfSyllables; mainStressed ++) {
  169. int stress [10];
  170. stress [mainStressed] = 1;
  171. for (int secondary1 = false; secondary1 <= true; secondary1 ++) {
  172. stress [mainStressed <= 1 ? 2 : 1] = secondary1 ? 2 : 0;
  173. if (numberOfSyllables == 2) {
  174. fillOvertStressPattern (me, underlyingForm, 2, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  175. } else for (int secondary2 = false; secondary2 <= true; secondary2 ++) {
  176. stress [mainStressed <= 2 ? 3 : 2] = secondary2 ? 2 : 0;
  177. if (numberOfSyllables == 3) {
  178. fillOvertStressPattern (me, underlyingForm, 3, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  179. } else for (int secondary3 = false; secondary3 <= true; secondary3 ++) {
  180. stress [mainStressed <= 3 ? 4 : 3] = secondary3 ? 2 : 0;
  181. if (numberOfSyllables == 4) {
  182. fillOvertStressPattern (me, underlyingForm, 4, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  183. } else for (int secondary4 = false; secondary4 <= true; secondary4 ++) {
  184. stress [mainStressed <= 4 ? 5 : 4] = secondary4 ? 2 : 0;
  185. if (numberOfSyllables == 5) {
  186. fillOvertStressPattern (me, underlyingForm, 5, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  187. } else for (int secondary5 = false; secondary5 <= true; secondary5 ++) {
  188. stress [mainStressed <= 5 ? 6 : 5] = secondary5 ? 2 : 0;
  189. if (numberOfSyllables == 6) {
  190. fillOvertStressPattern (me, underlyingForm, 6, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  191. } else for (int secondary6 = false; secondary6 <= true; secondary6 ++) {
  192. stress [mainStressed <= 6 ? 7 : 6] = secondary6 ? 2 : 0;
  193. fillOvertStressPattern (me, underlyingForm, 7, stress, underlyingWeightPattern, overtFormsHaveSecondaryStress);
  194. }
  195. }
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. static void computeViolationMarks (OTCandidate me) {
  203. #define isHeavy(s) ((s) == U'H' || (s) == U'J')
  204. #define isLight(s) ((s) == U'L' || (s) == U'K')
  205. #define isSyllable(s) (isHeavy (s) || isLight (s))
  206. #define isStress(s) ((s) == U'1' || (s) == U'2')
  207. const char32 * const firstSlash = str32chr (my string.get(), U'/');
  208. const char32 * const lastSlash = str32chr (firstSlash + 1, U'/');
  209. my marks = INTVECzero (my numberOfConstraints = NUMBER_OF_CONSTRAINTS);
  210. /* Violations of WSP: count all H not followed by 1 or 2. */
  211. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  212. if (isHeavy (p [0]) && ! isStress (p [1]))
  213. my marks [WSP] ++;
  214. }
  215. /* Violations of FtNonfinal: count all heads followed by ). */
  216. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  217. if (isStress (p [0]) && p [1] == ')')
  218. my marks [FtNonfinal] ++;
  219. }
  220. /* Violations of Iambic: count all heads not followed by ). */
  221. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  222. if (isStress (p [0]) && p [1] != ')')
  223. my marks [Iambic] ++;
  224. }
  225. /* Violations of Parse and Peripheral: count all syllables not between (). */
  226. int depth = 0;
  227. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  228. if (p [0] == U'(') depth ++;
  229. else if (p [0] == U')') depth --;
  230. else if (isSyllable (p [0]) && depth != 1) {
  231. my marks [Parse] ++;
  232. if (p != firstSlash + 1 && p != lastSlash - 1)
  233. my marks [Peripheral] ++;
  234. }
  235. }
  236. /* Violations of FootBin: count all (L1) and (L2). */
  237. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  238. if (isLight (p [0]) && p [-1] == '(' && isStress (p [1]) && p [2] == U')')
  239. my marks [FootBin] ++;
  240. }
  241. /* Violations of WFL: count all initial / not followed by (. */
  242. if (firstSlash [1] != U'(')
  243. my marks [WFL] = 1;
  244. /* Violations of WFR: count all final / not preceded by ). */
  245. if (lastSlash [-1] != ')')
  246. my marks [WFR] = 1;
  247. /* Violations of Main_L: count syllables from foot containing X1 to left edge. */
  248. {
  249. const char32 *p = str32chr (firstSlash, U'1');
  250. for (; *p != U'('; p --) { }
  251. for (; p != firstSlash; p --) {
  252. if (isSyllable (p [0]))
  253. my marks [Main_L] ++;
  254. }
  255. }
  256. /* Violations of Main_R: count syllables from foot containing X1 to right edge. */
  257. {
  258. const char32 *p = str32chr (firstSlash, U'1');
  259. for (; *p != U')'; p ++) { }
  260. for (; p != lastSlash; p ++) {
  261. if (isSyllable (p [0]))
  262. my marks [Main_R] ++;
  263. }
  264. }
  265. /* Violations of AFL: count syllables from every foot to left edge. */
  266. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  267. if (p [0] == U'(') {
  268. for (const char32 *q = p; q != firstSlash; q --) {
  269. if (isSyllable (q [0]))
  270. my marks [AFL] ++;
  271. }
  272. }
  273. }
  274. /* Violations of AFR: count syllables from every foot to right edge. */
  275. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  276. if (p [0] == U')') {
  277. for (const char32 *q = p; q != lastSlash; q ++) {
  278. if (isSyllable (q [0]))
  279. my marks [AFR] ++;
  280. }
  281. }
  282. }
  283. /* Violations of Nonfinal: count all final / preceded by ). */
  284. if (lastSlash [-1] == U')')
  285. my marks [Nonfinal] = 1;
  286. /* Violations of Trochaic: count all heads not preceded by (. */
  287. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  288. if (isStress (p [0]) && p [-2] != '(')
  289. my marks [Trochaic] ++;
  290. }
  291. /* Violations of FootBimoraic: count weight between (). */
  292. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  293. if (p [0] == U'(') {
  294. int weight = 0;
  295. for (p ++; p [0] != ')'; p ++) {
  296. if (isHeavy (p [0])) weight += 2;
  297. else if (isLight (p [0])) weight += 1;
  298. }
  299. if (weight != 2) my marks [FootBimoraic] ++;
  300. }
  301. }
  302. /* Violations of FootBisyllabic: count all (X1) and (X2). */
  303. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  304. if (isSyllable (p [0]) && p [-1] == U'(' && isStress (p [1]) && p [2] == U')')
  305. my marks [FootBisyllabic] ++;
  306. }
  307. /* Violations of MainNonfinal: count all final / preceded by ) preceded by 1 in the same foot. */
  308. if (lastSlash [-1] == U')') {
  309. for (const char32 *p = lastSlash - 2; ; p --) {
  310. if (p [0] == '2') break;
  311. if (p [0] == '1') {
  312. my marks [MainNonfinal] = 1;
  313. break;
  314. }
  315. }
  316. }
  317. /* Violations of HeadNonfinal: count all final / preceded by ) directly preceded by 1, plus MainNonfinal. */
  318. if (lastSlash [-1] == U')') {
  319. if (lastSlash [-2] == U'1') {
  320. my marks [HeadNonfinal] = 2;
  321. } else {
  322. for (const char32 *p = lastSlash - 2; ; p --) {
  323. if (p [0] == U'2') break;
  324. if (p [0] == U'1') {
  325. my marks [HeadNonfinal] = 1;
  326. break;
  327. }
  328. }
  329. }
  330. }
  331. /* Violations of *Clash: count all 1 and 2 followed by an 1 or 2 after the next L or H. */
  332. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  333. if (isStress (p [0])) {
  334. for (const char32 *q = p + 1; q != lastSlash; q ++) {
  335. if (isSyllable (q [0])) {
  336. if (isStress (q [1])) {
  337. my marks [Clash] ++;
  338. }
  339. break;
  340. }
  341. }
  342. }
  343. }
  344. /* Violations of *Lapse: count all sequences of three unstressed syllables. */
  345. depth = 0;
  346. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  347. if (isSyllable (p [0])) {
  348. if (isStress (p [1])) {
  349. depth = 0;
  350. } else {
  351. if (++ depth > 2) {
  352. my marks [Lapse] ++;
  353. }
  354. }
  355. }
  356. }
  357. /* Violations of WeightByPosition: count all K. */
  358. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  359. if (p [0] == U'K')
  360. my marks [WeightByPosition] ++;
  361. }
  362. /* Violations of *MoraicConsonant: count all J. */
  363. for (const char32 *p = firstSlash + 1; p != lastSlash; p ++) {
  364. if (p [0] == U'J')
  365. my marks [MoraicConsonant] ++;
  366. }
  367. }
  368. static void replaceOutput (OTCandidate me) {
  369. bool abstract = false;
  370. Melder_assert (my string);
  371. char32 newString [150], *q = & newString [0];
  372. for (const char32 *p = & my string [0]; *p != U'\0'; p ++) {
  373. if (p [0] == U' ') {
  374. *q ++ = p [-1] == U']' || p [1] == U'/' ? U' ' : U'.';
  375. } else if (isSyllable (p [0])) {
  376. *q ++ = U'c';
  377. if (abstract) {
  378. *q ++ = U'V';
  379. if (isStress (p [1])) {
  380. *q ++ = p [1];
  381. }
  382. if (p [0] == U'L') {
  383. ;
  384. } else if (p [0] == U'H') {
  385. *q ++ = U'V';
  386. } else if (p [0] == U'K') {
  387. *q ++ = U'c';
  388. } else {
  389. *q ++ = U'C';
  390. }
  391. } else {
  392. *q ++ = U'v';
  393. if (p [0] == U'L') {
  394. ;
  395. } else if (p [0] == 'H') {
  396. *q ++ = U':';
  397. } else {
  398. *q ++ = U'c';
  399. }
  400. }
  401. } else if (isStress (p [0]) && abstract) {
  402. ;
  403. } else {
  404. if (p [0] == U'/') abstract = true;
  405. *q ++ = p [0];
  406. }
  407. }
  408. *q = U'\0';
  409. my string = Melder_dup (newString);
  410. }
  411. autoOTMulti OTMulti_create_metrics (
  412. kOTGrammar_createMetricsGrammar_initialRanking equal_footForm_wsp,
  413. int trochaicityConstraint, int includeFootBimoraic, int includeFootBisyllabic,
  414. int includePeripheral, int nonfinalityConstraint, int overtFormsHaveSecondaryStress,
  415. int includeClashAndLapse, int includeCodas)
  416. {
  417. try {
  418. int underlyingWeightPattern [1+7], maximumUnderlyingWeight = includeCodas ? 3 : 2;
  419. autoOTMulti me = Thing_new (OTMulti);
  420. my constraints = NUMvector <structOTConstraint> (1, my numberOfConstraints = NUMBER_OF_CONSTRAINTS);
  421. for (integer icons = 1; icons <= NUMBER_OF_CONSTRAINTS; icons ++) {
  422. OTConstraint constraint = & my constraints [icons];
  423. constraint -> name = Melder_dup (constraintNames [icons]);
  424. constraint -> ranking = 100.0;
  425. constraint -> plasticity = 1.0;
  426. }
  427. if (equal_footForm_wsp >= kOTGrammar_createMetricsGrammar_initialRanking::FOOT_FORM_HIGH) {
  428. /* Foot form constraints high. */
  429. my constraints [FtNonfinal]. ranking = 101.0;
  430. my constraints [Iambic]. ranking = 101.0;
  431. my constraints [Trochaic]. ranking = -1e9;
  432. }
  433. if (equal_footForm_wsp == kOTGrammar_createMetricsGrammar_initialRanking::WSP_HIGH) {
  434. /* Quantity sensitivity high, foot form constraints in the second stratum. */
  435. my constraints [WSP]. ranking = 102.0;
  436. }
  437. integer numberOfCandidates = 0;
  438. for (int numberOfSyllables = 2; numberOfSyllables <= 7; numberOfSyllables ++) {
  439. integer numberOfUnderlyingWeightPatterns = numberOfSyllables > 5 ? 1 : Melder_iround (pow (maximumUnderlyingWeight, numberOfSyllables));
  440. numberOfCandidates += ( includeCodas ? numberOfCandidates_codas : numberOfCandidates_noCodas ) [numberOfSyllables] * numberOfUnderlyingWeightPatterns;
  441. }
  442. my candidates = NUMvector <structOTCandidate> (1, numberOfCandidates);
  443. my numberOfCandidates = 0;
  444. for (int numberOfSyllables = 2; numberOfSyllables <= 7; numberOfSyllables ++) {
  445. integer numberOfUnderlyingWeightPatterns = numberOfSyllables > 5 ? 1 : Melder_iround (pow (maximumUnderlyingWeight, numberOfSyllables));
  446. for (integer isyll = 1; isyll <= numberOfSyllables; isyll ++) {
  447. underlyingWeightPattern [isyll] = 1; /* L or cv */
  448. }
  449. for (integer iweightPattern = 1; iweightPattern <= numberOfUnderlyingWeightPatterns; iweightPattern ++) {
  450. fillTableau (me.get(), numberOfSyllables, underlyingWeightPattern, overtFormsHaveSecondaryStress, includeCodas);
  451. /*
  452. * Cycle to next underlying weight pattern.
  453. */
  454. underlyingWeightPattern [numberOfSyllables] += 1;
  455. for (integer isyll = numberOfSyllables; isyll >= 2; isyll --) {
  456. if (underlyingWeightPattern [isyll] > maximumUnderlyingWeight) {
  457. underlyingWeightPattern [isyll] = 1;
  458. underlyingWeightPattern [isyll - 1] += 1;
  459. }
  460. }
  461. }
  462. }
  463. Melder_assert (my numberOfCandidates == numberOfCandidates);
  464. /* Compute violation marks. */
  465. for (integer icand = 1; icand <= my numberOfCandidates; icand ++) {
  466. computeViolationMarks (& my candidates [icand]);
  467. }
  468. OTMulti_checkIndex (me.get());
  469. OTMulti_newDisharmonies (me.get(), 0.0);
  470. if (trochaicityConstraint == 1) {
  471. OTMulti_removeConstraint (me.get(), U"Trochaic");
  472. } else {
  473. OTMulti_removeConstraint (me.get(), U"FtNonfinal");
  474. }
  475. if (! includeFootBimoraic) OTMulti_removeConstraint (me.get(), U"FtBimor");
  476. if (! includeFootBisyllabic) OTMulti_removeConstraint (me.get(), U"FtBisyl");
  477. if (! includePeripheral) OTMulti_removeConstraint (me.get(), U"Peripheral");
  478. if (nonfinalityConstraint == 1) {
  479. OTMulti_removeConstraint (me.get(), U"MainNonfinal");
  480. OTMulti_removeConstraint (me.get(), U"HeadNonfinal");
  481. } else if (nonfinalityConstraint == 2) {
  482. OTMulti_removeConstraint (me.get(), U"HeadNonfinal");
  483. OTMulti_removeConstraint (me.get(), U"Nonfinal");
  484. } else {
  485. OTMulti_removeConstraint (me.get(), U"MainNonfinal");
  486. OTMulti_removeConstraint (me.get(), U"Nonfinal");
  487. }
  488. if (! includeClashAndLapse) {
  489. OTMulti_removeConstraint (me.get(), U"*Clash");
  490. OTMulti_removeConstraint (me.get(), U"*Lapse");
  491. }
  492. if (! includeCodas) {
  493. OTMulti_removeConstraint (me.get(), U"WeightByPosition");
  494. OTMulti_removeConstraint (me.get(), U"*C\\mu");
  495. }
  496. if (includeCodas) {
  497. for (integer icand = 1; icand <= my numberOfCandidates; icand ++) {
  498. replaceOutput (& my candidates [icand]);
  499. }
  500. }
  501. return me;
  502. } catch (MelderError) {
  503. Melder_throw (U"Metrics grammar not created.");
  504. }
  505. }
  506. /* End of file OTMulti_ex_metrics.cpp */