├── .DS_Store ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── auxiliaries.pl ├── d_grammar.pl ├── d_grammar_case.pl ├── dancing_links.pl ├── hybrid_case.pl ├── hybrid_grammar.pl ├── lambek_grammar.pl ├── latex.pl ├── lexicon.pl ├── ll1_grammar.pl ├── mill1.pl ├── mill1.tgz ├── options.pl ├── ordset.pl ├── portray_graph_dot.pl ├── portray_graph_none.pl ├── portray_graph_tikz.pl ├── proof_generation.pl ├── proof_generation_nd.pl ├── replace.pl ├── sem_utils.pl ├── semantic_terms.pdf ├── translations.pl └── tree234.pl /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RichardMoot/LinearOne/55540e9a91b7a5c7722775f39ffbf50f5b472a7e/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore emacs backups 2 | *~ 3 | # ignore parse logs 4 | parse_log.txt 5 | fish_log*.txt 6 | # ignore (Lua)LaTeX graph and proof files 7 | test_graph.pdf 8 | lexicon*.pdf 9 | lexicon.tex 10 | lexicon.aux 11 | lexicon.log 12 | graph.* 13 | latex_proofs.* 14 | whiskas.* 15 | big_whiskas.* 16 | texput.log 17 | # ignore files automatically generated by exhaustive_test/6 18 | delib.pl 19 | deliberately.pl 20 | and.pl 21 | fish.pl 22 | test.pl 23 | test_grammar.pl 24 | test_grammar2.pl 25 | new_grammar.pl 26 | lsa_grammar.pl 27 | tmp*.txt 28 | grammar.tgz 29 | hybrid_split.pl 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | 504 | 505 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | mill1.tgz: *.pl 3 | tar cvfzH mill1.tgz *.pl 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LinearOne 2 | 3 | :copyright: 2015-2019 [CNRS](http://www.cnrs.fr) 4 | 5 | :copyright: 2015-2019 Richard Moot (@RichardMoot) 6 | 7 | This research has received financial support from the ANR CONTINT, project POLYMNIE (ANR-12-CORD-0004). 8 | 9 | LinearOne is a prototype theorem prover/parser for first-order (multiplicative, intuitionistic) linear logic. It also supports (by translation) parsing of hybrid type-logical grammars and Displacement calculus grammars. 10 | 11 | LinearOne is provided under the GNU Lesser General Public License (see the included file LICENSE for details). 12 | 13 | LinearOne is a set of SWI Prolog files, which optional graph output to LuaLaTeX (using the TikZ 3.0.0 graph drawing libraries) and proof output to LaTeX/pdfLaTeX/luaLaTeX. 14 | 15 | # Quick start 16 | 17 | ### Starting Prolog 18 | 19 | After downloading, enter the LinearOne directory and type. 20 | 21 | ``` 22 | swipl # (or the name of SWI Prolog on your system) 23 | ``` 24 | 25 | This will start SWI Prolog. 26 | 27 | ### Loading the source and the grammars 28 | 29 | In SWI Prolog, type 30 | 31 | ``` 32 | [mill1,d_grammar]. 33 | ``` 34 | 35 | to load the library files and the example Displacement calculus grammar, there is a hybrid type-logical grammar available as well. 36 | 37 | ``` 38 | [hybrid_grammar]. 39 | ``` 40 | 41 | ### Parsing 42 | 43 | To try one of the examples in either grammar, use 44 | 45 | ``` 46 | test(1). % (check the grammar files to see the available examples). 47 | ``` 48 | 49 | You can also use 50 | 51 | ``` 52 | parse([john,ate,more,donuts,than,mary,bought,bagels], s). 53 | ``` 54 | 55 | to directly parse a sentence. Check the lexicon and experiment a bit with the grammars yourself. 56 | 57 | ### Viewing the output 58 | 59 | When a parse is found, it is output to the file `latex_proofs.tex` and a pdf file `latex_proofs.pdf` is automatically produced. View `latex_proofs.pdf` with your favorite previewer. You will probably need to zoom in for larger proofs. 60 | 61 | # Troubleshooting 62 | 63 | 64 | ### No LaTeX output is produced! 65 | 66 | Make sure that you have write permissions in the LinearOne directory and that Prolog can find your LaTeX installation. To find the location of pdflatex type the following in a shell terminal 67 | 68 | ``` 69 | where pdflatex 70 | ``` 71 | 72 | Add the required path to the file `mill1.pl`. For example, the path `/usr/texbin/` is added as follows. 73 | 74 | ``` 75 | user:file_search_path(path, '/usr/texbin/'). 76 | ``` 77 | 78 | It is also possible that LaTeX aborts with an error (verify the file `latex_proofs.tex`). 79 | 80 | ### The proofs don't fit the page! 81 | 82 | The `geometry/1` predicate in the file `latex.pl` can be modified to the desired page size. Comment out all but the desired page size (or add your own preferred page size). Zooming will be necessary! 83 | 84 | ### I don't see any graph output 85 | 86 | Graph output is optional. In the file mill1.pl, comment out the line 87 | 88 | ``` 89 | use_module(portray_graph_none,...) 90 | ``` 91 | 92 | and remove the comments from line 93 | 94 | ``` 95 | use_module(portray_graph_tikz,...) 96 | ``` 97 | 98 | Also make sure your LaTeX installation includes lualatex and Tikz 3.0.0 or later (that is, you need a 2014 or later LaTeX installation). 99 | -------------------------------------------------------------------------------- /auxiliaries.pl: -------------------------------------------------------------------------------- 1 | :- module(auxiliaries, [select_formula/4, 2 | is_ll1_formula/1, 3 | is_ll1_formula/2, 4 | count_check/4, 5 | subproofs/2, 6 | rulename/2, 7 | is_axiom/1, 8 | merge_fvs/3, 9 | universal_closure/2, 10 | universal_disclosure/2, 11 | free_vars_n/2, 12 | free_vars_p/2, 13 | free_vars/2, 14 | antecedent/2, 15 | non_member/2, 16 | identical_prefix/3, 17 | identical_postfix/3, 18 | identical_lists/2, 19 | split_list/4]). 20 | 21 | :- use_module(ordset, [ord_union/3, ord_delete/3, ord_insert/3]). 22 | 23 | % = is_ll1_formula(+Term) 24 | % 25 | % true if Term is a correct first-order linear logic formula; outputs error message and fails if it is not 26 | 27 | % proposition 28 | is_ll1_formula(at(_)) :- 29 | !. 30 | % predicate 31 | is_ll1_formula(at(_, _)) :- 32 | !. 33 | is_ll1_formula(forall(_,A)) :- 34 | !, 35 | is_ll1_formula(A). 36 | is_ll1_formula(exists(_,A)) :- 37 | !, 38 | is_ll1_formula(A). 39 | is_ll1_formula(impl(A,B)) :- 40 | !, 41 | is_ll1_formula(A), 42 | is_ll1_formula(B). 43 | is_ll1_formula(p(A,B)) :- 44 | !, 45 | is_ll1_formula(A), 46 | is_ll1_formula(B). 47 | is_ll1_formula(Term) :- 48 | functor(Term, F, A), 49 | format(user_error, '{Error: unknown term ~w/~w used in first-order linear logic entry!}', [F,A]), 50 | fail. 51 | 52 | % = is_ll1_formula(+Term, +Word) 53 | % 54 | % true if Term is a correct first-order linear logic formula; outputs error message and fails if it is not 55 | 56 | % proposition 57 | is_ll1_formula(at(_), _) :- 58 | !. 59 | % predicate 60 | is_ll1_formula(at(_, _), _) :- 61 | !. 62 | is_ll1_formula(forall(_,A), W) :- 63 | !, 64 | is_ll1_formula(A, W). 65 | is_ll1_formula(exists(_,A), W) :- 66 | !, 67 | is_ll1_formula(A, W). 68 | is_ll1_formula(impl(A,B), W) :- 69 | !, 70 | is_ll1_formula(A, W), 71 | is_ll1_formula(B, W). 72 | is_ll1_formula(p(A,B), W) :- 73 | !, 74 | is_ll1_formula(A, W), 75 | is_ll1_formula(B, W). 76 | is_ll1_formula(Term, W) :- 77 | functor(Term, F, A), 78 | format(user_error, '{Error: unknown term ~w/~w used in first-order linear logic entry for "~w"!}', [F,A,W]), 79 | fail. 80 | 81 | 82 | % = select_formula(+Formula, +Index, +List, -Rest) 83 | % 84 | % selects Index-Formula pair from list, using forced-choice 85 | % determinism 86 | 87 | select_formula(F, N, L0, L) :- 88 | select(N-F, L0, L), 89 | !. 90 | 91 | 92 | count_check(LN, LP, AtName, Rest) :- 93 | Count is LP - LN, 94 | ( 95 | Count =:= 0 96 | -> 97 | true 98 | ; 99 | format(user_error, '~NCount check failure: count(~w)= ~w', [AtName, Count]), 100 | print_count_offenders(Rest), 101 | fail 102 | ). 103 | 104 | print_count_offenders([]) :- 105 | nl(user_error). 106 | print_count_offenders([AtName-atoms(Pos, Neg)|Rest]) :- 107 | length(Pos, LP), 108 | length(Neg, LN), 109 | Count is LP - LN, 110 | ( 111 | Count =:= 0 112 | -> 113 | true 114 | ; 115 | format(user_error, ', count(~w)= ~w', [AtName, Count]) 116 | ), 117 | print_count_offenders(Rest). 118 | 119 | % = print_diff_lists(+List1, +List2) 120 | % 121 | % supposing List1 and List2 have the same length, we print the members of the two lists 122 | % side-by-side, marking by * the elements which differ between the two lists 123 | 124 | print_diff_lists([], []). 125 | print_diff_lists([A|As], [B|Bs]) :- 126 | copy_term(A, AA), 127 | copy_term(B, BB), 128 | numbervars(AA, 0, _), 129 | numbervars(BB, 0, _), 130 | ( A == B -> C = ' ' ; C = '*' ), 131 | format(user_error, '~w~t~w~50|~t~w~100|~w~n', [C,AA,BB,C]), 132 | print_diff_lists(As, Bs). 133 | 134 | % = sub_proofs(+Proof, ?SubProofList) 135 | % 136 | % true if SubProofList is the list of premisses of the current rule 137 | 138 | subproofs(_-R, S) :- 139 | subproofs(R, S). 140 | subproofs(rule(_,_,_,S), S). 141 | 142 | % = rule(+Proof, ?RuleName) 143 | % 144 | % true if RuleName is the name of the current rule 145 | 146 | rulename(_-R, N) :- 147 | rulename(R, N). 148 | rulename(rule(N,_,_,_), N). 149 | 150 | % = antecedent(+Proof, ?Antecedent) 151 | % 152 | % true if Antecedent is the antecedent of the conclusion of the 153 | % given Proof. 154 | 155 | antecedent(_-R, Ant) :- 156 | antecedent(R, Ant). 157 | antecedent(rule(_,Ant,_,_), Ant). 158 | 159 | % = is_axiom(+Proof) 160 | % 161 | % true if Proof is an axiom rule 162 | 163 | is_axiom(_-R) :- 164 | is_axiom(R). 165 | is_axiom(rule(ax,_,_,_)). 166 | 167 | 168 | % merge two sets of free variables 169 | % remove variables already instantiated (these have an integer value) 170 | % we need to sort again (since variable instantiations/unifications may 171 | % have changed term order) 172 | 173 | merge_fvs(Vs0, Ws0, Zs) :- 174 | reduce_fvs(Vs0, Vs1), 175 | sort(Vs1, Vs), 176 | reduce_fvs(Ws0, Ws1), 177 | sort(Ws1, Ws), 178 | ord_union(Vs, Ws, Zs). 179 | 180 | reduce_fvs([], []). 181 | reduce_fvs([V|Vs], Ws) :- 182 | ( 183 | integer(V) 184 | -> 185 | reduce_fvs(Vs, Ws) 186 | ; 187 | Ws = [V|Ws0], 188 | reduce_fvs(Vs, Ws0) 189 | ). 190 | 191 | % = universal_closure(+Formula, +ClosedFormula) 192 | 193 | universal_closure(Formula, ClosedFormula) :- 194 | free_vars(Formula, FreeVars), 195 | universal_closure(FreeVars, Formula, ClosedFormula). 196 | 197 | universal_closure([], Formula, Formula). 198 | universal_closure([X|Xs], Formula0, Formula) :- 199 | ( 200 | var(X) 201 | -> 202 | universal_closure(Xs, forall(X,Formula0), Formula) 203 | ; 204 | universal_closure(Xs, Formula0, Formula) 205 | ). 206 | 207 | % = 208 | 209 | universal_disclosure(forall(_,A0), A) :- 210 | !, 211 | universal_disclosure(A0, A). 212 | universal_disclosure(A, A). 213 | 214 | % = free_vars_n(+Formula, -SetOfFreeVars) 215 | % 216 | % true if Formula (of negative polariy) has 217 | % SetOfFreeVars, but with a slight twist: all 218 | % variables bound by a tensor prefix are 219 | % considered free. For example, a prefix of 220 | % universal quantifiers is removed (and, in 221 | % general, any negative forall/impl and 222 | % postive exists/prod); this is the implicit 223 | % tensor contraction rule). 224 | 225 | free_vars_n(_-A, Vars) :- 226 | free_vars_n(A, Vars). 227 | free_vars_n(at(_, Vars0), Vars) :- 228 | free_vars_list(Vars0, Vars). 229 | free_vars_n(at(_, _, _, Vars0), Vars) :- 230 | free_vars_list(Vars0, Vars). 231 | free_vars_n(p(A,B), Vars) :- 232 | free_vars(A, Vars1), 233 | free_vars(B, Vars2), 234 | ord_union(Vars1, Vars2, Vars). 235 | free_vars_n(impl(A,B), Vars) :- 236 | free_vars_p(A, Vars1), 237 | free_vars_n(B, Vars2), 238 | ord_union(Vars1, Vars2, Vars). 239 | free_vars_n(forall(_,A), Vars) :- 240 | free_vars_n(A, Vars). 241 | free_vars_n(exists(X,A), Vars) :- 242 | free_vars(A, Vars0), 243 | ord_delete(Vars0, X, Vars). 244 | 245 | 246 | is_variable(X) :- 247 | ( 248 | var(X) 249 | -> 250 | true 251 | ; 252 | X = var(_) 253 | -> 254 | true 255 | ; 256 | X = '$VAR'(_) 257 | -> 258 | true 259 | ). 260 | 261 | free_vars_list(Vs, Ws) :- 262 | free_vars_list(Vs, [], Ws). 263 | 264 | free_vars_list([], Ws, Ws). 265 | free_vars_list([V|Vs], Ws0, Ws) :- 266 | ( 267 | is_variable(V) 268 | -> 269 | ord_insert(Ws0, V, Ws2) 270 | ; 271 | atomic(V) 272 | -> 273 | Ws2 = Ws0 274 | ; 275 | compound(V) 276 | -> 277 | V =..[_|As], 278 | free_vars_list(As, [], Ws1), 279 | ord_union(Ws0, Ws1, Ws2) 280 | ), 281 | free_vars_list(Vs, Ws2, Ws). 282 | 283 | % = free_vars_p(+Formula, -SetOfFreeVars) 284 | % 285 | % true if Formula (of positive polariy) has 286 | % SetOfFreeVars, but with a slight twist: all 287 | % variables bound by a tensor prefix are 288 | % considered free (this is the implicit tensor 289 | % contraction rule). 290 | 291 | free_vars_p(_-A, Vars) :- 292 | free_vars_p(A, Vars). 293 | free_vars_p(at(_, Vars0), Vars) :- 294 | free_vars_list(Vars0, Vars). 295 | free_vars_p(at(_, _, _, Vars0), Vars) :- 296 | free_vars_list(Vars0, Vars). 297 | free_vars_p(p(A,B), Vars) :- 298 | free_vars_p(A, Vars1), 299 | free_vars_p(B, Vars2), 300 | ord_union(Vars1, Vars2, Vars). 301 | free_vars_p(impl(A,B), Vars) :- 302 | free_vars(A, Vars1), 303 | free_vars(B, Vars2), 304 | ord_union(Vars1, Vars2, Vars). 305 | free_vars_p(exists(_,A), Vars) :- 306 | free_vars_p(A, Vars). 307 | free_vars_p(forall(X,A), Vars) :- 308 | free_vars(A, Vars0), 309 | ord_delete(Vars0, X, Vars). 310 | 311 | % = free_vars(+Formula, -SetOfFreeVars) 312 | % 313 | % true if Formula has SetOfFreeVars under the 314 | % standard interpretation of free/bound. 315 | 316 | free_vars(_-A, Vars) :- 317 | free_vars(A, Vars). 318 | free_vars(at(_, Vars0), Vars) :- 319 | free_vars_list(Vars0, Vars). 320 | free_vars(at(_, _, _, Vars0), Vars) :- 321 | free_vars_list(Vars0, Vars). 322 | free_vars(p(A,B), Vars) :- 323 | free_vars(A, Vars1), 324 | free_vars(B, Vars2), 325 | ord_union(Vars1, Vars2, Vars). 326 | free_vars(impl(A,B), Vars) :- 327 | free_vars(A, Vars1), 328 | free_vars(B, Vars2), 329 | ord_union(Vars1, Vars2, Vars). 330 | free_vars(exists(X,A), Vars) :- 331 | free_vars(A, Vars0), 332 | ord_delete(Vars0, X, Vars). 333 | free_vars(forall(X,A), Vars) :- 334 | free_vars(A, Vars0), 335 | ord_delete(Vars0, X, Vars). 336 | 337 | % = non_member(+Element, +List) 338 | % 339 | % true if Element is not a member of List (that is if it is not strictly 340 | % equal to one of the members of List; member_chk(Element, List) must fail). 341 | 342 | non_member(_, []). 343 | non_member(X, [Y|Ys]) :- 344 | X \== Y, 345 | non_member(X, Ys). 346 | 347 | % = identical_prefix(+Prefix, -PostFix, +List) 348 | % 349 | % true if Prefix is a prefix of List using strict identity instead 350 | % of unifiability; returns the PostFix 351 | 352 | identical_prefix([], Ys, Ys). 353 | identical_prefix([X|Xs], Zs, [Y|Ys]) :- 354 | X == Y, 355 | identical_prefix(Xs, Zs, Ys). 356 | 357 | % = identical_postfix(-Prefix, +PostFix, +List) 358 | % 359 | % true if Postfix is a postfix of List using strict identity instead 360 | % of unifiability; returns the Prefix 361 | 362 | identical_postfix(Xs, Ys, Zs) :- 363 | length(Ys, N), 364 | length(PostFix, N), 365 | append(Xs, PostFix, Zs), 366 | identical_lists(PostFix, Ys). 367 | 368 | % = identical_lists(+List1, +List2) 369 | % 370 | % true if List1 and List2 are strictly identical (essentially List1 == List2, 371 | % but checks that both arguments are proper lists) 372 | 373 | identical_lists([], []). 374 | identical_lists([X|Xs], [Y|Ys]) :- 375 | X == Y, 376 | identical_lists(Xs, Ys). 377 | 378 | % = split_list(+List, +Element, -Before, -After) 379 | % 380 | % as select/3, but returns two lists, one with the prefix of List before Element 381 | % and one with the suffix of List after Element 382 | % in other words, append(Before, [Element|After], List) is true 383 | 384 | split_list([A|As], A, [], As) :- 385 | !. 386 | split_list([A|As0], C, [A|As], Bs) :- 387 | split_list(As0, C, As, Bs). 388 | -------------------------------------------------------------------------------- /d_grammar.pl: -------------------------------------------------------------------------------- 1 | % ================================= 2 | % = Displacement calculus grammar = 3 | % ================================= 4 | 5 | % This grammar contains many examples from 6 | % 7 | % Glyn Morrill, Oriol Valentin and Mario Fadda (2011), 8 | % The Displacement Calculus, Journal of Logic, Language 9 | % and Information 20, p. 1-48. 10 | 11 | % define operators to allow for easier specification of 12 | % displacement calculus lexical entries. 13 | % 14 | % WARNING: in case of doubt, use parentheses to disambiguate! 15 | % I have deliberately not changed the definitions of standard 16 | % mathematical and logical operations of Prolog, notably | 17 | % (alternative of ; for use in DCG), / and *. 18 | % 19 | % This means for example that: 20 | % c/d*b/c = ((c/d)*b)/c 21 | % which corresponds to a left-to-right evaluation of the 22 | % mathematical functions of division and multiplication. 23 | % However, we do have the familiar a/b/c = (a/b)/c and 24 | % c\b\a = (c\(b\a) and even a\b/c = (a\b)/c. 25 | 26 | :- op(400, xfy, \). 27 | :- op(400, xfy, \>). % = \downarrow_> 28 | :- op(400, yfx, />). % = \uparrow_> 29 | :- op(400, xfy, \<). % = \downarrow_< 30 | :- op(400, yfx, /<). % = \uparrow_> 31 | :- op(400, yfx, *<). % = \odot_< 32 | :- op(400, yfx, *>). % = \odot_> 33 | 34 | :- abolish(lex/3), abolish(lex/4), abolish(lex/5), abolish(atomic_formula/3), abolish(atomic_formula/1), abolish(test/1), abolish(macro/2). 35 | 36 | % ======================= 37 | % = Example Sentences = 38 | % ======================= 39 | 40 | 41 | test(0) :- 42 | parse([mary,gave,john,the_cold_shoulder], s). 43 | test(1) :- 44 | parse([john,gave,every,book,to,mary], s). 45 | test(2) :- 46 | parse([john,gave2,every,book,to,mary], s). 47 | test(3) :- 48 | parse([mary,thinks,someone,left], s). 49 | test(4) :- 50 | parse([everyone,loves,someone], s). 51 | test(5) :- 52 | parse([john,slept,before,mary,did], s). 53 | test(6) :- 54 | parse([dog,that,mary,saw,today], cn). 55 | test(7) :- 56 | parse([bagels,which,john,sold,for,ten_million_dollars], cn). 57 | test(8) :- 58 | parse([mountain,the,painting,of,which,by,cezanne,john,sold,for,ten_million_dollars], cn). 59 | test(9) :- 60 | parse([john,who,jogs,sneezed], s). 61 | test(10) :- 62 | parse([john,studies,logic,and,charles,phonetics], s). 63 | test(11) :- 64 | parse([john,ate,more,donuts,than,mary,bought,bagels], s). 65 | test(12) :- 66 | parse([dat,jan,boeken,las], cs). 67 | test(13) :- 68 | parse([dat,jan,boeken,kan,lezen], cs). 69 | test(14) :- 70 | parse([dat,jan,boeken,wil,kunnen,lezen], cs). 71 | test(15) :- 72 | parse([dat,jan,alles,las], cs). 73 | test(16) :- 74 | parse([dat,jan,alles,kan,lezen], cs). 75 | test(17) :- 76 | parse([dat,jan,cecilia,de,nijlpaarden,zag,voeren], cs). 77 | test(18) :- 78 | parse([dat,jan,cecilia,henk,de,nijlpaarden,zag,helpen,voeren], cs). 79 | test(19) :- 80 | parse([wil2,jan,boeken,lezen], q). 81 | test(20) :- 82 | parse([jan,wil2,boeken,lezen], n*(^(q/,appl(Y,Z)))))). 147 | lex(someone, (s/>n)\n)\(n\s))/(n\s))\((n\s)/>(n\s)), lambda(X,lambda(Y,appl(appl(X,Y),Y)))). 151 | lex(that, (cn\cn)/(^(s/n)\n)/n), lambda(X,lambda(Y,appl(appl(X,Y),Y)))). 159 | 160 | % = Dutch 161 | 162 | lex(dat, cs/s, lambda(X,X)). 163 | lex(jan, n, j). 164 | lex(henk, n, h). 165 | lex(cecilia, n, c). 166 | lex(nijlpaarden, cn, hippos). 167 | lex(de, n/cn, iota). 168 | lex(boeken, n, b). 169 | lex(las, n\(n\s), read). 170 | lex(kan, (n\si)\<(n\s), lambda(VP,lambda(S,appl(appl(can,appl(VP,S)),S)))). 171 | lex(wil, (n\si)\<(n\s), lambda(VP,lambda(S,appl(appl(want,appl(VP,S)),S)))). 172 | lex(kunnen, rproj((n\si)\<(n\si)), lambda(VP,lambda(S,appl(appl(can,appl(VP,S)),S)))). 173 | lex(lezen, rproj(n\(n\si)), read). 174 | lex(voeren, rproj(n\(n\si)), feed). 175 | lex(alles, (s/,appl(X,Y))))). 176 | lex(alles, (si/,appl(X,Y))))). 177 | lex(zag, (n\si)\<(n\(n\s)), lambda(VP,lambda(X,lambda(Y,appl(appl(appl(see,appl(VP,X)),X),Y))))). 178 | lex(helpen, rproj((n\si)\<(n\(n\si))), lambda(VP,lambda(X,lambda(Y,appl(appl(appl(help,appl(VP,X)),X),Y))))). 179 | lex(wil2, q/(^(s/<((n\si)\<(n\s)))), lambda(P,appl(P,lambda(Q,lambda(X,appl(appl(want,appl(Q,X)),X)))))). 180 | -------------------------------------------------------------------------------- /d_grammar_case.pl: -------------------------------------------------------------------------------- 1 | % ================================= 2 | % = Displacement calculus grammar = 3 | % ================================= 4 | 5 | % This grammar is a version of the file "d_grammar.pl" with the 6 | % addition of case for noun phrases. As the original "d_grammar.pl" 7 | % this grammar contains many examples from 8 | % 9 | % Glyn Morrill, Oriol Valentin and Mario Fadda (2011), 10 | % The Displacement Calculus, Journal of Logic, Language 11 | % and Information 20, p. 1-48. 12 | 13 | % define operators to allow for easier specification of 14 | % displacement calculus lexical entries. 15 | % 16 | % WARNING: in case of doubt, use parentheses to disambiguate! 17 | % I have deliberately not changed the definitions of standard 18 | % mathematical and logical operations of Prolog, notably | 19 | % (alternative of ; for use in DCG), / and *. 20 | % 21 | % This means for example that: 22 | % c/d*b/c = ((c/d)*b)/c 23 | % which corresponds to a left-to-right evaluation of the 24 | % mathematical functions of division and multiplication. 25 | % However, we do have the familiar a/b/c = (a/b)/c and 26 | % c\b\a = (c\(b\a) and even a\b/c = (a\b)/c. 27 | 28 | :- op(400, xfy, \). 29 | :- op(400, xfy, \>). % = \downarrow_> 30 | :- op(400, yfx, />). % = \uparrow_> 31 | :- op(400, xfy, \<). % = \downarrow_< 32 | :- op(400, yfx, /<). % = \uparrow_> 33 | :- op(400, yfx, *<). % = \odot_< 34 | :- op(400, yfx, *>). % = \odot_> 35 | 36 | 37 | :- abolish(lex/3), abolish(lex/4), abolish(lex/5), abolish(test/1), abolish(atomic_formula/1), abolish(atomic_formula/3), abolish(macro/2). 38 | 39 | atomic_formula(n(_,_,_)). 40 | 41 | % ======================= 42 | % = Example Sentences = 43 | % ======================= 44 | 45 | 46 | test(0) :- 47 | parse([mary,gave,john,the_cold_shoulder], s). 48 | test(1) :- 49 | parse([john,gave,every,book,to,mary], s). 50 | test(2) :- 51 | parse([john,gave2,every,book,to,mary], s). 52 | test(3) :- 53 | parse([mary,thinks,someone,left], s). 54 | test(4) :- 55 | parse([everyone,loves,someone], s). 56 | test(5) :- 57 | parse([john,slept,before,mary,did], s). 58 | test(6) :- 59 | parse([dog,that,mary,saw,today], cn). 60 | test(7) :- 61 | parse([bagels,which,john,sold,for,ten_million_dollars], cn). 62 | test(8) :- 63 | parse([mountain,the,painting,of,which,by,cezanne,john,sold,for,ten_million_dollars], cn). 64 | test(9) :- 65 | parse([john,who,jogs,sneezed], s). 66 | test(10) :- 67 | parse([john,studies,logic,and,charles,phonetics], s). 68 | test(11) :- 69 | parse([john,ate,more,donuts,than,mary,bought,bagels], s). 70 | test(12) :- 71 | parse([dat,jan,boeken,las], cs). 72 | test(13) :- 73 | parse([dat,jan,boeken,kan,lezen], cs). 74 | test(14) :- 75 | parse([dat,jan,boeken,wil,kunnen,lezen], cs). 76 | test(15) :- 77 | parse([dat,jan,alles,las], cs). 78 | test(16) :- 79 | parse([dat,jan,alles,kan,lezen], cs). 80 | test(17) :- 81 | parse([dat,jan,cecilia,de,nijlpaarden,zag,voeren], cs). 82 | test(18) :- 83 | parse([dat,jan,cecilia,henk,de,nijlpaarden,zag,helpen,voeren], cs). 84 | test(19) :- 85 | parse([wil2,jan,boeken,lezen], q). 86 | test(20) :- 87 | parse([jan,wil2,boeken,lezen], n(A,B,C)*(^(q/,appl(Y,Z)))))). 163 | lex(someone, (s/>n(_,_,_))\n(_,_,_))\(n(_,_,_)\s))/(n(_,_,_)\s))\((n(_,_,_)\s)/>(n(_,_,_)\s)), lambda(X,lambda(Y,appl(appl(X,Y),Y)))). 167 | lex(that, (cn\cn)/(^(s/n(A,B,C))\n(D,E,F))/n(D,E,F)), lambda(X,lambda(Y,appl(appl(X,Y),Y)))). 175 | 176 | % = Dutch 177 | 178 | lex(dat, cs/s, lambda(X,X)). 179 | lex(jan, n(sg,3,m), j). 180 | lex(henk, n(sg,3,m), h). 181 | lex(cecilia, n(sg,3,f), c). 182 | lex(nijlpaarden, cn, hippos). 183 | lex(de, n(_,_,_)/cn, iota). 184 | lex(boeken, n(pl,3,o), b). 185 | lex(las, n(_,_,_)\(n(_,_,_)\s), read). 186 | lex(kan, (n(A,B,C)\si)\<(n(A,B,C)\s), lambda(VP,lambda(S,appl(appl(can,appl(VP,S)),S)))). 187 | lex(wil, (n(A,B,C)\si)\<(n(A,B,C)\s), lambda(VP,lambda(S,appl(appl(want,appl(VP,S)),S)))). 188 | lex(kunnen, rproj((n(A,B,C)\si)\<(n(A,B,C)\si)), lambda(VP,lambda(S,appl(appl(can,appl(VP,S)),S)))). 189 | lex(lezen, rproj(n(_,_,_)\(n(_,_,_)\si)), read). 190 | lex(voeren, rproj(n(_,_,_)\(n(_,_,_)\si)), feed). 191 | lex(alles, (s/,appl(X,Y))))). 192 | lex(alles, (si/,appl(X,Y))))). 193 | lex(zag, (n(_,_,_)\si)\<(n(_,_,_)\(n(_,_,_)\s)), lambda(VP,lambda(X,lambda(Y,appl(appl(appl(see,appl(VP,X)),X),Y))))). 194 | lex(helpen, rproj((n(_,_,_)\si)\<(n(_,_,_)\(n(_,_,_)\si))), lambda(VP,lambda(X,lambda(Y,appl(appl(appl(help,appl(VP,X)),X),Y))))). 195 | lex(wil2, q/(^(s/<((n(sg,_,_)\si)\<(n(sg,_,_)\s)))), lambda(P,appl(P,lambda(Q,lambda(X,appl(appl(want,appl(Q,X)),X)))))). 196 | -------------------------------------------------------------------------------- /dancing_links.pl: -------------------------------------------------------------------------------- 1 | :- module(dancing_links, [compute_axioms/4, update_roots_axiom/4, update_roots_contraction/5]). 2 | 3 | :- use_module(ordset, [ord_union/3,ord_insert/3,ord_member/2,ord_select/3]). 4 | :- use_module(tree234, [btree_init/1,btree_get_replace/5,btree_insert/4,btree_to_list/2,btree_get/3]). 5 | :- use_module(auxiliaries, [count_check/4]). 6 | 7 | % ======================================= 8 | % = Dancing links = 9 | % ======================================= 10 | 11 | % = compute most restricted axioms. 12 | 13 | compute_axioms(Root, Graph, ATree, Axioms) :- 14 | btree_init(Tree0), 15 | compute_ancestors(Root, Graph, Tree0, Tree), 16 | collect_atoms(Graph, ATree), 17 | best_axiom(ATree, Tree, Axioms). 18 | 19 | % get all atomic formulas from the graph 20 | 21 | collect_atoms(Graph, Tree) :- 22 | btree_init(Tree0), 23 | collect_atoms(Graph, Tree0, Tree). 24 | 25 | collect_atoms([], Tree, Tree). 26 | collect_atoms([vertex(N, Atoms, _, _)|Rest], Tree0, Tree) :- 27 | collect_atoms1(Atoms, N, Tree0, Tree1), 28 | collect_atoms(Rest, Tree1, Tree). 29 | 30 | collect_atoms1([], _, Tree, Tree). 31 | collect_atoms1([A|As], N, Tree0, Tree) :- 32 | collect_atom(A, N, Tree0, Tree1), 33 | collect_atoms1(As, N, Tree1, Tree). 34 | 35 | collect_atom(neg(Atom,Id1,Id2,_Sem,Vars), Num, Tree0, Tree) :- 36 | ( 37 | btree_get_replace(Tree0, Atom, atoms(Ps,Ns), atoms(Ps,[tuple(Id1,Id2,Num,Vars)|Ns]), Tree) 38 | -> 39 | true 40 | ; 41 | btree_insert(Tree0, Atom, atoms([],[tuple(Id1,Id2,Num,Vars)]), Tree) 42 | ). 43 | 44 | collect_atom(pos(Atom,Id1,Id2,_Sem,Vars), Num, Tree0, Tree) :- 45 | ( 46 | btree_get_replace(Tree0, Atom, atoms(Ps,Ns), atoms([tuple(Id1,Id2,Num,Vars)|Ps],Ns), Tree) 47 | -> 48 | true 49 | ; 50 | btree_insert(Tree0, Atom, atoms([tuple(Id1,Id2,Num,Vars)],[]), Tree) 51 | ). 52 | 53 | 54 | best_axiom(AtomTree, AncestorTree, Links) :- 55 | btree_to_list(AtomTree, List), 56 | best_axiom1(List, AncestorTree, Links). 57 | 58 | best_axiom1(List, ATree, Links) :- 59 | best_axiom1(List, ATree, min, _Min, [], Links). 60 | 61 | best_axiom1([], _, Min, Min, Links, Links). 62 | best_axiom1([AtName-atoms(Pos, Neg)|Rest], ATree, Min0, Min, Links0, Links) :- 63 | /* count check */ 64 | length(Pos, LP), 65 | length(Neg, LN), 66 | count_check(LN, LP, AtName, Rest), 67 | try_link_atoms(Pos, Neg, ATree, Min0, Min1, Links0, Links1), 68 | best_axiom1(Rest, ATree, Min1, Min, Links1, Links). 69 | 70 | 71 | try_link_atoms(Ps, Ns, ATree, Min0, Min, Links) :- 72 | try_link_atoms(Ps, Ns, ATree, Min0, Min, [], Links). 73 | 74 | try_link_atoms([], _, _, Min, Min, Links, Links). 75 | try_link_atoms([P|Ps], Ns, ATree, Min0, Min, Links0, Links) :- 76 | try_link_atom(Ns, [], 0, P, ATree, Min0, Min1, Links0, Links1), 77 | try_link_atoms(Ps, Ns, ATree, Min1, Min, Links1, Links). 78 | 79 | % we only need to keep track of the atoms with the *minimum* number of possible connections 80 | % (all of them, to allow for addition and evaluation of tie-breakers later). 81 | try_link_atom([], Options, NO, tuple(IdP1,IdP2,NumP,_), _, Min0, Min, Links0, Links) :- 82 | ( 83 | NO @< Min0 84 | -> 85 | /* new best choice, forget Min0 and Links0 */ 86 | Min = NO, 87 | Links = [tuple(IdP1,IdP2,NumP,Options)] 88 | ; 89 | NO == Min0 90 | -> 91 | /* same as best choice, remember for future tie-breaker */ 92 | Min = Min0, 93 | Links = [tuple(IdP1,IdP2,NumP,Options)|Links0] 94 | ; 95 | /* worse than other choices, forget Options */ 96 | Min = Min0, 97 | Links = Links0 98 | ). 99 | try_link_atom([tuple(IdN1,IdN2,NumN,VarsN)|Ns], Options0, NO0, tuple(IdP1,IdP2,NumP,VarsP), ATree, Min0, Min, Links0, Links) :- 100 | btree_get(ATree, NumN, AncN), 101 | btree_get(ATree, NumP, AncP), 102 | ( 103 | unifiable(VarsN, VarsP, _Unifier), 104 | \+ ord_member(NumP, AncN), 105 | \+ ord_member(NumN, AncP) 106 | -> 107 | /* possible axiom link, add to options */ 108 | Options = [tuple(IdN1,IdN2,NumN)|Options0], 109 | NO is NO0 + 1 110 | ; 111 | Options = Options0, 112 | NO = NO0 113 | ), 114 | try_link_atom(Ns, Options, NO, tuple(IdP1,IdP2,NumP,VarsP), ATree, Min0, Min, Links0, Links). 115 | 116 | % ======================================= 117 | % = Ancestor predicates = 118 | % ======================================= 119 | 120 | % compute for each node in the graph the set of its ancestors. 121 | % NOTE: we presuppose acyclicity throughout! 122 | 123 | compute_ancestors(Roots, Graph, Tree0, Tree) :- 124 | compute_ancestors(Roots, Graph, [], _, Tree0, Tree). 125 | 126 | compute_ancestors([], _, Visited, Visited, Tree, Tree). 127 | compute_ancestors([A|As], Graph, Visited0, Visited, Tree0, Tree) :- 128 | btree_insert(Tree0, A, [A], Tree1), 129 | ord_insert(Visited0, A, Visited1), 130 | visit(A, Graph, [A], Visited1, Visited2, Tree1, Tree2), 131 | compute_ancestors(As, Graph, Visited2, Visited, Tree2, Tree). 132 | 133 | % = visit(+Vertex, +Graph, ?Ancestors, +Visited). 134 | 135 | visit(N, Graph, Anc, V0, V, Tree0, Tree) :- 136 | graph_get(N, Graph, Edges), 137 | next_edges(Edges, Next0, []), 138 | sort(Next0, Next1), 139 | /* for cross edges, add the current ancestors */ 140 | ord_intersect(Next1, V0, Cross), 141 | update_cross(Cross, Anc, Tree0, Tree1), 142 | /* remove already visited nodes */ 143 | ord_subtract(Next1, V0, Next), 144 | visit_next(Next, Graph, Anc, V0, V, Tree1, Tree). 145 | 146 | visit_next([], _, _, V, V, Tree, Tree). 147 | visit_next([N|Ns], G, Anc0, V0, V, Tree0, Tree) :- 148 | ord_insert(Anc0, N, Anc), 149 | ord_insert(V0, N, V1), 150 | ( 151 | ord_member(N, V0) 152 | -> 153 | update_cross1(N, Anc, Tree0, Tree1) 154 | ; 155 | btree_insert(Tree0, N, Anc, Tree1) 156 | ), 157 | visit(N, G, Anc, V1, V2, Tree1, Tree2), 158 | visit_next(Ns, G, Anc0, V2, V, Tree2, Tree). 159 | 160 | update_cross([], _, Tree, Tree). 161 | update_cross([C|Cs], Anc, Tree0, Tree) :- 162 | update_cross1(C, Anc, Tree0, Tree1), 163 | update_cross(Cs, Anc, Tree1, Tree). 164 | update_cross1(C, Anc, Tree0, Tree) :- 165 | btree_get_replace(Tree0, C, As0, As, Tree), 166 | ord_union(Anc, As0, As). 167 | 168 | 169 | next_edges([], N, N). 170 | next_edges([P|Ps], N0, N) :- 171 | next_par(P, N0, N1), 172 | next_edges(Ps, N1, N). 173 | 174 | next_par(par(X,Y), [X,Y|Ns], Ns). 175 | next_par(univ(_,X), [X|Ns], Ns). 176 | 177 | graph_get(N, Graph, Ps) :- 178 | memberchk(vertex(N, _, _, Ps), Graph). 179 | 180 | 181 | % update_roots 182 | 183 | update_roots_axiom(Roots0, N0, N1, Roots) :- 184 | ( 185 | /* delete N0 if it is a root */ 186 | ord_select(N0, Roots0, Roots1) 187 | -> 188 | Bool = 1 189 | ; 190 | Roots1 = Roots0, Bool = 0 191 | ), 192 | /* delete N1 only when N0 wasn't a root */ 193 | ( Bool =:= 0, ord_select(N1, Roots1, Roots) 194 | -> 195 | true 196 | ; 197 | Roots = Roots1 198 | ). 199 | 200 | update_roots_contraction(Roots0, Graph, N0, N1, Roots) :- 201 | ( 202 | ord_select(N0, Roots0, Roots1) 203 | -> 204 | /* N1 does not necessarily become a root when N0 was, verify there are no other paths */ 205 | (is_root(Graph,N1) -> ord_insert(Roots1, N1, Roots) ; Roots = Roots1) 206 | ; 207 | Roots = Roots0 208 | ). 209 | 210 | is_root([], _). 211 | is_root([vertex(_, _, _, Ps)|Rest], N) :- 212 | next_edges(Ps, Next, []), 213 | \+ member(N, Next), 214 | is_root(Rest, N). -------------------------------------------------------------------------------- /hybrid_case.pl: -------------------------------------------------------------------------------- 1 | % ================================= 2 | % = Hybrid grammar = 3 | % ================================= 4 | 5 | % This grammar is a variant of hybrid_grammar.pl differing only in the addition of case to the noun phrases. 6 | % Like the original hybrid_grammar.pl, this grammar contains many examples from the following articles. 7 | % 8 | % Yusuke Kubota and Robert Levine (2012) Gapping as Like-Category Coordination, in Denis Bechet and 9 | % Alexander Dikovsky (eds), Logical Aspects of Computational Linguistics 2012, Springer Lecture Notes 10 | % in Computer Science 7351, pp. 135-150. 11 | % 12 | % Yusuke Kubota and Robert Levine (2013) Determiner Gapping as Higher-Order Discontinuous Constituency 13 | % in Glyn Morrill and Mark-Jan Nederhof (eds), Formal Grammar 2013, Springer Lecture Notes in Computer 14 | % Science 8036, pp. 225-241. 15 | 16 | % define operators to allow for easier specification of 17 | % hybrid type-logical grammar lexical entries. 18 | % 19 | % WARNING: in case of doubt, use parentheses to disambiguate! 20 | % I have deliberately not changed the definitions of standard 21 | % mathematical and logical operations of Prolog, notably | 22 | % (alternative of ; for use in DCG), / and *. 23 | % 24 | % This means for example that: 25 | % c/d*b/c = ((c/d)*b)/c 26 | % which corresponds to a left-to-right evaluation of the 27 | % mathematical functions of division and multiplication. 28 | % 29 | % It also means that (s|s|np) = (s|(s|np)) 30 | % 31 | % However, we do have the familiar a/b/c = (a/b)/c and 32 | % c\b\a = (c\(b\a) and even a\b/c = (a\b)/c. 33 | % 34 | % For lambda terms, X^M is short for lambda(X,M) and M@N 35 | % is short for appl(M,N). As expected, X^Y^Z^X@Y@Z is 36 | % short for lambda(X,lambda(Y,lambda(Z,appl(appl(X,Y),Z)))) 37 | % though be warned that X@Y+V@Z corresponds to (X@Y)+(V@Z) 38 | 39 | :- op(400, xfy, \). 40 | :- op(190, yfx, @). 41 | 42 | :- abolish(lex/3), abolish(lex/4), abolish(test/1), abolish(atomic_formula/3), abolish(atomic_formula/1), abolish(macro/2). 43 | 44 | % = define np as a (non-propositional) atomic formula with a single case argument 45 | 46 | atomic_formula(np(_)). 47 | 48 | test(1) :- 49 | parse([someone,talked,to,everyone,yesterday], s). 50 | test(2) :- 51 | parse([leslie,bought,a,cd,and1,robin,a,book], s1). 52 | test(3) :- 53 | parse([leslie,bought,a,cd,and,robin,a,book], s). 54 | test(4) :- 55 | parse([robin,must,discover,a,solution], s). 56 | test(5) :- 57 | parse([john,cant,eat,steak,and1,mary,pizza], s1). 58 | test(6) :- 59 | parse([john,cant,eat,steak,and,mary,pizza], s). 60 | % split scope 61 | test(7) :- 62 | parse([no2,neg,fish,walks], s). 63 | test(8) :- 64 | parse([no2,neg,dog,eats,whiskas,or2,neg,cat,alpo], s). 65 | % comparative subdeletion 66 | test(9) :- 67 | parse([john,ate,more,donuts,than,mary,bought,bagels], s). 68 | test(b) :- 69 | parse([john,ate,more2,donuts,than2,mary,bought,bagels], s). 70 | test(10) :- 71 | parse([no,fish,walks], s). 72 | % NOTE: The next two examples illustrate the improvement of the dancing links algorithm over the naive algorith rather spectacularly! 73 | test(11) :- 74 | /* first-found axioms */ 75 | /* 3,142,516 axioms ! */ 76 | /* 5,808,425,093 inferences, 2014.396 CPU in 2139.522 seconds (94% CPU, 2883458 Lips) */ 77 | /* with first dancing links version */ 78 | /* 28,640 axioms */ 79 | /* 65,938,819 inferences, 9.097 CPU in 9.842 seconds (92% CPU, 7248058 Lips) */ 80 | parse([no,dog,eats,whiskas,or,cat,alpo], s). 81 | test(12) :- 82 | /* first-found */ 83 | /* 4,215,069,209 axioms performed */ 84 | /* 3,014,184,930,660 inferences, 375241.334 CPU in 375357.875 seconds (100% CPU, 8032657 Lips) */ 85 | /* = 4d8h14m01.334s */ 86 | /* 59 proofs */ 87 | /* with first dancing links version */ 88 | /* 24,757,440 axioms */ 89 | /* 78,463,497,676 inferences, 10008.709 CPU in 10097.414 seconds (99% CPU, 7839522 Lips) */ 90 | /* = 2h46m48.709s */ 91 | /* 42 proofs (why this difference?) */ 92 | parse([no,dog,eats,more,whiskas2,than,leslie,buys,donuts,or,cat,alpo], s). 93 | 94 | 95 | 96 | test_and :- 97 | exhaustive_test('and.pl', and, ((((s| np)| np)| (s| np)| np)| (s| np)| np), lambda(M, lambda(J, lambda(K, lambda(L, bool(appl(appl(J, K), L), &, appl(appl(M, K), L)))))), [and], (((np\s)/np)\((np\s)/np))/((np\s)/np)). 98 | 99 | 100 | % ======================= 101 | % = Lexicon = 102 | % ======================= 103 | 104 | % = lex(+Word, +Formula, +ProsodicTerm, +SemanticTerm) 105 | % 106 | % ProsodicTerm must be a linear lambda term containing exactly one occurrence of Word 107 | 108 | lex(leslie, np(_), leslie, l). 109 | lex(robin, np(_), robin, r). 110 | lex(john, np(_), john, j). 111 | lex(mary, np(_), mary, m). 112 | lex(bought, tv_c, bought, buy). 113 | lex(buys, tv_c, buys, buy). 114 | lex(eats, tv_c, eats, eat). 115 | lex(ate, tv_c, ate, eat). 116 | lex(talked, (np(nom)\s)/pp, talked, talk). 117 | lex(discover, tv_c, discover, discover). 118 | lex(discovers, tv_c, discovers, discover). 119 | lex(walks, np(nom)\s, walks, walk). 120 | lex(eat, tv_c, eat, eat). 121 | lex(a, ((s|(s|np(_)))|n), lambda(N,lambda(P,lambda(Z,appl(appl(P,lambda(V,appl(a,appl(N,V)))),Z)))), lambda(X,lambda(Y,quant(exists,Z,bool(appl(X,Z),&,appl(Y,Z)))))). 122 | lex(every, ((s|(s|np(_)))|n), lambda(N, lambda(P,appl(P,every+N))), lambda(X,lambda(Y,quant(forall,Z,bool(appl(X,Z),->,appl(Y,Z)))))). 123 | lex(someone, (s|(s|np(_))), lambda(Pr,lambda(Z,appl(appl(Pr,someone),Z))), lambda(P,quant(exists,X,bool(appl(person,X),&,appl(P,X))))). 124 | lex(everyone, (s|(s|np(_))), lambda(Pr,lambda(Z,appl(appl(Pr,everyone),Z))), lambda(P,quant(forall,X,bool(appl(person,X),->,appl(P,X))))). 125 | lex(yesterday, (np(nom)\s)\(np(nom)\s), yesterday, lambda(X,lambda(Y,appl(yesterday,appl(X,Y))))). 126 | lex(fish, n, fish, fish). 127 | lex(dog, n, dog, dog). 128 | lex(cat, n, cat, cat). 129 | lex(cd, n, cd, cd). 130 | lex(book, n, book, book). 131 | lex(donuts, n, donuts, donuts). 132 | lex(bagels, n, bagels, bagels). 133 | lex(solution, n, solution, solution). 134 | lex(steak, np(_), steak, steak). 135 | lex(pizza, np(_), pizza, pizza). 136 | lex(whiskas, np(_), whiskas, whiskas). 137 | lex(alpo, np(_), alpo, alpo). 138 | lex(whiskas2, n, whiskas2, whiskas). 139 | lex(alpo2, n, alpo2, alpo). 140 | lex(to, pp/np(acc), to, lambda(X,X)). 141 | % = uses s1 as final category to avoid quantifier scope outside of the individual conjuncts 142 | lex(and1, (((s1|tv_c)|(s|tv_c))|(s|tv_c)), lambda(STV2,lambda(STV1,lambda(TV,lambda(V,appl(appl(STV1,TV),appl(and1,appl(appl(STV2,lambda(W,W)),V))))))), lambda(S2,lambda(S1,lambda(T,bool(appl(S1,T),&,appl(S2,T)))))). 143 | lex(and, (((s|tv_c)|(s|tv_c))|(s|tv_c)), lambda(STV2,lambda(STV1,lambda(TV,lambda(V,appl(appl(STV1,TV),appl(and,appl(appl(STV2,lambda(W,W)),V))))))), lambda(S2,lambda(S1,lambda(T,bool(appl(S1,T),&,appl(S2,T)))))). 144 | lex(must, (s|(s|(vp_c/vp_c))), lambda(SVP,lambda(Z,appl(appl(SVP,must),Z))), lambda(F,necessary(appl(F,lambda(Y,Y))))). 145 | lex(cant, (s|(s|(vp_c/vp_c))), lambda(SVP,lambda(Z,appl(appl(SVP,cant),Z))), lambda(F,neg(possible(appl(F,lambda(Y,Y)))))). 146 | lex(no, (s|(s|h_det_c)), lambda(Rho,lambda(Z,appl(appl(Rho,lambda(Phi,lambda(Sigma,lambda(V,appl(appl(Sigma,lambda(W,appl(no,appl(Phi,W)))),V))))),Z))), lambda(P,neg(appl(P,lambda(Q,lambda(R,quant(exists,X,bool(appl(Q,X),&,appl(R,X))))))))). 147 | lex(than, than, than, lambda(X,X)). 148 | lex(more, (((s|(s|h_det_c))|(s|h_det_c))|than), lambda(Than,lambda(Rho1,lambda(Rho2,lambda(Z,appl(appl(Rho2,lambda(Phi,lambda(Sigma,appl(Sigma,lambda(V,appl(more,appl(Phi,V))))))),appl(Than,appl(appl(Rho1,lambda(Phi2,lambda(Sigma2,lambda(W,appl(appl(Sigma2,Phi2),W))))),Z))))))), lambda(_,lambda(F,lambda(G,bool(number_of(appl(G,lambda(P,lambda(Q,lambda(X,bool(appl(P,X),&,appl(Q,X))))))),gneq,number_of(appl(F,lambda(P2,lambda(Q2,lambda(Y,bool(appl(P2,Y),&,appl(Q2,Y)))))))))))). 149 | lex(or, ((((s|h_det_c)|tv_c)|((s|h_det_c)|tv_c))|((s|h_det_c)|tv_c)), lambda(Rho2,lambda(Rho1,lambda(Phi,lambda(Tau,lambda(Z,appl(appl(appl(Rho1,Phi),Tau),appl(or,appl(appl(appl(Rho2,lambda(V,V)),lambda(Phi2,lambda(Sigma2,lambda(W,appl(appl(Sigma2,Phi2),W))))),Z)))))))), lambda(SDTV2,lambda(SDTV1,lambda(TV,lambda(Det,bool(appl(appl(SDTV1,TV),Det),\/,appl(appl(SDTV2,TV),Det))))))). 150 | %lex(more_d, (s/,appl(Y,Z)))))). 119 | lex(someone, (s|(s|np)), lambda(Pr,lambda(Z,appl(appl(Pr,someone),Z))), lambda(P,quant(exists,X,bool(appl(person,X),&,appl(P,X))))). 120 | lex(everyone, (s|(s|np)), lambda(Pr,lambda(Z,appl(appl(Pr,everyone),Z))), lambda(P,quant(forall,X,bool(appl(person,X),->,appl(P,X))))). 121 | lex(yesterday, (np\s)\(np\s), yesterday, X^Y^(yesterday@(X@Y))). 122 | lex(fish, n, fish, fish). 123 | lex(dog, n, dog, dog). 124 | lex(cat, n, cat, cat). 125 | lex(cd, n, cd, cd). 126 | lex(book, n, book, book). 127 | lex(donuts, n, donuts, donuts). 128 | lex(bagels, n, bagels, bagels). 129 | lex(solution, n, solution, solution). 130 | lex(steak, np, steak, steak). 131 | lex(pizza, np, pizza, pizza). 132 | lex(whiskas, np, whiskas, whiskas). 133 | lex(alpo, np, alpo, alpo). 134 | lex(whiskas2, n, whiskas2, whiskas). 135 | lex(alpo2, n, alpo2, alpo). 136 | lex(to, pp/np, to, lambda(X,X)). 137 | lex(that, (n|n)|(s|np), lambda(SNP,lambda(N,N+that+appl(SNP,epsilon))), lambda(P,lambda(Q,lambda(X,bool(appl(Q,X),&,appl(P,X)))))). 138 | % = uses s1 as final category to avoid quantifier scope outside of the individual conjuncts 139 | lex(and1, (((s1|tv)|(s|tv))|(s|tv)), lambda(STV2,lambda(STV1,lambda(TV,lambda(V,appl(appl(STV1,TV),appl(and1,appl(appl(STV2,lambda(W,W)),V))))))), lambda(S2,lambda(S1,lambda(T,bool(appl(S1,T),&,appl(S2,T)))))). 140 | lex(and, (((s|tv)|(s|tv))|(s|tv)), lambda(STV2,lambda(STV1,lambda(TV,lambda(V,appl(appl(STV1,TV),appl(and,appl(appl(STV2,lambda(W,W)),V))))))), lambda(S2,lambda(S1,lambda(T,bool(appl(S1,T),&,appl(S2,T)))))). 141 | lex(and_np, dr(dl(np,np),np), and_np, lambda(NP2,lambda(NP1,bool(NP1,&,NP2)))). 142 | lex(and_q, (((s|s|np)|(s|s|np))|(s|s|np)), lambda(SP2,lambda(SP1,lambda(P,appl(P,appl(SP1,lambda(V,V))+and_q+appl(SP2,lambda(W,W)))))), lambda(SQ2,lambda(SQ1,lambda(SNP,bool(appl(SQ1,SNP),&,appl(SQ2,SNP)))))). 143 | lex(must, (s|(s|(vp/vp))), lambda(SVP,lambda(Z,appl(appl(SVP,must),Z))), lambda(F,necessary(appl(F,lambda(Y,Y))))). 144 | lex(cant, (s|(s|(vp/vp))), lambda(SVP,lambda(Z,appl(appl(SVP,cant),Z))), lambda(F,neg(possible(appl(F,lambda(Y,Y)))))). 145 | lex(no, (s|(s|h_det)), lambda(Rho,lambda(Z,appl(appl(Rho,lambda(Phi,lambda(Sigma,lambda(V,appl(appl(Sigma,lambda(W,appl(no,appl(Phi,W)))),V))))),Z))), lambda(P,neg(appl(P,lambda(Q,lambda(R,quant(exists,X,bool(appl(Q,X),&,appl(R,X))))))))). 146 | lex(than, than, than, lambda(X,X)). 147 | lex(more, (((s|(s|h_det))|(s|h_det))|than), lambda(Than,lambda(Rho1,lambda(Rho2,lambda(Z,appl(appl(Rho2,lambda(Phi,lambda(Sigma,appl(Sigma,lambda(V,appl(more,appl(Phi,V))))))),appl(Than,appl(appl(Rho1,lambda(Phi2,lambda(Sigma2,lambda(W,appl(appl(Sigma2,Phi2),W))))),Z))))))), lambda(_,lambda(F,lambda(G,bool(number_of(appl(G,lambda(P,lambda(Q,lambda(X,bool(appl(P,X),&,appl(Q,X))))))),gneq,number_of(appl(F,lambda(P2,lambda(Q2,lambda(Y,bool(appl(P2,Y),&,appl(Q2,Y)))))))))))). 148 | lex(or, ((((s|h_det)|tv)|((s|h_det)|tv))|((s|h_det)|tv)), lambda(Rho2,lambda(Rho1,lambda(Phi,lambda(Tau,lambda(Z,appl(appl(appl(Rho1,Phi),Tau),appl(or,appl(appl(appl(Rho2,lambda(V,V)),lambda(Phi2,lambda(Sigma2,lambda(W,appl(appl(Sigma2,Phi2),W))))),Z)))))))), lambda(SDTV2,lambda(SDTV1,lambda(TV,lambda(Det,bool(appl(appl(SDTV1,TV),Det),\/,appl(appl(SDTV2,TV),Det))))))). 149 | %lex(more_d, (s/,appl(Q,X)))))). 19 | lex(some, ((s/np)\s)/n, lambda(P,lambda(Q,quant(exists,X,bool(appl(P,X),&,appl(Q,X)))))). 20 | lex(a, ((s/np)\s)/n, lambda(P,lambda(Q,quant(exists,X,bool(appl(P,X),&,appl(Q,X)))))). 21 | lex(student, n, student). 22 | lex(exam, n, exam). 23 | lex(donkey, n, donkey). 24 | lex(aced, (np\s)/np, ace). 25 | lex(own, (np\s)/np, own). 26 | lex(slept, np\s, sleep). 27 | lex(john, np, john). 28 | lex(mary, np, mary). 29 | lex(during, ((np\s)\(np\s))/np, lambda(X,lambda(P,lambda(Y,appl(appl(during,X),appl(P,Y)))))). 30 | lex(the, np/n, iota). 31 | lex(who, (n\n)/(np\s), lambda(P,lambda(Q,lambda(X,bool(appl(Q,X),&,appl(P,X)))))). 32 | lex(loves, (np\s)/np, love). 33 | lex(alyssa, np, alyssa). 34 | lex(and, ((s/(np\s))\(s/(np\s)))/(s/(np\s)), lambda(Q2,lambda(Q1,lambda(P,bool(appl(Q1,P),&,appl(Q2,P)))))). 35 | 36 | 37 | test(1) :- 38 | parse([every,student,aced,some,exam], s). 39 | 40 | test(2) :- 41 | parse([the,student,who,slept,during,the,exam,loves,alyssa], s). 42 | test(3) :- 43 | parse([john,and,mary,own,a,donkey], s). 44 | -------------------------------------------------------------------------------- /latex.pl: -------------------------------------------------------------------------------- 1 | :- module(latex, [latex_proof/1,latex_nd/1,latex_hybrid/1,latex_displacement/1,proof_header/0,proof_footer/0,latex_semantics/1,latex_lexicon/1,latex_lexicon1/0,latex_it_atom/1,latex_arguments/1,latex_rm_atom/1,latex_it_atom/1]). 2 | 3 | :- use_module(proof_generation, [eta_reduce/2]). 4 | :- use_module(translations, [compute_pros_term/3,translate/3,translate_hybrid/6]). 5 | :- use_module(lexicon, [macro_expand/2,canonical_semantic_term/2]). 6 | :- use_module(options, [term_application/1, 7 | lexicon_separator/1, 8 | hybrid_connective/4, 9 | hybrid_epsilon/1, 10 | hybrid_concat/1, 11 | hybrid_item_start/1, 12 | hybrid_item_mid/1, 13 | hybrid_item_end/1, 14 | d_separator/1, 15 | d_concat/1, 16 | d_epsilon/1, 17 | output_indices/1, 18 | geometry/1, 19 | eta_short/1]). 20 | 21 | proof_header :- 22 | ( exists_file('latex_proofs.tex') -> delete_file('latex_proofs.tex') ; true), 23 | open('latex_proofs.tex', write, _Stream, [alias(latex)]), 24 | format(latex, '\\documentclass[leqno,fleqn]{article}~2n', []), 25 | geometry(Geometry), 26 | format(latex, '\\usepackage[~p]{geometry}~n', [Geometry]), 27 | format(latex, '\\usepackage{proof}~n', []), 28 | format(latex, '\\usepackage{amsmath}~n', []), 29 | format(latex, '\\usepackage{amssymb}~2n', []), 30 | format(latex, '\\begin{document}~2n', []). 31 | 32 | proof_footer :- 33 | format(latex, '~n\\end{document}~n', []), 34 | close(latex), 35 | ( 36 | access_file('latex_proofs.tex', read) 37 | -> 38 | /* find pdflatex in the user's $PATH */ 39 | absolute_file_name(path(pdflatex), PdfLaTeX, [access(execute)]), 40 | process_create(PdfLaTeX, ['latex_proofs.tex'], [stdout(null)]), 41 | format('LaTeX proofs ready~n', []) 42 | ; 43 | format('LaTeX proof output failed~n', []) 44 | ). 45 | 46 | % = 47 | 48 | lexicon_header :- 49 | ( stream_property(Stream, alias(latex)) -> close(Stream) ; true), 50 | ( exists_file('lexicon.tex') -> delete_file('lexicon.tex') ; true), 51 | open('lexicon.tex', write, _Stream, [alias(latex)]), 52 | format(latex, '\\documentclass[leqno,fleqn]{article}~2n', []), 53 | geometry(Geometry), 54 | format(latex, '\\usepackage[~p]{geometry}~n', [Geometry]), 55 | format(latex, '\\usepackage{proof}~n', []), 56 | format(latex, '\\usepackage{amsmath}~n', []), 57 | format(latex, '\\usepackage{amssymb}~2n', []), 58 | format(latex, '\\begin{document}~2n', []), 59 | format(latex, '\\begin{align*}~n', []). 60 | 61 | lexicon_footer :- 62 | format(latex, '\\end{align*}~2n', []), 63 | format(latex, '~n\\end{document}~n', []), 64 | close(latex), 65 | ( 66 | access_file('lexicon.tex', read) 67 | -> 68 | /* find pdflatex in the user's $PATH */ 69 | absolute_file_name(path(pdflatex), PdfLaTeX, [access(execute)]), 70 | process_create(PdfLaTeX, ['lexicon.tex'], [stdout(null)]), 71 | format('LaTeX lexicon ready~n', []) 72 | ; 73 | format('LaTeX lexicon output failed~n', []) 74 | ). 75 | 76 | % = latex_lexicon1 77 | % 78 | % abbreviates latex_lexicon(mill1); outputs the current lexicon as first-order linear logic formulas, translating 79 | % displacement calculus, hybrid type-logical grammar and Lambek calculus entries when required. 80 | 81 | latex_lexicon1 :- 82 | latex_lexicon(mill1). 83 | 84 | % = latex_lexicon(+GrammarType) 85 | % 86 | % Grammar type must be one of d, displacement, mill1, hybrid 87 | % outputs the grammar in the format indicated by the grammar type. 88 | 89 | % displacement calculus 90 | 91 | latex_lexicon(displacement) :- 92 | latex_lexicon(d). 93 | 94 | latex_lexicon(d) :- 95 | lexicon_header, 96 | ( 97 | current_predicate(lex/3) 98 | -> 99 | findall(d_lex(X,Y,Z), lex(X,Y,Z), List) 100 | ; 101 | List = [] 102 | ), 103 | latex_lexicon_d(List), 104 | lexicon_footer. 105 | 106 | % first-order linear logic 107 | 108 | latex_lexicon(mill1) :- 109 | lexicon_header, 110 | ( 111 | current_predicate(lex/3) 112 | -> 113 | findall(mill1_lex(X,Y,Z), lex(X,Y,Z), List1) 114 | ; 115 | List1 = [] 116 | ), 117 | ( 118 | current_predicate(lex/4) 119 | -> 120 | findall(hybrid_lex(X,Y,Z,V), lex(X,Y,Z,V), List2) 121 | ; 122 | List2 = [] 123 | ), 124 | ( 125 | current_predicate(lex/5) 126 | -> 127 | findall(ll1_lex(X,Y,Z), lex(X,Y,l,r,Z), List3) 128 | ; 129 | List3 = [] 130 | ), 131 | append(List1, List2, List12), 132 | append(List12, List3, List), 133 | latex_lexicon_list(List), 134 | lexicon_footer. 135 | 136 | % hybrid type-logical grammars 137 | % 138 | % treat "acg" and "lambda" as "hybrid". 139 | 140 | latex_lexicon(acg) :- 141 | latex_lexicon(hybrid). 142 | latex_lexicon(lambda) :- 143 | latex_lexicon(hybrid). 144 | 145 | latex_lexicon(hybrid) :- 146 | lexicon_header, 147 | ( 148 | current_predicate(lex/4) 149 | -> 150 | findall(hybrid_lex(X,Y,Z,V), lex(X,Y,Z,V), List) 151 | ; 152 | List = [] 153 | ), 154 | latex_lexicon_hybrid(List), 155 | lexicon_footer. 156 | 157 | % = latex_lexicon_d(+ListOfEntries) 158 | % 159 | % output ListOfEntries as Displacement calculus lexical entries 160 | 161 | latex_lexicon_d([]). 162 | latex_lexicon_d([d_lex(A,B,C)|As]) :- 163 | latex_d_item(A,B,C), 164 | latex_lexicon_d(As). 165 | 166 | latex_d_item(Word, Formula0, Semantics0) :- 167 | macro_expand(Formula0, Formula), 168 | lexicon_separator(Sep), 169 | canonical_semantic_term(Semantics0, Semantics), 170 | numbervars(Semantics, 0, _), 171 | !, 172 | format(latex, '~@ &~w ~@ ~w ~@\\\\~n', [latex_rm_atom(Word), Sep, latex_d_formula(Formula), Sep, latex_semantics(Semantics,0)]). 173 | 174 | % = latex_lexicon_list(+ListOfEntries) 175 | % 176 | % output ListOfEntries as first-order linear logic lexical entries 177 | 178 | latex_lexicon_list([]). 179 | latex_lexicon_list([A|As]) :- 180 | latex_mill1_item(A), 181 | latex_lexicon_list(As). 182 | 183 | latex_mill1_item(hybrid_lex(Word,Formula0,ProsTerm,Semantics0)) :- 184 | macro_expand(Formula0, Formula1), 185 | translate_hybrid(Formula1, ProsTerm, Word, l, r, Formula), 186 | canonical_semantic_term(Semantics0, Semantics), 187 | numbervars(Formula, 0, _), 188 | numbervars(Semantics, 0, _), 189 | lexicon_separator(Sep), 190 | !, 191 | format(latex, '~@ &~w ~@ ~w ~@\\\\~n', [latex_rm_atom(Word), Sep, latex_formula(Formula), Sep, latex_semantics(Semantics,0)]). 192 | latex_mill1_item(mill1_lex(Word,Formula0,Semantics0)) :- 193 | macro_expand(Formula0, Formula1), 194 | try_translate(Formula1, Formula), 195 | canonical_semantic_term(Semantics0, Semantics), 196 | numbervars(Formula, 0, _), 197 | numbervars(Semantics, 0, _), 198 | lexicon_separator(Sep), 199 | !, 200 | format(latex, '~@ &~w ~@ ~w ~@\\\\~n', [latex_rm_atom(Word), Sep, latex_formula(Formula), Sep, latex_semantics(Semantics,0)]). 201 | latex_mill1_item(ll1_lex(Word,Formula0,Semantics0)) :- 202 | macro_expand(Formula0, Formula), 203 | canonical_semantic_term(Semantics0, Semantics), 204 | numbervars(Formula, 0, _), 205 | numbervars(Semantics, 0, _), 206 | lexicon_separator(Sep), 207 | !, 208 | format(latex, '~@ &~w ~@ ~w ~@\\\\~n', [latex_rm_atom(Word), Sep, latex_formula(Formula), Sep, latex_semantics(Semantics,0)]). 209 | 210 | % = latex_lexicon_hybrid(+ListOfEntries) 211 | % 212 | % output ListOfEntries as hybrid type-logical grammars lexical entries 213 | 214 | latex_lexicon_hybrid([]). 215 | latex_lexicon_hybrid([hybrid_lex(A,B,C,D)|As]) :- 216 | latex_lexical_entry(A, B, C, D), 217 | latex_lexicon_hybrid(As). 218 | 219 | latex_lexical_entry(mill1_lex(Word,Formula0,Semantics0)) :- 220 | macro_expand(Formula0, Formula1), 221 | try_translate(Formula1, Formula), 222 | canonical_semantic_term(Semantics0, Semantics), 223 | numbervars(Semantics, 0, _), 224 | lexicon_separator(Sep), 225 | !, 226 | format(latex, '~@ &~w ~@ ~w ~@\\\\~n', [latex_rm_atom(Word), Sep, latex_formula(Formula), Sep, latex_semantics(Semantics,0)]). 227 | latex_lexical_entry(Word, Formula0, ProsTerm0, SemTerm0) :- 228 | macro_expand(Formula0, Formula), 229 | /* prevent strange behavior when a variable is shared between the prosodic term */ 230 | /* and the semantic term (otherwise, the behavior is correct under the Prolog */ 231 | /* meaning of bound variables, but very unlikely what the grammar writer intended) */ 232 | /* NOTE: best practice is still to use a different set of variables for the prosodic */ 233 | /* term and the semantic term */ 234 | canonical_semantic_term(SemTerm0, SemTerm), 235 | numbervars(SemTerm, 0, _), 236 | compute_pros_term(ProsTerm0, Formula, ProsTerm), 237 | lexicon_separator(Sep), 238 | !, 239 | format(latex, '~@ &~w ~@ ~w ~@ ~w ~@\\\\~n', [latex_rm_atom(Word),Sep,latex_hybrid_formula(Formula),Sep,latex_pros_term(ProsTerm),Sep,latex_semantics(SemTerm,0)]). 240 | 241 | 242 | try_translate(Formula0, Formula) :- 243 | translate(Formula0, [l,r], Formula), 244 | !. 245 | try_translate(Formula, Formula). 246 | 247 | % = latex_proof(+Proof) 248 | % 249 | % produces LaTeX output of Proof to the stream "latex". 250 | 251 | latex_proof(Proof0) :- 252 | copy_term(Proof0, Proof), 253 | numbervars(Proof, 0, _), 254 | format(latex, '\\[~n', []), 255 | latex_proof(Proof, 0), 256 | format(latex, '\\]~n\\bigskip~n', []). 257 | 258 | latex_proof(_-Proof, Tab) :- 259 | latex_proof(Proof, Tab). 260 | latex_proof(rule(Name, Ant, Suc, SubProofs), Tab0) :- 261 | format(latex, '\\infer[~@]{~@}{', [latex_rule_name(Name),latex_sequent(Ant,Suc)]), 262 | Tab is Tab0 + 6, 263 | latex_proofs(SubProofs, Tab), 264 | (SubProofs = [] -> true ; tab(latex,Tab0)), 265 | format(latex, '}~n', []). 266 | 267 | 268 | latex_proofs([], _Tab). 269 | latex_proofs([P|Ps], Tab) :- 270 | /* newline and tab only when there is at least one premiss */ 271 | nl(latex), 272 | tab(latex, Tab), 273 | latex_proofs1(Ps, P, Tab). 274 | 275 | latex_proofs1([], P, Tab) :- 276 | latex_proof(P, Tab). 277 | latex_proofs1([P|Ps], Q, Tab) :- 278 | latex_proof(Q, Tab), 279 | tab(latex, Tab), 280 | format(latex, '&~n', []), 281 | tab(latex, Tab), 282 | latex_proofs1(Ps, P, Tab). 283 | 284 | % = latex_rule_name(+RuleName) 285 | % 286 | % output RuleName to LaTeX stream "latex" 287 | 288 | %latex_rule_name(ax) :- 289 | % write('Axiom'). 290 | % don't print "Axiom" to save space (replace by the code commented out above if you want the axioms to be explicitly named) 291 | latex_rule_name(ax). 292 | latex_rule_name(hyp(_)). 293 | latex_rule_name(cut) :- 294 | write(latex, 'Cut'). 295 | latex_rule_name(fl) :- 296 | write(latex, 'L\\forall'). 297 | latex_rule_name(fr) :- 298 | write(latex, 'R\\forall'). 299 | latex_rule_name(el) :- 300 | write(latex, 'L\\exists'). 301 | latex_rule_name(er) :- 302 | write(latex, 'R\\exists'). 303 | latex_rule_name(il) :- 304 | write(latex, 'L\\multimap'). 305 | latex_rule_name(ir) :- 306 | write(latex, 'R\\multimap'). 307 | latex_rule_name(pl) :- 308 | write(latex, 'L\\otimes'). 309 | latex_rule_name(pr) :- 310 | write(latex, 'R\\otimes'). 311 | latex_rule_name(fi) :- 312 | write(latex, '\\forall I'). 313 | latex_rule_name(fe) :- 314 | write(latex, '\\forall E'). 315 | latex_rule_name(ei) :- 316 | write(latex, '\\exists I'). 317 | latex_rule_name(ee(_)) :- 318 | write(latex, '\\exists E'). 319 | latex_rule_name(ee) :- 320 | write(latex, '\\exists E'). 321 | latex_rule_name(ii) :- 322 | write(latex, '\\multimap I'). 323 | latex_rule_name(ii(_)) :- 324 | write(latex, '\\multimap I'). 325 | latex_rule_name(dre) :- 326 | write(latex, '/ E'). 327 | latex_rule_name(dle) :- 328 | write(latex, '\\backslash E'). 329 | latex_rule_name(dre(W)) :- 330 | format(latex, '\\uparrow_{~w} E', [W]). 331 | latex_rule_name(dle(W)) :- 332 | format(latex, '\\downarrow_{~w} E', [W]). 333 | latex_rule_name(he) :- 334 | hybrid_connective(_, _, C, _), 335 | format(latex, '~w E', [C]). 336 | latex_rule_name(hi) :- 337 | hybrid_connective(_, _, C, _), 338 | format(latex, '~w I', [C]). 339 | latex_rule_name(hi(_)) :- 340 | hybrid_connective(_, _, C, _), 341 | format(latex, '~w I', [C]). 342 | latex_rule_name(ie) :- 343 | write(latex, '\\multimap E'). 344 | latex_rule_name(pi) :- 345 | write(latex, '\\otimes I'). 346 | latex_rule_name(pe) :- 347 | write(latex, '\\otimes E'). 348 | latex_rule_name(pe(_)) :- 349 | write(latex, '\\otimes E'). 350 | latex_rule_name(dri(_)) :- 351 | format(latex, '/ I', []), 352 | !. 353 | latex_rule_name(dli(_)) :- 354 | format(latex, '\\backslash I', []), 355 | !. 356 | latex_rule_name(dri) :- 357 | format(latex, '/ I', []), 358 | !. 359 | latex_rule_name(dli) :- 360 | format(latex, '\\backslash I', []), 361 | !. 362 | latex_rule_name(bridge_i) :- 363 | format(latex, '\\,\\hat{\\,} I', []). 364 | latex_rule_name(rproj_e) :- 365 | format(latex, '\\triangleright^{-1} E', []). 366 | latex_rule_name(lproj_e) :- 367 | format(latex, '\\triangleleft^{-1} E', []). 368 | 369 | latex_rule_name_i(ii(I)) :- 370 | format(latex, '\\multimap I_{~w}', [I]), 371 | !. 372 | latex_rule_name_i(dri(I)) :- 373 | format(latex, '/ I_{~w}', [I]), 374 | !. 375 | latex_rule_name_i(dli(I)) :- 376 | format(latex, '\\backslash I_{~w}', [I]), 377 | !. 378 | latex_rule_name_i(dri(D,I)) :- 379 | format(latex, '\\uparrow_{~w} I_{~w}', [D,I]), 380 | !. 381 | latex_rule_name_i(dli(D,I)) :- 382 | format(latex, '\\downarrow_{~w} I_{~w}', [D,I]), 383 | !. 384 | latex_rule_name_i(hi(I)) :- 385 | hybrid_connective(_, _, C, _), 386 | format(latex, '~w I_{~w}', [C,I]), 387 | !. 388 | latex_rule_name_i(pe(I)) :- 389 | format(latex, '\\otimes E_{~w}', [I]), 390 | !. 391 | latex_rule_name_i(ee(I)) :- 392 | format(latex, '\\exists E_{~w}', [I]), 393 | !. 394 | latex_rule_name_i(Name) :- 395 | latex_rule_name(Name). 396 | 397 | latex_sequent(Ant, Suc) :- 398 | format(latex, '~@ \\vdash ~@', [latex_antecedent(Ant),latex_formula(Suc)]). 399 | 400 | latex_antecedent([]). 401 | latex_antecedent([A|As]) :- 402 | latex_antecedent(As, A). 403 | 404 | latex_antecedent([], A) :- 405 | latex_formula(A). 406 | latex_antecedent([A|As], B) :- 407 | latex_formula(B), 408 | write(latex, ','), 409 | latex_antecedent(As, A). 410 | 411 | 412 | % = latex_nd(+Proof) 413 | % 414 | % this version of latex_proof output natural deduction proofs with implicit antecedents (and coindexing between rules and withdrawn hypotheses) 415 | 416 | latex_nd(Proof0) :- 417 | copy_term(Proof0, Proof1), 418 | numbervars(Proof1, 0, _), 419 | eta_reduce(Proof1, Proof), 420 | format(latex, '\\[~n', []), 421 | latex_nd(Proof, 0), 422 | format(latex, '\\]~n\\bigskip~n', []). 423 | 424 | latex_nd(_-Proof, Tab) :- 425 | latex_nd(Proof, Tab). 426 | latex_nd(rule(Name, _, Formula, SubProofs), Tab) :- 427 | latex_nd(SubProofs, Name, Formula, Tab). 428 | 429 | latex_nd([], Name, Formula, _Tab) :- 430 | ( Name = hyp(I) -> format(latex, '[~@]^{~w} ', [latex_formula(Formula),I]) ; format(latex, '~@ ', [latex_formula(Formula)])). 431 | latex_nd([S|Ss], Name, Formula, Tab0) :- 432 | format(latex, '\\infer[~@]{~@}{', [latex_rule_name_i(Name),latex_formula(Formula)]), 433 | Tab is Tab0 + 6, 434 | nl(latex), 435 | tab(latex, Tab), 436 | latex_nds(Ss, S, Tab), 437 | tab(latex,Tab0), 438 | format(latex, '}~n', []). 439 | 440 | latex_nds([], P, Tab) :- 441 | latex_nd(P, Tab). 442 | latex_nds([P|Ps], Q, Tab) :- 443 | latex_nd(Q, Tab), 444 | tab(latex, Tab), 445 | format(latex, '&~n', []), 446 | tab(latex, Tab), 447 | latex_nds(Ps, P, Tab). 448 | 449 | 450 | % = latex_hybrid(+Proof) 451 | % 452 | % this version of latex_proof outputs hybrid type-logical grammar natural deduction proofs (with implicit antecedents and coindexing between rules and withdrawn hypotheses) 453 | 454 | latex_hybrid(Proof0) :- 455 | eta_reduce(Proof0, Proof), 456 | format(latex, '\\[~n', []), 457 | latex_hybrid(Proof, 0), 458 | format(latex, '\\]~n\\bigskip~n', []). 459 | 460 | latex_hybrid(_-Proof, Tab) :- 461 | latex_hybrid(Proof, Tab). 462 | latex_hybrid(rule(Name, Term, Formula, SubProofs), Tab) :- 463 | latex_hybrid(SubProofs, Name, Term, Formula, Tab). 464 | 465 | latex_hybrid([], Name, Term, Formula, _Tab) :- 466 | ( Name = hyp(I) -> format(latex, '\\left [ ~@\\right ]^{~w} ', [latex_hybrid_item(Term,Formula),I]) ; format(latex, '~@ ', [latex_hybrid_item(Term,Formula)])). 467 | latex_hybrid([S|Ss], Name, Term, Formula, Tab0) :- 468 | format(latex, '\\infer[~@]{~@}{', [latex_rule_name_i(Name),latex_hybrid_item(Term,Formula)]), 469 | Tab is Tab0 + 6, 470 | nl(latex), 471 | tab(latex, Tab), 472 | latex_hybrids(Ss, S, Tab), 473 | tab(latex,Tab0), 474 | format(latex, '}~n', []). 475 | 476 | latex_hybrids([], P, Tab) :- 477 | latex_hybrid(P, Tab). 478 | latex_hybrids([P|Ps], Q, Tab) :- 479 | latex_hybrid(Q, Tab), 480 | tab(latex, Tab), 481 | format(latex, '&~n', []), 482 | tab(latex, Tab), 483 | latex_hybrids(Ps, P, Tab). 484 | 485 | % = latex_hybrid_item 486 | 487 | latex_hybrid_item(Pros, Formula) :- 488 | hybrid_item_start(HS), 489 | hybrid_item_mid(HM), 490 | hybrid_item_end(HE), 491 | format(latex, '~w~@~w~@~w ', [HS,latex_pros_term(Pros),HM,latex_hybrid_formula(Formula),HE]). 492 | 493 | % = latex_pros_term(+Prosodics) 494 | % 495 | % output a prosodic term, as used in lambda grammars/ACGs and hybrid type-logical grammars to LaTeX 496 | 497 | latex_pros_term(epsilon) :- 498 | !, 499 | hybrid_epsilon(Epsilon), 500 | format(latex, '~w ', [Epsilon]). 501 | latex_pros_term(A+B) :- 502 | !, 503 | hybrid_concat(Conc), 504 | format(latex, '~@ ~w ~@ ', [latex_pros_term(A),Conc,latex_pros_term(B)]). 505 | latex_pros_term('$VAR'(N)) :- 506 | !, 507 | pros_variable_atom(N, At), 508 | write(latex, At). 509 | latex_pros_term(Atom) :- 510 | atomic(Atom), 511 | !, 512 | latex_pros_atom(Atom). 513 | latex_pros_term(lambda(X,Y)) :- 514 | !, 515 | format(latex, '\\lambda ~@ . ~@ ', [latex_pros_term(X),latex_pros_term(Y)]). 516 | latex_pros_term(appl(X,Y)) :- 517 | !, 518 | format(latex, '(~@\\,~@)', [latex_pros_term(X),latex_pros_term(Y)]). 519 | 520 | % = pros_variable_atom(+Number, -LaTeXAtom) 521 | % 522 | % translates a Number into a Prolog atom printed as a LaTeX variable with a subscript 523 | 524 | pros_variable_atom(N, At) :- 525 | VI is N mod 5, 526 | VN is N//5, 527 | print_pros_var1(VI, V), 528 | atomic_list_concat([V, '_{', VN, '}'], At). 529 | 530 | print_pros_var1(0, p). 531 | print_pros_var1(1, q). 532 | print_pros_var1(2, r). 533 | print_pros_var1(3, s). 534 | print_pros_var1(4, t). 535 | 536 | latex_pros_atom(A0) :- 537 | /* take care of Prolog atoms containing '_' */ 538 | atomic_list_concat(List, '_', A0), 539 | atomic_list_concat(List, '\\_', A), 540 | format(latex, '\\textrm{~w}', [A]). 541 | 542 | % = latex_hybrid_formula(+Formula) 543 | % 544 | % outputs a formula of hybrid type-logical grammars to LaTeX 545 | 546 | latex_hybrid_formula(F) :- 547 | latex_hybrid_formula(F, 0). 548 | latex_hybrid_formula(at(A), _) :- 549 | latex_atom(A). 550 | latex_hybrid_formula(at(F, Vs), _) :- 551 | format(latex, '~@~@', [latex_atom(F),latex_arguments(Vs)]). 552 | latex_hybrid_formula(h(A,B), N) :- 553 | hybrid_connective(h(A,B), L, C, R), 554 | ( 555 | N = 0 556 | -> 557 | format(latex, '~@~w~@ ', [latex_hybrid_formula(L,1),C,latex_hybrid_formula(R,1)]) 558 | ; 559 | format(latex, '(~@~w~@)', [latex_hybrid_formula(L,1),C,latex_hybrid_formula(R,1)]) 560 | ). 561 | latex_hybrid_formula(dr(A,B), N) :- 562 | ( 563 | N = 0 564 | -> 565 | format(latex, '~@/~@ ', [latex_hybrid_formula(A,1),latex_hybrid_formula(B,1)]) 566 | ; 567 | format(latex, '(~@/~@)', [latex_hybrid_formula(A,1),latex_hybrid_formula(B,1)]) 568 | ). 569 | latex_hybrid_formula(dl(A,B), N) :- 570 | ( 571 | N = 0 572 | -> 573 | format(latex, '(~@\\backslash ~@)', [latex_hybrid_formula(A,1),latex_hybrid_formula(B,1)]) 574 | ; 575 | format(latex, '(~@\\backslash ~@)', [latex_hybrid_formula(A,1),latex_hybrid_formula(B,1)]) 576 | ). 577 | 578 | % latex_displacement 579 | 580 | latex_displacement(Proof0) :- 581 | eta_reduce(Proof0, Proof), 582 | format(latex, '\\[~n', []), 583 | latex_displacement(Proof, 0), 584 | format(latex, '\\]~n\\bigskip~n', []). 585 | 586 | latex_displacement(_-Proof, Tab) :- 587 | latex_displacement(Proof, Tab). 588 | latex_displacement(rule(hyp(I), Ant, Suc, []), _Tab) :- 589 | !, 590 | format(latex, '[~@\\vdash ~@]^{~w}~n', [latex_d_label(Ant),latex_d_formula(Suc),I]). 591 | latex_displacement(rule(ax, Ant, Suc, []), _Tab) :- 592 | !, 593 | format(latex, '~@\\vdash ~@~n', [latex_d_label(Ant),latex_d_formula(Suc)]). 594 | latex_displacement(rule(Name, Ant, Suc, SubProofs), Tab0) :- 595 | format(latex, '\\infer[~@]{~@ \\vdash ~@}{', [latex_rule_name_i(Name),latex_d_label(Ant),latex_d_formula(Suc)]), 596 | Tab is Tab0 + 6, 597 | latex_d_proofs(SubProofs, Tab), 598 | (SubProofs = [] -> true ; tab(latex,Tab0)), 599 | format(latex, '}~n', []). 600 | 601 | 602 | latex_d_proofs([], _Tab). 603 | latex_d_proofs([P|Ps], Tab) :- 604 | /* newline and tab only when there is at least one premiss */ 605 | nl(latex), 606 | tab(latex, Tab), 607 | latex_d_proofs1(Ps, P, Tab). 608 | 609 | latex_d_proofs1([], P, Tab) :- 610 | latex_displacement(P, Tab). 611 | latex_d_proofs1([P|Ps], Q, Tab) :- 612 | latex_displacement(Q, Tab), 613 | tab(latex, Tab), 614 | format(latex, '&~n', []), 615 | tab(latex, Tab), 616 | latex_d_proofs1(Ps, P, Tab). 617 | 618 | 619 | % = latex_d_label 620 | 621 | latex_d_label([A|As]) :- 622 | latex_d_label1(As, A). 623 | 624 | latex_d_label1([], A) :- 625 | latex_d_label_item(A). 626 | latex_d_label1([B|Bs], A) :- 627 | latex_d_label_item(A), 628 | d_separator(Sep), 629 | write(latex, Sep), 630 | latex_d_label1(Bs, B). 631 | 632 | latex_d_label_item([]) :- 633 | d_epsilon(Epsilon), 634 | write(latex, Epsilon). 635 | latex_d_label_item([A|As]) :- 636 | latex_d_label_item1(As, A). 637 | 638 | latex_d_label_item1([], A) :- 639 | latex_d_item(A). 640 | latex_d_label_item1([B|Bs], A) :- 641 | latex_d_item(A), 642 | d_concat(Conc), 643 | write(latex, Conc), 644 | latex_d_label_item1(Bs, B). 645 | 646 | latex_d_item('$VAR'(N)) :- 647 | !, 648 | /* shared with hybrid type-logical grammars */ 649 | pros_variable_atom(N, At), 650 | write(latex, At). 651 | latex_d_item(W) :- 652 | latex_atom(W). 653 | 654 | % = latex_d_formula 655 | 656 | latex_d_formula(F) :- 657 | latex_d_formula(F, 0). 658 | 659 | latex_d_formula(at(A), _) :- 660 | latex_it_atom(A). 661 | latex_d_formula(at(F, Vs), _) :- 662 | format(latex, '~@~@', [latex_it_atom(F),latex_arguments(Vs)]). 663 | latex_d_formula(bridge(A), _) :- 664 | !, 665 | format(latex, '\\,\\hat{\\,}(~@ )', [latex_d_formula(A, 0)]). 666 | latex_d_formula(lproj(A), _) :- 667 | !, 668 | format(latex, '\\triangleleft^{-1}( ~@ )', [latex_d_formula(A, 0)]). 669 | latex_d_formula(rproj(A), _) :- 670 | !, 671 | format(latex, '\\triangleright^{-1}( ~@ )', [latex_d_formula(A, 0)]). 672 | latex_d_formula(p(A,B), NB) :- 673 | !, 674 | ( 675 | NB =:= 0 676 | -> 677 | format(latex, '~@ \\bullet ~@', [latex_d_formula(A, 1),latex_d_formula(B, 1)]) 678 | ; 679 | format(latex, '(~@ \\bullet ~@)', [latex_d_formula(A, 1),latex_d_formula(B, 1)]) 680 | ). 681 | latex_d_formula(dl(A,B), NB) :- 682 | !, 683 | ( 684 | NB =:= 0 685 | -> 686 | format(latex, '~@ \\backslash ~@', [latex_d_formula(A, 1),latex_d_formula(B, 1)]) 687 | ; 688 | format(latex, '(~@ \\backslash ~@)', [latex_d_formula(A, 1),latex_d_formula(B, 1)]) 689 | ). 690 | latex_d_formula(dr(A,B), NB) :- 691 | !, 692 | ( 693 | NB =:= 0 694 | -> 695 | format(latex, '~@ / ~@', [latex_d_formula(A, 1),latex_d_formula(B, 1)]) 696 | ; 697 | format(latex, '(~@ / ~@)', [latex_d_formula(A, 1),latex_d_formula(B, 1)]) 698 | ). 699 | latex_d_formula(p(K,A,B), NB) :- 700 | !, 701 | ( 702 | NB =:= 0 703 | -> 704 | format(latex, '~@ \\odot_{~w} ~@', [latex_d_formula(A, 1),K,latex_d_formula(B, 1)]) 705 | ; 706 | format(latex, '(~@ \\odot_{~w} ~@)', [latex_d_formula(A, 1),K,latex_d_formula(B, 1)]) 707 | ). 708 | latex_d_formula(dl(K,A,B), NB) :- 709 | !, 710 | ( 711 | NB =:= 0 712 | -> 713 | format(latex, '~@ \\downarrow_{~w} ~@', [latex_d_formula(A, 1),K,latex_d_formula(B, 1)]) 714 | ; 715 | format(latex, '(~@ \\downarrow_{~w} ~@)', [latex_d_formula(A, 1),K,latex_d_formula(B, 1)]) 716 | ). 717 | latex_d_formula(dr(K,A,B), NB) :- 718 | !, 719 | ( 720 | NB =:= 0 721 | -> 722 | format(latex, '~@ \\uparrow_{~w} ~@', [latex_d_formula(A, 1),K,latex_d_formula(B, 0)]) 723 | ; 724 | format(latex, '(~@ \\uparrow_{~w} ~@)', [latex_d_formula(A, 1),K,latex_d_formula(B, 1)]) 725 | ). 726 | 727 | 728 | % = latex_formula(+Formula) 729 | % 730 | % 731 | 732 | latex_formula(F) :- 733 | latex_formula(F, 0). 734 | 735 | latex_formula(_-F, N) :- 736 | latex_formula(F, N). 737 | latex_formula(at(F,Vs), _) :- 738 | % update_vars(Vs0, Vs), 739 | format(latex, '~@~@', [latex_atom(F),latex_arguments(Vs)]). 740 | latex_formula(at(F,N,E,Vs), _) :- 741 | ( 742 | output_indices(yes) 743 | -> 744 | format(latex, '~@^{~p,~p}~@', [latex_atom(F),N,E,latex_arguments(Vs)]) 745 | ; 746 | format(latex, '~@~@', [latex_atom(F),latex_arguments(Vs)]) 747 | ). 748 | latex_formula(forall(X,F), _) :- 749 | !, 750 | ( 751 | is_quantified(F) 752 | -> 753 | format(latex, '\\forall ~@. ~@', [latex_var(X),latex_formula(F, 1)]) 754 | ; 755 | format(latex, '\\forall ~@. [~@]', [latex_var(X),latex_formula(F, 0)]) 756 | ). 757 | latex_formula(exists(X,F), _) :- 758 | !, 759 | ( 760 | is_quantified(F) 761 | -> 762 | format(latex, '\\exists ~@. ~@', [latex_var(X),latex_formula(F, 1)]) 763 | ; 764 | format(latex, '\\exists ~@. [~@]', [latex_var(X),latex_formula(F, 0)]) 765 | ). 766 | latex_formula(p(A,B), NB) :- 767 | !, 768 | ( 769 | NB =:= 0 770 | -> 771 | format(latex, '~@ \\otimes ~@', [latex_formula(A, 1),latex_formula(B, 1)]) 772 | ; 773 | format(latex, '(~@ \\otimes ~@)', [latex_formula(A, 1),latex_formula(B, 1)]) 774 | ). 775 | latex_formula(impl(A,B), NB) :- 776 | !, 777 | ( 778 | NB =:= 0 779 | -> 780 | format(latex, '~@ \\multimap ~@', [latex_formula(A, 1),latex_formula(B, 0)]) 781 | ; 782 | format(latex, '(~@ \\multimap ~@)', [latex_formula(A, 1),latex_formula(B, 1)]) 783 | ). 784 | 785 | is_quantified(_-F) :- 786 | is_quantified(F). 787 | is_quantified(exists(_,_)). 788 | is_quantified(forall(_,_)). 789 | is_quantified(at(_,_)). 790 | is_quantified(at(_,_,_,_)). 791 | 792 | latex_var(V) :- 793 | ( 794 | V = var(M) 795 | -> 796 | variable_atom(M, W), 797 | write(latex, W) 798 | ; 799 | print(latex, V) 800 | ). 801 | 802 | 803 | variable_atom(N, At) :- 804 | VN is N mod 5, 805 | VI is N//5, 806 | print_var1(VN, V), 807 | atomic_list_concat([V, '_{', VI, '}'], At). 808 | 809 | print_var1(0, x). 810 | print_var1(1, y). 811 | print_var1(2, z). 812 | print_var1(3, v). 813 | print_var1(4, w). 814 | 815 | % = latex_semantics(+LambdaTerm) 816 | % 817 | % output LambdaTerm to LaTeX stream "latex 818 | % supports several convenient abbreviations to make the output look more like first-order/higher-order logic 819 | 820 | latex_semantics(Sem) :- 821 | format(latex, '~2n\\begin{equation}~n', []), 822 | latex_semantics(Sem, 0), 823 | format(latex, '~n\\end{equation}~2n', []). 824 | 825 | latex_semantics(true, _) :- 826 | !, 827 | format(latex, '\\top ', []). 828 | latex_semantics(false, _) :- 829 | !, 830 | format(latex, '\\bot ', []). 831 | latex_semantics(empty_set, _) :- 832 | !, 833 | format(latex, '\\emptyset ', []). 834 | latex_semantics(forall, _) :- 835 | !, 836 | format(latex, '\\forall ', []). 837 | latex_semantics(exists, _) :- 838 | !, 839 | format(latex, '\\exists ', []). 840 | latex_semantics(iota, _) :- 841 | !, 842 | format(latex, '\\iota ', []). 843 | latex_semantics(epsilon, _) :- 844 | !, 845 | format(latex, '\\epsilon ', []). 846 | latex_semantics(tau, _) :- 847 | !, 848 | format(latex, '\\tau ', []). 849 | latex_semantics(number_of(A), _) :- 850 | !, 851 | format(latex, ' | ~@ |', [latex_semantics(A, 0)]). 852 | latex_semantics(A, _) :- 853 | atomic(A), 854 | !, 855 | latex_atom(A). 856 | latex_semantics('$VAR'(N), _) :- 857 | !, 858 | variable_atom(N, At), 859 | write(latex, At). 860 | latex_semantics(lambda(X,M), NB) :- 861 | !, 862 | ( 863 | NB =:= 0 864 | -> 865 | format(latex, '\\lambda ~@. ~@', [latex_semantics(X, 1), latex_semantics(M, 1)]) 866 | ; 867 | format(latex, '(\\lambda ~@. ~@)', [latex_semantics(X, 1), latex_semantics(M, 1)]) 868 | ). 869 | latex_semantics(appl(appl(appl(F,Z),Y),X), _) :- 870 | atomic(F), 871 | term_application(prolog_like), 872 | !, 873 | format(latex, '~@(~@,~@,~@)', [latex_atom(F),latex_semantics(X, 0),latex_semantics(Y, 0),latex_semantics(Z, 0)]). 874 | latex_semantics(appl(appl(F,Y),X), _) :- 875 | atomic(F), 876 | term_application(prolog_like), 877 | !, 878 | format(latex, '~@(~@,~@)', [latex_atom(F),latex_semantics(X, 0),latex_semantics(Y, 0)]). 879 | latex_semantics(appl(F,X), _) :- 880 | atomic(F), 881 | term_application(prolog_like), 882 | !, 883 | format(latex, '~@(~@)', [latex_atom(F),latex_semantics(X, 0)]). 884 | latex_semantics(appl(N,M), NB) :- 885 | !, 886 | ( 887 | NB =:= 0 888 | -> 889 | format(latex, '~@\\, ~@', [latex_semantics(N, 1), latex_semantics(M, 1)]) 890 | ; 891 | format(latex, '(~@\\, ~@)', [latex_semantics(N, 1), latex_semantics(M, 1)]) 892 | ). 893 | latex_semantics(pair(N,M), _NB) :- 894 | !, 895 | format(latex, '\\langle ~@,~@\\rangle', [latex_semantics(N, 0), latex_semantics(M, 0)]). 896 | latex_semantics(pi1(N), _NB) :- 897 | !, 898 | ( 899 | unary_term(N) 900 | -> 901 | format(latex, '\\pi_1 ~@', [latex_semantics(N, 1)]) 902 | ; 903 | format(latex, '\\pi_1(~@)', [latex_semantics(N, 0)]) 904 | ). 905 | latex_semantics(pi2(N), _NB) :- 906 | !, 907 | ( 908 | unary_term(N) 909 | -> 910 | format(latex, '\\pi_2 ~@', [latex_semantics(N, 1)]) 911 | ; 912 | format(latex, '\\pi_2(~@)', [latex_semantics(N, 0)]) 913 | ). 914 | latex_semantics(neg(N), _NB) :- 915 | !, 916 | ( 917 | unary_term(N) 918 | -> 919 | format(latex, '\\neg ~@', [latex_semantics(N, 1)]) 920 | ; 921 | format(latex, '\\neg(~@)', [latex_semantics(N, 0)]) 922 | ). 923 | latex_semantics(not(N), _NB) :- 924 | !, 925 | ( 926 | unary_term(N) 927 | -> 928 | format(latex, '\\neg ~@', [latex_semantics(N, 1)]) 929 | ; 930 | format(latex, '\\neg(~@)', [latex_semantics(N, 0)]) 931 | ). 932 | latex_semantics(possible(N), _NB) :- 933 | !, 934 | ( 935 | unary_term(N) 936 | -> 937 | format(latex, '\\Diamond ~@', [latex_semantics(N, 1)]) 938 | ; 939 | format(latex, '\\Diamond(~@)', [latex_semantics(N, 0)]) 940 | ). 941 | latex_semantics(necessary(N), _NB) :- 942 | !, 943 | ( 944 | unary_term(N) 945 | -> 946 | format(latex, '\\Box ~@', [latex_semantics(N, 1)]) 947 | ; 948 | format(latex, '\\Box(~@)', [latex_semantics(N, 0)]) 949 | ). 950 | latex_semantics(quant(Q,X,F), _NB) :- 951 | !, 952 | ( 953 | F = quant(_,_,_) 954 | -> 955 | format(latex, '~@ ~@. ~@', [latex_quantifier(Q), latex_semantics(X, 0), latex_semantics(F, 1)]) 956 | ; 957 | format(latex, '~@ ~@.[~@]', [latex_quantifier(Q), latex_semantics(X, 0), latex_semantics(F, 0)]) 958 | ). 959 | latex_semantics(bool(P,B,Q), NB) :- 960 | !, 961 | ( 962 | NB =:= 0 963 | -> 964 | format(latex, '~@ ~@ ~@', [latex_semantics(P, 1), latex_bool(B), latex_semantics(Q, 1)]) 965 | ; 966 | format(latex, '(~@ ~@ ~@)', [latex_semantics(P, 1), latex_bool(B), latex_semantics(Q, 1)]) 967 | ). 968 | latex_semantics(Term, _) :- 969 | /* unknown: warn but output normally */ 970 | functor(Term, F, A), 971 | format(user_error, '~N{Warning: unknown LaTeX output form: ~w (with functor ~w/~w)}~n', [Term, F, A]), 972 | format(latex, ' ~w ', [Term]). 973 | 974 | latex_bool(&) :- 975 | !, 976 | write(latex, '\\wedge'). 977 | latex_bool(\/) :- 978 | !, 979 | write(latex, '\\vee'). 980 | latex_bool(->) :- 981 | !, 982 | write(latex, '\\rightarrow'). 983 | latex_bool(leq) :- 984 | !, 985 | write(latex, '\\leq'). 986 | latex_bool(lneq) :- 987 | !, 988 | write(latex, '\\lneq'). 989 | latex_bool(geq) :- 990 | !, 991 | write(latex, '\\geq'). 992 | latex_bool(gneq) :- 993 | !, 994 | write(latex, '\\gneq'). 995 | latex_bool(set_member) :- 996 | !, 997 | write(latex, '\\in'). 998 | latex_bool(B) :- 999 | /* unknown: warn but output normally */ 1000 | format(user_error, '~N{Warning: unknown LaTeX output boolean connective: ~w}~n', [B]), 1001 | format(latex, ' ~w ', [B]). 1002 | 1003 | latex_quantifier(Q) :- 1004 | atom(Q), 1005 | !, 1006 | format(latex, '\\~w ', [Q]). 1007 | latex_quantifier(Q) :- 1008 | /* unknown: warn but output normally */ 1009 | format(user_error, '~N{Warning: unknown LaTeX output quantifier: ~w}~n', [Q]), 1010 | format(latex, ' ~w ', [Q]). 1011 | 1012 | % = latex_atom(+PrologAtom) 1013 | % 1014 | % output a Prolog atom to LaTeX, giving some constants (forall/exists/iota) 1015 | % special treatment and taking care of underscores to help LaTeX process them 1016 | 1017 | latex_atom(forall) :- 1018 | !, 1019 | format(latex, '\\forall ', []). 1020 | latex_atom(exists) :- 1021 | !, 1022 | format(latex, '\\exists ', []). 1023 | latex_atom(iota) :- 1024 | !, 1025 | format(latex, '\\iota ', []). 1026 | latex_atom(epsilon) :- 1027 | !, 1028 | format(latex, '\\epsilon ', []). 1029 | latex_atom(tau) :- 1030 | !, 1031 | format(latex, '\\tau ', []). 1032 | latex_atom(A0) :- 1033 | /* take care of Prolog atoms containing '_' */ 1034 | atomic_list_concat(List, '_', A0), 1035 | atomic_list_concat(List, '\\_', A), 1036 | format(latex, '\\textrm{~w}', [A]). 1037 | 1038 | latex_rm_atom(A0) :- 1039 | /* take care of Prolog atoms containing '_' */ 1040 | atomic_list_concat(List, '_', A0), 1041 | atomic_list_concat(List, '\\_', A), 1042 | format(latex, '\\textrm{~w}', [A]). 1043 | 1044 | latex_it_atom(A0) :- 1045 | /* take care of Prolog atoms containing '_' */ 1046 | atomic_list_concat(List, '_', A0), 1047 | atomic_list_concat(List, '\\_', A), 1048 | format(latex, '\\textit{~w}', [A]). 1049 | 1050 | latex_term(Term) :- 1051 | ( 1052 | var(Term) 1053 | -> 1054 | format(latex, '\\_', []) 1055 | ; 1056 | integer(Term) 1057 | -> 1058 | write(latex,Term) 1059 | ; 1060 | Term = '$VAR'(_) 1061 | -> 1062 | print(latex, Term) 1063 | ; 1064 | Term = var(V) 1065 | -> 1066 | variable_atom(V, At), 1067 | write(latex, At) 1068 | ; 1069 | Term =.. [F|Args], 1070 | latex_it_atom(F), 1071 | latex_arguments(Args) 1072 | ). 1073 | 1074 | % = latex_arguments(+ListOfArguments) 1075 | % 1076 | % write a list of arguments to a predicate ie. (t_1, t_2, t3) sending 1077 | % each t_i to print and outputing nothing for a proposition (ie. the 1078 | % empty list of arguments. 1079 | 1080 | latex_arguments([]). 1081 | latex_arguments([A|As]) :- 1082 | write(latex, '('), 1083 | latex_arguments(As, A), 1084 | write(latex, ')'). 1085 | 1086 | latex_arguments([], A) :- 1087 | latex_term(A). 1088 | latex_arguments([A|As], A0) :- 1089 | format(latex, '~@, ', [latex_term(A0)]), 1090 | latex_arguments(As, A). 1091 | 1092 | % = unary_term(+Term) 1093 | % 1094 | % if unary_term(Term) is true of their argument, the unary connectives pi1, 1095 | % pi2, neg, etc. will not put parentheses around this argument. 1096 | 1097 | unary_term(pi1(_)). 1098 | unary_term(pi2(_)). 1099 | unary_term(neg(_)). 1100 | unary_term(possible(_)). 1101 | unary_term(necessary(_)). 1102 | unary_term(number_of(_)). 1103 | unary_term(quant(_, _, _)). 1104 | unary_term(true). 1105 | unary_term(false). 1106 | -------------------------------------------------------------------------------- /lexicon.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | 3 | :- module(lexicon, [lookup/4, 4 | lookup/5, 5 | macro_expand/2, 6 | lexical_lookup/5, 7 | lex_to_displacement/2, 8 | lex_to_hybrid/3, 9 | canonical_semantic_term/2]). 10 | 11 | :- use_module(translations, [translate/3, translate_hybrid/6,linear_to_hybrid/3,linear_to_displacement/3]). 12 | :- use_module(auxiliaries, [universal_closure/2,universal_disclosure/2, is_ll1_formula/2]). 13 | %:- use_module(prenex, [prenex/2,pushin/2]). 14 | 15 | % define operators to allow for easier specification of 16 | % hybrid and displacement lexical entries. 17 | % 18 | % WARNING: in case of doubt, use parentheses to disambiguate! 19 | % I have deliberately not changed the definitions of standard 20 | % mathematical and logical operations of Prolog, notably | 21 | % (alternative of ; for use in DCG), / and *. 22 | % 23 | % This means for example that: 24 | % c/d*b/c = ((c/d)*b)/c 25 | % which corresponds to a left-to-right evaluation of the 26 | % mathematical functions of division and multiplication. 27 | % However, we do have the familiar a/b/c = (a/b)/c and 28 | % c\b\a = (c\(b\a) and even a\b/c = (a\b)/c. 29 | 30 | :- op(400, xfy, \). 31 | :- op(400, xfy, \>). % = \downarrow_> 32 | :- op(400, yfx, />). % = \uparrow_> 33 | :- op(400, xfy, \<). % = \downarrow_< 34 | :- op(400, yfx, /<). % = \uparrow_> 35 | :- op(400, yfx, *<). % = \odot_< 36 | :- op(400, yfx, *>). % = \odot_> 37 | :- op(400, fx, ^). 38 | :- op(190, yfx, @). 39 | 40 | :- dynamic hybrid_lookup/3, memo_lookup/2. 41 | 42 | update(F0, F) :- 43 | replace_s_levels(F0, F). 44 | % F0 = F. 45 | % pushin(F0, F). 46 | % prenex(F0, F). 47 | 48 | 49 | lookup(Words, Formulas, Goal, ExpandedGoal) :- 50 | lookup(Words, Formulas, _, Goal, ExpandedGoal). 51 | 52 | lookup(Words, Formulas, Semantics, Goal0, ExpandedGoal) :- 53 | retractall(hybrid_lookup(_, _, _)), 54 | sentence_lookup(Words, Formulas, Semantics, 0, N), 55 | macro_expand(Goal0, Goal), 56 | translate(Goal, [0, N], ExpandedGoal0), 57 | update(ExpandedGoal0, ExpandedGoal). 58 | 59 | sentence_lookup([], [], [], N, N). 60 | sentence_lookup([W|Ws], [F|Fs], [N0-S|Ss], N0, N) :- 61 | N1 is N0 + 1, 62 | lexical_lookup(W, F, S, N0, N1), 63 | sentence_lookup(Ws, Fs, Ss, N1, N). 64 | 65 | lexical_lookup(Word, Formula, Semantics, N0, N1) :- 66 | ( 67 | current_predicate(lex/3), 68 | lex(Word, _, _) 69 | -> 70 | /* Lambek/Displacement entry */ 71 | lex(Word, Formula0, Semantics0), 72 | canonical_semantic_term(Semantics0, Semantics), 73 | macro_expand(Formula0, Formula1), 74 | translate(Formula1, [N0,N1], Formula2), 75 | update(Formula2, Formula), 76 | retractall(memo_lookup(N0, _)), 77 | assert(memo_lookup(N0, Word)) 78 | ; 79 | current_predicate(lex/4), 80 | lex(Word, _, _, _) 81 | -> 82 | /* hybrid entry */ 83 | lex(Word, Formula0, ProsTerm0, Semantics0), 84 | /* prevent potential errors caused by accidental sharing of variables between ProsTerm and Semantics0 */ 85 | copy_term(ProsTerm0, ProsTerm), 86 | canonical_semantic_term(Semantics0, Semantics), 87 | macro_expand(Formula0, Formula1), 88 | translate_hybrid(Formula1, ProsTerm, Word, N0, N1, Formula2), 89 | update(Formula2, Formula), 90 | retractall(hybrid_lookup(N0, _, _)), 91 | assert(hybrid_lookup(N0, Formula1, ProsTerm)) 92 | ; 93 | /* first-order linear logic entry */ 94 | current_predicate(lex/5), 95 | lex(Word, _, _, _, _) 96 | -> 97 | lex(Word, Formula0, N0, N1, Semantics0), 98 | macro_expand(Formula0, Formula1), 99 | is_ll1_formula(Formula1, Word), 100 | update(Formula1, Formula), 101 | /* prevent potential errors caused by accidental sharing of variables between ProsTerm and Semantics0 */ 102 | canonical_semantic_term(Semantics0, Semantics) 103 | ; 104 | format(user_error, '~N{Error: No lexical entry for "~w"}~n', [Word]), 105 | fail 106 | ). 107 | 108 | lex_to_displacement(Word, Formula) :- 109 | lexical_lookup(Word, MFormula, _, 1, 2), 110 | universal_closure(MFormula, CFormula), 111 | linear_to_displacement(CFormula, [1,2], Formula). 112 | lex_to_hybrid(Word, Formula, Term) :- 113 | lexical_lookup(Word, MFormula, _, 1, 2), 114 | universal_disclosure(MFormula, FFormula), 115 | % MFormula = FFormula, 116 | linear_to_hybrid(FFormula, Formula, Term). 117 | 118 | macro_expand(F0, F) :- 119 | current_predicate(macro/2), 120 | macro(F0, F1), 121 | !, 122 | macro_expand(F1, F). 123 | macro_expand(d_q, F) :- 124 | !, 125 | macro_expand(((s/ 169 | Formula = at(At, Vars) 170 | ; 171 | Formula = at(At, [Vars]) 172 | ). 173 | macro_expand(A0, A) :- 174 | atom(A0), 175 | !, 176 | ( 177 | current_predicate(user:atomic_formula/3), 178 | user:atomic_formula(F, A0, _Vars) 179 | -> 180 | format(user_error, '~N{Warning: atomic formula used as "~w" but declared as "~w"}~n', [A0,F]) 181 | ; 182 | true 183 | ), 184 | A = at(A0). 185 | macro_expand(at(A), at(A)) :- 186 | !. 187 | macro_expand(at(A,B), at(A,B)) :- 188 | !. 189 | 190 | macro_expand(forall(X,A0), forall(X,A)) :- 191 | !, 192 | macro_expand(A0, A). 193 | macro_expand(exists(X,A0), exists(X,A)) :- 194 | !, 195 | macro_expand(A0, A). 196 | macro_expand(impl(A0,B0), impl(A,B)) :- 197 | !, 198 | macro_expand(A0, A), 199 | macro_expand(B0, B). 200 | 201 | macro_expand(p(K,A0,B0), p(K,A,B)) :- 202 | !, 203 | macro_expand(A0, A), 204 | macro_expand(B0, B). 205 | macro_expand(dl(K,A0,B0), dl(K,A,B)) :- 206 | !, 207 | macro_expand(A0, A), 208 | macro_expand(B0, B). 209 | macro_expand(dr(K,A0,B0), dr(K,A,B)) :- 210 | !, 211 | macro_expand(A0, A), 212 | macro_expand(B0, B). 213 | 214 | macro_expand((A0*B0), p(A,B)) :- 215 | !, 216 | macro_expand(A0, A), 217 | macro_expand(B0, B). 218 | macro_expand(p(A0,B0), p(A,B)) :- 219 | !, 220 | macro_expand(A0, A), 221 | macro_expand(B0, B). 222 | 223 | macro_expand((A0\B0), dl(A,B)) :- 224 | !, 225 | macro_expand(A0, A), 226 | macro_expand(B0, B). 227 | macro_expand(dl(A0,B0), dl(A,B)) :- 228 | !, 229 | macro_expand(A0, A), 230 | macro_expand(B0, B). 231 | 232 | macro_expand((A0/B0), dr(A,B)) :- 233 | !, 234 | macro_expand(A0, A), 235 | macro_expand(B0, B). 236 | macro_expand(dr(A0,B0), dr(A,B)) :- 237 | !, 238 | macro_expand(A0, A), 239 | macro_expand(B0, B). 240 | 241 | 242 | macro_expand((A0\B0), dl(>,A,B)) :- 247 | !, 248 | macro_expand(A0, A), 249 | macro_expand(B0, B). 250 | macro_expand((A0/B0), dr(>,A,B)) :- 255 | !, 256 | macro_expand(A0, A), 257 | macro_expand(B0, B). 258 | macro_expand((A0*B0), p(>,A,B)) :- 263 | !, 264 | macro_expand(A0, A), 265 | macro_expand(B0, B). 266 | macro_expand(^A0, bridge(A)) :- 267 | !, 268 | macro_expand(A0, A). 269 | macro_expand(bridge(A0), bridge(A)) :- 270 | !, 271 | macro_expand(A0, A). 272 | macro_expand(lproj(A0), lproj(A)) :- 273 | !, 274 | macro_expand(A0, A). 275 | macro_expand(rproj(A0), rproj(A)) :- 276 | !, 277 | macro_expand(A0, A). 278 | 279 | macro_expand((B0->A0), h(A,B)) :- 280 | !, 281 | macro_expand(A0, A), 282 | macro_expand(B0, B). 283 | macro_expand((A0|B0), h(A,B)) :- 284 | !, 285 | macro_expand(A0, A), 286 | macro_expand(B0, B). 287 | macro_expand(Formula, Formula) :- 288 | !, 289 | functor(Formula, F, A), 290 | functor(Term, F, A), 291 | format('~N{Warning: unknown formula ~w with functor ~w/~d}~n', [Formula, F, A]), 292 | ( 293 | current_predicate(user:atomic_formula/3), 294 | user:atomic_formula(Atomic, F, _), 295 | functor(Atomic, F, A0) 296 | -> 297 | format('~N{Warning: did you mean ~w/~d?}~n', [F, A0]) 298 | ; 299 | format('{Warning: you have to declare atomic formulas explicitly with: atomic_formula(~p).}~n', [Term]) 300 | ), 301 | fail. 302 | 303 | in_lexicon(W) :- 304 | lex(W, _, _). 305 | in_lexicon(W) :- 306 | lex(W, _, _, _). 307 | 308 | 309 | canonical_semantic_term(Term0, Term) :- 310 | copy_term(Term0, Term1), 311 | canonical_semantics(Term1, Term). 312 | 313 | canonical_semantics(X, Z) :- 314 | var(X), 315 | !, 316 | Z = X. 317 | canonical_semantics(X0@Y0, appl(X,Y)) :- 318 | !, 319 | canonical_semantics(X0, X), 320 | canonical_semantics(Y0, Y). 321 | canonical_semantics(X^Y0, lambda(X,Y)) :- 322 | !, 323 | canonical_semantics(Y0, Y). 324 | canonical_semantics(Term0, Term) :- 325 | Term0 =.. [F|List0], 326 | length(List0, L), 327 | length(List, L), 328 | Term =.. [F|List], 329 | canonical_semantics_list(List0, List). 330 | 331 | canonical_semantics_list([], []). 332 | canonical_semantics_list([X|Xs], [Y|Ys]) :- 333 | canonical_semantics(X, Y), 334 | canonical_semantics_list(Xs, Ys). 335 | 336 | replace_s_levels(at(s1, Ys), forall(X,at(s, [X|Ys]))) :- 337 | !. 338 | replace_s_levels(at(s2, Ys), forall(X,at(s, [s(X)|Ys]))) :- 339 | !. 340 | replace_s_levels(at(s3, Ys), forall(X,at(s, [s(s(X))|Ys]))) :- 341 | !. 342 | replace_s_levels(at(s4, Ys), forall(X,at(s, [s(s(s(X)))|Ys]))) :- 343 | !. 344 | replace_s_levels(at(X,Ys), at(X,Ys)). 345 | replace_s_levels(p(A0,B0), p(A,B)) :- 346 | replace_s_levels(A0, A), 347 | replace_s_levels(B0, B). 348 | replace_s_levels(impl(A0,B0), impl(A,B)) :- 349 | replace_s_levels(A0, A), 350 | replace_s_levels(B0, B). 351 | replace_s_levels(forall(X,A0), forall(X,A)) :- 352 | replace_s_levels(A0, A). 353 | replace_s_levels(exists(X,A0), exists(X,A)) :- 354 | replace_s_levels(A0, A). 355 | -------------------------------------------------------------------------------- /ll1_grammar.pl: -------------------------------------------------------------------------------- 1 | % ==================================== 2 | % = First-order linear logic grammar = 3 | % ==================================== 4 | 5 | % This grammar provides some examples of how to use the first-order variables for some things which cannot directly be implemented 6 | % either in hybrid type-logical grammars or in displacement grammars (even when case is added). The treatment of non-associativity 7 | % and blocking empty antecedent derivations given here is briefly mentioned in Section 6 of the following article 8 | % 9 | % Richard Moot (2014), Extended Lambek calculi and first-order linear logic, in Claudia Casadio, Bob Coecke, Michael Moortgat and 10 | % Philip Scott, eds `Categories and Types in Logic, Language, and Physics: Essays Dedicated to Jim Lambek on the Occasion of His 11 | % 90th Birthday', Springer LNCS 8222, 297-330 12 | 13 | :- op(190, yfx, @). 14 | 15 | :- abolish(lex/3), abolish(lex/4), abolish(test/1), abolish(atomic_formula/3), abolish(atomic_formula/1), abolish(macro/2). 16 | 17 | % For lambda terms, X^M is short for lambda(X,M) and M@N 18 | % is short for appl(M,N). As expected, X^Y^Z^X@Y@Z is 19 | % short for lambda(X,lambda(Y,lambda(Z,appl(appl(X,Y),Z)))) 20 | % though be warned that X@Y+V@Z corresponds to (X@Y)+(V@Z) 21 | 22 | atomic_formula(n(_)). 23 | atomic_formula(np(_)). 24 | atomic_formula(s(_)). 25 | atomic_formula(pp(_)). 26 | 27 | % = specify some abbreviations to make the lexical entries slightly more compact 28 | 29 | macro(adj(L,R), forall(X,forall(Y,impl(at(n, [X,R,Y]), at(n, [s(X),L,Y]))))). 30 | macro(pp(X,Y,Z), at(pp, [X,Y,Z])). 31 | macro(np(X,Y,Z), at(np, [X,Y,Z])). 32 | macro(n(X,Y,Z), at(n, [X,Y,Z])). 33 | macro(s(X,Y,Z), at(s, [X,Y,Z])). 34 | 35 | 36 | lex(the, forall(X,forall(Y,forall(Z,impl(n(Y,R,X), np(Z,L,X))))), L, R, iota). 37 | lex(hulk, forall(X,n(X,L,R)), L, R, hulk). 38 | lex(is, forall(Y,impl(adj(R,Y),forall(X,impl(np(nom,X,L), s(main,X,Y))))), L, R, Pred^Subj^Pred@Subj). 39 | lex(red, adj(L,R), L, R, red). 40 | lex(green, adj(L,R), L, R, green). 41 | lex(very, forall(X,impl(adj(R,X),adj(L,X))), L, R, Adj^N^(very@Adj)@N). 42 | % extraction and CSC 43 | lex(book, forall(X,n(X,L,R)), L, R, book). 44 | lex(and, forall(Z,forall(Y,impl(np(t(Z),R,Y),forall(X,impl(np(s(Z),X,L),np(Z,X,Y)))))), L, R, and). 45 | lex(read, forall(Z,forall(Y,impl(np(Z,R,Y),forall(X,impl(np(Z,X,L),s(Z,X,Y)))))), L, R, read). 46 | lex(mary, forall(Z,np(Z,L,R)), L, R, mary). 47 | lex(ak, forall(Z,np(Z,L,R)), L, R, ak). 48 | lex(wp, forall(Z,np(Z,L,R)), L, R, wp). 49 | lex(which, forall(Z,forall(X,impl(exists(Y,impl(np(Z,Y,Y),s(Z,R,X))),forall(V,impl(n(Z,V,L),n(Z,V,X)))))), L, R, Q^P^X^bool(P@X,&,Q@X)). 50 | 51 | test(1) :- 52 | parse([the,hulk,is,green], s(main)). 53 | test(2) :- 54 | /* should fail because of non-associativity */ 55 | parse([the,hulk,is,green,red], s(main)). 56 | test(3) :- 57 | /* NOTE: the semantics looks odd due to the notation convention for binary predicates, which displays */ 58 | /* (very green) (iota hulk) */ 59 | /* as very(iota(hulk), green) */ 60 | /* (change "option(prolog_like)." to "option(lambda_like)." in latex.pl to switch this off) */ 61 | parse([the,hulk,is,very,green], s(main)). 62 | test(4) :- 63 | /* should fail because empy antecedent derivations have been excluded for "very" */ 64 | parse([the,hulk,is,very], s(main)). 65 | 66 | % extraction and CSC 67 | test(5) :- 68 | parse([book,which,mary,read], forall(X,n(X))). 69 | test(6) :- 70 | parse([mary,read,ak,and,wp], forall(X,s(X))). 71 | test(7) :- 72 | parse([book,which,mary,read,ak,and], forall(X,n(X))). 73 | test(8) :- 74 | parse([book,which,mary,read,and,wp], forall(X,n(X))). 75 | % 76 | -------------------------------------------------------------------------------- /mill1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RichardMoot/LinearOne/55540e9a91b7a5c7722775f39ffbf50f5b472a7e/mill1.tgz -------------------------------------------------------------------------------- /options.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | 3 | :- module(options, [term_application/1, 4 | lexicon_separator/1, 5 | hybrid_pros/1, 6 | hybrid_connective/4, 7 | hybrid_epsilon/1, 8 | hybrid_concat/1, 9 | hybrid_item_start/1, 10 | hybrid_item_mid/1, 11 | hybrid_item_end/1, 12 | d_separator/1, 13 | d_concat/1, 14 | d_epsilon/1, 15 | output_indices/1, 16 | geometry/1, 17 | eta_short/1, 18 | generate_diagnostics/1]). 19 | 20 | % ===================================================== 21 | % = parameters for semantic output = 22 | % ===================================================== 23 | 24 | % set this option to "prolog_like" for a Prolog-like output; this will portray terms like 25 | % ((f y) x) as f(x,y) 26 | 27 | term_application(prolog_like). 28 | % term_application(lambda_like). 29 | 30 | %lexicon_separator(' - '). 31 | lexicon_separator(' :: '). 32 | 33 | % ===================================================== 34 | % = parameters for hybrid type-logical grammar output = 35 | % ===================================================== 36 | 37 | % = hybrid_pros 38 | % 39 | % This flag controls how the prosodic lambda term of hybrid type-logical grammars are output to LaTeX. 40 | % 41 | % When set of "pure", lambda terms are converted to pure lambda terms (without either the empty string 42 | % "epsilon" or the explicit concatenation operation "+". 43 | % 44 | % When set to "simple", pure lambda terms are converted, whenever possible, to simple lambda terms 45 | % using concatenation "+" and the empty string "epsilon". 46 | 47 | %hybrid_pros(pure). 48 | hybrid_pros(simple). 49 | 50 | 51 | % this option allows you to choose how to display the ACG/lambda grammar/hybrid type-logical 52 | % grammar "|" or "-o" connective. 53 | % A connective h(A,B) will be displayed by portraying, from left-to-right one of the 54 | % subformulas (A or B) then a Prolog atom (passed to LaTeX directly), then the other 55 | % subformula. 56 | 57 | hybrid_connective(h(A,B), A, '|', B). % hybrid type-logical grammar style 58 | %hybrid_connective(h(A,B), B, '\\multimap ', A). % ACG/lambda grammar style 59 | 60 | % these options allow you to customise the LaTeX display of the empty string "epsilon" and 61 | % the concatenation "+"; the only argument of these predicates is a single Prolog atom which 62 | % will be sent to LaTeX (we need a double backslash for LaTeX commands, due to the Prolog 63 | % meaning of the backslash). 64 | % 65 | % NOTE: these options make sense only when the option the file translations.pl has the option 66 | % 67 | % "hybrid_pros(simple)." 68 | % 69 | % For hybrid_pros(pure), there is no effect. 70 | 71 | hybrid_epsilon('\\epsilon'). 72 | hybrid_concat('\\circ'). 73 | 74 | % customize the display of items in hybrid proofs 75 | 76 | % = single-line Pros:Formula 77 | % 78 | %hybrid_item_start(''). 79 | %hybrid_item_mid(':'). 80 | %hybrid_item_end(''). 81 | 82 | % = separate line for Pros and Formula 83 | % 84 | hybrid_item_start('\\begin{array}{l}'). 85 | hybrid_item_mid('\\\\'). 86 | hybrid_item_end('\\end{array}'). 87 | 88 | % ===================================================== 89 | % = parameters for Displacement calculus output = 90 | % ===================================================== 91 | 92 | % these options allow you to customise the LaTeX display of Displacement calculus 93 | % string labels, we can use a symbol for the separator, for concatenation and for the 94 | % empty string, with d_separator, d_concat and d_epsilon respectively. 95 | 96 | % this option uses the +, 1, 0 operations, though it doesn't simplify "+0" 97 | %d_separator('+1+'). 98 | %d_concat('+'). 99 | %d_epsilon(0). 100 | d_separator(','). 101 | d_concat('\\ '). 102 | d_epsilon('\\epsilon'). 103 | 104 | 105 | % ===================================================== 106 | % = parameters for axiom link trace = 107 | % ===================================================== 108 | 109 | 110 | % set this option to "yes" to ouput unique identifier indices of atomic formulas (useful for 111 | % debugging) 112 | 113 | %output_indices(yes). 114 | 115 | output_indices(no). 116 | 117 | % ===================================================== 118 | % = parameters LaTeX paper size = 119 | % ===================================================== 120 | 121 | % the argument to the predicate geometry/1 is passed as an argument to the LaTeX geometry package. 122 | % so very wide page lenghts are preset; comment out all but the desired choice. 123 | % geometry(a2paper). 124 | geometry(a1paper). 125 | % geometry('paperwidth=200cm,textwidth=195cm'). 126 | % geometry('paperwidth=300cm,textwidth=295cm'). 127 | % geometry('paperwidth=400cm,textwidth=395cm'). 128 | % geometry('paperwidth=500cm,textwidth=495cm'). 129 | 130 | 131 | % ===================================================== 132 | % = parameters for proof generation = 133 | % ===================================================== 134 | 135 | % set this flag to anything but true to obtain long normal form natural deduction 136 | % proofs. 137 | 138 | eta_short(true). 139 | 140 | 141 | 142 | % set this flag to true to obtain a proof trace of the sequent proof generation 143 | % 144 | %generate_diagnostics(true). 145 | generate_diagnostics(false). 146 | -------------------------------------------------------------------------------- /ordset.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | % This is the file ordset.pl from the Public Domain DEC-10 Prolog 3 | % Library. The only changes and additions to the code are the 4 | % following. They are marked as such in the source code. 20030605 RM 5 | % 6 | % Replaced ord_union with an improved, pure version, also due to 7 | % R.A.O'Keefe. RM 8 | % 9 | % Added an ord_member predicate, which functions like member_chk for 10 | % lists, using the order of the elements. RM 11 | % 12 | % Added an ord_select predicate, which is deterministic when we know 13 | % the element to be selected. RM 14 | % 15 | % Added an ord_dup_insert predicate, which is exactly like ord_insert 16 | % except for the fact that the result is an ordered multiset instead 17 | % of an ordered set RM 18 | 19 | % File : ORDSET.PL 20 | % Author : R.A.O'Keefe 21 | % Updated: 22 May 1983 22 | % Purpose: Ordered set manipulation utilities 23 | 24 | % In this module, sets are represented by ordered lists with no 25 | % duplicates. Thus {c,r,a,f,t} would be [a,c,f,r,t]. The ordering 26 | % is defined by the @< family of term comparison predicates, which 27 | % is the ordering used by sort/2 and setof/3. 28 | 29 | % The benefit of the ordered representation is that the elementary 30 | % set operations can be done in time proportional to the Sum of the 31 | % argument sizes rather than their Product. Some of the unordered 32 | % set routines, such as member/2, length/2,, select/3 can be used 33 | % unchanged. The main difficulty with the ordered representation is 34 | % remembering to use it! 35 | 36 | :- module(ordset, [ 37 | list_to_ord_set/2, % List -> Set 38 | ord_merge/3, % OrdList x OrdList -> OrdList 39 | ord_disjoint/2, % Set x Set -> 40 | ord_insert/3, % Set x Elem -> Set 41 | ord_intersect/2, % Set x Set -> 42 | ord_intersect/3, % Set x Set -> Set 43 | ord_seteq/2, % Set x Set -> 44 | ord_subset/2, % Set x Set -> 45 | ord_subtract/3, % Set x Set -> Set 46 | ord_symdiff/3, % Set x Set -> Set 47 | ord_union/3, % Set x Set -> Set 48 | ord_key_intersect/3, % Set x Set -> Set 49 | ord_key_union/3, % Set x Set -> Set 50 | ord_key_union_i/3, % Set x Set -> Set 51 | ord_key_union_u/3, % Set x Set -> Set 52 | ord_key_select/4, % Key x Set -> Value x Set 53 | ord_key_delete/3, % Set x Key -> Set 54 | ord_key_insert/4, % Set x Key x Value -> Set 55 | ord_member/2, % Elem x Set -> 56 | ord_key_member/3, % Key x Set -> Value 57 | ord_dup_insert/3, % Set x Elem -> Set 58 | ord_delete/3, % Set x Elem -> Set 59 | ord_select/3] ). % Elem x Set -> Set 60 | 61 | % list_to_ord_set(+List, ?Set) 62 | % is true when Set is the ordered representation of the set represented 63 | % by the unordered representation List. The only reason for giving it 64 | % a name at all is that you may not have realised that sort/2 could be 65 | % used this way. 66 | 67 | list_to_ord_set(List, Set) :- 68 | sort(List, Set). 69 | 70 | 71 | % ord_merge(+List1, +List2, -Merged) 72 | % is true when Merged is the stable merge of the two given lists. 73 | % If the two lists are not ordered, the merge doesn't mean a great 74 | % deal. Merging is perfectly well defined when the inputs contain 75 | % duplicates, and all copies of an element are preserved in the 76 | % output, e.g. merge("122357", "34568", "12233455678"). Study this 77 | % routine carefully, as it is the basis for all the rest. 78 | 79 | ord_merge([Head1|Tail1], [Head2|Tail2], [Head2|Merged]) :- 80 | Head1 @> Head2, !, 81 | ord_merge([Head1|Tail1], Tail2, Merged). 82 | ord_merge([Head1|Tail1], List2, [Head1|Merged]) :- 83 | List2 \== [], !, 84 | ord_merge(Tail1, List2, Merged). 85 | ord_merge([], List2, List2) :- !. 86 | ord_merge(List1, [], List1). 87 | 88 | 89 | 90 | % ord_disjoint(+Set1, +Set2) 91 | % is true when the two ordered sets have no element in common. If the 92 | % arguments are not ordered, I have no idea what happens. 93 | 94 | ord_disjoint([], _) :- !. 95 | ord_disjoint(_, []) :- !. 96 | ord_disjoint([Head1|Tail1], [Head2|Tail2]) :- 97 | compare(Order, Head1, Head2), 98 | ord_disjoint(Order, Head1, Tail1, Head2, Tail2). 99 | 100 | ord_disjoint(<, _, Tail1, Head2, Tail2) :- 101 | ord_disjoint(Tail1, [Head2|Tail2]). 102 | ord_disjoint(>, Head1, Tail1, _, Tail2) :- 103 | ord_disjoint([Head1|Tail1], Tail2). 104 | 105 | 106 | % ord_insert(+Set1, +Element, ?Set2) 107 | % is the equivalent of add_element for ordered sets. It should give 108 | % exactly the same result as merge(Set1, [Element], Set2), but a bit 109 | % faster, and certainly more clearly. 110 | 111 | ord_insert([], Element, [Element]). 112 | ord_insert([Head|Tail], Element, Set) :- 113 | compare(Order, Head, Element), 114 | ord_insert(Order, Head, Tail, Element, Set). 115 | 116 | 117 | ord_insert(<, Head, Tail, Element, [Head|Set]) :- 118 | ord_insert(Tail, Element, Set). 119 | ord_insert(=, Head, Tail, _, [Head|Tail]). 120 | ord_insert(>, Head, Tail, Element, [Element,Head|Tail]). 121 | 122 | 123 | 124 | % ord_intersect(+Set1, +Set2) 125 | % is true when the two ordered sets have at least one element in common. 126 | % Note that the test is == rather than = . 127 | 128 | ord_intersect([Head1|Tail1], [Head2|Tail2]) :- 129 | compare(Order, Head1, Head2), 130 | ord_intersect(Order, Head1, Tail1, Head2, Tail2). 131 | 132 | ord_intersect(=, _, _, _, _). 133 | ord_intersect(<, _, Tail1, Head2, Tail2) :- 134 | ord_intersect(Tail1, [Head2|Tail2]). 135 | ord_intersect(>, Head1, Tail1, _, Tail2) :- 136 | ord_intersect([Head1|Tail1], Tail2). 137 | 138 | 139 | 140 | % ord_intersect(+Set1, +Set2, ?Intersection) 141 | % is true when Intersection is the ordered representation of Set1 142 | % and Set2, provided that Set1 and Set2 are ordered sets. 143 | 144 | % modified to work without cuts, like ord_union/3 20040429 RM 145 | % removed error in the base case 20040503 RM 146 | 147 | ord_intersect([], _, []). 148 | ord_intersect([H1|T1], Set2, Intersection) :- 149 | ord_intersect_2(Set2, H1, T1, Intersection). 150 | 151 | ord_intersect_2([], _, _, []). 152 | ord_intersect_2([H2|T2], H1, T1, Intersection) :- 153 | compare(Order, H1, H2), 154 | ord_intersect_3(Order, H1, T1, H2, T2, Intersection). 155 | 156 | ord_intersect_3(<, _, T1, H2, T2, Intersection) :- 157 | ord_intersect_2(T1, H2, T2, Intersection). 158 | ord_intersect_3(=, H1, T1, _, T2, [H1|Intersection]) :- 159 | ord_intersect(T1, T2, Intersection). 160 | ord_intersect_3(>, H1, T1, _, T2, Intersection) :- 161 | ord_intersect_2(T2, H1, T1, Intersection). 162 | 163 | /* original code 164 | 165 | ord_intersect(_, [], []) :- !. 166 | ord_intersect([], _, []) :- !. 167 | ord_intersect([Head1|Tail1], [Head2|Tail2], Intersection) :- 168 | compare(Order, Head1, Head2), 169 | ord_intersect(Order, Head1, Tail1, Head2, Tail2, Intersection). 170 | 171 | ord_intersect(=, Head, Tail1, _, Tail2, [Head|Intersection]) :- 172 | ord_intersect(Tail1, Tail2, Intersection). 173 | ord_intersect(<, _, Tail1, Head2, Tail2, Intersection) :- 174 | ord_intersect(Tail1, [Head2|Tail2], Intersection). 175 | ord_intersect(>, Head1, Tail1, _, Tail2, Intersection) :- 176 | ord_intersect([Head1|Tail1], Tail2, Intersection). 177 | 178 | */ 179 | 180 | % ord_seteq(+Set1, +Set2) 181 | % is true when the two arguments represent the same set. Since they 182 | % are assumed to be ordered representations, they must be identical. 183 | 184 | 185 | ord_seteq(Set1, Set2) :- 186 | Set1 == Set2. 187 | 188 | 189 | 190 | % ord_subset(+Set1, +Set2) 191 | % is true when every element of the ordered set Set1 appears in the 192 | % ordered set Set2. 193 | 194 | ord_subset([], _) :- !. 195 | ord_subset([Head1|Tail1], [Head2|Tail2]) :- 196 | compare(Order, Head1, Head2), 197 | ord_subset(Order, Head1, Tail1, Head2, Tail2). 198 | 199 | ord_subset(=, _, Tail1, _, Tail2) :- 200 | ord_subset(Tail1, Tail2). 201 | ord_subset(>, Head1, Tail1, _, Tail2) :- 202 | ord_subset([Head1|Tail1], Tail2). 203 | 204 | 205 | 206 | % ord_subtract(+Set1, +Set2, ?Difference) 207 | % is true when Difference contains all and only the elements of Set1 208 | % which are not also in Set2. 209 | 210 | 211 | ord_subtract(Set1, [], Set1) :- !. 212 | ord_subtract([], _, []) :- !. 213 | ord_subtract([Head1|Tail1], [Head2|Tail2], Difference) :- 214 | compare(Order, Head1, Head2), 215 | ord_subtract(Order, Head1, Tail1, Head2, Tail2, Difference). 216 | 217 | ord_subtract(=, _, Tail1, _, Tail2, Difference) :- 218 | ord_subtract(Tail1, Tail2, Difference). 219 | ord_subtract(<, Head1, Tail1, Head2, Tail2, [Head1|Difference]) :- 220 | ord_subtract(Tail1, [Head2|Tail2], Difference). 221 | ord_subtract(>, Head1, Tail1, _, Tail2, Difference) :- 222 | ord_subtract([Head1|Tail1], Tail2, Difference). 223 | 224 | 225 | 226 | % ord_symdiff(+Set1, +Set2, ?Difference) 227 | % is true when Difference is the symmetric difference of Set1 and Set2. 228 | 229 | ord_symdiff(Set1, [], Set1) :- !. 230 | ord_symdiff([], Set2, Set2) :- !. 231 | ord_symdiff([Head1|Tail1], [Head2|Tail2], Difference) :- 232 | compare(Order, Head1, Head2), 233 | ord_symdiff(Order, Head1, Tail1, Head2, Tail2, Difference). 234 | 235 | ord_symdiff(=, _, Tail1, _, Tail2, Difference) :- 236 | ord_symdiff(Tail1, Tail2, Difference). 237 | ord_symdiff(<, Head1, Tail1, Head2, Tail2, [Head1|Difference]) :- 238 | ord_symdiff(Tail1, [Head2|Tail2], Difference). 239 | ord_symdiff(>, Head1, Tail1, Head2, Tail2, [Head2|Difference]) :- 240 | ord_symdiff([Head1|Tail1], Tail2, Difference). 241 | 242 | 243 | 244 | % ord_union(+Set1, +Set2, ?Union) 245 | % is true when Union is the union of Set1 and Set2. Note that when 246 | % something occurs in both sets, we want to retain only one copy. 247 | 248 | % replaced original code with improved code from Richard A. O'Keefe's 249 | % `The Craft of Prolog' (1990) MIT Press. Read this book for discussion 250 | % and comments on the code. RM 251 | 252 | ord_union([], Set2, Set2). 253 | ord_union([H1|T1], Set2, Union) :- 254 | ord_union_2(Set2, H1, T1, Union). 255 | 256 | ord_union_2([], H1, T1, [H1|T1]). 257 | ord_union_2([H2|T2], H1, T1, Union) :- 258 | compare(Order, H1, H2), 259 | ord_union_3(Order, H1, T1, H2, T2, Union). 260 | 261 | ord_union_3(<, H1, T1, H2, T2, [H1|Union]) :- 262 | ord_union_2(T1, H2, T2, Union). 263 | ord_union_3(=, H1, T1, _, T2, [H1|Union]) :- 264 | ord_union(T1, T2, Union). 265 | ord_union_3(>, H1, T1, H2, T2, [H2|Union]) :- 266 | ord_union_2(T2, H1, T1, Union). 267 | 268 | /* original code 269 | 270 | ord_union(Set1, [], Set1) :- !. 271 | ord_union([], Set2, Set2) :- !. 272 | ord_union([Head1|Tail1], [Head2|Tail2], Union) :- 273 | compare(Order, Head1, Head2), 274 | ord_union(Order, Head1, Tail1, Head2, Tail2, Union). 275 | 276 | ord_union(=, Head, Tail1, _, Tail2, [Head|Union]) :- 277 | ord_union(Tail1, Tail2, Union). 278 | ord_union(<, Head1, Tail1, Head2, Tail2, [Head1|Union]) :- 279 | ord_union(Tail1, [Head2|Tail2], Union). 280 | ord_union(>, Head1, Tail1, Head2, Tail2, [Head2|Union]) :- 281 | ord_union([Head1|Tail1], Tail2, Union). 282 | */ 283 | 284 | % ord_dup_insert(+Set1, +Element, ?Set2) 285 | % 286 | % implementation of ord_insert for ordered *multisets* RM 287 | 288 | ord_dup_insert([], Element, [Element]). 289 | ord_dup_insert([Head|Tail], Element, Set) :- 290 | compare(Order, Head, Element), 291 | ord_dup_insert(Order, Head, Tail, Element, Set). 292 | 293 | 294 | ord_dup_insert(<, Head, Tail, Element, [Head|Set]) :- 295 | ord_dup_insert(Tail, Element, Set). 296 | ord_dup_insert(=, Head, Tail, Element, [Element,Head|Tail]). 297 | ord_dup_insert(>, Head, Tail, Element, [Element,Head|Tail]). 298 | 299 | % = ord_member(+Element, +OrdSet) 300 | % 301 | % given that the OrdSet is ordered, if we know Element, we can use the 302 | % order to get this element deterministically. RM 303 | 304 | ord_member(Element, [Head|Tail]) :- 305 | compare(Order, Element, Head), 306 | ord_member(Order, Element, Tail). 307 | 308 | ord_member(=, _, _). 309 | ord_member(>, Element, Tail) :- 310 | ord_member(Element, Tail). 311 | 312 | % = ord_select(+Element, +OrdSet, ?OrdSet) 313 | % 314 | % given that the OrdSet is ordered, if we know Element, we can use the 315 | % order to get this element deterministically. RM 316 | 317 | ord_select(Element, [Head|Tail], Rest) :- 318 | compare(Order, Element, Head), 319 | ord_select(Order, Element, Tail, Head, Rest). 320 | 321 | ord_select(=, _, Rest, _, Rest). 322 | ord_select(>, Element, Tail, Head, [Head|Rest]) :- 323 | ord_select(Element, Tail, Rest). 324 | 325 | 326 | % = ord_delete(+OrdSet, +Element, -OrdSet) 327 | % 328 | % as ord_select/3, but succeeds even if the Element is not in OrdSet 329 | % RM 330 | 331 | ord_delete([], _, []). 332 | ord_delete([Head|Tail], Element, Rest) :- 333 | compare(Order, Element, Head), 334 | ord_delete(Order, Tail, Element, Head, Rest). 335 | 336 | ord_delete(<, Tail, _, Head, [Head|Tail]). 337 | ord_delete(=, Rest, _, _, Rest). 338 | ord_delete(>, Tail, Element, Head, [Head|Rest]) :- 339 | ord_delete(Tail, Element, Rest). 340 | 341 | 342 | % = ord_key_member(+Key, +OrdSet, ?Value) 343 | % 344 | % as ord_member/2, but assumes the elements of OrdSet are Key-Value 345 | % pairs. RM 346 | 347 | ord_key_member(Element, [Head-Data0|Tail], Data) :- 348 | compare(Order, Element, Head), 349 | ord_key_member(Order, Element, Tail, Data0, Data). 350 | 351 | ord_key_member(=, _, _, Data, Data). 352 | ord_key_member(>, Element, Tail, _, Data) :- 353 | ord_key_member(Element, Tail, Data). 354 | 355 | % = ord_key_select(+Key, +OrdSet, -Value, -OrdSet) 356 | % 357 | % as ord_select/3, but assumes the elements of OrdSet are Key-Value 358 | % pairs. RM 359 | 360 | ord_key_select(Element, [Head-Data0|Tail], Data, Rest) :- 361 | compare(Order, Element, Head), 362 | ord_key_select(Order, Element, Tail, Head, Data0, Data, Rest). 363 | 364 | ord_key_select(=, _, Rest, _, Data, Data, Rest). 365 | ord_key_select(>, Element, Tail, Head, Data0, Data, [Head-Data0|Rest]) :- 366 | ord_key_select(Element, Tail, Data, Rest). 367 | 368 | % = ord_key_delete(+OrdSet, +Key, -OrdSet) 369 | % 370 | % as ord_delete/3, but assumes the elements of OrdSet are Key-Value 371 | % pairs. RM 372 | 373 | ord_key_delete([], _, []). 374 | ord_key_delete([Key-Data|Tail], Element, Rest) :- 375 | compare(Order, Element, Key), 376 | ord_key_delete(Order, Tail, Element, Key, Data, Rest). 377 | 378 | ord_key_delete(<, Tail, _, Key, Data, [Key-Data|Tail]). 379 | ord_key_delete(=, Rest, _, _, _, Rest). 380 | ord_key_delete(>, Tail, Element, Key, Data, [Key-Data|Rest]) :- 381 | ord_key_delete(Tail, Element, Rest). 382 | 383 | % = ord_key_insert(+OrdSet, +Key, +Data, -OrdSet) 384 | % 385 | % as ord_insert/3, but assumes the elements of OrdSet are Key-Value 386 | % pairs. RM 387 | 388 | ord_key_insert([], Key, Data, [Key-Data]). 389 | ord_key_insert([Key-Data|Tail], Key0, Data0, Rest) :- 390 | compare(Order, Key0, Key), 391 | ord_key_insert(Order, Tail, Key0, Data0, Key, Data, Rest). 392 | 393 | ord_key_insert(<, Tail, Key0, Data0, Key, Data, [Key0-Data0,Key-Data|Tail]). 394 | ord_key_insert(=, Rest, Key, Data0, Key, _Data, [Key-Data0|Rest]). 395 | ord_key_insert(>, Tail, Key0, Data0, Key, Data, [Key-Data|Rest]) :- 396 | ord_key_insert(Tail, Key0, Data0, Rest). 397 | 398 | 399 | % = ord_key_union(+Map1, +Map2, ?Map3) 400 | % 401 | % as ord_union/3, but for ordered sets of Key-Value pairs, where Value 402 | % is itself an ordered set. If Map1 and Map2 contain the same Key, 403 | % Map3 will contain the ord_union of the two values. RM 404 | 405 | ord_key_union([], Set2, Set2). 406 | ord_key_union([H1-V1|T1], Set2, Union) :- 407 | ord_key_union_2(Set2, H1, V1, T1, Union). 408 | 409 | ord_key_union_2([], H1, V1, T1, [H1-V1|T1]). 410 | ord_key_union_2([H2-V2|T2], H1, V1, T1, Union) :- 411 | compare(Order, H1, H2), 412 | ord_key_union_3(Order, H1, V1, T1, H2, V2, T2, Union). 413 | 414 | ord_key_union_3(<, H1, V1, T1, H2, V2, T2, [H1-V1|Union]) :- 415 | ord_key_union_2(T1, H2, V2, T2, Union). 416 | ord_key_union_3(=, H1, V1, T1, _, V2, T2, [H1-V|Union]) :- 417 | ord_union(V1, V2, V), 418 | ord_key_union(T1, T2, Union). 419 | ord_key_union_3(>, H1, V1, T1, H2, V2, T2, [H2-V2|Union]) :- 420 | ord_key_union_2(T2, H1, V1, T1, Union). 421 | 422 | % = ord_key_union_i(+Map1, +Map2, ?Map3) 423 | % 424 | % as ord_union/3, but for ordered sets of Key-Value pairs, where Value 425 | % is itself an ordered set. If Map1 and Map2 contain the same Key, 426 | % Map3 will contain the ord_interset of the two values. RM 427 | 428 | ord_key_union_i([], Set2, Set2). 429 | ord_key_union_i([H1-V1|T1], Set2, Union) :- 430 | ord_key_union_i2(Set2, H1, V1, T1, Union). 431 | 432 | ord_key_union_i2([], H1, V1, T1, [H1-V1|T1]). 433 | ord_key_union_i2([H2-V2|T2], H1, V1, T1, Union) :- 434 | compare(Order, H1, H2), 435 | ord_key_union_i3(Order, H1, V1, T1, H2, V2, T2, Union). 436 | 437 | ord_key_union_i3(<, H1, V1, T1, H2, V2, T2, [H1-V1|Union]) :- 438 | ord_key_union_i2(T1, H2, V2, T2, Union). 439 | ord_key_union_i3(=, H1, V1, T1, _, V2, T2, [H1-V|Union]) :- 440 | ord_intersect(V1, V2, V), 441 | ord_key_union_i(T1, T2, Union). 442 | ord_key_union_i3(>, H1, V1, T1, H2, V2, T2, [H2-V2|Union]) :- 443 | ord_key_union_i2(T2, H1, V1, T1, Union). 444 | 445 | % = ord_key_union_u(+Map1, +Map2, ?Map3) 446 | % 447 | % as ord_union/3, but for ordered sets of Key-Value pairs, where Value 448 | % is itself an ordered set. If Map1 and Map2 contain the same Key, 449 | % Map3 will unify the two values (and fail in case of conflic). RM 450 | 451 | ord_key_union_u([], Set2, Set2). 452 | ord_key_union_u([H1-V1|T1], Set2, Union) :- 453 | ord_key_union_u2(Set2, H1, V1, T1, Union). 454 | 455 | ord_key_union_u2([], H1, V1, T1, [H1-V1|T1]). 456 | ord_key_union_u2([H2-V2|T2], H1, V1, T1, Union) :- 457 | compare(Order, H1, H2), 458 | ord_key_union_u3(Order, H1, V1, T1, H2, V2, T2, Union). 459 | 460 | ord_key_union_u3(<, H1, V1, T1, H2, V2, T2, [H1-V1|Union]) :- 461 | ord_key_union_u2(T1, H2, V2, T2, Union). 462 | ord_key_union_u3(=, H1, V, T1, _, V, T2, [H1-V|Union]) :- 463 | ord_key_union_u(T1, T2, Union). 464 | ord_key_union_u3(>, H1, V1, T1, H2, V2, T2, [H2-V2|Union]) :- 465 | ord_key_union_u2(T2, H1, V1, T1, Union). 466 | 467 | 468 | % = ord_key_intersect(+Map1, +Map2, ?Map3) 469 | % 470 | % as ord_intersect/3, but for ordered sets of Key-Value pairs, where 471 | % Value is itself an ordered set. If Map1 and Map2 contain the same Key, 472 | % Map3 will contain the ord_intersect of the two values. RM 473 | 474 | ord_key_intersect([], _, []). 475 | ord_key_intersect([H1-V1|T1], Set2, Intersection) :- 476 | ord_key_intersect_2(Set2, H1, V1, T1, Intersection). 477 | 478 | ord_key_intersect_2([], _, _, _, []). 479 | ord_key_intersect_2([H2-V2|T2], H1, V1, T1, Intersection) :- 480 | compare(Order, H1, H2), 481 | ord_key_intersect_3(Order, H1, V1, T1, H2, V2, T2, Intersection). 482 | 483 | ord_key_intersect_3(<, _, _, T1, H2, V2, T2, Intersection) :- 484 | ord_key_intersect_2(T1, H2, V2, T2, Intersection). 485 | ord_key_intersect_3(=, H1, V1, T1, _, V2, T2, [H1-V|Intersection]) :- 486 | ord_intersect(V1, V2, V), 487 | ord_key_intersect(T1, T2, Intersection). 488 | ord_key_intersect_3(>, H1, V1, T1, _, _, T2, Intersection) :- 489 | ord_key_intersect_2(T2, H1, V1, T1, Intersection). 490 | 491 | -------------------------------------------------------------------------------- /portray_graph_dot.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | 3 | % = portray_graph(+Graph) 4 | % 5 | % GraphViz output 6 | 7 | :- module(portray_graph_tikz, [portray_graph/1,header/1,footer/1]). 8 | 9 | header. 10 | footer. 11 | 12 | portray_graph([]). 13 | portray_graph([vertex(N,As,FVs,Ps)|Rest]) :- 14 | format('~w [shape="record" label="{ ', [N]), 15 | portray_fvs(FVs), 16 | format('| ', []), 17 | portray_atoms(As), 18 | format('}"];~n', []), 19 | portray_links(Ps, N), 20 | portray_graph(Rest). 21 | 22 | portray_links([], _). 23 | portray_links([P|Ps], N) :- 24 | portray_link(P, N), 25 | portray_links(Ps, N). 26 | 27 | portray_link(univ(A,P), N) :- 28 | format('~w -> ~w [label="~p"];~n', [N,P,'$VAR'(A)]). 29 | portray_link(par(P,Q), N) :- 30 | format('~w -> ~w;~n~w -> ~w;~n', [N,P,N,Q]). 31 | 32 | portray_atoms([]). 33 | portray_atoms([A|As]) :- 34 | portray_atom(A), 35 | portray_atoms(As). 36 | 37 | portray_atom(neg(A,_,_)) :- 38 | format('-~w ', [A]). 39 | portray_atom(pos(A,_,_)) :- 40 | format('+~w ', [A]). 41 | 42 | 43 | portray_fvs([]). 44 | portray_fvs([V|Vs]) :- 45 | ( 46 | var(V) 47 | -> 48 | true 49 | ; 50 | V = var(N) 51 | -> 52 | format('~p ', ['$VAR'(N)]) 53 | ; 54 | true 55 | ), 56 | portray_fvs(Vs). 57 | -------------------------------------------------------------------------------- /portray_graph_none.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | 3 | % = portray_graph(+Graph) 4 | % 5 | % no graph output output 6 | 7 | :- module(portray_graph_tikz, [portray_graph/1,graph_header/0,graph_footer/1,latex_graph/1]). 8 | 9 | portray_graph(_). 10 | 11 | graph_header. 12 | 13 | graph_footer(_). 14 | 15 | latex_graph(_). 16 | -------------------------------------------------------------------------------- /portray_graph_tikz.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | 3 | % = portray_graph(+Graph) 4 | % 5 | % GraphViz output 6 | 7 | :- module(portray_graph_tikz, [portray_graph/1,graph_header/0,graph_footer/1,latex_graph/1]). 8 | 9 | :- dynamic '$GRAPH_NO'/1. 10 | 11 | graph_header :- 12 | ( exists_file('graph.tex') -> delete_file('graph.tex') ; true), 13 | open('graph.tex', write, _, [alias(graph)]), 14 | format(graph, '\\documentclass{article}~2n', []), 15 | format(graph, '\\usepackage[a2paper]{geometry}~n', []), 16 | format(graph, '\\usepackage{amsmath}~n', []), 17 | format(graph, '\\usepackage{cmll}~n', []), 18 | format(graph, '\\usepackage{tikz}~n', []), 19 | format(graph, '\\usetikzlibrary{graphs, graphdrawing}~n', []), 20 | format(graph, '\\usetikzlibrary{quotes}~n', []), 21 | format(graph, '\\usegdlibrary{layered}~2n', []), 22 | format(graph, '\\begin{document}~n', []), 23 | format(graph, '\\begin{center}~n', []), 24 | retractall('$GRAPH_NO'(_)), 25 | assert('$GRAPH_NO'(0)). 26 | 27 | graph_footer(P) :- 28 | '$GRAPH_NO'(N), 29 | write_graphs(N), 30 | write_proofs(P), 31 | format(graph, '\\end{center}~n', []), 32 | format(graph, '\\end{document}~n', []), 33 | close(graph), 34 | ( 35 | access_file('graph.tex', read) 36 | -> 37 | /* it is recommended to comment out the following line */ 38 | /* for larger proofs, since lualatex slows down */ 39 | /* considerably for a trace consisting of several */ 40 | /* larger graphs */ 41 | /* find lualatex in the user's $PATH */ 42 | % absolute_file_name(path(lualatex), LuaLaTeX, [access(execute)]), 43 | % process_create(LuaLaTeX, ['graph.tex'], [stdout(null)]), 44 | format('LaTeX graphs ready~n', []) 45 | ; 46 | format('LaTeX graph output failed~n', []) 47 | ). 48 | 49 | 50 | write_proofs(P) :- 51 | ( 52 | P =:= 0 53 | -> 54 | format(graph, 'No proofs found!~n', []) 55 | ; 56 | P =:= 1 57 | -> 58 | format(graph, '1 proof found.~n', []) 59 | ; 60 | format(graph, '~p proofs found.~n', [P]) 61 | ). 62 | 63 | write_graphs(N) :- 64 | ( 65 | N =:= 0 66 | -> 67 | format(graph, 'No graphs output!~n', []) 68 | ; 69 | N =:= 1 70 | -> 71 | format(graph, '1 graph output.~n', []) 72 | ; 73 | format(graph, '~p graphs output.~n', [N]) 74 | ). 75 | 76 | latex_graph(G0) :- 77 | copy_term(G0, G), 78 | graph_header, 79 | graph_numbervars(G, 0, _), 80 | format(graph, '{\\tikz \\graph [multi, layered layout, level distance=1.3cm] {~n', []), 81 | portray_vertices(G, -1, Max), 82 | portray_edges(G, Max), 83 | format(graph, '};~2n', []), 84 | format(graph, '\\end{center}~n', []), 85 | format(graph, '\\end{document}~n', []), 86 | told, 87 | ( 88 | access_file('graph.tex', read) 89 | -> 90 | /* find lualatex in the user's $PATH */ 91 | absolute_file_name(path(lualatex), LuaLaTeX, [access(execute)]), 92 | process_create(LuaLaTeX, ['graph.tex'], [stdout(null)]), 93 | format('LaTeX graphs ready~n', []) 94 | ; 95 | format('LaTeX graph output failed~n', []) 96 | ). 97 | 98 | portray_graph(G) :- 99 | '$GRAPH_NO'(N0), 100 | retractall('$GRAPH_NO'(_)), 101 | N is N0 + 1, 102 | assert('$GRAPH_NO'(N)), 103 | /* do temporary numbervars */ 104 | \+ \+ ( graph_numbervars(G, 0, _), 105 | format(graph, '{\\flushleft ~p\\hfill}~2n\\tikz \\graph [multi, layered layout, level distance=1.3cm] {~n', [N]), 106 | portray_vertices(G, -1, Max), 107 | portray_edges(G, Max), 108 | format(graph, '};~2n', [])). 109 | 110 | graph_numbervars([], N, N). 111 | graph_numbervars([vertex(_,As,_,_)|Rest], N0, N) :- 112 | atoms_numbervars(As, N0, N1), 113 | graph_numbervars(Rest, N1, N). 114 | 115 | atoms_numbervars([], N, N). 116 | atoms_numbervars([A|As], N0, N) :- 117 | atom_numbervars(A, N0, N1), 118 | atoms_numbervars(As, N1, N). 119 | 120 | atom_numbervars(neg(_, _, Vars), N0, N) :- 121 | numbervars(Vars, N0, N). 122 | atom_numbervars(pos(_, _, Vars), N0, N) :- 123 | numbervars(Vars, N0, N). 124 | atom_numbervars(neg(_, _, _, _, Vars), N0, N) :- 125 | numbervars(Vars, N0, N). 126 | atom_numbervars(pos(_, _, _, _, Vars), N0, N) :- 127 | numbervars(Vars, N0, N). 128 | 129 | portray_vertices([], Max, Max). 130 | portray_vertices([vertex(N,As,FVs,_Ps)|Rest], Max0, Max) :- 131 | format(graph, '~w/{$', [N]), 132 | portray_fvs(FVs), 133 | write(graph, '\\ '), 134 | portray_atoms(As), 135 | format(graph, '$};~n', []), 136 | Max1 is max(Max0,N), 137 | portray_vertices(Rest, Max1, Max). 138 | 139 | portray_edges([], _). 140 | portray_edges([vertex(N,_As,_FVs,Ps)|Rest], Max0) :- 141 | portray_links(Ps, N, Max0, Max), 142 | portray_edges(Rest, Max). 143 | 144 | 145 | portray_links([], _, Max, Max). 146 | portray_links([P|Ps], N, Max0, Max) :- 147 | portray_link(P, N, Max0, Max1), 148 | portray_links(Ps, N, Max1, Max). 149 | 150 | portray_link(univ(A,P), N, Max0, Max) :- 151 | Max is Max0 + 1, 152 | format(graph, '~w/{$\\!~@\\!$} [shape=circle,draw];~n', [Max,portray_var(A)]), 153 | format(graph, '~w <- ~w;~n~w <- ~w;~n', [N,Max,Max,P]). 154 | portray_link(par(P,Q), N, Max0, Max) :- 155 | Max is Max0 + 1, 156 | format(graph, '~w/{$\\!\\parr\\!$} [shape=circle,draw];~n', [Max]), 157 | format(graph, '~w <- ~w;~n', [N,Max]), 158 | ( 159 | P =:= Q 160 | -> 161 | format(graph, '~w <-[bend left] ~w;~n~w <-[bend right] ~w;~n', [Max,P,Max,Q]) 162 | ; 163 | format(graph, '~w <- ~w;~n~w <- ~w;~n', [Max,P,Max,Q]) 164 | ). 165 | 166 | portray_atoms([]) :- 167 | write(graph, '\\emptyset'). 168 | portray_atoms([A|As]) :- 169 | write(graph, '\\{'), 170 | portray_atoms1(As, A). 171 | 172 | portray_atoms1([], A) :- 173 | portray_atom(A), 174 | write(graph, '\\}'). 175 | portray_atoms1([B|Bs], A) :- 176 | portray_atom(A), 177 | write(graph, ','), 178 | portray_atoms1(Bs, B). 179 | 180 | portray_atom(neg(A,_,Vars)) :- 181 | format(graph, '\\overset{-}{~@}',[portray_atom1(Vars, A)]). 182 | portray_atom(pos(A,_,Vars)) :- 183 | format(graph, '\\overset{+}{~@}',[portray_atom1(Vars, A)]). 184 | portray_atom(neg(A,_,_,_,Vars)) :- 185 | format(graph, '\\overset{-}{~@}',[portray_atom1(Vars, A)]). 186 | portray_atom(pos(A,_,_,_,Vars)) :- 187 | format(graph, '\\overset{+}{~@}',[portray_atom1(Vars, A)]). 188 | 189 | portray_fvs([]). 190 | portray_fvs([V|Vs]) :- 191 | ( 192 | var(V) 193 | -> 194 | true 195 | ; 196 | V = var(N) 197 | -> 198 | portray_var(N) 199 | ; 200 | true 201 | ), 202 | portray_fvs(Vs). 203 | 204 | portray_atom1([], Atom) :- 205 | latex_it_atom(Atom). 206 | portray_atom1([V|Vs], Pred) :- 207 | latex_it_atom(Pred), 208 | format(graph, '(~@)', [portray_vars(Vs,V)]). 209 | 210 | portray_vars([], V) :- 211 | portray_var1(V). 212 | portray_vars([V|Vs], W) :- 213 | portray_var1(W), 214 | write(graph, ','), 215 | portray_vars(Vs, V). 216 | 217 | portray_var1(Int) :- 218 | integer(Int), 219 | !, 220 | print(graph, Int). 221 | portray_var1(var(N)) :- 222 | !, 223 | portray_var(N). 224 | portray_var1('$VAR'(N)) :- 225 | !, 226 | print(graph, '$VAR'(N)). 227 | portray_var1(Term) :- 228 | Term =.. [F0|Args], 229 | atomic_list_concat(List, '_', F0), 230 | atomic_list_concat(List, '\\_', F), 231 | format(graph, '\\textit{~w}', [F]), 232 | latex_arguments(Args). 233 | 234 | portray_var(N) :- 235 | VI is N mod 5, 236 | VN is N//5, 237 | var_name(VN), 238 | format(graph, '_{~w}', [VI]). 239 | 240 | var_name(0) :- 241 | write(graph, x). 242 | var_name(1) :- 243 | write(graph, y). 244 | var_name(2) :- 245 | write(graph, z). 246 | var_name(3) :- 247 | write(graph, v). 248 | var_name(4) :- 249 | write(graph, w). 250 | 251 | % = latex_arguments(+ListOfArguments) 252 | % 253 | % write a list of arguments to a predicate ie. (t_1, t_2, t3) sending 254 | % each t_i to print and outputing nothing for a proposition (ie. the 255 | % empty list of arguments. 256 | 257 | latex_arguments([]). 258 | latex_arguments([A|As]) :- 259 | write(graph, '('), 260 | latex_arguments(As, A), 261 | write(graph, ')'). 262 | 263 | latex_arguments([], A) :- 264 | ( 265 | var(A) 266 | -> 267 | format(graph, '\\_', []) 268 | ; 269 | format(graph, '~@', [portray_var1(A)]) 270 | ). 271 | latex_arguments([A|As], A0) :- 272 | ( 273 | var(A0) 274 | -> 275 | format(graph, '\\_, ', []) 276 | ; 277 | format(graph, '~@, ', [portray_var1(A0)]) 278 | ), 279 | latex_arguments(As, A). 280 | 281 | latex_it_atom(A0) :- 282 | /* take care of Prolog atoms containing '_' */ 283 | atomic_list_concat(List, '_', A0), 284 | atomic_list_concat(List, '\\_', A), 285 | format(graph, '\\textit{~w}', [A]). 286 | -------------------------------------------------------------------------------- /proof_generation_nd.pl: -------------------------------------------------------------------------------- 1 | 2 | % Direct ND generation 3 | 4 | create_pos_proof(N-A, L0, L, Proof) :- 5 | create_pos_proof(A, N, L0, L, Proof). 6 | 7 | % = create_pos_proof(+PositiveFormula, +NodeNumber, +/-AtomsDL, -Proof) 8 | 9 | create_pos_proof(at(A,C,N,Vars), M, [pos(A,C,N,_,Vars)|L], L, rule(ax,[M-at(A,C,N,Vars)], M-at(A,_C,_N,Vars), [])) :- 10 | !. 11 | create_pos_proof(exists(X,N-A), N, L0, L, rule(er, Gamma, N-exists(Y,N-A3), [ProofA])) :- 12 | !, 13 | /* rename to make sure bound variable isn't unified */ 14 | rename_bound_variables(A, A2), 15 | rename_bound_variable(exists(X,N-A2), X, Y, exists(Y,N-A3)), 16 | create_pos_proof(A, N, L0, L, ProofA), 17 | ProofA = rule(_, Gamma, N-A2, _). 18 | create_pos_proof(p(N-A,N-B), N, L0, L, rule(pr, GD, N-p(N-A2,N-B2), [P1,P2])) :- 19 | !, 20 | create_pos_proof(A, N, L0, L1, P1), 21 | create_pos_proof(B, N, L1, L, P2), 22 | P1 = rule(_, Gamma, N-A2, _), 23 | P2 = rule(_, Delta, N-B2, _), 24 | append(Gamma, Delta, GD). 25 | % complex (negative) subformula 26 | create_pos_proof(F, N, L, L, rule(ax, [N-F], N-F, [])). 27 | 28 | % = create_neg_proof(+NumberedNegativeFormula, +/-AtomsDL, +Goal, -Proof) 29 | 30 | create_neg_proof(N-A, L0, L, Neg, Proof) :- 31 | create_neg_proof(A, N, L0, L, Neg, Proof). 32 | 33 | % = create_neg_proof(+NegativeFormula, +NodeNumber, +/-AtomsDL, +Goal, -Proof) 34 | 35 | create_neg_proof(at(A,C,N,Vars), M, [neg(A,C,N,_,Vars)|L], L, at(A,C,N,Vars), rule(ax, [M-at(A,_C,_N,Vars)], M-at(A,C,N,Vars), [])) :- 36 | !. 37 | create_neg_proof(impl(N-A,N-B), N, L0, L, Neg, rule(il, GD, N-Neg, [ProofA,ProofB])) :- 38 | !, 39 | create_pos_proof(A, N, L0, L1, ProofA), 40 | create_neg_proof(B, N, L1, L, Neg, ProofB), 41 | rename_bound_variables(B, B2), 42 | ProofA = rule(_, Gamma, N-A3, _), 43 | ProofB = rule(_, Delta, _, _), 44 | select_formula(B2, N, Delta, Delta_B), 45 | append(Gamma, [N-impl(N-A3,N-B2)|Delta_B], GD). 46 | create_neg_proof(forall(X,N-A), N, L0, L, Neg, rule(fl, GammaP, C, [ProofA])) :- 47 | !, 48 | rename_bound_variables(A, A2), 49 | create_neg_proof(A, N, L0, L, Neg, ProofA), 50 | ProofA = rule(_, Gamma, C, _), 51 | /* rename to make sure bound variables aren't unified */ 52 | replace_formula(A2, N, N-forall(Y,N-A3), Gamma, GammaP), 53 | rename_bound_variable(forall(X,N-A2), X, Y, forall(Y,N-A3)). 54 | % complex (positive) subformula 55 | create_neg_proof(F, N, L, L, _, rule(ax, [N-F], N-F, [])). 56 | 57 | 58 | % = combine_univ(+Proof1, +Proof2, +Node1, +Node2, +VariableNumber, -Proof) 59 | % 60 | % combine Proof1 and Proof2 into Proof using a unary par contraction (with eigenvariable 61 | % VariableNumber) which links Node1 to Node2 62 | 63 | % = left rule for existential quantifier 64 | combine_univ(P1, P2, N0, N1, V, N1-Rule) :- 65 | P1 = rule(_, Gamma, N0-exists(var(V),N1-A), _), 66 | P2 = rule(_, Delta0, C, _), 67 | !, 68 | append(Delta1, [_-A|Delta2], Delta0), 69 | append(Delta1, [N1-exists(var(V),N1-A)|Delta2], Delta), 70 | append(Delta1, Gamma, GD1), 71 | append(GD1, Delta2, GD), 72 | /* try to create a cut-free proof */ 73 | try_cut_elimination_left(P1, rule(el, Delta, C, [P2]), GD, Delta1, Delta2, C, N0-exists(var(V),N1-A), N0-exists(var(V),N1-A), Rule). 74 | 75 | % = right rule for universal quantifier 76 | combine_univ(P1, P2, N0, N1, V, N1-Rule) :- 77 | P2 = rule(_, Gamma, N1-A, _), 78 | P1 = rule(_, Delta, C, _), 79 | append(Delta0, [_-forall(var(V),N1-A)|Delta1], Delta), 80 | append(Delta0, Gamma, GD0), 81 | append(GD0, Delta1, GD), 82 | /* try to create a cut-free proof */ 83 | try_cut_elimination_right(rule(fr,Gamma,N1-forall(var(V),N1-A), [P2]), P1, GD, C, Gamma, N0-forall(var(V),N1-A), N0-forall(var(V),N1-A), Rule). 84 | 85 | % = combine(+Proof1, +Proof2, +Node1, +Node2, -Proof) 86 | % 87 | % combine Proof1 and Proof2 into Proof using a binary par contraction which links Node1 88 | % to Node2 (since this is a valid contraction, the two edges leaving Node1 must arrive 89 | % in the same node Node2) 90 | 91 | % = left rule for product 92 | combine(P1, P2, N0, N1, N1-Rule) :- 93 | P1 = rule(_, Gamma, N0-p(N1-A, N1-B), _), 94 | P2 = rule(_, Delta0, C, _), 95 | !, 96 | select_formula(B, N1, Delta0, Delta1), 97 | select_formula(A, N1, Delta1, Delta), 98 | replace_formula(A, N1, N1-p(N1-A,N1-B), Delta1, Delta2), 99 | append(Delta3, [N1-p(N1-A,N1-B)|Delta4], Delta2), 100 | append(Gamma, Delta, GD), 101 | /* try to create a cut-free proof */ 102 | try_cut_elimination_left(P1, rule(pl, Delta2, C, [P2]), GD, Delta3, Delta4, C, N0-p(N1-A, N1-B), N0-p(N1-A, N1-B), Rule). 103 | 104 | % = right rule for implication 105 | combine(P1, P2, N0, N1, N1-Rule) :- 106 | P1 = rule(_, Gamma, A, _), 107 | P2 = rule(_, Delta0, N1-D, _), 108 | append(Gamma0, [N0-impl(N1-C,N1-D)|Gamma1], Gamma), 109 | select_formula(C, N1, Delta0, Delta), 110 | append(Gamma0, Delta, GD0), 111 | append(GD0, Gamma1, GD), 112 | /* try to create a cut-free proof */ 113 | try_cut_elimination_right(rule(ir, Delta, N0-impl(N1-C,N1-D), [P2]), P1, GD, A, Delta, N0-impl(N1-C,N1-D), N0-impl(N1-C,N1-D), Rule). 114 | -------------------------------------------------------------------------------- /replace.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | 3 | :- module(replace, [replace_proofs_labels/4, 4 | replace_proof_labels/4, 5 | replace_formula/5, 6 | replace_graph/6, 7 | rename_bound_variable/4, 8 | rename_bound_variables/2]). 9 | 10 | :- use_module(ordset, [ord_key_insert/4, ord_key_member/3]). 11 | 12 | % ======================================= 13 | % = Auxiliary replacement predicates = 14 | % ======================================= 15 | 16 | /* I don't believe it's necessary to do replacements inside the subproofs Rs here */ 17 | 18 | replace_proofs_labels([], _, _, []). 19 | replace_proofs_labels([R0|Rs0], X, Y, [R|Rs]) :- 20 | replace_proof_labels(R0, X, Y, R), 21 | replace_proofs_labels(Rs0, X, Y, Rs). 22 | 23 | replace_proof_labels(N0-R0, X, Y, N-R) :- 24 | replace_item(N0, X, Y, N), 25 | replace_proof_labels(R0, X, Y, R). 26 | replace_proof_labels(rule(N, As0, F0, Rs), X, Y, rule(N, As, F, Rs)) :- 27 | replace_antecedent_labels(As0, X, Y, As), 28 | replace_formula_labels(F0, X, Y, F). 29 | 30 | replace_antecedent_labels([], _, _, []). 31 | replace_antecedent_labels([A|As], X, Y, [B|Bs]) :- 32 | replace_formula_labels(A, X, Y, B), 33 | replace_antecedent_labels(As, X, Y, Bs). 34 | 35 | replace_formula_labels(N0-F0, X, Y, N-F) :- 36 | replace_item(N0, X, Y, N), 37 | replace_formula_labels(F0, X, Y, F). 38 | replace_formula_labels(at(A,B,C,D), _, _, at(A,B,C,D)). 39 | replace_formula_labels(impl(A0,B0), X, Y, impl(A,B)) :- 40 | replace_formula_labels(A0, X, Y, A), 41 | replace_formula_labels(B0, X, Y, B). 42 | replace_formula_labels(p(A0,B0), X, Y, p(A,B)) :- 43 | replace_formula_labels(A0, X, Y, A), 44 | replace_formula_labels(B0, X, Y, B). 45 | replace_formula_labels(forall(V,A0), X, Y, forall(V,A)) :- 46 | replace_formula_labels(A0, X, Y, A). 47 | replace_formula_labels(exists(V,A0), X, Y, exists(V,A)) :- 48 | replace_formula_labels(A0, X, Y, A). 49 | 50 | % = replace(+InFormula, +Index, ?IndexedFormula, +InList, ?OutList) 51 | % 52 | % replaces Index-Formula in InList by IndexedFormula in OutList, 53 | % using forced-choice determinism 54 | 55 | replace_formula(F0, N, F, L0, L) :- 56 | select(N-F0, L0, F, L), 57 | !. 58 | 59 | %= replace_graph(+InGraph, +InPars, +InNodeNum, ?OutNodeNum, -OutGraph, OutPars) 60 | 61 | replace_graph(Graph0, Par0, N0, N, Graph, Par) :- 62 | replace(Graph0, N0, N, Graph), 63 | replace_pars(Par0, N0, N, Par). 64 | 65 | % = replace(+InGraph,+InNodeNum,?OutNodeNum,-OutGraph) 66 | % 67 | % renumbers InNodeNum for OutNodeNum throughout Graph. 68 | 69 | replace([], _, _, []). 70 | replace([vertex(N,As,FVs,Ps0)|Rest0], N0, N1, [vertex(N,As,FVs,Ps)|Rest]) :- 71 | replace_pars(Ps0, N0, N1, Ps), 72 | replace(Rest0, N0, N1, Rest). 73 | 74 | replace_pars([], _, _, []). 75 | replace_pars([P0|Ps0], N0, N1, [P|Ps]) :- 76 | replace_par(P0, N0, N1, P), 77 | replace_pars(Ps0, N0, N1, Ps). 78 | 79 | replace_par(par(X,Y), N0, N1, par(V,W)) :- 80 | replace_item(X, N0, N1, V), 81 | replace_item(Y, N0, N1, W). 82 | replace_par(univ(M,X), N0, N1, univ(M,Y)) :- 83 | replace_item(X, N0, N1, Y). 84 | 85 | replace_item(X, N0, N1, Y) :- 86 | ( 87 | X = N0 88 | -> 89 | Y = N1 90 | ; 91 | Y = X 92 | ). 93 | 94 | 95 | % = rename_bound_variable(+LabeledFormulaIn, +InVariable, ?OutVariable, ?LabeldFormulaOut) 96 | % 97 | % true if LabeledFormulaOut is identical to LabeledFormulaIn except that all bound 98 | % occurrences of InVariable have been renamed to OutVariable. 99 | 100 | rename_bound_variable(N-F0, X, Y, N-F) :- 101 | rename_bound_variable(F0, X, Y, F). 102 | rename_bound_variable(at(A,C,N,Vars0), X, Y, at(A,C,N,Vars)) :- 103 | rename_bound_var_list(Vars0, X, Y, Vars). 104 | rename_bound_variable(forall(Z,A0), X, Y, forall(V,A)) :- 105 | rename_bound_var(Z, X, Y, V), 106 | rename_bound_variable(A0, X, Y, A). 107 | rename_bound_variable(exists(Z,A0), X, Y, exists(V,A)) :- 108 | rename_bound_var(Z, X, Y, V), 109 | rename_bound_variable(A0, X, Y, A). 110 | rename_bound_variable(impl(A0,B0), X, Y, impl(A,B)) :- 111 | rename_bound_variable(A0, X, Y, A), 112 | rename_bound_variable(B0, X, Y, B). 113 | rename_bound_variable(p(A0,B0), X, Y, p(A,B)) :- 114 | rename_bound_variable(A0, X, Y, A), 115 | rename_bound_variable(B0, X, Y, B). 116 | 117 | 118 | rename_bound_var_list([], _, _, []). 119 | rename_bound_var_list([V|Vs], X, Y, [W|Ws]) :- 120 | rename_bound_var(V, X, Y, W), 121 | rename_bound_var_list(Vs, X, Y, Ws). 122 | 123 | rename_bound_var(V, X, Y, W) :- 124 | ( 125 | V == X 126 | -> 127 | W = Y 128 | ; 129 | compound(V), 130 | V =.. [F|As0], 131 | F \= '$VAR' 132 | -> 133 | rename_bound_var_list(As0, X, Y, As), 134 | W =.. [F|As] 135 | ; 136 | W = V 137 | ). 138 | 139 | 140 | rename_bound_variables(F0, F) :- 141 | rename_bound_variables(F0, [], F). 142 | rename_bound_variables(N-F0, Map, N-F) :- 143 | rename_bound_variables(F0, Map, F). 144 | rename_bound_variables(at(A,C,N,Vars0), Map, at(A,C,N,Vars)) :- 145 | rename_bound_var_list(Vars0, Map, Vars). 146 | rename_bound_variables(forall(Z,A0), Map0, forall(V,A)) :- 147 | ord_key_insert(Map0, Z, V, Map), 148 | rename_bound_variables(A0, Map, A). 149 | rename_bound_variables(exists(Z,A0), Map0, exists(V,A)) :- 150 | ord_key_insert(Map0, Z, V, Map), 151 | rename_bound_variables(A0, Map, A). 152 | rename_bound_variables(impl(A0,B0), Map, impl(A,B)) :- 153 | rename_bound_variables(A0, Map, A), 154 | rename_bound_variables(B0, Map, B). 155 | rename_bound_variables(p(A0,B0), Map, p(A,B)) :- 156 | rename_bound_variables(A0, Map, A), 157 | rename_bound_variables(B0, Map, B). 158 | 159 | rename_bound_var_list([], _, []). 160 | rename_bound_var_list([V|Vs], Map, [W|Ws]) :- 161 | rename_bound_var(V, Map, W), 162 | rename_bound_var_list(Vs, Map, Ws). 163 | 164 | rename_bound_var(V, Map, W) :- 165 | ( 166 | ord_key_member(V, Map, W) 167 | -> 168 | true 169 | ; 170 | W = V 171 | ). 172 | -------------------------------------------------------------------------------- /sem_utils.pl: -------------------------------------------------------------------------------- 1 | % -*- Mode: Prolog -*- 2 | 3 | :- module(sem_utils, [reduce_sem/2, 4 | substitute_sem/3, 5 | replace_sem/4, 6 | free_var_indices/2, 7 | freeze/2, 8 | melt/2, 9 | replace_sem/4, 10 | melt_bound_variables/2]). 11 | 12 | % = 13 | 14 | :- use_module(ordset, [ord_intersect/3, 15 | ord_insert/3, 16 | ord_delete/3, 17 | ord_subset/2, 18 | ord_subtract/3]). 19 | :- use_module(tree234, [btree_get/3, 20 | btree_insert/4, 21 | btree_put/4]). 22 | :- use_module(lexicon, [macro_expand/2]). 23 | 24 | 25 | reduce_quine(active). 26 | 27 | reduce_eta(active). 28 | 29 | % basic types 30 | 31 | e_type(e). 32 | t_type(t). 33 | s_type(s). 34 | 35 | semantic_set_type(E, _T, E). 36 | % semantic_set_type(E, T, E->T). 37 | 38 | 39 | % reduce_sem(+LambdaTerm, -BetaEtaReducedLambdaTerm) 40 | % 41 | % true if BetaEtaReducedLambdaTerm is the beta-eta normal form of 42 | % Lambda Term. Works using a simply repeat loop reducing one redex 43 | % at each step. 44 | 45 | reduce_sem(Term0, Term) :- 46 | get_max_variable_number(Term0, Max), 47 | reduce_sem(Term0, Term1, Max, _), 48 | relabel_sem_vars(Term1, Term). 49 | 50 | reduce_sem(Term0, Term, Max0, Max) :- 51 | reduce_sem1(Term0, Term1, Max0, Max1), 52 | !, 53 | reduce_sem(Term1, Term, Max1, Max). 54 | 55 | reduce_sem(Term, Term, Max, Max). 56 | 57 | 58 | % reduce_sem1(+Redex, -Contractum). 59 | % 60 | % true if Redex reduces to Contractum in a single beta or eta 61 | % reduction. 62 | 63 | reduce_sem1(appl(lambda(X0,T0),Y), T, Max0, Max) :- 64 | alpha_conversion(lambda(X0,T0),lambda(X,T1), Max0, Max), 65 | replace_sem(T1, X, Y, T). 66 | reduce_sem1(lambda(X,appl(F,X)), F, Max, Max) :- 67 | reduce_eta(active), 68 | \+ subterm(F, X). 69 | reduce_sem1(pi1(pair(T,_)), T, Max, Max). 70 | reduce_sem1(pi2(pair(_,T)), T, Max, Max). 71 | reduce_sem1(pair(pi1(T),pi2(T)), T, Max, Max) :- 72 | reduce_eta(active). 73 | 74 | % = Quine's reductions 75 | 76 | reduce_sem1(bool(true,&,X), X, Max, Max) :- 77 | reduce_quine(active). 78 | reduce_sem1(bool(X,&,true), X, Max, Max) :- 79 | reduce_quine(active). 80 | reduce_sem1(bool(false,&,_), false, Max, Max) :- 81 | reduce_quine(active). 82 | reduce_sem1(bool(_,&,false), false, Max, Max) :- 83 | reduce_quine(active). 84 | 85 | reduce_sem1(bool(true,\/,_), true, Max, Max) :- 86 | reduce_quine(active). 87 | reduce_sem1(bool(_,\/,true), true, Max, Max) :- 88 | reduce_quine(active). 89 | reduce_sem1(bool(false,\/,X), X, Max, Max) :- 90 | reduce_quine(active). 91 | reduce_sem1(bool(X,\/,false), X, Max, Max) :- 92 | reduce_quine(active). 93 | 94 | reduce_sem1(bool(true,->,X), X, Max, Max) :- 95 | reduce_quine(active). 96 | reduce_sem1(bool(_,->,true), true, Max, Max) :- 97 | reduce_quine(active). 98 | reduce_sem1(bool(false,->,_), true, Max, Max) :- 99 | reduce_quine(active). 100 | reduce_sem1(bool(X,->,false), not(X), Max, Max) :- 101 | reduce_quine(active). 102 | 103 | % = recursive case 104 | 105 | reduce_sem1(T, U, Max0, Max) :- 106 | T =.. [F|Ts], 107 | reduce_list(Ts, Us, Max0, Max), 108 | U =.. [F|Us]. 109 | 110 | reduce_list([T|Ts], [U|Ts], Max0, Max) :- 111 | reduce_sem1(T, U, Max0, Max). 112 | reduce_list([T|Ts], [T|Us], Max0, Max) :- 113 | reduce_list(Ts, Us, Max0, Max). 114 | 115 | % subterm(Term, SubTerm) 116 | % 117 | % true if Term contains SubTerm as a subterm. 118 | 119 | subterm(X, X) :- 120 | !. 121 | subterm(X, Y) :- 122 | functor(X, _, N), 123 | subterm(N, X, Y). 124 | 125 | subterm(N0, X, Y) :- 126 | N0 > 0, 127 | arg(N0, X, A), 128 | subterm(A, Y). 129 | 130 | subterm(N0, X, Y) :- 131 | N0 > 0, 132 | N is N0-1, 133 | subterm(N, X, Y). 134 | 135 | % = alpha_conversion(+InTerm, -OutTerm) 136 | 137 | alpha_conversion(Term0, Term, Max0, Max) :- 138 | melt_bound_variables(Term0, Term), 139 | Max1 is Max0 + 1, 140 | numbervars(Term, Max1, Max). 141 | 142 | % = replace_sem(InTerm, Term1, Term2, OutTerm, Max) 143 | % 144 | % true if OutTerm is InTerm with all occurrences of Term1 replaced 145 | % by occurrences of Term2. 146 | 147 | replace_sem(X0, X, Y0, Y) :- 148 | X0 == X, 149 | !, 150 | Y = Y0. 151 | replace_sem(X, _, _, X) :- 152 | var(X), 153 | !. 154 | replace_sem(U, X, Y, V) :- 155 | functor(U, F, N), 156 | functor(V, F, N), 157 | replace_sem(N, U, X, Y, V). 158 | 159 | replace_sem(0, _, _, _, _) :- 160 | !. 161 | replace_sem(N0, U, X, Y, V) :- 162 | N0 > 0, 163 | N is N0-1, 164 | arg(N0, U, A), 165 | replace_sem(A, X, Y, B), 166 | arg(N0, V, B), 167 | replace_sem(N, U, X, Y, V). 168 | 169 | % = substitute_sem(+ListOfSubstitutions, +InTerm, -OutTerm). 170 | 171 | substitute_sem(L, T0, T) :- 172 | max_key_list(L, 0, Max0), 173 | get_max_variable_number(T0, Max1), 174 | Max2 is max(Max0+1,Max1+1), 175 | numbervars(T0, Max2, Max), 176 | substitute_sem(L, T0, T, Max, _). 177 | 178 | substitute_sem([], T, T, N, N). 179 | substitute_sem([X-U|Rest], T0, T, N0, N) :- 180 | numbervars(U, N0, N1), 181 | replace_sem(T0, '$VAR'(X), U, T1), 182 | substitute_sem(Rest, T1, T, N1, N). 183 | 184 | max_key_list([], M, M). 185 | max_key_list([K-_|Ss], M0, M) :- 186 | ( 187 | K > M0 188 | -> 189 | max_key_list(Ss, K, M) 190 | ; 191 | max_key_list(Ss, M0, M) 192 | ). 193 | 194 | % = free_var_indices(+Term, -ListOfVariableIndices) 195 | % 196 | % given a Term representing a lambda term return all 197 | % indices of variables occurring freely in this lambda term. 198 | 199 | free_var_indices('$VAR'(N), [N]) :- 200 | !. 201 | free_var_indices(A, []) :- 202 | atomic(A), 203 | !. 204 | free_var_indices(lambda('$VAR'(X),Y), F) :- 205 | !, 206 | free_var_indices(Y, F0), 207 | ord_delete(F0, X, F). 208 | free_var_indices(quant(_,'$VAR'(X),Y), F) :- 209 | !, 210 | free_var_indices(Y, F0), 211 | ord_delete(F0, X, F). 212 | free_var_indices(T, F) :- 213 | T =.. [Fun|Args], 214 | free_var_indices_list([Fun|Args], [], F). 215 | 216 | free_var_indices_list([], F, F). 217 | free_var_indices_list([A|As], F0, F) :- 218 | free_var_indices(A, V), 219 | ord_union(F0, V, F1), 220 | free_var_indices_list(As, F1, F). 221 | 222 | bound_variables(Var, []) :- 223 | var(Var), 224 | !. 225 | bound_variables(lambda(X, Y), BVs) :- 226 | !, 227 | ( 228 | var(X) 229 | -> 230 | /* already molten */ 231 | bound_variables(Y, BVs) 232 | ; 233 | X = '$VAR'(N), 234 | bound_variables(Y, BVs0), 235 | ord_insert(BVs0, N, BVs) 236 | ). 237 | bound_variables('$VAR'(_), []) :- 238 | !. 239 | bound_variables(X, []) :- 240 | atomic(X), 241 | !. 242 | bound_variables(Term, BVs) :- 243 | Term =.. List, 244 | bound_variables_list(List, BVs). 245 | 246 | bound_variables_list([], []). 247 | bound_variables_list([V|Vs], Bs) :- 248 | bound_variables(V, Bs0), 249 | bound_variables_list(Vs, Bs1), 250 | ord_union(Bs0, Bs1, Bs). 251 | 252 | % = relabel_sem_vars(T0, T) 253 | % 254 | % rename the variables in term T0 in such a way that all variables are in 255 | % the range '$VAR'(0) to '$VAR'(N) for the smallest N possible. 256 | 257 | relabel_sem_vars(T0, T) :- 258 | relabel_sem_vars(T0, T, 0, _, empty, _). 259 | 260 | % relabel_sem(T0, T, M0, M) 261 | 262 | relabel_sem_vars('$VAR'(I), '$VAR'(J), N0, N, M0, M) :- 263 | !, 264 | ( 265 | btree_get(M0, I, J) 266 | -> 267 | M = M0, 268 | N = N0 269 | ; 270 | J = N0, 271 | N is N0 +1, 272 | btree_insert(M0, I, J, M) 273 | ). 274 | relabel_sem_vars(Term0, Term, N0, N, M0, M) :- 275 | functor(Term0, F, A), 276 | functor(Term, F, A), 277 | relabel_sem_vars_args(1, A, Term0, Term, N0, N, M0, M). 278 | 279 | relabel_sem_vars_args(A0, A, Term0, Term, N0, N, M0, M) :- 280 | ( 281 | A0 > A 282 | -> 283 | N = N0, 284 | M = M0 285 | ; 286 | arg(A0, Term0, Arg0), 287 | arg(A0, Term, Arg), 288 | relabel_sem_vars(Arg0, Arg, N0, N1, M0, M1), 289 | A1 is A0 + 1, 290 | relabel_sem_vars_args(A1, A, Term0, Term, N1, N, M1, M) 291 | ). 292 | 293 | create_tree([], Tree, Tree). 294 | create_tree([I|Vs], Tree0, Tree) :- 295 | btree_put(Tree0, I, _, Tree1), 296 | create_tree(Vs, Tree1, Tree). 297 | 298 | % = melt_bound_variables(+Term0, -Term) 299 | % 300 | % true if Term is identical to Term0 but with all occurrences of 301 | % bound variables (because of numbervars, all variables are of the form 302 | % '$VAR'(N)') replaced by Prolog variables. 303 | 304 | melt_bound_variables(Term0, Term) :- 305 | bound_variables(Term0, List), 306 | create_tree(List, empty, Tree), 307 | melt_bound_variables(Term0, Term, Tree). 308 | 309 | melt_bound_variables(X, X, _Tree) :- 310 | var(X), 311 | !. 312 | melt_bound_variables('$VAR'(I), Var, Tree) :- 313 | !, 314 | ( 315 | btree_get(Tree, I, Var) 316 | -> 317 | true 318 | ; 319 | Var = '$VAR'(I) 320 | ). 321 | melt_bound_variables(Term0, Term, Tree) :- 322 | functor(Term0, F, A), 323 | functor(Term, F, A), 324 | melt_bound_variables_args(1, A, Term0, Term, Tree). 325 | 326 | melt_bound_variables_args(A0, A, Term0, Term, Tree) :- 327 | ( 328 | A0 > A 329 | -> 330 | true 331 | ; 332 | arg(A0, Term0, Arg0), 333 | arg(A0, Term, Arg), 334 | melt_bound_variables(Arg0, Arg, Tree), 335 | A1 is A0 + 1, 336 | melt_bound_variables_args(A1, A, Term0, Term, Tree) 337 | ). 338 | 339 | % = get_variable_numbers(+LambdaTerm, -SetOfIntegers) 340 | % 341 | % true if SetOfIntegers contains all variable number which 342 | % are the result of a call to numbervars/3 (that is to say, 343 | % the set of all N which occur as a subterm '$VAR'(N)) 344 | 345 | get_variable_numbers(Term, Set) :- 346 | get_variable_numbers(Term, List, []), 347 | sort(List, Set). 348 | 349 | get_variable_numbers(Var, L, L) :- 350 | var(Var), 351 | !. 352 | get_variable_numbers('$VAR'(N), [N|L], L) :- 353 | !. 354 | get_variable_numbers(Term, L0, L) :- 355 | functor(Term, _, A), 356 | get_variable_numbers_args(1, A, Term, L0, L). 357 | 358 | get_variable_numbers_args(A0, A, Term, L0, L) :- 359 | ( 360 | A0 > A 361 | -> 362 | L = L0 363 | ; 364 | arg(A0, Term, Arg), 365 | get_variable_numbers(Arg, L0, L1), 366 | A1 is A0 +1, 367 | get_variable_numbers_args(A1, A, Term, L1, L) 368 | ). 369 | 370 | % = get_max_variable_number(+LambdaTerm, ?MaxVar) 371 | % 372 | % true if MaxVar is the largest number N which 373 | % occurs as a subterm '$VAR'(N)) of LambdaTerm 374 | % That is to say, if LambdaTerm contains variables 375 | % and MaxVar1 is MaxVar + 1, then the call 376 | % 377 | % numbervars(LambdaTerm, MaxVar1, NewMaxVar) 378 | % 379 | % is guaranteed to be sound (in the sense that 380 | % it does not accidentally unifies distinct 381 | % variables. 382 | % 383 | % If LambdaTerm contains no occurrences of a 384 | % subterm '$VAR'(N) then MaxVar is defined as 385 | % -1. 386 | 387 | get_max_variable_number(Term, Max) :- 388 | get_max_variable_number(Term, -1, Max). 389 | 390 | get_max_variable_number(Var, Max, Max) :- 391 | var(Var), 392 | !. 393 | get_max_variable_number('$VAR'(N), Max0, Max) :- 394 | !, 395 | Max is max(N,Max0). 396 | get_max_variable_number(Term, Max0, Max) :- 397 | functor(Term, _, A), 398 | get_max_variable_number_args(1, A, Term, Max0, Max). 399 | 400 | get_max_variable_number_args(A0, A, Term, Max0, Max) :- 401 | ( 402 | A0 > A 403 | -> 404 | Max = Max0 405 | ; 406 | arg(A0, Term, Arg), 407 | get_max_variable_number(Arg, Max0, Max1), 408 | A1 is A0 +1, 409 | get_max_variable_number_args(A1, A, Term, Max1, Max) 410 | ). 411 | 412 | check_type(At, Type, Word, Tr0, Tr) :- 413 | atomic(At), 414 | !, 415 | ( 416 | btree_get(Tr0, At, TA) 417 | -> 418 | Tr0 = Tr, 419 | verify_expected_type(At, Word, Type, TA) 420 | ; 421 | btree_insert(Tr0, At, Type, Tr) 422 | ). 423 | check_type('WORD'(_), _Type, _Word, Tr, Tr) :- 424 | !. 425 | check_type('$VAR'(N), Type, Word, Tr0, Tr) :- 426 | !, 427 | ( 428 | btree_get(Tr0, N, TN) 429 | -> 430 | Tr = Tr0, 431 | verify_expected_type('$VAR'(N), Word, Type, TN) 432 | ; 433 | btree_insert(Tr0, N, Type, Tr) 434 | ). 435 | check_type(lambda('$VAR'(N),T), Type, Word, Tr0, Tr) :- 436 | !, 437 | ( 438 | Type = (V->W) 439 | -> 440 | btree_insert(Tr0, N, V, Tr1), 441 | check_type(T, W, Word, Tr1, Tr) 442 | ; 443 | Tr = Tr0, 444 | format('{Typing Error (~w): expected type(~p)->type(~W) found ~W}~n', [Word,'$VAR'(N),T,[numbervars(true)],Type,[numbervars(true)]]), 445 | format(log, '{Typing Error (~w): expected type(~w)->type(~W) found ~W}~n', [Word,'$VAR'(N),T,[numbervars(true)],Type,[numbervars(true)]]) 446 | ). 447 | check_type(sub(X,_), Type, W, Tr0, Tr) :- 448 | !, 449 | check_type(X, Type, W, Tr0, Tr). 450 | check_type(sup(X,_), Type, W, Tr0, Tr) :- 451 | !, 452 | check_type(X, Type, W, Tr0, Tr). 453 | check_type(num(X), E, W, Tr0, Tr) :- 454 | !, 455 | e_type(E), 456 | check_type(X, E, W, Tr0, Tr). 457 | check_type(complement(X), E, W, Tr0, Tr) :- 458 | !, 459 | e_type(E), 460 | check_type(X, E, W, Tr0, Tr). 461 | check_type(time(X), E, W, Tr0, Tr) :- 462 | !, 463 | verify_e_type(time(X), W, E), 464 | s_type(S), 465 | check_type(X, S, W, Tr0, Tr). 466 | check_type(count(X), E, W, Tr0, Tr) :- 467 | !, 468 | e_type(E), 469 | t_type(T), 470 | check_type(X, E->T, W, Tr0, Tr). 471 | check_type(not(X), T, W, Tr0, Tr) :- 472 | !, 473 | check_type(X, T, W, Tr0, Tr). 474 | check_type(appl(X,Y), W, Word, Tr0, Tr) :- 475 | !, 476 | check_type(X, (V->W), Word, Tr0, Tr1), 477 | check_type(Y, V, Word, Tr1, Tr). 478 | check_type(quant(Q,X), T, Word, Tr0, Tr) :- 479 | e_type(E), 480 | t_type(U), 481 | ( 482 | Q = iota 483 | -> 484 | verify_e_type(quant(Q,X), Word, T), 485 | V = (T -> U) 486 | ; 487 | V = (E -> U) 488 | ), 489 | !, 490 | check_type(X, V, Word, Tr0, Tr). 491 | check_type(quant(Q,V,X), T, Word, Tr0, Tr) :- 492 | !, 493 | e_type(E), 494 | check_type(V, E, Word, Tr0, Tr1), 495 | ( 496 | Q = iota 497 | -> 498 | verify_e_type(quant(Q,V,X), Word, T) 499 | ; 500 | t_type(U), 501 | verify_expected_type(quant(Q,V,X), Word, T, U) 502 | ), 503 | check_type(X, t, Word, Tr1, Tr). 504 | % allow polymorphic booleans 505 | check_type(bool(X,B,Y), T, Word, Tr0, Tr) :- 506 | !, 507 | e_type(E), 508 | t_type(T), 509 | operator_type(B, E, T, U, V), 510 | check_type(X, U, Word, Tr0, Tr1), 511 | check_type(Y, V, Word, Tr1, Tr). 512 | check_type(pair(X,Y), Type, Word, Tr0, Tr) :- 513 | !, 514 | ( 515 | Type = U-V 516 | -> 517 | check_type(X, U, Word, Tr0, Tr1), 518 | check_type(Y, V, Word, Tr1, Tr) 519 | ; 520 | Tr = Tr0, 521 | format('{Typing Error (~w): expected type(~p)->type(~w) found ~w}~n', [Word,pair(X,Y),U-V,Type]), 522 | format(log, '{Typing Error (~w): expected type(~w)->type(~w) found ~w}~n', [Word,pair(X,Y),U-V,Type]) 523 | ). 524 | check_type(fst(X), Type, Word, Tr0, Tr) :- 525 | !, 526 | check_type(X, Type-_, Word, Tr0, Tr). 527 | check_type(snd(X), Type, Word, Tr0, Tr) :- 528 | !, 529 | check_type(X, _-Type, Word, Tr0, Tr). 530 | check_type(pi1(X), Type, Word, Tr0, Tr) :- 531 | !, 532 | check_type(X, Type-_, Word, Tr0, Tr). 533 | check_type(pi2(X), Type, Word, Tr0, Tr) :- 534 | !, 535 | check_type(X, _-Type, Word, Tr0, Tr). 536 | 537 | % unknown term 538 | check_type(Term, Type, Word, Tr, Tr) :- 539 | format('{Typing Error (~w): unknown term ~k of type ~p}~n', [Word,Term,Type]), 540 | format(log, '{Typing Error (~w): unknown term ~k of type ~p}~n', [Word,Term,Type]). 541 | 542 | % = polymorphic 543 | operator_type((=) , _, _, X, X). 544 | operator_type((:=) , _, _, X, X). 545 | operator_type(< , _, _, X, X). 546 | operator_type(> , _, _, X, X). 547 | operator_type(neq , _, _, X, X). 548 | % = DRS 549 | operator_type(overlaps , _, _, X, X). 550 | operator_type(abuts , _, _, X, X). 551 | % = entity and set 552 | operator_type(in, E, T, E, Set) :- 553 | semantic_set_type(E, T, Set). 554 | operator_type(not_in, E, T, E, Set) :- 555 | semantic_set_type(E, T, Set). 556 | % = set and set 557 | operator_type(intersect, E, T, Set, Set) :- 558 | semantic_set_type(E, T, Set). 559 | operator_type(intersection, E, T, Set, Set) :- 560 | semantic_set_type(E, T, Set). 561 | operator_type(setminus, E, T, Set, Set) :- 562 | semantic_set_type(E, T, Set). 563 | operator_type(union, E, T, Set, Set) :- 564 | semantic_set_type(E, T, Set). 565 | operator_type(subset, E, T, Set, Set) :- 566 | semantic_set_type(E, T, Set). 567 | operator_type(subseteq, E, T, Set, Set) :- 568 | semantic_set_type(E, T, Set). 569 | operator_type(nsubseteq, E, T, Set, Set) :- 570 | semantic_set_type(E, T, Set). 571 | operator_type(subsetneq, E, T, Set, Set) :- 572 | semantic_set_type(E, T, Set). 573 | % = default to boolean 574 | operator_type(_, _, T, T, T). 575 | 576 | verify_expected_type(Term, Word, ExpectedType, Type) :- 577 | ( 578 | Type = ExpectedType 579 | -> 580 | true 581 | ; 582 | format('{Typing Error (~w): expected type(~p) = ~w, found ~w}~n', [Word,Term,ExpectedType,Type]), 583 | format(log, '{Typing Error (~w): expected type(~w) = ~w, found ~w}~n', [Word,Term,ExpectedType,Type]) 584 | ). 585 | 586 | verify_e_or_s_type(Term, Word, Type) :- 587 | findall(ES, (e_type(ES) ; s_type(ES)), ESs), 588 | ( 589 | memberchk(Type, ESs) 590 | -> 591 | true 592 | ; 593 | format('{Typing Error (~w): expected either an entity or a state/event type for type(~p) in ~w, found ~w}~n', [Word,Term,Es,Type]), 594 | format('{Typing Error (~w): expected either an entity or a state/event type for type(~p) in ~w, found ~w}~n', [Word,Term,Es,Type]) 595 | ). 596 | 597 | 598 | verify_e_type(Term, Word, Type) :- 599 | findall(E, e_type(E), Es), 600 | ( 601 | memberchk(Type, Es) 602 | -> 603 | true 604 | ; 605 | format('{Typing Error (~w): expected entity for type(~p) in ~w, found ~w}~n', [Word,Term,Es,Type]), 606 | format('{Typing Error (~w): expected entity for type(~p) in ~w, found ~w}~n', [Word,Term,Es,Type]) 607 | ). 608 | 609 | verify_s_type(Term, Word, Type) :- 610 | findall(S, s_type(S), Ss), 611 | ( 612 | memberchk(Type, Ss) 613 | -> 614 | true 615 | ; 616 | format('{Typing Error (~w): expected state type for type(~p) in ~w, found ~w}~n', [Word,Term,Ss,Type]), 617 | format('{Typing Error (~w): expected state type for type(~p) in ~w, found ~w}~n', [Word,Term,Ss,Type]) 618 | ). 619 | 620 | verify_t_type(Term, Word, Type) :- 621 | findall(T, t_type(T), Ts), 622 | ( 623 | memberchk(Type, Ts) 624 | -> 625 | true 626 | ; 627 | format('{Typing Error (~w): expected boolean type for type(~p) in ~w, found ~w}~n', [Word,Term,Ts,Type]), 628 | format('{Typing Error (~w): expected boolean type for type(~p) in ~w, found ~w}~n', [Word,Term,Ts,Type]) 629 | ). 630 | 631 | 632 | 633 | check_var_list([], _, Tr, Tr). 634 | check_var_list([V|Vs], Word, Tr0, Tr) :- 635 | check_var(V, Word, Tr0, Tr1), 636 | check_var_list(Vs, Word, Tr1, Tr). 637 | 638 | check_var(event(V), Word, Tr0, Tr) :- 639 | !, 640 | check_type(V, S, Word, Tr0, Tr), 641 | verify_s_type(V, Word, S). 642 | check_var(variable(V), Word, Tr0, Tr) :- 643 | !, 644 | check_type(V, E, Word, Tr0, Tr), 645 | verify_e_type(V, Word, E). 646 | check_var(set_variable(V), Word, Tr0, Tr) :- 647 | !, 648 | check_type(V, E->T, Word, Tr0, Tr), 649 | verify_e_type(V, Word, E), 650 | verify_t_type(V, Word, T). 651 | check_var(constant(V), Word, Tr0, Tr) :- 652 | !, 653 | check_type(V, E, Word, Tr0, Tr), 654 | verify_e_type(V, Word, E). 655 | check_var(V, Word, Tr0, Tr) :- 656 | check_type(V, E, Word, Tr0, Tr), 657 | verify_e_type(V, Word, E). 658 | 659 | 660 | check_cond_list([], _, Tr, Tr). 661 | check_cond_list([C|Cs], Word, Tr0, Tr) :- 662 | t_type(T), 663 | check_type(C, T, Word, Tr0, Tr1), 664 | check_cond_list(Cs, Word, Tr1, Tr). 665 | 666 | syntactic_to_semantic_type(lit(A), _W, T, Tree) :- 667 | !, 668 | btree_get(Tree, A, T). 669 | syntactic_to_semantic_type(dia(_,A), W, TA, Tree) :- 670 | !, 671 | syntactic_to_semantic_type(A, W, TA, Tree). 672 | syntactic_to_semantic_type(box(_,A), W, TA, Tree) :- 673 | !, 674 | syntactic_to_semantic_type(A, W, TA, Tree). 675 | syntactic_to_semantic_type(dr(_,B,A), W, (TA->TB), Tree) :- 676 | !, 677 | syntactic_to_semantic_type(A, W, TA, Tree), 678 | syntactic_to_semantic_type(B, W, TB, Tree). 679 | syntactic_to_semantic_type(dl(_,A,B), W, (TA->TB), Tree) :- 680 | !, 681 | syntactic_to_semantic_type(A, W, TA, Tree), 682 | syntactic_to_semantic_type(B, W, TB, Tree). 683 | syntactic_to_semantic_type(p(_,A,B), W, TA-TB, Tree) :- 684 | !, 685 | syntactic_to_semantic_type(A, W, TA, Tree), 686 | syntactic_to_semantic_type(B, W, TB, Tree). 687 | syntactic_to_semantic_type(Syn, W, _, _) :- 688 | format('{Formula Error(~w): unknown syntactic formula ~w}~n', [W,Syn]), 689 | format(log, '{Formula Error(~w): unknown syntactic formula ~w}~n', [W,Syn]), 690 | fail. 691 | 692 | % = freeze(+Term, -FrozenTerm) 693 | 694 | freeze(Term0, Term) :- 695 | copy_term(Term0, Term), 696 | numbervars(Term, 1, _). 697 | 698 | % = melt(+Frozen, -Term) 699 | 700 | melt(Term, Molten) :- 701 | melt(Term, Molten, empty, _). 702 | 703 | melt('$VAR'(N), Var, T0, T) :- 704 | integer(N), 705 | !, 706 | ( 707 | btree_get(T0, N, Var) 708 | -> 709 | T = T0 710 | ; 711 | btree_insert(T0, N, Var, T) 712 | ). 713 | melt(A0, A, T0, T) :- 714 | atomic(A0), 715 | !, 716 | A = A0, 717 | T = T0. 718 | melt(Term0, Term, T0, T) :- 719 | Term0 =.. [F|List0], 720 | melt_list(List0, List, T0, T), 721 | Term =.. [F|List]. 722 | 723 | melt_list([], [], T, T). 724 | melt_list([A|As], [B|Bs], T0, T) :- 725 | melt(A, B, T0, T1), 726 | melt(As, Bs, T1, T). 727 | -------------------------------------------------------------------------------- /semantic_terms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RichardMoot/LinearOne/55540e9a91b7a5c7722775f39ffbf50f5b472a7e/semantic_terms.pdf --------------------------------------------------------------------------------